//---------------------------------------------------------------- void ofImage::saveImageFromPixels(string fileName, ofPixels &pix){ if (pix.bAllocated == false){ ofLog(OF_LOG_ERROR,"error saving image - pixels aren't allocated"); return; } #ifdef TARGET_LITTLE_ENDIAN if (pix.bytesPerPixel != 1) swapRgb(pix); #endif FIBITMAP * bmp = getBmpFromPixels(pix); #ifdef TARGET_LITTLE_ENDIAN if (pix.bytesPerPixel != 1) swapRgb(pix); #endif fileName = ofToDataPath(fileName); if (pix.bAllocated == true){ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; fif = FreeImage_GetFileType(fileName.c_str(), 0); if(fif == FIF_UNKNOWN) { // or guess via filename fif = FreeImage_GetFIFFromFilename(fileName.c_str()); } if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) { FreeImage_Save(fif, bmp, fileName.c_str(), 0); } } if (bmp != NULL){ FreeImage_Unload(bmp); } }
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); }
//------------------------------------ void ofImage::setFromPixels(unsigned char * newPixels, int w, int h, int newType, bool bOrderIsRGB){ if (!myPixels.bAllocated){ allocate(w, h, newType); } if (!((width == w) && (height == h) && (type == newType))){ bool bCacheBUseTexture = bUseTexture; clear(); bUseTexture = bCacheBUseTexture; allocate(w,h, newType); } int newBpp = 0; switch (type){ case OF_IMAGE_GRAYSCALE: newBpp = 8; break; case OF_IMAGE_COLOR: newBpp = 24; break; case OF_IMAGE_COLOR_ALPHA: newBpp = 32; break; default: ofLog(OF_LOG_ERROR,"error = bad imageType in ofImage::setFromPixels"); return; } allocatePixels(myPixels, w, h, newBpp); int bytesPerPixel = myPixels.bitsPerPixel / 8; memcpy(myPixels.pixels, newPixels, w*h*bytesPerPixel); if (myPixels.bytesPerPixel > 1){ if (!bOrderIsRGB){ swapRgb(myPixels); } } update(); }
//------------------------------------------------------------------ void ofxAdvancedImage::loadFromData(unsigned char * datasource, int len) { //Load image from memory code, based on Zach's code updated by madparker on OF Forum //if we already have a loaded image clear it // if(isValid()){ clear(); // } //create a freeimage memory handle from the buffer address FIMEMORY *hmem = NULL; hmem = FreeImage_OpenMemory((BYTE *)datasource,len); if (hmem == NULL){ printf("couldn't create memory handle! \n"); return; } //get the file type! FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem); //make the image!! putBmpIntoPixels(FreeImage_LoadFromMemory(fif, hmem, 0), myPixels); // bmp = FreeImage_LoadFromMemory(fif, hmem, 0); //free our memory FreeImage_CloseMemory(hmem); if (getBmpFromPixels(myPixels) == NULL){ printf("couldn't create bmp! \n"); return; } //flip it! FreeImage_FlipVertical(getBmpFromPixels(myPixels)); if (myPixels.bAllocated == true && bUseTexture == true){ tex.allocate(myPixels.width, myPixels.height, myPixels.glDataType); } swapRgb(myPixels); update(); reset(); }
//---------------------------------------------------- bool ofImage::loadImageIntoPixels(string fileName, ofPixels &pix){ int width, height, bpp; fileName = ofToDataPath(fileName); bool bLoaded = false; FIBITMAP * bmp = NULL; FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; fif = FreeImage_GetFileType(fileName.c_str(), 0); if(fif == FIF_UNKNOWN) { // or guess via filename fif = FreeImage_GetFIFFromFilename(fileName.c_str()); } if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) { bmp = FreeImage_Load(fif, fileName.c_str(), 0); bLoaded = true; if (bmp == NULL){ bLoaded = false; } } //----------------------------- if (bLoaded ){ width = FreeImage_GetWidth(bmp); height = FreeImage_GetHeight(bmp); bpp = FreeImage_GetBPP(bmp); bool bPallette = (FreeImage_GetColorType(bmp) == FIC_PALETTE); switch (bpp){ case 8: if (bPallette) { FIBITMAP * bmpTemp = FreeImage_ConvertTo24Bits(bmp); if (bmp != NULL) FreeImage_Unload(bmp); bmp = bmpTemp; bpp = FreeImage_GetBPP(bmp); } else { // do nothing we are grayscale } break; case 24: // do nothing we are color break; case 32: // do nothing we are colorAlpha break; default: FIBITMAP * bmpTemp = FreeImage_ConvertTo24Bits(bmp); if (bmp != NULL) FreeImage_Unload(bmp); bmp = bmpTemp; bpp = FreeImage_GetBPP(bmp); } int byteCount = bpp / 8; //------------------------------------------ // call the allocation routine (which checks if really need to allocate) here: allocatePixels(pix, width, height, bpp); FreeImage_ConvertToRawBits(pix.pixels, bmp, width*byteCount, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, true); // get bits //------------------------------------------ // RGB or RGBA swap // this can be done with some ill pointer math. // anyone game? // #ifdef TARGET_LITTLE_ENDIAN if (byteCount != 1) swapRgb(pix); #endif //------------------------------------------ } else { width = height = bpp = 0; } if (bmp != NULL){ FreeImage_Unload(bmp); } return bLoaded; }
bool ofMemoryImage::loadFromDataIntoPixels(const unsigned char * datasource, int len, ofPixels &pix ) { int width, height, bpp; bool bLoaded = false; FIBITMAP * bmp = NULL; FIMEMORY *hmem = NULL; hmem = FreeImage_OpenMemory((Byte *)datasource, len); if (hmem == NULL) { printf("couldn't create memory handle! \n"); } cout << "memory open " << endl; //get the file type! FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem); cout << "image format "<< fif << endl; if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) { bmp = FreeImage_LoadFromMemory(fif, hmem, 0); if (bmp == NULL) { cout << "we could not load from memory!! " << endl; } else { FreeImage_CloseMemory(hmem); } bLoaded = true; if (bmp == NULL) { bLoaded = false; cout << "we are not loadded " << endl; } } if (bLoaded ) { width = FreeImage_GetWidth(bmp); height = FreeImage_GetHeight(bmp); bpp = FreeImage_GetBPP(bmp); bool bPallette = (FreeImage_GetColorType(bmp) == FIC_PALETTE); switch (bpp) { case 8: if (bPallette) { FIBITMAP * bmpTemp = FreeImage_ConvertTo24Bits(bmp); if (bmp != NULL) FreeImage_Unload(bmp); bmp = bmpTemp; bpp = FreeImage_GetBPP(bmp); } else { // do nothing we are grayscale } break; case 24: // do nothing we are color break; case 32: // do nothing we are colorAlpha break; default: FIBITMAP * bmpTemp = FreeImage_ConvertTo24Bits(bmp); if (bmp != NULL) FreeImage_Unload(bmp); bmp = bmpTemp; bpp = FreeImage_GetBPP(bmp); } int byteCount = bpp / 8; //------------------------------------------ // call the allocation routine (which checks if really need to allocate) here: allocatePixels(pix, width, height, bpp); FreeImage_ConvertToRawBits(pix.pixels, bmp, width*byteCount, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, false); // get bits //------------------------------------------ // RGB or RGBA swap // this can be done with some ill pointer math. // anyone game? // #ifdef TARGET_LITTLE_ENDIAN if (byteCount != 1) swapRgb(pix); #endif //------------------------------------------ } else { width = height = bpp = 0; } if (bmp != NULL) { FreeImage_Unload(bmp); } cout << bLoaded << endl; return bLoaded; }
//-------------------------------------------------------------- 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 }