www.pudn.com > PtOpenGuiSourceCode.zip > filter.cpp


/* Panorama_Tools	-	Generate, Edit and Convert Panoramic Images 
   Copyright (C) 1998,1999 - Helmut Dersch  der@fh-furtwangen.de 
    
   This program is free software; you can redistribute it and/or modify 
   it under the terms of the GNU General Public License as published by 
   the Free Software Foundation; either version 2, or (at your option) 
   any later version. 
 
   This program is distributed in the hope that it will be useful, 
   but WITHOUT ANY WARRANTY; without even the implied warranty of 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
   GNU General Public License for more details. 
 
   You should have received a copy of the GNU General Public License 
   along with this program; if not, write to the Free Software 
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
 
/*------------------------------------------------------------*/ 
 
 
// Program specific includes 
 
#include "filter.h" 			 
 
 
// Standard C includes 
 
#include  
#include  
#include  
#include  
#include  
 
 
 
 
//   Main entry for all Panorama Tools. Dispatches to individual tools using 
//   the selector entry.  
 
 
// These globals are only used and valid during dialog set-up!  
 
 
TrformStr 		*gTrPtr; 
sPrefs			*gsPrPtr; 
 
 
 
void dispatch (TrformStr *TrPtr, sPrefs *spref) 
{ 
	panoPrefs	prefs, *prPtr; 
	char version[10]; 
	 
 
	if( TrPtr->src->bitsPerPixel != 32 && TrPtr->src->bitsPerPixel != 24 && 
		TrPtr->src->bitsPerPixel != 64 && TrPtr->src->bitsPerPixel != 48) 	// Only support 3/4 byte/short pixels 
	{ 
		PrintError( "Please convert image to 24/32/48/64 bit pixelsize."); 
		PrintError( "Pixelsize is now  %d", (int)TrPtr->src->bitsPerPixel );		 
		TrPtr->success = 0; 
		return; 
	} 
	 
	TrPtr->dest->bitsPerPixel = TrPtr->src->bitsPerPixel; 
 
	// Check version of preferences file 
 
	 
	if( readPrefs( version, _version ) != 0 || strcmp( version, VERSION ) != 0 ) 
	{ 
		writePrefs( VERSION, _version ); 
		SetSizeDefaults( spref); 
		writePrefs( (char*)spref, _sizep ); 
		 
		SetPrefDefaults( &prefs, _perspective ); 
		writePrefs( (char*)&prefs.pP, _perspective ); 
		SetPrefDefaults( &prefs, _correct ); 
		writePrefs( (char*)&prefs.cP, _correct ); 
		SetPrefDefaults( &prefs, _remap ); 
		writePrefs( (char*)&prefs.rP, _remap ); 
		SetPrefDefaults( &prefs, _adjust ); 
		writePrefs( (char*)&prefs.aP, _adjust ); 
		SetPrefDefaults( &prefs, _panleft ); 
		writePrefs( (char*)&prefs.pc, _panleft ); 
		 
	} 
 
	// Read and/or set preferences; Do Xform 
	 
	gTrPtr = TrPtr; 
	gsPrPtr = spref; 
 
 
	switch( TrPtr->mode & 7 ) 
	{ 
		case _interactive: 		// Display dialog, set prefs, Do Xform 
					if( readPrefs( (char*)spref, _sizep ) != 0 )  
							SetSizeDefaults( spref); 
					prPtr = &prefs; 
					if( readPrefs( (char*)prPtr, TrPtr->tool ) != 0 ) 
						SetPrefDefaults( prPtr,  TrPtr->tool); 
					if( !SetPrefs(  prPtr )) 
					{ 
						TrPtr->success = 0; 
					} 
					else 
					{ 
						TrPtr->interpolator = spref->interpolator; 
						TrPtr->gamma		= spref->gamma; 
							 
						writePrefs( (char*)prPtr, TrPtr->tool ); 
						writePrefs( (char*)spref, _sizep ); 
						DoTransForm( TrPtr, prPtr ); 
					} 
					break; 
		case _setprefs: 		// Display dialog, set prefs 
					if( readPrefs( (char*)spref, _sizep ) != 0 )  
							SetSizeDefaults( spref); 
					prPtr = &prefs; 
					if( readPrefs( (char*)prPtr, TrPtr->tool ) != 0 ) 
						SetPrefDefaults( prPtr,  TrPtr->tool); 
					if( SetPrefs( prPtr ) ) 
					{ 
						writePrefs( (char*)spref, _sizep ); 
						writePrefs( (char*)prPtr, TrPtr->tool ); 
						TrPtr->success = 1; 
					} 
					else 
						TrPtr->success = 0; 
					break; 
		case _useprefs:			// Read prefs, do Xform 
					if( readPrefs( (char*)spref, _sizep ) != 0 )  
							SetSizeDefaults( spref); 
					prPtr = &prefs; 
					if( readPrefs( (char*)prPtr, TrPtr->tool ) != 0 ) 
						SetPrefDefaults( prPtr,  TrPtr->tool); 
					DoTransForm( TrPtr, prPtr ); 
					break; 
		case _usedata:			// ignore prefs, do Xform 
					prPtr = (panoPrefs *) TrPtr->data; 
					DoTransForm( TrPtr, prPtr ); 
					break; 
		default:	TrPtr->success = 0; 
					break; 
	} 
	 
	return; 
} 
					 
	 
 
 
void DoTransForm( TrformStr *TrPtr, panoPrefs *prPtr ) 
{ 
 
	// Dispatch to selected tool 
	 
	 
	switch( TrPtr->tool ) 
	{ 
		case _perspective: 	 
			perspective	(TrPtr, &prPtr->pP); 
			break; 
		case _remap:		 
			remap		(TrPtr, &prPtr->rP); 
			break; 
		case _correct:		 
			correct		(TrPtr, &prPtr->cP);   
			break; 
		case _adjust:		 
			adjust		(TrPtr, &prPtr->aP);  
			break; 
//		case _interpolate:		 
//			interp      (TrPtr, &prPtr->iP); 
//			break; 
		case _panright: 
		case _panleft: 
		case _panup: 
		case _pandown: 
		case _zoomin: 
		case _zoomout: 
		case _apply: 
		case _getPano: 
		case _increment: 
			pan(TrPtr,  &prPtr->pc); 
			break; 
	} 
	Progress( _disposeProgress, "" );  
	return; 
	 
} 
 
 
void SetPrefDefaults(panoPrefs *prPtr,  int selector) 
{ 
	// Dispatch to selected tool 
	 
	switch( selector ) 
	{ 
		case _perspective: 	 
			SetPerspectiveDefaults( &prPtr->pP);  
			break; 
		case _remap:		 
			SetRemapDefaults( &prPtr->rP);  
			break; 
		case _correct: 
			SetCorrectDefaults( &prPtr->cP);   
			break; 
		case _adjust:		 
			SetAdjustDefaults( &prPtr->aP);  
			break; 
//		case _interpolate:		 
//			SetInterpolateDefaults( &prPtr->iP ); 
//			break; 
		case _panright: 
		case _panleft: 
		case _panup: 
		case _pandown: 
		case _zoomin: 
		case _zoomout: 
		case _apply: 
		case _getPano: 
		case _increment: 
			SetPanDefaults( &prPtr->pc ); 
			break; 
	} 
	return; 
} 
 
