diff options
Diffstat (limited to 'plugins/AdvaImg/src/FreeImageToolkit/ClassicRotate.cpp')
| -rw-r--r-- | plugins/AdvaImg/src/FreeImageToolkit/ClassicRotate.cpp | 917 | 
1 files changed, 0 insertions, 917 deletions
diff --git a/plugins/AdvaImg/src/FreeImageToolkit/ClassicRotate.cpp b/plugins/AdvaImg/src/FreeImageToolkit/ClassicRotate.cpp deleted file mode 100644 index 2e561d4877..0000000000 --- a/plugins/AdvaImg/src/FreeImageToolkit/ClassicRotate.cpp +++ /dev/null @@ -1,917 +0,0 @@ -// ========================================================== -// Bitmap rotation by means of 3 shears. -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Thorsten Radde (support@IdealSoftware.com) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// This file is part of FreeImage 3 -// -// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES -// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE -// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED -// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT -// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY -// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL -// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER -// THIS DISCLAIMER. -// -// Use at your own risk! -// ========================================================== - -/*  - ============================================================ - References :  - [1] Paeth A., A Fast Algorithm for General Raster Rotation.  - Graphics Gems, p. 179, Andrew Glassner editor, Academic Press, 1990.  - [2] Yariv E., High quality image rotation (rotate by shear).  - [Online] http://www.codeproject.com/bitmap/rotatebyshear.asp - [3] Treskunov A., Fast and high quality true-color bitmap rotation function. - [Online] http://anton.treskunov.net/Software/doc/fast_and_high_quality_true_color_bitmap_rotation_function.html - ============================================================ -*/ - -#include "FreeImage.h" -#include "Utilities.h" - -#define RBLOCK		64	// image blocks of RBLOCK*RBLOCK pixels - -// -------------------------------------------------------------------------- - -/** -Skews a row horizontally (with filtered weights).  -Limited to 45 degree skewing only. Filters two adjacent pixels. -Parameter T can be BYTE, WORD of float.  -@param src Pointer to source image to rotate -@param dst Pointer to destination image -@param row Row index -@param iOffset Skew offset -@param dWeight Relative weight of right pixel -@param bkcolor Background color -*/ -template <class T> void  -HorizontalSkewT(FIBITMAP *src, FIBITMAP *dst, int row, int iOffset, double weight, const void *bkcolor = NULL) { -	int iXPos; - -	const unsigned src_width  = FreeImage_GetWidth(src); -	const unsigned dst_width  = FreeImage_GetWidth(dst); - -	T pxlSrc[4], pxlLeft[4], pxlOldLeft[4];	// 4 = 4*sizeof(T) max -	 -	// background -	const T pxlBlack[4] = {0, 0, 0, 0 }; -	const T *pxlBkg = static_cast<const T*>(bkcolor); // assume at least bytespp and 4*sizeof(T) max -	if(!pxlBkg) { -		// default background color is black -		pxlBkg = pxlBlack; -	} - -	// calculate the number of bytes per pixel -	const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); -	// calculate the number of samples per pixel -	const unsigned samples = bytespp / sizeof(T); - -	BYTE *src_bits = FreeImage_GetScanLine(src, row); -	BYTE *dst_bits = FreeImage_GetScanLine(dst, row); - -	// fill gap left of skew with background -	if(bkcolor) { -		for(int k = 0; k < iOffset; k++) { -			memcpy(&dst_bits[k * bytespp], bkcolor, bytespp); -		} -		AssignPixel((BYTE*)&pxlOldLeft[0], (BYTE*)bkcolor, bytespp); -	} else { -		if(iOffset > 0) { -			memset(dst_bits, 0, iOffset * bytespp); -		}		 -		memset(&pxlOldLeft[0], 0, bytespp); -	} - -	for(unsigned i = 0; i < src_width; i++) { -		// loop through row pixels -		AssignPixel((BYTE*)&pxlSrc[0], (BYTE*)src_bits, bytespp); -		// calculate weights -		for(unsigned j = 0; j < samples; j++) { -			pxlLeft[j] = static_cast<T>(pxlBkg[j] + (pxlSrc[j] - pxlBkg[j]) * weight + 0.5); -		} -		// check boundaries  -		iXPos = i + iOffset; -		if((iXPos >= 0) && (iXPos < (int)dst_width)) { -			// update left over on source -			for(unsigned j = 0; j < samples; j++) { -				pxlSrc[j] = pxlSrc[j] - (pxlLeft[j] - pxlOldLeft[j]); -			} -			AssignPixel((BYTE*)&dst_bits[iXPos*bytespp], (BYTE*)&pxlSrc[0], bytespp); -		} -		// save leftover for next pixel in scan -		AssignPixel((BYTE*)&pxlOldLeft[0], (BYTE*)&pxlLeft[0], bytespp); - -		// next pixel in scan -		src_bits += bytespp; -	}			 - -	// go to rightmost point of skew -	iXPos = src_width + iOffset;  - -	if((iXPos >= 0) && (iXPos < (int)dst_width)) { -		dst_bits = FreeImage_GetScanLine(dst, row) + iXPos * bytespp; - -		// If still in image bounds, put leftovers there -		AssignPixel((BYTE*)dst_bits, (BYTE*)&pxlOldLeft[0], bytespp); - -		// clear to the right of the skewed line with background -		dst_bits += bytespp; -		if(bkcolor) { -			for(unsigned i = 0; i < dst_width - iXPos - 1; i++) { -				memcpy(&dst_bits[i * bytespp], bkcolor, bytespp); -			} -		} else { -			memset(dst_bits, 0, bytespp * (dst_width - iXPos - 1)); -		} - -	} -} - -/** -Skews a row horizontally (with filtered weights).  -Limited to 45 degree skewing only. Filters two adjacent pixels. -@param src Pointer to source image to rotate -@param dst Pointer to destination image -@param row Row index -@param iOffset Skew offset -@param dWeight Relative weight of right pixel -@param bkcolor Background color -*/ -static void  -HorizontalSkew(FIBITMAP *src, FIBITMAP *dst, int row, int iOffset, double dWeight, const void *bkcolor) { -	FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - -	switch(image_type) { -		case FIT_BITMAP: -			switch(FreeImage_GetBPP(src)) { -				case 8: -				case 24: -				case 32: -					HorizontalSkewT<BYTE>(src, dst, row, iOffset, dWeight, bkcolor); -				break; -			} -			break; -		case FIT_UINT16: -		case FIT_RGB16: -		case FIT_RGBA16: -			HorizontalSkewT<WORD>(src, dst, row, iOffset, dWeight, bkcolor); -			break; -		case FIT_FLOAT: -		case FIT_RGBF: -		case FIT_RGBAF: -			HorizontalSkewT<float>(src, dst, row, iOffset, dWeight, bkcolor); -			break; -	} -} - -/** -Skews a column vertically (with filtered weights).  -Limited to 45 degree skewing only. Filters two adjacent pixels. -Parameter T can be BYTE, WORD of float.  -@param src Pointer to source image to rotate -@param dst Pointer to destination image -@param col Column index -@param iOffset Skew offset -@param dWeight Relative weight of upper pixel -@param bkcolor Background color -*/ -template <class T> void  -VerticalSkewT(FIBITMAP *src, FIBITMAP *dst, int col, int iOffset, double weight, const void *bkcolor = NULL) { -	int iYPos; - -	unsigned src_height = FreeImage_GetHeight(src); -	unsigned dst_height = FreeImage_GetHeight(dst); - -	T pxlSrc[4], pxlLeft[4], pxlOldLeft[4];	// 4 = 4*sizeof(T) max - -	// background -	const T pxlBlack[4] = {0, 0, 0, 0 }; -	const T *pxlBkg = static_cast<const T*>(bkcolor); // assume at least bytespp and 4*sizeof(T) max -	if(!pxlBkg) { -		// default background color is black -		pxlBkg = pxlBlack; -	} - -	// calculate the number of bytes per pixel -	const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); -	// calculate the number of samples per pixel -	const unsigned samples = bytespp / sizeof(T); - -	const unsigned src_pitch = FreeImage_GetPitch(src); -	const unsigned dst_pitch = FreeImage_GetPitch(dst); -	const unsigned index = col * bytespp; - -	BYTE *src_bits = FreeImage_GetBits(src) + index; -	BYTE *dst_bits = FreeImage_GetBits(dst) + index; - -	// fill gap above skew with background -	if(bkcolor) { -		for(int k = 0; k < iOffset; k++) { -			memcpy(dst_bits, bkcolor, bytespp); -			dst_bits += dst_pitch; -		} -		memcpy(&pxlOldLeft[0], bkcolor, bytespp); -	} else { -		for(int k = 0; k < iOffset; k++) { -			memset(dst_bits, 0, bytespp); -			dst_bits += dst_pitch; -		} -		memset(&pxlOldLeft[0], 0, bytespp); -	} - -	for(unsigned i = 0; i < src_height; i++) { -		// loop through column pixels -		AssignPixel((BYTE*)(&pxlSrc[0]), src_bits, bytespp); -		// calculate weights -		for(unsigned j = 0; j < samples; j++) { -			pxlLeft[j] = static_cast<T>(pxlBkg[j] + (pxlSrc[j] - pxlBkg[j]) * weight + 0.5); -		} -		// check boundaries -		iYPos = i + iOffset; -		if((iYPos >= 0) && (iYPos < (int)dst_height)) { -			// update left over on source -			for(unsigned j = 0; j < samples; j++) { -				pxlSrc[j] = pxlSrc[j] - (pxlLeft[j] - pxlOldLeft[j]); -			} -			dst_bits = FreeImage_GetScanLine(dst, iYPos) + index; -			AssignPixel(dst_bits, (BYTE*)(&pxlSrc[0]), bytespp); -		} -		// save leftover for next pixel in scan -		AssignPixel((BYTE*)(&pxlOldLeft[0]), (BYTE*)(&pxlLeft[0]), bytespp); - -		// next pixel in scan -		src_bits += src_pitch; -	} -	// go to bottom point of skew -	iYPos = src_height + iOffset; - -	if((iYPos >= 0) && (iYPos < (int)dst_height)) { -		dst_bits = FreeImage_GetScanLine(dst, iYPos) + index; - -		// if still in image bounds, put leftovers there				 -		AssignPixel((BYTE*)(dst_bits), (BYTE*)(&pxlOldLeft[0]), bytespp); - -		// clear below skewed line with background -		if(bkcolor) { -			while(++iYPos < (int)dst_height) {					 -				dst_bits += dst_pitch; -				AssignPixel((BYTE*)(dst_bits), (BYTE*)(bkcolor), bytespp); -			} -		} else { -			while(++iYPos < (int)dst_height) {					 -				dst_bits += dst_pitch; -				memset(dst_bits, 0, bytespp); -			} -		} -	} -} - -/** -Skews a column vertically (with filtered weights).  -Limited to 45 degree skewing only. Filters two adjacent pixels. -@param src Pointer to source image to rotate -@param dst Pointer to destination image -@param col Column index -@param iOffset Skew offset -@param dWeight Relative weight of upper pixel -@param bkcolor Background color -*/ -static void  -VerticalSkew(FIBITMAP *src, FIBITMAP *dst, int col, int iOffset, double dWeight, const void *bkcolor) { -	FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - -	switch(image_type) { -		case FIT_BITMAP: -			switch(FreeImage_GetBPP(src)) { -				case 8: -				case 24: -				case 32: -					VerticalSkewT<BYTE>(src, dst, col, iOffset, dWeight, bkcolor); -					break; -			} -			break; -			case FIT_UINT16: -			case FIT_RGB16: -			case FIT_RGBA16: -				VerticalSkewT<WORD>(src, dst, col, iOffset, dWeight, bkcolor); -				break; -			case FIT_FLOAT: -			case FIT_RGBF: -			case FIT_RGBAF: -				VerticalSkewT<float>(src, dst, col, iOffset, dWeight, bkcolor); -				break; -	} -}  - -/** -Rotates an image by 90 degrees (counter clockwise).  -Precise rotation, no filters required.<br> -Code adapted from CxImage (http://www.xdp.it/cximage.htm) -@param src Pointer to source image to rotate -@return Returns a pointer to a newly allocated rotated image if successful, returns NULL otherwise -*/ -static FIBITMAP*  -Rotate90(FIBITMAP *src) { - -	const unsigned bpp = FreeImage_GetBPP(src); - -	const unsigned src_width  = FreeImage_GetWidth(src); -	const unsigned src_height = FreeImage_GetHeight(src);	 -	const unsigned dst_width  = src_height; -	const unsigned dst_height = src_width; - -	FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - -	// allocate and clear dst image -	FIBITMAP *dst = FreeImage_AllocateT(image_type, dst_width, dst_height, bpp); -	if(NULL == dst) return NULL; - -	// get src and dst scan width -	const unsigned src_pitch  = FreeImage_GetPitch(src); -	const unsigned dst_pitch  = FreeImage_GetPitch(dst); - -	switch(image_type) { -		case FIT_BITMAP: -			if(bpp == 1) { -				// speedy rotate for BW images - -				BYTE *bsrc  = FreeImage_GetBits(src);  -				BYTE *bdest = FreeImage_GetBits(dst); - -				BYTE *dbitsmax = bdest + dst_height * dst_pitch - 1; - -				for(unsigned y = 0; y < src_height; y++) { -					// figure out the column we are going to be copying to -					const div_t div_r = div(y, 8); -					// set bit pos of src column byte -					const BYTE bitpos = (BYTE)(128 >> div_r.rem); -					BYTE *srcdisp = bsrc + y * src_pitch; -					for(unsigned x = 0; x < src_pitch; x++) { -						// get source bits -						BYTE *sbits = srcdisp + x; -						// get destination column -						BYTE *nrow = bdest + (dst_height - 1 - (x * 8)) * dst_pitch + div_r.quot; -						for (int z = 0; z < 8; z++) { -						   // get destination byte -							BYTE *dbits = nrow - z * dst_pitch; -							if ((dbits < bdest) || (dbits > dbitsmax)) break; -							if (*sbits & (128 >> z)) *dbits |= bitpos; -						} -					} -				} -			} -			else if((bpp == 8) || (bpp == 24) || (bpp == 32)) { -				// anything other than BW : -				// This optimized version of rotation rotates image by smaller blocks. It is quite -				// a bit faster than obvious algorithm, because it produces much less CPU cache misses. -				// This optimization can be tuned by changing block size (RBLOCK). 96 is good value for current -				// CPUs (tested on Athlon XP and Celeron D). Larger value (if CPU has enough cache) will increase -				// speed somehow, but once you drop out of CPU's cache, things will slow down drastically. -				// For older CPUs with less cache, lower value would yield better results. - -				BYTE *bsrc  = FreeImage_GetBits(src);  // source pixels -				BYTE *bdest = FreeImage_GetBits(dst);  // destination pixels - -				// calculate the number of bytes per pixel (1 for 8-bit, 3 for 24-bit or 4 for 32-bit) -				const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); -				 -				// for all image blocks of RBLOCK*RBLOCK pixels -				 -				// x-segment -				for(unsigned xs = 0; xs < dst_width; xs += RBLOCK) { -					// y-segment -					for(unsigned ys = 0; ys < dst_height; ys += RBLOCK) { -						for(unsigned y = ys; y < MIN(dst_height, ys + RBLOCK); y++) {    // do rotation -							const unsigned y2 = dst_height - y - 1; -							// point to src pixel at (y2, xs) -							BYTE *src_bits = bsrc + (xs * src_pitch) + (y2 * bytespp); -							// point to dst pixel at (xs, y) -							BYTE *dst_bits = bdest + (y * dst_pitch) + (xs * bytespp); -							for(unsigned x = xs; x < MIN(dst_width, xs + RBLOCK); x++) { -								// dst.SetPixel(x, y, src.GetPixel(y2, x)); -								AssignPixel(dst_bits, src_bits, bytespp); -								dst_bits += bytespp; -								src_bits += src_pitch; -							} -						} -					} -				} -			} -			break; -		case FIT_UINT16: -		case FIT_RGB16: -		case FIT_RGBA16: -		case FIT_FLOAT: -		case FIT_RGBF: -		case FIT_RGBAF: -		{ -			BYTE *bsrc  = FreeImage_GetBits(src);  // source pixels -			BYTE *bdest = FreeImage_GetBits(dst);  // destination pixels - -			// calculate the number of bytes per pixel -			const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - -			for(unsigned y = 0; y < dst_height; y++) { -				BYTE *src_bits = bsrc + (src_width - 1 - y) * bytespp; -				BYTE *dst_bits = bdest + (y * dst_pitch); -				for(unsigned x = 0; x < dst_width; x++) { -					AssignPixel(dst_bits, src_bits, bytespp); -					src_bits += src_pitch; -					dst_bits += bytespp; -				} -			} -		} -		break; -	} - -	return dst; -} - -/** -Rotates an image by 180 degrees (counter clockwise).  -Precise rotation, no filters required. -@param src Pointer to source image to rotate -@return Returns a pointer to a newly allocated rotated image if successful, returns NULL otherwise -*/ -static FIBITMAP*  -Rotate180(FIBITMAP *src) { -	int x, y, k, pos; - -	const int bpp = FreeImage_GetBPP(src); - -	const int src_width  = FreeImage_GetWidth(src); -	const int src_height = FreeImage_GetHeight(src); -	const int dst_width  = src_width; -	const int dst_height = src_height; - -	FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - -	FIBITMAP *dst = FreeImage_AllocateT(image_type, dst_width, dst_height, bpp); -	if(NULL == dst) return NULL; - -	switch(image_type) { -		case FIT_BITMAP: -			if(bpp == 1) { -				for(int y = 0; y < src_height; y++) { -					BYTE *src_bits = FreeImage_GetScanLine(src, y); -					BYTE *dst_bits = FreeImage_GetScanLine(dst, dst_height - y - 1); -					for(int x = 0; x < src_width; x++) { -						// get bit at (x, y) -						k = (src_bits[x >> 3] & (0x80 >> (x & 0x07))) != 0; -						// set bit at (dst_width - x - 1, dst_height - y - 1) -						pos = dst_width - x - 1; -						k ? dst_bits[pos >> 3] |= (0x80 >> (pos & 0x7)) : dst_bits[pos >> 3] &= (0xFF7F >> (pos & 0x7)); -					}			 -				} -				break; -			} -			// else if((bpp == 8) || (bpp == 24) || (bpp == 32)) FALL TROUGH -		case FIT_UINT16: -		case FIT_RGB16: -		case FIT_RGBA16: -		case FIT_FLOAT: -		case FIT_RGBF: -		case FIT_RGBAF: -		{ -			 // Calculate the number of bytes per pixel -			const int bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - -			for(y = 0; y < src_height; y++) { -				BYTE *src_bits = FreeImage_GetScanLine(src, y); -				BYTE *dst_bits = FreeImage_GetScanLine(dst, dst_height - y - 1) + (dst_width - 1) * bytespp; -				for(x = 0; x < src_width; x++) { -					// get pixel at (x, y) -					// set pixel at (dst_width - x - 1, dst_height - y - 1) -					AssignPixel(dst_bits, src_bits, bytespp); -					src_bits += bytespp; -					dst_bits -= bytespp;					 -				}				 -			} -		} -		break; -	} - -	return dst; -} - -/** -Rotates an image by 270 degrees (counter clockwise).  -Precise rotation, no filters required.<br> -Code adapted from CxImage (http://www.xdp.it/cximage.htm) -@param src Pointer to source image to rotate -@return Returns a pointer to a newly allocated rotated image if successful, returns NULL otherwise -*/ -static FIBITMAP*  -Rotate270(FIBITMAP *src) { -	int x2, dlineup; - -	const unsigned bpp = FreeImage_GetBPP(src); - -	const unsigned src_width  = FreeImage_GetWidth(src); -	const unsigned src_height = FreeImage_GetHeight(src);	 -	const unsigned dst_width  = src_height; -	const unsigned dst_height = src_width; - -	FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - -	// allocate and clear dst image -	FIBITMAP *dst = FreeImage_AllocateT(image_type, dst_width, dst_height, bpp); -	if(NULL == dst) return NULL; - -	// get src and dst scan width -	const unsigned src_pitch  = FreeImage_GetPitch(src); -	const unsigned dst_pitch  = FreeImage_GetPitch(dst); -	 -	switch(image_type) { -		case FIT_BITMAP: -			if(bpp == 1) { -				// speedy rotate for BW images -				 -				BYTE *bsrc  = FreeImage_GetBits(src);  -				BYTE *bdest = FreeImage_GetBits(dst); -				BYTE *dbitsmax = bdest + dst_height * dst_pitch - 1; -				dlineup = 8 * dst_pitch - dst_width; - -				for(unsigned y = 0; y < src_height; y++) { -					// figure out the column we are going to be copying to -					const div_t div_r = div(y + dlineup, 8); -					// set bit pos of src column byte -					const BYTE bitpos = (BYTE)(1 << div_r.rem); -					const BYTE *srcdisp = bsrc + y * src_pitch; -					for(unsigned x = 0; x < src_pitch; x++) { -						// get source bits -						const BYTE *sbits = srcdisp + x; -						// get destination column -						BYTE *nrow = bdest + (x * 8) * dst_pitch + dst_pitch - 1 - div_r.quot; -						for(unsigned z = 0; z < 8; z++) { -						   // get destination byte -							BYTE *dbits = nrow + z * dst_pitch; -							if ((dbits < bdest) || (dbits > dbitsmax)) break; -							if (*sbits & (128 >> z)) *dbits |= bitpos; -						} -					} -				} -			}  -			else if((bpp == 8) || (bpp == 24) || (bpp == 32)) { -				// anything other than BW : -				// This optimized version of rotation rotates image by smaller blocks. It is quite -				// a bit faster than obvious algorithm, because it produces much less CPU cache misses. -				// This optimization can be tuned by changing block size (RBLOCK). 96 is good value for current -				// CPUs (tested on Athlon XP and Celeron D). Larger value (if CPU has enough cache) will increase -				// speed somehow, but once you drop out of CPU's cache, things will slow down drastically. -				// For older CPUs with less cache, lower value would yield better results. - -				BYTE *bsrc  = FreeImage_GetBits(src);  // source pixels -				BYTE *bdest = FreeImage_GetBits(dst);  // destination pixels - -				// Calculate the number of bytes per pixel (1 for 8-bit, 3 for 24-bit or 4 for 32-bit) -				const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - -				// for all image blocks of RBLOCK*RBLOCK pixels - -				// x-segment -				for(unsigned xs = 0; xs < dst_width; xs += RBLOCK) { -					// y-segment -					for(unsigned ys = 0; ys < dst_height; ys += RBLOCK) { -						for(unsigned x = xs; x < MIN(dst_width, xs + RBLOCK); x++) {    // do rotation -							x2 = dst_width - x - 1; -							// point to src pixel at (ys, x2) -							BYTE *src_bits = bsrc + (x2 * src_pitch) + (ys * bytespp); -							// point to dst pixel at (x, ys) -							BYTE *dst_bits = bdest + (ys * dst_pitch) + (x * bytespp); -							for(unsigned y = ys; y < MIN(dst_height, ys + RBLOCK); y++) { -								// dst.SetPixel(x, y, src.GetPixel(y, x2)); -								AssignPixel(dst_bits, src_bits, bytespp); -								src_bits += bytespp; -								dst_bits += dst_pitch; -							} -						} -					} -				} -			} -			break; -		case FIT_UINT16: -		case FIT_RGB16: -		case FIT_RGBA16: -		case FIT_FLOAT: -		case FIT_RGBF: -		case FIT_RGBAF: -		{ -			BYTE *bsrc  = FreeImage_GetBits(src);  // source pixels -			BYTE *bdest = FreeImage_GetBits(dst);  // destination pixels - -			// calculate the number of bytes per pixel -			const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - -			for(unsigned y = 0; y < dst_height; y++) { -				BYTE *src_bits = bsrc + (src_height - 1) * src_pitch + y * bytespp; -				BYTE *dst_bits = bdest + (y * dst_pitch); -				for(unsigned x = 0; x < dst_width; x++) { -					AssignPixel(dst_bits, src_bits, bytespp); -					src_bits -= src_pitch; -					dst_bits += bytespp; -				} -			} -		} -		break; -	} - -	return dst; -} - -/** -Rotates an image by a given degree in range [-45 .. +45] (counter clockwise)  -using the 3-shear technique. -@param src Pointer to source image to rotate -@param dAngle Rotation angle -@return Returns a pointer to a newly allocated rotated image if successful, returns NULL otherwise -*/ -static FIBITMAP*  -Rotate45(FIBITMAP *src, double dAngle, const void *bkcolor) { -	const double ROTATE_PI = double(3.1415926535897932384626433832795); - -	unsigned u; - -	const unsigned bpp = FreeImage_GetBPP(src); - -	const double dRadAngle = dAngle * ROTATE_PI / double(180); // Angle in radians -	const double dSinE = sin(dRadAngle); -	const double dTan = tan(dRadAngle / 2); - -	const unsigned src_width  = FreeImage_GetWidth(src); -	const unsigned src_height = FreeImage_GetHeight(src); - -	FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - -	// Calc first shear (horizontal) destination image dimensions  -	const unsigned width_1  = src_width + unsigned((double)src_height * fabs(dTan) + 0.5); -	const unsigned height_1 = src_height;  - -	// Perform 1st shear (horizontal) -	// ---------------------------------------------------------------------- - -	// Allocate image for 1st shear -	FIBITMAP *dst1 = FreeImage_AllocateT(image_type, width_1, height_1, bpp); -	if(NULL == dst1) { -		return NULL; -	} -	 -	for(u = 0; u < height_1; u++) {   -		double dShear; - -		if(dTan >= 0)	{ -			// Positive angle -			dShear = (u + 0.5) * dTan; -		} -		else { -			// Negative angle -			dShear = (double(u) - height_1 + 0.5) * dTan; -		} -		int iShear = int(floor(dShear)); -		HorizontalSkew(src, dst1, u, iShear, dShear - double(iShear), bkcolor); -	} - -	// Perform 2nd shear  (vertical) -	// ---------------------------------------------------------------------- - -	// Calc 2nd shear (vertical) destination image dimensions -	const unsigned width_2  = width_1; -	unsigned height_2 = unsigned((double)src_width * fabs(dSinE) + (double)src_height * cos(dRadAngle) + 0.5) + 1; - -	// Allocate image for 2nd shear -	FIBITMAP *dst2 = FreeImage_AllocateT(image_type, width_2, height_2, bpp); -	if(NULL == dst2) { -		FreeImage_Unload(dst1); -		return NULL; -	} - -	double dOffset;     // Variable skew offset -	if(dSinE > 0)	{    -		// Positive angle -		dOffset = (src_width - 1.0) * dSinE; -	} -	else { -		// Negative angle -		dOffset = -dSinE * (double(src_width) - width_2); -	} - -	for(u = 0; u < width_2; u++, dOffset -= dSinE) { -		int iShear = int(floor(dOffset)); -		VerticalSkew(dst1, dst2, u, iShear, dOffset - double(iShear), bkcolor); -	} - -	// Perform 3rd shear (horizontal) -	// ---------------------------------------------------------------------- - -	// Free result of 1st shear -	FreeImage_Unload(dst1); - -	// Calc 3rd shear (horizontal) destination image dimensions -	const unsigned width_3  = unsigned(double(src_height) * fabs(dSinE) + double(src_width) * cos(dRadAngle) + 0.5) + 1; -	const unsigned height_3 = height_2; - -	// Allocate image for 3rd shear -	FIBITMAP *dst3 = FreeImage_AllocateT(image_type, width_3, height_3, bpp); -	if(NULL == dst3) { -		FreeImage_Unload(dst2); -		return NULL; -	} - -	if(dSinE >= 0) { -		// Positive angle -		dOffset = (src_width - 1.0) * dSinE * -dTan; -	} -	else { -		// Negative angle -		dOffset = dTan * ( (src_width - 1.0) * -dSinE + (1.0 - height_3) ); -	} -	for(u = 0; u < height_3; u++, dOffset += dTan) { -		int iShear = int(floor(dOffset)); -		HorizontalSkew(dst2, dst3, u, iShear, dOffset - double(iShear), bkcolor); -	} -	// Free result of 2nd shear     -	FreeImage_Unload(dst2); - -	// Return result of 3rd shear -	return dst3;       -} - -/** -Rotates a 1-, 8-, 24- or 32-bit image by a given angle (given in degree).  -Angle is unlimited, except for 1-bit images (limited to integer multiples of 90 degree).  -3-shears technique is used. -@param src Pointer to source image to rotate -@param dAngle Rotation angle -@return Returns a pointer to a newly allocated rotated image if successful, returns NULL otherwise -*/ -static FIBITMAP*  -RotateAny(FIBITMAP *src, double dAngle, const void *bkcolor) { -	if(NULL == src) { -		return NULL; -	} - -	FIBITMAP *image = src; - -	while(dAngle >= 360) { -		// Bring angle to range of (-INF .. 360) -		dAngle -= 360; -	} -	while(dAngle < 0) { -		// Bring angle to range of [0 .. 360)  -		dAngle += 360; -	} -	if((dAngle > 45) && (dAngle <= 135)) { -		// Angle in (45 .. 135]  -		// Rotate image by 90 degrees into temporary image, -		// so it requires only an extra rotation angle  -		// of -45 .. +45 to complete rotation. -		image = Rotate90(src); -		dAngle -= 90; -	} -	else if((dAngle > 135) && (dAngle <= 225)) {  -		// Angle in (135 .. 225]  -		// Rotate image by 180 degrees into temporary image, -		// so it requires only an extra rotation angle  -		// of -45 .. +45 to complete rotation. -		image = Rotate180(src); -		dAngle -= 180; -	} -	else if((dAngle > 225) && (dAngle <= 315)) {  -		// Angle in (225 .. 315]  -		// Rotate image by 270 degrees into temporary image, -		// so it requires only an extra rotation angle  -		// of -45 .. +45 to complete rotation. -		image = Rotate270(src); -		dAngle -= 270; -	} - -	// If we got here, angle is in (-45 .. +45] - -	if(NULL == image)	{ -		// Failed to allocate middle image -		return NULL; -	} - -	if(0 == dAngle) { -		if(image == src) { -			// Nothing to do ... -			return FreeImage_Clone(src); -		} else { -			// No more rotation needed -			return image; -		} -	} -	else { -		// Perform last rotation -		FIBITMAP *dst = Rotate45(image, dAngle, bkcolor); - -		if(src != image) { -			// Middle image was required, free it now. -			FreeImage_Unload(image); -		} - -		return dst; -	} -} - -// ========================================================== - -FIBITMAP *DLL_CALLCONV  -FreeImage_Rotate(FIBITMAP *dib, double angle, const void *bkcolor) { -	if(!FreeImage_HasPixels(dib)) return NULL; - -	if(0 == angle) { -		return FreeImage_Clone(dib); -	} -	// DIB are stored upside down ... -	angle *= -1; - -	try { -		unsigned bpp = FreeImage_GetBPP(dib); -		FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); -		 -		switch(image_type) { -			case FIT_BITMAP: -				if(bpp == 1) { -					// only rotate for integer multiples of 90 degree -					if(fmod(angle, 90) != 0) -						return NULL; - -					// perform the rotation -					FIBITMAP *dst = RotateAny(dib, angle, bkcolor); -					if(!dst) throw(1); - -					// build a greyscale palette -					RGBQUAD *dst_pal = FreeImage_GetPalette(dst); -					if(FreeImage_GetColorType(dib) == FIC_MINISBLACK) { -						dst_pal[0].rgbRed = dst_pal[0].rgbGreen = dst_pal[0].rgbBlue = 0; -						dst_pal[1].rgbRed = dst_pal[1].rgbGreen = dst_pal[1].rgbBlue = 255;			 -					} else { -						dst_pal[0].rgbRed = dst_pal[0].rgbGreen = dst_pal[0].rgbBlue = 255; -						dst_pal[1].rgbRed = dst_pal[1].rgbGreen = dst_pal[1].rgbBlue = 0;			 -					} - -					// copy metadata from src to dst -					FreeImage_CloneMetadata(dst, dib); - -					return dst; -				} -				else if((bpp == 8) || (bpp == 24) || (bpp == 32)) { -					FIBITMAP *dst = RotateAny(dib, angle, bkcolor); -					if(!dst) throw(1); -					 -					if(bpp == 8) { -						// copy original palette to rotated bitmap -						RGBQUAD *src_pal = FreeImage_GetPalette(dib); -						RGBQUAD *dst_pal = FreeImage_GetPalette(dst); -						memcpy(&dst_pal[0], &src_pal[0], 256 * sizeof(RGBQUAD)); - -						// copy transparency table  -						FreeImage_SetTransparencyTable(dst, FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib)); - -						// copy background color  -						RGBQUAD bkcolor;  -						if( FreeImage_GetBackgroundColor(dib, &bkcolor) ) { -							FreeImage_SetBackgroundColor(dst, &bkcolor);  -						} - -					} - -					// copy metadata from src to dst -					FreeImage_CloneMetadata(dst, dib); - -					return dst; -				} -				break; -			case FIT_UINT16: -			case FIT_RGB16: -			case FIT_RGBA16: -			case FIT_FLOAT: -			case FIT_RGBF: -			case FIT_RGBAF: -			{ -				FIBITMAP *dst = RotateAny(dib, angle, bkcolor); -				if(!dst) throw(1); - -				// copy metadata from src to dst -				FreeImage_CloneMetadata(dst, dib); - -				return dst; -			} -			break; -		} - -	} catch(int) { -		return NULL; -	} - -	return NULL; -} -  | 
