From 88708cffa15662dcd2755fce699112d24a10a087 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 30 May 2012 17:27:49 +0000 Subject: update for zlib & FreeImage git-svn-id: http://svn.miranda-ng.org/main/trunk@238 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- .../FreeImage/Source/FreeImageToolkit/Channels.cpp | 976 ++++++++++----------- 1 file changed, 488 insertions(+), 488 deletions(-) (limited to 'plugins/FreeImage/Source/FreeImageToolkit/Channels.cpp') diff --git a/plugins/FreeImage/Source/FreeImageToolkit/Channels.cpp b/plugins/FreeImage/Source/FreeImageToolkit/Channels.cpp index 36475f5aba..5f01ad815f 100644 --- a/plugins/FreeImage/Source/FreeImageToolkit/Channels.cpp +++ b/plugins/FreeImage/Source/FreeImageToolkit/Channels.cpp @@ -1,488 +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; -} +// ========================================================== +// 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; +} -- cgit v1.2.3