void	SetPanDefaults( panControls *pc) 
{ 
	pc->panAngle	= 15.0; 
	pc->zoomFactor	= 30.0; 
} 
 
 
int SetPrefs(  panoPrefs *prPtr ) 
{ 
	// Dispatch to selected tool 
	 
	switch( gTrPtr->tool ) 
	{ 
		case _perspective: 	 
			return SetPerspectivePrefs	( &prPtr->pP ); 
			break; 
		case _remap:		 
			return SetRemapPrefs		( &prPtr->rP ); 
			break; 
		case _correct:		 
			return SetCorrectPrefs		(  &prPtr->cP );  
			break; 
		case _adjust:		 
			return SetAdjustPrefs		(  &prPtr->aP ); 
			break; 
//		case _interpolate:		 
//			return SetInterpPrefs		(  &prPtr->iP ); 
//			break; 
		case _panright: 
		case _panleft: 
		case _panup: 
		case _pandown: 
		case _zoomin: 
		case _zoomout: 
		case _apply: 
		case _getPano: 
		case _increment: 
			return TRUE; 
			break; 
	} 
	return FALSE; 
} 
 
 
 
//   Filter function; src and dest should be equal sized 
 
 
void filter( TrformStr *TrPtr, flfn func, void* params, int color) 
{ 
	register int 		x, y;			// Loop through destination image 
	register int     	i,  col; 		// Auxilliary loop variables 
	int 				skip = 0;		// Update progress counter 
	unsigned char 		*dest, *src;	// Source and destination image data 
	char*				progressMessage;// Message to be displayed by progress reporter 
	char                percent[8];		// Number displayed by Progress reporter 
	int					valid;			// Is this pixel valid? (i.e. inside source image) 
	long				coeff;			// pixel coefficient in destination image 
 
	int 				xs, ys;			// Source screen coordinates  
 
	// Variables used to convert screen coordinates to cartesian coordinates 
	 
	int 				w2 = TrPtr->dest->width / 2.0 - 0.5;  // Steve's L 
	int 				h2 = TrPtr->dest->height / 2.0 - 0.5;   
 
 
	// We can handle 3 and 4 Bytes/Pixel (and more, if exists). 
	 
	int					BytesPerPixel 	= TrPtr->src->bitsPerPixel / 8; 
	int					FirstColorByte	= BytesPerPixel - 3; 
 
 
 
	// Selection rectangle 
	PTRect			destRect; 
	if( TrPtr->dest->selection.bottom == 0 && TrPtr->dest->selection.right == 0 ){ 
		destRect.left 	= 0; 
		destRect.right	= TrPtr->dest->width; 
		destRect.top	= 0; 
		destRect.bottom = TrPtr->dest->height; 
	}else{ 
		memcpy( &destRect, &TrPtr->dest->selection, sizeof(PTRect) ); 
	} 
 
	dest = *TrPtr->dest->data; 
	src  = *TrPtr->src->data; // is locked 
 
 
	if(TrPtr->mode & _show_progress){ 
		switch(color){ 
			case 0: progressMessage = "Image Conversion"; 	break; 
			case 1:	switch( TrPtr->src->dataformat) 
					{ 
						case _RGB: 	progressMessage = "Red Channel"  ; break; 
						case _Lab:	progressMessage = "Lightness" 	 ; break; 
					} break; 
			case 2:	switch( TrPtr->src->dataformat) 
					{ 
						case _RGB: 	progressMessage = "Green Channel"; break; 
						case _Lab:	progressMessage = "Color A" 	 ; break; 
					} break;  
			case 3:	switch( TrPtr->src->dataformat) 
					{ 
						case _RGB: 	progressMessage = "Blue Channel"; break; 
						case _Lab:	progressMessage = "Color B" 	; break; 
					} break;  
			default: progressMessage = "Something is wrong here"; 
		} 
		Progress( _initProgress, progressMessage ); 
	} 
 
 
 
	for(y=destRect.top; ymode & _show_progress) 
			{	 
				sprintf( percent, "%d", (int) (y * 100)/ TrPtr->dest->height); 
				if( ! Progress( _setProgress, percent ) ) 
				{ 
					//myfree( (void**)TrPtr->dest->data ); 
					TrPtr->success = 0; 
					return; 
				} 
			} 
			else 
			{ 
				 
				if( ! Progress( _idleProgress, 0) ) 
				{ 
					//myfree( (void**)TrPtr->dest->data ); 
					TrPtr->success = 0; 
					return; 
				} 
			} 
			skip = 0; 
			 
		} 
		for(x=destRect.left; x= TrPtr->src->width)   || (ys >= TrPtr->src->height) ) 
				valid = FALSE; 
			else 
				valid = TRUE; 
 
			// if alpha channel marks valid portions, set valid  
 
			if( (TrPtr->mode & _honor_valid) &&  
				(FirstColorByte == 1)		 && 
				(src[ ys * TrPtr->src->bytesPerLine + BytesPerPixel * xs] == 0)) 
				valid = FALSE;		 
 
 
			// Check for and handle edge locations 
 
			if( xs < 0) 			xs = 0;  
			if( xs >= TrPtr->src->width ) 	xs = TrPtr->src->width -1; 
			if( ys < 0) 			ys = 0; 
			if( ys >= TrPtr->src->height ) 	ys = TrPtr->src->height -1; 
 
 
			// Calculate pixel coefficient in dest image just once 
 
			coeff = (y-destRect.top) * TrPtr->dest->bytesPerLine  + BytesPerPixel * (x-destRect.left);		 
 
			if( valid ) 
			{ 
				if( color == 0 ) // Convert all color channels equally  
				{ 
					for( col = FirstColorByte; col < FirstColorByte + 3; col++) 
					{ 
						dest[ coeff + col] = func( src[ ys * TrPtr->src->bytesPerLine + BytesPerPixel * xs + col ], x-w2, y-h2, params ); 
					} 
					if( FirstColorByte == 1 ) 
						dest[ coeff ] = 255; // Set alpha channel 
				} 
				else // Convert just one channel 
				{ 
					col = (FirstColorByte ? color : color-1);  
					 
					dest[ coeff + col] = func( src[ ys * TrPtr->src->bytesPerLine + BytesPerPixel * xs + col ], x-w2, y-h2, params ); 
 
					if( FirstColorByte == 1 ) 
						dest[ coeff ] = 255; // Set alpha channel 
				} 
			} 
			else 
			{ 
				for(i = 0; i < 3 + FirstColorByte; i++) 
					dest[ coeff + i] = 0; 
			} 
 
		} 
	} 
 
	if(TrPtr->mode & _show_progress) 
	{ 
		Progress( _disposeProgress, percent ); 
	}	 
 
	TrPtr->success = 1; 
} 
 
 
 
