// File: crn_freeimage_image_utils.h // See Copyright Notice and license at the end of inc/crnlib.h // Note: This header file requires FreeImage/FreeImagePlus. #include "crn_image_utils.h" #include "freeImagePlus.h" namespace crnlib { namespace freeimage_image_utils { inline bool load_from_file(image_u8& dest, const wchar_t* pFilename, int fi_flag) { fipImage src_image; if (!src_image.loadU(pFilename, fi_flag)) return false; const uint orig_bits_per_pixel = src_image.getBitsPerPixel(); const FREE_IMAGE_COLOR_TYPE orig_color_type = src_image.getColorType(); if (!src_image.convertTo32Bits()) return false; if (src_image.getBitsPerPixel() != 32) return false; uint width = src_image.getWidth(); uint height = src_image.getHeight(); dest.resize(src_image.getWidth(), src_image.getHeight(), src_image.getWidth()); color_quad_u8* pDst = dest.get_ptr(); bool grayscale = true; bool has_alpha = false; for (uint y = 0; y < height; y++) { const BYTE* pSrc = src_image.getScanLine((WORD)(height - 1 - y)); color_quad_u8* pD = pDst; for (uint x = width; x; x--) { color_quad_u8 c; c.r = pSrc[FI_RGBA_RED]; c.g = pSrc[FI_RGBA_GREEN]; c.b = pSrc[FI_RGBA_BLUE]; c.a = pSrc[FI_RGBA_ALPHA]; if (!c.is_grayscale()) grayscale = false; has_alpha |= (c.a < 255); pSrc += 4; *pD++ = c; } pDst += width; } dest.reset_comp_flags(); if (grayscale) dest.set_grayscale(true); dest.set_component_valid(3, has_alpha || (orig_color_type == FIC_RGBALPHA) || (orig_bits_per_pixel == 32)); return true; } const int cSaveLuma = -1; inline bool save_to_grayscale_file(const wchar_t* pFilename, const image_u8& src, int component, int fi_flag) { fipImage dst_image(FIT_BITMAP, (WORD)src.get_width(), (WORD)src.get_height(), 8); RGBQUAD* p = dst_image.getPalette(); for (uint i = 0; i < dst_image.getPaletteSize(); i++) { p[i].rgbRed = (BYTE)i; p[i].rgbGreen = (BYTE)i; p[i].rgbBlue = (BYTE)i; p[i].rgbReserved = 255; } for (uint y = 0; y < src.get_height(); y++) { const color_quad_u8* pSrc = src.get_scanline(y); for (uint x = 0; x < src.get_width(); x++) { BYTE v; if (component == cSaveLuma) v = (BYTE)(*pSrc).get_luma(); else v = (*pSrc)[component]; dst_image.setPixelIndex(x, src.get_height() - 1 - y, &v); pSrc++; } } if (!dst_image.saveU(pFilename, fi_flag)) return false; return true; } inline bool save_to_file(const wchar_t* pFilename, const image_u8& src, int fi_flag, bool ignore_alpha = false) { const bool save_alpha = src.is_component_valid(3); uint bpp = (save_alpha && !ignore_alpha) ? 32 : 24; if (bpp == 32) { dynamic_wstring ext(pFilename); get_extension(ext); if ((ext == L"jpg") || (ext == L"jpeg") || (ext == L"gif") || (ext == L"jp2")) bpp = 24; } if ((bpp == 24) && (src.is_grayscale())) return save_to_grayscale_file(pFilename, src, cSaveLuma, fi_flag); fipImage dst_image(FIT_BITMAP, (WORD)src.get_width(), (WORD)src.get_height(), (WORD)bpp); for (uint y = 0; y < src.get_height(); y++) { for (uint x = 0; x < src.get_width(); x++) { color_quad_u8 c(src(x, y)); RGBQUAD quad; quad.rgbRed = c.r; quad.rgbGreen = c.g; quad.rgbBlue = c.b; if (bpp == 32) quad.rgbReserved = c.a; else quad.rgbReserved = 255; dst_image.setPixelColor(x, src.get_height() - 1 - y, &quad); } } if (!dst_image.saveU(pFilename, fi_flag)) return false; return true; } } // namespace freeimage_image_utils } // namespace crnlib