#include "opencv2/opencv.hpp"

#include <stdio.h>
#include <stdlib.h>


void help (char *software)
{
	printf(
		"---------8<--------8<---------8<--------8<--------\n"
		"Usage: %s [options]\n"
		"Options:\n"

		"-s, -src : src filename (image.png)\n"
		"-d, -dst : dst filename (image_%05d.png)\n"

		"--------->8-------->8--------->8-------->8--------\n", software);
}


int main (int argc, char **argv)
{
	char *SRC = "image.png";
	char *DST = "image_%05d.png";

	for (int i=1; i<argc-1; i++)
	{
		if (strcmp(argv[i], "-s")   == 0) SRC = argv[++i];
		if (strcmp(argv[i], "-src") == 0) SRC = argv[++i];
		if (strcmp(argv[i], "-d")   == 0) DST = argv[++i];
		if (strcmp(argv[i], "-dst") == 0) DST = argv[++i];
	}

	IplImage *src = cvLoadImage(SRC);
	if (src == NULL || DST == NULL)
	{
		help(argv[0]);
	}
	else
	{
		const int W = src->width;
		const int H = src->height;

		const int K = std::max(W,H);

		IplImage *dst = cvCloneImage(src);
		for (int k=0; k<K; k++)
		{
			const float rate = (float)k / K;
			printf ("[%05d/%05d, %5.2f]\n", k, K, rate);

			cvZero (dst);

			for (int y=0; y<H; y++)
			{
				const int y_src = y;
				const int y_tmp = y_src + H * rate + 0.5f;
				const int y_dst = y_tmp < H ? y_tmp : y_tmp - H;

				unsigned char *data_src = (unsigned char *)(src->imageData) + src->widthStep * y_src;
				unsigned char *data_dst = (unsigned char *)(dst->imageData) + dst->widthStep * y_dst;

				for (int x=0; x<W; x++)
				{
					const int x_src = x;
					const int x_tmp = x_src + W * rate + 0.5f;
					const int x_dst = x_tmp < W ? x_tmp : x_tmp - W;

					unsigned char *d_src = data_src + src->nChannels * x_src;
					unsigned char *d_dst = data_dst + src->nChannels * x_dst;

					if      (src->nChannels == 1)
					{
						d_dst[0] = d_src[0];
					}
					else if (src->nChannels == 3)
					{
						d_dst[0] = d_src[0];
						d_dst[1] = d_src[1];
						d_dst[2] = d_src[2];
					}
					else
					{
						;
					}
				}
			}

			char buf[BUFSIZ] = {0};
			sprintf_s (buf, BUFSIZ, DST, k);
			printf ("Saving... %s\n", buf);

			cvSaveImage (buf, dst);

			cvNamedWindow ("Display");
			cvShowImage ("Display", dst);

			if (cvWaitKey(1) == 0x1b) break;
		}
		cvReleaseImage(&dst);

		cvReleaseImage(&src);
	}

	return 0;
}