// Given source image and dest dimensions, set dest and 
// allocate memory for dest->data 
 
int SetDestImage( TrformStr *TrPtr, int width, int height)  
{ 
	int result = 0; 
 
	if( TrPtr->mode & _destSupplied ) 
		return 0; 
		 
	memcpy( TrPtr->dest, TrPtr->src, sizeof( PTImage )); 
	 
	TrPtr->dest->width			= width; 
	TrPtr->dest->height			= height; 
 
	// bytesPerLine depending on image format 
 
	TrPtr->dest->bytesPerLine	=	TrPtr->dest->width * (TrPtr->dest->bitsPerPixel / 8) ;  
 
	TrPtr->dest->dataSize 		= TrPtr->dest->height * TrPtr->dest->bytesPerLine; 
	//TrPtr->dest->data 			= (unsigned char**) mymalloc (TrPtr->dest->dataSize); 
	TrPtr->dest->data 		= new unsigned char*[TrPtr->dest->dataSize]; 
 
	if( TrPtr->dest->data 		== NULL ) 
		result = -1; 
	 
	return result; 
} 
 
 
// Copy image data from src to dest with framing/cropping if sizes differ 
// src and dest may differ in bytesPerPixel (3 and/or 4) 
 
void CopyImageData( PTImage *dest, PTImage *src ) 
{ 
	register unsigned char 	*in, *out; 
	register int 			x,y, dx, dy, id, is, i; 
	int						bpp_s, bpp_d; 
	 
	in 		= *(src->data); 
	out 	= *(dest->data); 
	dx		= (src->width  - dest->width)  / 2; 
	dy		= (src->height - dest->height) / 2; 
	bpp_s	= src->bitsPerPixel  / 8; 
	bpp_d	= dest->bitsPerPixel / 8; 
	 
	for( y = 0; y < dest->height; y++) 
	{ 
		for( x = 0; x < dest->width; x++) 
		{ 
			is = (y + dy) * src->bytesPerLine  + bpp_s * (x + dx); 
			id = y        * dest->bytesPerLine + bpp_d * x; 
 
			if( y + dy < 0 || y + dy >= src->height || 
				x + dx < 0 || x + dx >= src->width ) 	// outside src; set dest = 0 
			{ 
				i = bpp_d; 
				while( i-- > 0 ) out[ id++ ] = 0; 
			} 
			else 										// inside src; set dest = src 
			{ 
				switch( bpp_d ) 
				{ 
					case 8: switch( bpp_s ) 
							{ 
								case 8:	memcpy( out + id, in + is, 8 );  
										break;	 
								case 6: out[id++] = 255U; out[id++] = 255U; 
										memcpy( out + id, in + is, 6 );  
										break; 
								case 4: out[id++] = in[ is++ ]; out[id++] = 0; 
										out[id++] = in[ is++ ]; out[id++] = 0; 
										out[id++] = in[ is++ ]; out[id++] = 0; 
										out[id++] = in[ is++ ]; out[id++] = 0; 
										break; 
								case 3: out[id++] = 255U; out[id++] = 255U; 
										out[id++] = in[ is++ ]; out[id++] = 0; 
										out[id++] = in[ is++ ]; out[id++] = 0; 
										out[id++] = in[ is++ ]; out[id++] = 0; 
										break; 
							} 
							break; 
					case 6:  switch( bpp_s ) 
							{ 
								case 8:	is += 2; 
										memcpy( out + id, in + is, 6 );  
										break;	 
								case 6: memcpy( out + id, in + is, 6 );  
										break; 
								case 4: is++; 
										out[id++] = in[ is++ ]; out[id++] = 0; 
										out[id++] = in[ is++ ]; out[id++] = 0; 
										out[id++] = in[ is++ ]; out[id++] = 0; 
										break; 
								case 3: out[id++] = in[ is++ ]; out[id++] = 0; 
										out[id++] = in[ is++ ]; out[id++] = 0; 
										out[id++] = in[ is++ ]; out[id++] = 0; 
										break; 
							} 
							break; 
 
					case 4:  switch( bpp_s ) 
							{ 
								case 8:	out[id++] = in[ is++ ]; is++; 
										out[id++] = in[ is++ ]; is++; 
										out[id++] = in[ is++ ]; is++; 
										out[id++] = in[ is++ ]; is++; 
										break;	 
								case 6: out[id++] = 255U; 
										out[id++] = in[ is++ ]; is++; 
										out[id++] = in[ is++ ]; is++; 
										out[id++] = in[ is++ ]; is++; 
										break; 
								case 4: memcpy( out + id, in + is, 4 );  
										break; 
								case 3: out[id++] = 255U; 
										memcpy( out + id, in + is, 3 );  
										break; 
							} 
							break; 
 
					case 3:  switch( bpp_s ) 
							{ 
								case 8:	is+=2; 
										out[id++] = in[ is++ ]; is++; 
										out[id++] = in[ is++ ]; is++; 
										out[id++] = in[ is++ ]; is++;  
										break;	 
								case 6: out[id++] = in[ is++ ]; is++; 
										out[id++] = in[ is++ ]; is++; 
										out[id++] = in[ is++ ]; is++;  
										break; 
								case 4: is++; 
										memcpy( out + id, in + is, 3 );  
										break; 
								case 3: memcpy( out + id, in + is, 3 );  
										break; 
							} 
							break; 
 
				} 
			} 
		} 
	} 
} 
 
