diff options
Diffstat (limited to 'plugins/FreeImage/Source/FreeImageToolkit/Display.cpp')
| -rw-r--r-- | plugins/FreeImage/Source/FreeImageToolkit/Display.cpp | 460 | 
1 files changed, 230 insertions, 230 deletions
diff --git a/plugins/FreeImage/Source/FreeImageToolkit/Display.cpp b/plugins/FreeImage/Source/FreeImageToolkit/Display.cpp index f7e9aa7689..245c5c3a18 100644 --- a/plugins/FreeImage/Source/FreeImageToolkit/Display.cpp +++ b/plugins/FreeImage/Source/FreeImageToolkit/Display.cpp @@ -1,230 +1,230 @@ -// ==========================================================
 -// Display routines
 -//
 -// 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 Composite a foreground image against a background color or a background image.
 -
 -The equation for computing a composited sample value is:<br>
 -output = alpha * foreground + (1-alpha) * background<br>
 -where alpha and the input and output sample values are expressed as fractions in the range 0 to 1. 
 -For colour images, the computation is done separately for R, G, and B samples.
 -
 -@param fg Foreground image
 -@param useFileBkg If TRUE and a file background is present, use it as the background color
 -@param appBkColor If not equal to NULL, and useFileBkg is FALSE, use this color as the background color
 -@param bg If not equal to NULL and useFileBkg is FALSE and appBkColor is NULL, use this as the background image
 -@return Returns the composite image if successful, returns NULL otherwise
 -@see FreeImage_IsTransparent, FreeImage_HasBackgroundColor
 -*/
 -FIBITMAP * DLL_CALLCONV
 -FreeImage_Composite(FIBITMAP *fg, BOOL useFileBkg, RGBQUAD *appBkColor, FIBITMAP *bg) {
 -	if(!FreeImage_HasPixels(fg)) return NULL;
 -
 -	int width  = FreeImage_GetWidth(fg);
 -	int height = FreeImage_GetHeight(fg);
 -	int bpp    = FreeImage_GetBPP(fg);
 -
 -	if((bpp != 8) && (bpp != 32))
 -		return NULL;
 -
 -	if(bg) {
 -		int bg_width  = FreeImage_GetWidth(bg);
 -		int bg_height = FreeImage_GetHeight(bg);
 -		int bg_bpp    = FreeImage_GetBPP(bg);
 -		if((bg_width != width) || (bg_height != height) || (bg_bpp != 24))
 -			return NULL;
 -	}
 -
 -	int bytespp = (bpp == 8) ? 1 : 4;
 -
 -	
 -	int x, y, c;
 -	BYTE alpha = 0, not_alpha;
 -	BYTE index;
 -	RGBQUAD fgc;	// foreground color
 -	RGBQUAD bkc;	// background color
 -
 -	memset(&fgc, 0, sizeof(RGBQUAD));
 -	memset(&bkc, 0, sizeof(RGBQUAD));
 -
 -	// allocate the composite image
 -	FIBITMAP *composite = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
 -	if(!composite) return NULL;
 -
 -	// get the palette
 -	RGBQUAD *pal = FreeImage_GetPalette(fg);
 -
 -	// retrieve the alpha table from the foreground image
 -	BOOL bIsTransparent = FreeImage_IsTransparent(fg);
 -	BYTE *trns = FreeImage_GetTransparencyTable(fg);
 -
 -	// retrieve the background color from the foreground image
 -	BOOL bHasBkColor = FALSE;
 -
 -	if(useFileBkg && FreeImage_HasBackgroundColor(fg)) {
 -		FreeImage_GetBackgroundColor(fg, &bkc);
 -		bHasBkColor = TRUE;
 -	} else {
 -		// no file background color
 -		// use application background color ?
 -		if(appBkColor) {
 -			memcpy(&bkc, appBkColor, sizeof(RGBQUAD));
 -			bHasBkColor = TRUE;
 -		}
 -		// use background image ?
 -		else if(bg) {
 -			bHasBkColor = FALSE;
 -		}
 -	}
 -
 -	for(y = 0; y < height; y++) {
 -		// foreground
 -		BYTE *fg_bits = FreeImage_GetScanLine(fg, y);
 -		// background
 -		BYTE *bg_bits = FreeImage_GetScanLine(bg, y);
 -		// composite image
 -		BYTE *cp_bits = FreeImage_GetScanLine(composite, y);
 -
 -		for(x = 0; x < width; x++) {
 -
 -			// foreground color + alpha
 -
 -			if(bpp == 8) {
 -				// get the foreground color
 -				index = fg_bits[0];
 -				memcpy(&fgc, &pal[index], sizeof(RGBQUAD));
 -				// get the alpha
 -				if(bIsTransparent) {
 -					alpha = trns[index];
 -				} else {
 -					alpha = 255;
 -				}
 -			}
 -			else if(bpp == 32) {
 -				// get the foreground color
 -				fgc.rgbBlue  = fg_bits[FI_RGBA_BLUE];
 -				fgc.rgbGreen = fg_bits[FI_RGBA_GREEN];
 -				fgc.rgbRed   = fg_bits[FI_RGBA_RED];
 -				// get the alpha
 -				alpha = fg_bits[FI_RGBA_ALPHA];
 -			}
 -
 -			// background color
 -
 -			if(!bHasBkColor) {
 -				if(bg) {
 -					// get the background color from the background image
 -					bkc.rgbBlue  = bg_bits[FI_RGBA_BLUE];
 -					bkc.rgbGreen = bg_bits[FI_RGBA_GREEN];
 -					bkc.rgbRed   = bg_bits[FI_RGBA_RED];
 -				}
 -				else {
 -					// use a checkerboard pattern
 -					c = (((y & 0x8) == 0) ^ ((x & 0x8) == 0)) * 192;
 -					c = c ? c : 255;
 -					bkc.rgbBlue  = (BYTE)c;
 -					bkc.rgbGreen = (BYTE)c;
 -					bkc.rgbRed   = (BYTE)c;
 -				}
 -			}
 -
 -			// composition
 -
 -			if(alpha == 0) {
 -				// output = background
 -				cp_bits[FI_RGBA_BLUE] = bkc.rgbBlue;
 -				cp_bits[FI_RGBA_GREEN] = bkc.rgbGreen;
 -				cp_bits[FI_RGBA_RED] = bkc.rgbRed;
 -			}
 -			else if(alpha == 255) {
 -				// output = foreground
 -				cp_bits[FI_RGBA_BLUE] = fgc.rgbBlue;
 -				cp_bits[FI_RGBA_GREEN] = fgc.rgbGreen;
 -				cp_bits[FI_RGBA_RED] = fgc.rgbRed;
 -			}
 -			else {
 -				// output = alpha * foreground + (1-alpha) * background
 -				not_alpha = (BYTE)~alpha;
 -				cp_bits[FI_RGBA_BLUE] = (BYTE)((alpha * (WORD)fgc.rgbBlue  + not_alpha * (WORD)bkc.rgbBlue) >> 8);
 -				cp_bits[FI_RGBA_GREEN] = (BYTE)((alpha * (WORD)fgc.rgbGreen + not_alpha * (WORD)bkc.rgbGreen) >> 8);
 -				cp_bits[FI_RGBA_RED] = (BYTE)((alpha * (WORD)fgc.rgbRed   + not_alpha * (WORD)bkc.rgbRed) >> 8);
 -			}
 -
 -			fg_bits += bytespp;
 -			bg_bits += 3;
 -			cp_bits += 3;
 -		}
 -	}
 -
 -	// copy metadata from src to dst
 -	FreeImage_CloneMetadata(composite, fg);
 -	
 -	return composite;	
 -}
 -
 -/**
 -Pre-multiplies a 32-bit image's red-, green- and blue channels with it's alpha channel 
 -for to be used with e.g. the Windows GDI function AlphaBlend(). 
 -The transformation changes the red-, green- and blue channels according to the following equation:  
 -channel(x, y) = channel(x, y) * alpha_channel(x, y) / 255  
 -@param dib Input/Output dib to be premultiplied
 -@return Returns TRUE on success, FALSE otherwise (e.g. when the bitdepth of the source dib cannot be handled). 
 -*/
 -BOOL DLL_CALLCONV 
 -FreeImage_PreMultiplyWithAlpha(FIBITMAP *dib) {
 -	if (!FreeImage_HasPixels(dib)) return FALSE;
 -	
 -	if ((FreeImage_GetBPP(dib) != 32) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) {
 -		return FALSE;
 -	}
 -
 -	int width = FreeImage_GetWidth(dib);
 -	int height = FreeImage_GetHeight(dib);
 -
 -	for(int y = 0; y < height; y++) {
 -		BYTE *bits = FreeImage_GetScanLine(dib, y);
 -		for (int x = 0; x < width; x++, bits += 4) {
 -			const BYTE alpha = bits[FI_RGBA_ALPHA];
 -			// slightly faster: care for two special cases
 -			if(alpha == 0x00) {
 -				// special case for alpha == 0x00
 -				// color * 0x00 / 0xFF = 0x00
 -				bits[FI_RGBA_BLUE] = 0x00;
 -				bits[FI_RGBA_GREEN] = 0x00;
 -				bits[FI_RGBA_RED] = 0x00;
 -			} else if(alpha == 0xFF) {
 -				// nothing to do for alpha == 0xFF
 -				// color * 0xFF / 0xFF = color
 -				continue;
 -			} else {
 -				bits[FI_RGBA_BLUE] = (BYTE)( (alpha * (WORD)bits[FI_RGBA_BLUE] + 127) / 255 );
 -				bits[FI_RGBA_GREEN] = (BYTE)( (alpha * (WORD)bits[FI_RGBA_GREEN] + 127) / 255 );
 -				bits[FI_RGBA_RED] = (BYTE)( (alpha * (WORD)bits[FI_RGBA_RED] + 127) / 255 );
 -			}
 -		}
 -	}
 -	return TRUE;
 -}
 -
 +// ========================================================== +// Display routines +// +// 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 Composite a foreground image against a background color or a background image. + +The equation for computing a composited sample value is:<br> +output = alpha * foreground + (1-alpha) * background<br> +where alpha and the input and output sample values are expressed as fractions in the range 0 to 1.  +For colour images, the computation is done separately for R, G, and B samples. + +@param fg Foreground image +@param useFileBkg If TRUE and a file background is present, use it as the background color +@param appBkColor If not equal to NULL, and useFileBkg is FALSE, use this color as the background color +@param bg If not equal to NULL and useFileBkg is FALSE and appBkColor is NULL, use this as the background image +@return Returns the composite image if successful, returns NULL otherwise +@see FreeImage_IsTransparent, FreeImage_HasBackgroundColor +*/ +FIBITMAP * DLL_CALLCONV +FreeImage_Composite(FIBITMAP *fg, BOOL useFileBkg, RGBQUAD *appBkColor, FIBITMAP *bg) { +	if(!FreeImage_HasPixels(fg)) return NULL; + +	int width  = FreeImage_GetWidth(fg); +	int height = FreeImage_GetHeight(fg); +	int bpp    = FreeImage_GetBPP(fg); + +	if((bpp != 8) && (bpp != 32)) +		return NULL; + +	if(bg) { +		int bg_width  = FreeImage_GetWidth(bg); +		int bg_height = FreeImage_GetHeight(bg); +		int bg_bpp    = FreeImage_GetBPP(bg); +		if((bg_width != width) || (bg_height != height) || (bg_bpp != 24)) +			return NULL; +	} + +	int bytespp = (bpp == 8) ? 1 : 4; + +	 +	int x, y, c; +	BYTE alpha = 0, not_alpha; +	BYTE index; +	RGBQUAD fgc;	// foreground color +	RGBQUAD bkc;	// background color + +	memset(&fgc, 0, sizeof(RGBQUAD)); +	memset(&bkc, 0, sizeof(RGBQUAD)); + +	// allocate the composite image +	FIBITMAP *composite = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); +	if(!composite) return NULL; + +	// get the palette +	RGBQUAD *pal = FreeImage_GetPalette(fg); + +	// retrieve the alpha table from the foreground image +	BOOL bIsTransparent = FreeImage_IsTransparent(fg); +	BYTE *trns = FreeImage_GetTransparencyTable(fg); + +	// retrieve the background color from the foreground image +	BOOL bHasBkColor = FALSE; + +	if(useFileBkg && FreeImage_HasBackgroundColor(fg)) { +		FreeImage_GetBackgroundColor(fg, &bkc); +		bHasBkColor = TRUE; +	} else { +		// no file background color +		// use application background color ? +		if(appBkColor) { +			memcpy(&bkc, appBkColor, sizeof(RGBQUAD)); +			bHasBkColor = TRUE; +		} +		// use background image ? +		else if(bg) { +			bHasBkColor = FALSE; +		} +	} + +	for(y = 0; y < height; y++) { +		// foreground +		BYTE *fg_bits = FreeImage_GetScanLine(fg, y); +		// background +		BYTE *bg_bits = FreeImage_GetScanLine(bg, y); +		// composite image +		BYTE *cp_bits = FreeImage_GetScanLine(composite, y); + +		for(x = 0; x < width; x++) { + +			// foreground color + alpha + +			if(bpp == 8) { +				// get the foreground color +				index = fg_bits[0]; +				memcpy(&fgc, &pal[index], sizeof(RGBQUAD)); +				// get the alpha +				if(bIsTransparent) { +					alpha = trns[index]; +				} else { +					alpha = 255; +				} +			} +			else if(bpp == 32) { +				// get the foreground color +				fgc.rgbBlue  = fg_bits[FI_RGBA_BLUE]; +				fgc.rgbGreen = fg_bits[FI_RGBA_GREEN]; +				fgc.rgbRed   = fg_bits[FI_RGBA_RED]; +				// get the alpha +				alpha = fg_bits[FI_RGBA_ALPHA]; +			} + +			// background color + +			if(!bHasBkColor) { +				if(bg) { +					// get the background color from the background image +					bkc.rgbBlue  = bg_bits[FI_RGBA_BLUE]; +					bkc.rgbGreen = bg_bits[FI_RGBA_GREEN]; +					bkc.rgbRed   = bg_bits[FI_RGBA_RED]; +				} +				else { +					// use a checkerboard pattern +					c = (((y & 0x8) == 0) ^ ((x & 0x8) == 0)) * 192; +					c = c ? c : 255; +					bkc.rgbBlue  = (BYTE)c; +					bkc.rgbGreen = (BYTE)c; +					bkc.rgbRed   = (BYTE)c; +				} +			} + +			// composition + +			if(alpha == 0) { +				// output = background +				cp_bits[FI_RGBA_BLUE] = bkc.rgbBlue; +				cp_bits[FI_RGBA_GREEN] = bkc.rgbGreen; +				cp_bits[FI_RGBA_RED] = bkc.rgbRed; +			} +			else if(alpha == 255) { +				// output = foreground +				cp_bits[FI_RGBA_BLUE] = fgc.rgbBlue; +				cp_bits[FI_RGBA_GREEN] = fgc.rgbGreen; +				cp_bits[FI_RGBA_RED] = fgc.rgbRed; +			} +			else { +				// output = alpha * foreground + (1-alpha) * background +				not_alpha = (BYTE)~alpha; +				cp_bits[FI_RGBA_BLUE] = (BYTE)((alpha * (WORD)fgc.rgbBlue  + not_alpha * (WORD)bkc.rgbBlue) >> 8); +				cp_bits[FI_RGBA_GREEN] = (BYTE)((alpha * (WORD)fgc.rgbGreen + not_alpha * (WORD)bkc.rgbGreen) >> 8); +				cp_bits[FI_RGBA_RED] = (BYTE)((alpha * (WORD)fgc.rgbRed   + not_alpha * (WORD)bkc.rgbRed) >> 8); +			} + +			fg_bits += bytespp; +			bg_bits += 3; +			cp_bits += 3; +		} +	} + +	// copy metadata from src to dst +	FreeImage_CloneMetadata(composite, fg); +	 +	return composite;	 +} + +/** +Pre-multiplies a 32-bit image's red-, green- and blue channels with it's alpha channel  +for to be used with e.g. the Windows GDI function AlphaBlend().  +The transformation changes the red-, green- and blue channels according to the following equation:   +channel(x, y) = channel(x, y) * alpha_channel(x, y) / 255   +@param dib Input/Output dib to be premultiplied +@return Returns TRUE on success, FALSE otherwise (e.g. when the bitdepth of the source dib cannot be handled).  +*/ +BOOL DLL_CALLCONV  +FreeImage_PreMultiplyWithAlpha(FIBITMAP *dib) { +	if (!FreeImage_HasPixels(dib)) return FALSE; +	 +	if ((FreeImage_GetBPP(dib) != 32) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) { +		return FALSE; +	} + +	int width = FreeImage_GetWidth(dib); +	int height = FreeImage_GetHeight(dib); + +	for(int y = 0; y < height; y++) { +		BYTE *bits = FreeImage_GetScanLine(dib, y); +		for (int x = 0; x < width; x++, bits += 4) { +			const BYTE alpha = bits[FI_RGBA_ALPHA]; +			// slightly faster: care for two special cases +			if(alpha == 0x00) { +				// special case for alpha == 0x00 +				// color * 0x00 / 0xFF = 0x00 +				bits[FI_RGBA_BLUE] = 0x00; +				bits[FI_RGBA_GREEN] = 0x00; +				bits[FI_RGBA_RED] = 0x00; +			} else if(alpha == 0xFF) { +				// nothing to do for alpha == 0xFF +				// color * 0xFF / 0xFF = color +				continue; +			} else { +				bits[FI_RGBA_BLUE] = (BYTE)( (alpha * (WORD)bits[FI_RGBA_BLUE] + 127) / 255 ); +				bits[FI_RGBA_GREEN] = (BYTE)( (alpha * (WORD)bits[FI_RGBA_GREEN] + 127) / 255 ); +				bits[FI_RGBA_RED] = (BYTE)( (alpha * (WORD)bits[FI_RGBA_RED] + 127) / 255 ); +			} +		} +	} +	return TRUE; +} +  | 
