void FreeImageStack::loadImage(unsigned int iSlice, npp::ImageNPP_8u_C1 & rImage) const { NPP_ASSERT_MSG(iSlice < slices(), "Slice index exceeded number of slices in stack."); FIBITMAP * pBitmap = FreeImage_LockPage(pImageStack_, iSlice); NPP_ASSERT_NOT_NULL(pBitmap); // make sure this is an 8-bit single channel image NPP_DEBUG_ASSERT(FreeImage_GetColorType(pBitmap) == FIC_MINISBLACK); NPP_DEBUG_ASSERT(FreeImage_GetBPP(pBitmap) == 8); NPP_DEBUG_ASSERT(FreeImage_GetWidth(pBitmap) == nWidth_); NPP_DEBUG_ASSERT(FreeImage_GetHeight(pBitmap) == nHeight_); unsigned int nSrcPitch = FreeImage_GetPitch(pBitmap); unsigned char * pSrcData = FreeImage_GetBits(pBitmap); if (rImage.width() == nWidth_ && rImage.height() == nHeight_) { NPP_CHECK_CUDA(cudaMemcpy2D(rImage.data(), rImage.pitch(), pSrcData, nSrcPitch, nWidth_, nHeight_, cudaMemcpyHostToDevice)); } else { // create new NPP image npp::ImageNPP_8u_C1 oImage(nWidth_, nHeight_); // transfer slice data into new device image NPP_CHECK_CUDA(cudaMemcpy2D(oImage.data(), oImage.pitch(), pSrcData, nSrcPitch, nWidth_, nHeight_, cudaMemcpyHostToDevice)); // swap the result image with the reference passed into this method rImage.swap(oImage); } // release locked slice FreeImage_UnlockPage(pImageStack_, pBitmap, FALSE); }
FreeImageStack::FreeImageStack(const std::string & rFileName): sFileName_(rFileName) , pImageStack_(0) , nWidth_(0) , nHeight_(0) , pBitmap_32f_(0) , nMaxXY_(0) , nMaxOffset_(0) { // open the bitmap pImageStack_ = FreeImage_OpenMultiBitmap(FIF_TIFF, (sFileName_ + ".tif").c_str(), FALSE, // create new TRUE, // open read-only FALSE, // keep all slices in memory TIFF_DEFAULT); NPP_ASSERT_NOT_NULL(pImageStack_); NPP_ASSERT_NOT_NULL(slices()); FIBITMAP * pBitmap = FreeImage_LockPage(pImageStack_, 0); // store away the size of the first image // this information is later used to insure that all slices // accessed are of the same size. if they are not an exception // is thrown when such a deviating slice is being accessed nWidth_ = FreeImage_GetWidth(pBitmap); nHeight_ = FreeImage_GetHeight(pBitmap); NPP_ASSERT(FreeImage_GetColorType(pBitmap) == FIC_MINISBLACK); NPP_ASSERT(FreeImage_GetBPP(pBitmap) == 8); FreeImage_UnlockPage(pImageStack_, pBitmap, FALSE); }
int FreeImageGifData::getDelayValue(int index) { if (m_gifHandle) { FIBITMAP* frame = FreeImage_LockPage(m_gifHandle, index); FITAG* delayTag = NULL; if (!FreeImage_GetMetadata(FIMD_ANIMATION, frame, "FrameTime", &delayTag)) { FreeImage_UnlockPage(m_gifHandle, frame, false); return -1; } LONG delayVal = *(LONG*)FreeImage_GetTagValue(delayTag); FreeImage_UnlockPage(m_gifHandle, frame, false); return delayVal / 10; } return -1; }
void fipMultiPage::unlockPage(fipImage& image, BOOL changed) { if(_mpage) { FreeImage_UnlockPage(_mpage, image, changed); // clear the image so that it becomes invalid. // this is possible because of the friend declaration image._dib = NULL; image._bHasChanged = FALSE; } }
HBITMAP FreeImageGifData::getFrame(int index) { if (m_gifHandle) { FIBITMAP* frame = FreeImage_LockPage(m_gifHandle, index); HBITMAP outBitmap = FreeImageHelper::FromFreeImage(frame); FreeImage_UnlockPage(m_gifHandle, frame, false); return outBitmap; } return nullptr; }
// return a bool if succesful? bool ofxGifDecoder::decode(string fileName) { reset(); int width, height, bpp; fileName = ofToDataPath(fileName); bool bDecoded = false; FIMULTIBITMAP* multiBmp = NULL; FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; fif = FreeImage_GetFileType(fileName.c_str(), 0); if(fif != FIF_GIF) { ofLog(OF_LOG_WARNING, "ofxGifDecoder::decode. this is not a gif file. not processing"); return bDecoded; } multiBmp = FreeImage_OpenMultiBitmap(fif, fileName.c_str(), false, false,true, GIF_LOAD256); if (multiBmp){ // num frames int nPages = FreeImage_GetPageCount(multiBmp); // here we process the first frame for (int i = 0; i < nPages; i++) { FIBITMAP * dib = FreeImage_LockPage(multiBmp, i); if(dib) { if (i == 0) { createGifFile(dib, nPages); bDecoded = true; // we have at least 1 frame } processFrame(dib, i); FreeImage_UnlockPage(multiBmp, dib, false); } else { ofLog(OF_LOG_WARNING, "ofxGifDecoder::decode. problem locking page"); } } FreeImage_CloseMultiBitmap(multiBmp, 0); }else { ofLog(OF_LOG_WARNING, "ofxGifDecoder::decode. there was an error processing."); } return bDecoded; }
bool CloneMultiPage(FREE_IMAGE_FORMAT fif, char *input, char *output, int output_flag) { BOOL bMemoryCache = TRUE; // Open src file (read-only, use memory cache) FIMULTIBITMAP *src = FreeImage_OpenMultiBitmap(fif, input, FALSE, TRUE, bMemoryCache); if(src) { // Open dst file (creation, use memory cache) FIMULTIBITMAP *dst = FreeImage_OpenMultiBitmap(fif, output, TRUE, FALSE, bMemoryCache); // Get src page count int count = FreeImage_GetPageCount(src); // Clone src to dst for(int page = 0; page < count; page++) { // Load the bitmap at position 'page' FIBITMAP *dib = FreeImage_LockPage(src, page); if(dib) { // add a new bitmap to dst FreeImage_AppendPage(dst, dib); // Unload the bitmap (do not apply any change to src) FreeImage_UnlockPage(src, dib, FALSE); } } // Close src FreeImage_CloseMultiBitmap(src, 0); // Save and close dst FreeImage_CloseMultiBitmap(dst, output_flag); return true; } return false; }
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; }
static void *bg_new_img(void *data) { /* so we can poll for it */ block_usr1_signal(); struct imv_loader *ldr = data; char path[PATH_MAX] = "-"; pthread_mutex_lock(&ldr->lock); int from_stdin = !strncmp(path, ldr->path, 2); if(!from_stdin) { (void)snprintf(path, PATH_MAX, "%s", ldr->path); } pthread_mutex_unlock(&ldr->lock); FREE_IMAGE_FORMAT fmt; if (from_stdin) { pthread_mutex_lock(&ldr->lock); ldr->fi_buffer = FreeImage_OpenMemory(ldr->buffer, ldr->buffer_size); fmt = FreeImage_GetFileTypeFromMemory(ldr->fi_buffer, 0); pthread_mutex_unlock(&ldr->lock); } else { fmt = FreeImage_GetFileType(path, 0); } if(fmt == FIF_UNKNOWN) { if (from_stdin) { pthread_mutex_lock(&ldr->lock); FreeImage_CloseMemory(ldr->fi_buffer); pthread_mutex_unlock(&ldr->lock); } error_occurred(ldr); return NULL; } int num_frames = 1; FIMULTIBITMAP *mbmp = NULL; FIBITMAP *bmp = NULL; int width, height; int raw_frame_time = 100; /* default to 100 */ if(fmt == FIF_GIF) { if(from_stdin) { pthread_mutex_lock(&ldr->lock); mbmp = FreeImage_LoadMultiBitmapFromMemory(FIF_GIF, ldr->fi_buffer, GIF_LOAD256); pthread_mutex_unlock(&ldr->lock); } else { mbmp = FreeImage_OpenMultiBitmap(FIF_GIF, path, /* don't create file */ 0, /* read only */ 1, /* keep in memory */ 1, /* flags */ GIF_LOAD256); } if(!mbmp) { error_occurred(ldr); return NULL; } num_frames = FreeImage_GetPageCount(mbmp); FIBITMAP *frame = FreeImage_LockPage(mbmp, 0); width = FreeImage_GetWidth(frame); height = FreeImage_GetHeight(frame); bmp = FreeImage_ConvertTo32Bits(frame); /* get duration of first frame */ FITAG *tag = NULL; FreeImage_GetMetadata(FIMD_ANIMATION, frame, "FrameTime", &tag); if(FreeImage_GetTagValue(tag)) { raw_frame_time = *(int*)FreeImage_GetTagValue(tag); } FreeImage_UnlockPage(mbmp, frame, 0); } else { /* Future TODO: If we load image line-by-line we could stop loading large * ones before wasting much more time/memory on them. */ int flags = (fmt == FIF_JPEG) ? JPEG_EXIFROTATE : 0; FIBITMAP *image; if(from_stdin) { pthread_mutex_lock(&ldr->lock); image = FreeImage_LoadFromMemory(fmt, ldr->fi_buffer, flags); pthread_mutex_unlock(&ldr->lock); } else { image = FreeImage_Load(fmt, path, flags); } if(!image) { error_occurred(ldr); pthread_mutex_lock(&ldr->lock); FreeImage_CloseMemory(ldr->fi_buffer); ldr->fi_buffer = NULL; pthread_mutex_unlock(&ldr->lock); return NULL; } /* Check for cancellation before we convert pixel format */ if(is_thread_cancelled()) { FreeImage_Unload(image); return NULL; } width = FreeImage_GetWidth(bmp); height = FreeImage_GetHeight(bmp); bmp = FreeImage_ConvertTo32Bits(image); FreeImage_Unload(image); } /* now update the loader */ pthread_mutex_lock(&ldr->lock); /* check for cancellation before finishing */ if(is_thread_cancelled()) { if(mbmp) { FreeImage_CloseMultiBitmap(mbmp, 0); } if(bmp) { FreeImage_Unload(bmp); } pthread_mutex_unlock(&ldr->lock); return NULL; } if(ldr->mbmp) { FreeImage_CloseMultiBitmap(ldr->mbmp, 0); } if(ldr->bmp) { FreeImage_Unload(ldr->bmp); } ldr->mbmp = mbmp; ldr->bmp = bmp; if(ldr->out_bmp) { FreeImage_Unload(ldr->out_bmp); } ldr->out_bmp = FreeImage_Clone(bmp); ldr->out_is_new_image = 1; ldr->width = width; ldr->height = height; ldr->cur_frame = 0; ldr->next_frame = 1; ldr->num_frames = num_frames; ldr->frame_time = (double)raw_frame_time * 0.0001; pthread_mutex_unlock(&ldr->lock); return NULL; }
void task_glow_precalc() { FIMULTIBITMAP* anim = inputanim; float thresh=0.5; float gain=2.0; float blur=1.5; int frameskip=1; sscanf(args[1].c_str(), "%f", &thresh); sscanf(args[2].c_str(), "%f", &gain); sscanf(args[3].c_str(), "%f", &blur); sscanf(args[4].c_str(), "%i", &frameskip); int frameCount = FreeImage_GetPageCount(anim); vector<double> fb; for (int frame=0; frame<frameCount/frameskip; frame++) { FIBITMAP* fiBitmap = FreeImage_LockPage(anim, frame*frameskip); FIBITMAP* grayBitmap = FreeImage_ConvertToGreyscale(fiBitmap); FreeImage_UnlockPage(anim, fiBitmap, FALSE); int width = FreeImage_GetWidth(grayBitmap); int height = FreeImage_GetHeight(grayBitmap); // put into an array of doubles (phew) fb.resize(width*height); for (int y=0; y<height; y++) { BYTE* src = FreeImage_GetScanLine(grayBitmap, y); double* dst = &fb[y*width]; for (int x=0; x<width; x++) { *dst++ = *src++ * (1.0/255); } } // threshold for (int i=0; i<(int)fb.size(); i++) { double& v = fb[i]; v = (v-thresh)*gain; if (v<0) v=0; } // blur Blur(fb, width, height, blur); // put it back into greyBitmap for (int y=0; y<height; y++) { BYTE* dst = FreeImage_GetScanLine(grayBitmap, y); double* src = &fb[y*width]; for (int x=0; x<width; x++) { double v = *src++ * 256; if (v<0) v=0; if (v>255) v=255; *dst++ = int(v); } } // downsample it to glowgrid FIBITMAP* smallBitmap = FreeImage_Rescale(grayBitmap, GLOWGRID_W, GLOWGRID_H, FILTER_BSPLINE); // print result (should use 4bpp not 8?) for (int y=0; y<GLOWGRID_H; y++) { BYTE* src = FreeImage_GetScanLine(smallBitmap, y); for (int x=0; x<GLOWGRID_W; x++) { putchar( *src++ ); } } } }
/* * Render a particular frame to a canvas (not gif specific). */ bool CAnimation::renderFileFrame(CCanvas *cnv, unsigned int frame) { extern STRING g_projectPath; cnv->ClearScreen(TRANSP_COLOR); // Wrap around. frame %= m_data.frameCount; if (m_data.filename.empty()) return false; const STRING file = resolve(g_projectPath + MISC_PATH + m_data.filename); FIMULTIBITMAP *mbmp = FreeImage_OpenMultiBitmap( FreeImage_GetFileType(getAsciiString(file).c_str(), 16), getAsciiString(file).c_str(), FALSE, TRUE, TRUE ); if (!mbmp) return false; CCanvas cnvImg; cnvImg.CreateBlank(NULL, m_data.pxWidth, m_data.pxHeight, TRUE); const int pageCount = FreeImage_GetPageCount(mbmp); if (frame < pageCount) { CONST HDC hdc = cnvImg.OpenDC(); FIBITMAP *bmp = FreeImage_LockPage(mbmp, frame); SetDIBitsToDevice( hdc, 0, 0, m_data.pxWidth, m_data.pxHeight, 0, 0, 0, FreeImage_GetHeight(bmp), FreeImage_GetBits(bmp), FreeImage_GetInfo(bmp), DIB_RGB_COLORS ); /* No need to stretch gif. StretchDIBits( hdc, 0, 0, m_data.pxWidth, m_data.pxHeight, 0, 0, FreeImage_GetWidth(bmp), FreeImage_GetHeight(bmp), FreeImage_GetBits(bmp), FreeImage_GetInfo(bmp), DIB_RGB_COLORS, SRCCOPY );*/ FreeImage_UnlockPage(mbmp, bmp, FALSE); cnvImg.CloseDC(hdc); } FreeImage_CloseMultiBitmap(mbmp, 0); // Apply ambient level. extern AMBIENT_LEVEL g_ambientLevel; if (g_ambientLevel.color) { CCanvas cnvAl; cnvAl.CreateBlank(NULL, m_data.pxWidth, m_data.pxHeight, TRUE); cnvAl.ClearScreen(g_ambientLevel.color); cnvAl.BltAdditivePart(cnvImg.GetDXSurface(), 0, 0, 0, 0, m_data.pxWidth, m_data.pxHeight, g_ambientLevel.sgn, -1, m_data.transpColors[frame]); } cnvImg.BltTransparent(cnv, 0, 0, m_data.transpColors[frame]); return true; }
/* * Render all frames of a file (not gif specific). */ bool CAnimation::renderFileFrame(CCanvas *, unsigned int) { extern STRING g_projectPath; if (m_data.filename.empty()) return false; const STRING file = resolve(g_projectPath + MISC_PATH + m_data.filename); FIMULTIBITMAP *mbmp = FreeImage_OpenMultiBitmap( FreeImage_GetFileType(getAsciiString(file).c_str(), 16), getAsciiString(file).c_str(), FALSE, TRUE, TRUE ); if (!mbmp) return false; // Create ambient level canvas. extern AMBIENT_LEVEL g_ambientLevel; CCanvas cnvAl; if (g_ambientLevel.color) { cnvAl.CreateBlank(NULL, m_data.pxWidth, m_data.pxHeight, TRUE); cnvAl.ClearScreen(g_ambientLevel.color); } // Intermediate canvas. CCanvas cnv; cnv.CreateBlank(NULL, m_data.pxWidth, m_data.pxHeight, TRUE); freeCanvases(); m_canvases.clear(); for (int i = 0; i != m_data.frameCount; ++i) { CONST HDC hdc = cnv.OpenDC(); FIBITMAP *bmp = FreeImage_LockPage(mbmp, i); SetDIBitsToDevice( hdc, 0, 0, m_data.pxWidth, m_data.pxHeight, 0, 0, 0, FreeImage_GetHeight(bmp), FreeImage_GetBits(bmp), FreeImage_GetInfo(bmp), DIB_RGB_COLORS ); /* No need to stretch gif. StretchDIBits( hdc, 0, 0, 0, 0, FreeImage_GetWidth(bmp), FreeImage_GetHeight(bmp), FreeImage_GetBits(bmp), FreeImage_GetInfo(bmp), DIB_RGB_COLORS, SRCCOPY );*/ FreeImage_UnlockPage(mbmp, bmp, FALSE); cnv.CloseDC(hdc); // Apply ambient level. if (g_ambientLevel.color) { cnvAl.BltAdditivePart(cnv.GetDXSurface(), 0, 0, 0, 0, m_data.pxWidth, m_data.pxHeight, g_ambientLevel.sgn, -1, m_data.transpColors[i]); } // Blt to the member canvas. CCanvas *pCnv = new CCanvas(); pCnv->CreateBlank(NULL, m_data.pxWidth, m_data.pxHeight, TRUE); pCnv->ClearScreen(TRANSP_COLOR); cnv.BltTransparent(pCnv, 0, 0, m_data.transpColors[i]); m_canvases.push_back(pCnv); } FreeImage_CloseMultiBitmap(mbmp, 0); return true; }