// expand image from 3 to 4 bytes per pixel. No pad bytes allowed. 
// Memory must be allocated 
void ThreeToFourBPP( PTImage *im ){ 
	register int x,y,c1,c2; 
 
	if( im->bitsPerPixel == 32 || im->bitsPerPixel == 64) // Nothing to do 
		return; 
 
	if( im->bitsPerPixel == 24 ){	// Convert to 4byte / pixel 
		for( y = im->height-1; y>=0; y--){ 
			for( x= im->width-1; x>=0; x--){ 
				c1 = (y * im->width + x) * 4; 
				c2 = y * im->bytesPerLine + x * 3; 
				(*(im->data))[c1++] = UCHAR_MAX; 
				(*(im->data))[c1++] = (*(im->data))[c2++]; 
				(*(im->data))[c1++] = (*(im->data))[c2++]; 
				(*(im->data))[c1++] = (*(im->data))[c2++]; 
			} 
		} 
		im->bitsPerPixel = 32; 
		im->bytesPerLine = im->width * 4; 
	}else if( im->bitsPerPixel == 48 ){ // Convert to 8byte / pixel 
		for( y = im->height-1; y>=0; y--){ 
			for( x= im->width-1; x>=0; x--){ 
				c1 = (y * im->width + x) * 4; 
				c2 = y * im->bytesPerLine/2 + x * 3; 
				((USHORT*)(*(im->data)))[c1++] = USHRT_MAX; 
				((USHORT*)(*(im->data)))[c1++] = ((USHORT*)(*(im->data)))[c2++]; 
				((USHORT*)(*(im->data)))[c1++] = ((USHORT*)(*(im->data)))[c2++]; 
				((USHORT*)(*(im->data)))[c1++] = ((USHORT*)(*(im->data)))[c2++]; 
			} 
		} 
		im->bitsPerPixel = 64; 
		im->bytesPerLine = im->width * 8; 
	} 
	im->dataSize = im->height * im->bytesPerLine; 
} 
 
