summaryrefslogtreecommitdiff
path: root/plugins/AdvaImg/src/FreeImageToolkit/Background.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/AdvaImg/src/FreeImageToolkit/Background.cpp')
-rw-r--r--plugins/AdvaImg/src/FreeImageToolkit/Background.cpp895
1 files changed, 0 insertions, 895 deletions
diff --git a/plugins/AdvaImg/src/FreeImageToolkit/Background.cpp b/plugins/AdvaImg/src/FreeImageToolkit/Background.cpp
deleted file mode 100644
index 0e8fd76d1f..0000000000
--- a/plugins/AdvaImg/src/FreeImageToolkit/Background.cpp
+++ /dev/null
@@ -1,895 +0,0 @@
-// ==========================================================
-// Background filling routines
-//
-// Design and implementation by
-// - Carsten Klein (c.klein@datagis.com)
-//
-// 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 Determines, whether a palletized image is visually greyscale or not.
-
- Unlike with FreeImage_GetColorType, which returns either FIC_MINISBLACK or
- FIC_MINISWHITE for a greyscale image with a linear ramp palette, the return
- value of this function does not depend on the palette's order, but only on the
- palette's individual colors.
- @param dib The image to be tested.
- @return Returns TRUE if the palette of the image specified contains only
- greyscales, FALSE otherwise.
- */
-static BOOL
-IsVisualGreyscaleImage(FIBITMAP *dib) {
-
- switch (FreeImage_GetBPP(dib)) {
- case 1:
- case 4:
- case 8: {
- unsigned ncolors = FreeImage_GetColorsUsed(dib);
- RGBQUAD *rgb = FreeImage_GetPalette(dib);
- for (unsigned i = 0; i< ncolors; i++) {
- if ((rgb->rgbRed != rgb->rgbGreen) || (rgb->rgbRed != rgb->rgbBlue)) {
- return FALSE;
- }
- }
- return TRUE;
- }
- default: {
- return (FreeImage_GetColorType(dib) == FIC_MINISBLACK);
- }
- }
-}
-
-/** @brief Looks up a specified color in a FIBITMAP's palette and returns the color's
- palette index or -1 if the color was not found.
-
- Unlike with FreeImage_GetColorType, which returns either FIC_MINISBLACK or
- FIC_MINISWHITE for a greyscale image with a linear ramp palette, the return
- value of this function does not depend on the palette's order, but only on the
- palette's individual colors.
- @param dib The image, whose palette should be searched through.
- @param color The color to be searched in the palette.
- @param options Options that affect the color search process.
- @param color_type A pointer, that optionally specifies the image's color type as
- returned by FreeImage_GetColorType. If invalid or NULL, this function determines the
- color type with FreeImage_GetColorType.
- @return Returns the specified color's palette index, the color's rgbReserved member
- if option FI_COLOR_ALPHA_IS_INDEX was specified or -1, if the color was not found
- in the image's palette or if the specified image is non-palletized.
- */
-static int
-GetPaletteIndex(FIBITMAP *dib, const RGBQUAD *color, int options, FREE_IMAGE_COLOR_TYPE *color_type) {
-
- int result = -1;
-
- if ((!dib) || (!color)) {
- return result;
- }
-
- int bpp = FreeImage_GetBPP(dib);
-
- // First check trivial case: return color->rgbReserved if only
- // FI_COLOR_ALPHA_IS_INDEX is set.
- if ((options & FI_COLOR_ALPHA_IS_INDEX) == FI_COLOR_ALPHA_IS_INDEX) {
- if (bpp == 1) {
- return color->rgbReserved & 0x01;
- } else if (bpp == 4) {
- return color->rgbReserved & 0x0F;
- }
- return color->rgbReserved;
- }
-
- if (bpp == 8) {
- FREE_IMAGE_COLOR_TYPE ct =
- (color_type == NULL || *color_type < 0) ?
- FreeImage_GetColorType(dib) : *color_type;
- if (ct == FIC_MINISBLACK) {
- return GREY(color->rgbRed, color->rgbGreen, color->rgbBlue);
- }
- if (ct == FIC_MINISWHITE) {
- return 255 - GREY(color->rgbRed, color->rgbGreen, color->rgbBlue);
- }
- } else if (bpp > 8) {
- // for palettized images only
- return result;
- }
-
- if (options & FI_COLOR_FIND_EQUAL_COLOR) {
-
- // Option FI_COLOR_ALPHA_IS_INDEX is implicit here so, set
- // index to color->rgbReserved
- result = color->rgbReserved;
- if (bpp == 1) {
- result &= 0x01;
- } else if (bpp == 4) {
- result &= 0x0F;
- }
-
- unsigned ucolor;
- if (!IsVisualGreyscaleImage(dib)) {
- ucolor = (*((unsigned *)color)) & 0xFFFFFF;
- } else {
- ucolor = GREY(color->rgbRed, color->rgbGreen, color->rgbBlue) * 0x010101;
- //ucolor = (ucolor | (ucolor << 8) | (ucolor << 16));
- }
- unsigned ncolors = FreeImage_GetColorsUsed(dib);
- unsigned *palette = (unsigned *)FreeImage_GetPalette(dib);
- for (unsigned i = 0; i < ncolors; i++) {
- if ((palette[i] & 0xFFFFFF) == ucolor) {
- result = i;
- break;
- }
- }
- } else {
- unsigned minimum = UINT_MAX;
- unsigned ncolors = FreeImage_GetColorsUsed(dib);
- BYTE *palette = (BYTE *)FreeImage_GetPalette(dib);
- BYTE red, green, blue;
- if (!IsVisualGreyscaleImage(dib)) {
- red = color->rgbRed;
- green = color->rgbGreen;
- blue = color->rgbBlue;
- } else {
- red = GREY(color->rgbRed, color->rgbGreen, color->rgbBlue);
- green = blue = red;
- }
- for (unsigned i = 0; i < ncolors; i++) {
- unsigned m = abs(palette[FI_RGBA_BLUE] - blue)
- + abs(palette[FI_RGBA_GREEN] - green)
- + abs(palette[FI_RGBA_RED] - red);
- if (m < minimum) {
- minimum = m;
- result = i;
- if (m == 0) {
- break;
- }
- }
- palette += sizeof(RGBQUAD);
- }
- }
- return result;
-}
-
-/** @brief Blends an alpha-transparent foreground color over an opaque background
- color.
-
- This function blends the alpha-transparent foreground color fgcolor over the
- background color bgcolor. The background color is considered fully opaque,
- whatever it's alpha value contains, whereas the foreground color is considered
- to be a real RGBA color with an alpha value, which is used for the blend
- operation. The resulting color is returned through the blended parameter.
- @param bgcolor The background color for the blend operation.
- @param fgcolor The foreground color for the blend operation. This color's alpha
- value, stored in the rgbReserved member, is the alpha value used for the blend
- operation.
- @param blended This out parameter takes the blended color and so, returns it to
- the caller. This color's alpha value will be 0xFF (255) so, the blended color
- itself has no transparency. The this argument is not changed, if the function
- fails.
- @return Returns TRUE on success, FALSE otherwise. This function fails if any of
- the color arguments is a null pointer.
- */
-static BOOL
-GetAlphaBlendedColor(const RGBQUAD *bgcolor, const RGBQUAD *fgcolor, RGBQUAD *blended) {
-
- if ((!bgcolor) || (!fgcolor) || (!blended)) {
- return FALSE;
- }
-
- BYTE alpha = fgcolor->rgbReserved;
- BYTE not_alpha = ~alpha;
-
- blended->rgbRed = (BYTE)( ((WORD)fgcolor->rgbRed * alpha + not_alpha * (WORD)bgcolor->rgbRed) >> 8 );
- blended->rgbGreen = (BYTE)( ((WORD)fgcolor->rgbGreen * alpha + not_alpha * (WORD)bgcolor->rgbGreen) >> 8) ;
- blended->rgbBlue = (BYTE)( ((WORD)fgcolor->rgbBlue * alpha + not_alpha * (WORD)bgcolor->rgbBlue) >> 8 );
- blended->rgbReserved = 0xFF;
-
- return TRUE;
-}
-
-/** @brief Fills a FIT_BITMAP image with the specified color.
-
- This function does the dirty work for FreeImage_FillBackground for FIT_BITMAP
- images.
- @param dib The image to be filled.
- @param color The color, the specified image should be filled with.
- @param options Options that affect the color search process for palletized images.
- @return Returns TRUE on success, FALSE otherwise. This function fails if any of
- the dib and color is NULL or the provided image is not a FIT_BITMAP image.
- */
-static BOOL
-FillBackgroundBitmap(FIBITMAP *dib, const RGBQUAD *color, int options) {
-
- if ((!dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) {
- return FALSE;;
- }
-
- if (!color) {
- return FALSE;
- }
-
- const RGBQUAD *color_intl = color;
- unsigned bpp = FreeImage_GetBPP(dib);
- unsigned width = FreeImage_GetWidth(dib);
- unsigned height = FreeImage_GetHeight(dib);
-
- FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
-
- // get a pointer to the first scanline (bottom line)
- BYTE *src_bits = FreeImage_GetScanLine(dib, 0);
- BYTE *dst_bits = src_bits;
-
- BOOL supports_alpha = ((bpp >= 24) || ((bpp == 8) && (color_type != FIC_PALETTE)));
-
- // Check for RGBA case if bitmap supports alpha
- // blending (8-bit greyscale, 24- or 32-bit images)
- if (supports_alpha && (options & FI_COLOR_IS_RGBA_COLOR)) {
-
- if (color->rgbReserved == 0) {
- // the fill color is fully transparent; we are done
- return TRUE;
- }
-
- // Only if the fill color is NOT fully opaque, draw it with
- // the (much) slower FreeImage_DrawLine function and return.
- // Since we do not have the FreeImage_DrawLine function in this
- // release, just assume to have an unicolor background and fill
- // all with an 'alpha-blended' color.
- if (color->rgbReserved < 255) {
-
- // If we will draw on an unicolor background, it's
- // faster to draw opaque with an alpha blended color.
- // So, first get the color from the first pixel in the
- // image (bottom-left pixel).
- RGBQUAD bgcolor;
- if (bpp == 8) {
- bgcolor = FreeImage_GetPalette(dib)[*src_bits];
- } else {
- bgcolor.rgbBlue = src_bits[FI_RGBA_BLUE];
- bgcolor.rgbGreen = src_bits[FI_RGBA_GREEN];
- bgcolor.rgbRed = src_bits[FI_RGBA_RED];
- bgcolor.rgbReserved = 0xFF;
- }
- RGBQUAD blend;
- GetAlphaBlendedColor(&bgcolor, color_intl, &blend);
- color_intl = &blend;
- }
- }
-
- int index = (bpp <= 8) ? GetPaletteIndex(dib, color_intl, options, &color_type) : 0;
- if (index == -1) {
- // No palette index found for a palletized
- // image. This should never happen...
- return FALSE;
- }
-
- // first, build the first scanline (line 0)
- switch (bpp) {
- case 1: {
- unsigned bytes = (width / 8);
- memset(dst_bits, ((index == 1) ? 0xFF : 0x00), bytes);
- //int n = width % 8;
- int n = width & 7;
- if (n) {
- if (index == 1) {
- // set n leftmost bits
- dst_bits[bytes] |= (0xFF << (8 - n));
- } else {
- // clear n leftmost bits
- dst_bits[bytes] &= (0xFF >> n);
- }
- }
- break;
- }
- case 4: {
- unsigned bytes = (width / 2);
- memset(dst_bits, (index | (index << 4)), bytes);
- //if (bytes % 2) {
- if (bytes & 1) {
- dst_bits[bytes] &= 0x0F;
- dst_bits[bytes] |= (index << 4);
- }
- break;
- }
- case 8: {
- memset(dst_bits, index, FreeImage_GetLine(dib));
- break;
- }
- case 16: {
- WORD wcolor = RGBQUAD_TO_WORD(dib, color_intl);
- for (unsigned x = 0; x < width; x++) {
- ((WORD *)dst_bits)[x] = wcolor;
- }
- break;
- }
- case 24: {
- RGBTRIPLE rgbt = *((RGBTRIPLE *)color_intl);
- for (unsigned x = 0; x < width; x++) {
- ((RGBTRIPLE *)dst_bits)[x] = rgbt;
- }
- break;
- }
- case 32: {
- RGBQUAD rgbq;
- rgbq.rgbBlue = ((RGBTRIPLE *)color_intl)->rgbtBlue;
- rgbq.rgbGreen = ((RGBTRIPLE *)color_intl)->rgbtGreen;
- rgbq.rgbRed = ((RGBTRIPLE *)color_intl)->rgbtRed;
- rgbq.rgbReserved = 0xFF;
- for (unsigned x = 0; x < width; x++) {
- ((RGBQUAD *)dst_bits)[x] = rgbq;
- }
- break;
- }
- default:
- return FALSE;
- }
-
- // Then, copy the first scanline into all following scanlines.
- // 'src_bits' is a pointer to the first scanline and is already
- // set up correctly.
- if (src_bits) {
- unsigned pitch = FreeImage_GetPitch(dib);
- unsigned bytes = FreeImage_GetLine(dib);
- dst_bits = src_bits + pitch;
- for (unsigned y = 1; y < height; y++) {
- memcpy(dst_bits, src_bits, bytes);
- dst_bits += pitch;
- }
- }
- return TRUE;
-}
-
-/** @brief Fills an image with the specified color.
-
- This function sets all pixels of an image to the color provided through the color
- parameter. Since this should work for all image types supported by FreeImage, the
- pointer color must point to a memory location, which is at least as large as the
- image's color value, if this size is greater than 4 bytes. As the color is specified
- by an RGBQUAD structure for all images of type FIT_BITMAP (including all palletized
- images), the smallest possible size of this memory is the size of the RGBQUAD structure,
- which uses 4 bytes.
-
- So, color must point to a double, if the image to be filled is of type FIT_DOUBLE and
- point to a RGBF structure if the image is of type FIT_RGBF and so on.
-
- However, the fill color is always specified through a RGBQUAD structure for all images
- of type FIT_BITMAP. So, for 32- and 24-bit images, the red, green and blue members of
- the RGBQUAD structure are directly used for the image's red, green and blue channel
- respectively. Although alpha transparent RGBQUAD colors are supported, the alpha channel
- of a 32-bit image never gets modified by this function. A fill color with an alpha value
- smaller than 255 gets blended with the image's actual background color, which is determined
- from the image's bottom-left pixel. So, currently using alpha enabled colors, assumes the
- image to be unicolor before the fill operation. However, the RGBQUAD's rgbReserved member is
- only taken into account, if option FI_COLOR_IS_RGBA_COLOR has been specified.
-
- For 16-bit images, the red-, green- and blue components of the specified color are
- transparently translated into either the 16-bit 555 or 565 representation. This depends
- on the image's actual red- green- and blue masks.
-
- Special attention must be payed for palletized images. Generally, the RGB color specified
- is looked up in the image's palette. The found palette index is then used to fill the image.
- There are some option flags, that affect this lookup process:
-
- no option specified (0x00) Uses the color, that is nearest to the specified color.
- This is the default behavior and should always find a
- color in the palette. However, the visual result may
- far from what was expected and mainly depends on the
- image's palette.
-
- FI_COLOR_FIND_EQUAL_COLOR (0x02) Searches the image's palette for the specified color
- but only uses the returned palette index, if the specified
- color exactly matches the palette entry. Of course,
- depending on the image's actual palette entries, this
- operation may fail. In this case, the function falls back
- to option FI_COLOR_ALPHA_IS_INDEX and uses the RGBQUAD's
- rgbReserved member (or its low nibble for 4-bit images
- or its least significant bit (LSB) for 1-bit images) as
- the palette index used for the fill operation.
-
- FI_COLOR_ALPHA_IS_INDEX (0x04) Does not perform any color lookup from the palette, but
- uses the RGBQUAD's alpha channel member rgbReserved as
- the palette index to be used for the fill operation.
- However, for 4-bit images, only the low nibble of the
- rgbReserved member are used and for 1-bit images, only
- the least significant bit (LSB) is used.
-
- This function fails if any of dib and color is NULL.
-
- @param dib The image to be filled.
- @param color A pointer to the color value to be used for filling the image. The
- memory pointed to by this pointer is always assumed to be at least as large as the
- image's color value, but never smaller than the size of an RGBQUAD structure.
- @param options Options that affect the color search process for palletized images.
- @return Returns TRUE on success, FALSE otherwise. This function fails if any of
- dib and color is NULL.
- */
-BOOL DLL_CALLCONV
-FreeImage_FillBackground(FIBITMAP *dib, const void *color, int options) {
-
- if (!FreeImage_HasPixels(dib)) {
- return FALSE;
- }
-
- if (!color) {
- return FALSE;
- }
-
- // handle FIT_BITMAP images with FreeImage_FillBackground()
- if (FreeImage_GetImageType(dib) == FIT_BITMAP) {
- return FillBackgroundBitmap(dib, (RGBQUAD *)color, options);
- }
-
- // first, construct the first scanline (bottom line)
- unsigned bytespp = (FreeImage_GetBPP(dib) / 8);
- BYTE *src_bits = FreeImage_GetScanLine(dib, 0);
- BYTE *dst_bits = src_bits;
- for (unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
- memcpy(dst_bits, color, bytespp);
- dst_bits += bytespp;
- }
-
- // then, copy the first scanline into all following scanlines
- unsigned height = FreeImage_GetHeight(dib);
- unsigned pitch = FreeImage_GetPitch(dib);
- unsigned bytes = FreeImage_GetLine(dib);
- dst_bits = src_bits + pitch;
- for (unsigned y = 1; y < height; y++) {
- memcpy(dst_bits, src_bits, bytes);
- dst_bits += pitch;
- }
- return TRUE;
-}
-
-/** @brief Allocates a new image of the specified type, width, height and bit depth and
- optionally fills it with the specified color.
-
- This function is an extension to FreeImage_AllocateT, which additionally supports specifying
- a palette to be set for the newly create image, as well as specifying a background color,
- the newly created image should initially be filled with.
-
- Basically, this function internally relies on function FreeImage_AllocateT, followed by a
- call to FreeImage_FillBackground. This is why both parameters color and options behave the
- same as it is documented for function FreeImage_FillBackground. So, please refer to the
- documentation of FreeImage_FillBackground to learn more about parameters color and options.
-
- The palette specified through parameter palette is only copied to the newly created
- image, if its image type is FIT_BITMAP and the desired bit depth is smaller than or equal
- to 8 bits per pixel. In other words, the palette parameter is only taken into account for
- palletized images. However, if the preceding conditions match and if palette is not NULL,
- the memory pointed to by the palette pointer is assumed to be at least as large as size
- of a fully populated palette for the desired bit depth. So, for an 8-bit image, this size
- is 256 x sizeof(RGBQUAD), for an 4-bit image it is 16 x sizeof(RGBQUAD) and it is
- 2 x sizeof(RGBQUAD) for a 1-bit image. In other words, this function does not support
- partial palettes.
-
- However, specifying a palette is not necessarily needed, even for palletized images. This
- function is capable of implicitly creating a palette, if parameter palette is NULL. If the
- specified background color is a greyscale value (red = green = blue) or if option
- FI_COLOR_ALPHA_IS_INDEX is specified, a greyscale palette is created. For a 1-bit image, only
- if the specified background color is either black or white, a monochrome palette, consisting
- of black and white only is created. In any case, the darker colors are stored at the smaller
- palette indices.
-
- If the specified background color is not a greyscale value, or is neither black nor white
- for a 1-bit image, solely this single color is injected into the otherwise black-initialized
- palette. For this operation, option FI_COLOR_ALPHA_IS_INDEX is implicit, so the specified
- color is applied to the palette entry, specified by the background color's rgbReserved
- member. The image is then filled with this palette index.
-
- This function returns a newly created image as function FreeImage_AllocateT does, if both
- parameters color and palette are NULL. If only color is NULL, the palette pointed to by
- parameter palette is initially set for the new image, if a palletized image of type
- FIT_BITMAP is created. However, in the latter case, this function returns an image, whose
- pixels are all initialized with zeros so, the image will be filled with the color of the
- first palette entry.
-
- @param type Specifies the image type of the new image.
- @param width The desired width in pixels of the new image.
- @param height The desired height in pixels of the new image.
- @param bpp The desired bit depth of the new image.
- @param color A pointer to the color value to be used for filling the image. The
- memory pointed to by this pointer is always assumed to be at least as large as the
- image's color value but never smaller than the size of an RGBQUAD structure.
- @param options Options that affect the color search process for palletized images.
- @param red_mask Specifies the bits used to store the red components of a pixel.
- @param green_mask Specifies the bits used to store the green components of a pixel.
- @param blue_mask Specifies the bits used to store the blue components of a pixel.
- @return Returns a pointer to a newly allocated image on success, NULL otherwise.
- */
-FIBITMAP * DLL_CALLCONV
-FreeImage_AllocateExT(FREE_IMAGE_TYPE type, int width, int height, int bpp, const void *color, int options, const RGBQUAD *palette, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
-
- FIBITMAP *bitmap = FreeImage_AllocateT(type, width, height, bpp, red_mask, green_mask, blue_mask);
-
- if (!color) {
- if ((palette) && (type == FIT_BITMAP) && (bpp <= 8)) {
- memcpy(FreeImage_GetPalette(bitmap), palette, FreeImage_GetColorsUsed(bitmap) * sizeof(RGBQUAD));
- }
- return bitmap;
- }
-
- if (bitmap != NULL) {
-
- // Only fill the new bitmap if the specified color
- // differs from "black", that is not all bytes of the
- // color are equal to zero.
- switch (bpp) {
- case 1: {
- // although 1-bit implies FIT_BITMAP, better get an unsigned
- // color and palette
- unsigned *urgb = (unsigned *)color;
- unsigned *upal = (unsigned *)FreeImage_GetPalette(bitmap);
- RGBQUAD rgbq = RGBQUAD();
-
- if (palette != NULL) {
- // clone the specified palette
- memcpy(FreeImage_GetPalette(bitmap), palette, 2 * sizeof(RGBQUAD));
- } else if (options & FI_COLOR_ALPHA_IS_INDEX) {
- CREATE_GREYSCALE_PALETTE(upal, 2);
- } else {
- // check, whether the specified color is either black or white
- if ((*urgb & 0xFFFFFF) == 0x000000) {
- // in any case build a FIC_MINISBLACK palette
- CREATE_GREYSCALE_PALETTE(upal, 2);
- color = &rgbq;
- } else if ((*urgb & 0xFFFFFF) == 0xFFFFFF) {
- // in any case build a FIC_MINISBLACK palette
- CREATE_GREYSCALE_PALETTE(upal, 2);
- rgbq.rgbReserved = 1;
- color = &rgbq;
- } else {
- // Otherwise inject the specified color into the so far
- // black-only palette. We use color->rgbReserved as the
- // desired palette index.
- BYTE index = ((RGBQUAD *)color)->rgbReserved & 0x01;
- upal[index] = *urgb & 0x00FFFFFF;
- }
- options |= FI_COLOR_ALPHA_IS_INDEX;
- }
- // and defer to FreeImage_FillBackground
- FreeImage_FillBackground(bitmap, color, options);
- break;
- }
- case 4: {
- // 4-bit implies FIT_BITMAP so, get a RGBQUAD color
- RGBQUAD *rgb = (RGBQUAD *)color;
- RGBQUAD *pal = FreeImage_GetPalette(bitmap);
- RGBQUAD rgbq = RGBQUAD();
-
- if (palette != NULL) {
- // clone the specified palette
- memcpy(pal, palette, 16 * sizeof(RGBQUAD));
- } else if (options & FI_COLOR_ALPHA_IS_INDEX) {
- CREATE_GREYSCALE_PALETTE(pal, 16);
- } else {
- // check, whether the specified color is a grey one
- if ((rgb->rgbRed == rgb->rgbGreen) && (rgb->rgbRed == rgb->rgbBlue)) {
- // if so, build a greyscale palette
- CREATE_GREYSCALE_PALETTE(pal, 16);
- rgbq.rgbReserved = rgb->rgbRed >> 4;
- color = &rgbq;
- } else {
- // Otherwise inject the specified color into the so far
- // black-only palette. We use color->rgbReserved as the
- // desired palette index.
- BYTE index = (rgb->rgbReserved & 0x0F);
- ((unsigned *)pal)[index] = *((unsigned *)rgb) & 0x00FFFFFF;
- }
- options |= FI_COLOR_ALPHA_IS_INDEX;
- }
- // and defer to FreeImage_FillBackground
- FreeImage_FillBackground(bitmap, color, options);
- break;
- }
- case 8: {
- // 8-bit implies FIT_BITMAP so, get a RGBQUAD color
- RGBQUAD *rgb = (RGBQUAD *)color;
- RGBQUAD *pal = FreeImage_GetPalette(bitmap);
- RGBQUAD rgbq;
-
- if (palette != NULL) {
- // clone the specified palette
- memcpy(pal, palette, 256 * sizeof(RGBQUAD));
- } else if (options & FI_COLOR_ALPHA_IS_INDEX) {
- CREATE_GREYSCALE_PALETTE(pal, 256);
- } else {
- // check, whether the specified color is a grey one
- if ((rgb->rgbRed == rgb->rgbGreen) && (rgb->rgbRed == rgb->rgbBlue)) {
- // if so, build a greyscale palette
- CREATE_GREYSCALE_PALETTE(pal, 256);
- rgbq.rgbReserved = rgb->rgbRed;
- color = &rgbq;
- } else {
- // Otherwise inject the specified color into the so far
- // black-only palette. We use color->rgbReserved as the
- // desired palette index.
- BYTE index = rgb->rgbReserved;
- ((unsigned *)pal)[index] = *((unsigned *)rgb) & 0x00FFFFFF;
- }
- options |= FI_COLOR_ALPHA_IS_INDEX;
- }
- // and defer to FreeImage_FillBackground
- FreeImage_FillBackground(bitmap, color, options);
- break;
- }
- case 16: {
- WORD wcolor = (type == FIT_BITMAP) ?
- RGBQUAD_TO_WORD(bitmap, ((RGBQUAD *)color)) : *((WORD *)color);
- if (wcolor != 0) {
- FreeImage_FillBackground(bitmap, color, options);
- }
- break;
- }
- default: {
- int bytespp = bpp / 8;
- for (int i = 0; i < bytespp; i++) {
- if (((BYTE *)color)[i] != 0) {
- FreeImage_FillBackground(bitmap, color, options);
- break;
- }
- }
- break;
- }
- }
- }
- return bitmap;
-}
-
-/** @brief Allocates a new image of the specified width, height and bit depth and optionally
- fills it with the specified color.
-
- This function is an extension to FreeImage_Allocate, which additionally supports specifying
- a palette to be set for the newly create image, as well as specifying a background color,
- the newly created image should initially be filled with.
-
- Basically, this function internally relies on function FreeImage_Allocate, followed by a
- call to FreeImage_FillBackground. This is why both parameters color and options behave the
- same as it is documented for function FreeImage_FillBackground. So, please refer to the
- documentation of FreeImage_FillBackground to learn more about parameters color and options.
-
- The palette specified through parameter palette is only copied to the newly created
- image, if the desired bit depth is smaller than or equal to 8 bits per pixel. In other words,
- the palette parameter is only taken into account for palletized images. However, if the
- image to be created is a palletized image and if palette is not NULL, the memory pointed to
- by the palette pointer is assumed to be at least as large as size of a fully populated
- palette for the desired bit depth. So, for an 8-bit image, this size is 256 x sizeof(RGBQUAD),
- for an 4-bit image it is 16 x sizeof(RGBQUAD) and it is 2 x sizeof(RGBQUAD) for a 1-bit
- image. In other words, this function does not support partial palettes.
-
- However, specifying a palette is not necessarily needed, even for palletized images. This
- function is capable of implicitly creating a palette, if parameter palette is NULL. If the
- specified background color is a greyscale value (red = green = blue) or if option
- FI_COLOR_ALPHA_IS_INDEX is specified, a greyscale palette is created. For a 1-bit image, only
- if the specified background color is either black or white, a monochrome palette, consisting
- of black and white only is created. In any case, the darker colors are stored at the smaller
- palette indices.
-
- If the specified background color is not a greyscale value, or is neither black nor white
- for a 1-bit image, solely this single color is injected into the otherwise black-initialized
- palette. For this operation, option FI_COLOR_ALPHA_IS_INDEX is implicit, so the specified
- color is applied to the palette entry, specified by the background color's rgbReserved
- member. The image is then filled with this palette index.
-
- This function returns a newly created image as function FreeImage_Allocate does, if both
- parameters color and palette are NULL. If only color is NULL, the palette pointed to by
- parameter palette is initially set for the new image, if a palletized image of type
- FIT_BITMAP is created. However, in the latter case, this function returns an image, whose
- pixels are all initialized with zeros so, the image will be filled with the color of the
- first palette entry.
-
- @param width The desired width in pixels of the new image.
- @param height The desired height in pixels of the new image.
- @param bpp The desired bit depth of the new image.
- @param color A pointer to an RGBQUAD structure, that provides the color to be used for
- filling the image.
- @param options Options that affect the color search process for palletized images.
- @param red_mask Specifies the bits used to store the red components of a pixel.
- @param green_mask Specifies the bits used to store the green components of a pixel.
- @param blue_mask Specifies the bits used to store the blue components of a pixel.
- @return Returns a pointer to a newly allocated image on success, NULL otherwise.
- */
-FIBITMAP * DLL_CALLCONV
-FreeImage_AllocateEx(int width, int height, int bpp, const RGBQUAD *color, int options, const RGBQUAD *palette, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
- return FreeImage_AllocateExT(FIT_BITMAP, width, height, bpp, ((void *)color), options, palette, red_mask, green_mask, blue_mask);
-}
-
-/** @brief Enlarges or shrinks an image selectively per side and fills newly added areas
- with the specified background color.
-
- This function enlarges or shrinks an image selectively per side. The main purpose of this
- function is to add borders to an image. To add a border to any of the image's sides, a
- positive integer value must be passed in any of the parameters left, top, right or bottom.
- This value represents the border's width in pixels. Newly created parts of the image (the
- border areas) are filled with the specified color. Specifying a negative integer value for
- a certain side, will shrink or crop the image on this side. Consequently, specifying zero
- for a certain side will not change the image's extension on that side.
-
- So, calling this function with all parameters left, top, right and bottom set to zero, is
- effectively the same as calling function FreeImage_Clone; setting all parameters left, top,
- right and bottom to value equal to or smaller than zero, my easily be substituted by a call
- to function FreeImage_Copy. Both these cases produce a new image, which is guaranteed not to
- be larger than the input image. Thus, since the specified color is not needed in these cases,
- the pointer color may be NULL.
-
- Both parameters color and options work according to function FreeImage_FillBackground. So,
- please refer to the documentation of FreeImage_FillBackground to learn more about parameters
- color and options. For palletized images, the palette of the input image src is
- transparently copied to the newly created enlarged or shrunken image, so any color
- look-ups are performed on this palette.
-
- Here are some examples, that illustrate, how to use the parameters left, top, right and
- bottom:
-
- // create a white color
- RGBQUAD c;
- c.rgbRed = 0xFF;
- c.rgbGreen = 0xFF;
- c.rgbBlue = 0xFF;
- c.rgbReserved = 0x00;
-
- // add a white, symmetric 10 pixel wide border to the image
- dib2 = FreeImage_EnlargeCanvas(dib, 10, 10, 10, 10, &c, FI_COLOR_IS_RGB_COLOR);
-
- // add white, 20 pixel wide stripes to the top and bottom side of the image
- dib3 = FreeImage_EnlargeCanvas(dib, 0, 20, 0, 20, &c, FI_COLOR_IS_RGB_COLOR);
-
- // add white, 30 pixel wide stripes to the right side of the image and
- // cut off the 40 leftmost pixel columns
- dib3 = FreeImage_EnlargeCanvas(dib, -40, 0, 30, 0, &c, FI_COLOR_IS_RGB_COLOR);
-
- This function fails if either the input image is NULL or the pointer to the color is
- NULL, while at least on of left, top, right and bottom is greater than zero. This
- function also returns NULL, if the new image's size will be negative in either x- or
- y-direction.
-
- @param dib The image to be enlarged or shrunken.
- @param left The number of pixels, the image should be enlarged on its left side. Negative
- values shrink the image on its left side.
- @param top The number of pixels, the image should be enlarged on its top side. Negative
- values shrink the image on its top side.
- @param right The number of pixels, the image should be enlarged on its right side. Negative
- values shrink the image on its right side.
- @param bottom The number of pixels, the image should be enlarged on its bottom side. Negative
- values shrink the image on its bottom side.
- @param color The color, the enlarged sides of the image should be filled with.
- @param options Options that affect the color search process for palletized images.
- @return Returns a pointer to a newly allocated enlarged or shrunken image on success,
- NULL otherwise. This function fails if either the input image is NULL or the pointer to the
- color is NULL, while at least on of left, top, right and bottom is greater than zero. This
- function also returns NULL, if the new image's size will be negative in either x- or
- y-direction.
- */
-FIBITMAP * DLL_CALLCONV
-FreeImage_EnlargeCanvas(FIBITMAP *src, int left, int top, int right, int bottom, const void *color, int options) {
-
- if(!FreeImage_HasPixels(src)) return NULL;
-
- // Just return a clone of the image, if left, top, right and bottom are
- // all zero.
- if ((left == 0) && (right == 0) && (top == 0) && (bottom == 0)) {
- return FreeImage_Clone(src);
- }
-
- int width = FreeImage_GetWidth(src);
- int height = FreeImage_GetHeight(src);
-
- // Relay on FreeImage_Copy, if all parameters left, top, right and
- // bottom are smaller than or equal zero. The color pointer may be
- // NULL in this case.
- if ((left <= 0) && (right <= 0) && (top <= 0) && (bottom <= 0)) {
- return FreeImage_Copy(src, -left, -top, width + right, height + bottom);
- }
-
- // From here, we need a valid color, since the image will be enlarged on
- // at least one side. So, fail if we don't have a valid color pointer.
- if (!color) {
- return NULL;
- }
-
- if (((left < 0) && (-left >= width)) || ((right < 0) && (-right >= width)) ||
- ((top < 0) && (-top >= height)) || ((bottom < 0) && (-bottom >= height))) {
- return NULL;
- }
-
- unsigned newWidth = width + left + right;
- unsigned newHeight = height + top + bottom;
-
- FREE_IMAGE_TYPE type = FreeImage_GetImageType(src);
- unsigned bpp = FreeImage_GetBPP(src);
-
- FIBITMAP *dst = FreeImage_AllocateExT(
- type, newWidth, newHeight, bpp, color, options,
- FreeImage_GetPalette(src),
- FreeImage_GetRedMask(src),
- FreeImage_GetGreenMask(src),
- FreeImage_GetBlueMask(src));
-
- if (!dst) {
- return NULL;
- }
-
- if ((type == FIT_BITMAP) && (bpp <= 4)) {
- FIBITMAP *copy = FreeImage_Copy(src,
- ((left >= 0) ? 0 : -left),
- ((top >= 0) ? 0 : -top),
- ((width+right)>width)?width:(width+right),
- ((height+bottom)>height)?height:(height+bottom));
-
- if (!copy) {
- FreeImage_Unload(dst);
- return NULL;
- }
-
- if (!FreeImage_Paste(dst, copy,
- ((left <= 0) ? 0 : left),
- ((top <= 0) ? 0 : top), 256)) {
- FreeImage_Unload(copy);
- FreeImage_Unload(dst);
- return NULL;
- }
-
- FreeImage_Unload(copy);
-
- } else {
-
- int bytespp = bpp / 8;
- BYTE *srcPtr = FreeImage_GetScanLine(src, height - 1 - ((top >= 0) ? 0 : -top));
- BYTE *dstPtr = FreeImage_GetScanLine(dst, newHeight - 1 - ((top <= 0) ? 0 : top));
-
- unsigned srcPitch = FreeImage_GetPitch(src);
- unsigned dstPitch = FreeImage_GetPitch(dst);
-
- int lineWidth = bytespp * (width + MIN(0, left) + MIN(0, right));
- int lines = height + MIN(0, top) + MIN(0, bottom);
-
- if (left <= 0) {
- srcPtr += (-left * bytespp);
- } else {
- dstPtr += (left * bytespp);
- }
-
- for (int i = 0; i < lines; i++) {
- memcpy(dstPtr, srcPtr, lineWidth);
- srcPtr -= srcPitch;
- dstPtr -= dstPitch;
- }
- }
-
- // copy metadata from src to dst
- FreeImage_CloneMetadata(dst, src);
-
- // copy transparency table
- FreeImage_SetTransparencyTable(dst, FreeImage_GetTransparencyTable(src), FreeImage_GetTransparencyCount(src));
-
- // copy background color
- RGBQUAD bkcolor;
- if( FreeImage_GetBackgroundColor(src, &bkcolor) ) {
- FreeImage_SetBackgroundColor(dst, &bkcolor);
- }
-
- // clone resolution
- FreeImage_SetDotsPerMeterX(dst, FreeImage_GetDotsPerMeterX(src));
- FreeImage_SetDotsPerMeterY(dst, FreeImage_GetDotsPerMeterY(src));
-
- // clone ICC profile
- FIICCPROFILE *src_profile = FreeImage_GetICCProfile(src);
- FIICCPROFILE *dst_profile = FreeImage_CreateICCProfile(dst, src_profile->data, src_profile->size);
- dst_profile->flags = src_profile->flags;
-
- return dst;
-}
-