void storeFreeImage(const Ref<Image>& img, const FileName& fileName) { FIBITMAP* dib = FreeImage_Allocate((int)img->width, (int)img->height, 24); for(size_t y = 0; y < img->height; y++) { for(size_t x = 0; x < img->width; x++) { Color4 c = img->get(x, y); RGBQUAD Value = {0}; Value.rgbRed = (BYTE)(clamp(c.r) * 255.0f); Value.rgbGreen = (BYTE)(clamp(c.g) * 255.0f); Value.rgbBlue = (BYTE)(clamp(c.b) * 255.0f); FreeImage_SetPixelColor(dib, (unsigned int)x, (unsigned int)y, &Value); } } FIBITMAP* fiLogo = loadWatermark(); unsigned int LogoWidth = FreeImage_GetWidth (fiLogo); unsigned int LogoHeight = FreeImage_GetHeight(fiLogo); if(LogoWidth > img->width || LogoHeight > img->height) { FreeImage_Unload(fiLogo); FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(fileName.c_str()); if(FreeImage_FIFSupportsWriting(fif)) FreeImage_Save(fif, dib, fileName.c_str()); FreeImage_Unload(dib); } else { int x_pos = (int)img->width - LogoWidth; int y_pos = (int)img->height - LogoHeight; FIBITMAP* fiFG = FreeImage_Allocate((int)img->width, (int)img->height, 32); BOOL b = FreeImage_Paste(fiFG, fiLogo, x_pos, y_pos, 255); FreeImage_Unload(fiLogo); FIBITMAP* fiNew = FreeImage_Composite(fiFG, FALSE, NULL, dib); FreeImage_Unload(dib); FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(fileName.c_str()); int save_flags = 0; if(fif == FIF_JPEG) save_flags = JPEG_QUALITYSUPERB | JPEG_BASELINE | JPEG_OPTIMIZE; if(FreeImage_FIFSupportsWriting(fif)) FreeImage_Save(fif, fiNew, fileName.c_str(), save_flags); FreeImage_Unload(fiNew); } }
bool ImageLoaderFreeImage::loadInputImage(const QString &imageFileName, QString &errorMessage) { bool result = false; FreeImageErrorMessage.clear(); const FREE_IMAGE_FORMAT fileType = FreeImage_GetFileType(imageFileName.toAscii(), 0); FIBITMAP* newImage = FreeImage_Load(fileType, imageFileName.toAscii(), TIFF_CMYK|JPEG_CMYK); // Filter out images which FreeImage can load but not convert to Rgb24 // And images which we simply don't handle if (newImage) { const FREE_IMAGE_TYPE type = FreeImage_GetImageType(newImage); if (type != FIT_BITMAP // 1pbb Monochrome, 1-8bpp Palette, 8bpp Greyscale, // 24bpp Rgb, 32bpp Argb, 32bpp Cmyk && type != FIT_RGB16 // 16bpp Greyscale, 48bpp Rgb ) { FreeImage_Unload(newImage); newImage = NULL; } } if (newImage) { result = true; disposeImage(); m_bitmap = newImage; m_widthPixels = FreeImage_GetWidth(m_bitmap); m_heightPixels = FreeImage_GetHeight(m_bitmap); m_horizontalDotsPerMeter = FreeImage_GetDotsPerMeterX(m_bitmap); m_verticalDotsPerMeter = FreeImage_GetDotsPerMeterY(m_bitmap); if (m_horizontalDotsPerMeter == 0) m_horizontalDotsPerMeter = 2835; // 72 dpi if (m_verticalDotsPerMeter == 0) m_verticalDotsPerMeter = 2835; m_imageFileName = imageFileName; if (colorDataType() == Types::ColorTypeRGB && bitsPerPixel() == 32) { // Sometimes, there are strange .PSD images like this (FreeImage bug?) RGBQUAD white = { 255, 255, 255, 0 }; FIBITMAP *Image24Bit = FreeImage_Composite(m_bitmap, FALSE, &white); FreeImage_Unload(m_bitmap); m_bitmap = Image24Bit; } } errorMessage = FreeImageErrorMessage; return result; }
/* * Arguments: dest. dib_udata, foreground dib_udata, * [use_file_background (boolean), app_background_color (Color), * background dib_udata] * Returns: [dest. dib_udata] */ static int dib_composite (lua_State *L) { FIBITMAP **dibp = checkudata(L, 1, DIB_TYPENAME); FIBITMAP *fg_dib = lua_unboxpointer(L, 2, DIB_TYPENAME); const BOOL use_file_bkg = lua_toboolean(L, 3); RGBQUAD app_bkcolor; const int i = lua_isnoneornil(L, 4) ? 0 : (lfi_tocolor(L, 4, &app_bkcolor), 1); FIBITMAP *bg_dib = lua_isuserdata(L, 4 + i) ? lua_unboxpointer(L, 4 + i, DIB_TYPENAME) : NULL; *dibp = FreeImage_Composite(fg_dib, use_file_bkg, i ? &app_bkcolor : NULL, bg_dib); return dib_checkerror(L, *dibp); }
void fipWinImage::drawEx(HDC hDC, RECT& rcDest, BOOL useFileBkg, RGBQUAD *appBkColor, FIBITMAP *bg) const { // Convert to a standard bitmap if needed if(_bHasChanged) { if(_bDeleteMe) { FreeImage_Unload(_display_dib); _display_dib = NULL; _bDeleteMe = FALSE; } FREE_IMAGE_TYPE image_type = getImageType(); if(image_type == FIT_BITMAP) { BOOL bHasBackground = FreeImage_HasBackgroundColor(_dib); BOOL bIsTransparent = FreeImage_IsTransparent(_dib); if(!bIsTransparent && (!bHasBackground || !useFileBkg)) { // Copy pointer _display_dib = _dib; } else { // Create the transparent / alpha blended image _display_dib = FreeImage_Composite(_dib, useFileBkg, appBkColor, bg); if(_display_dib) { // Remember to delete _display_dib _bDeleteMe = TRUE; } else { // Something failed: copy pointers _display_dib = _dib; } } } else { // Convert to a standard dib for display if(image_type == FIT_COMPLEX) { // Convert to type FIT_DOUBLE FIBITMAP *dib_double = FreeImage_GetComplexChannel(_dib, FICC_MAG); // Convert to a standard bitmap (linear scaling) _display_dib = FreeImage_ConvertToStandardType(dib_double, TRUE); // Free image of type FIT_DOUBLE FreeImage_Unload(dib_double); } else if((image_type == FIT_RGBF) || (image_type == FIT_RGB16)) { // Apply a tone mapping algorithm and convert to 24-bit _display_dib = FreeImage_ToneMapping(_dib, _tmo, _tmo_param_1, _tmo_param_2); } else if(image_type == FIT_RGBA16) { // Convert to 32-bit FIBITMAP *dib32 = FreeImage_ConvertTo32Bits(_dib); if(dib32) { // Create the transparent / alpha blended image _display_dib = FreeImage_Composite(dib32, useFileBkg, appBkColor, bg); FreeImage_Unload(dib32); } } else { // Other cases: convert to a standard bitmap (linear scaling) _display_dib = FreeImage_ConvertToStandardType(_dib, TRUE); } // Remember to delete _display_dib _bDeleteMe = TRUE; } _bHasChanged = FALSE; } // Draw the dib SetStretchBltMode(hDC, COLORONCOLOR); StretchDIBits(hDC, rcDest.left, rcDest.top, rcDest.right-rcDest.left, rcDest.bottom-rcDest.top, 0, 0, FreeImage_GetWidth(_display_dib), FreeImage_GetHeight(_display_dib), FreeImage_GetBits(_display_dib), FreeImage_GetInfo(_display_dib), DIB_RGB_COLORS, SRCCOPY); }
static void *bg_next_frame(void *data) { struct imv_loader *ldr = data; pthread_mutex_lock(&ldr->lock); int num_frames = ldr->num_frames; if(num_frames < 2) { pthread_mutex_unlock(&ldr->lock); return NULL; } FITAG *tag = NULL; char disposal_method = 0; int frame_time = 0; short top = 0; short left = 0; ldr->cur_frame = ldr->next_frame; ldr->next_frame = (ldr->cur_frame + 1) % ldr->num_frames; FIBITMAP *frame = FreeImage_LockPage(ldr->mbmp, ldr->cur_frame); FIBITMAP *frame32 = FreeImage_ConvertTo32Bits(frame); /* First frame is always going to use the raw frame */ if(ldr->cur_frame > 0) { FreeImage_GetMetadata(FIMD_ANIMATION, frame, "DisposalMethod", &tag); if(FreeImage_GetTagValue(tag)) { disposal_method = *(char*)FreeImage_GetTagValue(tag); } } FreeImage_GetMetadata(FIMD_ANIMATION, frame, "FrameLeft", &tag); if(FreeImage_GetTagValue(tag)) { left = *(short*)FreeImage_GetTagValue(tag); } FreeImage_GetMetadata(FIMD_ANIMATION, frame, "FrameTop", &tag); if(FreeImage_GetTagValue(tag)) { top = *(short*)FreeImage_GetTagValue(tag); } FreeImage_GetMetadata(FIMD_ANIMATION, frame, "FrameTime", &tag); if(FreeImage_GetTagValue(tag)) { frame_time = *(int*)FreeImage_GetTagValue(tag); } /* some gifs don't provide a frame time at all */ if(frame_time == 0) { frame_time = 100; } ldr->frame_time += frame_time * 0.001; FreeImage_UnlockPage(ldr->mbmp, frame, 0); /* If this frame is inset, we need to expand it for compositing */ if(ldr->width != (int)FreeImage_GetWidth(frame32) || ldr->height != (int)FreeImage_GetHeight(frame32)) { FIBITMAP *expanded = FreeImage_Allocate(ldr->width, ldr->height, 32, 0,0,0); FreeImage_Paste(expanded, frame32, left, top, 255); FreeImage_Unload(frame32); frame32 = expanded; } switch(disposal_method) { case 0: /* nothing specified, fall through to compositing */ case 1: /* composite over previous frame */ if(ldr->bmp && ldr->cur_frame > 0) { FIBITMAP *bg_frame = FreeImage_ConvertTo24Bits(ldr->bmp); FreeImage_Unload(ldr->bmp); FIBITMAP *comp = FreeImage_Composite(frame32, 1, NULL, bg_frame); FreeImage_Unload(bg_frame); FreeImage_Unload(frame32); ldr->bmp = comp; } else { /* No previous frame, just render directly */ if(ldr->bmp) { FreeImage_Unload(ldr->bmp); } ldr->bmp = frame32; } break; case 2: /* TODO - set to background, composite over that */ if(ldr->bmp) { FreeImage_Unload(ldr->bmp); } ldr->bmp = frame32; break; case 3: /* TODO - restore to previous content */ if(ldr->bmp) { FreeImage_Unload(ldr->bmp); } ldr->bmp = frame32; break; } if(ldr->out_bmp) { FreeImage_Unload(ldr->out_bmp); } ldr->out_bmp = FreeImage_Clone(ldr->bmp); pthread_mutex_unlock(&ldr->lock); return NULL; }
// parsePNGFile() // Takes in a PNG file and plugs the indexes into // the proper art format. static bool parsePNGFile(uint32_t pngi, FILE* afile) { FILE* pngfile; char pngfilename[FILENAME_MAX]; uint8_t* buffer; uint32_t xsize, ysize; int32_t xi, yi; FIBITMAP *pngas; FIBITMAP *pngaspal; FIBITMAP *pngasbg; FIBITMAP *pngas24; FIBITMAP *pngastemp; uint32_t m; uint32_t n; uint32_t _px; uint32_t* _pbx; pngi; TilesList[pngi].animdata = 0; TilesList[pngi].offset = ftell(afile); TilesList[pngi].sizex = 0; TilesList[pngi].sizey = 0; sprintf(pngfilename, "%s%stile%04u.png", inputdir, PATH_DELIMITER, pngi); pngastemp = FreeImage_Load(FIF_PNG, pngfilename, 0); if (pngastemp == NULL) return false; pngas = FreeImage_AllocateEx(FreeImage_GetWidth(pngastemp), FreeImage_GetHeight(pngastemp), 8, &rgbpal[255], 0, rgbpal, 0, 0, 0); FreeImage_FlipVertical(pngastemp); if (FreeImage_GetBPP(pngastemp) != 8) { // printf("ssssnaaaaoooo\n"); if (FreeImage_GetBPP(pngastemp) == 32) { pngasbg = FreeImage_Composite(pngastemp, FALSE, &rgbpal[255], NULL); // pngas24 = FreeImage_ConvertTo24Bits(pngasbg); pngaspal = FreeImage_ColorQuantizeEx(pngasbg, FIQ_NNQUANT, 256, 256, rgbpal); FreeImage_SetTransparentIndex(pngaspal, 255); } else { pngaspal = FreeImage_ColorQuantizeEx(pngastemp, FIQ_NNQUANT, 256, 256, rgbpal); FreeImage_SetTransparentIndex(pngaspal, 255); } if (pngaspal == NULL) { printf("error: tile%04u.png is an invalid 8/24/32bit image\n", pngi); return false; } pngas = pngaspal; } else { pngas = pngastemp; } xsize = FreeImage_GetWidth(pngas); ysize = FreeImage_GetHeight(pngas); TilesList[pngi].sizex = xsize; TilesList[pngi].sizey = ysize; buffer = malloc(xsize * ysize); if (buffer == NULL) { printf("error: not enough memory to read image\n"); return false; } // This is where the magic happens for (xi = 0; xi < TilesList[pngi].sizex; xi++) { for (yi = 0; yi < TilesList[pngi].sizey; yi++) { FreeImage_GetPixelIndex(pngas, xi, yi, &buffer[xi * TilesList[pngi].sizey + yi]); fwrite(&buffer[xi * TilesList[pngi].sizey + yi], 1, 1, afile); } } free(buffer); // Gotta free memory explicitly return true; }