// eliminate alpha channel. 
// pad bytes allowed 
void 	FourToThreeBPP		( PTImage *im ) 
{ 
	register int x,y,c1,c2; 
	 
	if( im->bitsPerPixel == 24 || im->bitsPerPixel == 48 ) // Nothing to do 
		return; 
 
	 
	if( im->bitsPerPixel == 32 ) // Convert to 3byte / pixel 
	{ 
		register unsigned char *data = *(im->data); 
		for( y = 0; y < im->height; y++) 
		{ 
			for( x=0; x < im->width; x++) 
			{ 
				c1 =  y * im->bytesPerLine + x * 4; 
				c2 = (y * im->width + x) * 3; 
				c1++; 
				data [c2++] = data [c1++]; 
				data [c2++] = data [c1++]; 
				data [c2++] = data [c1++]; 
			} 
		} 
		im->bitsPerPixel = 24; 
		im->bytesPerLine = im->width * 3; 
	} 
	else if( im->bitsPerPixel == 64 )// Convert to 6byte / pixel 
	{ 
		register USHORT *data = (USHORT*)*(im->data); 
		for( y = 0; y < im->height; y++) 
		{ 
			for( x=0; x < im->width; x++) 
			{ 
				c1 =  y * im->bytesPerLine/2 + x * 4; 
				c2 = (y * im->width + x) * 3; 
				c1++; 
				data [c2++] = data [c1++]; 
				data [c2++] = data [c1++]; 
				data [c2++] = data [c1++]; 
			} 
		} 
		im->bitsPerPixel = 48; 
		im->bytesPerLine = im->width * 6; 
	} 
	 
	im->dataSize = im->height * im->bytesPerLine; 
} 
 
 
void OneToTwoByte( PTImage *im ) 
{ 
	register int x,y,c1,c2,i; 
	int bpp; 
	 
	if( im->bitsPerPixel > 32 ) return; 
 
	bpp = im->bitsPerPixel / 8; 
 
	for( y = im->height-1; y>=0; y--) 
	{ 
		for( x= im->width-1; x>=0; x--) 
		{ 
			c1 = ( y * im->width + x) * bpp * 2; 
			c2 = y * im->bytesPerLine + x * bpp; 
			 
			for(i=0; idata + c1)) = ((USHORT)(*(im->data))[c2++]) << 8; c1 += 2; 
			} 
		} 
	} 
	im->bitsPerPixel 	*= 2; 
	im->bytesPerLine 	= im->width * im->bitsPerPixel/8; 
	im->dataSize 		= im->height * im->bytesPerLine; 
} 
 
