// Last updated 2010/08/02 16:20

// This is derived from a PHP script at:
// http://eclecticdjs.com/mike/tutorials/php/imagemagick/imagickpixeliterator/3D_landscape.php

#include <windows.h>
#include <wand/magick_wand.h>
#include <time.h>

void test_wand(LPTSTR lpCmdLine)
{
	MagickWand *image = NULL, *canvas = NULL;
	DrawingWand *line = NULL;
	PixelWand *pw = NULL;
	
	int w,h;
	int r,g,b,grey,offset;
	int start_y,end_y;
	int x,y;
	int line_height;
	char *url,*file;

	MagickWandGenesis();
	// input image
// The input image is at: "http://eclecticdjs.com/mike/temp/ball/fract6.jpg"
	url = "fract6.jpg";
	// output image
	file = "3d_fractal.jpg";


	image = NewMagickWand();
	pw = NewPixelWand();

	MagickReadImage(image,url);
	// scale it down
	w = (int) MagickGetImageWidth(image);
	h = (int) MagickGetImageHeight(image);

	PixelSetColor(pw,"transparent");
	if(MagickShearImage(image,pw,45,0) == MagickFalse)
		MessageBox(NULL,"B - Shear failed","",MB_OK);
	w = (int) MagickGetImageWidth(image);
	h = (int) MagickGetImageHeight(image);

	// scale it to make it look like it is laying down
	if(MagickScaleImage(image,w,h/2) == MagickFalse)
		MessageBox(NULL,"C - Scale failed","",MB_OK);
	// Get image stats
	w = (int) MagickGetImageWidth(image);
	h = (int) MagickGetImageHeight(image);

	// Make a blank canvas to draw on
	canvas = NewMagickWand();
	// Use a colour from the input image
	MagickGetImagePixelColor(image,0,0,pw);
	MagickNewImage(canvas,w,h*2,pw);

	offset = h;
// The original drawing method was to go along each row from top to bottom so that
// a line in the "front" (which is one lower down the picture) will be drawn over
// one behind it.
// The problem with this method is that every line is drawn even if it will be covered
// up by a line "in front" of it later on.
// The method used here goes up each column from left to right and only draws a line if
// it is longer than everything drawn so far in this column and will therefore be visible.
// With the new drawing method this takes 13 secs - the previous method took 59 secs
	// loop through all points in image
	for(x=0;x<w;x++) {
		// The PHP version created, used and destroyed the drawingwand inside
		// the inner loop but it is about 25% faster to do only the DrawLine
		// inside the loop
		line = NewDrawingWand();
		line_height = 0;
		for(y=h-1;y>=0;y--) {
			// get (r,g,b) and grey value
			if(MagickGetImagePixelColor(image,x,y,pw) == MagickFalse)continue;
			// 255* adjusts the rgb values to Q8 even if the IM being used is Q16
			r = (int) (255*PixelGetRed(pw));
			g = (int) (255*PixelGetGreen(pw));
			b = (int) (255*PixelGetBlue(pw));

			// Calculate grayscale - a divisor of 10-25 seems to work well.
//			grey = (r+g+b)/25;
			grey = (r+g+b)/15;
//			grey = (r+g+b)/10;
			// Only draw a line if it will show "above" what's already been done
			if(line_height == 0 || line_height < grey) {
				DrawSetFillColor(line,pw);
				DrawSetStrokeColor(line,pw);
				// Draw the part of the line that is visible
				start_y = y+offset - line_height;
				end_y = y-grey+offset;
				DrawLine(line,x,start_y,x,end_y);
				line_height = grey;
			}
			line_height--;
		}
		// Draw the lines on the image
		MagickDrawImage(canvas,line);
		DestroyDrawingWand(line);
	}
	MagickScaleImage(canvas,w-h,h*2);
	// write canvas
	MagickWriteImage(canvas,file);
	// clean up
	DestroyMagickWand(canvas);
	DestroyMagickWand(image);
	DestroyPixelWand(pw);
	MagickWandTerminus();
}