Image *Image::New(FIBITMAP* dib) { NanScope(); Local<Value> arg = NanNew<Integer>(0); Local<Object> obj = NanNew<FunctionTemplate>(constructor_template)->GetFunction()->NewInstance(1, &arg); Image *image = ObjectWrap::Unwrap<Image>(obj); int w,h,pitch; FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib); obj->SetInternalField(0, NanNew<External>(dib)); obj->Set(NanNew<String>("width"), NanNew<Integer>(w=FreeImage_GetWidth(dib))); obj->Set(NanNew<String>("height"), NanNew<Integer>(h=FreeImage_GetHeight(dib))); obj->Set(NanNew<String>("bpp"), NanNew<Integer>((int)FreeImage_GetBPP(dib))); obj->Set(NanNew<String>("pitch"), NanNew<Integer>(pitch=FreeImage_GetPitch(dib))); obj->Set(NanNew<String>("type"), NanNew<Integer>(type)); obj->Set(NanNew<String>("redMask"), NanNew<Integer>((int)FreeImage_GetRedMask(dib))); obj->Set(NanNew<String>("greenMask"), NanNew<Integer>((int)FreeImage_GetGreenMask(dib))); obj->Set(NanNew<String>("blueMask"), NanNew<Integer>((int)FreeImage_GetBlueMask(dib))); BYTE *bits = FreeImage_GetBits(dib); obj->Set(NanNew<String>("buffer"), NanNewBufferHandle((char*) bits, h * pitch)); return image; }
template<class Tdst, class Tsrc> FIBITMAP* CONVERT_TYPE<Tdst, Tsrc>::convert(FIBITMAP *src, FREE_IMAGE_TYPE dst_type) { FIBITMAP *dst = NULL; unsigned width = FreeImage_GetWidth(src); unsigned height = FreeImage_GetHeight(src); unsigned bpp = FreeImage_GetBPP(src); // allocate dst image dst = FreeImage_AllocateT(dst_type, width, height, bpp, FreeImage_GetRedMask(src), FreeImage_GetGreenMask(src), FreeImage_GetBlueMask(src)); if(!dst) return NULL; // convert from src_type to dst_type for(unsigned y = 0; y < height; y++) { const Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y)); Tdst *dst_bits = reinterpret_cast<Tdst*>(FreeImage_GetScanLine(dst, y)); for(unsigned x = 0; x < width; x++) { *dst_bits++ = static_cast<Tdst>(*src_bits++); } } return dst; }
Image *Image::New(FIBITMAP* dib) { HandleScope scope; Local<Value> arg = Integer::NewFromUnsigned(0); Local<Object> obj = constructor_template->GetFunction()->NewInstance(1, &arg); Image *image = ObjectWrap::Unwrap<Image>(obj); image->dib = dib; int w,h,pitch; FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib); obj->SetInternalField(0, External::New(dib)); obj->Set(JS_STR("width"), JS_INT(w=FreeImage_GetWidth(dib))); obj->Set(JS_STR("height"), JS_INT(h=FreeImage_GetHeight(dib))); obj->Set(JS_STR("bpp"), JS_INT((int)FreeImage_GetBPP(dib))); obj->Set(JS_STR("pitch"), JS_INT(pitch=FreeImage_GetPitch(dib))); obj->Set(JS_STR("type"), JS_INT(type)); obj->Set(JS_STR("redMask"), JS_INT((int)FreeImage_GetRedMask(dib))); obj->Set(JS_STR("greenMask"), JS_INT((int)FreeImage_GetGreenMask(dib))); obj->Set(JS_STR("blueMask"), JS_INT((int)FreeImage_GetBlueMask(dib))); BYTE *bits=FreeImage_GetBits(dib); node::Buffer *buf = node::Buffer::New((char*)bits,h*pitch); obj->Set(JS_STR("buffer"), buf->handle_); return image; }
/* ================== Receiving a IND_Image returns a D3D format for the source and destination. No conversion allowed in-between ================== */ void DirectXTextureBuilder::getSourceAndDestinationFormat(IND_Image *pImage, D3DFORMAT* pSrcFormat, D3DFORMAT* pDstFormat) { int bpp (pImage->getBpp()); switch (pImage->getFormatInt()) { case IND_RGB: { if (16 == bpp) { FIBITMAP* fib = pImage->getFreeImageHandle(); //Check if 565 RGB if ((FreeImage_GetRedMask(fib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(fib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(fib) == FI16_565_BLUE_MASK)) { *pSrcFormat = D3DFMT_R5G6B5; } else { *pSrcFormat = D3DFMT_UNKNOWN; g_debug->header("Not supported format of image! texture not loaded" , 4); } } else if (32 == bpp) { *pSrcFormat = D3DFMT_A8B8G8R8; } else { *pSrcFormat = D3DFMT_UNKNOWN; g_debug->header("The pixel format for the image could not be resolved correctly!" , 4); } } break; case IND_RGBA: { if (16 == bpp) { *pSrcFormat =D3DFMT_A4R4G4B4; } else if (32 == bpp){ *pSrcFormat = D3DFMT_A8R8G8B8; } else { *pSrcFormat = D3DFMT_UNKNOWN; g_debug->header("The pixel format for the image could not be resolved correctly!" , 4); } } break; //FIXME: IND_LUMINANCE ignored? default: { *pSrcFormat = D3DFMT_UNKNOWN; g_debug->header("The pixel format for the image could not be resolved correctly!" , 4); } } //No conversions by DirectX *pDstFormat = *pSrcFormat; }
byte* LoadImage(const char* filename, uint* width, uint* height, uint* bits, bool flipY) { FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; FIBITMAP* dib = nullptr; fif = FreeImage_GetFileType(filename, 0); if (fif == FIF_UNKNOWN) fif = FreeImage_GetFIFFromFilename(filename); if (fif == FIF_UNKNOWN) return nullptr; if (FreeImage_FIFSupportsReading(fif)) dib = FreeImage_Load(fif, filename); SP_ASSERT(dib, "Could not load image '", filename, "'!"); FIBITMAP* bitmap = FreeImage_ConvertTo32Bits(dib); FreeImage_Unload(dib); byte* pixels = FreeImage_GetBits(bitmap); uint w = FreeImage_GetWidth(bitmap); uint h = FreeImage_GetHeight(bitmap); uint b = FreeImage_GetBPP(bitmap); if (flipY) FreeImage_FlipVertical(bitmap); if (FreeImage_GetRedMask(bitmap) == 0xff0000) SwapRedBlue32(bitmap); if (width) *width = w; if (height) *height = h; if (bits) *bits = b; int32 size = w * h * (b / 8); byte* result = spnew byte[size]; memcpy(result, pixels, size); FreeImage_Unload(bitmap); return result; }
void GLTexture2D::Load() { auto fileOptions = GetParameters(); auto filename = application->GetConfig().resourceBase + "/" + fileOptions[0]; if (!boost::filesystem::exists(filename)) { LOG(ERROR) << "File \"" << filename.c_str() << L"\" cannot be opened."; throw resource_loading_error() << ::boost::errinfo_file_name(filename) << resid_info(id) << errdesc_info("Cannot open include file."); } auto format = FreeImage_GetFileType(filename.c_str()); auto flags = 0; if (format == FIF_JPEG) { flags = JPEG_ACCURATE; } else if (format == FIF_TARGA) { flags = TARGA_LOAD_RGB888; } auto bitmap = FreeImage_Load(format, filename.c_str(), flags); auto bitmap32 = FreeImage_ConvertTo32Bits(bitmap); auto width = FreeImage_GetWidth(bitmap32); auto height = FreeImage_GetHeight(bitmap32); auto redMask = FreeImage_GetRedMask(bitmap32); auto greenMask = FreeImage_GetGreenMask(bitmap32); auto blueMask = FreeImage_GetBlueMask(bitmap32); void* data = FreeImage_GetBits(bitmap32); GLenum fmt = GL_RGBA; if (redMask > greenMask && greenMask > blueMask) fmt = GL_BGRA; auto internalFmt = GL_RGBA8; for (unsigned int i = 1; i < fileOptions.size(); ++i) { boost::trim(fileOptions[i]); if (fileOptions[i] == "sRGB" && application->GetConfig().useSRGB) internalFmt = GL_SRGB8_ALPHA8; } TextureDescriptor texDesc(4, internalFmt, fmt, GL_UNSIGNED_BYTE); texture = std::make_unique<GLTexture>(width, height, texDesc, data); FreeImage_Unload(bitmap32); FreeImage_Unload(bitmap); Resource::Load(); }
static void splitRGBAtoBitBlt(FIBITMAP * &image, FIBITMAP *&mask) { unsigned int img_w = FreeImage_GetWidth(image); unsigned int img_h = FreeImage_GetHeight(image); mask = FreeImage_AllocateT(FIT_BITMAP, img_w, img_h, FreeImage_GetBPP(image), FreeImage_GetRedMask(image), FreeImage_GetGreenMask(image), FreeImage_GetBlueMask(image)); RGBQUAD Fpix; RGBQUAD Npix = {0x0, 0x0, 0x0, 0xFF}; for(unsigned int y = 0; (y < img_h); y++) { for(unsigned int x = 0; (x < img_w); x++) { FreeImage_GetPixelColor(image, x, y, &Fpix); uint8_t grey = (255 - Fpix.rgbReserved); Npix.rgbRed = grey; Npix.rgbGreen= grey; Npix.rgbBlue = grey; Npix.rgbReserved = 255; Fpix.rgbRed = subtractAlpha(Fpix.rgbRed, grey); Fpix.rgbGreen= subtractAlpha(Fpix.rgbGreen, grey); Fpix.rgbBlue = subtractAlpha(Fpix.rgbBlue, grey); Fpix.rgbReserved = 255; FreeImage_SetPixelColor(image, x, y, &Fpix); FreeImage_SetPixelColor(mask, x, y, &Npix); } } }
static BOOL DLL_CALLCONV Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { if ((dib != NULL) && (handle != NULL)) { // write the file header BITMAPFILEHEADER bitmapfileheader; bitmapfileheader.bfType = 0x4D42; bitmapfileheader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + FreeImage_GetHeight(dib) * FreeImage_GetPitch(dib); bitmapfileheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + FreeImage_GetColorsUsed(dib) * sizeof(RGBQUAD); bitmapfileheader.bfReserved1 = 0; bitmapfileheader.bfReserved2 = 0; // take care of the bit fields data of any bool bit_fields = (FreeImage_GetBPP(dib) == 16); if (bit_fields) { bitmapfileheader.bfSize += 3 * sizeof(DWORD); bitmapfileheader.bfOffBits += 3 * sizeof(DWORD); } #ifdef FREEIMAGE_BIGENDIAN SwapFileHeader(&bitmapfileheader); #endif if (io->write_proc(&bitmapfileheader, sizeof(BITMAPFILEHEADER), 1, handle) != 1) return FALSE; // update the bitmap info header BITMAPINFOHEADER bih = *FreeImage_GetInfoHeader(dib); if (bit_fields) bih.biCompression = BI_BITFIELDS; else if ((bih.biBitCount == 8) && (flags & BMP_SAVE_RLE)) bih.biCompression = BI_RLE8; else bih.biCompression = BI_RGB; // write the bitmap info header #ifdef FREEIMAGE_BIGENDIAN SwapInfoHeader(&bih); #endif if (io->write_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle) != 1) return FALSE; // write the bit fields when we are dealing with a 16 bit BMP if (bit_fields) { DWORD d; d = FreeImage_GetRedMask(dib); if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1) return FALSE; d = FreeImage_GetGreenMask(dib); if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1) return FALSE; d = FreeImage_GetBlueMask(dib); if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1) return FALSE; } // write the palette if (FreeImage_GetPalette(dib) != NULL) { RGBQUAD *pal = FreeImage_GetPalette(dib); FILE_BGRA bgra; for(unsigned i = 0; i < FreeImage_GetColorsUsed(dib); i++ ) { bgra.b = pal[i].rgbBlue; bgra.g = pal[i].rgbGreen; bgra.r = pal[i].rgbRed; bgra.a = pal[i].rgbReserved; if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1) return FALSE; } } // write the bitmap data... if RLE compression is enable, use it unsigned bpp = FreeImage_GetBPP(dib); if ((bpp == 8) && (flags & BMP_SAVE_RLE)) { BYTE *buffer = new BYTE[FreeImage_GetPitch(dib) * 2]; for (DWORD i = 0; i < FreeImage_GetHeight(dib); ++i) { int size = RLEEncodeLine(buffer, FreeImage_GetScanLine(dib, i), FreeImage_GetLine(dib)); if (io->write_proc(buffer, size, 1, handle) != 1) { delete [] buffer; return FALSE; } } buffer[0] = RLE_COMMAND; buffer[1] = RLE_ENDOFBITMAP; if (io->write_proc(buffer, 2, 1, handle) != 1) { delete [] buffer; return FALSE; } delete [] buffer; #ifdef FREEIMAGE_BIGENDIAN } else if (bpp == 16) { WORD pixel; for(int y = 0; y < FreeImage_GetHeight(dib); y++) { BYTE *line = FreeImage_GetScanLine(dib, y); for(int x = 0; x < FreeImage_GetWidth(dib); x++) { pixel = ((WORD *)line)[x]; SwapShort(&pixel); if (io->write_proc(&pixel, sizeof(WORD), 1, handle) != 1) return FALSE; } } } else if (bpp == 24) { FILE_BGR bgr; for(int y = 0; y < FreeImage_GetHeight(dib); y++) { BYTE *line = FreeImage_GetScanLine(dib, y); for(int x = 0; x < FreeImage_GetWidth(dib); x++) { RGBTRIPLE *triple = ((RGBTRIPLE *)line)+x; bgr.b = triple->rgbtBlue; bgr.g = triple->rgbtGreen; bgr.r = triple->rgbtRed; if (io->write_proc(&bgr, sizeof(FILE_BGR), 1, handle) != 1) return FALSE; } } } else if (bpp == 32) { FILE_BGRA bgra; for(int y = 0; y < FreeImage_GetHeight(dib); y++) { BYTE *line = FreeImage_GetScanLine(dib, y); for(int x = 0; x < FreeImage_GetWidth(dib); x++) { RGBQUAD *quad = ((RGBQUAD *)line)+x; bgra.b = quad->rgbBlue; bgra.g = quad->rgbGreen; bgra.r = quad->rgbRed; bgra.a = quad->rgbReserved; if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1) return FALSE; } } #endif } else if (io->write_proc(FreeImage_GetBits(dib), FreeImage_GetHeight(dib) * FreeImage_GetPitch(dib), 1, handle) != 1) { return FALSE; } return TRUE; } else { return FALSE; } }
FIBITMAP * DLL_CALLCONV FreeImage_Clone(FIBITMAP *dib) { if(!dib) return NULL; unsigned width = FreeImage_GetWidth(dib); unsigned height = FreeImage_GetHeight(dib); unsigned bpp = FreeImage_GetBPP(dib); // allocate a new dib FIBITMAP *new_dib = FreeImage_AllocateT(FreeImage_GetImageType(dib), width, height, bpp, FreeImage_GetRedMask(dib), FreeImage_GetGreenMask(dib), FreeImage_GetBlueMask(dib)); if (new_dib) { // save ICC profile links FIICCPROFILE *src_iccProfile = FreeImage_GetICCProfile(dib); FIICCPROFILE *dst_iccProfile = FreeImage_GetICCProfile(new_dib); // save metadata links METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)dib->data)->metadata; METADATAMAP *dst_metadata = ((FREEIMAGEHEADER *)new_dib->data)->metadata; // calculate the size of a FreeImage image // align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary // palette is aligned on a 16 bytes boundary // pixels are aligned on a 16 bytes boundary unsigned dib_size = FreeImage_GetImageSize(width, height, bpp); // copy the bitmap + internal pointers (remember to restore new_dib internal pointers later) memcpy(new_dib->data, dib->data, dib_size); // reset ICC profile link for new_dib memset(dst_iccProfile, 0, sizeof(FIICCPROFILE)); // restore metadata link for new_dib ((FREEIMAGEHEADER *)new_dib->data)->metadata = dst_metadata; // copy possible ICC profile FreeImage_CreateICCProfile(new_dib, src_iccProfile->data, src_iccProfile->size); dst_iccProfile->flags = src_iccProfile->flags; // copy metadata models for(METADATAMAP::iterator i = (*src_metadata).begin(); i != (*src_metadata).end(); i++) { int model = (*i).first; TAGMAP *src_tagmap = (*i).second; if(src_tagmap) { // create a metadata model TAGMAP *dst_tagmap = new TAGMAP(); // fill the model for(TAGMAP::iterator j = src_tagmap->begin(); j != src_tagmap->end(); j++) { std::string dst_key = (*j).first; FITAG *dst_tag = FreeImage_CloneTag( (*j).second ); // assign key and tag value (*dst_tagmap)[dst_key] = dst_tag; } // assign model and tagmap (*dst_metadata)[model] = dst_tagmap; } } return new_dib; } return NULL; }
/* ================== Return OpenGL format and type depending on IndieLib defined quality and type This methot converts source image as needed ================== */ void OpenGLTextureBuilder::getGLFormat(IND_Surface *pNewSurface, IND_Image* pImage,GLint *pGLInternalFormat, GLint *pGLFormat, GLint *pGLType) { assert(pNewSurface); assert(pImage); assert(pGLFormat); assert(pGLType); if (!pGLFormat || !pGLType || !pNewSurface || !pImage) return; //TODO: Review image loading to support luminance+alpha. Now only supports Luminance without alpha int colorFormat = pImage->getFormatInt(); int bpp = pImage->getBpp(); //Check image color format switch (colorFormat) { case IND_LUMINANCE: //TODO: Other bpp *pGLInternalFormat = GL_LUMINANCE; *pGLFormat = GL_LUMINANCE; if (8 == bpp) { //No alpha channel by default pNewSurface->_surface->_attributes._type = IND_OPAQUE; //GL type *pGLType = GL_UNSIGNED_BYTE; } else if (16 == bpp) { //No alpha channel by default pNewSurface->_surface->_attributes._type = IND_OPAQUE; //GL types *pGLType = GL_UNSIGNED_SHORT_5_6_5; } else { *pGLInternalFormat = GL_NONE; *pGLFormat = GL_NONE; *pGLType = GL_NONE; g_debug->header("Not supported format of image! texture not loaded" , DebugApi::LogHeaderWarning); } break; case (IND_RGB): *pGLInternalFormat = GL_RGB; if (16 == bpp) { FIBITMAP* fib = pImage->getFreeImageHandle(); *pGLFormat = GL_RGB; //Check if 565 RGB if ((FreeImage_GetRedMask(fib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(fib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(fib) == FI16_565_BLUE_MASK)) { *pGLType = GL_UNSIGNED_SHORT_5_6_5; } else { *pGLInternalFormat = GL_NONE; *pGLFormat = GL_NONE; *pGLType = GL_NONE; g_debug->header("Not supported format of image! texture not loaded" , DebugApi::LogHeaderWarning); } } else if (32 == bpp) { //FreeImage loads channel order differently depending on processor endianess (24 and 32 bits). #if FI_RGBA_BLUE > FI_RGBA_RED *pGLFormat = GL_RGB; //Generally for MacOSX and Big Endian Linux / Unix #else *pGLFormat = GL_BGR; //Generally for Windows and Linux (little Endian) #endif *pGLType = GL_UNSIGNED_BYTE; } else { *pGLInternalFormat = GL_NONE; *pGLFormat = GL_NONE; *pGLType = GL_NONE; g_debug->header("Not supported format of image! texture not loaded" , DebugApi::LogHeaderWarning); } break; case (IND_RGBA): if (16 == bpp) { *pGLInternalFormat = GL_RGBA; *pGLFormat = GL_RGBA; *pGLType = GL_UNSIGNED_SHORT_4_4_4_4; } else if (32 == bpp) { *pGLInternalFormat = GL_RGBA; //FreeImage loads channel order differently depending on processor endianess (24 and 32 bits). #if FI_RGBA_BLUE > FI_RGBA_RED *pGLFormat = GL_RGBA; //Generally for MacOSX and Big Endian Linux / Unix #else *pGLFormat = GL_BGRA; //Generally for Windows and Linux (little Endian) #endif *pGLType = GL_UNSIGNED_BYTE; } else { *pGLInternalFormat = GL_NONE; *pGLFormat = GL_NONE; *pGLType = GL_NONE; g_debug->header("Not supported format of image! texture not loaded" , DebugApi::LogHeaderWarning); } break; case (IND_COLOUR_INDEX): default: *pGLInternalFormat = GL_NONE; *pGLFormat = GL_NONE; *pGLType = GL_NONE; g_debug->header("Not supported format of image! texture not loaded" , DebugApi::LogHeaderWarning); break; } }
FIBITMAP * DLL_CALLCONV FreeImage_Clone(FIBITMAP *dib) { if(!dib) { return NULL; } FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib); unsigned width = FreeImage_GetWidth(dib); unsigned height = FreeImage_GetHeight(dib); unsigned bpp = FreeImage_GetBPP(dib); const BYTE *ext_bits = ((FREEIMAGEHEADER *)dib->data)->external_bits; // check for pixel availability ... BOOL header_only = FreeImage_HasPixels(dib) ? FALSE : TRUE; // check whether this image has masks defined ... BOOL need_masks = (bpp == 16 && type == FIT_BITMAP) ? TRUE : FALSE; // allocate a new dib FIBITMAP *new_dib = FreeImage_AllocateHeaderT(header_only, type, width, height, bpp, FreeImage_GetRedMask(dib), FreeImage_GetGreenMask(dib), FreeImage_GetBlueMask(dib)); if (new_dib) { // save ICC profile links FIICCPROFILE *src_iccProfile = FreeImage_GetICCProfile(dib); FIICCPROFILE *dst_iccProfile = FreeImage_GetICCProfile(new_dib); // save metadata links METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)dib->data)->metadata; METADATAMAP *dst_metadata = ((FREEIMAGEHEADER *)new_dib->data)->metadata; // calculate the size of the src image // align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary // palette is aligned on a 16 bytes boundary // pixels are aligned on a 16 bytes boundary // when using a user provided pixel buffer, force a 'header only' calculation size_t dib_size = FreeImage_GetInternalImageSize(header_only || ext_bits, width, height, bpp, need_masks); // copy the bitmap + internal pointers (remember to restore new_dib internal pointers later) memcpy(new_dib->data, dib->data, dib_size); // reset ICC profile link for new_dib memset(dst_iccProfile, 0, sizeof(FIICCPROFILE)); // restore metadata link for new_dib ((FREEIMAGEHEADER *)new_dib->data)->metadata = dst_metadata; // reset thumbnail link for new_dib ((FREEIMAGEHEADER *)new_dib->data)->thumbnail = NULL; // copy possible ICC profile FreeImage_CreateICCProfile(new_dib, src_iccProfile->data, src_iccProfile->size); dst_iccProfile->flags = src_iccProfile->flags; // copy metadata models for(METADATAMAP::iterator i = (*src_metadata).begin(); i != (*src_metadata).end(); i++) { int model = (*i).first; TAGMAP *src_tagmap = (*i).second; if(src_tagmap) { // create a metadata model TAGMAP *dst_tagmap = new(std::nothrow) TAGMAP(); if(dst_tagmap) { // fill the model for(TAGMAP::iterator j = src_tagmap->begin(); j != src_tagmap->end(); j++) { std::string dst_key = (*j).first; FITAG *dst_tag = FreeImage_CloneTag( (*j).second ); // assign key and tag value (*dst_tagmap)[dst_key] = dst_tag; } // assign model and tagmap (*dst_metadata)[model] = dst_tagmap; } } } // copy the thumbnail FreeImage_SetThumbnail(new_dib, FreeImage_GetThumbnail(dib)); // copy user provided pixel buffer (if any) if(ext_bits) { const unsigned pitch = FreeImage_GetPitch(dib); const unsigned linesize = FreeImage_GetLine(dib); for(unsigned y = 0; y < height; y++) { memcpy(FreeImage_GetScanLine(new_dib, y), ext_bits, linesize); ext_bits += pitch; } } return new_dib; } return NULL; }
FIBITMAP* CResizeEngine::scale(FIBITMAP *src, unsigned dst_width, unsigned dst_height) { DWORD src_width = FreeImage_GetWidth(src); DWORD src_height = FreeImage_GetHeight(src); unsigned redMask = FreeImage_GetRedMask(src); unsigned greenMask = FreeImage_GetGreenMask(src); unsigned blueMask = FreeImage_GetBlueMask(src); unsigned bpp = FreeImage_GetBPP(src); FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); // allocate the dst image FIBITMAP *dst = FreeImage_AllocateT(image_type, dst_width, dst_height, bpp, redMask, greenMask, blueMask); if(!dst) return NULL; if(bpp == 8) { if(FreeImage_GetColorType(src) == FIC_MINISWHITE) { // build an inverted greyscale palette RGBQUAD *dst_pal = FreeImage_GetPalette(dst); for(int i = 0; i < 256; i++) { dst_pal[i].rgbRed = dst_pal[i].rgbGreen = dst_pal[i].rgbBlue = (BYTE)(255 - i); } } else { // build a greyscale palette RGBQUAD *dst_pal = FreeImage_GetPalette(dst); for(int i = 0; i < 256; i++) { dst_pal[i].rgbRed = dst_pal[i].rgbGreen = dst_pal[i].rgbBlue = (BYTE)i; } } } // decide which filtering order (xy or yx) is faster for this mapping by // counting convolution multiplies if(dst_width*src_height <= dst_height*src_width) { // xy filtering // ------------- // allocate a temporary image FIBITMAP *tmp = FreeImage_AllocateT(image_type, dst_width, src_height, bpp, redMask, greenMask, blueMask); if(!tmp) { FreeImage_Unload(dst); return NULL; } // scale source image horizontally into temporary image horizontalFilter(src, src_width, src_height, tmp, dst_width, src_height); // scale temporary image vertically into result image verticalFilter(tmp, dst_width, src_height, dst, dst_width, dst_height); // free temporary image FreeImage_Unload(tmp); } else { // yx filtering // ------------- // allocate a temporary image FIBITMAP *tmp = FreeImage_AllocateT(image_type, src_width, dst_height, bpp, redMask, greenMask, blueMask); if(!tmp) { FreeImage_Unload(dst); return NULL; } // scale source image vertically into temporary image verticalFilter(src, src_width, src_height, tmp, src_width, dst_height); // scale temporary image horizontally into result image horizontalFilter(tmp, src_width, dst_height, dst, dst_width, dst_height); // free temporary image FreeImage_Unload(tmp); } return dst; }
/** Scan input dib format and return the equivalent PKPixelFormatGUID format for saving @param dib Image to be saved @param guid_format (returned value) GUID format @param bHasAlpha (returned value) TRUE if an alpha layer is present @return Returns TRUE if successful, returns FALSE otherwise */ static ERR GetOutputPixelFormat(FIBITMAP *dib, PKPixelFormatGUID *guid_format, BOOL *bHasAlpha) { const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); const unsigned bpp = FreeImage_GetBPP(dib); const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib); *guid_format = GUID_PKPixelFormatDontCare; *bHasAlpha = FALSE; switch(image_type) { case FIT_BITMAP: // standard image : 1-, 4-, 8-, 16-, 24-, 32-bit switch(bpp) { case 1: // assume FIC_MINISBLACK if(color_type == FIC_MINISBLACK) { *guid_format = GUID_PKPixelFormatBlackWhite; } break; case 8: // assume FIC_MINISBLACK if(color_type == FIC_MINISBLACK) { *guid_format = GUID_PKPixelFormat8bppGray; } break; case 16: if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) { *guid_format = GUID_PKPixelFormat16bppRGB565; } else { // includes case where all the masks are 0 *guid_format = GUID_PKPixelFormat16bppRGB555; } break; #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR case 24: *guid_format = GUID_PKPixelFormat24bppBGR; break; case 32: *guid_format = GUID_PKPixelFormat32bppBGRA; *bHasAlpha = TRUE; break; #elif FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB case 24: *guid_format = GUID_PKPixelFormat24bppRGB; break; case 32: *guid_format = GUID_PKPixelFormat32bppRGBA; *bHasAlpha = TRUE; break; #endif case 4: default: // not supported break; } break; case FIT_UINT16: // array of unsigned short : unsigned 16-bit *guid_format = GUID_PKPixelFormat16bppGray; break; case FIT_FLOAT: // array of float : 32-bit IEEE floating point *guid_format = GUID_PKPixelFormat32bppGrayFloat; break; case FIT_RGB16: // 48-bit RGB image : 3 x 16-bit *guid_format = GUID_PKPixelFormat48bppRGB; break; case FIT_RGBA16: // 64-bit RGBA image : 4 x 16-bit *guid_format = GUID_PKPixelFormat64bppRGBA; *bHasAlpha = TRUE; break; case FIT_RGBF: // 96-bit RGB float image : 3 x 32-bit IEEE floating point *guid_format = GUID_PKPixelFormat96bppRGBFloat; break; case FIT_RGBAF: // 128-bit RGBA float image : 4 x 32-bit IEEE floating point *guid_format = GUID_PKPixelFormat128bppRGBAFloat; *bHasAlpha = TRUE; break; case FIT_INT16: // array of short : signed 16-bit case FIT_UINT32: // array of unsigned long : unsigned 32-bit case FIT_INT32: // array of long : signed 32-bit case FIT_DOUBLE: // array of double : 64-bit IEEE floating point case FIT_COMPLEX: // array of FICOMPLEX : 2 x 64-bit IEEE floating point default: // unsupported format break; } return (*guid_format != GUID_PKPixelFormatDontCare) ? WMP_errSuccess : WMP_errUnsupportedFormat; }