void TwoToOneByte( PTImage *im ){ 
	register int x,y,c1,c2,i; 
	int bpp_old, bpp_new; 
	 
	if( im->bitsPerPixel < 48 ) return; 
	 
	bpp_old = im->bitsPerPixel / 8; 
	bpp_new = bpp_old / 2; 
 
	for( y = 0; y < im->height; y++){ 
		for( x=0; x < im->width; x++){ 
			c1 = (y * im->width + x) * bpp_new; 
			c2 = y * im->bytesPerLine + x * bpp_old; 
			 
			for(i=0; idata))[c1++] = *((USHORT*)(*im->data + c2)) >> 8; c2 += 2; 
			} 
		} 
	} 
	im->bitsPerPixel 	/= 2; 
	im->bytesPerLine 	= im->width * im->bitsPerPixel/8; 
	im->dataSize 		= im->height * im->bytesPerLine; 
} 
 
 
 
void SetImageDefaults(PTImage *im){ 
	im->data 		= NULL; 
	im->bytesPerLine	= 0; 
	im->width		= 0; 
	im->height		= 0; 
	im->dataSize		= 0; 
	im->bitsPerPixel	= 0; 
	im->format		= 0; 
	im->dataformat		= _RGB; 
	im->hfov		= 0.0; 
	im->yaw			= 0.0; 
	im->pitch		= 0.0; 
	im->roll		= 0.0; 
	SetCorrectDefaults( &(im->cP) ); 
	*(im->name)		= 0; 
	im->selection.top	= 0; 
	im->selection.bottom    = 0; 
	im->selection.left	= 0; 
	im->selection.right	= 0; 
} 
 
