int main(int argc, char **argv)
{
	if (argc != 2)
    {
		std::cerr << argv[0] << " image.jpg" << std::endl;
		return -1;
	}

	cv::Mat inputImage = cv::imread(argv[1]);
    // How to check read image ok?
    printf("- Image size w=%d, h=%d.\n", inputImage.cols, inputImage.rows);
    while (inputImage.cols > 720 || inputImage.rows > 800)
    {
        cv::resize(inputImage, inputImage, cv::Size(round(0.618 * inputImage.cols),
                                                    round(0.618 * inputImage.rows)));
        printf("- After resize, Image size w=%d, h=%d.\n", inputImage.cols, inputImage.rows);
    }

	ImageInfo ii;
	ii.leftMouseDown = false;
    ii.rightMouseDown = false;
	ii.patchSize = 9;

	ii.image = inputImage.clone();
	ii.displayImage = ii.image.clone();
    ii.targetMask.create(ii.image.size(), CV_8UC1);
	ii.targetMask.setTo(0); // a black picture.
    //cv::imshow("Target mask", ii.targetMask);
    ii.sourceMask.create(ii.image.size(), CV_8UC1);
	ii.sourceMask.setTo(0); // a black picture.
    //cv::imshow("Source mask", ii.sourceMask);

	//cv::namedWindow("Image Inpaint", cv::WINDOW_NORMAL);
	cv::namedWindow("Image Inpaint");
	cv::setMouseCallback("Image Inpaint", onMouse, &ii);
	cv::createTrackbar("Patchsize", "Image Inpaint", &ii.patchSize, 50);

	bool done = false;
	bool editingMode = true;
    int iterations = 0;

    Inpaint::CriminisiInpainter inpainter;
	cv::Mat image;

	while (!done)
    {
		if (editingMode)
        {
			image = ii.displayImage.clone();
		}
        else
        {
			if (inpainter.hasMoreSteps())
            {
                ++iterations;
				inpainter.step();
                inpainter.image().copyTo(image); // copy temp result into image
                // Set image's target regiion to specified value.
                // The target region decrease with algorithm proceed.
                image.setTo(cv::Scalar(0,250,0), inpainter.targetRegion());
                // Only a single window is displayed.
                // check the processing result of each iteration.
               // cv::imshow("Processing", inpainter.image());
			}
            else
            {
                // algorithm finished.
                printf("- No more processings, iterations = %d.\n", iterations);
				ii.image = inpainter.image().clone();
				ii.displayImage = ii.image.clone();
                ii.targetMask = inpainter.targetRegion().clone();
				editingMode = true;
			}
		}

		cv::imshow("Image Inpaint", image);
		int key = cv::waitKey(10); // wait for key strok for 10 ms.

		if (key == 'x')
        {
            printf("- Done.\n");
			done = true;
		}
        else if (key == 'e')
        {
			if (editingMode)
            {
				// Was in editing, now perform
                printf("- In edit mode, set parameters.\n");

                // Check the source and target mask here
		        //cv::imshow("Target mask",ii.targetMask);
		        //cv::imshow("Source mask", ii.sourceMask);
                inpainter.setSourceImage(ii.image);
                inpainter.setTargetMask(ii.targetMask);
                inpainter.setSourceMask(ii.sourceMask);
                inpainter.setPatchSize(ii.patchSize);
                inpainter.initialize();
			}
			editingMode = !editingMode;
		}
        else if (key == 'r')
        {
			// revert
            printf("- Revert to initial state and set to edit mode.\n");
			ii.image = inputImage.clone();
			ii.displayImage = ii.image.clone();
			ii.targetMask.create(ii.image.size(), CV_8UC1);
			ii.targetMask.setTo(0);
            ii.sourceMask.create(ii.image.size(), CV_8UC1);
			ii.sourceMask.setTo(0);
			editingMode = true;
		}
        else
        {
            //printf("- Press other keys.\n");
        }
	}

	cv::imshow("Source", inputImage);
    if (!inpainter.image().empty())
        cv::imshow("Final", inpainter.image()); // bug here.
	cv::waitKey(); // wait for key strok forever.
	//cv::imwrite("Final.png", inpainter.image());

	return 0;
}
/** Main entry point */
int main(int argc, char **argv)
{
	if (argc != 2) {
		std::cerr << argv[0] << " image.png" << std::endl;
		return -1;
	}

	cv::Mat inputImage = cv::imread(argv[1]);

	ImageInfo ii;
	ii.leftMouseDown = false;
    ii.rightMouseDown = false;
	ii.patchSize = 9;

	ii.image = inputImage.clone();
	ii.displayImage = ii.image.clone();
    ii.targetMask.create(ii.image.size(), CV_8UC1);
	ii.targetMask.setTo(0);
    ii.sourceMask.create(ii.image.size(), CV_8UC1);
	ii.sourceMask.setTo(0);

	cv::namedWindow("Image Inpaint", cv::WINDOW_NORMAL);
	cv::setMouseCallback("Image Inpaint", onMouse, &ii);
	cv::createTrackbar("Patchsize", "Image Inpaint", &ii.patchSize, 50);
	
	bool done = false;
	bool editingMode = true;

    Inpaint::CriminisiInpainter inpainter;
	cv::Mat image;	
	while (!done) {
		if (editingMode) {
			image = ii.displayImage.clone();
		} else {
			if (inpainter.hasMoreSteps()) {
				inpainter.step();
                inpainter.image().copyTo(image);
                image.setTo(cv::Scalar(0,250,0), inpainter.targetRegion());
			} else {
				ii.image = inpainter.image().clone();
				ii.displayImage = ii.image.clone();
                ii.targetMask = inpainter.targetRegion().clone();
				editingMode = true;
			}
		}

		cv::imshow("Image Inpaint", image);
		int key = cv::waitKey(10);

		if (key == 'x') {
			done = true;
		} else if (key == 'e') {
			if (editingMode) {
				// Was in editing, now perform
                inpainter.setSourceImage(ii.image);
                inpainter.setTargetMask(ii.targetMask);
                inpainter.setSourceMask(ii.sourceMask);
                inpainter.setPatchSize(ii.patchSize);
                inpainter.initialize();
			} 
			editingMode = !editingMode;
		} else if (key == 'r') {
			// revert
			ii.image = inputImage.clone();
			ii.displayImage = ii.image.clone();
			ii.targetMask.create(ii.image.size(), CV_8UC1);
			ii.targetMask.setTo(0);
            ii.sourceMask.create(ii.image.size(), CV_8UC1);
			ii.sourceMask.setTo(0);
			editingMode = true;
		}
	}

	cv::imshow("source", inputImage);
    cv::imshow("final", inpainter.image());
	cv::waitKey();
	cv::imwrite("final.png", inpainter.image());

	return 0;
}