/* A facade class to demonstartae image processing using imagemagick API */
/* www.hackorama.com kishan@hackorama.com 2005/2006                      */

#include "pixmap.h"

Pixmap::Pixmap()
{
	Pixmap(NULL);
}

Pixmap::Pixmap(Image *_image)
{
	p = (PixelPacket*) new PixelPacket();
	if( _image == (Image *) NULL){
		image = NULL;
	}else{
		image = new Image();
		image = _image;
	}
	init();
#ifdef DEBUG
	debug = true;
#else
	debug = false;
#endif

}

Pixmap::~Pixmap()
{
	if(p != NULL){
		free(p);
		p = NULL;
	}
	if(image != NULL){
		free(image);
		image = NULL;
	}
}

Image*
Pixmap::getImage()
{
	return image;
}

void
Pixmap::init()
{
	max_rgb = MAX_RGB;
	pen_r = max_rgb;
	pen_g = 0;
	pen_b = 0;
        if (image == (Image *) NULL){
		width = 0;
		height =  0;
		ok = false;
	}else{
		width = image->columns;
		height =  image->rows;
		ok = true;
	}
}

int
Pixmap::loadImage(char *filename)
{
        ExceptionInfo exception;
        GetExceptionInfo(&exception);
        image_info = CloneImageInfo((ImageInfo *) NULL);
        (void) strcpy(image_info->filename, filename);
        image = ReadImage(image_info,&exception);
	
	init();

	image_out = CloneImage( image, 0, 0, (MagickBooleanType)1, &exception);
	if (image_out == (Image *) NULL){
                cout << "Error Creating Output Image. Exiting ...\n" ;
		return false;
        }
	return true;
}

void 
Pixmap::writeImage(char *filename, int i)
{
	char file_name[256];
	if( i < 10 ) sprintf( file_name, "%s-00%d.jpg", filename, i );
	else if( i < 100 && i > 9 ) sprintf( file_name, "%s-0%d.jpg", filename, i );
	else sprintf( file_name, "%s-%d.jpg", filename, i );
	
	writeImage(file_name);
}

void 
Pixmap::writeImage(char *filename)
{
	image_info=CloneImageInfo((ImageInfo *) NULL);
	(void) strcpy(image->filename, filename);
  	(void) strcpy(image_info->filename, filename);
      	WriteImage(image_info,image);
}

void
Pixmap::setDebug(bool flag)
{
	debug = flag;
}

int
Pixmap::getWidth()
{
	if( width < 0 ) width = 0;
	return width;
}

int
Pixmap::getHeight()
{
	if( height < 0 ) height = 0;
	return height;
}

bool
Pixmap::isValid()
{
	if( image == NULL ) ok = false;
	return ok;
}

int
Pixmap::maxRGB()
{
	return max_rgb;
}

bool
Pixmap::inRange(int x, int y)
{
	if( ! isValid() )  return false;
	if( ( x >= 0 &&  x < width ) && ( y >= 0 &&  y < height ) ) {
		return true;
	}
	return false;
}

void
Pixmap::switchColor( int r, int g, int b, int new_r, int new_g, int new_b )
{
	for(int i=0; i<width; i++){
		for(int j=0; j<height; j++){
			switchPixel( i, j, r, g, b, new_r, new_g, new_b);
		}
	}
}

bool
Pixmap::switchPixel( int x, int y, int r, int g, int b, 
		     int new_r, int new_g, int new_b )
{
	if( ! inRange( x, y ) ) return true;
	pixel = GetOnePixel( image, x, y);
	if( pixel.red == convertRGB(r) &&  
	    pixel.green == convertRGB(g) && 
	    pixel.blue == convertRGB(b) ){
		return setPixel( x, y, convertRGB(new_r), convertRGB(new_g), convertRGB(new_b) );
	}
	return false;
}

int
Pixmap::getPixel( int x, int y ) 
{
	if( ! inRange( x, y ) ) return 0;
	pixel = GetOnePixel( image, x, y);
	return ( pixel.red + pixel.green + pixel.blue );
}

void
Pixmap::setPen( int r, int g, int b ) 
{
	pen_r = convertRGB(r);
	pen_g = convertRGB(g);
	pen_b = convertRGB(b);
}

int
Pixmap::convertRGB( int x ) 
{
	if( x <= 0 || x > 255  ) return x;
	int factor = max_rgb / 255;
	return x*factor;
}

bool
Pixmap::colorPixel( int x, int y ) // not black
{
	if( ! inRange( x, y ) ) return true;
	pixel = GetOnePixel( image, x, y);
	int p = pixel.red + pixel.green + pixel.blue ;
	if( p > 0 && p < (3 * max_rgb) ) return true;
	return false;
}