// Copy all position  related data 
void CopyPosition( PTImage *to, PTImage *from ){ 
	to->format 		= from->format; 
	to->hfov		= from->hfov; 
	to->yaw			= from->yaw; 
	to->pitch		= from->pitch; 
	to->roll		= from->roll; 
	memcpy(&(to->cP), &(from->cP), sizeof( cPrefs ) ); 
} 
 
#ifndef abs 
#define abs(a) ( (a) >= 0 ? (a) : -(a) ) 
#endif 
#define EPSILON 1.0e-8 
 
// Compare position data of two image 
// return 0 if equal 
// return +1 if only yaw differs 
// return +2 if more differs 
int PositionCmp( PTImage *im1, PTImage *im2 ) 
{ 
	if( abs(im1->format - im2->format	) < EPSILON 	&& 
		abs(im1->hfov	- im2->hfov		) < EPSILON		&& 
		abs(im1->pitch	- im2->pitch	) < EPSILON		&& 
		abs(im1->roll	- im2->roll		) < EPSILON		&& 
		EqualCPrefs( &im1->cP, &im2->cP ) ) 
	{ 
		if( im1->yaw	== im2->yaw	) 
			return 0; 
		else 
			return 1; 
	} 
	else 
	{ 
		return 2; 
	} 
} 
 
