diff options
Diffstat (limited to 'plugins/FreeImage/src/FreeImageToolkit/Channels.cpp')
| -rw-r--r-- | plugins/FreeImage/src/FreeImageToolkit/Channels.cpp | 488 | 
1 files changed, 488 insertions, 0 deletions
diff --git a/plugins/FreeImage/src/FreeImageToolkit/Channels.cpp b/plugins/FreeImage/src/FreeImageToolkit/Channels.cpp new file mode 100644 index 0000000000..f6e6c5509c --- /dev/null +++ b/plugins/FreeImage/src/FreeImageToolkit/Channels.cpp @@ -0,0 +1,488 @@ +// ========================================================== +// Channel processing support +// +// Design and implementation by +// - Hervé Drolon (drolon@infonie.fr) +// +// 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! +// ========================================================== + +#include "FreeImage.h" +#include "Utilities.h" + + +/** @brief Retrieves the red, green, blue or alpha channel of a BGR[A] image.  +@param src Input image to be processed. +@param channel Color channel to extract +@return Returns the extracted channel if successful, returns NULL otherwise. +*/ +FIBITMAP * DLL_CALLCONV  +FreeImage_GetChannel(FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel) { + +	if (!FreeImage_HasPixels(src)) return NULL; + +	FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); +	unsigned bpp = FreeImage_GetBPP(src); + +	// 24- or 32-bit  +	if(image_type == FIT_BITMAP && ((bpp == 24) || (bpp == 32))) { +		int c; + +		// select the channel to extract +		switch(channel) { +			case FICC_BLUE: +				c = FI_RGBA_BLUE; +				break; +			case FICC_GREEN: +				c = FI_RGBA_GREEN; +				break; +			case FICC_RED:  +				c = FI_RGBA_RED; +				break; +			case FICC_ALPHA: +				if(bpp != 32) return NULL; +				c = FI_RGBA_ALPHA; +				break; +			default: +				return NULL; +		} + +		// allocate a 8-bit dib +		unsigned width  = FreeImage_GetWidth(src); +		unsigned height = FreeImage_GetHeight(src); +		FIBITMAP *dst = FreeImage_Allocate(width, height, 8) ; +		if (!dst) return NULL; +		// build a greyscale palette +		RGBQUAD *pal = FreeImage_GetPalette(dst); +		for(int i = 0; i < 256; i++) { +			pal[i].rgbBlue = pal[i].rgbGreen = pal[i].rgbRed = (BYTE)i; +		} + +		// perform extraction + +		int bytespp = bpp / 8;	// bytes / pixel + +		for(unsigned y = 0; y < height; y++) { +			BYTE *src_bits = FreeImage_GetScanLine(src, y); +			BYTE *dst_bits = FreeImage_GetScanLine(dst, y); +			for(unsigned x = 0; x < width; x++) { +				dst_bits[x] = src_bits[c]; +				src_bits += bytespp; +			} +		} + +		// copy metadata from src to dst +		FreeImage_CloneMetadata(dst, src); +		 +		return dst; +	} + +	// 48-bit RGB or 64-bit RGBA images +	if ((image_type == FIT_RGB16) ||  (image_type == FIT_RGBA16)) { +		int c; + +		// select the channel to extract (always RGB[A]) +		switch(channel) { +			case FICC_BLUE: +				c = 2; +				break; +			case FICC_GREEN: +				c = 1; +				break; +			case FICC_RED:  +				c = 0; +				break; +			case FICC_ALPHA: +				if(bpp != 64) return NULL; +				c = 3; +				break; +			default: +				return NULL; +		} + +		// allocate a greyscale dib +		unsigned width  = FreeImage_GetWidth(src); +		unsigned height = FreeImage_GetHeight(src); +		FIBITMAP *dst = FreeImage_AllocateT(FIT_UINT16, width, height) ; +		if (!dst) return NULL; + +		// perform extraction + +		int bytespp = bpp / 16;	// words / pixel + +		for(unsigned y = 0; y < height; y++) { +			unsigned short *src_bits = (unsigned short*)FreeImage_GetScanLine(src, y); +			unsigned short *dst_bits = (unsigned short*)FreeImage_GetScanLine(dst, y); +			for(unsigned x = 0; x < width; x++) { +				dst_bits[x] = src_bits[c]; +				src_bits += bytespp; +			} +		} + +		// copy metadata from src to dst +		FreeImage_CloneMetadata(dst, src); +		 +		return dst; +	} + +	// 96-bit RGBF or 128-bit RGBAF images +	if ((image_type == FIT_RGBF) ||  (image_type == FIT_RGBAF)) { +		int c; + +		// select the channel to extract (always RGB[A]) +		switch(channel) { +			case FICC_BLUE: +				c = 2; +				break; +			case FICC_GREEN: +				c = 1; +				break; +			case FICC_RED:  +				c = 0; +				break; +			case FICC_ALPHA: +				if(bpp != 128) return NULL; +				c = 3; +				break; +			default: +				return NULL; +		} + +		// allocate a greyscale dib +		unsigned width  = FreeImage_GetWidth(src); +		unsigned height = FreeImage_GetHeight(src); +		FIBITMAP *dst = FreeImage_AllocateT(FIT_FLOAT, width, height) ; +		if (!dst) return NULL; + +		// perform extraction + +		int bytespp = bpp / 32;	// floats / pixel + +		for(unsigned y = 0; y < height; y++) { +			float *src_bits = (float*)FreeImage_GetScanLine(src, y); +			float *dst_bits = (float*)FreeImage_GetScanLine(dst, y); +			for(unsigned x = 0; x < width; x++) { +				dst_bits[x] = src_bits[c]; +				src_bits += bytespp; +			} +		} + +		// copy metadata from src to dst +		FreeImage_CloneMetadata(dst, src); +		 +		return dst; +	} + +	return NULL; +} + +/** @brief Insert a greyscale dib into a RGB[A] image.  +Both src and dst must have the same width and height. +@param dst Image to modify (RGB or RGBA) +@param src Input greyscale image to insert +@param channel Color channel to modify +@return Returns TRUE if successful, FALSE otherwise. +*/ +BOOL DLL_CALLCONV  +FreeImage_SetChannel(FIBITMAP *dst, FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel) { +	int c; + +	if (!FreeImage_HasPixels(src) || !FreeImage_HasPixels(dst)) return FALSE; +	 +	// src and dst images should have the same width and height +	unsigned src_width  = FreeImage_GetWidth(src); +	unsigned src_height = FreeImage_GetHeight(src); +	unsigned dst_width  = FreeImage_GetWidth(dst); +	unsigned dst_height = FreeImage_GetHeight(dst); +	if ((src_width != dst_width) || (src_height != dst_height)) +		return FALSE; + +	// src image should be grayscale, dst image should be RGB or RGBA +	FREE_IMAGE_COLOR_TYPE src_type = FreeImage_GetColorType(src); +	FREE_IMAGE_COLOR_TYPE dst_type = FreeImage_GetColorType(dst); +	if ((dst_type != FIC_RGB) && (dst_type != FIC_RGBALPHA) || (src_type != FIC_MINISBLACK)) { +		return FALSE; +	} + +	FREE_IMAGE_TYPE src_image_type = FreeImage_GetImageType(src); +	FREE_IMAGE_TYPE dst_image_type = FreeImage_GetImageType(dst); + +	if ((dst_image_type == FIT_BITMAP) && (src_image_type == FIT_BITMAP)) { + +		// src image should be grayscale, dst image should be 24- or 32-bit +		unsigned src_bpp = FreeImage_GetBPP(src); +		unsigned dst_bpp = FreeImage_GetBPP(dst); +		if ((src_bpp != 8) || (dst_bpp != 24) && (dst_bpp != 32)) +			return FALSE; + + +		// select the channel to modify +		switch(channel) { +			case FICC_BLUE: +				c = FI_RGBA_BLUE; +				break; +			case FICC_GREEN: +				c = FI_RGBA_GREEN; +				break; +			case FICC_RED:  +				c = FI_RGBA_RED; +				break; +			case FICC_ALPHA: +				if(dst_bpp != 32) return FALSE; +				c = FI_RGBA_ALPHA; +				break; +			default: +				return FALSE; +		} + +		// perform insertion + +		int bytespp = dst_bpp / 8;	// bytes / pixel + +		for(unsigned y = 0; y < dst_height; y++) { +			BYTE *src_bits = FreeImage_GetScanLine(src, y); +			BYTE *dst_bits = FreeImage_GetScanLine(dst, y); +			for(unsigned x = 0; x < dst_width; x++) { +				dst_bits[c] = src_bits[x]; +				dst_bits += bytespp; +			} +		} + +		return TRUE; +	} + +	if (((dst_image_type == FIT_RGB16) || (dst_image_type == FIT_RGBA16)) && (src_image_type == FIT_UINT16)) { + +		// src image should be grayscale, dst image should be 48- or 64-bit +		unsigned src_bpp = FreeImage_GetBPP(src); +		unsigned dst_bpp = FreeImage_GetBPP(dst); +		if ((src_bpp != 16) || (dst_bpp != 48) && (dst_bpp != 64)) +			return FALSE; + + +		// select the channel to modify (always RGB[A]) +		switch(channel) { +			case FICC_BLUE: +				c = 2; +				break; +			case FICC_GREEN: +				c = 1; +				break; +			case FICC_RED:  +				c = 0; +				break; +			case FICC_ALPHA: +				if(dst_bpp != 64) return FALSE; +				c = 3; +				break; +			default: +				return FALSE; +		} + +		// perform insertion + +		int bytespp = dst_bpp / 16;	// words / pixel + +		for(unsigned y = 0; y < dst_height; y++) { +			unsigned short *src_bits = (unsigned short*)FreeImage_GetScanLine(src, y); +			unsigned short *dst_bits = (unsigned short*)FreeImage_GetScanLine(dst, y); +			for(unsigned x = 0; x < dst_width; x++) { +				dst_bits[c] = src_bits[x]; +				dst_bits += bytespp; +			} +		} + +		return TRUE; +	} +	 +	if (((dst_image_type == FIT_RGBF) || (dst_image_type == FIT_RGBAF)) && (src_image_type == FIT_FLOAT)) { + +		// src image should be grayscale, dst image should be 96- or 128-bit +		unsigned src_bpp = FreeImage_GetBPP(src); +		unsigned dst_bpp = FreeImage_GetBPP(dst); +		if ((src_bpp != 32) || (dst_bpp != 96) && (dst_bpp != 128)) +			return FALSE; + + +		// select the channel to modify (always RGB[A]) +		switch(channel) { +			case FICC_BLUE: +				c = 2; +				break; +			case FICC_GREEN: +				c = 1; +				break; +			case FICC_RED:  +				c = 0; +				break; +			case FICC_ALPHA: +				if(dst_bpp != 128) return FALSE; +				c = 3; +				break; +			default: +				return FALSE; +		} + +		// perform insertion + +		int bytespp = dst_bpp / 32;	// floats / pixel + +		for(unsigned y = 0; y < dst_height; y++) { +			float *src_bits = (float*)FreeImage_GetScanLine(src, y); +			float *dst_bits = (float*)FreeImage_GetScanLine(dst, y); +			for(unsigned x = 0; x < dst_width; x++) { +				dst_bits[c] = src_bits[x]; +				dst_bits += bytespp; +			} +		} + +		return TRUE; +	} + +	return FALSE; +} + +/** @brief Retrieves the real part, imaginary part, magnitude or phase of a complex image. +@param src Input image to be processed. +@param channel Channel to extract +@return Returns the extracted channel if successful, returns NULL otherwise. +*/ +FIBITMAP * DLL_CALLCONV  +FreeImage_GetComplexChannel(FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel) { +	unsigned x, y; +	double mag, phase; +	FICOMPLEX *src_bits = NULL; +	double *dst_bits = NULL; +	FIBITMAP *dst = NULL; + +	if (!FreeImage_HasPixels(src)) return NULL; + +	if(FreeImage_GetImageType(src) == FIT_COMPLEX) { +		// allocate a dib of type FIT_DOUBLE +		unsigned width  = FreeImage_GetWidth(src); +		unsigned height = FreeImage_GetHeight(src); +		dst = FreeImage_AllocateT(FIT_DOUBLE, width, height) ; +		if (!dst) return NULL; + +		// perform extraction + +		switch(channel) { +			case FICC_REAL: // real part +				for(y = 0; y < height; y++) { +					src_bits = (FICOMPLEX *)FreeImage_GetScanLine(src, y); +					dst_bits = (double *)FreeImage_GetScanLine(dst, y); +					for(x = 0; x < width; x++) { +						dst_bits[x] = src_bits[x].r; +					} +				} +				break; + +			case FICC_IMAG: // imaginary part +				for(y = 0; y < height; y++) { +					src_bits = (FICOMPLEX *)FreeImage_GetScanLine(src, y); +					dst_bits = (double *)FreeImage_GetScanLine(dst, y); +					for(x = 0; x < width; x++) { +						dst_bits[x] = src_bits[x].i; +					} +				} +				break; + +			case FICC_MAG: // magnitude +				for(y = 0; y < height; y++) { +					src_bits = (FICOMPLEX *)FreeImage_GetScanLine(src, y); +					dst_bits = (double *)FreeImage_GetScanLine(dst, y); +					for(x = 0; x < width; x++) { +						mag = src_bits[x].r * src_bits[x].r + src_bits[x].i * src_bits[x].i; +						dst_bits[x] = sqrt(mag); +					} +				} +				break; + +			case FICC_PHASE: // phase +				for(y = 0; y < height; y++) { +					src_bits = (FICOMPLEX *)FreeImage_GetScanLine(src, y); +					dst_bits = (double *)FreeImage_GetScanLine(dst, y); +					for(x = 0; x < width; x++) { +						if ((src_bits[x].r == 0) && (src_bits[x].i == 0)) { +							phase = 0; +						} else { +							phase = atan2(src_bits[x].i, src_bits[x].r); +						} +						dst_bits[x] = phase; +					} +				} +				break; +		} +	} + +	// copy metadata from src to dst +	FreeImage_CloneMetadata(dst, src); +	 +	return dst; +} + +/** @brief Set the real or imaginary part of a complex image. +Both src and dst must have the same width and height. +@param dst Image to modify (image of type FIT_COMPLEX) +@param src Input image of type FIT_DOUBLE +@param channel Channel to modify +@return Returns TRUE if successful, FALSE otherwise. +*/ +BOOL DLL_CALLCONV  +FreeImage_SetComplexChannel(FIBITMAP *dst, FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel) { +	unsigned x, y; +	double *src_bits = NULL; +	FICOMPLEX *dst_bits = NULL; + +	if (!FreeImage_HasPixels(src) || !FreeImage_HasPixels(dst)) return FALSE; + +	// src image should be of type FIT_DOUBLE, dst image should be of type FIT_COMPLEX +	const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(src); +	const FREE_IMAGE_TYPE dst_type = FreeImage_GetImageType(dst); +	if ((src_type != FIT_DOUBLE) || (dst_type != FIT_COMPLEX)) +		return FALSE; + +	// src and dst images should have the same width and height +	unsigned src_width  = FreeImage_GetWidth(src); +	unsigned src_height = FreeImage_GetHeight(src); +	unsigned dst_width  = FreeImage_GetWidth(dst); +	unsigned dst_height = FreeImage_GetHeight(dst); +	if ((src_width != dst_width) || (src_height != dst_height)) +		return FALSE; + +	// select the channel to modify +	switch(channel) { +		case FICC_REAL: // real part +			for(y = 0; y < dst_height; y++) { +				src_bits = (double *)FreeImage_GetScanLine(src, y); +				dst_bits = (FICOMPLEX *)FreeImage_GetScanLine(dst, y); +				for(x = 0; x < dst_width; x++) { +					dst_bits[x].r = src_bits[x]; +				} +			} +			break; +		case FICC_IMAG: // imaginary part +			for(y = 0; y < dst_height; y++) { +				src_bits = (double *)FreeImage_GetScanLine(src, y); +				dst_bits = (FICOMPLEX *)FreeImage_GetScanLine(dst, y); +				for(x = 0; x < dst_width; x++) { +					dst_bits[x].i = src_bits[x]; +				} +			} +			break; +	} + +	return TRUE; +}  | 