bool
Pixmap::darkPixel( int x, int y ) // not black
{
	if( ! inRange( x, y ) ) return true;
	pixel = GetOnePixel( image, x, y);
	int p = pixel.red + pixel.green + pixel.blue ;
	if( p >= max_rgb ) return true;
	return false;
}

bool
Pixmap::lightPixel( int x, int y ) // not black
{
	if( ! inRange( x, y ) ) return true;
	pixel = GetOnePixel( image, x, y);
	int p = pixel.red + pixel.green + pixel.blue ;
	if( p < max_rgb ) return true;
	return false;
}

bool
Pixmap::redPixel( int x, int y ) 
{
	if( ! inRange( x, y ) ) return false;
	pixel = GetOnePixel( image, x, y);
	int p = pixel.red + pixel.green + pixel.blue ;
	if( pixel.red == max_rgb && p == max_rgb ) return true;
	return false;
}

bool
Pixmap::greenPixel( int x, int y ) 
{
	if( ! inRange( x, y ) ) return false;
	pixel = GetOnePixel( image, x, y);
	int p = pixel.red + pixel.green + pixel.blue ;
	if( pixel.green == max_rgb && p == max_rgb ) return true;
	return false;
}

bool
Pixmap::bluePixel( int x, int y ) 
{
	if( ! inRange( x, y ) ) return false;
	pixel = GetOnePixel( image, x, y);
	int p = pixel.red + pixel.green + pixel.blue ;
	if( pixel.blue == max_rgb && p == max_rgb ) return true;
	return false;
}

bool
Pixmap::whitePixel( int x, int y ) // not black
{
	if( ! inRange( x, y ) ) return true;
	pixel = GetOnePixel( image, x, y);
	int p = pixel.red + pixel.green + pixel.blue ;
	if( p == (3 * max_rgb) ) return true;
	return false;
}

bool
Pixmap::blackPixel( int x, int y ) // black 
{
	if( ! inRange( x, y ) ) return false;
	pixel = GetOnePixel( image, x, y);
	int p = pixel.red + pixel.green + pixel.blue ;
	if( p ==  0 ) return true;
	return false;
}

bool
Pixmap::markPixels(int x, int y, int r, int g, int b, int border)
{

	setPixel(x-border, y-border, r, g, b);
	setPixel(x,   y-border, r, g, b);
	setPixel(x+border, y-border, r, g, b);

	setPixel(x-border, y, r, g, b);
	setPixel(x,   y, r, g, b);
	setPixel(x+border, y, r, g, b);
	
	setPixel(x-border, y+border, r, g, b);
	setPixel(x,   y+border, r, g, b);
	setPixel(x+border, y+border, r, g, b);
	
	return true;
}

bool
Pixmap::setPixel(int x, int y)
{
	if( ! inRange( x, y ) ) return false;
	p = SetImagePixels(image, x, y, 1, 1);
	p->red = pen_r;
	p->green = pen_g;
	p->blue = pen_b;
	if (!SyncImagePixels(image)) { 
		fprintf( stdout, "Sync Error\n" );
		return false;
	}
	return true;
}

bool
Pixmap::setPixel(int x, int y, int r, int g, int b)
{
	if( ! inRange( x, y ) ) return false;
	p = SetImagePixels(image, x, y, 1, 1);
	p->red = r;
	p->green = g;
	p->blue = b;
	if (!SyncImagePixels(image)) { 
		fprintf( stdout, "Sync Error\n" );
		return false;
	}
	return true;
}

void
Pixmap::clear(int r, int g, int b)
{
	for(int i=0; i<width; i++){
		for(int j=0; j<height; j++){
			setPixel( i, j, r, g, b);
		}
	}
}

void
Pixmap::clear()
{
	clear(maxRGB(), maxRGB(), maxRGB());
}


void
Pixmap::markVLine(int x)
{
	markVLine(1, height-1, x);
}

void
Pixmap::markHLine(int y)
{
	markHLine(1, width-1, y);
}

void
Pixmap::markHLine(int _x1, int _x2, int y)
{
	int x1 = 0,  x2 = 0;
	x1 = _x1 < _x2 ? _x1 : _x2;
	x2 = _x1 < _x2 ? _x2 : _x1;
	for(int x = x1; x <= x2; x++) setPixel(x, y);

}

void
Pixmap::markVLine(int _y1, int _y2, int x)
{
	int y1 = 0,  y2 = 0;
	y1 = _y1 < _y2 ? _y1 : _y2;
	y2 = _y1 < _y2 ? _y2 : _y1;
	for(int y = y1; y <= y2; y++) setPixel(x, y);
}



syntax highlighted by Code2HTML, v. 0.9