// Sends an ImageServer frame // [ImageType(1 byte) ImageSize(4 bytes) ImageData(n bytes)] int transmitFrame(FIMEMORY *fiBuffer, SOCKET &clientSocket, unsigned char imageType) { int socketStatus; u_long imageSize; BYTE *fiBufferPtr = NULL; DWORD fiBufferSize = 0; // Get pointer to buffer memory socketStatus = FreeImage_AcquireMemory(fiBuffer, &fiBufferPtr, &fiBufferSize); if (socketStatus != 1) return SOCKET_ERROR; // Send the image type socketStatus = send(clientSocket, (char*)&imageType, 1, 0); if (socketStatus != 1) return socketStatus; // Send the image size (in bytes) imageSize = htonl((u_long)fiBufferSize); socketStatus = send(clientSocket, (char*)&imageSize, 4, 0); if (socketStatus != 4) return socketStatus; // Send the image socketStatus = send(clientSocket, (char*)fiBufferPtr, fiBufferSize, 0); if (socketStatus != fiBufferSize) return socketStatus; /* char msg[1024]; sprintf_s(msg, 1024, "imageType: %i imageSize: %i", imageType, imageSize); MessageBox(NULL,msg,"ADES DEBUG", MB_OK); */ return socketStatus; }
// 独立函数,读取gif图片,写白背景,转为PNG并写入缓存,返回缓存地址 FOX_DLL FIMEMORY * gif2png_bufopen(char *gifpath, BYTE ** buffpointeraddr, DWORD * bufflenaddr) { FIBITMAP * hImage ; RGBQUAD * pal ; FIMEMORY * hMemory = NULL ; BYTE *mem_buffer = NULL ; DWORD size_in_bytes = 0 ; hImage = FreeImage_Load(FIF_GIF, gifpath, 0); pal = FreeImage_GetPalette(hImage); pal[70].rgbRed = 255 ; pal[70].rgbGreen = 255 ; pal[70].rgbBlue = 255 ; FreeImage_SetTransparent(hImage, false); hMemory = FreeImage_OpenMemory() ; FreeImage_SaveToMemory(FIF_PNG, hImage, hMemory, PNG_DEFAULT) ; FreeImage_Unload(hImage) ; FreeImage_AcquireMemory(hMemory, &mem_buffer, &size_in_bytes); *buffpointeraddr = mem_buffer ; *bufflenaddr = size_in_bytes ; return hMemory ; // FreeImage_CloseMemory(hMemory) ; // 使用完缓存记得要释放 }
static BlockReference* FreeImage_SavePageToBlock(MULTIBITMAPHEADER *header, FIBITMAP *data) { if (header->read_only || !header->locked_pages.empty()) return NULL; DWORD compressed_size = 0; BYTE *compressed_data = NULL; // compress the bitmap data // open a memory handle FIMEMORY *hmem = FreeImage_OpenMemory(); if(hmem==NULL) return NULL; // save the file to memory if(!FreeImage_SaveToMemory(header->cache_fif, data, hmem, 0)) { FreeImage_CloseMemory(hmem); return NULL; } // get the buffer from the memory stream if(!FreeImage_AcquireMemory(hmem, &compressed_data, &compressed_size)) { FreeImage_CloseMemory(hmem); return NULL; } // write the compressed data to the cache int ref = header->m_cachefile->writeFile(compressed_data, compressed_size); // get rid of the compressed data FreeImage_CloseMemory(hmem); return new(std::nothrow) BlockReference(ref, compressed_size); }
//--------------------------------------------------------------------- DataStreamPtr FreeImageCodec::code(MemoryDataStreamPtr& input, Codec::CodecDataPtr& pData) const { // Set error handler FreeImage_SetOutputMessage(FreeImageSaveErrorHandler); FIBITMAP* fiBitmap = encode(input, pData); // open memory chunk allocated by FreeImage FIMEMORY* mem = FreeImage_OpenMemory(); // write data into memory FreeImage_SaveToMemory((FREE_IMAGE_FORMAT)mFreeImageType, fiBitmap, mem); // Grab data information BYTE* data; DWORD size; FreeImage_AcquireMemory(mem, &data, &size); // Copy data into our own buffer // Because we're asking MemoryDataStream to free this, must create in a compatible way BYTE* ourData = OGRE_ALLOC_T(BYTE, size, MEMCATEGORY_GENERAL); memcpy(ourData, data, size); // Wrap data in stream, tell it to free on close DataStreamPtr outstream(OGRE_NEW MemoryDataStream(ourData, size, true)); // Now free FreeImage memory buffers FreeImage_CloseMemory(mem); // Unload bitmap FreeImage_Unload(fiBitmap); return outstream; }
//--------------------------------------------------------------------- DataStreamPtr FreeImageCodec::code(MemoryDataStreamPtr& input, Codec::CodecDataPtr& pData) const { FIBITMAP* fiBitmap = encode(input, pData); // open memory chunk allocated by FreeImage FIMEMORY* mem = FreeImage_OpenMemory(); // write data into memory FreeImage_SaveToMemory((FREE_IMAGE_FORMAT)mFreeImageType, fiBitmap, mem); // Grab data information BYTE* data; DWORD size; FreeImage_AcquireMemory(mem, &data, &size); // Copy data into our own buffer BYTE* ourData = new BYTE[size]; memcpy(ourData, data, size); // Wrap data in stream, tell it to free on close DataStreamPtr outstream(new MemoryDataStream(ourData, size, true)); // Now free FreeImage memory buffers FreeImage_CloseMemory(mem); // Unload bitmap FreeImage_Unload(fiBitmap); return outstream; }
void testAcquireMemIO(const char *lpszPathName) { FIMEMORY *hmem = NULL; // load a regular file FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(lpszPathName); FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, 0); // open and allocate a memory stream hmem = FreeImage_OpenMemory(); // save the file to memory FreeImage_SaveToMemory(FIF_PNG, dib, hmem, PNG_DEFAULT); FreeImage_Unload(dib); // get the buffer from the memory stream BYTE *mem_buffer = NULL; DWORD size_in_bytes = 0; FreeImage_AcquireMemory(hmem, &mem_buffer, &size_in_bytes); // save the buffer in a file stream FILE *stream = fopen("buffer.png", "wb"); if(stream) { fwrite(mem_buffer, sizeof(BYTE), size_in_bytes, stream); fclose(stream); } // close and free the memory stream FreeImage_CloseMemory(hmem); }
/** Retrieve the position of a chunk in a PNG stream @param hPngMemory PNG stream handle @param chunk_name Name of the chunk to be found @param offset Start of the search in the stream @param start_pos [returned value] Start position of the chunk @param next_pos [returned value] Start position of the next chunk @return Returns TRUE if successful, returns FALSE otherwise */ static BOOL mng_FindChunk(FIMEMORY *hPngMemory, BYTE *chunk_name, long offset, DWORD *start_pos, DWORD *next_pos) { BOOL mEnd = FALSE; DWORD mLength = 0; BYTE *data = NULL; DWORD size_in_bytes = 0; *start_pos = 0; *next_pos = 0; // get a pointer to the stream buffer FreeImage_AcquireMemory(hPngMemory, &data, &size_in_bytes); if(!(data && size_in_bytes) || (size_in_bytes < 20) || (size_in_bytes - offset < 20)) { // not enough space to read a signature(8 bytes) + a chunk(at least 12 bytes) return FALSE; } try { // skip the signature and/or any following chunk(s) DWORD chunk_pos = offset; while(1) { // get chunk length if(chunk_pos + 4 > size_in_bytes) { break; } memcpy(&mLength, &data[chunk_pos], 4); mng_SwapLong(&mLength); chunk_pos += 4; const DWORD next_chunk_pos = chunk_pos + 4 + mLength + 4; if(next_chunk_pos > size_in_bytes) { break; } // get chunk name if(memcmp(&data[chunk_pos], chunk_name, 4) == 0) { chunk_pos -= 4; // found chunk *start_pos = chunk_pos; *next_pos = next_chunk_pos; return TRUE; } chunk_pos = next_chunk_pos; } return FALSE; } catch(int) { return FALSE; } }
void DLL_CALLCONV FreeImage_UnlockPage(FIMULTIBITMAP *bitmap, FIBITMAP *page, BOOL changed) { if ((bitmap) && (page)) { MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); // find out if the page we try to unlock is actually locked... if (header->locked_pages.find(page) != header->locked_pages.end()) { // store the bitmap compressed in the cache for later writing if (changed && !header->read_only) { header->changed = TRUE; // cut loose the block from the rest BlockListIterator i = FreeImage_FindBlock(bitmap, header->locked_pages[page]); // compress the data DWORD compressed_size = 0; BYTE *compressed_data = NULL; // open a memory handle FIMEMORY *hmem = FreeImage_OpenMemory(); // save the page to memory FreeImage_SaveToMemory(header->cache_fif, page, hmem, 0); // get the buffer from the memory stream FreeImage_AcquireMemory(hmem, &compressed_data, &compressed_size); // write the data to the cache if (i->m_type == BLOCK_REFERENCE) { header->m_cachefile.deleteFile(i->getReference()); } int iPage = header->m_cachefile.writeFile(compressed_data, compressed_size); *i = PageBlock(BLOCK_REFERENCE, iPage, compressed_size); // get rid of the compressed data FreeImage_CloseMemory(hmem); } // reset the locked page so that another page can be locked FreeImage_Unload(page); header->locked_pages.erase(page); } } }
FIMEMORY* FreeImage_SaveToMem(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, fiio_mem_handle *handle, int flags) { if (handle) { FIMEMORY *hmem = FreeImage_OpenMemory(NULL, 0); if(fif == FIF_UNKNOWN) fif = FIF_BMP; handle->curpos = 0; FreeImage_SaveToMemory(fif, dib, hmem, flags); FreeImage_AcquireMemory(hmem, (BYTE **)&handle->data, (DWORD *)&handle->datalen); return hmem; } return NULL; }
void DLL_CALLCONV FreeImage_InsertPage(FIMULTIBITMAP *bitmap, int page, FIBITMAP *data) { if ((bitmap) && (data)) { if (page < FreeImage_GetPageCount(bitmap)) { MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); if ((!header->read_only) && (header->locked_pages.empty())) { DWORD compressed_size = 0; BYTE *compressed_data = NULL; // compress the bitmap data // open a memory handle FIMEMORY *hmem = FreeImage_OpenMemory(); // save the file to memory FreeImage_SaveToMemory(header->cache_fif, data, hmem, 0); // get the buffer from the memory stream FreeImage_AcquireMemory(hmem, &compressed_data, &compressed_size); // write the compressed data to the cache int ref = header->m_cachefile->writeFile(compressed_data, compressed_size); // add a block if (page > 0) { BlockListIterator block_source = FreeImage_FindBlock(bitmap, page); BlockReference *block = new BlockReference(ref, compressed_size); header->m_blocks.insert(block_source, (BlockTypeS *)block); } else { BlockReference *block = new BlockReference(ref, compressed_size); header->m_blocks.push_front((BlockTypeS *)block); } // get rid of the compressed buffer FreeImage_CloseMemory(hmem); header->changed = TRUE; header->page_count = -1; } } } }
/** Write a metadata model as a TIF IFD, returns the IFD as a buffer. The buffer is allocated by the function and must be freed by the caller, using 'free'. @param dib Input FIBITMAP @param md_model Metadata model to write @param ppbProfile Returned buffer @param uProfileLength Returned buffer size @return Returns TRUE if successful, FALSE otherwise @see tiff_write_ifd */ BOOL tiff_get_ifd_profile(FIBITMAP *dib, FREE_IMAGE_MDMODEL md_model, BYTE **ppbProfile, unsigned *uProfileLength) { FIMEMORY *hmem = NULL; try { // open a memory stream hmem = FreeImage_OpenMemory(NULL, 0); if(!hmem) { throw(1); } // write the metadata model as a TIF IFD BOOL bResult = tiff_write_ifd(dib, md_model, hmem); if(bResult) { BYTE *data = NULL; DWORD size_in_bytes = 0; // get a pointer to the stream buffer FreeImage_AcquireMemory(hmem, &data, &size_in_bytes); // (re-)allocate output buffer BYTE *pbProfile = *ppbProfile; pbProfile = (BYTE*)realloc(pbProfile, size_in_bytes); if(!pbProfile) { throw(1); } else { // copy IFD memcpy(pbProfile, data, size_in_bytes); *ppbProfile = pbProfile; *uProfileLength = size_in_bytes; } } // free the memory stream FreeImage_CloseMemory(hmem); return bResult; } catch(int) { FreeImage_CloseMemory(hmem); return FALSE; } }
/** Insert a chunk just before the inNextChunkName chunk @param hPngMemory PNG stream handle @param start_pos Start position of the inNextChunkName chunk @param next_pos Start position of the next chunk @return Returns TRUE if successfull, returns FALSE otherwise */ static BOOL mng_CopyInsertChunks(FIMEMORY *hPngMemory, BYTE *inNextChunkName, BYTE *inInsertChunk, DWORD inChunkLength, DWORD start_pos, DWORD next_pos) { BYTE *data = NULL; DWORD size_in_bytes = 0; // length of the chunk to check DWORD chunk_length = next_pos - start_pos; if(chunk_length == 0) { return TRUE; } // get a pointer to the stream buffer FreeImage_AcquireMemory(hPngMemory, &data, &size_in_bytes); if(!(data && size_in_bytes) || (size_in_bytes < 20) || (chunk_length >= size_in_bytes)) { // not enough space to read a signature(8 bytes) + a chunk(at least 12 bytes) return FALSE; } // new file length unsigned buffer_size = inChunkLength + size_in_bytes; BYTE *buffer = (BYTE*)malloc(buffer_size * sizeof(BYTE)); if(!buffer) { return FALSE; } unsigned p = 0; memcpy(&buffer[p], &data[0], start_pos); p += start_pos; memcpy(&buffer[p], inInsertChunk, inChunkLength); p += inChunkLength; memcpy(&buffer[p], &data[start_pos], size_in_bytes - start_pos); // seek to the start of the stream FreeImage_SeekMemory(hPngMemory, 0, SEEK_SET); // re-write the stream FreeImage_WriteMemory(buffer, 1, buffer_size, hPngMemory); free(buffer); return TRUE; }
static PageBlock FreeImage_SavePageToBlock(MULTIBITMAPHEADER *header, FIBITMAP *data) { PageBlock res; if (header->read_only || !header->locked_pages.empty()) { return res; } DWORD compressed_size = 0; BYTE *compressed_data = NULL; // compress the bitmap data // open a memory handle FIMEMORY *hmem = FreeImage_OpenMemory(); if(hmem==NULL) { return res; } // save the file to memory if(!FreeImage_SaveToMemory(header->cache_fif, data, hmem, 0)) { FreeImage_CloseMemory(hmem); return res; } // get the buffer from the memory stream if(!FreeImage_AcquireMemory(hmem, &compressed_data, &compressed_size)) { FreeImage_CloseMemory(hmem); return res; } // write the compressed data to the cache int ref = header->m_cachefile.writeFile(compressed_data, compressed_size); // get rid of the compressed data FreeImage_CloseMemory(hmem); res = PageBlock(BLOCK_REFERENCE, ref, compressed_size); return res; }
void DLL_CALLCONV FreeImage_AppendPage(FIMULTIBITMAP *bitmap, FIBITMAP *data) { if ((bitmap) && (data)) { MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); if ((!header->read_only) && (header->locked_pages.empty())) { DWORD compressed_size = 0; BYTE *compressed_data = NULL; // compress the bitmap data // open a memory handle FIMEMORY *hmem = FreeImage_OpenMemory(); // save the file to memory FreeImage_SaveToMemory(header->cache_fif, data, hmem, 0); // get the buffer from the memory stream FreeImage_AcquireMemory(hmem, &compressed_data, &compressed_size); // write the compressed data to the cache int ref = header->m_cachefile->writeFile(compressed_data, compressed_size); BlockReference *block = new BlockReference(ref, compressed_size); // get rid of the compressed data FreeImage_CloseMemory(hmem); // add the block header->m_blocks.push_back((BlockTypeS *)block); header->changed = TRUE; header->page_count = -1; } } }
/** Write a FIBITMAP to a JNG stream @param format_id ID of the caller @param io Stream i/o functions @param dib Image to be saved @param handle Stream handle @param flags Saving flags @return Returns TRUE if successful, returns FALSE otherwise */ BOOL mng_WriteJNG(int format_id, FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int flags) { DWORD jng_width = 0; DWORD jng_height = 0; BYTE jng_color_type = 0; BYTE jng_image_sample_depth = 8; BYTE jng_image_compression_method = 8; // 8: ISO-10918-1 Huffman-coded baseline JPEG. BYTE jng_image_interlace_method = 0; BYTE jng_alpha_sample_depth = 0; BYTE jng_alpha_compression_method = 0; BYTE jng_alpha_filter_method = 0; BYTE jng_alpha_interlace_method = 0; BYTE buffer[16]; FIMEMORY *hJngMemory = NULL; FIMEMORY *hJpegMemory = NULL; FIMEMORY *hPngMemory = NULL; FIBITMAP *dib_rgb = NULL; FIBITMAP *dib_alpha = NULL; if(!dib || (FreeImage_GetImageType(dib) != FIT_BITMAP)) { return FALSE; } unsigned bpp = FreeImage_GetBPP(dib); switch(bpp) { case 8: if(FreeImage_GetColorType(dib) == FIC_MINISBLACK) { dib_rgb = dib; jng_color_type = MNG_COLORTYPE_JPEGGRAY; } else { // JPEG plugin will convert other types (FIC_MINISWHITE, FIC_PALETTE) to 24-bit on the fly //dib_rgb = FreeImage_ConvertTo24Bits(dib); dib_rgb = dib; jng_color_type = MNG_COLORTYPE_JPEGCOLOR; } break; case 24: dib_rgb = dib; jng_color_type = MNG_COLORTYPE_JPEGCOLOR; break; case 32: dib_rgb = FreeImage_ConvertTo24Bits(dib); jng_color_type = MNG_COLORTYPE_JPEGCOLORA; jng_alpha_sample_depth = 8; break; default: return FALSE; } jng_width = (DWORD)FreeImage_GetWidth(dib); jng_height = (DWORD)FreeImage_GetHeight(dib); try { hJngMemory = FreeImage_OpenMemory(); // --- write JNG file signature --- FreeImage_WriteMemory(g_jng_signature, 1, 8, hJngMemory); // --- write a JHDR chunk --- SwapLong(&jng_width); SwapLong(&jng_height); memcpy(&buffer[0], &jng_width, 4); memcpy(&buffer[4], &jng_height, 4); SwapLong(&jng_width); SwapLong(&jng_height); buffer[8] = jng_color_type; buffer[9] = jng_image_sample_depth; buffer[10] = jng_image_compression_method; buffer[11] = jng_image_interlace_method; buffer[12] = jng_alpha_sample_depth; buffer[13] = jng_alpha_compression_method; buffer[14] = jng_alpha_filter_method; buffer[15] = jng_alpha_interlace_method; mng_WriteChunk(mng_JHDR, &buffer[0], 16, hJngMemory); // --- write a sequence of JDAT chunks --- hJpegMemory = FreeImage_OpenMemory(); flags |= JPEG_BASELINE; if(!FreeImage_SaveToMemory(FIF_JPEG, dib_rgb, hJpegMemory, flags)) { throw (const char*)NULL; } if(dib_rgb != dib) { FreeImage_Unload(dib_rgb); dib_rgb = NULL; } { BYTE *jpeg_data = NULL; DWORD size_in_bytes = 0; // get a pointer to the stream buffer FreeImage_AcquireMemory(hJpegMemory, &jpeg_data, &size_in_bytes); // write chunks for(DWORD k = 0; k < size_in_bytes;) { DWORD bytes_left = size_in_bytes - k; DWORD chunk_size = MIN(JPEG_CHUNK_SIZE, bytes_left); mng_WriteChunk(mng_JDAT, &jpeg_data[k], chunk_size, hJngMemory); k += chunk_size; } } FreeImage_CloseMemory(hJpegMemory); hJpegMemory = NULL; // --- write alpha layer as a sequence of IDAT chunk --- if((bpp == 32) && (jng_color_type == MNG_COLORTYPE_JPEGCOLORA)) { dib_alpha = FreeImage_GetChannel(dib, FICC_ALPHA); hPngMemory = FreeImage_OpenMemory(); if(!FreeImage_SaveToMemory(FIF_PNG, dib_alpha, hPngMemory, PNG_DEFAULT)) { throw (const char*)NULL; } FreeImage_Unload(dib_alpha); dib_alpha = NULL; // get the IDAT chunk { BOOL bResult = FALSE; DWORD start_pos = 0; DWORD next_pos = 0; long offset = 8; do { // find the next IDAT chunk from 'offset' position bResult = mng_FindChunk(hPngMemory, mng_IDAT, offset, &start_pos, &next_pos); if(!bResult) break; BYTE *png_data = NULL; DWORD size_in_bytes = 0; // get a pointer to the stream buffer FreeImage_AcquireMemory(hPngMemory, &png_data, &size_in_bytes); // write the IDAT chunk mng_WriteChunk(mng_IDAT, &png_data[start_pos+8], next_pos - start_pos - 12, hJngMemory); offset = next_pos; } while(bResult); } FreeImage_CloseMemory(hPngMemory); hPngMemory = NULL; } // --- write a IEND chunk --- mng_WriteChunk(mng_IEND, NULL, 0, hJngMemory); // write the JNG on output stream { BYTE *jng_data = NULL; DWORD size_in_bytes = 0; FreeImage_AcquireMemory(hJngMemory, &jng_data, &size_in_bytes); io->write_proc(jng_data, 1, size_in_bytes, handle); } FreeImage_CloseMemory(hJngMemory); FreeImage_CloseMemory(hJpegMemory); FreeImage_CloseMemory(hPngMemory); return TRUE; } catch(const char *text) { FreeImage_CloseMemory(hJngMemory); FreeImage_CloseMemory(hJpegMemory); FreeImage_CloseMemory(hPngMemory); if(dib_rgb && (dib_rgb != dib)) { FreeImage_Unload(dib_rgb); } FreeImage_Unload(dib_alpha); if(text) { FreeImage_OutputMessageProc(format_id, text); } return FALSE; } }
BOOL fipMemoryIO::acquire(BYTE **data, DWORD *size_in_bytes) { return FreeImage_AcquireMemory(_hmem, data, size_in_bytes); }
GXBOOL RenderTargetImpl::SaveToMemory(clstd::MemBuffer* pBuffer, GXLPCSTR pImageFormat) { GXSIZE sDimension; GXBOOL bval = TRUE; GXFormat format = m_pColorTexture->GetFormat(); m_pColorTexture->GetDimension(&sDimension); Texture* pReadBackTexture = NULL; GetColorTexture(&pReadBackTexture, GXResUsage::Read); Texture::MAPPED mapped; if(pReadBackTexture->Map(&mapped, GXResMap::Read)) { GXUINT bpp = GetBytesOfGraphicsFormat(format); GXLPVOID pSourceBits = mapped.pBits; GXINT nSourcePitch = mapped.Pitch; clstd::Image temp_image; FREE_IMAGE_TYPE fit = FIT_BITMAP; switch(format) { case Format_R8G8B8A8: temp_image.Set(sDimension.cx, sDimension.cy, "RGBA", 8, pSourceBits, nSourcePitch); break; case Format_B8G8R8X8: temp_image.Set(sDimension.cx, sDimension.cy, "BGRX", 8, pSourceBits, nSourcePitch); break; case Format_B8G8R8: temp_image.Set(sDimension.cx, sDimension.cy, "BGRX", 8, pSourceBits, nSourcePitch); break; case Format_R8: temp_image.Set(sDimension.cx, sDimension.cy, "R", 8, pSourceBits, nSourcePitch); break; case Format_R8G8: temp_image.Set(sDimension.cx, sDimension.cy, "RG", 8, pSourceBits, nSourcePitch); break; case Format_R32G32B32A32_Float: fit = FIT_RGBAF; break; case Format_R32: fit = FIT_FLOAT; break; } if(temp_image.GetDataSize() > 0) { temp_image.SetFormat("BGRA"); pSourceBits = temp_image.GetLine(0); nSourcePitch = temp_image.GetPitch(); bpp = temp_image.GetChannels(); } FIBITMAP* fibmp = (fit == FIT_BITMAP) ? FreeImage_Allocate(sDimension.cx, sDimension.cy, bpp * 8) : FreeImage_AllocateT(fit, sDimension.cx, sDimension.cy, bpp * 8); BYTE* pDest = FreeImage_GetBits(fibmp); GXINT nDestPitch = FreeImage_GetPitch(fibmp); pDest += nDestPitch * (sDimension.cy - 1); for(int y = 0; y < sDimension.cy; y++) { memcpy(pDest, pSourceBits, clMin(nDestPitch, nSourcePitch)); pDest -= nDestPitch; pSourceBits = reinterpret_cast<GXLPVOID>(reinterpret_cast<size_t>(pSourceBits) + nSourcePitch); } pReadBackTexture->Unmap(); FREE_IMAGE_FORMAT fi_format = FIF_UNKNOWN; clStringA strFormat = pImageFormat; strFormat.MakeUpper(); if(strFormat == "PNG") { fi_format = FIF_PNG; } else if(strFormat == "JPEG" || strFormat == "JPG") { fi_format = FIF_JPEG; } else if(strFormat == "TIF" || strFormat == "TIFF") { fi_format = FIF_TIFF; } else if(strFormat == "TGA") { fi_format = FIF_TARGA; } else if(strFormat == "BMP") { fi_format = FIF_BMP; } else if(strFormat == "EXR") { fi_format = FIF_EXR; } if(fi_format != FIF_UNKNOWN) { FIMEMORY* fimemory = FreeImage_OpenMemory(); if(FreeImage_SaveToMemory(fi_format, fibmp, fimemory)) { BYTE *pData; DWORD size_in_bytes; if(FreeImage_AcquireMemory(fimemory, &pData, &size_in_bytes)) { pBuffer->Resize(0, FALSE); pBuffer->Append(pData, size_in_bytes); } else { bval = FALSE; } } else { bval = FALSE; } FreeImage_CloseMemory(fimemory); } else { bval = FALSE; } FreeImage_Unload(fibmp); } SAFE_RELEASE(pReadBackTexture); return bval; }
static void saveImage(ofPixels_<PixelType> & pix, ofBuffer & buffer, ofImageFormat format, ofImageQualityType qualityLevel) { //thanks to alvaro casinelli for the implementation ofInitFreeImage(); if (pix.isAllocated() == false){ ofLog(OF_LOG_ERROR,"error saving image - pixels aren't allocated"); return; } #ifdef TARGET_LITTLE_ENDIAN if(sizeof(PixelType) == 1) { pix.swapRgb(); } #endif FIBITMAP * bmp = getBmpFromPixels(pix); #ifdef TARGET_LITTLE_ENDIAN if(sizeof(PixelType) == 1) { pix.swapRgb(); } #endif if (bmp) // bitmap successfully created { // (b) open a memory stream to compress the image onto mem_buffer: // FIMEMORY *hmem = FreeImage_OpenMemory(); // (c) encode and save the image to the memory (on dib FIBITMAP image): // if(FREE_IMAGE_FORMAT(format) == FIF_JPEG) { int quality = JPEG_QUALITYSUPERB; switch(qualityLevel) { case OF_IMAGE_QUALITY_WORST: quality = JPEG_QUALITYBAD; break; case OF_IMAGE_QUALITY_LOW: quality = JPEG_QUALITYAVERAGE; break; case OF_IMAGE_QUALITY_MEDIUM: quality = JPEG_QUALITYNORMAL; break; case OF_IMAGE_QUALITY_HIGH: quality = JPEG_QUALITYGOOD; break; case OF_IMAGE_QUALITY_BEST: quality = JPEG_QUALITYSUPERB; break; } FreeImage_SaveToMemory(FIF_JPEG, bmp, hmem, quality); }else{ FreeImage_SaveToMemory((FREE_IMAGE_FORMAT)format, bmp, hmem); } /* NOTE: at this point, hmem contains the entire data in memory stored in fif format. the amount of space used by the memory is equal to file_size: long file_size = FreeImage_TellMemory(hmem); but can also be retrieved by FreeImage_AcquireMemory that retrieves both the length of the buffer, and the buffer memory address. */ #ifdef TARGET_WIN32 DWORD size_in_bytes = 0; #else uint32_t size_in_bytes = 0; #endif // Save compressed data on mem_buffer // note: FreeImage_AquireMemory allocates space for aux_mem_buffer): // unsigned char *mem_buffer = NULL; if (!FreeImage_AcquireMemory(hmem, &mem_buffer, &size_in_bytes)) cout << "Error aquiring compressed image from memory" << endl; /* Now, before closing the memory stream, copy the content of mem_buffer to an auxiliary buffer */ buffer.set((char*)mem_buffer,size_in_bytes); // Finally, close the FIBITMAP object, or we will get a memory leak: FreeImage_Unload(bmp); // Close the memory stream (otherwise we may get a memory leak). FreeImage_CloseMemory(hmem); } }
static bool saveImage(const ofPixels_<PixelType> & _pix, ofBuffer & buffer, ofImageFormat format, ofImageQualityType qualityLevel) { // thanks to alvaro casinelli for the implementation ofInitFreeImage(); if (_pix.isAllocated() == false){ ofLogError("ofImage","saveImage(): couldn't save to ofBuffer, pixels are not allocated"); return false; } if(format==OF_IMAGE_FORMAT_JPEG && (_pix.getNumChannels()==4 || _pix.getBitsPerChannel() > 8)){ ofPixels pix3 = _pix; pix3.setNumChannels(3); return saveImage(pix3,buffer,format,qualityLevel); } FIBITMAP * bmp = nullptr; #ifdef TARGET_LITTLE_ENDIAN if(sizeof(PixelType) == 1 && (_pix.getPixelFormat()==OF_PIXELS_RGB || _pix.getPixelFormat()==OF_PIXELS_RGBA)) { // Make a local copy. ofPixels_<PixelType> pix = _pix; pix.swapRgb(); bmp = getBmpFromPixels(pix); }else{ #endif bmp = getBmpFromPixels(_pix); #ifdef TARGET_LITTLE_ENDIAN } #endif if (bmp) // bitmap successfully created { bool returnValue; // (b) open a memory stream to compress the image onto mem_buffer: // FIMEMORY *hmem = FreeImage_OpenMemory(); // (c) encode and save the image to the memory (on dib FIBITMAP image): // if(FREE_IMAGE_FORMAT(format) == FIF_JPEG) { int quality = JPEG_QUALITYSUPERB; switch(qualityLevel) { case OF_IMAGE_QUALITY_WORST: quality = JPEG_QUALITYBAD; break; case OF_IMAGE_QUALITY_LOW: quality = JPEG_QUALITYAVERAGE; break; case OF_IMAGE_QUALITY_MEDIUM: quality = JPEG_QUALITYNORMAL; break; case OF_IMAGE_QUALITY_HIGH: quality = JPEG_QUALITYGOOD; break; case OF_IMAGE_QUALITY_BEST: quality = JPEG_QUALITYSUPERB; break; } returnValue = FreeImage_SaveToMemory(FIF_JPEG, bmp, hmem, quality); }else{ returnValue = FreeImage_SaveToMemory((FREE_IMAGE_FORMAT)format, bmp, hmem); } /* NOTE: at this point, hmem contains the entire data in memory stored in fif format. the amount of space used by the memory is equal to file_size: long file_size = FreeImage_TellMemory(hmem); but can also be retrieved by FreeImage_AcquireMemory that retrieves both the length of the buffer, and the buffer memory address. */ #ifdef TARGET_WIN32 DWORD size_in_bytes = 0; #else std::uint32_t size_in_bytes = 0; #endif // Save compressed data on mem_buffer // note: FreeImage_AquireMemory allocates space for aux_mem_buffer): // unsigned char *mem_buffer = nullptr; if (!FreeImage_AcquireMemory(hmem, &mem_buffer, &size_in_bytes)){ ofLogError("ofImage") << "saveImage(): couldn't save to ofBuffer, aquiring compressed image from memory failed"; return false; } /* Now, before closing the memory stream, copy the content of mem_buffer to an auxiliary buffer */ buffer.set((char*)mem_buffer,size_in_bytes); // Finally, close the FIBITMAP object, or we will get a memory leak: FreeImage_Unload(bmp); // Close the memory stream (otherwise we may get a memory leak). FreeImage_CloseMemory(hmem); return returnValue; }else{ return false; } }
static BOOL DLL_CALLCONV Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { WebPMux *mux = NULL; FIMEMORY *hmem = NULL; WebPData webp_image; WebPData output_data = { 0 }; WebPMuxError error_status; int copy_data = 1; // 1 : copy data into the mux, 0 : keep a link to local data if(!dib || !handle || !data) { return FALSE; } try { // get the MUX object mux = (WebPMux*)data; if(!mux) { return FALSE; } // --- prepare image data --- // encode image as a WebP blob hmem = FreeImage_OpenMemory(); if(!hmem || !EncodeImage(hmem, dib, flags)) { throw (1); } // store the blob into the mux BYTE *data = NULL; DWORD data_size = 0; FreeImage_AcquireMemory(hmem, &data, &data_size); webp_image.bytes = data; webp_image.size = data_size; error_status = WebPMuxSetImage(mux, &webp_image, copy_data); // no longer needed since copy_data == 1 FreeImage_CloseMemory(hmem); hmem = NULL; if(error_status != WEBP_MUX_OK) { throw (1); } // --- set metadata --- // set ICC color profile { FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib); if (iccProfile->size && iccProfile->data) { WebPData icc_profile; icc_profile.bytes = (uint8_t*)iccProfile->data; icc_profile.size = (size_t)iccProfile->size; error_status = WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data); if(error_status != WEBP_MUX_OK) { throw (1); } } } // set XMP metadata { FITAG *tag = NULL; if(FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag)) { WebPData xmp_profile; xmp_profile.bytes = (uint8_t*)FreeImage_GetTagValue(tag); xmp_profile.size = (size_t)FreeImage_GetTagLength(tag); error_status = WebPMuxSetChunk(mux, "XMP ", &xmp_profile, copy_data); if(error_status != WEBP_MUX_OK) { throw (1); } } } // set Exif metadata { FITAG *tag = NULL; if(FreeImage_GetMetadata(FIMD_EXIF_RAW, dib, g_TagLib_ExifRawFieldName, &tag)) { WebPData exif_profile; exif_profile.bytes = (uint8_t*)FreeImage_GetTagValue(tag); exif_profile.size = (size_t)FreeImage_GetTagLength(tag); error_status = WebPMuxSetChunk(mux, "EXIF", &exif_profile, copy_data); if(error_status != WEBP_MUX_OK) { throw (1); } } } // get data from mux in WebP RIFF format error_status = WebPMuxAssemble(mux, &output_data); if(error_status != WEBP_MUX_OK) { FreeImage_OutputMessageProc(s_format_id, "Failed to create webp output file"); throw (1); } // write the file to the output stream if(io->write_proc((void*)output_data.bytes, 1, (unsigned)output_data.size, handle) != output_data.size) { FreeImage_OutputMessageProc(s_format_id, "Failed to write webp output file"); throw (1); } // free WebP output file WebPDataClear(&output_data); return TRUE; } catch(int) { if(hmem) { FreeImage_CloseMemory(hmem); } WebPDataClear(&output_data); return FALSE; } }
/** Load a FIBITMAP from a MNG or a JNG stream @param format_id ID of the caller @param io Stream i/o functions @param handle Stream handle @param Offset Start of the first chunk @param flags Loading flags @return Returns a dib if successful, returns NULL otherwise */ FIBITMAP* mng_ReadChunks(int format_id, FreeImageIO *io, fi_handle handle, long Offset, int flags = 0) { DWORD mLength = 0; BYTE mChunkName[5]; BYTE *mChunk = NULL; DWORD crc_file; long LastOffset; long mOrigPos; BYTE *PLTE_file_chunk = NULL; // whole PLTE chunk (lentgh, name, array, crc) DWORD PLTE_file_size = 0; // size of PLTE chunk BOOL m_HasGlobalPalette = FALSE; // may turn to TRUE in PLTE chunk unsigned m_TotalBytesOfChunks = 0; FIBITMAP *dib = NULL; FIBITMAP *dib_alpha = NULL; FIMEMORY *hJpegMemory = NULL; FIMEMORY *hPngMemory = NULL; FIMEMORY *hIDATMemory = NULL; // --- DWORD jng_width = 0; DWORD jng_height = 0; BYTE jng_color_type = 0; BYTE jng_image_sample_depth = 0; BYTE jng_image_compression_method = 0; BYTE jng_alpha_sample_depth = 0; BYTE jng_alpha_compression_method = 0; BYTE jng_alpha_filter_method = 0; BYTE jng_alpha_interlace_method = 0; DWORD mng_frame_width = 0; DWORD mng_frame_height = 0; DWORD mng_ticks_per_second = 0; DWORD mng_nominal_layer_count = 0; DWORD mng_nominal_frame_count = 0; DWORD mng_nominal_play_time = 0; DWORD mng_simplicity_profile = 0; DWORD res_x = 2835; // 72 dpi DWORD res_y = 2835; // 72 dpi RGBQUAD rgbBkColor = {0, 0, 0, 0}; WORD bk_red, bk_green, bk_blue; BOOL hasBkColor = FALSE; BOOL mHasIDAT = FALSE; tEXtMAP key_value_pair; // --- BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; // get the file size const long mLOF = mng_LOF(io, handle); // go to the first chunk io->seek_proc(handle, Offset, SEEK_SET); try { BOOL mEnd = FALSE; while(mEnd == FALSE) { // start of the chunk LastOffset = io->tell_proc(handle); // read length mLength = 0; io->read_proc(&mLength, 1, sizeof(mLength), handle); mng_SwapLong(&mLength); // read name io->read_proc(&mChunkName[0], 1, 4, handle); mChunkName[4] = '\0'; if(mLength > 0) { mChunk = (BYTE*)realloc(mChunk, mLength); if(!mChunk) { FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: out of memory", mChunkName); throw (const char*)NULL; } Offset = io->tell_proc(handle); if(Offset + (long)mLength > mLOF) { FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: unexpected end of file", mChunkName); throw (const char*)NULL; } // read chunk io->read_proc(mChunk, 1, mLength, handle); } // read crc io->read_proc(&crc_file, 1, sizeof(crc_file), handle); mng_SwapLong(&crc_file); // check crc DWORD crc_check = FreeImage_ZLibCRC32(0, &mChunkName[0], 4); crc_check = FreeImage_ZLibCRC32(crc_check, mChunk, mLength); if(crc_check != crc_file) { FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: bad CRC", mChunkName); throw (const char*)NULL; } switch( mng_GetChunckType(mChunkName) ) { case MHDR: // The MHDR chunk is always first in all MNG datastreams except for those // that consist of a single PNG or JNG datastream with a PNG or JNG signature. if(mLength == 28) { memcpy(&mng_frame_width, &mChunk[0], 4); memcpy(&mng_frame_height, &mChunk[4], 4); memcpy(&mng_ticks_per_second, &mChunk[8], 4); memcpy(&mng_nominal_layer_count, &mChunk[12], 4); memcpy(&mng_nominal_frame_count, &mChunk[16], 4); memcpy(&mng_nominal_play_time, &mChunk[20], 4); memcpy(&mng_simplicity_profile, &mChunk[24], 4); mng_SwapLong(&mng_frame_width); mng_SwapLong(&mng_frame_height); mng_SwapLong(&mng_ticks_per_second); mng_SwapLong(&mng_nominal_layer_count); mng_SwapLong(&mng_nominal_frame_count); mng_SwapLong(&mng_nominal_play_time); mng_SwapLong(&mng_simplicity_profile); } else { FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: size is %d instead of 28", mChunkName, mLength); } break; case MEND: mEnd = TRUE; break; case LOOP: case ENDL: break; case DEFI: break; case SAVE: case SEEK: case TERM: break; case BACK: break; // Global "PLTE" and "tRNS" (if any). PNG "PLTE" will be of 0 byte, as it uses global data. case PLTE: // Global m_HasGlobalPalette = TRUE; PLTE_file_size = mLength + 12; // (lentgh, name, array, crc) = (4, 4, mLength, 4) PLTE_file_chunk = (BYTE*)realloc(PLTE_file_chunk, PLTE_file_size); if(!PLTE_file_chunk) { FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: out of memory", mChunkName); throw (const char*)NULL; } else { mOrigPos = io->tell_proc(handle); // seek to the start of the chunk io->seek_proc(handle, LastOffset, SEEK_SET); // load the whole chunk io->read_proc(PLTE_file_chunk, 1, PLTE_file_size, handle); // go to the start of the next chunk io->seek_proc(handle, mOrigPos, SEEK_SET); } break; case tRNS: // Global break; case IHDR: Offset = LastOffset; // parse the PNG file and get its file size if(mng_CountPNGChunks(io, handle, Offset, &m_TotalBytesOfChunks) == FALSE) { // reach an unexpected end of file mEnd = TRUE; FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: unexpected end of PNG file", mChunkName); break; } // wrap the { IHDR, ..., IEND } chunks as a PNG stream if(hPngMemory == NULL) { hPngMemory = FreeImage_OpenMemory(); } mOrigPos = io->tell_proc(handle); // write PNG file signature FreeImage_SeekMemory(hPngMemory, 0, SEEK_SET); FreeImage_WriteMemory(g_png_signature, 1, 8, hPngMemory); mChunk = (BYTE*)realloc(mChunk, m_TotalBytesOfChunks); if(!mChunk) { FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: out of memory", mChunkName); throw (const char*)NULL; } // on calling CountPNGChunks earlier, we were in Offset pos, // go back there io->seek_proc(handle, Offset, SEEK_SET); io->read_proc(mChunk, 1, m_TotalBytesOfChunks, handle); // Put back to original pos io->seek_proc(handle, mOrigPos, SEEK_SET); // write the PNG chunks FreeImage_WriteMemory(mChunk, 1, m_TotalBytesOfChunks, hPngMemory); // plug in global PLTE if local PLTE exists if(m_HasGlobalPalette) { // ensure we remove some local chunks, so that global // "PLTE" can be inserted right before "IDAT". mng_RemoveChunk(hPngMemory, mng_PLTE); mng_RemoveChunk(hPngMemory, mng_tRNS); mng_RemoveChunk(hPngMemory, mng_bKGD); // insert global "PLTE" chunk in its entirety before "IDAT" mng_InsertChunk(hPngMemory, mng_IDAT, PLTE_file_chunk, PLTE_file_size); } if(dib) FreeImage_Unload(dib); dib = mng_LoadFromMemoryHandle(hPngMemory, flags); // stop after the first image mEnd = TRUE; break; case JHDR: if(mLength == 16) { memcpy(&jng_width, &mChunk[0], 4); memcpy(&jng_height, &mChunk[4], 4); mng_SwapLong(&jng_width); mng_SwapLong(&jng_height); jng_color_type = mChunk[8]; jng_image_sample_depth = mChunk[9]; jng_image_compression_method = mChunk[10]; //BYTE jng_image_interlace_method = mChunk[11]; // for debug only jng_alpha_sample_depth = mChunk[12]; jng_alpha_compression_method = mChunk[13]; jng_alpha_filter_method = mChunk[14]; jng_alpha_interlace_method = mChunk[15]; } else { FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: invalid chunk length", mChunkName); throw (const char*)NULL; } break; case JDAT: if(hJpegMemory == NULL) { hJpegMemory = FreeImage_OpenMemory(); } // as there may be several JDAT chunks, concatenate them FreeImage_WriteMemory(mChunk, 1, mLength, hJpegMemory); break; case IDAT: if(!header_only && (jng_alpha_compression_method == 0)) { // PNG grayscale IDAT format if(hIDATMemory == NULL) { hIDATMemory = FreeImage_OpenMemory(); mHasIDAT = TRUE; } // as there may be several IDAT chunks, concatenate them FreeImage_WriteMemory(mChunk, 1, mLength, hIDATMemory); } break; case IEND: if(!hJpegMemory) { mEnd = TRUE; break; } // load the JPEG if(dib) { FreeImage_Unload(dib); } dib = mng_LoadFromMemoryHandle(hJpegMemory, flags); // load the PNG alpha layer if(mHasIDAT) { BYTE *data = NULL; DWORD size_in_bytes = 0; // get a pointer to the IDAT buffer FreeImage_AcquireMemory(hIDATMemory, &data, &size_in_bytes); if(data && size_in_bytes) { // wrap the IDAT chunk as a PNG stream if(hPngMemory == NULL) { hPngMemory = FreeImage_OpenMemory(); } mng_WritePNGStream(jng_width, jng_height, jng_alpha_sample_depth, data, size_in_bytes, hPngMemory); // load the PNG if(dib_alpha) { FreeImage_Unload(dib_alpha); } dib_alpha = mng_LoadFromMemoryHandle(hPngMemory, flags); } } // stop the parsing mEnd = TRUE; break; case JDAA: break; case gAMA: break; case pHYs: // unit is pixels per meter memcpy(&res_x, &mChunk[0], 4); mng_SwapLong(&res_x); memcpy(&res_y, &mChunk[4], 4); mng_SwapLong(&res_y); break; case bKGD: memcpy(&bk_red, &mChunk[0], 2); mng_SwapShort(&bk_red); rgbBkColor.rgbRed = (BYTE)bk_red; memcpy(&bk_green, &mChunk[2], 2); mng_SwapShort(&bk_green); rgbBkColor.rgbGreen = (BYTE)bk_green; memcpy(&bk_blue, &mChunk[4], 2); mng_SwapShort(&bk_blue); rgbBkColor.rgbBlue = (BYTE)bk_blue; hasBkColor = TRUE; break; case tEXt: mng_SetMetadata_tEXt(key_value_pair, mChunk, mLength); break; case UNKNOWN_CHUNCK: default: break; } // switch( GetChunckType ) } // while(!mEnd) FreeImage_CloseMemory(hJpegMemory); FreeImage_CloseMemory(hPngMemory); FreeImage_CloseMemory(hIDATMemory); free(mChunk); free(PLTE_file_chunk); // convert to 32-bit if a transparent layer is available if(!header_only && dib_alpha) { FIBITMAP *dst = FreeImage_ConvertTo32Bits(dib); if((FreeImage_GetBPP(dib_alpha) == 8) && (FreeImage_GetImageType(dib_alpha) == FIT_BITMAP)) { FreeImage_SetChannel(dst, dib_alpha, FICC_ALPHA); } else { FIBITMAP *dst_alpha = FreeImage_ConvertTo8Bits(dib_alpha); FreeImage_SetChannel(dst, dst_alpha, FICC_ALPHA); FreeImage_Unload(dst_alpha); } FreeImage_Unload(dib); dib = dst; } FreeImage_Unload(dib_alpha); if(dib) { // set metadata FreeImage_SetDotsPerMeterX(dib, res_x); FreeImage_SetDotsPerMeterY(dib, res_y); if(hasBkColor) { FreeImage_SetBackgroundColor(dib, &rgbBkColor); } if(key_value_pair.size()) { for(tEXtMAP::iterator j = key_value_pair.begin(); j != key_value_pair.end(); j++) { std::string key = (*j).first; std::string value = (*j).second; mng_SetKeyValue(FIMD_COMMENTS, dib, key.c_str(), value.c_str()); } } } return dib; } catch(const char *text) { FreeImage_CloseMemory(hJpegMemory); FreeImage_CloseMemory(hPngMemory); FreeImage_CloseMemory(hIDATMemory); free(mChunk); free(PLTE_file_chunk); FreeImage_Unload(dib); FreeImage_Unload(dib_alpha); if(text) { FreeImage_OutputMessageProc(format_id, text); } return NULL; } }