void FreeImageGifData::add24bitBGRDataPage(int width, int height, BYTE* pData) { FIBITMAP* newBitmap = FreeImage_Allocate(width, height, 24, 0x0000FF, 0x00FF00, 0xFF0000); BYTE* bitmapData = FreeImage_GetBits(newBitmap); memcpy(bitmapData, pData, width * height * 3); //Set metadata FIBITMAP* convBitmap = FreeImage_ColorQuantizeEx(newBitmap, FIQ_WUQUANT, 256); FITAG* delayTag = FreeImage_CreateTag(); FreeImage_SetMetadata(FIMD_ANIMATION, convBitmap, NULL, NULL); LONG delayVal = 20; if (delayTag) { FreeImage_SetTagKey(delayTag, "FrameTime"); FreeImage_SetTagType(delayTag, FIDT_LONG); FreeImage_SetTagCount(delayTag, 1); FreeImage_SetTagLength(delayTag, 4); FreeImage_SetTagValue(delayTag, &delayVal); FreeImage_SetMetadata(FIMD_ANIMATION, convBitmap, FreeImage_GetTagKey(delayTag), delayTag); FreeImage_DeleteTag(delayTag); } FreeImage_AppendPage(m_gifHandle, convBitmap); int pCount = FreeImage_GetPageCount(m_gifHandle); FreeImage_Unload(newBitmap); FreeImage_Unload(convBitmap); }
void ofxGifEncoder::doSave() { // create a multipage bitmap FIMULTIBITMAP *multi = FreeImage_OpenMultiBitmap(FIF_GIF, ofToDataPath(fileName).c_str(), TRUE, FALSE); FIBITMAP * bmp = NULL; for(int i = 0; i < frames.size(); i++ ) { // we need to swap the channels if we're on little endian (see ofImage::swapRgb); #ifdef TARGET_LITTLE_ENDIAN swapRgb(frames[i]); #endif // get the pixel data bmp = FreeImage_ConvertFromRawBits( frames[i]->pixels, frames[i]->width, frames[i]->height, frames[i]->width*(frames[i]->bitsPerPixel/8), frames[i]->bitsPerPixel, 0, 0, 0, true // in of006 this (topdown) had to be false. ); #ifdef TARGET_LITTLE_ENDIAN swapRgb(frames[i]); #endif DWORD frameDuration = (DWORD) (frames[i]->duration * 1000.f); bmp = FreeImage_ColorQuantizeEx(bmp, FIQ_NNQUANT, nColors); // dithering :) if(ditherMode > OFX_GIF_DITHER_NONE) bmp = FreeImage_Dither(bmp, (FREE_IMAGE_DITHER)ditherMode); // clear any animation metadata used by this dib as we’ll adding our own ones FreeImage_SetMetadata(FIMD_ANIMATION, bmp, NULL, NULL); // add animation tags to dib[i] FITAG *tag = FreeImage_CreateTag(); if(tag) { FreeImage_SetTagKey(tag, "FrameTime"); FreeImage_SetTagType(tag, FIDT_LONG); FreeImage_SetTagCount(tag, 1); FreeImage_SetTagLength(tag, 4); FreeImage_SetTagValue(tag, &frameDuration); FreeImage_SetMetadata(FIMD_ANIMATION, bmp, FreeImage_GetTagKey(tag), tag); FreeImage_DeleteTag(tag); } FreeImage_AppendPage(multi, bmp); } FreeImage_Unload(bmp); FreeImage_CloseMultiBitmap(multi); }
ColorQuantize(PClip originClip, int paletteSize, bool useGlobalPalette, FREE_IMAGE_QUANTIZE algorithm, const char *globalPaletteOutputFile, IScriptEnvironment* env) : m_origin(originClip) , m_paletteSize(paletteSize) , m_useGlobalPalette(useGlobalPalette) , m_algorithm(algorithm) , m_targetVideoInfo(originClip->GetVideoInfo()) , m_globalPalette(0) { if (!originClip->GetVideoInfo().IsRGB24()) { m_originRgb = env->Invoke("ConvertToRgb24", originClip).AsClip(); m_targetVideoInfo.pixel_type = VideoInfo::CS_BGR24; } else { m_originRgb = originClip; } if (m_useGlobalPalette) { FIBITMAP *hugeImage = FreeImage_Allocate(m_targetVideoInfo.width, m_targetVideoInfo.height * m_targetVideoInfo.num_frames, 24); for (int frame = 0; frame < m_targetVideoInfo.num_frames; ++frame) { const PVideoFrame videoFrame = m_originRgb->GetFrame(frame, env); copyVideoFrameToImage(m_originRgb->GetFrame(frame, env),hugeImage, frame * m_targetVideoInfo.height); } FIBITMAP *quantizedImage = FreeImage_ColorQuantizeEx(hugeImage, algorithm, m_paletteSize); FreeImage_Unload(hugeImage); m_globalPalette = new RGBQUAD[m_paletteSize]; memcpy(m_globalPalette, FreeImage_GetPalette(quantizedImage), m_paletteSize * sizeof(RGBQUAD)); FreeImage_Unload(quantizedImage); if (globalPaletteOutputFile) savePaletteImage(globalPaletteOutputFile, m_globalPalette, m_paletteSize); } }
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) { PVideoFrame dst = env->NewVideoFrame(m_targetVideoInfo); unsigned char* const dstp = dst->GetWritePtr(); FIBITMAP *frameImage = FreeImage_Allocate(m_targetVideoInfo.width, m_targetVideoInfo.height, 24); copyVideoFrameToImage(m_originRgb->GetFrame(n, env), frameImage); const int reservedPaletteSize = m_useGlobalPalette ? m_paletteSize : 0; FIBITMAP *quantizedFrameImage = FreeImage_ColorQuantizeEx(frameImage, FIQ_NNQUANT, m_paletteSize, reservedPaletteSize, m_globalPalette); FreeImage_Unload(frameImage); FIBITMAP *quantizedFrameImageRgb24 = FreeImage_ConvertTo24Bits(quantizedFrameImage); FreeImage_Unload(quantizedFrameImage); for (int row = 0; row < m_targetVideoInfo.height; ++row) { unsigned char* dstrowp = dstp + row * dst->GetPitch(); const BYTE* const srcp = FreeImage_GetScanLine(quantizedFrameImageRgb24, row); memcpy(dstrowp, srcp, dst->GetRowSize()); } FreeImage_Unload(quantizedFrameImageRgb24); return dst; }
// 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; }
//-------------------------------------------------------------- void ofxGifEncoder::save (vector <ofxGifFrame *> frames, string fileName, int nColors) { if (nColors < 2 || nColors > 256) { ofLog(OF_LOG_WARNING, "nColors must be between 2 and 256. your gif won't be saved"); return; } // create a multipage bitmap FIMULTIBITMAP *multi = FreeImage_OpenMultiBitmap(FIF_GIF, ofToDataPath(fileName).c_str(), TRUE, FALSE); FIBITMAP * bmp = NULL; for(int i = 0; i < frames.size(); i++ ) { // we need to swap the channels if we're on little endian (see ofImage::swapRgb); #ifdef TARGET_LITTLE_ENDIAN swapRgb(frames[i]); #endif // get the pixel data bmp = FreeImage_ConvertFromRawBits( frames[i]->pixels, frames[i]->width, frames[i]->height, frames[i]->width*(frames[i]->bitsPerPixel/8), frames[i]->bitsPerPixel, 0, 0, 0, true // in of006 this (topdown) had to be false. ); #ifdef TARGET_LITTLE_ENDIAN swapRgb(frames[i]); #endif DWORD frameDuration = (DWORD) frames[i]->duration * 1000.f; // bmp = FreeImage_ColorQuantize(bmp, FIQ_NNQUANT); // if we want to set a reduced color palette (2 to 256); bmp = FreeImage_ColorQuantizeEx(bmp, FIQ_NNQUANT, nColors); // dithering :) // you can set a different dither pattern for each frame // bmp = FreeImage_Dither(bmp, (FREE_IMAGE_DITHER)((i+1)%6)); //bmp = FreeImage_Dither(bmp, FID_BAYER8x8); // clear any animation metadata used by this dib as we’ll adding our own ones FreeImage_SetMetadata(FIMD_ANIMATION, bmp, NULL, NULL); // add animation tags to dib[i] FITAG *tag = FreeImage_CreateTag(); if(tag) { FreeImage_SetTagKey(tag, "FrameTime"); FreeImage_SetTagType(tag, FIDT_LONG); FreeImage_SetTagCount(tag, 1); FreeImage_SetTagLength(tag, 4); FreeImage_SetTagValue(tag, &frameDuration); FreeImage_SetMetadata(FIMD_ANIMATION, bmp, FreeImage_GetTagKey(tag), tag); FreeImage_DeleteTag(tag); } FreeImage_AppendPage(multi, bmp); } FreeImage_Unload(bmp); FreeImage_CloseMultiBitmap(multi); }
void ofxGifEncoder::processFrame(ofxGifFrame * frame, FIMULTIBITMAP *multi){ FIBITMAP * bmp = NULL; // we need to swap the channels if we're on little endian (see ofImage::swapRgb); if (frame->bitsPerPixel ==32){ ofLog() << "image is transaprent!"; frame = convertTo24BitsWithGreenScreen(frame); } #ifdef TARGET_LITTLE_ENDIAN swapRgb(frame); #endif // from here on, we can only deal with 24 bits // get the pixel data bmp = FreeImage_ConvertFromRawBits( frame->pixels, frame->width, frame->height, frame->width*(frame->bitsPerPixel/8), frame->bitsPerPixel, 0, 0, 0, true // in of006 this (topdown) had to be false. ); FIBITMAP * bmpConverted; #ifdef TARGET_LITTLE_ENDIAN swapRgb(frame); #endif FIBITMAP * quantizedBmp = NULL; FIBITMAP * ditheredBmp = NULL; FIBITMAP * processedBmp = NULL; quantizedBmp = FreeImage_ColorQuantizeEx(bmp, FIQ_WUQUANT, nColors); processedBmp = quantizedBmp; if (nChannels == 4){ calculatePalette(processedBmp); FreeImage_SetTransparentIndex(processedBmp,getClosestToGreenScreenPaletteColorIndex()); } // dithering :) if(ditherMode > OFX_GIF_DITHER_NONE) { ditheredBmp = FreeImage_Dither(processedBmp, (FREE_IMAGE_DITHER)ditherMode); processedBmp = ditheredBmp; } DWORD frameDuration = (DWORD) (frame->duration * 1000.f); // clear any animation metadata used by this dib as we’ll adding our own ones FreeImage_SetMetadata(FIMD_ANIMATION, processedBmp, NULL, NULL); // add animation tags to dib[frameNum] FITAG *tag = FreeImage_CreateTag(); if(tag) { FreeImage_SetTagKey(tag, "FrameTime"); FreeImage_SetTagType(tag, FIDT_LONG); FreeImage_SetTagCount(tag, 1); FreeImage_SetTagLength(tag, 4); FreeImage_SetTagValue(tag, &frameDuration); FreeImage_SetMetadata(FIMD_ANIMATION, processedBmp, FreeImage_GetTagKey(tag), tag); FreeImage_DeleteTag(tag); } FreeImage_AppendPage(multi, processedBmp); // clear freeimage stuff if(bmp != NULL) FreeImage_Unload(bmp); if(quantizedBmp != NULL) FreeImage_Unload(quantizedBmp); if(ditheredBmp != NULL) FreeImage_Unload(ditheredBmp); // no need to unload processedBmp, as it points to either of the above }