// Compare optimizable cprefs-parameters 
int EqualCPrefs( cPrefs *c1, cPrefs *c2 ) 
{ 
	if( abs(c1->radial_params[0][0] - c2->radial_params[0][0]	) < EPSILON  && 
		abs(c1->radial_params[0][1] - c2->radial_params[0][1]	) < EPSILON  && 
		abs(c1->radial_params[0][2] - c2->radial_params[0][2]	) < EPSILON  && 
		abs(c1->radial_params[0][3] - c2->radial_params[0][3]	) < EPSILON  && 
		abs(c1->vertical_params[0]	- c2->vertical_params[0]	) < EPSILON	 && 
		abs(c1->horizontal_params[0]- c2->horizontal_params[0]	) < EPSILON ) 
		return TRUE; 
	else 
		return FALSE; 
} 
 
	 
 
 
// Do these images have equal pixel sizes 
 
int HaveEqualSize( PTImage *im1, PTImage *im2 ) 
{ 
 
	if( (im1->bytesPerLine != im2->bytesPerLine) || 
		(im1->width        != im2->width)		 || 
		(im1->height       != im2->height)       || 
		(im1->dataSize     != im2->dataSize)     || 
		(im1->bitsPerPixel != im2->bitsPerPixel) ) 
		return FALSE; 
	else 
		return TRUE; 
} 
 
 
 
void SetSizeDefaults( sPrefs *pref) 
{ 
	 
	pref->magic			= 70;			// File validity check; must be 70 
	pref->displayPart	= TRUE;			// Display cropped/framed image ? 
	pref->saveFile		= FALSE;		// Save to tempfile? 
	pref->launchApp		= FALSE;		// Open sFile ? 
	pref->interpolator	= _poly3; 
	makePathForResult( &(pref->sFile) ); 
	makePathToHost ( &(pref->lApp) ); 
	pref->gamma			= 1.0; 
	pref->noAlpha		= FALSE;			// Check only for Photoshop LE 
	pref->optCreatePano = TRUE; 
} 
 
 
 
 
 
void	SetVRPanoOptionsDefaults( VRPanoOptions *v) 
{ 
	v->width	= 	400; 
	v->height	=	300; 
	v->pan		=	0.0; 
	v->tilt		=	0.0; 
	v->fov		=	45.0; 
	v->codec	=	0;  
	v->cquality	=	80; 
	v->progressive = FALSE; 
} 
 
			 
 
// Crop Image to selection rectangle	 
int CropImage(PTImage *im, PTRect *r){ 
 
	int x,y,i; 
	unsigned char *src, *dst, **data = NULL; 
	int width = r->right - r->left; 
	int height = r->bottom - r->top; 
	int bytesPerPixel = im->bitsPerPixel / 8 ; 
	int bytesPerLine = width * im->bitsPerPixel / 8 ; 
	int dataSize = bytesPerLine * height; 
 
	// Some checks first 
	if( r->left < 0 || r->left >im->width || 
	    r->right < 0|| r->right > im->width || 
	    r->left >= r->right|| 
	    r->top < 0 || r->top > im->height|| 
	    r->bottom < 0 || r->bottom > im->height || 
	    r->top >= r->bottom ) 
		return -1; 
 
 
	//data = (unsigned char**) mymalloc( dataSize ); 
	data = new unsigned char*[ dataSize ]; 
	if( data == NULL ) return -1; 
	 
	for(y=0; ydata + (y+r->top)*im->bytesPerLine +r->left*bytesPerPixel,  
                    dst = *data + y*bytesPerLine;  
		    xdata); 
	delete (void**)im->data; 
	 
	im->data = data; 
	im->width = width; 
	im->height = height; 
	im->bytesPerLine = bytesPerLine; 
	im->dataSize = dataSize; 
	 
	return 0; 
}