// 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::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 }