bitmap_ptr finalize(bool showProgress = true) { if (chunks.empty()) { return nullptr; } if (showProgress) { std::cout << "Adding all accepted chunks to the final image\n"; } const auto it = chunks.begin(); bitmap_ptr firstChunk = GenericLoader(*it); auto currentHeight = 0; const auto type = FreeImage_GetImageType(firstChunk.get()); const auto bpp = FreeImage_GetBPP(firstChunk.get()); bitmap_ptr finalImage(FreeImage_AllocateT(type, width, height, bpp)); auto RGBChunkWorker = [=, &finalImage, ¤tHeight](const std::string& el) { bitmap_ptr chunk = GenericLoader(el); auto chunkHeight = FreeImage_GetHeight(chunk.get()); auto chunk_img = FreeImage_Copy(chunk.get(), 0, 0, this->width, chunkHeight); if (chunk_img) { FreeImage_Paste(finalImage.get(), chunk_img, 0, currentHeight, 256); } currentHeight += chunkHeight; }; std::for_each(chunks.begin(), chunks.end(), RGBChunkWorker); return finalImage; }
/** Poisson solver based on a multigrig algorithm. This routine solves a Poisson equation, remap result pixels to [0..1] and returns the solution. NB: The input image is first stored inside a square image whose size is (2^j + 1)x(2^j + 1) for some integer j, where j is such that 2^j is the nearest larger dimension corresponding to MAX(image width, image height). @param Laplacian Laplacian image @param ncycle Number of cycles in the multigrid algorithm (usually 2 or 3) @return Returns the solved PDE equations if successful, returns NULL otherwise */ FIBITMAP* DLL_CALLCONV FreeImage_MultigridPoissonSolver(FIBITMAP *Laplacian, int ncycle) { if(!Laplacian) return NULL; int width = FreeImage_GetWidth(Laplacian); int height = FreeImage_GetHeight(Laplacian); // get nearest larger dimension length that is acceptable by the algorithm int n = MAX(width, height); int size = 0; while((n >>= 1) > 0) size++; // size must be of the form 2^j + 1 for some integer j size = 1 + (1 << (size + 1)); // allocate a temporary square image I FIBITMAP *I = FreeImage_AllocateT(FIT_FLOAT, size, size); if(!I) return NULL; // copy Laplacian into I and shift pixels to create a boundary FreeImage_Paste(I, Laplacian, 1, 1, 255); // solve the PDE equation fmg_mglin(I, size, ncycle); // shift pixels back FIBITMAP *U = FreeImage_Copy(I, 1, 1, width + 1, height + 1); FreeImage_Unload(I); // remap pixels to [0..1] NormalizeY(U, 0, 1); // return the integrated image return U; }
BOOL fipImage::pasteSubImage(fipImage& src, int left, int top, int alpha) { if(_dib) { BOOL bResult = FreeImage_Paste(_dib, src._dib, left, top, alpha); _bHasChanged = TRUE; return bResult; } return FALSE; }
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); } }
/* * Arguments: dest. dib_udata, source dib_udata, * left (number), top (number), alpha (number) * Returns: [dest. dib_udata] */ static int dib_paste (lua_State *L) { FIBITMAP *dst_dib = lua_unboxpointer(L, 1, DIB_TYPENAME); FIBITMAP *src_dib = lua_unboxpointer(L, 2, DIB_TYPENAME); const int left = lua_tointeger(L, 3); const int top = lua_tointeger(L, 4); const int alpha = lua_tointeger(L, 5); return dib_checkerror(L, FreeImage_Paste(dst_dib, src_dib, left, top, alpha) ? dst_dib : NULL); }
FIBITMAP * gifcat(char gifpath[MAXGIFCOUNT][MAXPATHCHAR], unsigned gifPathCount) // 将多张图片连接为一张图片 { FIBITMAP * hImageAll ; unsigned ImgHeightAll = 0 ; FIBITMAP * hImage[MAXGIFCOUNT] ; unsigned ImgHeight[MAXGIFCOUNT] ; unsigned ImgWidth ; RGBQUAD * palSrc ; RGBQUAD * palAll ; unsigned n , NowYPos = 0 ; // --- for ( n=0; n < gifPathCount; ++n) { hImage[n] = FreeImage_Load(FIF_GIF, gifpath[n], 0); ImgHeight[n] = FreeImage_GetHeight(hImage[n]) ; ImgHeightAll += ImgHeight[n] ; } ImgWidth = FreeImage_GetWidth(hImage[0]) ; hImageAll = FreeImage_Allocate(ImgWidth, ImgHeightAll, 8, 0, 0, 0); //创建目标图像 palAll = FreeImage_GetPalette(hImageAll); // 复制调色板 palSrc = FreeImage_GetPalette(hImage[0]); for (n = 0; n < 256; ++n) { palAll[n].rgbRed = palSrc[n].rgbRed ; palAll[n].rgbGreen = palSrc[n].rgbGreen ; palAll[n].rgbBlue = palSrc[n].rgbBlue ; } palAll[70].rgbRed = 255 ; palAll[70].rgbGreen = 255 ; palAll[70].rgbBlue = 255 ; for ( n=0; n < gifPathCount; ++n) { // 粘贴图像 FreeImage_Paste(hImageAll, hImage[n], 0, NowYPos, 300) ; NowYPos += ImgHeight[n] ; FreeImage_Unload(hImage[n]) ; } return hImageAll ; }
void Image::_load(string sFilename) { errlog << "Load " << sFilename << endl; //image format FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; //pointer to the image, once loaded FIBITMAP *dib(0); //pointer to the image data BYTE* bits(0); //image width and height unsigned int width(0), height(0); //check the file signature and deduce its format fif = FreeImage_GetFileType(sFilename.c_str(), 0); //if still unknown, try to guess the file format from the file extension if(fif == FIF_UNKNOWN) fif = FreeImage_GetFIFFromFilename(sFilename.c_str()); //if still unkown, return failure if(fif == FIF_UNKNOWN) { errlog << "Unknown image type for file " << sFilename << endl; return; } //check that the plugin has reading capabilities and load the file if(FreeImage_FIFSupportsReading(fif)) dib = FreeImage_Load(fif, sFilename.c_str()); else errlog << "File " << sFilename << " doesn't support reading." << endl; //if the image failed to load, return failure if(!dib) { errlog << "Error loading image " << sFilename.c_str() << endl; return; } //retrieve the image data //get the image width and height width = FreeImage_GetWidth(dib); height = FreeImage_GetHeight(dib); int w = power_of_two(width); int h = power_of_two(height); int mode, modeflip; if(FreeImage_GetBPP(dib) == 24) // RGB 24bit { mode = GL_RGB; modeflip = GL_BGR; } else if(FreeImage_GetBPP(dib) == 32) // RGBA 32bit { mode = GL_RGBA; modeflip = GL_BGRA; } FIBITMAP *bitmap2 = FreeImage_Allocate(w, h, FreeImage_GetBPP(dib)); FreeImage_Paste(bitmap2, dib, 0, 0, 255); FreeImage_FlipVertical(bitmap2); //Apparently, FreeImage handles this strangely. Flipping beforehand doesn't work right. FreeImage_Unload(dib); bits = FreeImage_GetBits(bitmap2); //if this somehow one of these failed (they shouldn't), return failure if((bits == 0) || (width == 0) || (height == 0)) { errlog << "Something went terribly horribly wrong with getting image bits; just sit and wait for the singularity" << endl; return; } //generate an OpenGL texture ID for this texture m_iWidth = width; m_iHeight = height; m_iRealWidth = w; m_iRealHeight = h; glGenTextures(1, &m_hTex); //bind to the new texture ID glBindTexture(GL_TEXTURE_2D, m_hTex); //store the texture data for OpenGL use glTexImage2D(GL_TEXTURE_2D, 0, mode, w, h, 0, modeflip, GL_UNSIGNED_BYTE, bits); //Free FreeImage's copy of the data FreeImage_Unload(bitmap2); }
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; }
FOX_DLL unsigned gifsplit(char * pngprefix, char gifpath[MAXGIFCOUNT][MAXPATHCHAR], unsigned gifPathCount, unsigned ScreenWidth, unsigned ScreenHeight, unsigned bSaveToBuff, FIBITMAP * hImageList[MAXOUTBUFCOUNT]) // 1 base count { // ------ 声明开始 // FIBITMAP * hImageList[MAXOUTBUFCOUNT] ; // 输出 himage 数组, 首元素包含数组长度 FIBITMAP * hPicTemplete; FIBITMAP * hImage ; FIBITMAP * hPicBlank; BYTE * pBit ; unsigned ImgPitch, ImgWidth, ImgHeight ; char pathPNG[MAXPATHCHAR]; unsigned n; // ylist unsigned xsplitcount = 0 ; // X 切割份数 POSLIST ylist[MAXYLIST] ; unsigned TextLineCount = 0 ; // Y 切割份数 LineLR yinfo[MAXYLIST] ; unsigned StartX, EndX ; // joblist JOBLIST joblist[MAXJOBLIST] ; unsigned NowJobCount ; // joblist item count unsigned nNewPicCount = 0 ; // ------- 语句开始 hImage = gifcat(gifpath, gifPathCount) ; // 将多张图片连接为一张图片 hPicTemplete = CreateTemplete(hImage, ScreenWidth, ScreenHeight) ; // 创建空白PNG模版 ImgWidth = FreeImage_GetWidth(hImage) ; ImgHeight = FreeImage_GetHeight(hImage) ; ImgPitch = FreeImage_GetPitch(hImage) ; pBit = FreeImage_GetBits(hImage) ; TextLineCount = GetYList(ylist , pBit , ImgPitch, ImgWidth, ImgHeight) ; // 获取 Y 分割列表 StartX = GetLeftBorderX(0, ImgWidth, 0, ImgHeight, pBit, ImgPitch) ; EndX = GetRightBorderX(ImgWidth - 1, ImgWidth, 0, ImgHeight, pBit, ImgPitch) ; yinfo[0].left = StartX ; yinfo[0].right = EndX ; GetLineBorder(yinfo, ylist, TextLineCount, pBit, ImgPitch, ImgWidth, ImgHeight) ; // 每行左右坐标 yinfo[TextLineCount].left = StartX ; yinfo[TextLineCount].right = EndX ; NowJobCount = NewGetJobList(joblist, yinfo, ylist, TextLineCount, ScreenWidth, ScreenHeight, ImgWidth, ImgHeight, pBit, ImgPitch, bSaveToBuff) ; // 新版任务列表,只根据屏幕宽度取X坐标,不固定 // 根据joblist 来生成 png for (n = 0; n < NowJobCount; n++) { // printf("任务编号: %d , A: %d , L: %d , R: %d , T: %d , B: %d , nL: %d , nT: %d, R-L: %d\n", n, joblist[n].action, joblist[n].left, joblist[n].right, joblist[n].top, joblist[n].bottom, joblist[n].newleft, joblist[n].newtop, joblist[n].right - joblist[n].left) ; // 调试用 if ( ( joblist[n].action >= 1 ) && ( joblist[n].action != 5 ) ) hPicBlank = FreeImage_Clone(hPicTemplete); FreeImage_Paste(hPicBlank, FreeImage_Copy(hImage, joblist[n].left, joblist[n].top, joblist[n].right, joblist[n].bottom), joblist[n].newleft, joblist[n].newtop, 300); if ( joblist[n].action >= 5 ) { ++nNewPicCount ; sprintf(pathPNG, "%s%03d.png", pngprefix, nNewPicCount) ; printf("生成PNG %d : %s\n", nNewPicCount , pathPNG) ; if ( bSaveToBuff == 1 ) { // 输出到buff hImageList[nNewPicCount-1] = hPicBlank ; } else { // 输出到文件 FreeImage_Save(FIF_PNG, hPicBlank, pathPNG) ; FreeImage_Unload(hPicBlank) ; } } } return nNewPicCount; }
/** * Alpha blend or combine a sub part image with the current dib image. * For images of type FITBITMAP only: The bit depth of the dst bitmap must be greater than or * equal to the bit depth of the src. Upper promotion of src is done internally, without modifying * src. Supported dst bit depth equals to 1, 4, 8, 16, 24 or 32. * * For any other image type: The image type of the dst bitmap must be equal to the image type * of the src. The alpha parameter is always ignored and the source image is combined to the * destination image. * * The function returns TRUE if successful, FALSE otherwise (including if the one or both images is not loaded). * @param pIm Pointer to an image object, that is going to be pasted (Alpha blended and/or combined with the current image) * @param pX X Coordenate * @param pY Y Coordenate * @param pAlpha Alpha value on the destination image */ bool IND_Image::pasteImage(IND_Image *pIm, int pX, int pY, int pAlpha) { // No image loaded if (!isImageLoaded() || !pIm->isImageLoaded()) return false; return FreeImage_Paste(getFreeImageHandle(), pIm->getFreeImageHandle(), pX, pY, pAlpha) != 0; }
void poImage::composite(poImage *img, poPoint into, float blend) { FreeImage_Paste(bitmap, img->bitmap, into.x, into.y, blend*256); }