summaryrefslogtreecommitdiff
path: root/plugins/AdvaImg/src/FreeImage/MNGHelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/AdvaImg/src/FreeImage/MNGHelper.cpp')
-rw-r--r--plugins/AdvaImg/src/FreeImage/MNGHelper.cpp1320
1 files changed, 0 insertions, 1320 deletions
diff --git a/plugins/AdvaImg/src/FreeImage/MNGHelper.cpp b/plugins/AdvaImg/src/FreeImage/MNGHelper.cpp
deleted file mode 100644
index 2bc3e833a4..0000000000
--- a/plugins/AdvaImg/src/FreeImage/MNGHelper.cpp
+++ /dev/null
@@ -1,1320 +0,0 @@
-// ==========================================================
-// MNG / JNG helpers
-//
-// Design and implementation by
-// - Hervé Drolon (drolon@infonie.fr)
-//
-// This file is part of FreeImage 3
-//
-// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
-// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
-// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
-// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
-// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
-// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
-// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
-// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
-// THIS DISCLAIMER.
-//
-// Use at your own risk!
-// ==========================================================
-
-#include "FreeImage.h"
-#include "Utilities.h"
-
-/**
-References
-http://www.libpng.org/pub/mng/spec/jng.html
-http://www.w3.org/TR/PNG/
-http://libpng.org/pub/mng/spec/
-*/
-
-// --------------------------------------------------------------------------
-
-#define MNG_INCLUDE_JNG
-
-#ifdef MNG_INCLUDE_JNG
-#define MNG_COLORTYPE_JPEGGRAY 8 /* JHDR */
-#define MNG_COLORTYPE_JPEGCOLOR 10
-#define MNG_COLORTYPE_JPEGGRAYA 12
-#define MNG_COLORTYPE_JPEGCOLORA 14
-
-#define MNG_BITDEPTH_JPEG8 8 /* JHDR */
-#define MNG_BITDEPTH_JPEG12 12
-#define MNG_BITDEPTH_JPEG8AND12 20
-
-#define MNG_COMPRESSION_BASELINEJPEG 8 /* JHDR */
-
-#define MNG_INTERLACE_SEQUENTIAL 0 /* JHDR */
-#define MNG_INTERLACE_PROGRESSIVE 8
-#endif /* MNG_INCLUDE_JNG */
-
-// --------------------------------------------------------------------------
-
-#define JNG_SUPPORTED
-
-/** Size of a JDAT chunk on writing */
-const DWORD JPEG_CHUNK_SIZE = 8192;
-
-/** PNG signature */
-static const BYTE g_png_signature[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
-/** JNG signature */
-static const BYTE g_jng_signature[8] = { 139, 74, 78, 71, 13, 10, 26, 10 };
-
-// --------------------------------------------------------------------------
-
-/** Chunk type converted to enum */
-enum eChunckType {
- UNKNOWN_CHUNCK,
- MHDR,
- BACK,
- BASI,
- CLIP,
- CLON,
- DEFI,
- DHDR,
- DISC,
- ENDL,
- FRAM,
- IEND,
- IHDR,
- JHDR,
- LOOP,
- MAGN,
- MEND,
- MOVE,
- PAST,
- PLTE,
- SAVE,
- SEEK,
- SHOW,
- TERM,
- bKGD,
- cHRM,
- gAMA,
- iCCP,
- nEED,
- pHYg,
- vpAg,
- pHYs,
- sBIT,
- sRGB,
- tRNS,
- IDAT,
- JDAT,
- JDAA,
- JdAA,
- JSEP,
- oFFs,
- hIST,
- iTXt,
- sPLT,
- sTER,
- tEXt,
- tIME,
- zTXt
-};
-
-/**
-Helper for map<key, value> where value is a pointer to a string.
-Used to store tEXt metadata.
-*/
-typedef std::map<std::string, std::string> tEXtMAP;
-
-// --------------------------------------------------------------------------
-
-/*
- Constant strings for known chunk types. If you need to add a chunk,
- add a string holding the name here. To make the code more
- portable, we use ASCII numbers like this, not characters.
-*/
-
-static BYTE mng_MHDR[5]={ 77, 72, 68, 82, (BYTE) '\0'};
-static BYTE mng_BACK[5]={ 66, 65, 67, 75, (BYTE) '\0'};
-static BYTE mng_BASI[5]={ 66, 65, 83, 73, (BYTE) '\0'};
-static BYTE mng_CLIP[5]={ 67, 76, 73, 80, (BYTE) '\0'};
-static BYTE mng_CLON[5]={ 67, 76, 79, 78, (BYTE) '\0'};
-static BYTE mng_DEFI[5]={ 68, 69, 70, 73, (BYTE) '\0'};
-static BYTE mng_DHDR[5]={ 68, 72, 68, 82, (BYTE) '\0'};
-static BYTE mng_DISC[5]={ 68, 73, 83, 67, (BYTE) '\0'};
-static BYTE mng_ENDL[5]={ 69, 78, 68, 76, (BYTE) '\0'};
-static BYTE mng_FRAM[5]={ 70, 82, 65, 77, (BYTE) '\0'};
-static BYTE mng_IEND[5]={ 73, 69, 78, 68, (BYTE) '\0'};
-static BYTE mng_IHDR[5]={ 73, 72, 68, 82, (BYTE) '\0'};
-static BYTE mng_JHDR[5]={ 74, 72, 68, 82, (BYTE) '\0'};
-static BYTE mng_LOOP[5]={ 76, 79, 79, 80, (BYTE) '\0'};
-static BYTE mng_MAGN[5]={ 77, 65, 71, 78, (BYTE) '\0'};
-static BYTE mng_MEND[5]={ 77, 69, 78, 68, (BYTE) '\0'};
-static BYTE mng_MOVE[5]={ 77, 79, 86, 69, (BYTE) '\0'};
-static BYTE mng_PAST[5]={ 80, 65, 83, 84, (BYTE) '\0'};
-static BYTE mng_PLTE[5]={ 80, 76, 84, 69, (BYTE) '\0'};
-static BYTE mng_SAVE[5]={ 83, 65, 86, 69, (BYTE) '\0'};
-static BYTE mng_SEEK[5]={ 83, 69, 69, 75, (BYTE) '\0'};
-static BYTE mng_SHOW[5]={ 83, 72, 79, 87, (BYTE) '\0'};
-static BYTE mng_TERM[5]={ 84, 69, 82, 77, (BYTE) '\0'};
-static BYTE mng_bKGD[5]={ 98, 75, 71, 68, (BYTE) '\0'};
-static BYTE mng_cHRM[5]={ 99, 72, 82, 77, (BYTE) '\0'};
-static BYTE mng_gAMA[5]={103, 65, 77, 65, (BYTE) '\0'};
-static BYTE mng_iCCP[5]={105, 67, 67, 80, (BYTE) '\0'};
-static BYTE mng_nEED[5]={110, 69, 69, 68, (BYTE) '\0'};
-static BYTE mng_pHYg[5]={112, 72, 89, 103, (BYTE) '\0'};
-static BYTE mng_vpAg[5]={118, 112, 65, 103, (BYTE) '\0'};
-static BYTE mng_pHYs[5]={112, 72, 89, 115, (BYTE) '\0'};
-static BYTE mng_sBIT[5]={115, 66, 73, 84, (BYTE) '\0'};
-static BYTE mng_sRGB[5]={115, 82, 71, 66, (BYTE) '\0'};
-static BYTE mng_tRNS[5]={116, 82, 78, 83, (BYTE) '\0'};
-
-#if defined(JNG_SUPPORTED)
-static BYTE mng_IDAT[5]={ 73, 68, 65, 84, (BYTE) '\0'};
-static BYTE mng_JDAT[5]={ 74, 68, 65, 84, (BYTE) '\0'};
-static BYTE mng_JDAA[5]={ 74, 68, 65, 65, (BYTE) '\0'};
-static BYTE mng_JdAA[5]={ 74, 100, 65, 65, (BYTE) '\0'};
-static BYTE mng_JSEP[5]={ 74, 83, 69, 80, (BYTE) '\0'};
-static BYTE mng_oFFs[5]={111, 70, 70, 115, (BYTE) '\0'};
-#endif
-
-static BYTE mng_hIST[5]={104, 73, 83, 84, (BYTE) '\0'};
-static BYTE mng_iTXt[5]={105, 84, 88, 116, (BYTE) '\0'};
-static BYTE mng_sPLT[5]={115, 80, 76, 84, (BYTE) '\0'};
-static BYTE mng_sTER[5]={115, 84, 69, 82, (BYTE) '\0'};
-static BYTE mng_tEXt[5]={116, 69, 88, 116, (BYTE) '\0'};
-static BYTE mng_tIME[5]={116, 73, 77, 69, (BYTE) '\0'};
-static BYTE mng_zTXt[5]={122, 84, 88, 116, (BYTE) '\0'};
-
-
-// --------------------------------------------------------------------------
-
-/**
-Convert a chunk name to a unique ID
-*/
-static eChunckType
-mng_GetChunckType(const BYTE *mChunkName) {
- if(memcmp(mChunkName, mng_MHDR, 4) == 0) {
- return MHDR;
- }
- if(memcmp(mChunkName, mng_LOOP, 4) == 0) {
- return LOOP;
- }
- if(memcmp(mChunkName, mng_DEFI, 4) == 0) {
- return DEFI;
- }
- if(memcmp(mChunkName, mng_PLTE, 4) == 0) {
- return PLTE;
- }
- if(memcmp(mChunkName, mng_tRNS, 4) == 0) {
- return tRNS;
- }
- if(memcmp(mChunkName, mng_IHDR, 4) == 0) {
- return IHDR;
- }
- if(memcmp(mChunkName, mng_JHDR, 4) == 0) {
- return JHDR;
- }
- if(memcmp(mChunkName, mng_MEND, 4) == 0) {
- return MEND;
- }
- if(memcmp(mChunkName, mng_IEND, 4) == 0) {
- return IEND;
- }
- if(memcmp(mChunkName, mng_JDAT, 4) == 0) {
- return JDAT;
- }
- if(memcmp(mChunkName, mng_IDAT, 4) == 0) {
- return IDAT;
- }
- if(memcmp(mChunkName, mng_JDAA, 4) == 0) {
- return JDAA;
- }
- if(memcmp(mChunkName, mng_gAMA, 4) == 0) {
- return gAMA;
- }
- if(memcmp(mChunkName, mng_pHYs, 4) == 0) {
- return pHYs;
- }
- if(memcmp(mChunkName, mng_bKGD, 4) == 0) {
- return bKGD;
- }
- if(memcmp(mChunkName, mng_tEXt, 4) == 0) {
- return tEXt;
- }
-
- return UNKNOWN_CHUNCK;
-}
-
-inline void
-mng_SwapShort(WORD *sp) {
-#ifndef FREEIMAGE_BIGENDIAN
- SwapShort(sp);
-#endif
-}
-
-inline void
-mng_SwapLong(DWORD *lp) {
-#ifndef FREEIMAGE_BIGENDIAN
- SwapLong(lp);
-#endif
-}
-
-/**
-Returns the size, in bytes, of a FreeImageIO stream, from the current position.
-*/
-static long
-mng_LOF(FreeImageIO *io, fi_handle handle) {
- long start_pos = io->tell_proc(handle);
- io->seek_proc(handle, 0, SEEK_END);
- long file_length = io->tell_proc(handle);
- io->seek_proc(handle, start_pos, SEEK_SET);
- return file_length;
-}
-
-/**
-Count the number of bytes in a PNG stream, from IHDR to IEND.
-If successful, the stream position, as given by io->tell_proc(handle),
-should be the end of the PNG stream at the return of the function.
-@param io
-@param handle
-@param inPos
-@param m_TotalBytesOfChunks
-@return Returns TRUE if successful, returns FALSE otherwise
-*/
-static BOOL
-mng_CountPNGChunks(FreeImageIO *io, fi_handle handle, long inPos, unsigned *m_TotalBytesOfChunks) {
- long mLOF;
- long mPos;
- BOOL mEnd = FALSE;
- DWORD mLength = 0;
- BYTE mChunkName[5];
-
- *m_TotalBytesOfChunks = 0;
-
- // get the length of the file
- mLOF = mng_LOF(io, handle);
-
- // go to the start of the file
- io->seek_proc(handle, inPos, SEEK_SET);
-
- try {
- // parse chunks
- while(mEnd == FALSE) {
- // chunk length
- mPos = io->tell_proc(handle);
- if(mPos + 4 > mLOF) {
- throw(1);
- }
- io->read_proc(&mLength, 1, 4, handle);
- mng_SwapLong(&mLength);
- // chunk name
- mPos = io->tell_proc(handle);
- if(mPos + 4 > mLOF) {
- throw(1);
- }
- io->read_proc(&mChunkName[0], 1, 4, handle);
- mChunkName[4] = '\0';
-
- // go to next chunk
- mPos = io->tell_proc(handle);
- // 4 = size of the CRC
- if(mPos + (long)mLength + 4 > mLOF) {
- throw(1);
- }
- io->seek_proc(handle, mLength + 4, SEEK_CUR);
-
- switch( mng_GetChunckType(mChunkName) ) {
- case IHDR:
- if(mLength != 13) {
- throw(1);
- }
- break;
-
- case IEND:
- mEnd = TRUE;
- // the length below includes 4 bytes CRC, but no bytes for Length
- *m_TotalBytesOfChunks = io->tell_proc(handle) - inPos;
- break;
-
- case UNKNOWN_CHUNCK:
- default:
- break;
- }
-
- } // while(!mEnd)
-
- return TRUE;
-
- } catch(int) {
- return FALSE;
- }
-}
-
-/**
-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) {
- 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;
- }
-}
-
-/**
-Remove a chunk located at (start_pos, next_pos) in the PNG stream
-@param hPngMemory PNG stream handle
-@param start_pos Start position of the chunk
-@param next_pos Start position of the next chunk
-@return Returns TRUE if successfull, returns FALSE otherwise
-*/
-static BOOL
-mng_CopyRemoveChunks(FIMEMORY *hPngMemory, DWORD start_pos, DWORD next_pos) {
- BYTE *data = NULL;
- DWORD size_in_bytes = 0;
-
- // length of the chunk to remove
- 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 = size_in_bytes + chunk_length;
-
- BYTE *buffer = (BYTE*)malloc(buffer_size * sizeof(BYTE));
- if(!buffer) {
- return FALSE;
- }
- memcpy(&buffer[0], &data[0], start_pos);
- memcpy(&buffer[start_pos], &data[next_pos], size_in_bytes - next_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;
-}
-
-/**
-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 BOOL
-mng_RemoveChunk(FIMEMORY *hPngMemory, BYTE *chunk_name) {
- BOOL bResult = FALSE;
-
- DWORD start_pos = 0;
- DWORD next_pos = 0;
-
- bResult = mng_FindChunk(hPngMemory, chunk_name, 8, &start_pos, &next_pos);
- if(!bResult) {
- return FALSE;
- }
-
- bResult = mng_CopyRemoveChunks(hPngMemory, start_pos, next_pos);
- if(!bResult) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-static BOOL
-mng_InsertChunk(FIMEMORY *hPngMemory, BYTE *inNextChunkName, BYTE *inInsertChunk, unsigned chunk_length) {
- BOOL bResult = FALSE;
-
- DWORD start_pos = 0;
- DWORD next_pos = 0;
-
- bResult = mng_FindChunk(hPngMemory, inNextChunkName, 8, &start_pos, &next_pos);
- if(!bResult) {
- return FALSE;
- }
-
- bResult = mng_CopyInsertChunks(hPngMemory, inNextChunkName, inInsertChunk, chunk_length, start_pos, next_pos);
- if(!bResult) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-static FIBITMAP*
-mng_LoadFromMemoryHandle(FIMEMORY *hmem, int flags = 0) {
- long offset = 0;
- FIBITMAP *dib = NULL;
-
- if(hmem) {
- // seek to the start of the stream
- FreeImage_SeekMemory(hmem, offset, SEEK_SET);
-
- // check the file signature and deduce its format
- // (the second argument is currently not used by FreeImage)
- FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem, 0);
- if(fif != FIF_UNKNOWN) {
- dib = FreeImage_LoadFromMemory(fif, hmem, flags);
- }
- }
-
- return dib;
-}
-
-/**
-Write a chunk in a PNG stream from the current position.
-@param chunk_name Name of the chunk
-@param chunk_data Chunk array
-@param length Chunk length
-@param hPngMemory PNG stream handle
-*/
-static void
-mng_WriteChunk(BYTE *chunk_name, BYTE *chunk_data, DWORD length, FIMEMORY *hPngMemory) {
- DWORD crc_file = 0;
- // write a PNG chunk ...
- // - length
- mng_SwapLong(&length);
- FreeImage_WriteMemory(&length, 1, 4, hPngMemory);
- mng_SwapLong(&length);
- // - chunk name
- FreeImage_WriteMemory(chunk_name, 1, 4, hPngMemory);
- if(chunk_data && length) {
- // - chunk data
- FreeImage_WriteMemory(chunk_data, 1, length, hPngMemory);
- // - crc
- crc_file = FreeImage_ZLibCRC32(0, chunk_name, 4);
- crc_file = FreeImage_ZLibCRC32(crc_file, chunk_data, length);
- mng_SwapLong(&crc_file);
- FreeImage_WriteMemory(&crc_file, 1, 4, hPngMemory);
- } else {
- // - crc
- crc_file = FreeImage_ZLibCRC32(0, chunk_name, 4);
- mng_SwapLong(&crc_file);
- FreeImage_WriteMemory(&crc_file, 1, 4, hPngMemory);
- }
-
-}
-
-/**
-Wrap a IDAT chunk as a PNG stream.
-The stream has the structure { g_png_signature, IHDR, IDAT, IEND }
-The image is assumed to be a greyscale image.
-
-@param jng_width Image width
-@param jng_height Image height
-@param jng_alpha_sample_depth Bits per pixel
-@param mChunk PNG grayscale IDAT format
-@param mLength IDAT chunk length
-@param hPngMemory Output memory stream
-*/
-static void
-mng_WritePNGStream(DWORD jng_width, DWORD jng_height, BYTE jng_alpha_sample_depth, BYTE *mChunk, DWORD mLength, FIMEMORY *hPngMemory) {
- // PNG grayscale IDAT format
-
- BYTE data[14];
-
- // wrap the IDAT chunk as a PNG stream
-
- // write PNG file signature
- FreeImage_WriteMemory(g_png_signature, 1, 8, hPngMemory);
-
- // write a IHDR chunk ...
- /*
- The IHDR chunk must appear FIRST. It contains:
- Width: 4 bytes
- Height: 4 bytes
- Bit depth: 1 byte
- Color type: 1 byte
- Compression method: 1 byte
- Filter method: 1 byte
- Interlace method: 1 byte
- */
- // - chunk data
- mng_SwapLong(&jng_width);
- mng_SwapLong(&jng_height);
- memcpy(&data[0], &jng_width, 4);
- memcpy(&data[4], &jng_height, 4);
- mng_SwapLong(&jng_width);
- mng_SwapLong(&jng_height);
- data[8] = jng_alpha_sample_depth;
- data[9] = 0; // color_type gray (jng_color_type)
- data[10] = 0; // compression method 0 (jng_alpha_compression_method)
- data[11] = 0; // filter_method 0 (jng_alpha_filter_method)
- data[12] = 0; // interlace_method 0 (jng_alpha_interlace_method)
-
- mng_WriteChunk(mng_IHDR, &data[0], 13, hPngMemory);
-
- // write a IDAT chunk ...
- mng_WriteChunk(mng_IDAT, mChunk, mLength, hPngMemory);
-
- // write a IEND chunk ...
- mng_WriteChunk(mng_IEND, NULL, 0, hPngMemory);
-
-}
-
-// --------------------------------------------------------------------------
-
-/**
-Build and set a FITAG whose type is FIDT_ASCII.
-The tag must be destroyed by the caller using FreeImage_DeleteTag.
-@param model Metadata model to be filled
-@param dib Image to be filled
-@param key Tag key
-@param value Tag value
-@return Returns TRUE if successful, returns FALSE otherwise
-*/
-static BOOL
-mng_SetKeyValue(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, const char *value) {
- if(!dib || !key || !value) {
- return FALSE;
- }
- // create a tag
- FITAG *tag = FreeImage_CreateTag();
- if(tag) {
- BOOL bSuccess = TRUE;
- // fill the tag
- DWORD tag_length = (DWORD)(strlen(value) + 1);
- bSuccess &= FreeImage_SetTagKey(tag, key);
- bSuccess &= FreeImage_SetTagLength(tag, tag_length);
- bSuccess &= FreeImage_SetTagCount(tag, tag_length);
- bSuccess &= FreeImage_SetTagType(tag, FIDT_ASCII);
- bSuccess &= FreeImage_SetTagValue(tag, value);
- if(bSuccess) {
- // set the tag
- FreeImage_SetMetadata(model, dib, FreeImage_GetTagKey(tag), tag);
- }
- FreeImage_DeleteTag(tag);
- return bSuccess;
- }
-
- return FALSE;
-}
-
-/**
-Read a tEXt chunk and extract the key/value pair.
-@param key_value_pair [returned value] Array of key/value pairs
-@param mChunk Chunk data
-@param mLength Chunk length
-@return Returns TRUE if successful, returns FALSE otherwise
-*/
-static BOOL
-mng_SetMetadata_tEXt(tEXtMAP &key_value_pair, const BYTE *mChunk, DWORD mLength) {
- std::string key;
- std::string value;
- BYTE *buffer = (BYTE*)malloc(mLength * sizeof(BYTE));
- if(!buffer) {
- return FALSE;
- }
- DWORD pos = 0;
-
- memset(buffer, 0, mLength * sizeof(BYTE));
-
- for(DWORD i = 0; i < mLength; i++) {
- buffer[pos++] = mChunk[i];
- if(mChunk[i] == '\0') {
- if(key.size() == 0) {
- key = (char*)buffer;
- pos = 0;
- memset(buffer, 0, mLength * sizeof(BYTE));
- } else {
- break;
- }
- }
- }
- value = (char*)buffer;
- free(buffer);
-
- key_value_pair[key] = value;
-
- return TRUE;
-}
-
-// --------------------------------------------------------------------------
-
-/**
-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;
- }
-}
-
-// --------------------------------------------------------------------------
-
-/**
-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;
- }
-}