diff options
| author | George Hazan <ghazan@miranda.im> | 2018-01-26 17:38:31 +0300 | 
|---|---|---|
| committer | George Hazan <ghazan@miranda.im> | 2018-01-26 17:38:31 +0300 | 
| commit | dea9c030340e50324eba97c72a27c151bed12e1c (patch) | |
| tree | 6fc156f40f52a9fc6e6b29e60001959477ee1a5e /plugins/AdvaImg/src/FreeImageToolkit/Resize.cpp | |
| parent | c6e8f8223cab9d799593b7b2cfa22134aa9745d6 (diff) | |
AdvaImg:
- freeimage extracted to the separate library;
- FI_INTERFACE removed, all references to it are replaced with direct calls of FreeImage_* functions;
- unified project for AdvaImg
Diffstat (limited to 'plugins/AdvaImg/src/FreeImageToolkit/Resize.cpp')
| -rw-r--r-- | plugins/AdvaImg/src/FreeImageToolkit/Resize.cpp | 2116 | 
1 files changed, 0 insertions, 2116 deletions
diff --git a/plugins/AdvaImg/src/FreeImageToolkit/Resize.cpp b/plugins/AdvaImg/src/FreeImageToolkit/Resize.cpp deleted file mode 100644 index 7427986703..0000000000 --- a/plugins/AdvaImg/src/FreeImageToolkit/Resize.cpp +++ /dev/null @@ -1,2116 +0,0 @@ -// ========================================================== -// Upsampling / downsampling classes -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Detlev Vendt (detlev.vendt@brillit.de) -// - Carsten Klein (cklein05@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! -// ========================================================== - -#include "Resize.h" - -/** -Returns the color type of a bitmap. In contrast to FreeImage_GetColorType, -this function optionally supports a boolean OUT parameter, that receives TRUE, -if the specified bitmap is greyscale, that is, it consists of grey colors only. -Although it returns the same value as returned by FreeImage_GetColorType for all -image types, this extended function primarily is intended for palletized images, -since the boolean pointed to by 'bIsGreyscale' remains unchanged for RGB(A/F) -images. However, the outgoing boolean is properly maintained for palletized images, -as well as for any non-RGB image type, like FIT_UINTxx and FIT_DOUBLE, for example. -@param dib A pointer to a FreeImage bitmap to calculate the extended color type for -@param bIsGreyscale A pointer to a boolean, that receives TRUE, if the specified bitmap -is greyscale, that is, it consists of grey colors only. This parameter can be NULL. -@return the color type of the specified bitmap -*/ -static FREE_IMAGE_COLOR_TYPE -GetExtendedColorType(FIBITMAP *dib, BOOL *bIsGreyscale) { -	const unsigned bpp = FreeImage_GetBPP(dib); -	const unsigned size = CalculateUsedPaletteEntries(bpp); -	const RGBQUAD * const pal = FreeImage_GetPalette(dib); -	FREE_IMAGE_COLOR_TYPE color_type = FIC_MINISBLACK; -	BOOL bIsGrey = TRUE; - -	switch (bpp) { -		case 1: -		{ -			for (unsigned i = 0; i < size; i++) { -				if ((pal[i].rgbRed != pal[i].rgbGreen) || (pal[i].rgbRed != pal[i].rgbBlue)) { -					color_type = FIC_PALETTE; -					bIsGrey = FALSE; -					break; -				} -			} -			if (bIsGrey) { -				if (pal[0].rgbBlue == 255 && pal[1].rgbBlue == 0) { -					color_type = FIC_MINISWHITE; -				} else if (pal[0].rgbBlue != 0 || pal[1].rgbBlue != 255) { -					color_type = FIC_PALETTE; -				} -			} -			break; -		} - -		case 4: -		case 8: -		{ -			for (unsigned i = 0; i < size; i++) { -				if ((pal[i].rgbRed != pal[i].rgbGreen) || (pal[i].rgbRed != pal[i].rgbBlue)) { -					color_type = FIC_PALETTE; -					bIsGrey = FALSE; -					break; -				} -				if (color_type != FIC_PALETTE && pal[i].rgbBlue != i) { -					if ((size - i - 1) != pal[i].rgbBlue) { -						color_type = FIC_PALETTE; -						if (!bIsGreyscale) { -							// exit loop if we're not setting -							// bIsGreyscale parameter -							break; -						} -					} else { -						color_type = FIC_MINISWHITE; -					} -				} -			} -			break; -		} - -		default: -		{ -			color_type = FreeImage_GetColorType(dib); -			bIsGrey = (color_type == FIC_MINISBLACK) ? TRUE : FALSE; -			break; -		} - -	} -	if (bIsGreyscale) { -		*bIsGreyscale = bIsGrey; -	} - -	return color_type; -} - -/** -Returns a pointer to an RGBA palette, created from the specified bitmap. -The RGBA palette is a copy of the specified bitmap's palette, that, additionally -contains the bitmap's transparency information in the rgbReserved member -of the palette's RGBQUAD elements. -@param dib A pointer to a FreeImage bitmap to create the RGBA palette from. -@param buffer A pointer to the buffer to store the RGBA palette. -@return A pointer to the newly created RGBA palette or NULL, if the specified -bitmap is no palletized standard bitmap. If non-NULL, the returned value is -actually the pointer passed in parameter 'buffer'. -*/ -static inline RGBQUAD * -GetRGBAPalette(FIBITMAP *dib, RGBQUAD * const buffer) { -	// clone the palette -	const unsigned ncolors = FreeImage_GetColorsUsed(dib); -	if (ncolors == 0) { -		return NULL; -	} -	memcpy(buffer, FreeImage_GetPalette(dib), ncolors * sizeof(RGBQUAD)); -	// merge the transparency table -	const unsigned ntransp = MIN(ncolors, FreeImage_GetTransparencyCount(dib)); -	const BYTE * const tt = FreeImage_GetTransparencyTable(dib); -	for (unsigned i = 0; i < ntransp; i++) { -		buffer[i].rgbReserved = tt[i]; -	} -	for (unsigned i = ntransp; i < ncolors; i++) { -		buffer[i].rgbReserved = 255; -	} -	return buffer; -} - -// -------------------------------------------------------------------------- - -CWeightsTable::CWeightsTable(CGenericFilter *pFilter, unsigned uDstSize, unsigned uSrcSize) { -	double dWidth; -	double dFScale; -	const double dFilterWidth = pFilter->GetWidth(); - -	// scale factor -	const double dScale = double(uDstSize) / double(uSrcSize); - -	if(dScale < 1.0) { -		// minification -		dWidth = dFilterWidth / dScale;  -		dFScale = dScale;  -	} else { -		// magnification -		dWidth = dFilterWidth;  -		dFScale = 1.0;  -	} - -	// allocate a new line contributions structure -	// -	// window size is the number of sampled pixels -	m_WindowSize = 2 * (int)ceil(dWidth) + 1;  -	// length of dst line (no. of rows / cols)  -	m_LineLength = uDstSize;  - -	 // allocate list of contributions  -	m_WeightTable = (Contribution*)malloc(m_LineLength * sizeof(Contribution)); -	for(unsigned u = 0; u < m_LineLength; u++) { -		// allocate contributions for every pixel -		m_WeightTable[u].Weights = (double*)malloc(m_WindowSize * sizeof(double)); -	} - -	// offset for discrete to continuous coordinate conversion -	const double dOffset = (0.5 / dScale); - -	for(unsigned u = 0; u < m_LineLength; u++) { -		// scan through line of contributions - -		// inverse mapping (discrete dst 'u' to continous src 'dCenter') -		const double dCenter = (double)u / dScale + dOffset; - -		// find the significant edge points that affect the pixel -		const int iLeft = MAX(0, (int)(dCenter - dWidth + 0.5)); -		const int iRight = MIN((int)(dCenter + dWidth + 0.5), int(uSrcSize)); - -		m_WeightTable[u].Left = iLeft;  -		m_WeightTable[u].Right = iRight; - -		double dTotalWeight = 0;  // sum of weights (initialized to zero) -		for(int iSrc = iLeft; iSrc < iRight; iSrc++) { -			// calculate weights -			const double weight = dFScale * pFilter->Filter(dFScale * ((double)iSrc + 0.5 - dCenter)); -			// assert((iSrc-iLeft) < m_WindowSize); -			m_WeightTable[u].Weights[iSrc-iLeft] = weight; -			dTotalWeight += weight; -		} -		if((dTotalWeight > 0) && (dTotalWeight != 1)) { -			// normalize weight of neighbouring points -			for(int iSrc = iLeft; iSrc < iRight; iSrc++) { -				// normalize point -				m_WeightTable[u].Weights[iSrc-iLeft] /= dTotalWeight;  -			} -		} - -		// simplify the filter, discarding null weights at the right -		{			 -			int iTrailing = iRight - iLeft - 1; -			while(m_WeightTable[u].Weights[iTrailing] == 0) { -				m_WeightTable[u].Right--; -				iTrailing--; -				if(m_WeightTable[u].Right == m_WeightTable[u].Left) { -					break; -				} -			} -			 -		} - -	} // next dst pixel -} - -CWeightsTable::~CWeightsTable() { -	for(unsigned u = 0; u < m_LineLength; u++) { -		// free contributions for every pixel -		free(m_WeightTable[u].Weights); -	} -	// free list of pixels contributions -	free(m_WeightTable); -} - -// -------------------------------------------------------------------------- - -FIBITMAP* CResizeEngine::scale(FIBITMAP *src, unsigned dst_width, unsigned dst_height, unsigned src_left, unsigned src_top, unsigned src_width, unsigned src_height, unsigned flags) { - -	const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); -	const unsigned src_bpp = FreeImage_GetBPP(src); - -	// determine the image's color type -	BOOL bIsGreyscale = FALSE; -	FREE_IMAGE_COLOR_TYPE color_type; -	if (src_bpp <= 8) { -		color_type = GetExtendedColorType(src, &bIsGreyscale); -	} else { -		color_type = FIC_RGB; -	} - -	// determine the required bit depth of the destination image -	unsigned dst_bpp; -	unsigned dst_bpp_s1 = 0; -	if (color_type == FIC_PALETTE && !bIsGreyscale) { -		// non greyscale FIC_PALETTE images require a high-color destination -		// image (24- or 32-bits depending on the image's transparent state) -		dst_bpp = FreeImage_IsTransparent(src) ? 32 : 24; -	} else if (src_bpp <= 8) { -		// greyscale images require an 8-bit destination image -		// (or a 32-bit image if the image is transparent); -		// however, if flag FI_RESCALE_TRUE_COLOR is set, we will return -		// a true color (24 bpp) image -		if (FreeImage_IsTransparent(src)) { -			dst_bpp = 32; -			// additionally, for transparent images we always need a -			// palette including transparency information (an RGBA palette) -			// so, set color_type accordingly -			color_type = FIC_PALETTE; -		} else { -			dst_bpp = ((flags & FI_RESCALE_TRUE_COLOR) == FI_RESCALE_TRUE_COLOR) ? 24 : 8; -			// in any case, we use a fast 8-bit temporary image for the -			// first filter operation (stage 1, either horizontal or -			// vertical) and implicitly convert to 24 bpp (if requested -			// by flag FI_RESCALE_TRUE_COLOR) during the second filter -			// operation -			dst_bpp_s1 = 8; -		} -	} else if (src_bpp == 16 && image_type == FIT_BITMAP) { -		// 16-bit 555 and 565 RGB images require a high-color destination -		// image (fixed to 24 bits, since 16-bit RGBs don't support -		// transparency in FreeImage) -		dst_bpp = 24; -	} else { -		// bit depth remains unchanged for all other images -		dst_bpp = src_bpp; -	} - -	// make 'stage 1' bpp a copy of the destination bpp if it -	// was not explicitly set -	if (dst_bpp_s1 == 0) { -		dst_bpp_s1 = dst_bpp; -	} - -	// early exit if destination size is equal to source size -	if ((src_width == dst_width) && (src_height == dst_height)) { -		FIBITMAP *out = src; -		FIBITMAP *tmp = src; -		if ((src_width != FreeImage_GetWidth(src)) || (src_height != FreeImage_GetHeight(src))) { -			out = FreeImage_Copy(tmp, src_left, src_top, src_left + src_width, src_top + src_height); -			tmp = out; -		} -		if (src_bpp != dst_bpp) { -			switch (dst_bpp) { -				case 8: -					out = FreeImage_ConvertToGreyscale(tmp); -					break; -				case 24: -					out = FreeImage_ConvertTo24Bits(tmp); -					break; -				case 32: -					out = FreeImage_ConvertTo32Bits(tmp); -					break; -				default: -					break; -			} -			if (tmp != src) { -				FreeImage_Unload(tmp); -				tmp = NULL; -			} -		} - -		return (out != src) ? out : FreeImage_Clone(src); -	} - -	RGBQUAD pal_buffer[256]; -	RGBQUAD *src_pal = NULL; - -	// provide the source image's palette to the rescaler for -	// FIC_PALETTE type images (this includes palletized greyscale -	// images with an unordered palette as well as transparent images) -	if (color_type == FIC_PALETTE) { -		if (dst_bpp == 32) { -			// a 32-bit destination image signals transparency, so -			// create an RGBA palette from the source palette -			src_pal = GetRGBAPalette(src, pal_buffer); -		} else { -			src_pal = FreeImage_GetPalette(src); -		} -	} - -	// allocate the dst image -	FIBITMAP *dst = FreeImage_AllocateT(image_type, dst_width, dst_height, dst_bpp, 0, 0, 0); -	if (!dst) { -		return NULL; -	} -	 -	if (dst_bpp == 8) { -		RGBQUAD * const dst_pal = FreeImage_GetPalette(dst); -		if (color_type == FIC_MINISWHITE) { -			// build an inverted greyscale palette -			CREATE_GREYSCALE_PALETTE_REVERSE(dst_pal, 256); -		}  -		/* -		else { -			// build a default greyscale palette -			// Currently, FreeImage_AllocateT already creates a default -			// greyscale palette for 8 bpp images, so we can skip this here. -			CREATE_GREYSCALE_PALETTE(dst_pal, 256); -		} -		*/ -	} - -	// calculate x and y offsets; since FreeImage uses bottom-up bitmaps, the -	// value of src_offset_y is measured from the bottom of the image -	unsigned src_offset_x = src_left; -	unsigned src_offset_y = FreeImage_GetHeight(src) - src_height - src_top; - -	/* -	Decide which filtering order (xy or yx) is faster for this mapping.  -	--- The theory --- -	Try to minimize calculations by counting the number of convolution multiplies -	if(dst_width*src_height <= src_width*dst_height) { -		// xy filtering -	} else { -		// yx filtering -	} -	--- The practice --- -	Try to minimize calculations by counting the number of vertical convolutions (the most time consuming task) -	if(dst_width*dst_height <= src_width*dst_height) { -		// xy filtering -	} else { -		// yx filtering -	} -	*/ - -	if (dst_width <= src_width) { -		// xy filtering -		// ------------- - -		FIBITMAP *tmp = NULL; - -		if (src_width != dst_width) { -			// source and destination widths are different so, we must -			// filter horizontally -			if (src_height != dst_height) { -				// source and destination heights are also different so, we need -				// a temporary image -				tmp = FreeImage_AllocateT(image_type, dst_width, src_height, dst_bpp_s1, 0, 0, 0); -				if (!tmp) { -					FreeImage_Unload(dst); -					return NULL; -				} -			} else { -				// source and destination heights are equal so, we can directly -				// scale into destination image (second filter method will not -				// be invoked) -				tmp = dst; -			} - -			// scale source image horizontally into temporary (or destination) image -			horizontalFilter(src, src_height, src_width, src_offset_x, src_offset_y, src_pal, tmp, dst_width); - -			// set x and y offsets to zero for the second filter method -			// invocation (the temporary image only contains the portion of -			// the image to be rescaled with no offsets) -			src_offset_x = 0; -			src_offset_y = 0; - -			// also ensure, that the second filter method gets no source -			// palette (the temporary image is palletized only, if it is -			// greyscale; in that case, it is an 8-bit image with a linear -			// palette so, the source palette is not needed or will even be -			// mismatching, if the source palette is unordered) -			src_pal = NULL; -		} else { -			// source and destination widths are equal so, just copy the -			// image pointer -			tmp = src; -		} - -		if (src_height != dst_height) { -			// source and destination heights are different so, scale -			// temporary (or source) image vertically into destination image -			verticalFilter(tmp, dst_width, src_height, src_offset_x, src_offset_y, src_pal, dst, dst_height); -		} - -		// free temporary image, if not pointing to either src or dst -		if (tmp != src && tmp != dst) { -			FreeImage_Unload(tmp); -		} - -	} else { -		// yx filtering -		// ------------- - -		// Remark: -		// The yx filtering branch could be more optimized by taking into, -		// account that (src_width != dst_width) is always true, which -		// follows from the above condition, which selects filtering order. -		// Since (dst_width <= src_width) == TRUE selects xy filtering, -		// both widths must be different when performing yx filtering. -		// However, to make the code more robust, not depending on that -		// condition and more symmetric to the xy filtering case, these -		// (src_width != dst_width) conditions are still in place. - -		FIBITMAP *tmp = NULL; - -		if (src_height != dst_height) { -			// source and destination heights are different so, we must -			// filter vertically -			if (src_width != dst_width) { -				// source and destination widths are also different so, we need -				// a temporary image -				tmp = FreeImage_AllocateT(image_type, src_width, dst_height, dst_bpp_s1, 0, 0, 0); -				if (!tmp) { -					FreeImage_Unload(dst); -					return NULL; -				} -			} else { -				// source and destination widths are equal so, we can directly -				// scale into destination image (second filter method will not -				// be invoked) -				tmp = dst; -			} - -			// scale source image vertically into temporary (or destination) image -			verticalFilter(src, src_width, src_height, src_offset_x, src_offset_y, src_pal, tmp, dst_height); - -			// set x and y offsets to zero for the second filter method -			// invocation (the temporary image only contains the portion of -			// the image to be rescaled with no offsets) -			src_offset_x = 0; -			src_offset_y = 0; - -			// also ensure, that the second filter method gets no source -			// palette (the temporary image is palletized only, if it is -			// greyscale; in that case, it is an 8-bit image with a linear -			// palette so, the source palette is not needed or will even be -			// mismatching, if the source palette is unordered) -			src_pal = NULL; - -		} else { -			// source and destination heights are equal so, just copy the -			// image pointer -			tmp = src; -		} - -		if (src_width != dst_width) { -			// source and destination heights are different so, scale -			// temporary (or source) image horizontally into destination image -			horizontalFilter(tmp, dst_height, src_width, src_offset_x, src_offset_y, src_pal, dst, dst_width); -		} - -		// free temporary image, if not pointing to either src or dst -		if (tmp != src && tmp != dst) { -			FreeImage_Unload(tmp); -		} -	} - -	return dst; -}  - -void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsigned src_width, unsigned src_offset_x, unsigned src_offset_y, const RGBQUAD *const src_pal, FIBITMAP *const dst, unsigned dst_width) { - -	// allocate and calculate the contributions -	CWeightsTable weightsTable(m_pFilter, dst_width, src_width); - -	// step through rows -	switch(FreeImage_GetImageType(src)) { -		case FIT_BITMAP: -		{ -			switch(FreeImage_GetBPP(src)) { -				case 1: -				{ -					switch(FreeImage_GetBPP(dst)) { -						case 8: -						{ -							// transparently convert the 1-bit non-transparent greyscale image to 8 bpp -							src_offset_x >>= 3; -							if (src_pal) { -								// we have got a palette -								for (unsigned y = 0; y < height; y++) { -									// scale each row -									const BYTE * const src_bits = FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x; -									BYTE * const dst_bits = FreeImage_GetScanLine(dst, y); - -									for (unsigned x = 0; x < dst_width; x++) { -										// loop through row -										const unsigned iLeft = weightsTable.getLeftBoundary(x);		// retrieve left boundary -										const unsigned iRight = weightsTable.getRightBoundary(x);	// retrieve right boundary -										double value = 0; - -										for (unsigned i = iLeft; i < iRight; i++) { -											// scan between boundaries -											// accumulate weighted effect of each neighboring pixel -											const unsigned pixel = (src_bits[i >> 3] & (0x80 >> (i & 0x07))) != 0; -											value += (weightsTable.getWeight(x, i - iLeft) * (double)*(BYTE *)&src_pal[pixel]); -										} - -										// clamp and place result in destination pixel -										dst_bits[x] = (BYTE)CLAMP<int>((int)(value + 0.5), 0, 0xFF); -									} -								} -							} else { -								// we do not have a palette -								for (unsigned y = 0; y < height; y++) { -									// scale each row -									const BYTE * const src_bits = FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x; -									BYTE * const dst_bits = FreeImage_GetScanLine(dst, y); - -									for (unsigned x = 0; x < dst_width; x++) { -										// loop through row -										const unsigned iLeft = weightsTable.getLeftBoundary(x);		// retrieve left boundary -										const unsigned iRight = weightsTable.getRightBoundary(x);	// retrieve right boundary -										double value = 0; - -										for (unsigned i = iLeft; i < iRight; i++) { -											// scan between boundaries -											// accumulate weighted effect of each neighboring pixel -											const unsigned pixel = (src_bits[i >> 3] & (0x80 >> (i & 0x07))) != 0; -											value += (weightsTable.getWeight(x, i - iLeft) * (double)pixel); -										} -										value *= 0xFF; - -										// clamp and place result in destination pixel -										dst_bits[x] = (BYTE)CLAMP<int>((int)(value + 0.5), 0, 0xFF); -									} -								} -							} -						} -						break; - -						case 24: -						{ -							// transparently convert the non-transparent 1-bit image to 24 bpp -							src_offset_x >>= 3; -							if (src_pal) { -								// we have got a palette -								for (unsigned y = 0; y < height; y++) { -									// scale each row -									const BYTE * const src_bits = FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x; -									BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - -									for (unsigned x = 0; x < dst_width; x++) { -										// loop through row -										const unsigned iLeft = weightsTable.getLeftBoundary(x);    // retrieve left boundary -										const unsigned iRight = weightsTable.getRightBoundary(x);  // retrieve right boundary -										double r = 0, g = 0, b = 0; - -										for (unsigned i = iLeft; i < iRight; i++) { -											// scan between boundaries -											// accumulate weighted effect of each neighboring pixel -											const double weight = weightsTable.getWeight(x, i - iLeft); -											const unsigned pixel = (src_bits[i >> 3] & (0x80 >> (i & 0x07))) != 0; -											const BYTE * const entry = (BYTE *)&src_pal[pixel]; -											r += (weight * (double)entry[FI_RGBA_RED]); -											g += (weight * (double)entry[FI_RGBA_GREEN]); -											b += (weight * (double)entry[FI_RGBA_BLUE]); -										} - -										// clamp and place result in destination pixel -										dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(r + 0.5), 0, 0xFF); -										dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(g + 0.5), 0, 0xFF); -										dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(b + 0.5), 0, 0xFF); -										dst_bits += 3; -									} -								} -							} else { -								// we do not have a palette -								for (unsigned y = 0; y < height; y++) { -									// scale each row -									const BYTE * const src_bits = FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x; -									BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - -									for (unsigned x = 0; x < dst_width; x++) { -										// loop through row -										const unsigned iLeft = weightsTable.getLeftBoundary(x);    // retrieve left boundary -										const unsigned iRight = weightsTable.getRightBoundary(x);  // retrieve right boundary -										double value = 0; - -										for (unsigned i = iLeft; i < iRight; i++) { -											// scan between boundaries -											// accumulate weighted effect of each neighboring pixel -											const unsigned pixel = (src_bits[i >> 3] & (0x80 >> (i & 0x07))) != 0; -											value += (weightsTable.getWeight(x, i - iLeft) * (double)pixel); -										} -										value *= 0xFF; - -										// clamp and place result in destination pixel -										const BYTE bval = (BYTE)CLAMP<int>((int)(value + 0.5), 0, 0xFF); -										dst_bits[FI_RGBA_RED]	= bval; -										dst_bits[FI_RGBA_GREEN]	= bval; -										dst_bits[FI_RGBA_BLUE]	= bval; -										dst_bits += 3; -									} -								} -							} -						} -						break; - -						case 32: -						{ -							// transparently convert the transparent 1-bit image to 32 bpp;  -							// we always have got a palette here -							src_offset_x >>= 3; - -							for (unsigned y = 0; y < height; y++) { -								// scale each row -								const BYTE * const src_bits = FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x; -								BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - -								for (unsigned x = 0; x < dst_width; x++) { -									// loop through row -									const unsigned iLeft = weightsTable.getLeftBoundary(x);    // retrieve left boundary -									const unsigned iRight = weightsTable.getRightBoundary(x);  // retrieve right boundary -									double r = 0, g = 0, b = 0, a = 0; - -									for (unsigned i = iLeft; i < iRight; i++) { -										// scan between boundaries -										// accumulate weighted effect of each neighboring pixel -										const double weight = weightsTable.getWeight(x, i - iLeft); -										const unsigned pixel = (src_bits[i >> 3] & (0x80 >> (i & 0x07))) != 0; -										const BYTE * const entry = (BYTE *)&src_pal[pixel]; -										r += (weight * (double)entry[FI_RGBA_RED]); -										g += (weight * (double)entry[FI_RGBA_GREEN]); -										b += (weight * (double)entry[FI_RGBA_BLUE]); -										a += (weight * (double)entry[FI_RGBA_ALPHA]); -									} - -									// clamp and place result in destination pixel -									dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(r + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(g + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(b + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_ALPHA]	= (BYTE)CLAMP<int>((int)(a + 0.5), 0, 0xFF); -									dst_bits += 4; -								} -							} -						} -						break; -					} -				} -				break; - -				case 4: -				{ -					switch(FreeImage_GetBPP(dst)) { -						case 8: -						{ -							// transparently convert the non-transparent 4-bit greyscale image to 8 bpp;  -							// we always have got a palette for 4-bit images -							src_offset_x >>= 1; - -							for (unsigned y = 0; y < height; y++) { -								// scale each row -								const BYTE * const src_bits = FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x; -								BYTE * const dst_bits = FreeImage_GetScanLine(dst, y); - -								for (unsigned x = 0; x < dst_width; x++) { -									// loop through row -									const unsigned iLeft = weightsTable.getLeftBoundary(x);    // retrieve left boundary -									const unsigned iRight = weightsTable.getRightBoundary(x);  // retrieve right boundary -									double value = 0; - -									for (unsigned i = iLeft; i < iRight; i++) { -										// scan between boundaries -										// accumulate weighted effect of each neighboring pixel -										const unsigned pixel = i & 0x01 ? src_bits[i >> 1] & 0x0F : src_bits[i >> 1] >> 4; -										value += (weightsTable.getWeight(x, i - iLeft) * (double)*(BYTE *)&src_pal[pixel]); -									} - -									// clamp and place result in destination pixel -									dst_bits[x] = (BYTE)CLAMP<int>((int)(value + 0.5), 0, 0xFF); -								} -							} -						} -						break; - -						case 24: -						{ -							// transparently convert the non-transparent 4-bit image to 24 bpp;  -							// we always have got a palette for 4-bit images -							src_offset_x >>= 1; - -							for (unsigned y = 0; y < height; y++) { -								// scale each row -								const BYTE * const src_bits = FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x; -								BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - -								for (unsigned x = 0; x < dst_width; x++) { -									// loop through row -									const unsigned iLeft = weightsTable.getLeftBoundary(x);    // retrieve left boundary -									const unsigned iRight = weightsTable.getRightBoundary(x);  // retrieve right boundary -									double r = 0, g = 0, b = 0; - -									for (unsigned i = iLeft; i < iRight; i++) { -										// scan between boundaries -										// accumulate weighted effect of each neighboring pixel -										const double weight = weightsTable.getWeight(x, i - iLeft); -										const unsigned pixel = i & 0x01 ? src_bits[i >> 1] & 0x0F : src_bits[i >> 1] >> 4; -										const BYTE * const entry = (BYTE *)&src_pal[pixel]; -										r += (weight * (double)entry[FI_RGBA_RED]); -										g += (weight * (double)entry[FI_RGBA_GREEN]); -										b += (weight * (double)entry[FI_RGBA_BLUE]); -									} - -									// clamp and place result in destination pixel -									dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(r + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(g + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(b + 0.5), 0, 0xFF); -									dst_bits += 3; -								} -							} -						} -						break; - -						case 32: -						{ -							// transparently convert the transparent 4-bit image to 32 bpp;  -							// we always have got a palette for 4-bit images -							src_offset_x >>= 1; - -							for (unsigned y = 0; y < height; y++) { -								// scale each row -								const BYTE * const src_bits = FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x; -								BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - -								for (unsigned x = 0; x < dst_width; x++) { -									// loop through row -									const unsigned iLeft = weightsTable.getLeftBoundary(x);    // retrieve left boundary -									const unsigned iRight = weightsTable.getRightBoundary(x);  // retrieve right boundary -									double r = 0, g = 0, b = 0, a = 0; - -									for (unsigned i = iLeft; i < iRight; i++) { -										// scan between boundaries -										// accumulate weighted effect of each neighboring pixel -										const double weight = weightsTable.getWeight(x, i - iLeft); -										const unsigned pixel = i & 0x01 ? src_bits[i >> 1] & 0x0F : src_bits[i >> 1] >> 4; -										const BYTE * const entry = (BYTE *)&src_pal[pixel]; -										r += (weight * (double)entry[FI_RGBA_RED]); -										g += (weight * (double)entry[FI_RGBA_GREEN]); -										b += (weight * (double)entry[FI_RGBA_BLUE]); -										a += (weight * (double)entry[FI_RGBA_ALPHA]); -									} - -									// clamp and place result in destination pixel -									dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(r + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(g + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(b + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_ALPHA]	= (BYTE)CLAMP<int>((int)(a + 0.5), 0, 0xFF); -									dst_bits += 4; -								} -							} -						} -						break; -					} -				} -				break; - -				case 8: -				{ -					switch(FreeImage_GetBPP(dst)) { -						case 8: -						{ -							// scale the 8-bit non-transparent greyscale image -							// into an 8 bpp destination image -							if (src_pal) { -								// we have got a palette -								for (unsigned y = 0; y < height; y++) { -									// scale each row -									const BYTE * const src_bits = FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x; -									BYTE * const dst_bits = FreeImage_GetScanLine(dst, y); - -									for (unsigned x = 0; x < dst_width; x++) { -										// loop through row -										const unsigned iLeft = weightsTable.getLeftBoundary(x);				// retrieve left boundary -										const unsigned iLimit = weightsTable.getRightBoundary(x) - iLeft;	// retrieve right boundary -										const BYTE * const pixel = src_bits + iLeft; -										double value = 0; - -										// for(i = iLeft to iRight) -										for (unsigned i = 0; i < iLimit; i++) { -											// scan between boundaries -											// accumulate weighted effect of each neighboring pixel -											value += (weightsTable.getWeight(x, i) * (double)*(BYTE *)&src_pal[pixel[i]]); -										} - -										// clamp and place result in destination pixel -										dst_bits[x] = (BYTE)CLAMP<int>((int)(value + 0.5), 0, 0xFF); -									} -								} -							} else { -								// we do not have a palette -								for (unsigned y = 0; y < height; y++) { -									// scale each row -									const BYTE * const src_bits = FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x; -									BYTE * const dst_bits = FreeImage_GetScanLine(dst, y); - -									for (unsigned x = 0; x < dst_width; x++) { -										// loop through row -										const unsigned iLeft = weightsTable.getLeftBoundary(x);				// retrieve left boundary -										const unsigned iLimit = weightsTable.getRightBoundary(x) - iLeft;	// retrieve right boundary -										const BYTE * const pixel = src_bits + iLeft; -										double value = 0; - -										// for(i = iLeft to iRight) -										for (unsigned i = 0; i < iLimit; i++) { -											// scan between boundaries -											// accumulate weighted effect of each neighboring pixel -											value += (weightsTable.getWeight(x, i) * (double)pixel[i]); -										} - -										// clamp and place result in destination pixel -										dst_bits[x] = (BYTE)CLAMP<int>((int)(value + 0.5), 0, 0xFF); -									} -								} -							} -						} -						break; - -						case 24: -						{ -							// transparently convert the non-transparent 8-bit image to 24 bpp -							if (src_pal) { -								// we have got a palette -								for (unsigned y = 0; y < height; y++) { -									// scale each row -									const BYTE * const src_bits = FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x; -									BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - -									for (unsigned x = 0; x < dst_width; x++) { -										// loop through row -										const unsigned iLeft = weightsTable.getLeftBoundary(x);				// retrieve left boundary -										const unsigned iLimit = weightsTable.getRightBoundary(x) - iLeft;	// retrieve right boundary -										const BYTE * const pixel = src_bits + iLeft; -										double r = 0, g = 0, b = 0; - -										// for(i = iLeft to iRight) -										for (unsigned i = 0; i < iLimit; i++) { -											// scan between boundaries -											// accumulate weighted effect of each neighboring pixel -											const double weight = weightsTable.getWeight(x, i); -											const BYTE *const entry = (BYTE *)&src_pal[pixel[i]]; -											r += (weight * (double)entry[FI_RGBA_RED]); -											g += (weight * (double)entry[FI_RGBA_GREEN]); -											b += (weight * (double)entry[FI_RGBA_BLUE]); -										} - -										// clamp and place result in destination pixel -										dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(r + 0.5), 0, 0xFF); -										dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(g + 0.5), 0, 0xFF); -										dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(b + 0.5), 0, 0xFF); -										dst_bits += 3; -									} -								} -							} else { -								// we do not have a palette -								for (unsigned y = 0; y < height; y++) { -									// scale each row -									const BYTE * const src_bits = FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x; -									BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - -									for (unsigned x = 0; x < dst_width; x++) { -										// loop through row -										const unsigned iLeft = weightsTable.getLeftBoundary(x);				// retrieve left boundary -										const unsigned iLimit = weightsTable.getRightBoundary(x) - iLeft;	// retrieve right boundary -										const BYTE * const pixel = src_bits + iLeft; -										double value = 0; - -										// for(i = iLeft to iRight) -										for (unsigned i = 0; i < iLimit; i++) { -											// scan between boundaries -											// accumulate weighted effect of each neighboring pixel -											const double weight = weightsTable.getWeight(x, i); -											value += (weight * (double)pixel[i]); -										} - -										// clamp and place result in destination pixel -										const BYTE bval = (BYTE)CLAMP<int>((int)(value + 0.5), 0, 0xFF); -										dst_bits[FI_RGBA_RED]	= bval; -										dst_bits[FI_RGBA_GREEN]	= bval; -										dst_bits[FI_RGBA_BLUE]	= bval; -										dst_bits += 3; -									} -								} -							} -						} -						break; - -						case 32: -						{ -							// transparently convert the transparent 8-bit image to 32 bpp;  -							// we always have got a palette here -							for (unsigned y = 0; y < height; y++) { -								// scale each row -								const BYTE * const src_bits = FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x; -								BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - -								for (unsigned x = 0; x < dst_width; x++) { -									// loop through row -									const unsigned iLeft = weightsTable.getLeftBoundary(x);				// retrieve left boundary -									const unsigned iLimit = weightsTable.getRightBoundary(x) - iLeft;	// retrieve right boundary -									const BYTE * const pixel = src_bits + iLeft; -									double r = 0, g = 0, b = 0, a = 0; - -									// for(i = iLeft to iRight) -									for (unsigned i = 0; i < iLimit; i++) { -										// scan between boundaries -										// accumulate weighted effect of each neighboring pixel -										const double weight = weightsTable.getWeight(x, i); -										const BYTE * const entry = (BYTE *)&src_pal[pixel[i]]; -										r += (weight * (double)entry[FI_RGBA_RED]); -										g += (weight * (double)entry[FI_RGBA_GREEN]); -										b += (weight * (double)entry[FI_RGBA_BLUE]); -										a += (weight * (double)entry[FI_RGBA_ALPHA]); -									} - -									// clamp and place result in destination pixel -									dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(r + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(g + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(b + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_ALPHA]	= (BYTE)CLAMP<int>((int)(a + 0.5), 0, 0xFF); -									dst_bits += 4; -								} -							} -						} -						break; -					} -				} -				break; - -				case 16: -				{ -					// transparently convert the 16-bit non-transparent image to 24 bpp -					if (IS_FORMAT_RGB565(src)) { -						// image has 565 format -						for (unsigned y = 0; y < height; y++) { -							// scale each row -							const WORD * const src_bits = (WORD *)FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x / sizeof(WORD); -							BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - -							for (unsigned x = 0; x < dst_width; x++) { -								// loop through row -								const unsigned iLeft = weightsTable.getLeftBoundary(x);				// retrieve left boundary -								const unsigned iLimit = weightsTable.getRightBoundary(x) - iLeft;	// retrieve right boundary -								const WORD *pixel = src_bits + iLeft; -								double r = 0, g = 0, b = 0; - -								// for(i = iLeft to iRight) -								for (unsigned i = 0; i < iLimit; i++) { -									// scan between boundaries -									// accumulate weighted effect of each neighboring pixel -									const double weight = weightsTable.getWeight(x, i); -									r += (weight * (double)((*pixel & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT)); -									g += (weight * (double)((*pixel & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT)); -									b += (weight * (double)((*pixel & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT)); -									pixel++; -								} - -								// clamp and place result in destination pixel -								dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(((r * 0xFF) / 0x1F) + 0.5), 0, 0xFF); -								dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(((g * 0xFF) / 0x3F) + 0.5), 0, 0xFF); -								dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(((b * 0xFF) / 0x1F) + 0.5), 0, 0xFF); -								dst_bits += 3; -							} -						} -					} else { -						// image has 555 format -						for (unsigned y = 0; y < height; y++) { -							// scale each row -							const WORD * const src_bits = (WORD *)FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x; -							BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - -							for (unsigned x = 0; x < dst_width; x++) { -								// loop through row -								const unsigned iLeft = weightsTable.getLeftBoundary(x);				// retrieve left boundary -								const unsigned iLimit = weightsTable.getRightBoundary(x) - iLeft;	// retrieve right boundary -								const WORD *pixel = src_bits + iLeft; -								double r = 0, g = 0, b = 0; - -								// for(i = iLeft to iRight) -								for (unsigned i = 0; i < iLimit; i++) { -									// scan between boundaries -									// accumulate weighted effect of each neighboring pixel -									const double weight = weightsTable.getWeight(x, i); -									r += (weight * (double)((*pixel & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT)); -									g += (weight * (double)((*pixel & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT)); -									b += (weight * (double)((*pixel & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT)); -									pixel++; -								} - -								// clamp and place result in destination pixel -								dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(((r * 0xFF) / 0x1F) + 0.5), 0, 0xFF); -								dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(((g * 0xFF) / 0x1F) + 0.5), 0, 0xFF); -								dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(((b * 0xFF) / 0x1F) + 0.5), 0, 0xFF); -								dst_bits += 3; -							} -						} -					} -				} -				break; - -				case 24: -				{ -					// scale the 24-bit non-transparent image into a 24 bpp destination image -					for (unsigned y = 0; y < height; y++) { -						// scale each row -						const BYTE * const src_bits = FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x * 3; -						BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - -						for (unsigned x = 0; x < dst_width; x++) { -							// loop through row -							const unsigned iLeft = weightsTable.getLeftBoundary(x);				// retrieve left boundary -							const unsigned iLimit = weightsTable.getRightBoundary(x) - iLeft;	// retrieve right boundary -							const BYTE * pixel = src_bits + iLeft * 3; -							double r = 0, g = 0, b = 0; - -							// for(i = iLeft to iRight) -							for (unsigned i = 0; i < iLimit; i++) { -								// scan between boundaries -								// accumulate weighted effect of each neighboring pixel -								const double weight = weightsTable.getWeight(x, i); -								r += (weight * (double)pixel[FI_RGBA_RED]); -								g += (weight * (double)pixel[FI_RGBA_GREEN]); -								b += (weight * (double)pixel[FI_RGBA_BLUE]); -								pixel += 3; -							} - -							// clamp and place result in destination pixel -							dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(r + 0.5), 0, 0xFF); -							dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(g + 0.5), 0, 0xFF); -							dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(b + 0.5), 0, 0xFF); -							dst_bits += 3; -						} -					} -				} -				break; - -				case 32: -				{ -					// scale the 32-bit transparent image into a 32 bpp destination image -					for (unsigned y = 0; y < height; y++) { -						// scale each row -						const BYTE * const src_bits = FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x * 4; -						BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - -						for (unsigned x = 0; x < dst_width; x++) { -							// loop through row -							const unsigned iLeft = weightsTable.getLeftBoundary(x);				// retrieve left boundary -							const unsigned iLimit = weightsTable.getRightBoundary(x) - iLeft;	// retrieve right boundary -							const BYTE *pixel = src_bits + iLeft * 4; -							double r = 0, g = 0, b = 0, a = 0; - -							// for(i = iLeft to iRight) -							for (unsigned i = 0; i < iLimit; i++) { -								// scan between boundaries -								// accumulate weighted effect of each neighboring pixel -								const double weight = weightsTable.getWeight(x, i); -								r += (weight * (double)pixel[FI_RGBA_RED]); -								g += (weight * (double)pixel[FI_RGBA_GREEN]); -								b += (weight * (double)pixel[FI_RGBA_BLUE]); -								a += (weight * (double)pixel[FI_RGBA_ALPHA]); -								pixel += 4; -							} - -							// clamp and place result in destination pixel -							dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(r + 0.5), 0, 0xFF); -							dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(g + 0.5), 0, 0xFF); -							dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(b + 0.5), 0, 0xFF); -							dst_bits[FI_RGBA_ALPHA]	= (BYTE)CLAMP<int>((int)(a + 0.5), 0, 0xFF); -							dst_bits += 4; -						} -					} -				} -				break; -			} -		} -		break; - -		case FIT_UINT16: -		{ -			// Calculate the number of words per pixel (1 for 16-bit, 3 for 48-bit or 4 for 64-bit) -			const unsigned wordspp = (FreeImage_GetLine(src) / src_width) / sizeof(WORD); - -			for (unsigned y = 0; y < height; y++) { -				// scale each row -				const WORD *src_bits = (WORD*)FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x / sizeof(WORD); -				WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y); - -				for (unsigned x = 0; x < dst_width; x++) { -					// loop through row -					const unsigned iLeft = weightsTable.getLeftBoundary(x);				// retrieve left boundary -					const unsigned iLimit = weightsTable.getRightBoundary(x) - iLeft;	// retrieve right boundary -					const WORD *pixel = src_bits + iLeft * wordspp; -					double value = 0; - -					// for(i = iLeft to iRight) -					for (unsigned i = 0; i < iLimit; i++) { -						// scan between boundaries -						// accumulate weighted effect of each neighboring pixel -						const double weight = weightsTable.getWeight(x, i);						 -						value += (weight * (double)pixel[0]); -						pixel++; -					} - -					// clamp and place result in destination pixel -					dst_bits[0] = (WORD)CLAMP<int>((int)(value + 0.5), 0, 0xFFFF); -					dst_bits += wordspp; -				} -			} -		} -		break; - -		case FIT_RGB16: -		{ -			// Calculate the number of words per pixel (1 for 16-bit, 3 for 48-bit or 4 for 64-bit) -			const unsigned wordspp = (FreeImage_GetLine(src) / src_width) / sizeof(WORD); - -			for (unsigned y = 0; y < height; y++) { -				// scale each row -				const WORD *src_bits = (WORD*)FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x / sizeof(WORD); -				WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y); - -				for (unsigned x = 0; x < dst_width; x++) { -					// loop through row -					const unsigned iLeft = weightsTable.getLeftBoundary(x);				// retrieve left boundary -					const unsigned iLimit = weightsTable.getRightBoundary(x) - iLeft;	// retrieve right boundary -					const WORD *pixel = src_bits + iLeft * wordspp; -					double r = 0, g = 0, b = 0; - -					// for(i = iLeft to iRight) -					for (unsigned i = 0; i < iLimit; i++) { -						// scan between boundaries -						// accumulate weighted effect of each neighboring pixel -						const double weight = weightsTable.getWeight(x, i);						 -						r += (weight * (double)pixel[0]); -						g += (weight * (double)pixel[1]); -						b += (weight * (double)pixel[2]); -						pixel += wordspp; -					} - -					// clamp and place result in destination pixel -					dst_bits[0] = (WORD)CLAMP<int>((int)(r + 0.5), 0, 0xFFFF); -					dst_bits[1] = (WORD)CLAMP<int>((int)(g + 0.5), 0, 0xFFFF); -					dst_bits[2] = (WORD)CLAMP<int>((int)(b + 0.5), 0, 0xFFFF); -					dst_bits += wordspp; -				} -			} -		} -		break; - -		case FIT_RGBA16: -		{ -			// Calculate the number of words per pixel (1 for 16-bit, 3 for 48-bit or 4 for 64-bit) -			const unsigned wordspp = (FreeImage_GetLine(src) / src_width) / sizeof(WORD); - -			for (unsigned y = 0; y < height; y++) { -				// scale each row -				const WORD *src_bits = (WORD*)FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x / sizeof(WORD); -				WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y); - -				for (unsigned x = 0; x < dst_width; x++) { -					// loop through row -					const unsigned iLeft = weightsTable.getLeftBoundary(x);				// retrieve left boundary -					const unsigned iLimit = weightsTable.getRightBoundary(x) - iLeft;	// retrieve right boundary -					const WORD *pixel = src_bits + iLeft * wordspp; -					double r = 0, g = 0, b = 0, a = 0; - -					// for(i = iLeft to iRight) -					for (unsigned i = 0; i < iLimit; i++) { -						// scan between boundaries -						// accumulate weighted effect of each neighboring pixel -						const double weight = weightsTable.getWeight(x, i);						 -						r += (weight * (double)pixel[0]); -						g += (weight * (double)pixel[1]); -						b += (weight * (double)pixel[2]); -						a += (weight * (double)pixel[3]); -						pixel += wordspp; -					} - -					// clamp and place result in destination pixel -					dst_bits[0] = (WORD)CLAMP<int>((int)(r + 0.5), 0, 0xFFFF); -					dst_bits[1] = (WORD)CLAMP<int>((int)(g + 0.5), 0, 0xFFFF); -					dst_bits[2] = (WORD)CLAMP<int>((int)(b + 0.5), 0, 0xFFFF); -					dst_bits[3] = (WORD)CLAMP<int>((int)(a + 0.5), 0, 0xFFFF); -					dst_bits += wordspp; -				} -			} -		} -		break; - -		case FIT_FLOAT: -		case FIT_RGBF: -		case FIT_RGBAF: -		{ -			// Calculate the number of floats per pixel (1 for 32-bit, 3 for 96-bit or 4 for 128-bit) -			const unsigned floatspp = (FreeImage_GetLine(src) / src_width) / sizeof(float); - -			for(unsigned y = 0; y < height; y++) { -				// scale each row -				const float *src_bits = (float*)FreeImage_GetScanLine(src, y + src_offset_y) + src_offset_x / sizeof(float); -				float *dst_bits = (float*)FreeImage_GetScanLine(dst, y); - -				for(unsigned x = 0; x < dst_width; x++) { -					// loop through row -					const unsigned iLeft = weightsTable.getLeftBoundary(x);    // retrieve left boundary -					const unsigned iRight = weightsTable.getRightBoundary(x);  // retrieve right boundary -					double value[4] = {0, 0, 0, 0};                            // 4 = 128 bpp max - -					for(unsigned i = iLeft; i < iRight; i++) { -						// scan between boundaries -						// accumulate weighted effect of each neighboring pixel -						const double weight = weightsTable.getWeight(x, i-iLeft); - -						unsigned index = i * floatspp;	// pixel index -						for (unsigned j = 0; j < floatspp; j++) { -							value[j] += (weight * (double)src_bits[index++]); -						} -					} - -					// place result in destination pixel -					for (unsigned j = 0; j < floatspp; j++) { -						dst_bits[j] = (float)value[j]; -					} - -					dst_bits += floatspp; -				} -			} -		} -		break; -	} -} - -/// Performs vertical image filtering -void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned src_height, unsigned src_offset_x, unsigned src_offset_y, const RGBQUAD *const src_pal, FIBITMAP *const dst, unsigned dst_height) { - -	// allocate and calculate the contributions -	CWeightsTable weightsTable(m_pFilter, dst_height, src_height); - -	// step through columns -	switch(FreeImage_GetImageType(src)) { -		case FIT_BITMAP: -		{ -			const unsigned dst_pitch = FreeImage_GetPitch(dst); -			BYTE * const dst_base = FreeImage_GetBits(dst); - -			switch(FreeImage_GetBPP(src)) { -				case 1: -				{ -					const unsigned src_pitch = FreeImage_GetPitch(src); -					const BYTE * const src_base = FreeImage_GetBits(src) + src_offset_y * src_pitch + (src_offset_x >> 3); - -					switch(FreeImage_GetBPP(dst)) { -						case 8: -						{ -							// transparently convert the 1-bit non-transparent greyscale image to 8 bpp -							if (src_pal) { -								// we have got a palette -								for (unsigned x = 0; x < width; x++) { -									// work on column x in dst -									BYTE *dst_bits = dst_base + x; -									const unsigned index = x >> 3; -									const unsigned mask = 0x80 >> (x & 0x07); - -									// scale each column -									for (unsigned y = 0; y < dst_height; y++) { -										// loop through column -										const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -										const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -										const BYTE *src_bits = src_base + iLeft * src_pitch + index; -										double value = 0; - -										for (unsigned i = 0; i < iLimit; i++) { -											// scan between boundaries -											// accumulate weighted effect of each neighboring pixel -											const unsigned pixel = (*src_bits & mask) != 0; -											value += (weightsTable.getWeight(y, i) * (double)*(BYTE *)&src_pal[pixel]); -											src_bits += src_pitch; -										} -										value *= 0xFF; - -										// clamp and place result in destination pixel -										*dst_bits = (BYTE)CLAMP<int>((int)(value + 0.5), 0, 0xFF); -										dst_bits += dst_pitch; -									} -								} -							} else { -								// we do not have a palette -								for (unsigned x = 0; x < width; x++) { -									// work on column x in dst -									BYTE *dst_bits = dst_base + x; -									const unsigned index = x >> 3; -									const unsigned mask = 0x80 >> (x & 0x07); - -									// scale each column -									for (unsigned y = 0; y < dst_height; y++) { -										// loop through column -										const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -										const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -										const BYTE *src_bits = src_base + iLeft * src_pitch + index; -										double value = 0; - -										for (unsigned i = 0; i < iLimit; i++) { -											// scan between boundaries -											// accumulate weighted effect of each neighboring pixel -											value += (weightsTable.getWeight(y, i) * (double)((*src_bits & mask) != 0)); -											src_bits += src_pitch; -										} -										value *= 0xFF; - -										// clamp and place result in destination pixel -										*dst_bits = (BYTE)CLAMP<int>((int)(value + 0.5), 0, 0xFF); -										dst_bits += dst_pitch; -									} -								} -							} -						} -						break; - -						case 24: -						{ -							// transparently convert the non-transparent 1-bit image to 24 bpp -							if (src_pal) { -								// we have got a palette -								for (unsigned x = 0; x < width; x++) { -									// work on column x in dst -									BYTE *dst_bits = dst_base + x * 3; -									const unsigned index = x >> 3; -									const unsigned mask = 0x80 >> (x & 0x07); - -									// scale each column -									for (unsigned y = 0; y < dst_height; y++) { -										// loop through column -										const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -										const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -										const BYTE *src_bits = src_base + iLeft * src_pitch + index; -										double r = 0, g = 0, b = 0; - -										for (unsigned i = 0; i < iLimit; i++) { -											// scan between boundaries -											// accumulate weighted effect of each neighboring pixel -											const double weight = weightsTable.getWeight(y, i); -											const unsigned pixel = (*src_bits & mask) != 0; -											const BYTE * const entry = (BYTE *)&src_pal[pixel]; -											r += (weight * (double)entry[FI_RGBA_RED]); -											g += (weight * (double)entry[FI_RGBA_GREEN]); -											b += (weight * (double)entry[FI_RGBA_BLUE]); -											src_bits += src_pitch; -										} - -										// clamp and place result in destination pixel -										dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(r + 0.5), 0, 0xFF); -										dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(g + 0.5), 0, 0xFF); -										dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(b + 0.5), 0, 0xFF); -										dst_bits += dst_pitch; -									} -								} -							} else { -								// we do not have a palette -								for (unsigned x = 0; x < width; x++) { -									// work on column x in dst -									BYTE *dst_bits = dst_base + x * 3; -									const unsigned index = x >> 3; -									const unsigned mask = 0x80 >> (x & 0x07); - -									// scale each column -									for (unsigned y = 0; y < dst_height; y++) { -										// loop through column -										const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -										const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -										const BYTE *src_bits = src_base + iLeft * src_pitch + index; -										double value = 0; - -										for (unsigned i = 0; i < iLimit; i++) { -											// scan between boundaries -											// accumulate weighted effect of each neighboring pixel -											value += (weightsTable.getWeight(y, i) * (double)((*src_bits & mask) != 0)); -											src_bits += src_pitch; -										} -										value *= 0xFF; - -										// clamp and place result in destination pixel -										const BYTE bval = (BYTE)CLAMP<int>((int)(value + 0.5), 0, 0xFF); -										dst_bits[FI_RGBA_RED]	= bval; -										dst_bits[FI_RGBA_GREEN]	= bval; -										dst_bits[FI_RGBA_BLUE]	= bval; -										dst_bits += dst_pitch; -									} -								} -							} -						} -						break; - -						case 32: -						{ -							// transparently convert the transparent 1-bit image to 32 bpp;  -							// we always have got a palette here -							for (unsigned x = 0; x < width; x++) { -								// work on column x in dst -								BYTE *dst_bits = dst_base + x * 4; -								const unsigned index = x >> 3; -								const unsigned mask = 0x80 >> (x & 0x07); - -								// scale each column -								for (unsigned y = 0; y < dst_height; y++) { -									// loop through column -									const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -									const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -									const BYTE *src_bits = src_base + iLeft * src_pitch + index; -									double r = 0, g = 0, b = 0, a = 0; - -									for (unsigned i = 0; i < iLimit; i++) { -										// scan between boundaries -										// accumulate weighted effect of each neighboring pixel -										const double weight = weightsTable.getWeight(y, i); -										const unsigned pixel = (*src_bits & mask) != 0; -										const BYTE * const entry = (BYTE *)&src_pal[pixel]; -										r += (weight * (double)entry[FI_RGBA_RED]); -										g += (weight * (double)entry[FI_RGBA_GREEN]); -										b += (weight * (double)entry[FI_RGBA_BLUE]); -										a += (weight * (double)entry[FI_RGBA_ALPHA]); -										src_bits += src_pitch; -									} - -									// clamp and place result in destination pixel -									dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(r + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(g + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(b + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_ALPHA]	= (BYTE)CLAMP<int>((int)(a + 0.5), 0, 0xFF); -									dst_bits += dst_pitch; -								} -							} -						} -						break; -					} -				} -				break; - -				case 4: -				{ -					const unsigned src_pitch = FreeImage_GetPitch(src); -					const BYTE *const src_base = FreeImage_GetBits(src) + src_offset_y * src_pitch + (src_offset_x >> 1); - -					switch(FreeImage_GetBPP(dst)) { -						case 8: -						{ -							// transparently convert the non-transparent 4-bit greyscale image to 8 bpp;  -							// we always have got a palette for 4-bit images -							for (unsigned x = 0; x < width; x++) { -								// work on column x in dst -								BYTE *dst_bits = dst_base + x; -								const unsigned index = x >> 1; - -								// scale each column -								for (unsigned y = 0; y < dst_height; y++) { -									// loop through column -									const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -									const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -									const BYTE *src_bits = src_base + iLeft * src_pitch + index; -									double value = 0; - -									for (unsigned i = 0; i < iLimit; i++) { -										// scan between boundaries -										// accumulate weighted effect of each neighboring pixel -										const unsigned pixel = x & 0x01 ? *src_bits & 0x0F : *src_bits >> 4; -										value += (weightsTable.getWeight(y, i) * (double)*(BYTE *)&src_pal[pixel]); -										src_bits += src_pitch; -									} - -									// clamp and place result in destination pixel -									*dst_bits = (BYTE)CLAMP<int>((int)(value + 0.5), 0, 0xFF); -									dst_bits += dst_pitch; -								} -							} -						} -						break; - -						case 24: -						{ -							// transparently convert the non-transparent 4-bit image to 24 bpp;  -							// we always have got a palette for 4-bit images -							for (unsigned x = 0; x < width; x++) { -								// work on column x in dst -								BYTE *dst_bits = dst_base + x * 3; -								const unsigned index = x >> 1; - -								// scale each column -								for (unsigned y = 0; y < dst_height; y++) { -									// loop through column -									const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -									const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -									const BYTE *src_bits = src_base + iLeft * src_pitch + index; -									double r = 0, g = 0, b = 0; - -									for (unsigned i = 0; i < iLimit; i++) { -										// scan between boundaries -										// accumulate weighted effect of each neighboring pixel -										const double weight = weightsTable.getWeight(y, i); -										const unsigned pixel = x & 0x01 ? *src_bits & 0x0F : *src_bits >> 4; -										const BYTE *const entry = (BYTE *)&src_pal[pixel]; -										r += (weight * (double)entry[FI_RGBA_RED]); -										g += (weight * (double)entry[FI_RGBA_GREEN]); -										b += (weight * (double)entry[FI_RGBA_BLUE]); -										src_bits += src_pitch; -									} - -									// clamp and place result in destination pixel -									dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(r + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(g + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(b + 0.5), 0, 0xFF); -									dst_bits += dst_pitch; -								} -							} -						} -						break; - -						case 32: -						{ -							// transparently convert the transparent 4-bit image to 32 bpp;  -							// we always have got a palette for 4-bit images -							for (unsigned x = 0; x < width; x++) { -								// work on column x in dst -								BYTE *dst_bits = dst_base + x * 4; -								const unsigned index = x >> 1; - -								// scale each column -								for (unsigned y = 0; y < dst_height; y++) { -									// loop through column -									const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -									const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -									const BYTE *src_bits = src_base + iLeft * src_pitch + index; -									double r = 0, g = 0, b = 0, a = 0; - -									for (unsigned i = 0; i < iLimit; i++) { -										// scan between boundaries -										// accumulate weighted effect of each neighboring pixel -										const double weight = weightsTable.getWeight(y, i); -										const unsigned pixel = x & 0x01 ? *src_bits & 0x0F : *src_bits >> 4; -										const BYTE *const entry = (BYTE *)&src_pal[pixel]; -										r += (weight * (double)entry[FI_RGBA_RED]); -										g += (weight * (double)entry[FI_RGBA_GREEN]); -										b += (weight * (double)entry[FI_RGBA_BLUE]); -										a += (weight * (double)entry[FI_RGBA_ALPHA]); -										src_bits += src_pitch; -									} - -									// clamp and place result in destination pixel -									dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(r + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(g + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(b + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_ALPHA]	= (BYTE)CLAMP<int>((int)(a + 0.5), 0, 0xFF); -									dst_bits += dst_pitch; -								} -							} -						} -						break; -					} -				} -				break; - -				case 8: -				{ -					const unsigned src_pitch = FreeImage_GetPitch(src); -					const BYTE *const src_base = FreeImage_GetBits(src) + src_offset_y * src_pitch + src_offset_x; - -					switch(FreeImage_GetBPP(dst)) { -						case 8: -						{ -							// scale the 8-bit non-transparent greyscale image into an 8 bpp destination image -							if (src_pal) { -								// we have got a palette -								for (unsigned x = 0; x < width; x++) { -									// work on column x in dst -									BYTE *dst_bits = dst_base + x; - -									// scale each column -									for (unsigned y = 0; y < dst_height; y++) { -										// loop through column -										const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -										const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -										const BYTE *src_bits = src_base + iLeft * src_pitch + x; -										double value = 0; - -										for (unsigned i = 0; i < iLimit; i++) { -											// scan between boundaries -											// accumulate weighted effect of each neighboring pixel -											value += (weightsTable.getWeight(y, i) * (double)*(BYTE *)&src_pal[*src_bits]); -											src_bits += src_pitch; -										} - -										// clamp and place result in destination pixel -										*dst_bits = (BYTE)CLAMP<int>((int)(value + 0.5), 0, 0xFF); -										dst_bits += dst_pitch; -									} -								} -							} else { -								// we do not have a palette -								for (unsigned x = 0; x < width; x++) { -									// work on column x in dst -									BYTE *dst_bits = dst_base + x; - -									// scale each column -									for (unsigned y = 0; y < dst_height; y++) { -										// loop through column -										const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -										const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -										const BYTE *src_bits = src_base + iLeft * src_pitch + x; -										double value = 0; - -										for (unsigned i = 0; i < iLimit; i++) { -											// scan between boundaries -											// accumulate weighted effect of each neighboring pixel -											value += (weightsTable.getWeight(y, i) * (double)*src_bits); -											src_bits += src_pitch; -										} - -										// clamp and place result in destination pixel -										*dst_bits = (BYTE)CLAMP<int>((int)(value + 0.5), 0, 0xFF); -										dst_bits += dst_pitch; -									} -								} -							} -						} -						break; - -						case 24: -						{ -							// transparently convert the non-transparent 8-bit image to 24 bpp -							if (src_pal) { -								// we have got a palette -								for (unsigned x = 0; x < width; x++) { -									// work on column x in dst -									BYTE *dst_bits = dst_base + x * 3; - -									// scale each column -									for (unsigned y = 0; y < dst_height; y++) { -										// loop through column -										const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -										const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -										const BYTE *src_bits = src_base + iLeft * src_pitch + x; -										double r = 0, g = 0, b = 0; - -										for (unsigned i = 0; i < iLimit; i++) { -											// scan between boundaries -											// accumulate weighted effect of each neighboring pixel -											const double weight = weightsTable.getWeight(y, i); -											const BYTE * const entry = (BYTE *)&src_pal[*src_bits]; -											r += (weight * (double)entry[FI_RGBA_RED]); -											g += (weight * (double)entry[FI_RGBA_GREEN]); -											b += (weight * (double)entry[FI_RGBA_BLUE]); -											src_bits += src_pitch; -										} - -										// clamp and place result in destination pixel -										dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(r + 0.5), 0, 0xFF); -										dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(g + 0.5), 0, 0xFF); -										dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(b + 0.5), 0, 0xFF); -										dst_bits += dst_pitch; -									} -								} -							} else { -								// we do not have a palette -								for (unsigned x = 0; x < width; x++) { -									// work on column x in dst -									BYTE *dst_bits = dst_base + x * 3; - -									// scale each column -									for (unsigned y = 0; y < dst_height; y++) { -										// loop through column -										const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -										const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -										const BYTE *src_bits = src_base + iLeft * src_pitch + x; -										double value = 0; - -										for (unsigned i = 0; i < iLimit; i++) { -											// scan between boundaries -											// accumulate weighted effect of each neighboring pixel -											value += (weightsTable.getWeight(y, i) * (double)*src_bits); -											src_bits += src_pitch; -										} - -										// clamp and place result in destination pixel -										const BYTE bval = (BYTE)CLAMP<int>((int)(value + 0.5), 0, 0xFF); -										dst_bits[FI_RGBA_RED]	= bval; -										dst_bits[FI_RGBA_GREEN]	= bval; -										dst_bits[FI_RGBA_BLUE]	= bval; -										dst_bits += dst_pitch; -									} -								} -							} -						} -						break; - -						case 32: -						{ -							// transparently convert the transparent 8-bit image to 32 bpp;  -							// we always have got a palette here -							for (unsigned x = 0; x < width; x++) { -								// work on column x in dst -								BYTE *dst_bits = dst_base + x * 4; - -								// scale each column -								for (unsigned y = 0; y < dst_height; y++) { -									// loop through column -									const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -									const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -									const BYTE *src_bits = src_base + iLeft * src_pitch + x; -									double r = 0, g = 0, b = 0, a = 0; - -									for (unsigned i = 0; i < iLimit; i++) { -										// scan between boundaries -										// accumulate weighted effect of each neighboring pixel -										const double weight = weightsTable.getWeight(y, i); -										const BYTE * const entry = (BYTE *)&src_pal[*src_bits]; -										r += (weight * (double)entry[FI_RGBA_RED]); -										g += (weight * (double)entry[FI_RGBA_GREEN]); -										b += (weight * (double)entry[FI_RGBA_BLUE]); -										a += (weight * (double)entry[FI_RGBA_ALPHA]); -										src_bits += src_pitch; -									} - -									// clamp and place result in destination pixel -									dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(r + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(g + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(b + 0.5), 0, 0xFF); -									dst_bits[FI_RGBA_ALPHA]	= (BYTE)CLAMP<int>((int)(a + 0.5), 0, 0xFF); -									dst_bits += dst_pitch; -								} -							} -						} -						break; -					} -				} -				break; - -				case 16: -				{ -					// transparently convert the 16-bit non-transparent image to 24 bpp -					const unsigned src_pitch = FreeImage_GetPitch(src) / sizeof(WORD); -					const WORD *const src_base = (WORD *)FreeImage_GetBits(src) + src_offset_y * src_pitch + src_offset_x; - -					if (IS_FORMAT_RGB565(src)) { -						// image has 565 format -						for (unsigned x = 0; x < width; x++) { -							// work on column x in dst -							BYTE *dst_bits = dst_base + x * 3; - -							// scale each column -							for (unsigned y = 0; y < dst_height; y++) { -								// loop through column -								const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -								const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -								const WORD *src_bits = src_base + iLeft * src_pitch + x; -								double r = 0, g = 0, b = 0; - -								for (unsigned i = 0; i < iLimit; i++) { -									// scan between boundaries -									// accumulate weighted effect of each neighboring pixel -									const double weight = weightsTable.getWeight(y, i); -									r += (weight * (double)((*src_bits & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT)); -									g += (weight * (double)((*src_bits & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT)); -									b += (weight * (double)((*src_bits & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT)); -									src_bits += src_pitch; -								} - -								// clamp and place result in destination pixel -								dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(((r * 0xFF) / 0x1F) + 0.5), 0, 0xFF); -								dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(((g * 0xFF) / 0x3F) + 0.5), 0, 0xFF); -								dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(((b * 0xFF) / 0x1F) + 0.5), 0, 0xFF); -								dst_bits += dst_pitch; -							} -						} -					} else { -						// image has 555 format -						for (unsigned x = 0; x < width; x++) { -							// work on column x in dst -							BYTE *dst_bits = dst_base + x * 3; - -							// scale each column -							for (unsigned y = 0; y < dst_height; y++) { -								// loop through column -								const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -								const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -								const WORD *src_bits = src_base + iLeft * src_pitch + x; -								double r = 0, g = 0, b = 0; - -								for (unsigned i = 0; i < iLimit; i++) { -									// scan between boundaries -									// accumulate weighted effect of each neighboring pixel -									const double weight = weightsTable.getWeight(y, i); -									r += (weight * (double)((*src_bits & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT)); -									g += (weight * (double)((*src_bits & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT)); -									b += (weight * (double)((*src_bits & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT)); -									src_bits += src_pitch; -								} - -								// clamp and place result in destination pixel -								dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int)(((r * 0xFF) / 0x1F) + 0.5), 0, 0xFF); -								dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int)(((g * 0xFF) / 0x1F) + 0.5), 0, 0xFF); -								dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int)(((b * 0xFF) / 0x1F) + 0.5), 0, 0xFF); -								dst_bits += dst_pitch; -							} -						} -					} -				} -				break; - -				case 24: -				{ -					// scale the 24-bit transparent image into a 24 bpp destination image -					const unsigned src_pitch = FreeImage_GetPitch(src); -					const BYTE *const src_base = FreeImage_GetBits(src) + src_offset_y * src_pitch + src_offset_x * 3; - -					for (unsigned x = 0; x < width; x++) { -						// work on column x in dst -						const unsigned index = x * 3; -						BYTE *dst_bits = dst_base + index; - -						// scale each column -						for (unsigned y = 0; y < dst_height; y++) { -							// loop through column -							const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -							const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -							const BYTE *src_bits = src_base + iLeft * src_pitch + index; -							double r = 0, g = 0, b = 0; - -							for (unsigned i = 0; i < iLimit; i++) { -								// scan between boundaries -								// accumulate weighted effect of each neighboring pixel -								const double weight = weightsTable.getWeight(y, i); -								r += (weight * (double)src_bits[FI_RGBA_RED]); -								g += (weight * (double)src_bits[FI_RGBA_GREEN]); -								b += (weight * (double)src_bits[FI_RGBA_BLUE]); -								src_bits += src_pitch; -							} - -							// clamp and place result in destination pixel -							dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int) (r + 0.5), 0, 0xFF); -							dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int) (g + 0.5), 0, 0xFF); -							dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int) (b + 0.5), 0, 0xFF); -							dst_bits += dst_pitch; -						} -					} -				} -				break; - -				case 32: -				{ -					// scale the 32-bit transparent image into a 32 bpp destination image -					const unsigned src_pitch = FreeImage_GetPitch(src); -					const BYTE *const src_base = FreeImage_GetBits(src) + src_offset_y * src_pitch + src_offset_x * 4; - -					for (unsigned x = 0; x < width; x++) { -						// work on column x in dst -						const unsigned index = x * 4; -						BYTE *dst_bits = dst_base + index; - -						// scale each column -						for (unsigned y = 0; y < dst_height; y++) { -							// loop through column -							const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -							const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -							const BYTE *src_bits = src_base + iLeft * src_pitch + index; -							double r = 0, g = 0, b = 0, a = 0; - -							for (unsigned i = 0; i < iLimit; i++) { -								// scan between boundaries -								// accumulate weighted effect of each neighboring pixel -								const double weight = weightsTable.getWeight(y, i); -								r += (weight * (double)src_bits[FI_RGBA_RED]); -								g += (weight * (double)src_bits[FI_RGBA_GREEN]); -								b += (weight * (double)src_bits[FI_RGBA_BLUE]); -								a += (weight * (double)src_bits[FI_RGBA_ALPHA]); -								src_bits += src_pitch; -							} - -							// clamp and place result in destination pixel -							dst_bits[FI_RGBA_RED]	= (BYTE)CLAMP<int>((int) (r + 0.5), 0, 0xFF); -							dst_bits[FI_RGBA_GREEN]	= (BYTE)CLAMP<int>((int) (g + 0.5), 0, 0xFF); -							dst_bits[FI_RGBA_BLUE]	= (BYTE)CLAMP<int>((int) (b + 0.5), 0, 0xFF); -							dst_bits[FI_RGBA_ALPHA]	= (BYTE)CLAMP<int>((int) (a + 0.5), 0, 0xFF); -							dst_bits += dst_pitch; -						} -					} -				} -				break; -			} -		} -		break; - -		case FIT_UINT16: -		{ -			// Calculate the number of words per pixel (1 for 16-bit, 3 for 48-bit or 4 for 64-bit) -			const unsigned wordspp = (FreeImage_GetLine(src) / width) / sizeof(WORD); - -			const unsigned dst_pitch = FreeImage_GetPitch(dst) / sizeof(WORD); -			WORD *const dst_base = (WORD *)FreeImage_GetBits(dst); - -			const unsigned src_pitch = FreeImage_GetPitch(src) / sizeof(WORD); -			const WORD *const src_base = (WORD *)FreeImage_GetBits(src)	+ src_offset_y * src_pitch + src_offset_x * wordspp; - -			for (unsigned x = 0; x < width; x++) { -				// work on column x in dst -				const unsigned index = x * wordspp;	// pixel index -				WORD *dst_bits = dst_base + index; - -				// scale each column -				for (unsigned y = 0; y < dst_height; y++) { -					// loop through column -					const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -					const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -					const WORD *src_bits = src_base + iLeft * src_pitch + index; -					double value = 0; - -					for (unsigned i = 0; i < iLimit; i++) { -						// scan between boundaries -						// accumulate weighted effect of each neighboring pixel -						const double weight = weightsTable.getWeight(y, i); -						value += (weight * (double)src_bits[0]); -						src_bits += src_pitch; -					} - -					// clamp and place result in destination pixel -					dst_bits[0] = (WORD)CLAMP<int>((int)(value + 0.5), 0, 0xFFFF); - -					dst_bits += dst_pitch; -				} -			} -		} -		break; - -		case FIT_RGB16: -		{ -			// Calculate the number of words per pixel (1 for 16-bit, 3 for 48-bit or 4 for 64-bit) -			const unsigned wordspp = (FreeImage_GetLine(src) / width) / sizeof(WORD); - -			const unsigned dst_pitch = FreeImage_GetPitch(dst) / sizeof(WORD); -			WORD *const dst_base = (WORD *)FreeImage_GetBits(dst); - -			const unsigned src_pitch = FreeImage_GetPitch(src) / sizeof(WORD); -			const WORD *const src_base = (WORD *)FreeImage_GetBits(src) + src_offset_y * src_pitch + src_offset_x * wordspp; - -			for (unsigned x = 0; x < width; x++) { -				// work on column x in dst -				const unsigned index = x * wordspp;	// pixel index -				WORD *dst_bits = dst_base + index; - -				// scale each column -				for (unsigned y = 0; y < dst_height; y++) { -					// loop through column -					const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -					const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -					const WORD *src_bits = src_base + iLeft * src_pitch + index; -					double r = 0, g = 0, b = 0; - -					for (unsigned i = 0; i < iLimit; i++) { -						// scan between boundaries -						// accumulate weighted effect of each neighboring pixel -						const double weight = weightsTable.getWeight(y, i);					 -						r += (weight * (double)src_bits[0]); -						g += (weight * (double)src_bits[1]); -						b += (weight * (double)src_bits[2]); - -						src_bits += src_pitch; -					} - -					// clamp and place result in destination pixel -					dst_bits[0] = (WORD)CLAMP<int>((int)(r + 0.5), 0, 0xFFFF); -					dst_bits[1] = (WORD)CLAMP<int>((int)(g + 0.5), 0, 0xFFFF); -					dst_bits[2] = (WORD)CLAMP<int>((int)(b + 0.5), 0, 0xFFFF); - -					dst_bits += dst_pitch; -				} -			} -		} -		break; - -		case FIT_RGBA16: -		{ -			// Calculate the number of words per pixel (1 for 16-bit, 3 for 48-bit or 4 for 64-bit) -			const unsigned wordspp = (FreeImage_GetLine(src) / width) / sizeof(WORD); - -			const unsigned dst_pitch = FreeImage_GetPitch(dst) / sizeof(WORD); -			WORD *const dst_base = (WORD *)FreeImage_GetBits(dst); - -			const unsigned src_pitch = FreeImage_GetPitch(src) / sizeof(WORD); -			const WORD *const src_base = (WORD *)FreeImage_GetBits(src) + src_offset_y * src_pitch + src_offset_x * wordspp; - -			for (unsigned x = 0; x < width; x++) { -				// work on column x in dst -				const unsigned index = x * wordspp;	// pixel index -				WORD *dst_bits = dst_base + index; - -				// scale each column -				for (unsigned y = 0; y < dst_height; y++) { -					// loop through column -					const unsigned iLeft = weightsTable.getLeftBoundary(y);				// retrieve left boundary -					const unsigned iLimit = weightsTable.getRightBoundary(y) - iLeft;	// retrieve right boundary -					const WORD *src_bits = src_base + iLeft * src_pitch + index; -					double r = 0, g = 0, b = 0, a = 0; - -					for (unsigned i = 0; i < iLimit; i++) { -						// scan between boundaries -						// accumulate weighted effect of each neighboring pixel -						const double weight = weightsTable.getWeight(y, i);					 -						r += (weight * (double)src_bits[0]); -						g += (weight * (double)src_bits[1]); -						b += (weight * (double)src_bits[2]); -						a += (weight * (double)src_bits[3]); - -						src_bits += src_pitch; -					} - -					// clamp and place result in destination pixel -					dst_bits[0] = (WORD)CLAMP<int>((int)(r + 0.5), 0, 0xFFFF); -					dst_bits[1] = (WORD)CLAMP<int>((int)(g + 0.5), 0, 0xFFFF); -					dst_bits[2] = (WORD)CLAMP<int>((int)(b + 0.5), 0, 0xFFFF); -					dst_bits[3] = (WORD)CLAMP<int>((int)(a + 0.5), 0, 0xFFFF); - -					dst_bits += dst_pitch; -				} -			} -		} -		break; - -		case FIT_FLOAT: -		case FIT_RGBF: -		case FIT_RGBAF: -		{ -			// Calculate the number of floats per pixel (1 for 32-bit, 3 for 96-bit or 4 for 128-bit) -			const unsigned floatspp = (FreeImage_GetLine(src) / width) / sizeof(float); - -			const unsigned dst_pitch = FreeImage_GetPitch(dst) / sizeof(float); -			float *const dst_base = (float *)FreeImage_GetBits(dst); - -			const unsigned src_pitch = FreeImage_GetPitch(src) / sizeof(float); -			const float *const src_base = (float *)FreeImage_GetBits(src) + src_offset_y * src_pitch + src_offset_x * floatspp; - -			for (unsigned x = 0; x < width; x++) { -				// work on column x in dst -				const unsigned index = x * floatspp;	// pixel index -				float *dst_bits = (float *)dst_base + index; - -				// scale each column -				for (unsigned y = 0; y < dst_height; y++) { -					// loop through column -					const unsigned iLeft = weightsTable.getLeftBoundary(y);    // retrieve left boundary -					const unsigned iRight = weightsTable.getRightBoundary(y);  // retrieve right boundary -					const float *src_bits = src_base + iLeft * src_pitch + index; -					double value[4] = {0, 0, 0, 0};                            // 4 = 128 bpp max - -					for (unsigned i = iLeft; i < iRight; i++) { -						// scan between boundaries -						// accumulate weighted effect of each neighboring pixel -						const double weight = weightsTable.getWeight(y, i - iLeft); -						for (unsigned j = 0; j < floatspp; j++) { -							value[j] += (weight * (double)src_bits[j]); -						} -						src_bits += src_pitch; -					} - -					// place result in destination pixel -					for (unsigned j = 0; j < floatspp; j++) { -						dst_bits[j] = (float)value[j]; -					} -					dst_bits += dst_pitch; -				} -			} -		} -		break; -	} -}  | 
