RGBQUAD CxDib::GetPixelColor(long x,long y) { RGBQUAD rgb={0,0,0,0}; if ((hDib==NULL)||(x<0)||(y<0)|| (x>=m_bi.biWidth)||(y>=m_bi.biHeight)) return rgb; if (m_nColors) return GetPaletteIndex(GetPixelIndex(x,y)); else { BYTE* iDst = GetBits()+(m_bi.biHeight - y)*m_LineWidth + x*sizeof(RGBQUAD); rgb.rgbBlue = *iDst++; rgb.rgbGreen= *iDst++; rgb.rgbRed =*iDst; return rgb; } }
/** @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; }