diff options
author | Kirill Volinsky <mataes2007@gmail.com> | 2015-05-18 07:49:16 +0000 |
---|---|---|
committer | Kirill Volinsky <mataes2007@gmail.com> | 2015-05-18 07:49:16 +0000 |
commit | c4c881e04ba970c6ce373fc9333d6911f8a47a7d (patch) | |
tree | d3533f41a25a8ad09eddfd7eb19fda8e37acb7d8 /plugins/AdvaImg/src/FreeImage | |
parent | 68702ead76c7e204b3c857e496686f1a7556cae1 (diff) |
removed not used files
git-svn-id: http://svn.miranda-ng.org/main/trunk@13674 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/AdvaImg/src/FreeImage')
28 files changed, 1 insertions, 17511 deletions
diff --git a/plugins/AdvaImg/src/FreeImage/Plugin.cpp b/plugins/AdvaImg/src/FreeImage/Plugin.cpp index 13da67434e..171b4682b8 100644 --- a/plugins/AdvaImg/src/FreeImage/Plugin.cpp +++ b/plugins/AdvaImg/src/FreeImage/Plugin.cpp @@ -257,7 +257,7 @@ FreeImage_Initialise(BOOL load_local_plugins_only) { //s_plugins->AddNode(InitTIFF); //s_plugins->AddNode(InitWBMP); //s_plugins->AddNode(InitPSD); - s_plugins->AddNode(InitCUT); + //s_plugins->AddNode(InitCUT); //s_plugins->AddNode(InitXBM); //s_plugins->AddNode(InitXPM); //s_plugins->AddNode(InitDDS); diff --git a/plugins/AdvaImg/src/FreeImage/PluginCUT.cpp b/plugins/AdvaImg/src/FreeImage/PluginCUT.cpp deleted file mode 100644 index 5dcd16b84f..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginCUT.cpp +++ /dev/null @@ -1,240 +0,0 @@ -// ========================================================== -// CUT Loader -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// -// 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" - -// ---------------------------------------------------------- -// Constants + headers -// ---------------------------------------------------------- - -#ifdef _WIN32 -#pragma pack(push, 1) -#else -#pragma pack(1) -#endif - -typedef struct tagCUTHEADER { - WORD width; - WORD height; - LONG dummy; -} CUTHEADER; - -#ifdef _WIN32 -#pragma pack(pop) -#else -#pragma pack() -#endif - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "CUT"; -} - -static const char * DLL_CALLCONV -Description() { - return "Dr. Halo"; -} - -static const char * DLL_CALLCONV -Extension() { - return "cut"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-cut"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - FIBITMAP *dib = NULL; - - if(!handle) { - return NULL; - } - - try { - CUTHEADER header; - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // read the cut header - - if(io->read_proc(&header, 1, sizeof(CUTHEADER), handle) != sizeof(CUTHEADER)) { - throw FI_MSG_ERROR_PARSING; - } - -#ifdef FREEIMAGE_BIGENDIAN - SwapShort((WORD *)&header.width); - SwapShort((WORD *)&header.height); -#endif - - if ((header.width == 0) || (header.height == 0)) { - return NULL; - } - - // allocate a new bitmap - - dib = FreeImage_AllocateHeader(header_only, header.width, header.height, 8); - - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // stuff it with a palette - - RGBQUAD *palette = FreeImage_GetPalette(dib); - - for (int j = 0; j < 256; ++j) { - palette[j].rgbBlue = palette[j].rgbGreen = palette[j].rgbRed = (BYTE)j; - } - - if(header_only) { - // header only mode - return dib; - } - - // unpack the RLE bitmap bits - - BYTE *bits = FreeImage_GetScanLine(dib, header.height - 1); - - unsigned i = 0, k = 0; - unsigned pitch = FreeImage_GetPitch(dib); - unsigned size = header.width * header.height; - BYTE count = 0, run = 0; - - while (i < size) { - if(io->read_proc(&count, 1, sizeof(BYTE), handle) != 1) { - throw FI_MSG_ERROR_PARSING; - } - - if (count == 0) { - k = 0; - bits -= pitch; - - // paint shop pro adds two useless bytes here... - - io->read_proc(&count, 1, sizeof(BYTE), handle); - io->read_proc(&count, 1, sizeof(BYTE), handle); - - continue; - } - - if (count & 0x80) { - count &= ~(0x80); - - if(io->read_proc(&run, 1, sizeof(BYTE), handle) != 1) { - throw FI_MSG_ERROR_PARSING; - } - - if(k + count <= header.width) { - memset(bits + k, run, count); - } else { - throw FI_MSG_ERROR_PARSING; - } - } else { - if(k + count <= header.width) { - if(io->read_proc(&bits[k], count, sizeof(BYTE), handle) != 1) { - throw FI_MSG_ERROR_PARSING; - } - } else { - throw FI_MSG_ERROR_PARSING; - } - } - - k += count; - i += count; - } - - return dib; - - } catch(const char* text) { - if(dib) { - FreeImage_Unload(dib); - } - FreeImage_OutputMessageProc(s_format_id, text); - return NULL; - } -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitCUT(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = NULL; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginDDS.cpp b/plugins/AdvaImg/src/FreeImage/PluginDDS.cpp deleted file mode 100644 index 639942388f..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginDDS.cpp +++ /dev/null @@ -1,655 +0,0 @@ -// ========================================================== -// DDS Loader -// -// Design and implementation by -// - Volker Gärtner (volkerg@gmx.at) -// - Sherman Wilcox -// -// 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" - -// ---------------------------------------------------------- -// Definitions for the DDS format -// ---------------------------------------------------------- - -#ifdef _WIN32 -#pragma pack(push, 1) -#else -#pragma pack(1) -#endif - -typedef struct tagDDPIXELFORMAT { - DWORD dwSize; // size of this structure (must be 32) - DWORD dwFlags; // see DDPF_* - DWORD dwFourCC; - DWORD dwRGBBitCount; // Total number of bits for RGB formats - DWORD dwRBitMask; - DWORD dwGBitMask; - DWORD dwBBitMask; - DWORD dwRGBAlphaBitMask; -} DDPIXELFORMAT; - -// DIRECTDRAW PIXELFORMAT FLAGS -enum { - DDPF_ALPHAPIXELS = 0x00000001l, // surface has alpha channel - DDPF_ALPHA = 0x00000002l, // alpha only - DDPF_FOURCC = 0x00000004l, // FOURCC available - DDPF_RGB = 0x00000040l // RGB(A) bitmap -}; - -typedef struct tagDDCAPS2 { - DWORD dwCaps1; // Zero or more of the DDSCAPS_* members - DWORD dwCaps2; // Zero or more of the DDSCAPS2_* members - DWORD dwReserved[2]; -} DDCAPS2; - -// DIRECTDRAWSURFACE CAPABILITY FLAGS -enum { - DDSCAPS_ALPHA = 0x00000002l, // alpha only surface - DDSCAPS_COMPLEX = 0x00000008l, // complex surface structure - DDSCAPS_TEXTURE = 0x00001000l, // used as texture (should always be set) - DDSCAPS_MIPMAP = 0x00400000l // Mipmap present -}; - -enum { - DDSCAPS2_CUBEMAP = 0x00000200L, - DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400L, - DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800L, - DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000L, - DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000L, - DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000L, - DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000L, - DDSCAPS2_VOLUME = 0x00200000L -}; - -typedef struct tagDDSURFACEDESC2 { - DWORD dwSize; // size of this structure (must be 124) - DWORD dwFlags; // combination of the DDSS_* flags - DWORD dwHeight; - DWORD dwWidth; - DWORD dwPitchOrLinearSize; - DWORD dwDepth; // Depth of a volume texture - DWORD dwMipMapCount; - DWORD dwReserved1[11]; - DDPIXELFORMAT ddpfPixelFormat; - DDCAPS2 ddsCaps; - DWORD dwReserved2; -} DDSURFACEDESC2; - -enum { - DDSD_CAPS = 0x00000001l, - DDSD_HEIGHT = 0x00000002l, - DDSD_WITH = 0x00000004l, - DDSD_PITCH = 0x00000008l, - DDSD_ALPHABITDEPTH = 0x00000080l, - DDSD_PIXELFORMAT = 0x00001000l, - DDSD_MIPMAPCOUNT = 0x00020000l, - DDSD_LINEARSIZE = 0x00080000l, - DDSD_DEPTH = 0x00800000l -}; - -typedef struct tagDDSHEADER { - DWORD dwMagic; // FOURCC: "DDS " - DDSURFACEDESC2 surfaceDesc; -} DDSHEADER; - -#define MAKEFOURCC(ch0, ch1, ch2, ch3) \ - ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \ - ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 )) - -#define FOURCC_DXT1 MAKEFOURCC('D','X','T','1') -#define FOURCC_DXT2 MAKEFOURCC('D','X','T','2') -#define FOURCC_DXT3 MAKEFOURCC('D','X','T','3') -#define FOURCC_DXT4 MAKEFOURCC('D','X','T','4') -#define FOURCC_DXT5 MAKEFOURCC('D','X','T','5') - -// ---------------------------------------------------------- -// Structures used by DXT textures -// ---------------------------------------------------------- - -typedef struct tagColor8888 { - BYTE b; - BYTE g; - BYTE r; - BYTE a; -} Color8888; - -typedef struct tagColor565 { - WORD b : 5; - WORD g : 6; - WORD r : 5; -} Color565; - -typedef struct tagDXTColBlock { - Color565 colors[2]; - BYTE row[4]; -} DXTColBlock; - -typedef struct tagDXTAlphaBlockExplicit { - WORD row[4]; -} DXTAlphaBlockExplicit; - -typedef struct tagDXTAlphaBlock3BitLinear { - BYTE alpha[2]; - BYTE data[6]; -} DXTAlphaBlock3BitLinear; - -typedef struct tagDXT1Block -{ - DXTColBlock color; -} DXT1Block; - -typedef struct tagDXT3Block { // also used by dxt2 - DXTAlphaBlockExplicit alpha; - DXTColBlock color; -} DXT3Block; - -typedef struct tagDXT5Block { // also used by dxt4 - DXTAlphaBlock3BitLinear alpha; - DXTColBlock color; -} DXT5Block; - -#ifdef _WIN32 -# pragma pack(pop) -#else -# pragma pack() -#endif - -// ---------------------------------------------------------- -// Internal functions -// ---------------------------------------------------------- -#ifdef FREEIMAGE_BIGENDIAN -static void -SwapHeader(DDSHEADER *header) { - SwapLong(&header->dwMagic); - SwapLong(&header->surfaceDesc.dwSize); - SwapLong(&header->surfaceDesc.dwFlags); - SwapLong(&header->surfaceDesc.dwHeight); - SwapLong(&header->surfaceDesc.dwWidth); - SwapLong(&header->surfaceDesc.dwPitchOrLinearSize); - SwapLong(&header->surfaceDesc.dwDepth); - SwapLong(&header->surfaceDesc.dwMipMapCount); - for(int i=0; i<11; i++) { - SwapLong(&header->surfaceDesc.dwReserved1[i]); - } - SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwSize); - SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwFlags); - SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwFourCC); - SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwRGBBitCount); - SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwRBitMask); - SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwGBitMask); - SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwBBitMask); - SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwRGBAlphaBitMask); - SwapLong(&header->surfaceDesc.ddsCaps.dwCaps1); - SwapLong(&header->surfaceDesc.ddsCaps.dwCaps2); - SwapLong(&header->surfaceDesc.ddsCaps.dwReserved[0]); - SwapLong(&header->surfaceDesc.ddsCaps.dwReserved[1]); - SwapLong(&header->surfaceDesc.dwReserved2); -} -#endif - -// ========================================================== - -// Get the 4 possible colors for a block -// -static void -GetBlockColors (const DXTColBlock &block, Color8888 colors[4], bool isDXT1) { - int i; - // expand from 565 to 888 - for (i = 0; i < 2; i++) { - colors[i].a = 0xff; - /* - colors[i].r = (BYTE)(block.colors[i].r * 0xff / 0x1f); - colors[i].g = (BYTE)(block.colors[i].g * 0xff / 0x3f); - colors[i].b = (BYTE)(block.colors[i].b * 0xff / 0x1f); - */ - colors[i].r = (BYTE)((block.colors[i].r << 3U) | (block.colors[i].r >> 2U)); - colors[i].g = (BYTE)((block.colors[i].g << 2U) | (block.colors[i].g >> 4U)); - colors[i].b = (BYTE)((block.colors[i].b << 3U) | (block.colors[i].b >> 2U)); - } - - WORD *wCol = (WORD *)block.colors; - if (wCol[0] > wCol[1] || !isDXT1) { - // 4 color block - for (i = 0; i < 2; i++) { - colors[i + 2].a = 0xff; - colors[i + 2].r = (BYTE)((WORD (colors[0].r) * (2 - i) + WORD (colors[1].r) * (1 + i)) / 3); - colors[i + 2].g = (BYTE)((WORD (colors[0].g) * (2 - i) + WORD (colors[1].g) * (1 + i)) / 3); - colors[i + 2].b = (BYTE)((WORD (colors[0].b) * (2 - i) + WORD (colors[1].b) * (1 + i)) / 3); - } - } - else { - // 3 color block, number 4 is transparent - colors[2].a = 0xff; - colors[2].r = (BYTE)((WORD (colors[0].r) + WORD (colors[1].r)) / 2); - colors[2].g = (BYTE)((WORD (colors[0].g) + WORD (colors[1].g)) / 2); - colors[2].b = (BYTE)((WORD (colors[0].b) + WORD (colors[1].b)) / 2); - - colors[3].a = 0x00; - colors[3].g = 0x00; - colors[3].b = 0x00; - colors[3].r = 0x00; - } -} - -struct DXT_INFO_1 { - typedef DXT1Block Block; - enum { - isDXT1 = 1, - bytesPerBlock = 8 - }; -}; - -struct DXT_INFO_3 { - typedef DXT3Block Block; - enum { - isDXT1 = 1, - bytesPerBlock = 16 - }; -}; - -struct DXT_INFO_5 { - typedef DXT5Block Block; - enum - { - isDXT1 = 1, - bytesPerBlock = 16 - }; -}; - -template <class INFO> class DXT_BLOCKDECODER_BASE { -protected: - Color8888 m_colors[4]; - const typename INFO::Block *m_pBlock; - unsigned m_colorRow; - -public: - void Setup (const BYTE *pBlock) { - m_pBlock = (const typename INFO::Block *)pBlock; - GetBlockColors (m_pBlock->color, m_colors, INFO::isDXT1); - } - - void SetY (int y) { - m_colorRow = m_pBlock->color.row[y]; - } - - void GetColor (int x, int y, Color8888 &color) { - unsigned bits = (m_colorRow >> (x * 2)) & 3; - color = m_colors[bits]; - } -}; - -class DXT_BLOCKDECODER_1 : public DXT_BLOCKDECODER_BASE <DXT_INFO_1> { -public: - typedef DXT_INFO_1 INFO; -}; - -class DXT_BLOCKDECODER_3 : public DXT_BLOCKDECODER_BASE <DXT_INFO_3> { -public: - typedef DXT_BLOCKDECODER_BASE <DXT_INFO_3> base; - typedef DXT_INFO_3 INFO; - -protected: - unsigned m_alphaRow; - -public: - void SetY (int y) { - base::SetY (y); - m_alphaRow = m_pBlock->alpha.row[y]; - } - - void GetColor (int x, int y, Color8888 &color) { - base::GetColor (x, y, color); - const unsigned bits = (m_alphaRow >> (x * 4)) & 0xF; - color.a = (BYTE)((bits * 0xFF) / 0xF); - } -}; - -class DXT_BLOCKDECODER_5 : public DXT_BLOCKDECODER_BASE <DXT_INFO_5> { -public: - typedef DXT_BLOCKDECODER_BASE <DXT_INFO_5> base; - typedef DXT_INFO_5 INFO; - -protected: - unsigned m_alphas[8]; - unsigned m_alphaBits; - int m_offset; - -public: - void Setup (const BYTE *pBlock) { - base::Setup (pBlock); - - const DXTAlphaBlock3BitLinear &block = m_pBlock->alpha; - m_alphas[0] = block.alpha[0]; - m_alphas[1] = block.alpha[1]; - if (m_alphas[0] > m_alphas[1]) { - // 8 alpha block - for (int i = 0; i < 6; i++) { - m_alphas[i + 2] = ((6 - i) * m_alphas[0] + (1 + i) * m_alphas[1] + 3) / 7; - } - } - else { - // 6 alpha block - for (int i = 0; i < 4; i++) { - m_alphas[i + 2] = ((4 - i) * m_alphas[0] + (1 + i) * m_alphas[1] + 2) / 5; - } - m_alphas[6] = 0; - m_alphas[7] = 0xFF; - } - - } - - void SetY (int y) { - base::SetY (y); - int i = y / 2; - const DXTAlphaBlock3BitLinear &block = m_pBlock->alpha; - m_alphaBits = unsigned(block.data[0 + i * 3]) | (unsigned(block.data[1 + i * 3]) << 8) - | (unsigned(block.data[2 + i * 3]) << 16); - m_offset = (y & 1) * 12; - } - - void GetColor (int x, int y, Color8888 &color) { - base::GetColor (x, y, color); - unsigned bits = (m_alphaBits >> (x * 3 + m_offset)) & 7; - color.a = (BYTE)m_alphas[bits]; - } -}; - -template <class DECODER> void DecodeDXTBlock (BYTE *dstData, const BYTE *srcBlock, long dstPitch, int bw, int bh) { - DECODER decoder; - decoder.Setup (srcBlock); - for (int y = 0; y < bh; y++) { - BYTE *dst = dstData - y * dstPitch; - decoder.SetY (y); - for (int x = 0; x < bw; x++) { - decoder.GetColor (x, y, (Color8888 &)*dst); - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - INPLACESWAP(dst[FI_RGBA_RED], dst[FI_RGBA_BLUE]); -#endif - dst += 4; - } - } -} - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Internal functions -// ========================================================== - -static FIBITMAP * -LoadRGB (DDSURFACEDESC2 &desc, FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - int width = (int)desc.dwWidth & ~3; - int height = (int)desc.dwHeight & ~3; - int bpp = (int)desc.ddpfPixelFormat.dwRGBBitCount; - - // allocate a new dib - FIBITMAP *dib = FreeImage_Allocate (width, height, bpp, desc.ddpfPixelFormat.dwRBitMask, - desc.ddpfPixelFormat.dwGBitMask, desc.ddpfPixelFormat.dwBBitMask); - if (dib == NULL) - return NULL; - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - // Calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit) - int bytespp = FreeImage_GetLine(dib) / FreeImage_GetWidth(dib); -#endif - - // read the file - int line = CalculateLine(width, bpp); - int filePitch = (desc.dwFlags & DDSD_PITCH) ? (int)desc.dwPitchOrLinearSize : line; - long delta = (long)filePitch - (long)line; - for (int i = 0; i < height; i++) { - BYTE *pixels = FreeImage_GetScanLine(dib, height - i - 1); - io->read_proc (pixels, 1, line, handle); - io->seek_proc (handle, delta, SEEK_CUR); -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - for(int x = 0; x < width; x++) { - INPLACESWAP(pixels[FI_RGBA_RED],pixels[FI_RGBA_BLUE]); - pixels += bytespp; - } -#endif - } - - // enable transparency - FreeImage_SetTransparent (dib, (desc.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) ? TRUE : FALSE); - - if (!(desc.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) && bpp == 32) { - // no transparency: convert to 24-bit - FIBITMAP *old = dib; - dib = FreeImage_ConvertTo24Bits (old); - FreeImage_Unload (old); - } - return dib; -} - -template <class DECODER> static void -LoadDXT_Helper (FreeImageIO *io, fi_handle handle, int page, int flags, void *data, FIBITMAP *dib, int width, int height, int line) { - typedef typename DECODER::INFO INFO; - typedef typename INFO::Block Block; - - Block *input_buffer = new(std::nothrow) Block[(width + 3) / 4]; - if(!input_buffer) return; - - int widthRest = (int) width & 3; - int heightRest = (int) height & 3; - int inputLine = (width + 3) / 4; - int y = 0; - - if (height >= 4) { - for (; y < height; y += 4) { - io->read_proc (input_buffer, sizeof (typename INFO::Block), inputLine, handle); - // TODO: probably need some endian work here - BYTE *pbSrc = (BYTE *)input_buffer; - BYTE *pbDst = FreeImage_GetScanLine (dib, height - y - 1); - - if (width >= 4) { - for (int x = 0; x < width; x += 4) { - DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, 4, 4); - pbSrc += INFO::bytesPerBlock; - pbDst += 4 * 4; - } - } - if (widthRest) { - DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, widthRest, 4); - } - } - } - if (heightRest) { - io->read_proc (input_buffer, sizeof (typename INFO::Block), inputLine, handle); - // TODO: probably need some endian work here - BYTE *pbSrc = (BYTE *)input_buffer; - BYTE *pbDst = FreeImage_GetScanLine (dib, height - y - 1); - - if (width >= 4) { - for (int x = 0; x < width; x += 4) { - DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, 4, heightRest); - pbSrc += INFO::bytesPerBlock; - pbDst += 4 * 4; - } - } - if (widthRest) { - DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, widthRest, heightRest); - } - - } - - delete [] input_buffer; -} - -static FIBITMAP * -LoadDXT (int type, DDSURFACEDESC2 &desc, FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - int width = (int)desc.dwWidth & ~3; - int height = (int)desc.dwHeight & ~3; - - // allocate a 32-bit dib - FIBITMAP *dib = FreeImage_Allocate (width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if (dib == NULL) - return NULL; - - int bpp = FreeImage_GetBPP (dib); - int line = CalculateLine (width, bpp); - BYTE *bits = FreeImage_GetBits (dib); - - // select the right decoder - switch (type) { - case 1: - LoadDXT_Helper <DXT_BLOCKDECODER_1> (io, handle, page, flags, data, dib, width, height, line); - break; - case 3: - LoadDXT_Helper <DXT_BLOCKDECODER_3> (io, handle, page, flags, data, dib, width, height, line); - break; - case 5: - LoadDXT_Helper <DXT_BLOCKDECODER_5> (io, handle, page, flags, data, dib, width, height, line); - break; - } - - return dib; -} -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "DDS"; -} - -static const char * DLL_CALLCONV -Description() { - return "DirectX Surface"; -} - -static const char * DLL_CALLCONV -Extension() { - return "dds"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-dds"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - DDSHEADER header; - memset(&header, 0, sizeof(header)); - io->read_proc(&header, 1, sizeof(header), handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapHeader(&header); -#endif - if (header.dwMagic != MAKEFOURCC ('D','D','S',' ')) - return FALSE; - if (header.surfaceDesc.dwSize != sizeof (header.surfaceDesc) || - header.surfaceDesc.ddpfPixelFormat.dwSize != sizeof (header.surfaceDesc.ddpfPixelFormat)) - return FALSE; - return TRUE; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return FALSE; -} - -// ---------------------------------------------------------- - -static void * DLL_CALLCONV -Open(FreeImageIO *io, fi_handle handle, BOOL read) { - return NULL; -} - -static void DLL_CALLCONV -Close(FreeImageIO *io, fi_handle handle, void *data) { -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - DDSHEADER header; - FIBITMAP *dib = NULL; - - memset(&header, 0, sizeof(header)); - io->read_proc(&header, 1, sizeof(header), handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapHeader(&header); -#endif - if (header.surfaceDesc.ddpfPixelFormat.dwFlags & DDPF_RGB) { - dib = LoadRGB (header.surfaceDesc, io, handle, page, flags, data); - } - else if (header.surfaceDesc.ddpfPixelFormat.dwFlags & DDPF_FOURCC) { - switch (header.surfaceDesc.ddpfPixelFormat.dwFourCC) { - case FOURCC_DXT1: - dib = LoadDXT (1, header.surfaceDesc, io, handle, page, flags, data); - break; - case FOURCC_DXT3: - dib = LoadDXT (3, header.surfaceDesc, io, handle, page, flags, data); - break; - case FOURCC_DXT5: - dib = LoadDXT (5, header.surfaceDesc, io, handle, page, flags, data); - break; - } - } - return dib; -} - -/* -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - return FALSE; -} -*/ - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitDDS(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = Open; - plugin->close_proc = Close; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = NULL; //Save; // not implemented (yet?) - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginEXR.cpp b/plugins/AdvaImg/src/FreeImage/PluginEXR.cpp deleted file mode 100644 index b286430380..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginEXR.cpp +++ /dev/null @@ -1,773 +0,0 @@ -// ========================================================== -// EXR Loader and writer -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// 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" - -#ifdef _MSC_VER -// OpenEXR has many problems with MSVC warnings (why not just correct them ?), just ignore one of them -#pragma warning (disable : 4800) // ImfVersion.h - 'const int' : forcing value to bool 'true' or 'false' (performance warning) -#endif - -#include "../OpenEXR/IlmImf/ImfIO.h" -#include "../OpenEXR/Iex/Iex.h" -#include "../OpenEXR/IlmImf/ImfOutputFile.h" -#include "../OpenEXR/IlmImf/ImfInputFile.h" -#include "../OpenEXR/IlmImf/ImfRgbaFile.h" -#include "../OpenEXR/IlmImf/ImfChannelList.h" -#include "../OpenEXR/IlmImf/ImfRgba.h" -#include "../OpenEXR/IlmImf/ImfArray.h" -#include "../OpenEXR/IlmImf/ImfPreviewImage.h" -#include "../OpenEXR/Half/half.h" - - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ---------------------------------------------------------- - -/** -FreeImage input stream wrapper -@see Imf_2_2::IStream -*/ -class C_IStream : public Imf::IStream { -private: - FreeImageIO *_io; - fi_handle _handle; - -public: - C_IStream (FreeImageIO *io, fi_handle handle) : - Imf::IStream(""), _io (io), _handle(handle) { - } - - virtual bool read (char c[/*n*/], int n) { - return ((unsigned)n != _io->read_proc(c, 1, n, _handle)); - } - - virtual Imath::Int64 tellg() { - return _io->tell_proc(_handle); - } - - virtual void seekg(Imath::Int64 pos) { - _io->seek_proc(_handle, (unsigned)pos, SEEK_SET); - } - - virtual void clear() { - } -}; - -// ---------------------------------------------------------- - -/** -FreeImage output stream wrapper -@see Imf_2_2::OStream -*/ -class C_OStream : public Imf::OStream { -private: - FreeImageIO *_io; - fi_handle _handle; - -public: - C_OStream (FreeImageIO *io, fi_handle handle) : - Imf::OStream(""), _io (io), _handle(handle) { - } - - virtual void write(const char c[/*n*/], int n) { - if((unsigned)n != _io->write_proc((void*)&c[0], 1, n, _handle)) { - Iex::throwErrnoExc(); - } - } - - virtual Imath::Int64 tellp() { - return _io->tell_proc(_handle); - } - - virtual void seekp(Imath::Int64 pos) { - _io->seek_proc(_handle, (unsigned)pos, SEEK_SET); - } -}; - -// ---------------------------------------------------------- - - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "EXR"; -} - -static const char * DLL_CALLCONV -Description() { - return "ILM OpenEXR"; -} - -static const char * DLL_CALLCONV -Extension() { - return "exr"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-exr"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE exr_signature[] = { 0x76, 0x2F, 0x31, 0x01 }; - BYTE signature[] = { 0, 0, 0, 0 }; - - io->read_proc(signature, 1, 4, handle); - return (memcmp(exr_signature, signature, 4) == 0); -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return ( - (type == FIT_FLOAT) || - (type == FIT_RGBF) || - (type == FIT_RGBAF) - ); -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// -------------------------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - bool bUseRgbaInterface = false; - FIBITMAP *dib = NULL; - - if(!handle) { - return NULL; - } - - try { - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // save the stream starting point - const long stream_start = io->tell_proc(handle); - - // wrap the FreeImage IO stream - C_IStream istream(io, handle); - - // open the file - Imf::InputFile file(istream); - - // get file info - const Imath::Box2i &dataWindow = file.header().dataWindow(); - int width = dataWindow.max.x - dataWindow.min.x + 1; - int height = dataWindow.max.y - dataWindow.min.y + 1; - - //const Imf::Compression &compression = file.header().compression(); - - const Imf::ChannelList &channels = file.header().channels(); - - // check the number of components and check for a coherent format - - std::string exr_color_model; - Imf::PixelType pixel_type = Imf::HALF; - FREE_IMAGE_TYPE image_type = FIT_UNKNOWN; - int components = 0; - bool bMixedComponents = false; - - for (Imf::ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) { - components++; - if(components == 1) { - exr_color_model += i.name(); - pixel_type = i.channel().type; - } else { - exr_color_model += "/"; - exr_color_model += i.name(); - if (i.channel().type != pixel_type) { - bMixedComponents = true; - } - } - } - - if(bMixedComponents) { - bool bHandled = false; - // we may have a RGBZ or RGBAZ image ... - if(components > 4) { - if(channels.findChannel("R") && channels.findChannel("G") && channels.findChannel("B") && channels.findChannel("A")) { - std::string msg = "Warning: converting color model " + exr_color_model + " to RGBA color model"; - FreeImage_OutputMessageProc(s_format_id, msg.c_str()); - bHandled = true; - } - } - else if(components > 3) { - if(channels.findChannel("R") && channels.findChannel("G") && channels.findChannel("B")) { - std::string msg = "Warning: converting color model " + exr_color_model + " to RGB color model"; - FreeImage_OutputMessageProc(s_format_id, msg.c_str()); - bHandled = true; - } - } - if(!bHandled) { - THROW (Iex::InputExc, "Unable to handle mixed component types (color model = " << exr_color_model << ")"); - } - } - - switch(pixel_type) { - case Imf::UINT: - THROW (Iex::InputExc, "Unsupported format: UINT"); - break; - case Imf::HALF: - case Imf::FLOAT: - default: - break; - } - - // check for supported image color models - // -------------------------------------------------------------- - - if((components == 1) || (components == 2)) { - // if the image is gray-alpha (YA), ignore the alpha channel - if((components == 1) && channels.findChannel("Y")) { - image_type = FIT_FLOAT; - components = 1; - } else { - std::string msg = "Warning: loading color model " + exr_color_model + " as Y color model"; - FreeImage_OutputMessageProc(s_format_id, msg.c_str()); - image_type = FIT_FLOAT; - // ignore the other channel - components = 1; - } - } else if(components == 3) { - if(channels.findChannel("R") && channels.findChannel("G") && channels.findChannel("B")) { - image_type = FIT_RGBF; - } - else if(channels.findChannel("BY") && channels.findChannel("RY") && channels.findChannel("Y")) { - image_type = FIT_RGBF; - bUseRgbaInterface = true; - } - } else if(components >= 4) { - if(channels.findChannel("R") && channels.findChannel("G") && channels.findChannel("B")) { - if(channels.findChannel("A")) { - if(components > 4) { - std::string msg = "Warning: converting color model " + exr_color_model + " to RGBA color model"; - FreeImage_OutputMessageProc(s_format_id, msg.c_str()); - } - image_type = FIT_RGBAF; - // ignore other layers if there is more than one alpha layer - components = 4; - } else { - std::string msg = "Warning: converting color model " + exr_color_model + " to RGB color model"; - FreeImage_OutputMessageProc(s_format_id, msg.c_str()); - - image_type = FIT_RGBF; - // ignore other channels - components = 3; - } - } - } - - if(image_type == FIT_UNKNOWN) { - THROW (Iex::InputExc, "Unsupported color model: " << exr_color_model); - } - - // allocate a new dib - dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, 0); - if(!dib) THROW (Iex::NullExc, FI_MSG_ERROR_MEMORY); - - // try to load the preview image - // -------------------------------------------------------------- - - if(file.header().hasPreviewImage()) { - const Imf::PreviewImage& preview = file.header().previewImage(); - const unsigned thWidth = preview.width(); - const unsigned thHeight = preview.height(); - - FIBITMAP* thumbnail = FreeImage_Allocate(thWidth, thHeight, 32); - if(thumbnail) { - const Imf::PreviewRgba *src_line = preview.pixels(); - BYTE *dst_line = FreeImage_GetScanLine(thumbnail, thHeight - 1); - const unsigned dstPitch = FreeImage_GetPitch(thumbnail); - - for (unsigned y = 0; y < thHeight; ++y) { - const Imf::PreviewRgba *src_pixel = src_line; - RGBQUAD* dst_pixel = (RGBQUAD*)dst_line; - - for(unsigned x = 0; x < thWidth; ++x) { - dst_pixel->rgbRed = src_pixel->r; - dst_pixel->rgbGreen = src_pixel->g; - dst_pixel->rgbBlue = src_pixel->b; - dst_pixel->rgbReserved = src_pixel->a; - src_pixel++; - dst_pixel++; - } - src_line += thWidth; - dst_line -= dstPitch; - } - FreeImage_SetThumbnail(dib, thumbnail); - FreeImage_Unload(thumbnail); - } - } - - if(header_only) { - // header only mode - return dib; - } - - // load pixels - // -------------------------------------------------------------- - - const BYTE *bits = FreeImage_GetBits(dib); // pointer to our pixel buffer - const size_t bytespp = sizeof(float) * components; // size of our pixel in bytes - const unsigned pitch = FreeImage_GetPitch(dib); // size of our yStride in bytes - - Imf::PixelType pixelType = Imf::FLOAT; // load as float data type; - - if(bUseRgbaInterface) { - // use the RGBA interface (used when loading RY BY Y images ) - - const int chunk_size = 16; - - BYTE *scanline = (BYTE*)bits; - - // re-open using the RGBA interface - io->seek_proc(handle, stream_start, SEEK_SET); - Imf::RgbaInputFile rgbaFile(istream); - - // read the file in chunks - Imath::Box2i dw = dataWindow; - Imf::Array2D<Imf::Rgba> chunk(chunk_size, width); - while (dw.min.y <= dw.max.y) { - // read a chunk - rgbaFile.setFrameBuffer (&chunk[0][0] - dw.min.x - dw.min.y * width, 1, width); - rgbaFile.readPixels (dw.min.y, MIN(dw.min.y + chunk_size - 1, dw.max.y)); - // fill the dib - const int y_max = ((dw.max.y - dw.min.y) <= chunk_size) ? (dw.max.y - dw.min.y) : chunk_size; - for(int y = 0; y < y_max; y++) { - FIRGBF *pixel = (FIRGBF*)scanline; - const Imf::Rgba *half_rgba = chunk[y]; - for(int x = 0; x < width; x++) { - // convert from half to float - pixel[x].red = half_rgba[x].r; - pixel[x].green = half_rgba[x].g; - pixel[x].blue = half_rgba[x].b; - } - // next line - scanline += pitch; - } - // next chunk - dw.min.y += chunk_size; - } - - } else { - // use the low level interface - - // build a frame buffer (i.e. what we want on output) - Imf::FrameBuffer frameBuffer; - - // allow dataWindow with minimal bounds different form zero - size_t offset = - dataWindow.min.x * bytespp - dataWindow.min.y * pitch; - - if(components == 1) { - frameBuffer.insert ("Y", // name - Imf::Slice (pixelType, // type - (char*)(bits + offset), // base - bytespp, // xStride - pitch, // yStride - 1, 1, // x/y sampling - 0.0)); // fillValue - } else if((components == 3) || (components == 4)) { - const char *channel_name[4] = { "R", "G", "B", "A" }; - - for(int c = 0; c < components; c++) { - frameBuffer.insert ( - channel_name[c], // name - Imf::Slice (pixelType, // type - (char*)(bits + c * sizeof(float) + offset), // base - bytespp, // xStride - pitch, // yStride - 1, 1, // x/y sampling - 0.0)); // fillValue - } - } - - // read the file - file.setFrameBuffer(frameBuffer); - file.readPixels(dataWindow.min.y, dataWindow.max.y); - } - - // lastly, flip dib lines - FreeImage_FlipVertical(dib); - - } - catch(Iex::BaseExc & e) { - if(dib != NULL) { - FreeImage_Unload(dib); - } - FreeImage_OutputMessageProc(s_format_id, e.what()); - return NULL; - } - - return dib; -} - -/** -Set the preview image using the dib embedded thumbnail -*/ -static BOOL -SetPreviewImage(FIBITMAP *dib, Imf::Header& header) { - if(!FreeImage_GetThumbnail(dib)) { - return FALSE; - } - FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib); - - if((FreeImage_GetImageType(thumbnail) != FIT_BITMAP) || (FreeImage_GetBPP(thumbnail) != 32)) { - // invalid thumbnail - ignore it - FreeImage_OutputMessageProc(s_format_id, FI_MSG_WARNING_INVALID_THUMBNAIL); - } else { - const unsigned thWidth = FreeImage_GetWidth(thumbnail); - const unsigned thHeight = FreeImage_GetHeight(thumbnail); - - Imf::PreviewImage preview(thWidth, thHeight); - - // copy thumbnail to 32-bit RGBA preview image - - const BYTE* src_line = FreeImage_GetScanLine(thumbnail, thHeight - 1); - Imf::PreviewRgba* dst_line = preview.pixels(); - const unsigned srcPitch = FreeImage_GetPitch(thumbnail); - - for (unsigned y = 0; y < thHeight; y++) { - const RGBQUAD* src_pixel = (RGBQUAD*)src_line; - Imf::PreviewRgba* dst_pixel = dst_line; - - for(unsigned x = 0; x < thWidth; x++) { - dst_pixel->r = src_pixel->rgbRed; - dst_pixel->g = src_pixel->rgbGreen; - dst_pixel->b = src_pixel->rgbBlue; - dst_pixel->a = src_pixel->rgbReserved; - - src_pixel++; - dst_pixel++; - } - - src_line -= srcPitch; - dst_line += thWidth; - } - - header.setPreviewImage(preview); - } - - return TRUE; -} - -/** -Save using EXR_LC compression (works only with RGB[A]F images) -*/ -static BOOL -SaveAsEXR_LC(C_OStream& ostream, FIBITMAP *dib, Imf::Header& header, int width, int height) { - int x, y; - Imf::RgbaChannels rgbaChannels; - - try { - - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - - // convert from float to half - Imf::Array2D<Imf::Rgba> pixels(height, width); - switch(image_type) { - case FIT_RGBF: - rgbaChannels = Imf::WRITE_YC; - for(y = 0; y < height; y++) { - FIRGBF *src_bits = (FIRGBF*)FreeImage_GetScanLine(dib, height - 1 - y); - for(x = 0; x < width; x++) { - Imf::Rgba &dst_bits = pixels[y][x]; - dst_bits.r = src_bits[x].red; - dst_bits.g = src_bits[x].green; - dst_bits.b = src_bits[x].blue; - } - } - break; - case FIT_RGBAF: - rgbaChannels = Imf::WRITE_YCA; - for(y = 0; y < height; y++) { - FIRGBAF *src_bits = (FIRGBAF*)FreeImage_GetScanLine(dib, height - 1 - y); - for(x = 0; x < width; x++) { - Imf::Rgba &dst_bits = pixels[y][x]; - dst_bits.r = src_bits[x].red; - dst_bits.g = src_bits[x].green; - dst_bits.b = src_bits[x].blue; - dst_bits.a = src_bits[x].alpha; - } - } - break; - default: - THROW (Iex::IoExc, "Bad image type"); - break; - } - - // write the data - Imf::RgbaOutputFile file(ostream, header, rgbaChannels); - file.setFrameBuffer (&pixels[0][0], 1, width); - file.writePixels (height); - - return TRUE; - - } catch(Iex::BaseExc & e) { - FreeImage_OutputMessageProc(s_format_id, e.what()); - - return FALSE; - } - -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - const char *channel_name[4] = { "R", "G", "B", "A" }; - BOOL bIsFlipped = FALSE; - half *halfData = NULL; - - if(!dib || !handle) return FALSE; - - try { - // check for EXR_LC compression and verify that the format is RGB - if((flags & EXR_LC) == EXR_LC) { - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - if(((image_type != FIT_RGBF) && (image_type != FIT_RGBAF)) || ((flags & EXR_FLOAT) == EXR_FLOAT)) { - THROW (Iex::IoExc, "EXR_LC compression is only available with RGB[A]F images"); - } - if((FreeImage_GetWidth(dib) % 2) || (FreeImage_GetHeight(dib) % 2)) { - THROW (Iex::IoExc, "EXR_LC compression only works when the width and height are a multiple of 2"); - } - } - - // wrap the FreeImage IO stream - C_OStream ostream(io, handle); - - // compression - Imf::Compression compress; - if((flags & EXR_NONE) == EXR_NONE) { - // no compression - compress = Imf::NO_COMPRESSION; - } else if((flags & EXR_ZIP) == EXR_ZIP) { - // zlib compression, in blocks of 16 scan lines - compress = Imf::ZIP_COMPRESSION; - } else if((flags & EXR_PIZ) == EXR_PIZ) { - // piz-based wavelet compression - compress = Imf::PIZ_COMPRESSION; - } else if((flags & EXR_PXR24) == EXR_PXR24) { - // lossy 24-bit float compression - compress = Imf::PXR24_COMPRESSION; - } else if((flags & EXR_B44) == EXR_B44) { - // lossy 44% float compression - compress = Imf::B44_COMPRESSION; - } else { - // default value - compress = Imf::PIZ_COMPRESSION; - } - - // create the header - int width = FreeImage_GetWidth(dib); - int height = FreeImage_GetHeight(dib); - int dx = 0, dy = 0; - - Imath::Box2i dataWindow (Imath::V2i (0, 0), Imath::V2i (width - 1, height - 1)); - Imath::Box2i displayWindow (Imath::V2i (-dx, -dy), Imath::V2i (width - dx - 1, height - dy - 1)); - - Imf::Header header = Imf::Header(displayWindow, dataWindow, 1, - Imath::V2f(0,0), 1, - Imf::INCREASING_Y, compress); - - // handle thumbnail - SetPreviewImage(dib, header); - - // check for EXR_LC compression - if((flags & EXR_LC) == EXR_LC) { - return SaveAsEXR_LC(ostream, dib, header, width, height); - } - - // output pixel type - Imf::PixelType pixelType; - if((flags & EXR_FLOAT) == EXR_FLOAT) { - pixelType = Imf::FLOAT; // save as float data type - } else { - // default value - pixelType = Imf::HALF; // save as half data type - } - - // check the data type and number of channels - int components = 0; - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - switch(image_type) { - case FIT_FLOAT: - components = 1; - // insert luminance channel - header.channels().insert ("Y", Imf::Channel(pixelType)); - break; - case FIT_RGBF: - components = 3; - for(int c = 0; c < components; c++) { - // insert R, G and B channels - header.channels().insert (channel_name[c], Imf::Channel(pixelType)); - } - break; - case FIT_RGBAF: - components = 4; - for(int c = 0; c < components; c++) { - // insert R, G, B and A channels - header.channels().insert (channel_name[c], Imf::Channel(pixelType)); - } - break; - default: - THROW (Iex::ArgExc, "Cannot save: invalid data type.\nConvert the image to float before saving as OpenEXR."); - } - - // build a frame buffer (i.e. what we have on input) - Imf::FrameBuffer frameBuffer; - - BYTE *bits = NULL; // pointer to our pixel buffer - size_t bytespp = 0; // size of our pixel in bytes - size_t bytespc = 0; // size of our pixel component in bytes - unsigned pitch = 0; // size of our yStride in bytes - - - if(pixelType == Imf::HALF) { - // convert from float to half - halfData = new(std::nothrow) half[width * height * components]; - if(!halfData) { - THROW (Iex::NullExc, FI_MSG_ERROR_MEMORY); - } - - for(int y = 0; y < height; y++) { - float *src_bits = (float*)FreeImage_GetScanLine(dib, height - 1 - y); - half *dst_bits = halfData + y * width * components; - for(int x = 0; x < width; x++) { - for(int c = 0; c < components; c++) { - dst_bits[c] = src_bits[c]; - } - src_bits += components; - dst_bits += components; - } - } - bits = (BYTE*)halfData; - bytespc = sizeof(half); - bytespp = sizeof(half) * components; - pitch = sizeof(half) * width * components; - } else if(pixelType == Imf::FLOAT) { - // invert dib scanlines - bIsFlipped = FreeImage_FlipVertical(dib); - - bits = FreeImage_GetBits(dib); - bytespc = sizeof(float); - bytespp = sizeof(float) * components; - pitch = FreeImage_GetPitch(dib); - } - - if(image_type == FIT_FLOAT) { - frameBuffer.insert ("Y", // name - Imf::Slice (pixelType, // type - (char*)(bits), // base - bytespp, // xStride - pitch)); // yStride - } else if((image_type == FIT_RGBF) || (image_type == FIT_RGBAF)) { - for(int c = 0; c < components; c++) { - char *channel_base = (char*)(bits) + c*bytespc; - frameBuffer.insert (channel_name[c],// name - Imf::Slice (pixelType, // type - channel_base, // base - bytespp, // xStride - pitch)); // yStride - } - } - - // write the data - Imf::OutputFile file (ostream, header); - file.setFrameBuffer (frameBuffer); - file.writePixels (height); - - if(halfData != NULL) { - delete[] halfData; - } - if(bIsFlipped) { - // invert dib scanlines - FreeImage_FlipVertical(dib); - } - - return TRUE; - - } catch(Iex::BaseExc & e) { - if(halfData != NULL) { - delete[] halfData; - } - if(bIsFlipped) { - // invert dib scanlines - FreeImage_FlipVertical(dib); - } - - FreeImage_OutputMessageProc(s_format_id, e.what()); - - return FALSE; - } -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitEXR(Plugin *plugin, int format_id) { - s_format_id = format_id; - - // initialize the OpenEXR library - // note that this OpenEXR function produce so called "false memory leaks" - // see http://lists.nongnu.org/archive/html/openexr-devel/2013-11/msg00000.html - Imf::staticInitialize(); - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginG3.cpp b/plugins/AdvaImg/src/FreeImage/PluginG3.cpp deleted file mode 100644 index 0a083b459b..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginG3.cpp +++ /dev/null @@ -1,433 +0,0 @@ -// ========================================================== -// G3 Fax Loader -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Petr Pytelka (pyta@lightcomp.com) -// -// 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 "../LibTIFF4/tiffiop.h" - -#include "FreeImage.h" -#include "Utilities.h" - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Constant/Macro declarations -// ========================================================== - -#define G3_DEFAULT_WIDTH 1728 - -#define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3) - -// ========================================================== -// libtiff interface -// ========================================================== - -static tmsize_t -_g3ReadProc(thandle_t handle, void *buf, tmsize_t size) { - // returns an error when reading the TIFF header - return 0; -} - -static tmsize_t -_g3WriteProc(thandle_t handle, void *buf, tmsize_t size) { - // returns ok when writing the TIFF header - return size; -} - -static toff_t -_g3SeekProc(thandle_t handle, toff_t off, int whence) { - return 0; -} - -static int -_g3CloseProc(thandle_t handle) { - return 0; -} - -static toff_t -_g3SizeProc(thandle_t handle) { - return 0; -} - -static int -_g3MapProc(thandle_t, void** base, toff_t* size) { - return 0; -} - -static void -_g3UnmapProc(thandle_t, void* base, toff_t size) { -} - -// -------------------------------------------------------------- - -static tmsize_t -G3GetFileSize(FreeImageIO *io, fi_handle handle) { - long currentPos = io->tell_proc(handle); - io->seek_proc(handle, 0, SEEK_END); - long fileSize = io->tell_proc(handle); - io->seek_proc(handle, currentPos, SEEK_SET); - return fileSize; -} - -static BOOL -G3ReadFile(FreeImageIO *io, fi_handle handle, uint8 *tif_rawdata, tmsize_t tif_rawdatasize) { - return ((tmsize_t)(io->read_proc(tif_rawdata, (unsigned)tif_rawdatasize, 1, handle) * tif_rawdatasize) == tif_rawdatasize); -} - -// ========================================================== -// Internal functions -// ========================================================== - -static int -copyFaxFile(FreeImageIO *io, fi_handle handle, TIFF* tifin, uint32 xsize, int stretch, FIMEMORY *memory) { - BYTE *rowbuf = NULL; - BYTE *refbuf = NULL; - uint32 row; - uint16 badrun; - uint16 badfaxrun; - uint32 badfaxlines; - int ok; - - try { - - uint32 linesize = TIFFhowmany8(xsize); - rowbuf = (BYTE*) _TIFFmalloc(linesize); - refbuf = (BYTE*) _TIFFmalloc(linesize); - if (rowbuf == NULL || refbuf == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - tifin->tif_rawdatasize = G3GetFileSize(io, handle); - tifin->tif_rawdata = (tidata_t) _TIFFmalloc(tifin->tif_rawdatasize); - if (tifin->tif_rawdata == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - if(!G3ReadFile(io, handle, tifin->tif_rawdata, tifin->tif_rawdatasize)) { - throw "Read error at scanline 0"; - } - tifin->tif_rawcp = tifin->tif_rawdata; - tifin->tif_rawcc = tifin->tif_rawdatasize; - - (*tifin->tif_setupdecode)(tifin); - (*tifin->tif_predecode)(tifin, (uint16) 0); - tifin->tif_row = 0; - badfaxlines = 0; - badfaxrun = 0; - - _TIFFmemset(refbuf, 0, linesize); - row = 0; - badrun = 0; // current run of bad lines - while (tifin->tif_rawcc > 0) { - ok = (*tifin->tif_decoderow)(tifin, rowbuf, linesize, 0); - if (!ok) { - badfaxlines++; - badrun++; - // regenerate line from previous good line - _TIFFmemcpy(rowbuf, refbuf, linesize); - } else { - if (badrun > badfaxrun) - badfaxrun = badrun; - badrun = 0; - _TIFFmemcpy(refbuf, rowbuf, linesize); - } - tifin->tif_row++; - - FreeImage_WriteMemory(rowbuf, linesize, 1, memory); - row++; - if (stretch) { - FreeImage_WriteMemory(rowbuf, linesize, 1, memory); - row++; - } - } - if (badrun > badfaxrun) - badfaxrun = badrun; - - _TIFFfree(tifin->tif_rawdata); - tifin->tif_rawdata = NULL; - - _TIFFfree(rowbuf); - _TIFFfree(refbuf); - - /* - if (verbose) { - fprintf(stderr, "%d rows in input\n", rows); - fprintf(stderr, "%ld total bad rows\n", (long) badfaxlines); - fprintf(stderr, "%d max consecutive bad rows\n", badfaxrun); - } - */ - - } catch(const char *message) { - if(rowbuf) _TIFFfree(rowbuf); - if(refbuf) _TIFFfree(refbuf); - if(tifin->tif_rawdata) { - _TIFFfree(tifin->tif_rawdata); - tifin->tif_rawdata = NULL; - } - FreeImage_OutputMessageProc(s_format_id, message); - - return -1; - } - - return (row); -} - - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "G3"; -} - -static const char * DLL_CALLCONV -Description() { - return "Raw fax format CCITT G.3"; -} - -static const char * DLL_CALLCONV -Extension() { - return "g3"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; // there is now reasonable regexp for raw G3 -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/fax-g3"; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - TIFF *faxTIFF = NULL; - FIBITMAP *dib = NULL; - FIMEMORY *memory = NULL; - - //int verbose = 0; - int stretch = 0; - int rows; - float resX = 204.0; - float resY = 196.0; - - uint32 xsize = G3_DEFAULT_WIDTH; - int compression_in = COMPRESSION_CCITTFAX3; - int fillorder_in = FILLORDER_LSB2MSB; - uint32 group3options_in = 0; // 1d-encoded - uint32 group4options_in = 0; // compressed - int photometric_in = PHOTOMETRIC_MINISWHITE; - - if(handle==NULL) return NULL; - - try { - // set default load options - - compression_in = COMPRESSION_CCITTFAX3; // input is g3-encoded - group3options_in &= ~GROUP3OPT_2DENCODING; // input is 1d-encoded (g3 only) - fillorder_in = FILLORDER_MSB2LSB; // input has msb-to-lsb fillorder - - /* - Original input-related fax2tiff options - - while ((c = getopt(argc, argv, "R:X:o:1234ABLMPUW5678abcflmprsuvwz?")) != -1) { - switch (c) { - // input-related options - case '3': // input is g3-encoded - compression_in = COMPRESSION_CCITTFAX3; - break; - case '4': // input is g4-encoded - compression_in = COMPRESSION_CCITTFAX4; - break; - case 'U': // input is uncompressed (g3 and g4) - group3options_in |= GROUP3OPT_UNCOMPRESSED; - group4options_in |= GROUP4OPT_UNCOMPRESSED; - break; - case '1': // input is 1d-encoded (g3 only) - group3options_in &= ~GROUP3OPT_2DENCODING; - break; - case '2': // input is 2d-encoded (g3 only) - group3options_in |= GROUP3OPT_2DENCODING; - break; - case 'P': // input has not-aligned EOL (g3 only) - group3options_in &= ~GROUP3OPT_FILLBITS; - break; - case 'A': // input has aligned EOL (g3 only) - group3options_in |= GROUP3OPT_FILLBITS; - break; - case 'W': // input has 0 mean white - photometric_in = PHOTOMETRIC_MINISWHITE; - break; - case 'B': // input has 0 mean black - photometric_in = PHOTOMETRIC_MINISBLACK; - break; - case 'L': // input has lsb-to-msb fillorder - fillorder_in = FILLORDER_LSB2MSB; - break; - case 'M': // input has msb-to-lsb fillorder - fillorder_in = FILLORDER_MSB2LSB; - break; - case 'R': // input resolution - resY = (float) atof(optarg); - break; - case 'X': // input width - xsize = (uint32) atoi(optarg); - break; - - // output-related options - case 's': // stretch image by dup'ng scanlines - stretch = 1; - break; - case 'v': // -v for info - verbose++; - break; - } - } - - */ - - // open a temporary memory buffer to save decoded scanlines - memory = FreeImage_OpenMemory(); - if(!memory) throw FI_MSG_ERROR_MEMORY; - - // wrap the raw fax file - faxTIFF = TIFFClientOpen("(FakeInput)", "w", - // TIFFClientOpen() fails if we don't set existing value here - NULL, - _g3ReadProc, _g3WriteProc, - _g3SeekProc, _g3CloseProc, - _g3SizeProc, _g3MapProc, - _g3UnmapProc); - - if (faxTIFF == NULL) { - throw "Can not create fake input file"; - } - TIFFSetMode(faxTIFF, O_RDONLY); - TIFFSetField(faxTIFF, TIFFTAG_IMAGEWIDTH, xsize); - TIFFSetField(faxTIFF, TIFFTAG_SAMPLESPERPIXEL, 1); - TIFFSetField(faxTIFF, TIFFTAG_BITSPERSAMPLE, 1); - TIFFSetField(faxTIFF, TIFFTAG_FILLORDER, fillorder_in); - TIFFSetField(faxTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); - TIFFSetField(faxTIFF, TIFFTAG_PHOTOMETRIC, photometric_in); - TIFFSetField(faxTIFF, TIFFTAG_YRESOLUTION, resY); - TIFFSetField(faxTIFF, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); - - // NB: this must be done after directory info is setup - TIFFSetField(faxTIFF, TIFFTAG_COMPRESSION, compression_in); - if (compression_in == COMPRESSION_CCITTFAX3) - TIFFSetField(faxTIFF, TIFFTAG_GROUP3OPTIONS, group3options_in); - else if (compression_in == COMPRESSION_CCITTFAX4) - TIFFSetField(faxTIFF, TIFFTAG_GROUP4OPTIONS, group4options_in); - - resX = 204; - if (!stretch) { - TIFFGetField(faxTIFF, TIFFTAG_YRESOLUTION, &resY); - } else { - resY = 196; - } - - // decode the raw fax data - rows = copyFaxFile(io, handle, faxTIFF, xsize, stretch, memory); - if(rows <= 0) throw "Error when decoding raw fax file : check the decoder options"; - - - // allocate the output dib - dib = FreeImage_Allocate(xsize, rows, 1); - unsigned pitch = FreeImage_GetPitch(dib); - uint32 linesize = TIFFhowmany8(xsize); - - // fill the bitmap structure ... - // ... palette - RGBQUAD *pal = FreeImage_GetPalette(dib); - if(photometric_in == PHOTOMETRIC_MINISWHITE) { - pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255; - pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 0; - } else { - pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0; - pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; - } - // ... resolution - FreeImage_SetDotsPerMeterX(dib, (unsigned)(resX/0.0254000 + 0.5)); - FreeImage_SetDotsPerMeterY(dib, (unsigned)(resY/0.0254000 + 0.5)); - - // read the decoded scanline and fill the bitmap data - FreeImage_SeekMemory(memory, 0, SEEK_SET); - BYTE *bits = FreeImage_GetScanLine(dib, rows - 1); - for(int k = 0; k < rows; k++) { - FreeImage_ReadMemory(bits, linesize, 1, memory); - bits -= pitch; - } - - // free the TIFF wrapper - TIFFClose(faxTIFF); - - // free the memory buffer - FreeImage_CloseMemory(memory); - - } catch(const char *message) { - if(memory) FreeImage_CloseMemory(memory); - if(faxTIFF) TIFFClose(faxTIFF); - if(dib) FreeImage_Unload(dib); - FreeImage_OutputMessageProc(s_format_id, message); - return NULL; - } - - return dib; - -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitG3(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = NULL; - plugin->validate_proc = NULL; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = NULL; - plugin->supports_icc_profiles_proc = NULL; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginHDR.cpp b/plugins/AdvaImg/src/FreeImage/PluginHDR.cpp deleted file mode 100644 index 28ce1a5768..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginHDR.cpp +++ /dev/null @@ -1,722 +0,0 @@ -// ========================================================== -// HDR Loader and writer -// -// 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" - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// RGBE library -// ========================================================== - -// ---------------------------------------------------------- - -// maximum size of a line in the header -#define HDR_MAXLINE 256 - -// flags indicating which fields in an rgbeHeaderInfo are valid -#define RGBE_VALID_PROGRAMTYPE 0x01 -#define RGBE_VALID_COMMENT 0x02 -#define RGBE_VALID_GAMMA 0x04 -#define RGBE_VALID_EXPOSURE 0x08 - -// offsets to red, green, and blue components in a data (float) pixel -#define RGBE_DATA_RED 0 -#define RGBE_DATA_GREEN 1 -#define RGBE_DATA_BLUE 2 - -// ---------------------------------------------------------- -#ifdef _WIN32 -#pragma pack(push, 1) -#else -#pragma pack(1) -#endif - -typedef struct tagHeaderInfo { - int valid; // indicate which fields are valid - char programtype[16]; // listed at beginning of file to identify it after "#?". defaults to "RGBE" - char comment[HDR_MAXLINE]; // comment beginning with "# " - float gamma; // image has already been gamma corrected with given gamma. defaults to 1.0 (no correction) - float exposure; // a value of 1.0 in an image corresponds to <exposure> watts/steradian/m^2. defaults to 1.0 -} rgbeHeaderInfo; - -#ifdef _WIN32 -#pragma pack(pop) -#else -#pragma pack() -#endif - -typedef enum { - rgbe_read_error, - rgbe_write_error, - rgbe_format_error, - rgbe_memory_error -} rgbe_error_code; - -// ---------------------------------------------------------- -// Prototypes -// ---------------------------------------------------------- - -static BOOL rgbe_Error(rgbe_error_code error_code, const char *msg); -static BOOL rgbe_GetLine(FreeImageIO *io, fi_handle handle, char *buffer, int length); -static inline void rgbe_FloatToRGBE(BYTE rgbe[4], FIRGBF *rgbf); -static inline void rgbe_RGBEToFloat(FIRGBF *rgbf, BYTE rgbe[4]); -static BOOL rgbe_ReadHeader(FreeImageIO *io, fi_handle handle, unsigned *width, unsigned *height, rgbeHeaderInfo *header_info); -static BOOL rgbe_WriteHeader(FreeImageIO *io, fi_handle handle, unsigned width, unsigned height, rgbeHeaderInfo *info); -static BOOL rgbe_ReadPixels(FreeImageIO *io, fi_handle handle, FIRGBF *data, unsigned numpixels); -static BOOL rgbe_WritePixels(FreeImageIO *io, fi_handle handle, FIRGBF *data, unsigned numpixels); -static BOOL rgbe_ReadPixels_RLE(FreeImageIO *io, fi_handle handle, FIRGBF *data, int scanline_width, unsigned num_scanlines); -static BOOL rgbe_WriteBytes_RLE(FreeImageIO *io, fi_handle handle, BYTE *data, int numbytes); -static BOOL rgbe_WritePixels_RLE(FreeImageIO *io, fi_handle handle, FIRGBF *data, unsigned scanline_width, unsigned num_scanlines); -static BOOL rgbe_ReadMetadata(FIBITMAP *dib, rgbeHeaderInfo *header_info); -static BOOL rgbe_WriteMetadata(FIBITMAP *dib, rgbeHeaderInfo *header_info); - -// ---------------------------------------------------------- - -/** -Default error routine. change this to change error handling -*/ -static BOOL -rgbe_Error(rgbe_error_code error_code, const char *msg) { - switch (error_code) { - case rgbe_read_error: - FreeImage_OutputMessageProc(s_format_id, "RGBE read error"); - break; - case rgbe_write_error: - FreeImage_OutputMessageProc(s_format_id, "RGBE write error"); - break; - case rgbe_format_error: - FreeImage_OutputMessageProc(s_format_id, "RGBE bad file format: %s\n", msg); - break; - default: - case rgbe_memory_error: - FreeImage_OutputMessageProc(s_format_id, "RGBE error: %s\n",msg); - } - - return FALSE; -} - -/** -Get a line from a ASCII io stream -*/ -static BOOL -rgbe_GetLine(FreeImageIO *io, fi_handle handle, char *buffer, int length) { - int i; - memset(buffer, 0, length); - for(i = 0; i < length; i++) { - if(!io->read_proc(&buffer[i], 1, 1, handle)) - return FALSE; - if(buffer[i] == 0x0A) - break; - } - - return (i < length) ? TRUE : FALSE; -} - -/** -Standard conversion from float pixels to rgbe pixels. -Note: you can remove the "inline"s if your compiler complains about it -*/ -static inline void -rgbe_FloatToRGBE(BYTE rgbe[4], FIRGBF *rgbf) { - float v; - int e; - - v = rgbf->red; - if (rgbf->green > v) v = rgbf->green; - if (rgbf->blue > v) v = rgbf->blue; - if (v < 1e-32) { - rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; - } - else { - v = (float)(frexp(v, &e) * 256.0 / v); - rgbe[0] = (BYTE) (rgbf->red * v); - rgbe[1] = (BYTE) (rgbf->green * v); - rgbe[2] = (BYTE) (rgbf->blue * v); - rgbe[3] = (BYTE) (e + 128); - } -} - -/** -Standard conversion from rgbe to float pixels. -Note: Ward uses ldexp(col+0.5,exp-(128+8)). -However we wanted pixels in the range [0,1] to map back into the range [0,1]. -*/ -static inline void -rgbe_RGBEToFloat(FIRGBF *rgbf, BYTE rgbe[4]) { - if (rgbe[3]) { // nonzero pixel - float f = (float)(ldexp(1.0, rgbe[3] - (int)(128+8))); - rgbf->red = rgbe[0] * f; - rgbf->green = rgbe[1] * f; - rgbf->blue = rgbe[2] * f; - - } - else { - rgbf->red = rgbf->green = rgbf->blue = 0; - } -} - -/** -Minimal header reading. Modify if you want to parse more information -*/ -static BOOL -rgbe_ReadHeader(FreeImageIO *io, fi_handle handle, unsigned *width, unsigned *height, rgbeHeaderInfo *header_info) { - char buf[HDR_MAXLINE]; - float tempf; - int i; - BOOL bFormatFound = FALSE; - BOOL bHeaderFound = FALSE; - - header_info->valid = 0; - header_info->programtype[0] = 0; - header_info->gamma = 1.0; - header_info->exposure = 1.0; - - // get the first line - if(!rgbe_GetLine(io, handle, buf, HDR_MAXLINE)) - return rgbe_Error(rgbe_read_error, NULL); - - // check the signature - - if ((buf[0] != '#')||(buf[1] != '?')) { - // if you don't want to require the magic token then comment the next line - return rgbe_Error(rgbe_format_error,"bad initial token"); - } - else { - header_info->valid |= RGBE_VALID_PROGRAMTYPE; - for(i = 0; i < sizeof(header_info->programtype) - 1; i++) { - if((buf[i+2] == 0) || isspace(buf[i+2])) - break; - header_info->programtype[i] = buf[i+2]; - } - header_info->programtype[i] = 0; - } - - for(;;) { - // get next line - if(!rgbe_GetLine(io, handle, buf, HDR_MAXLINE)) - return rgbe_Error(rgbe_read_error, NULL); - - if((buf[0] == 0) || (buf[0] == '\n')) { - // end of header so break out of loop - bHeaderFound = TRUE; - break; - } - else if(strcmp(buf,"FORMAT=32-bit_rle_rgbe\n") == 0) { - bFormatFound = TRUE; - } - else if(sscanf(buf, "GAMMA=%g", &tempf) == 1) { - header_info->gamma = tempf; - header_info->valid |= RGBE_VALID_GAMMA; - } - else if(sscanf(buf,"EXPOSURE=%g",&tempf) == 1) { - header_info->exposure = tempf; - header_info->valid |= RGBE_VALID_EXPOSURE; - } - else if((buf[0] == '#') && (buf[1] == 0x20)) { - header_info->valid |= RGBE_VALID_COMMENT; - strcpy(header_info->comment, buf); - } - } - if(!bHeaderFound || !bFormatFound) { - return rgbe_Error(rgbe_format_error, "invalid header"); - } - - // get next line - if(!rgbe_GetLine(io, handle, buf, HDR_MAXLINE)) - return rgbe_Error(rgbe_read_error, NULL); - - // get the image width & height - if(sscanf(buf,"-Y %d +X %d", height, width) < 2) { - if(sscanf(buf,"+X %d +Y %d", height, width) < 2) { - return rgbe_Error(rgbe_format_error, "missing image size specifier"); - } - } - - return TRUE; -} - -/** - default minimal header. modify if you want more information in header -*/ -static BOOL -rgbe_WriteHeader(FreeImageIO *io, fi_handle handle, unsigned width, unsigned height, rgbeHeaderInfo *info) { - char buffer[HDR_MAXLINE]; - - const char *programtype = "RADIANCE"; - - if(info && (info->valid & RGBE_VALID_PROGRAMTYPE)) { - programtype = info->programtype; - } - // The #? is to identify file type, the programtype is optional - sprintf(buffer, "#?%s\n", programtype); - if(io->write_proc(buffer, 1, (unsigned int)strlen(buffer), handle) < 1) - return rgbe_Error(rgbe_write_error, NULL); - sprintf(buffer, "%s\n", info->comment); - if(io->write_proc(buffer, 1, (unsigned int)strlen(buffer), handle) < 1) - return rgbe_Error(rgbe_write_error, NULL); - sprintf(buffer, "FORMAT=32-bit_rle_rgbe\n"); - if(io->write_proc(buffer, 1, (unsigned int)strlen(buffer), handle) < 1) - return rgbe_Error(rgbe_write_error, NULL); - if(info && (info->valid & RGBE_VALID_GAMMA)) { - sprintf(buffer, "GAMMA=%g\n", info->gamma); - if(io->write_proc(buffer, 1, (unsigned int)strlen(buffer), handle) < 1) - return rgbe_Error(rgbe_write_error, NULL); - } - if(info && (info->valid & RGBE_VALID_EXPOSURE)) { - sprintf(buffer,"EXPOSURE=%g\n", info->exposure); - if(io->write_proc(buffer, 1, (unsigned int)strlen(buffer), handle) < 1) - return rgbe_Error(rgbe_write_error, NULL); - } - sprintf(buffer, "\n-Y %d +X %d\n", height, width); - if(io->write_proc(buffer, 1, (unsigned int)strlen(buffer), handle) < 1) - return rgbe_Error(rgbe_write_error, NULL); - - return TRUE; -} - -static BOOL -rgbe_ReadMetadata(FIBITMAP *dib, rgbeHeaderInfo *header_info) { - return TRUE; -} -static BOOL -rgbe_WriteMetadata(FIBITMAP *dib, rgbeHeaderInfo *header_info) { - header_info->gamma = 1; - header_info->valid |= RGBE_VALID_GAMMA; - header_info->exposure = 0; - header_info->valid |= RGBE_VALID_EXPOSURE; - - return TRUE; -} - -/** -Simple read routine. Will not correctly handle run length encoding -*/ -static BOOL -rgbe_ReadPixels(FreeImageIO *io, fi_handle handle, FIRGBF *data, unsigned numpixels) { - BYTE rgbe[4]; - - for(unsigned x = 0; x < numpixels; x++) { - if(io->read_proc(rgbe, 1, sizeof(rgbe), handle) < 1) { - return rgbe_Error(rgbe_read_error, NULL); - } - rgbe_RGBEToFloat(&data[x], rgbe); - } - - return TRUE; -} - -/** - Simple write routine that does not use run length encoding. - These routines can be made faster by allocating a larger buffer and - fread-ing and fwrite-ing the data in larger chunks. -*/ -static BOOL -rgbe_WritePixels(FreeImageIO *io, fi_handle handle, FIRGBF *data, unsigned numpixels) { - BYTE rgbe[4]; - - for(unsigned x = 0; x < numpixels; x++) { - rgbe_FloatToRGBE(rgbe, &data[x]); - if(io->write_proc(rgbe, sizeof(rgbe), 1, handle) < 1) - return rgbe_Error(rgbe_write_error, NULL); - } - - return TRUE; -} - -static BOOL -rgbe_ReadPixels_RLE(FreeImageIO *io, fi_handle handle, FIRGBF *data, int scanline_width, unsigned num_scanlines) { - BYTE rgbe[4], *scanline_buffer, *ptr, *ptr_end; - int i, count; - BYTE buf[2]; - - if ((scanline_width < 8)||(scanline_width > 0x7fff)) { - // run length encoding is not allowed so read flat - return rgbe_ReadPixels(io, handle, data, scanline_width * num_scanlines); - } - scanline_buffer = NULL; - // read in each successive scanline - while(num_scanlines > 0) { - if(io->read_proc(rgbe, 1, sizeof(rgbe), handle) < 1) { - free(scanline_buffer); - return rgbe_Error(rgbe_read_error,NULL); - } - if((rgbe[0] != 2) || (rgbe[1] != 2) || (rgbe[2] & 0x80)) { - // this file is not run length encoded - rgbe_RGBEToFloat(data, rgbe); - data ++; - free(scanline_buffer); - return rgbe_ReadPixels(io, handle, data, scanline_width * num_scanlines - 1); - } - if((((int)rgbe[2]) << 8 | rgbe[3]) != scanline_width) { - free(scanline_buffer); - return rgbe_Error(rgbe_format_error,"wrong scanline width"); - } - if(scanline_buffer == NULL) { - scanline_buffer = (BYTE*)malloc(sizeof(BYTE) * 4 * scanline_width); - if(scanline_buffer == NULL) { - return rgbe_Error(rgbe_memory_error, "unable to allocate buffer space"); - } - } - - ptr = &scanline_buffer[0]; - // read each of the four channels for the scanline into the buffer - for(i = 0; i < 4; i++) { - ptr_end = &scanline_buffer[(i+1)*scanline_width]; - while(ptr < ptr_end) { - if(io->read_proc(buf, 1, 2 * sizeof(BYTE), handle) < 1) { - free(scanline_buffer); - return rgbe_Error(rgbe_read_error, NULL); - } - if(buf[0] > 128) { - // a run of the same value - count = buf[0] - 128; - if((count == 0) || (count > ptr_end - ptr)) { - free(scanline_buffer); - return rgbe_Error(rgbe_format_error, "bad scanline data"); - } - while(count-- > 0) - *ptr++ = buf[1]; - } - else { - // a non-run - count = buf[0]; - if((count == 0) || (count > ptr_end - ptr)) { - free(scanline_buffer); - return rgbe_Error(rgbe_format_error, "bad scanline data"); - } - *ptr++ = buf[1]; - if(--count > 0) { - if(io->read_proc(ptr, 1, sizeof(BYTE) * count, handle) < 1) { - free(scanline_buffer); - return rgbe_Error(rgbe_read_error, NULL); - } - ptr += count; - } - } - } - } - // now convert data from buffer into floats - for(i = 0; i < scanline_width; i++) { - rgbe[0] = scanline_buffer[i]; - rgbe[1] = scanline_buffer[i+scanline_width]; - rgbe[2] = scanline_buffer[i+2*scanline_width]; - rgbe[3] = scanline_buffer[i+3*scanline_width]; - rgbe_RGBEToFloat(data, rgbe); - data ++; - } - - num_scanlines--; - } - - free(scanline_buffer); - - return TRUE; -} - -/** - The code below is only needed for the run-length encoded files. - Run length encoding adds considerable complexity but does - save some space. For each scanline, each channel (r,g,b,e) is - encoded separately for better compression. - @return Returns TRUE if successful, returns FALSE otherwise -*/ -static BOOL -rgbe_WriteBytes_RLE(FreeImageIO *io, fi_handle handle, BYTE *data, int numbytes) { - static const int MINRUNLENGTH = 4; - int cur, beg_run, run_count, old_run_count, nonrun_count; - BYTE buf[2]; - - cur = 0; - while(cur < numbytes) { - beg_run = cur; - // find next run of length at least 4 if one exists - run_count = old_run_count = 0; - while((run_count < MINRUNLENGTH) && (beg_run < numbytes)) { - beg_run += run_count; - old_run_count = run_count; - run_count = 1; - while((beg_run + run_count < numbytes) && (run_count < 127) && (data[beg_run] == data[beg_run + run_count])) { - run_count++; - } - } - // if data before next big run is a short run then write it as such - if ((old_run_count > 1)&&(old_run_count == beg_run - cur)) { - buf[0] = (BYTE)(128 + old_run_count); // write short run - buf[1] = data[cur]; - if(io->write_proc(buf, 2 * sizeof(BYTE), 1, handle) < 1) - return rgbe_Error(rgbe_write_error, NULL); - cur = beg_run; - } - // write out bytes until we reach the start of the next run - while(cur < beg_run) { - nonrun_count = beg_run - cur; - if (nonrun_count > 128) - nonrun_count = 128; - buf[0] = (BYTE)nonrun_count; - if(io->write_proc(buf, sizeof(buf[0]), 1, handle) < 1) - return rgbe_Error(rgbe_write_error,NULL); - if(io->write_proc(&data[cur], sizeof(data[0]) * nonrun_count, 1, handle) < 1) - return rgbe_Error(rgbe_write_error,NULL); - cur += nonrun_count; - } - // write out next run if one was found - if (run_count >= MINRUNLENGTH) { - buf[0] = (BYTE)(128 + run_count); - buf[1] = data[beg_run]; - if(io->write_proc(buf, sizeof(buf[0]) * 2, 1, handle) < 1) - return rgbe_Error(rgbe_write_error,NULL); - cur += run_count; - } - } - - return TRUE; -} - -static BOOL -rgbe_WritePixels_RLE(FreeImageIO *io, fi_handle handle, FIRGBF *data, unsigned scanline_width, unsigned num_scanlines) { - BYTE rgbe[4]; - BYTE *buffer; - - if ((scanline_width < 8)||(scanline_width > 0x7fff)) { - // run length encoding is not allowed so write flat - return rgbe_WritePixels(io, handle, data, scanline_width * num_scanlines); - } - buffer = (BYTE*)malloc(sizeof(BYTE) * 4 * scanline_width); - if (buffer == NULL) { - // no buffer space so write flat - return rgbe_WritePixels(io, handle, data, scanline_width * num_scanlines); - } - while(num_scanlines-- > 0) { - rgbe[0] = (BYTE)2; - rgbe[1] = (BYTE)2; - rgbe[2] = (BYTE)(scanline_width >> 8); - rgbe[3] = (BYTE)(scanline_width & 0xFF); - if(io->write_proc(rgbe, sizeof(rgbe), 1, handle) < 1) { - free(buffer); - return rgbe_Error(rgbe_write_error, NULL); - } - for(unsigned x = 0; x < scanline_width; x++) { - rgbe_FloatToRGBE(rgbe, data); - buffer[x] = rgbe[0]; - buffer[x+scanline_width] = rgbe[1]; - buffer[x+2*scanline_width] = rgbe[2]; - buffer[x+3*scanline_width] = rgbe[3]; - data ++; - } - // write out each of the four channels separately run length encoded - // first red, then green, then blue, then exponent - for(int i = 0; i < 4; i++) { - BOOL bOK = rgbe_WriteBytes_RLE(io, handle, &buffer[i*scanline_width], scanline_width); - if(!bOK) { - free(buffer); - return bOK; - } - } - } - free(buffer); - - return TRUE; -} - - -// ---------------------------------------------------------- - - - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "HDR"; -} - -static const char * DLL_CALLCONV -Description() { - return "High Dynamic Range Image"; -} - -static const char * DLL_CALLCONV -Extension() { - return "hdr"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/vnd.radiance"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE hdr_signature[] = { '#', '?' }; - BYTE signature[] = { 0, 0 }; - - io->read_proc(signature, 1, 2, handle); - - return (memcmp(hdr_signature, signature, 2) == 0); -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return (type == FIT_RGBF) ? TRUE : FALSE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// -------------------------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - FIBITMAP *dib = NULL; - - if(!handle) { - return NULL; - } - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - try { - - rgbeHeaderInfo header_info; - unsigned width, height; - - // Read the header - if(rgbe_ReadHeader(io, handle, &width, &height, &header_info) == FALSE) { - return NULL; - } - - // allocate a RGBF image - dib = FreeImage_AllocateHeaderT(header_only, FIT_RGBF, width, height); - if(!dib) { - throw FI_MSG_ERROR_MEMORY; - } - - // set the metadata as comments - rgbe_ReadMetadata(dib, &header_info); - - if(header_only) { - // header only mode - return dib; - } - - // read the image pixels and fill the dib - - for(unsigned y = 0; y < height; y++) { - FIRGBF *scanline = (FIRGBF*)FreeImage_GetScanLine(dib, height - 1 - y); - if(!rgbe_ReadPixels_RLE(io, handle, scanline, width, 1)) { - FreeImage_Unload(dib); - return NULL; - } - } - - } - catch(const char *text) { - if(dib != NULL) { - FreeImage_Unload(dib); - } - FreeImage_OutputMessageProc(s_format_id, text); - } - - return dib; -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - if(!dib) return FALSE; - - FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib); - if(src_type != FIT_RGBF) { - FreeImage_OutputMessageProc(s_format_id, "FREE_IMAGE_TYPE: Unable to convert from type %d to type %d.\n No such conversion exists.", src_type, FIT_RGBF); - return FALSE; - } - - unsigned width = FreeImage_GetWidth(dib); - unsigned height = FreeImage_GetHeight(dib); - - // write the header - - rgbeHeaderInfo header_info; - memset(&header_info, 0, sizeof(rgbeHeaderInfo)); - // fill the header with correct gamma and exposure - rgbe_WriteMetadata(dib, &header_info); - // fill a comment - sprintf(header_info.comment, "# Made with FreeImage %s", FreeImage_GetVersion()); - if(!rgbe_WriteHeader(io, handle, width, height, &header_info)) { - return FALSE; - } - - // write each scanline - - for(unsigned y = 0; y < height; y++) { - FIRGBF *scanline = (FIRGBF*)FreeImage_GetScanLine(dib, height - 1 - y); - if(!rgbe_WritePixels_RLE(io, handle, scanline, width, 1)) { - return FALSE; - } - } - - return TRUE; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitHDR(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginIFF.cpp b/plugins/AdvaImg/src/FreeImage/PluginIFF.cpp deleted file mode 100644 index ae1f903f82..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginIFF.cpp +++ /dev/null @@ -1,459 +0,0 @@ -// ========================================================== -// Deluxe Paint Loader -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Mark Sibly (marksibly@blitzbasic.com) -// - Aaron Shumate (trek@startreker.com) -// - 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" - -// ---------------------------------------------------------- -// Internal typedefs and structures -// ---------------------------------------------------------- - -#ifdef _WIN32 -#pragma pack(push, 1) -#else -#pragma pack(1) -#endif - -typedef struct { - WORD w, h; /* raster width & height in pixels */ - WORD x, y; /* position for this image */ - BYTE nPlanes; /* # source bitplanes */ - BYTE masking; /* masking technique */ - BYTE compression; /* compression algorithm */ - BYTE pad1; /* UNUSED. For consistency, put 0 here.*/ - WORD transparentColor; /* transparent "color number" */ - BYTE xAspect, yAspect; /* aspect ratio, a rational number x/y */ - WORD pageWidth, pageHeight; /* source "page" size in pixels */ -} BMHD; - -#ifdef _WIN32 -#pragma pack(pop) -#else -#pragma pack() -#endif - -#ifndef FREEIMAGE_BIGENDIAN -static void -SwapHeader(BMHD *header) { - SwapShort(&header->w); - SwapShort(&header->h); - SwapShort(&header->x); - SwapShort(&header->y); - SwapShort(&header->transparentColor); - SwapShort(&header->pageWidth); - SwapShort(&header->pageHeight); -} -#endif - -// ---------------------------------------------------------- - -/* IFF chunk IDs */ - -typedef DWORD IFF_ID; - -#define MAKE_ID(a, b, c, d) ((IFF_ID)(a)<<24 | (IFF_ID)(b)<<16 | (IFF_ID)(c)<<8 | (IFF_ID)(d)) - -#define ID_FORM MAKE_ID('F', 'O', 'R', 'M') /* EA IFF 85 group identifier */ -#define ID_CAT MAKE_ID('C', 'A', 'T', ' ') /* EA IFF 85 group identifier */ -#define ID_LIST MAKE_ID('L', 'I', 'S', 'T') /* EA IFF 85 group identifier */ -#define ID_PROP MAKE_ID('P', 'R', 'O', 'P') /* EA IFF 85 group identifier */ -#define ID_END MAKE_ID('E', 'N', 'D', ' ') /* unofficial END-of-FORM identifier (see Amiga RKM Devices Ed.3 page 376) */ - -#define ID_ILBM MAKE_ID('I', 'L', 'B', 'M') /* EA IFF 85 raster bitmap form */ -#define ID_DEEP MAKE_ID('D', 'E', 'E', 'P') /* Chunky pixel image files (Used in TV Paint) */ -#define ID_RGB8 MAKE_ID('R', 'G', 'B', '8') /* RGB image forms, Turbo Silver (Impulse) */ -#define ID_RGBN MAKE_ID('R', 'G', 'B', 'N') /* RGB image forms, Turbo Silver (Impulse) */ -#define ID_PBM MAKE_ID('P', 'B', 'M', ' ') /* 256-color chunky format (DPaint 2 ?) */ -#define ID_ACBM MAKE_ID('A', 'C', 'B', 'M') /* Amiga Contiguous Bitmap (AmigaBasic) */ -/* generic */ -#define ID_FVER MAKE_ID('F', 'V', 'E', 'R') /* AmigaOS version string */ -#define ID_JUNK MAKE_ID('J', 'U', 'N', 'K') /* always ignore this chunk */ -#define ID_ANNO MAKE_ID('A', 'N', 'N', 'O') /* EA IFF 85 Generic Annotation chunk */ -#define ID_AUTH MAKE_ID('A', 'U', 'T', 'H') /* EA IFF 85 Generic Author chunk */ -#define ID_CHRS MAKE_ID('C', 'H', 'R', 'S') /* EA IFF 85 Generic character string chunk */ -#define ID_NAME MAKE_ID('N', 'A', 'M', 'E') /* EA IFF 85 Generic Name of art, music, etc. chunk */ -#define ID_TEXT MAKE_ID('T', 'E', 'X', 'T') /* EA IFF 85 Generic unformatted ASCII text chunk */ -#define ID_copy MAKE_ID('(', 'c', ')', ' ') /* EA IFF 85 Generic Copyright text chunk */ -/* ILBM chunks */ -#define ID_BMHD MAKE_ID('B', 'M', 'H', 'D') /* ILBM BitmapHeader */ -#define ID_CMAP MAKE_ID('C', 'M', 'A', 'P') /* ILBM 8bit RGB colormap */ -#define ID_GRAB MAKE_ID('G', 'R', 'A', 'B') /* ILBM "hotspot" coordiantes */ -#define ID_DEST MAKE_ID('D', 'E', 'S', 'T') /* ILBM destination image info */ -#define ID_SPRT MAKE_ID('S', 'P', 'R', 'T') /* ILBM sprite identifier */ -#define ID_CAMG MAKE_ID('C', 'A', 'M', 'G') /* Amiga viewportmodes */ -#define ID_BODY MAKE_ID('B', 'O', 'D', 'Y') /* ILBM image data */ -#define ID_CRNG MAKE_ID('C', 'R', 'N', 'G') /* color cycling */ -#define ID_CCRT MAKE_ID('C', 'C', 'R', 'T') /* color cycling */ -#define ID_CLUT MAKE_ID('C', 'L', 'U', 'T') /* Color Lookup Table chunk */ -#define ID_DPI MAKE_ID('D', 'P', 'I', ' ') /* Dots per inch chunk */ -#define ID_DPPV MAKE_ID('D', 'P', 'P', 'V') /* DPaint perspective chunk (EA) */ -#define ID_DRNG MAKE_ID('D', 'R', 'N', 'G') /* DPaint IV enhanced color cycle chunk (EA) */ -#define ID_EPSF MAKE_ID('E', 'P', 'S', 'F') /* Encapsulated Postscript chunk */ -#define ID_CMYK MAKE_ID('C', 'M', 'Y', 'K') /* Cyan, Magenta, Yellow, & Black color map (Soft-Logik) */ -#define ID_CNAM MAKE_ID('C', 'N', 'A', 'M') /* Color naming chunk (Soft-Logik) */ -#define ID_PCHG MAKE_ID('P', 'C', 'H', 'G') /* Line by line palette control information (Sebastiano Vigna) */ -#define ID_PRVW MAKE_ID('P', 'R', 'V', 'W') /* A mini duplicate ILBM used for preview (Gary Bonham) */ -#define ID_XBMI MAKE_ID('X', 'B', 'M', 'I') /* eXtended BitMap Information (Soft-Logik) */ -#define ID_CTBL MAKE_ID('C', 'T', 'B', 'L') /* Newtek Dynamic Ham color chunk */ -#define ID_DYCP MAKE_ID('D', 'Y', 'C', 'P') /* Newtek Dynamic Ham chunk */ -#define ID_SHAM MAKE_ID('S', 'H', 'A', 'M') /* Sliced HAM color chunk */ -#define ID_ABIT MAKE_ID('A', 'B', 'I', 'T') /* ACBM body chunk */ -#define ID_DCOL MAKE_ID('D', 'C', 'O', 'L') /* unofficial direct color */ - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "IFF"; -} - -static const char * DLL_CALLCONV -Description() { - return "IFF Interleaved Bitmap"; -} - -static const char * DLL_CALLCONV -Extension() { - return "iff,lbm"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-iff"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - DWORD type = 0; - - // read chunk type - io->read_proc(&type, 4, 1, handle); -#ifndef FREEIMAGE_BIGENDIAN - SwapLong(&type); -#endif - - if(type != ID_FORM) - return FALSE; - - // skip 4 bytes - io->read_proc(&type, 4, 1, handle); - - // read chunk type - io->read_proc(&type, 4, 1, handle); -#ifndef FREEIMAGE_BIGENDIAN - SwapLong(&type); -#endif - - // File format : ID_PBM = Packed Bitmap, ID_ILBM = Interleaved Bitmap - return (type == ID_ILBM) || (type == ID_PBM); -} - - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return FALSE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - if (handle != NULL) { - FIBITMAP *dib = NULL; - - DWORD type, size; - - io->read_proc(&type, 4, 1, handle); -#ifndef FREEIMAGE_BIGENDIAN - SwapLong(&type); -#endif - - if(type != ID_FORM) - return NULL; - - io->read_proc(&size, 4, 1, handle); -#ifndef FREEIMAGE_BIGENDIAN - SwapLong(&size); -#endif - - io->read_proc(&type, 4, 1, handle); -#ifndef FREEIMAGE_BIGENDIAN - SwapLong(&type); -#endif - - if((type != ID_ILBM) && (type != ID_PBM)) - return NULL; - - size -= 4; - - unsigned width = 0, height = 0, planes = 0, depth = 0, comp = 0; - - while (size) { - DWORD ch_type,ch_size; - - io->read_proc(&ch_type, 4, 1, handle); -#ifndef FREEIMAGE_BIGENDIAN - SwapLong(&ch_type); -#endif - - io->read_proc(&ch_size,4,1,handle ); -#ifndef FREEIMAGE_BIGENDIAN - SwapLong(&ch_size); -#endif - - unsigned ch_end = io->tell_proc(handle) + ch_size; - - if (ch_type == ID_BMHD) { // Bitmap Header - if (dib) - FreeImage_Unload(dib); - - BMHD bmhd; - - io->read_proc(&bmhd, sizeof(bmhd), 1, handle); -#ifndef FREEIMAGE_BIGENDIAN - SwapHeader(&bmhd); -#endif - - width = bmhd.w; - height = bmhd.h; - planes = bmhd.nPlanes; - comp = bmhd.compression; - - if(bmhd.masking & 1) - planes++; // there is a mask ( 'stencil' ) - - if (planes > 8 && planes != 24) - return NULL; - - depth = planes > 8 ? 24 : 8; - - if( depth == 24 ) { - dib = FreeImage_Allocate(width, height, depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } else { - dib = FreeImage_Allocate(width, height, depth); - } - } else if (ch_type == ID_CMAP) { // Palette (Color Map) - if (!dib) - return NULL; - - RGBQUAD *pal = FreeImage_GetPalette(dib); - if(pal != NULL) { - unsigned palette_entries = MIN((unsigned)ch_size / 3, FreeImage_GetColorsUsed(dib)); - for (unsigned k = 0; k < palette_entries; k++) { - io->read_proc(&pal[k].rgbRed, 1, 1, handle ); - io->read_proc(&pal[k].rgbGreen, 1, 1, handle ); - io->read_proc(&pal[k].rgbBlue, 1, 1, handle ); - } - } - } else if (ch_type == ID_BODY) { - if (!dib) - return NULL; - - if (type == ID_PBM) { - // NON INTERLACED (LBM) - - unsigned line = FreeImage_GetLine(dib) + 1 & ~1; - - for (unsigned i = 0; i < FreeImage_GetHeight(dib); i++) { - BYTE *bits = FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - i - 1); - - if (comp == 1) { - // use RLE compression - - DWORD number_of_bytes_written = 0; - BYTE rle_count; - BYTE byte; - - while (number_of_bytes_written < line) { - io->read_proc(&rle_count, 1, 1, handle); - - if (rle_count < 128) { - for (int k = 0; k < rle_count + 1; k++) { - io->read_proc(&byte, 1, 1, handle); - - bits[number_of_bytes_written++] += byte; - } - } else if (rle_count > 128) { - io->read_proc(&byte, 1, 1, handle); - - for (int k = 0; k < 257 - rle_count; k++) { - bits[number_of_bytes_written++] += byte; - } - } - } - } else { - // don't use compression - - io->read_proc(bits, line, 1, handle); - } - } - - return dib; - } else { - // INTERLACED (ILBM) - - unsigned pixel_size = depth/8; - unsigned n_width=(width+15)&~15; - unsigned plane_size = n_width/8; - unsigned src_size = plane_size * planes; - BYTE *src = (BYTE*)malloc(src_size); - BYTE *dest = FreeImage_GetBits(dib); - - dest += FreeImage_GetPitch(dib) * height; - - for (unsigned y = 0; y < height; y++) { - dest -= FreeImage_GetPitch(dib); - - // read all planes in one hit, - // 'coz PSP compresses across planes... - - if (comp) { - // unpacker algorithm - - for(unsigned x = 0; x < src_size;) { - // read the next source byte into t - signed char t = 0; - io->read_proc(&t, 1, 1, handle); - - if (t >= 0) { - // t = [0..127] => copy the next t+1 bytes literally - unsigned size_to_read = t + 1; - - if((size_to_read + x) > src_size) { - // sanity check for buffer overruns - size_to_read = src_size - x; - io->read_proc(src + x, size_to_read, 1, handle); - x += (t + 1); - } else { - io->read_proc(src + x, size_to_read, 1, handle); - x += size_to_read; - } - } else if (t != -128) { - // t = [-1..-127] => replicate the next byte -t+1 times - BYTE b = 0; - io->read_proc(&b, 1, 1, handle); - unsigned size_to_copy = (unsigned)(-(int)t + 1); - - if((size_to_copy + x) > src_size) { - // sanity check for buffer overruns - size_to_copy = src_size - x; - memset(src + x, b, size_to_copy); - x += (unsigned)(-(int)t + 1); - } else { - memset(src + x, b, size_to_copy); - x += size_to_copy; - } - } - // t = -128 => noop - } - } else { - io->read_proc(src, src_size, 1, handle); - } - - // lazy planar->chunky... - - for (unsigned x = 0; x < width; x++) { - for (unsigned n = 0; n < planes; n++) { - BYTE bit = (BYTE)( src[n * plane_size + (x / 8)] >> ((x^7) & 7) ); - - dest[x * pixel_size + (n / 8)] |= (bit & 1) << (n & 7); - } - } - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - if (depth == 24) { - for (unsigned x = 0; x < width; ++x){ - INPLACESWAP(dest[x * 3], dest[x * 3 + 2]); - } - } -#endif - } - - free(src); - - return dib; - } - } - - // Every odd-length chunk is followed by a 0 pad byte. This pad - // byte is not counted in ch_size. - if (ch_size & 1) { - ch_size++; - ch_end++; - } - - io->seek_proc(handle, ch_end - io->tell_proc(handle), SEEK_CUR); - - size -= ch_size + 8; - } - - if (dib) - FreeImage_Unload(dib); - } - - return 0; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitIFF(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = NULL; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginJ2K.cpp b/plugins/AdvaImg/src/FreeImage/PluginJ2K.cpp deleted file mode 100644 index b8bcfc8b58..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginJ2K.cpp +++ /dev/null @@ -1,328 +0,0 @@ -// ========================================================== -// JPEG2000 J2K codestream Loader and Writer -// -// 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" -#include "../LibOpenJPEG/openjpeg.h" -#include "J2KHelper.h" - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Internal functions -// ========================================================== - -/** -OpenJPEG Error callback -*/ -static void j2k_error_callback(const char *msg, void *client_data) { - FreeImage_OutputMessageProc(s_format_id, "Error: %s", msg); -} -/** -OpenJPEG Warning callback -*/ -static void j2k_warning_callback(const char *msg, void *client_data) { - FreeImage_OutputMessageProc(s_format_id, "Warning: %s", msg); -} - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "J2K"; -} - -static const char * DLL_CALLCONV -Description() { - return "JPEG-2000 codestream"; -} - -static const char * DLL_CALLCONV -Extension() { - return "j2k,j2c"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/j2k"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE jpc_signature[] = { 0xFF, 0x4F }; - BYTE signature[2] = { 0, 0 }; - - long tell = io->tell_proc(handle); - io->read_proc(signature, 1, sizeof(jpc_signature), handle); - io->seek_proc(handle, tell, SEEK_SET); - - return (memcmp(jpc_signature, signature, sizeof(jpc_signature)) == 0); -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return ( - (depth == 8) || - (depth == 24) || - (depth == 32) - ); -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return ( - (type == FIT_BITMAP) || - (type == FIT_UINT16) || - (type == FIT_RGB16) || - (type == FIT_RGBA16) - ); -} - -// ---------------------------------------------------------- - -static void * DLL_CALLCONV -Open(FreeImageIO *io, fi_handle handle, BOOL read) { - // create the stream wrapper - J2KFIO_t *fio = opj_freeimage_stream_create(io, handle, read); - return fio; -} - -static void DLL_CALLCONV -Close(FreeImageIO *io, fi_handle handle, void *data) { - // destroy the stream wrapper - J2KFIO_t *fio = (J2KFIO_t*)data; - opj_freeimage_stream_destroy(fio); -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - J2KFIO_t *fio = (J2KFIO_t*)data; - if (handle && fio) { - opj_codec_t *d_codec = NULL; // handle to a decompressor - opj_dparameters_t parameters; // decompression parameters - opj_image_t *image = NULL; // decoded image - - FIBITMAP *dib = NULL; - - // check the file format - if(!Validate(io, handle)) { - return NULL; - } - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // get the OpenJPEG stream - opj_stream_t *d_stream = fio->stream; - - // set decoding parameters to default values - opj_set_default_decoder_parameters(¶meters); - - try { - // decode the JPEG-2000 codestream - - // get a decoder handle - d_codec = opj_create_decompress(OPJ_CODEC_J2K); - - // configure the event callbacks - // catch events using our callbacks (no local context needed here) - opj_set_info_handler(d_codec, NULL, NULL); - opj_set_warning_handler(d_codec, j2k_warning_callback, NULL); - opj_set_error_handler(d_codec, j2k_error_callback, NULL); - - // setup the decoder decoding parameters using user parameters - if( !opj_setup_decoder(d_codec, ¶meters) ) { - throw "Failed to setup the decoder\n"; - } - - // read the main header of the codestream and if necessary the JP2 boxes - if( !opj_read_header(d_stream, d_codec, &image)) { - throw "Failed to read the header\n"; - } - - // --- header only mode - - if (header_only) { - // create output image - dib = J2KImageToFIBITMAP(s_format_id, image, header_only); - if(!dib) { - throw "Failed to import JPEG2000 image"; - } - // clean-up and return header data - opj_destroy_codec(d_codec); - opj_image_destroy(image); - return dib; - } - - // decode the stream and fill the image structure - if( !( opj_decode(d_codec, d_stream, image) && opj_end_decompress(d_codec, d_stream) ) ) { - throw "Failed to decode image!\n"; - } - - // free the codec context - opj_destroy_codec(d_codec); - d_codec = NULL; - - // create output image - dib = J2KImageToFIBITMAP(s_format_id, image, header_only); - if(!dib) { - throw "Failed to import JPEG2000 image"; - } - - // free image data structure - opj_image_destroy(image); - - return dib; - - } catch (const char *text) { - if(dib) { - FreeImage_Unload(dib); - } - // free remaining structures - opj_destroy_codec(d_codec); - opj_image_destroy(image); - - FreeImage_OutputMessageProc(s_format_id, text); - - return NULL; - } - } - - return NULL; -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - J2KFIO_t *fio = (J2KFIO_t*)data; - if (dib && handle && fio) { - BOOL bSuccess; - opj_codec_t *c_codec = NULL; // handle to a compressor - opj_cparameters_t parameters; // compression parameters - opj_image_t *image = NULL; // image to encode - - // get the OpenJPEG stream - opj_stream_t *c_stream = fio->stream; - - // set encoding parameters to default values - opj_set_default_encoder_parameters(¶meters); - - try { - parameters.tcp_numlayers = 0; - // if no rate entered, apply a 16:1 rate by default - if(flags == J2K_DEFAULT) { - parameters.tcp_rates[0] = (float)16; - } else { - // for now, the flags parameter is only used to specify the rate - parameters.tcp_rates[0] = (float)(flags & 0x3FF); - } - parameters.tcp_numlayers++; - parameters.cp_disto_alloc = 1; - - // convert the dib to a OpenJPEG image - image = FIBITMAPToJ2KImage(s_format_id, dib, ¶meters); - if(!image) { - return FALSE; - } - - // decide if MCT should be used - parameters.tcp_mct = (image->numcomps == 3) ? 1 : 0; - - // encode the destination image - - // get a J2K compressor handle - c_codec = opj_create_compress(OPJ_CODEC_J2K); - - // configure the event callbacks - // catch events using our callbacks (no local context needed here) - opj_set_info_handler(c_codec, NULL, NULL); - opj_set_warning_handler(c_codec, j2k_warning_callback, NULL); - opj_set_error_handler(c_codec, j2k_error_callback, NULL); - - // setup the encoder parameters using the current image and using user parameters - opj_setup_encoder(c_codec, ¶meters, image); - - // encode the image - bSuccess = opj_start_compress(c_codec, image, c_stream); - if(bSuccess) { - bSuccess = bSuccess && opj_encode(c_codec, c_stream); - if(bSuccess) { - bSuccess = bSuccess && opj_end_compress(c_codec, c_stream); - } - } - if (!bSuccess) { - throw "Failed to encode image"; - } - - // free remaining compression structures - opj_destroy_codec(c_codec); - - // free image data - opj_image_destroy(image); - - return TRUE; - - } catch (const char *text) { - if(c_codec) opj_destroy_codec(c_codec); - if(image) opj_image_destroy(image); - FreeImage_OutputMessageProc(s_format_id, text); - return FALSE; - } - } - - return FALSE; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitJ2K(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = Open; - plugin->close_proc = Close; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginJNG.cpp b/plugins/AdvaImg/src/FreeImage/PluginJNG.cpp deleted file mode 100644 index 817e731168..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginJNG.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// ========================================================== -// JNG loader -// -// Design and implementation by -// - Herve 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" - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ---------------------------------------------------------- - -#define JNG_SIGNATURE_SIZE 8 // size of the signature - -// ---------------------------------------------------------- - -// ---------------------------------------------------------- -// mng interface (see MNGHelper.cpp) -// ---------------------------------------------------------- - -FIBITMAP* mng_ReadChunks(int format_id, FreeImageIO *io, fi_handle handle, long Offset, int flags = 0); -BOOL mng_WriteJNG(int format_id, FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int flags); - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "JNG"; -} - -static const char * DLL_CALLCONV -Description() { - return "JPEG Network Graphics"; -} - -static const char * DLL_CALLCONV -Extension() { - return "jng"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-mng"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE jng_signature[8] = { 139, 74, 78, 71, 13, 10, 26, 10 }; - BYTE signature[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - io->read_proc(&signature, 1, JNG_SIGNATURE_SIZE, handle); - - return (memcmp(jng_signature, signature, JNG_SIGNATURE_SIZE) == 0) ? TRUE : FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return ( - (depth == 8) || - (depth == 24) || - (depth == 32) - ); -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return (type == FIT_BITMAP) ? TRUE : FALSE; -} - -static BOOL DLL_CALLCONV -SupportsICCProfiles() { - return TRUE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - - -// ---------------------------------------------------------- - -static void * DLL_CALLCONV -Open(FreeImageIO *io, fi_handle handle, BOOL read) { - return NULL; -} - -static void DLL_CALLCONV -Close(FreeImageIO *io, fi_handle handle, void *data) { -} - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - long offset = JNG_SIGNATURE_SIZE; // move to skip first 8 bytes of signature - - // check the signature (8 bytes) - if(Validate(io, handle) == FALSE) { - return NULL; - } - - // parse chunks and decode a jng or mng bitmap - return mng_ReadChunks(s_format_id, io, handle, offset, flags); -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - - return mng_WriteJNG(s_format_id, io, dib, handle, flags); -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitJNG(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = Open; - plugin->close_proc = Close; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = SupportsICCProfiles; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginJP2.cpp b/plugins/AdvaImg/src/FreeImage/PluginJP2.cpp deleted file mode 100644 index 742fe2c038..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginJP2.cpp +++ /dev/null @@ -1,328 +0,0 @@ -// ========================================================== -// JPEG2000 JP2 file format Loader and Writer -// -// 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" -#include "../LibOpenJPEG/openjpeg.h" -#include "J2KHelper.h" - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Internal functions -// ========================================================== - -/** -OpenJPEG Error callback -*/ -static void jp2_error_callback(const char *msg, void *client_data) { - FreeImage_OutputMessageProc(s_format_id, "Error: %s", msg); -} -/** -OpenJPEG Warning callback -*/ -static void jp2_warning_callback(const char *msg, void *client_data) { - FreeImage_OutputMessageProc(s_format_id, "Warning: %s", msg); -} - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "JP2"; -} - -static const char * DLL_CALLCONV -Description() { - return "JPEG-2000 File Format"; -} - -static const char * DLL_CALLCONV -Extension() { - return "jp2"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/jp2"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE jp2_signature[] = { 0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A }; - BYTE signature[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - long tell = io->tell_proc(handle); - io->read_proc(signature, 1, sizeof(jp2_signature), handle); - io->seek_proc(handle, tell, SEEK_SET); - - return (memcmp(jp2_signature, signature, sizeof(jp2_signature)) == 0); -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return ( - (depth == 8) || - (depth == 24) || - (depth == 32) - ); -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return ( - (type == FIT_BITMAP) || - (type == FIT_UINT16) || - (type == FIT_RGB16) || - (type == FIT_RGBA16) - ); -} - -// ---------------------------------------------------------- - -static void * DLL_CALLCONV -Open(FreeImageIO *io, fi_handle handle, BOOL read) { - // create the stream wrapper - J2KFIO_t *fio = opj_freeimage_stream_create(io, handle, read); - return fio; -} - -static void DLL_CALLCONV -Close(FreeImageIO *io, fi_handle handle, void *data) { - // destroy the stream wrapper - J2KFIO_t *fio = (J2KFIO_t*)data; - opj_freeimage_stream_destroy(fio); -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - J2KFIO_t *fio = (J2KFIO_t*)data; - if (handle && fio) { - opj_codec_t *d_codec = NULL; // handle to a decompressor - opj_dparameters_t parameters; // decompression parameters - opj_image_t *image = NULL; // decoded image - - FIBITMAP *dib = NULL; - - // check the file format - if(!Validate(io, handle)) { - return NULL; - } - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // get the OpenJPEG stream - opj_stream_t *d_stream = fio->stream; - - // set decoding parameters to default values - opj_set_default_decoder_parameters(¶meters); - - try { - // decode the JPEG-2000 file - - // get a decoder handle - d_codec = opj_create_decompress(OPJ_CODEC_JP2); - - // configure the event callbacks - // catch events using our callbacks (no local context needed here) - opj_set_info_handler(d_codec, NULL, NULL); - opj_set_warning_handler(d_codec, jp2_warning_callback, NULL); - opj_set_error_handler(d_codec, jp2_error_callback, NULL); - - // setup the decoder decoding parameters using user parameters - if( !opj_setup_decoder(d_codec, ¶meters) ) { - throw "Failed to setup the decoder\n"; - } - - // read the main header of the codestream and if necessary the JP2 boxes - if( !opj_read_header(d_stream, d_codec, &image)) { - throw "Failed to read the header\n"; - } - - // --- header only mode - - if (header_only) { - // create output image - dib = J2KImageToFIBITMAP(s_format_id, image, header_only); - if(!dib) { - throw "Failed to import JPEG2000 image"; - } - // clean-up and return header data - opj_destroy_codec(d_codec); - opj_image_destroy(image); - return dib; - } - - // decode the stream and fill the image structure - if( !( opj_decode(d_codec, d_stream, image) && opj_end_decompress(d_codec, d_stream) ) ) { - throw "Failed to decode image!\n"; - } - - // free the codec context - opj_destroy_codec(d_codec); - d_codec = NULL; - - // create output image - dib = J2KImageToFIBITMAP(s_format_id, image, header_only); - if(!dib) { - throw "Failed to import JPEG2000 image"; - } - - // free image data structure - opj_image_destroy(image); - - return dib; - - } catch (const char *text) { - if(dib) { - FreeImage_Unload(dib); - } - // free remaining structures - opj_destroy_codec(d_codec); - opj_image_destroy(image); - - FreeImage_OutputMessageProc(s_format_id, text); - - return NULL; - } - } - - return NULL; -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - J2KFIO_t *fio = (J2KFIO_t*)data; - if (dib && handle && fio) { - BOOL bSuccess; - opj_codec_t *c_codec = NULL; // handle to a compressor - opj_cparameters_t parameters; // compression parameters - opj_image_t *image = NULL; // image to encode - - // get the OpenJPEG stream - opj_stream_t *c_stream = fio->stream; - - // set encoding parameters to default values - opj_set_default_encoder_parameters(¶meters); - - try { - parameters.tcp_numlayers = 0; - // if no rate entered, apply a 16:1 rate by default - if(flags == JP2_DEFAULT) { - parameters.tcp_rates[0] = (float)16; - } else { - // for now, the flags parameter is only used to specify the rate - parameters.tcp_rates[0] = (float)(flags & 0x3FF); - } - parameters.tcp_numlayers++; - parameters.cp_disto_alloc = 1; - - // convert the dib to a OpenJPEG image - image = FIBITMAPToJ2KImage(s_format_id, dib, ¶meters); - if(!image) { - return FALSE; - } - - // decide if MCT should be used - parameters.tcp_mct = (image->numcomps == 3) ? 1 : 0; - - // encode the destination image - - // get a JP2 compressor handle - c_codec = opj_create_compress(OPJ_CODEC_JP2); - - // configure the event callbacks - // catch events using our callbacks (no local context needed here) - opj_set_info_handler(c_codec, NULL, NULL); - opj_set_warning_handler(c_codec, jp2_warning_callback, NULL); - opj_set_error_handler(c_codec, jp2_error_callback, NULL); - - // setup the encoder parameters using the current image and using user parameters - opj_setup_encoder(c_codec, ¶meters, image); - - // encode the image - bSuccess = opj_start_compress(c_codec, image, c_stream); - if(bSuccess) { - bSuccess = bSuccess && opj_encode(c_codec, c_stream); - if(bSuccess) { - bSuccess = bSuccess && opj_end_compress(c_codec, c_stream); - } - } - if (!bSuccess) { - throw "Failed to encode image"; - } - - // free remaining compression structures - opj_destroy_codec(c_codec); - - // free image data - opj_image_destroy(image); - - return TRUE; - - } catch (const char *text) { - if(c_codec) opj_destroy_codec(c_codec); - if(image) opj_image_destroy(image); - FreeImage_OutputMessageProc(s_format_id, text); - return FALSE; - } - } - - return FALSE; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitJP2(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = Open; - plugin->close_proc = Close; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginJXR.cpp b/plugins/AdvaImg/src/FreeImage/PluginJXR.cpp deleted file mode 100644 index 0e14e09ac9..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginJXR.cpp +++ /dev/null @@ -1,1475 +0,0 @@ -// ========================================================== -// JPEG XR Loader & Writer -// -// Design and implementation by -// - Herve 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" -#include "../Metadata/FreeImageTag.h" - -#include "../LibJXR/jxrgluelib/JXRGlue.h" - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// FreeImageIO interface (I/O streaming functions) -// ========================================================== - -/** -JXR wrapper for FreeImage I/O handle -*/ -typedef struct tagFreeImageJXRIO { - FreeImageIO *io; - fi_handle handle; -} FreeImageJXRIO; - -static ERR -_jxr_io_Read(WMPStream* pWS, void* pv, size_t cb) { - FreeImageJXRIO *fio = (FreeImageJXRIO*)pWS->state.pvObj; - return (fio->io->read_proc(pv, (unsigned)cb, 1, fio->handle) == 1) ? WMP_errSuccess : WMP_errFileIO; -} - -static ERR -_jxr_io_Write(WMPStream* pWS, const void* pv, size_t cb) { - FreeImageJXRIO *fio = (FreeImageJXRIO*)pWS->state.pvObj; - if(0 != cb) { - return (fio->io->write_proc((void*)pv, (unsigned)cb, 1, fio->handle) == 1) ? WMP_errSuccess : WMP_errFileIO; - } - return WMP_errFileIO; -} - -static ERR -_jxr_io_SetPos(WMPStream* pWS, size_t offPos) { - FreeImageJXRIO *fio = (FreeImageJXRIO*)pWS->state.pvObj; - return (fio->io->seek_proc(fio->handle, (long)offPos, SEEK_SET) == 0) ? WMP_errSuccess : WMP_errFileIO; -} - -static ERR -_jxr_io_GetPos(WMPStream* pWS, size_t* poffPos) { - FreeImageJXRIO *fio = (FreeImageJXRIO*)pWS->state.pvObj; - long lOff = fio->io->tell_proc(fio->handle); - if(lOff == -1) { - return WMP_errFileIO; - } - *poffPos = (size_t)lOff; - return WMP_errSuccess; -} - -static Bool -_jxr_io_EOS(WMPStream* pWS) { - FreeImageJXRIO *fio = (FreeImageJXRIO*)pWS->state.pvObj; - long currentPos = fio->io->tell_proc(fio->handle); - fio->io->seek_proc(fio->handle, 0, SEEK_END); - long fileRemaining = fio->io->tell_proc(fio->handle) - currentPos; - fio->io->seek_proc(fio->handle, currentPos, SEEK_SET); - return (fileRemaining > 0); -} - -static ERR -_jxr_io_Close(WMPStream** ppWS) { - WMPStream *pWS = *ppWS; - // HACK : we use fMem to avoid a stream destruction by the library - // because FreeImage MUST HAVE the ownership of the stream - // see _jxr_io_Create - if(pWS && pWS->fMem) { - free(pWS); - *ppWS = NULL; - } - return WMP_errSuccess; -} - -static ERR -_jxr_io_Create(WMPStream **ppWS, FreeImageJXRIO *jxr_io) { - *ppWS = (WMPStream*)calloc(1, sizeof(**ppWS)); - if(*ppWS) { - WMPStream *pWS = *ppWS; - - pWS->state.pvObj = jxr_io; - pWS->Close = _jxr_io_Close; - pWS->EOS = _jxr_io_EOS; - pWS->Read = _jxr_io_Read; - pWS->Write = _jxr_io_Write; - pWS->SetPos = _jxr_io_SetPos; - pWS->GetPos = _jxr_io_GetPos; - - // HACK : we use fMem to avoid a stream destruction by the library - // because FreeImage MUST HAVE the ownership of the stream - // see _jxr_io_Close - pWS->fMem = FALSE; - - return WMP_errSuccess; - } - return WMP_errOutOfMemory; -} - -// ========================================================== -// JPEG XR Error handling -// ========================================================== - -static const char* -JXR_ErrorMessage(const int error) { - switch(error) { - case WMP_errNotYetImplemented: - case WMP_errAbstractMethod: - return "Not yet implemented"; - case WMP_errOutOfMemory: - return "Out of memory"; - case WMP_errFileIO: - return "File I/O error"; - case WMP_errBufferOverflow: - return "Buffer overflow"; - case WMP_errInvalidParameter: - return "Invalid parameter"; - case WMP_errInvalidArgument: - return "Invalid argument"; - case WMP_errUnsupportedFormat: - return "Unsupported format"; - case WMP_errIncorrectCodecVersion: - return "Incorrect codec version"; - case WMP_errIndexNotFound: - return "Format converter: Index not found"; - case WMP_errOutOfSequence: - return "Metadata: Out of sequence"; - case WMP_errMustBeMultipleOf16LinesUntilLastCall: - return "Must be multiple of 16 lines until last call"; - case WMP_errPlanarAlphaBandedEncRequiresTempFile: - return "Planar alpha banded encoder requires temp files"; - case WMP_errAlphaModeCannotBeTranscoded: - return "Alpha mode cannot be transcoded"; - case WMP_errIncorrectCodecSubVersion: - return "Incorrect codec subversion"; - case WMP_errFail: - case WMP_errNotInitialized: - default: - return "Invalid instruction - please contact the FreeImage team"; - } -} - -// ========================================================== -// Helper functions & macro -// ========================================================== - -#define JXR_CHECK(error_code) \ - if(error_code < 0) { \ - const char *error_message = JXR_ErrorMessage(error_code); \ - throw error_message; \ - } - -// -------------------------------------------------------------------------- - -/** -Input conversions natively understood by FreeImage -@see GetNativePixelFormat -*/ -typedef struct tagJXRInputConversion { - BITDEPTH_BITS bdBitDepth; - U32 cbitUnit; - FREE_IMAGE_TYPE image_type; - unsigned red_mask; - unsigned green_mask; - unsigned blue_mask; -} JXRInputConversion; - -/** -Conversion table for native FreeImage formats -@see GetNativePixelFormat -*/ -static JXRInputConversion s_FreeImagePixelInfo[] = { - // 1-bit bitmap - { BD_1, 1, FIT_BITMAP, 0, 0, 0 }, - // 8-, 24-, 32-bit bitmap - { BD_8, 8, FIT_BITMAP, 0, 0, 0 }, - { BD_8, 24, FIT_BITMAP, 0, 0, 0 }, - { BD_8, 32, FIT_BITMAP, 0, 0, 0 }, - // 16-bit RGB 565 - { BD_565, 16, FIT_BITMAP, FI16_565_RED_MASK, FI16_565_GREEN_MASK, FI16_565_BLUE_MASK }, - // 16-bit RGB 555 - { BD_5, 16, FIT_BITMAP, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK }, - // 16-bit greyscale, RGB16, RGBA16 bitmap - { BD_16, 16, FIT_UINT16, 0, 0, 0 }, - { BD_16, 48, FIT_RGB16, 0, 0, 0 }, - { BD_16, 64, FIT_RGBA16, 0, 0, 0 }, - // 32-bit float, RGBF, RGBAF bitmap - { BD_32F, 32, FIT_FLOAT, 0, 0, 0 }, - { BD_32F, 96, FIT_RGBF, 0, 0, 0 }, - { BD_32F, 128, FIT_RGBAF, 0, 0, 0 } -}; - -/** -Scan input pixelInfo specifications and return the equivalent FreeImage info for loading -@param pixelInfo Image specifications -@param out_guid_format (returned value) output pixel format -@param image_type (returned value) Image type -@param bpp (returned value) Image bit depth -@param red_mask (returned value) RGB mask -@param green_mask (returned value) RGB mask -@param blue_mask (returned value) RGB mask -@return Returns WMP_errSuccess if successful, returns WMP_errFail otherwise -@see GetInputPixelFormat -*/ -static ERR -GetNativePixelFormat(const PKPixelInfo *pixelInfo, PKPixelFormatGUID *out_guid_format, FREE_IMAGE_TYPE *image_type, unsigned *bpp, unsigned *red_mask, unsigned *green_mask, unsigned *blue_mask) { - const unsigned s_FreeImagePixelInfoSize = (unsigned)sizeof(s_FreeImagePixelInfo) / sizeof(*(s_FreeImagePixelInfo)); - - for(unsigned i = 0; i < s_FreeImagePixelInfoSize; i++) { - if(pixelInfo->bdBitDepth == s_FreeImagePixelInfo[i].bdBitDepth) { - if(pixelInfo->cbitUnit == s_FreeImagePixelInfo[i].cbitUnit) { - // found ! now get dst image format specifications - memcpy(out_guid_format, pixelInfo->pGUIDPixFmt, sizeof(PKPixelFormatGUID)); - *image_type = s_FreeImagePixelInfo[i].image_type; - *bpp = s_FreeImagePixelInfo[i].cbitUnit; - *red_mask = s_FreeImagePixelInfo[i].red_mask; - *green_mask = s_FreeImagePixelInfo[i].green_mask; - *blue_mask = s_FreeImagePixelInfo[i].blue_mask; - return WMP_errSuccess; - } - } - } - - // not found : need pixel format conversion - return WMP_errFail; -} - -/** -Scan input file guid format and return the equivalent FreeImage info & target guid format for loading -@param pDecoder Decoder handle -@param guid_format (returned value) Output pixel format -@param image_type (returned value) Image type -@param bpp (returned value) Image bit depth -@param red_mask (returned value) RGB mask -@param green_mask (returned value) RGB mask -@param blue_mask (returned value) RGB mask -@return Returns TRUE if successful, returns FALSE otherwise -*/ -static ERR -GetInputPixelFormat(PKImageDecode *pDecoder, PKPixelFormatGUID *guid_format, FREE_IMAGE_TYPE *image_type, unsigned *bpp, unsigned *red_mask, unsigned *green_mask, unsigned *blue_mask) { - ERR error_code = 0; // error code as returned by the interface - PKPixelInfo pixelInfo; // image specifications - - try { - // get input file pixel format ... - PKPixelFormatGUID pguidSourcePF; - error_code = pDecoder->GetPixelFormat(pDecoder, &pguidSourcePF); - JXR_CHECK(error_code); - pixelInfo.pGUIDPixFmt = &pguidSourcePF; - // ... check for a supported format and get the format specifications - error_code = PixelFormatLookup(&pixelInfo, LOOKUP_FORWARD); - JXR_CHECK(error_code); - - // search for an equivalent native FreeImage format - error_code = GetNativePixelFormat(&pixelInfo, guid_format, image_type, bpp, red_mask, green_mask, blue_mask); - - if(error_code != WMP_errSuccess) { - // try to find a suitable conversion function ... - const PKPixelFormatGUID *ppguidTargetPF = NULL; // target pixel format - unsigned iIndex = 0; // first available conversion function - do { - error_code = PKFormatConverter_EnumConversions(&pguidSourcePF, iIndex, &ppguidTargetPF); - if(error_code == WMP_errSuccess) { - // found a conversion function, is the converted format a native FreeImage format ? - pixelInfo.pGUIDPixFmt = ppguidTargetPF; - error_code = PixelFormatLookup(&pixelInfo, LOOKUP_FORWARD); - JXR_CHECK(error_code); - error_code = GetNativePixelFormat(&pixelInfo, guid_format, image_type, bpp, red_mask, green_mask, blue_mask); - if(error_code == WMP_errSuccess) { - break; - } - } - // try next conversion function - iIndex++; - } while(error_code != WMP_errIndexNotFound); - - } - - return (error_code == WMP_errSuccess) ? WMP_errSuccess : WMP_errUnsupportedFormat; - - } catch(...) { - return error_code; - } -} - -// -------------------------------------------------------------------------- - -/** -Scan input dib format and return the equivalent PKPixelFormatGUID format for saving -@param dib Image to be saved -@param guid_format (returned value) GUID format -@param bHasAlpha (returned value) TRUE if an alpha layer is present -@return Returns TRUE if successful, returns FALSE otherwise -*/ -static ERR -GetOutputPixelFormat(FIBITMAP *dib, PKPixelFormatGUID *guid_format, BOOL *bHasAlpha) { - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - const unsigned bpp = FreeImage_GetBPP(dib); - const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib); - - *guid_format = GUID_PKPixelFormatDontCare; - *bHasAlpha = FALSE; - - switch(image_type) { - case FIT_BITMAP: // standard image : 1-, 4-, 8-, 16-, 24-, 32-bit - switch(bpp) { - case 1: - // assume FIC_MINISBLACK - if(color_type == FIC_MINISBLACK) { - *guid_format = GUID_PKPixelFormatBlackWhite; - } - break; - case 8: - // assume FIC_MINISBLACK - if(color_type == FIC_MINISBLACK) { - *guid_format = GUID_PKPixelFormat8bppGray; - } - break; - case 16: - if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) { - *guid_format = GUID_PKPixelFormat16bppRGB565; - } else { - // includes case where all the masks are 0 - *guid_format = GUID_PKPixelFormat16bppRGB555; - } - break; -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - case 24: - *guid_format = GUID_PKPixelFormat24bppBGR; - break; - case 32: - *guid_format = GUID_PKPixelFormat32bppBGRA; - *bHasAlpha = TRUE; - break; -#elif FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - case 24: - *guid_format = GUID_PKPixelFormat24bppRGB; - break; - case 32: - *guid_format = GUID_PKPixelFormat32bppRGBA; - *bHasAlpha = TRUE; - break; -#endif - case 4: - default: - // not supported - break; - } - break; - case FIT_UINT16: // array of unsigned short : unsigned 16-bit - *guid_format = GUID_PKPixelFormat16bppGray; - break; - case FIT_FLOAT: // array of float : 32-bit IEEE floating point - *guid_format = GUID_PKPixelFormat32bppGrayFloat; - break; - case FIT_RGB16: // 48-bit RGB image : 3 x 16-bit - *guid_format = GUID_PKPixelFormat48bppRGB; - break; - case FIT_RGBA16: // 64-bit RGBA image : 4 x 16-bit - *guid_format = GUID_PKPixelFormat64bppRGBA; - *bHasAlpha = TRUE; - break; - case FIT_RGBF: // 96-bit RGB float image : 3 x 32-bit IEEE floating point - *guid_format = GUID_PKPixelFormat96bppRGBFloat; - break; - case FIT_RGBAF: // 128-bit RGBA float image : 4 x 32-bit IEEE floating point - *guid_format = GUID_PKPixelFormat128bppRGBAFloat; - *bHasAlpha = TRUE; - break; - - case FIT_INT16: // array of short : signed 16-bit - case FIT_UINT32: // array of unsigned long : unsigned 32-bit - case FIT_INT32: // array of long : signed 32-bit - case FIT_DOUBLE: // array of double : 64-bit IEEE floating point - case FIT_COMPLEX: // array of FICOMPLEX : 2 x 64-bit IEEE floating point - - default: - // unsupported format - break; - } - - return (*guid_format != GUID_PKPixelFormatDontCare) ? WMP_errSuccess : WMP_errUnsupportedFormat; -} - -// ========================================================== -// Metadata loading -// ========================================================== - -/** -Read a JPEG-XR IFD as a buffer -@see ReadMetadata -*/ -static ERR -ReadProfile(WMPStream* pStream, unsigned cbByteCount, unsigned uOffset, BYTE **ppbProfile) { - // (re-)allocate profile buffer - BYTE *pbProfile = *ppbProfile; - pbProfile = (BYTE*)realloc(pbProfile, cbByteCount); - if(!pbProfile) { - return WMP_errOutOfMemory; - } - // read the profile - if(WMP_errSuccess == pStream->SetPos(pStream, uOffset)) { - if(WMP_errSuccess == pStream->Read(pStream, pbProfile, cbByteCount)) { - *ppbProfile = pbProfile; - return WMP_errSuccess; - } - } - return WMP_errFileIO; -} - -/** -Convert a DPKPROPVARIANT to a FITAG, then store the tag as FIMD_EXIF_MAIN -@see ReadDescriptiveMetadata -*/ -static BOOL -ReadPropVariant(WORD tag_id, const DPKPROPVARIANT & varSrc, FIBITMAP *dib) { - DWORD dwSize; - - if(varSrc.vt == DPKVT_EMPTY) { - return FALSE; - } - - // get the tag key - TagLib& s = TagLib::instance(); - const char *key = s.getTagFieldName(TagLib::EXIF_MAIN, tag_id, NULL); - if(!key) { - return FALSE; - } - - // create a tag - FITAG *tag = FreeImage_CreateTag(); - if(tag) { - // set tag ID - FreeImage_SetTagID(tag, tag_id); - // set tag type, count, length and value - switch (varSrc.vt) { - case DPKVT_LPSTR: - FreeImage_SetTagType(tag, FIDT_ASCII); - dwSize = (DWORD)strlen(varSrc.VT.pszVal) + 1; - FreeImage_SetTagCount(tag, dwSize); - FreeImage_SetTagLength(tag, dwSize); - FreeImage_SetTagValue(tag, varSrc.VT.pszVal); - break; - - case DPKVT_LPWSTR: - FreeImage_SetTagType(tag, FIDT_UNDEFINED); - dwSize = (DWORD)(sizeof(U16) * (wcslen((wchar_t *) varSrc.VT.pwszVal) + 1)); // +1 for NULL term - FreeImage_SetTagCount(tag, dwSize); - FreeImage_SetTagLength(tag, dwSize); - FreeImage_SetTagValue(tag, varSrc.VT.pwszVal); - break; - - case DPKVT_UI2: - FreeImage_SetTagType(tag, FIDT_SHORT); - FreeImage_SetTagCount(tag, 1); - FreeImage_SetTagLength(tag, 2); - FreeImage_SetTagValue(tag, &varSrc.VT.uiVal); - break; - - case DPKVT_UI4: - FreeImage_SetTagType(tag, FIDT_LONG); - FreeImage_SetTagCount(tag, 1); - FreeImage_SetTagLength(tag, 4); - FreeImage_SetTagValue(tag, &varSrc.VT.ulVal); - break; - - default: - assert(FALSE); // This case is not handled - break; - } - // get the tag desctiption - const char *description = s.getTagDescription(TagLib::EXIF_MAIN, tag_id); - FreeImage_SetTagDescription(tag, description); - - // store the tag - FreeImage_SetMetadata(FIMD_EXIF_MAIN, dib, key, tag); - - FreeImage_DeleteTag(tag); - } - return TRUE; -} - -/** -Read JPEG-XR descriptive metadata and store as EXIF_MAIN metadata -@see ReadPropVariant -*/ -static ERR -ReadDescriptiveMetadata(PKImageDecode *pID, FIBITMAP *dib) { - // get Exif TIFF metadata - const DESCRIPTIVEMETADATA *pDescMetadata = &pID->WMP.sDescMetadata; - // convert metadata to FITAG and store into the EXIF_MAIN metadata model - ReadPropVariant(WMP_tagImageDescription, pDescMetadata->pvarImageDescription, dib); - ReadPropVariant(WMP_tagCameraMake, pDescMetadata->pvarCameraMake, dib); - ReadPropVariant(WMP_tagCameraModel, pDescMetadata->pvarCameraModel, dib); - ReadPropVariant(WMP_tagSoftware, pDescMetadata->pvarSoftware, dib); - ReadPropVariant(WMP_tagDateTime, pDescMetadata->pvarDateTime, dib); - ReadPropVariant(WMP_tagArtist, pDescMetadata->pvarArtist, dib); - ReadPropVariant(WMP_tagCopyright, pDescMetadata->pvarCopyright, dib); - ReadPropVariant(WMP_tagRatingStars, pDescMetadata->pvarRatingStars, dib); - ReadPropVariant(WMP_tagRatingValue, pDescMetadata->pvarRatingValue, dib); - ReadPropVariant(WMP_tagCaption, pDescMetadata->pvarCaption, dib); - ReadPropVariant(WMP_tagDocumentName, pDescMetadata->pvarDocumentName, dib); - ReadPropVariant(WMP_tagPageName, pDescMetadata->pvarPageName, dib); - ReadPropVariant(WMP_tagPageNumber, pDescMetadata->pvarPageNumber, dib); - ReadPropVariant(WMP_tagHostComputer, pDescMetadata->pvarHostComputer, dib); - return WMP_errSuccess; -} - -/** -Read ICC, XMP, Exif, Exif-GPS, IPTC, descriptive (i.e. Exif-TIFF) metadata -@see ReadProfile, ReadDescriptiveMetadata -*/ -static ERR -ReadMetadata(PKImageDecode *pID, FIBITMAP *dib) { - ERR error_code = 0; // error code as returned by the interface - size_t currentPos = 0; // current stream position - - WMPStream *pStream = pID->pStream; - WmpDEMisc *wmiDEMisc = &pID->WMP.wmiDEMisc; - BYTE *pbProfile = NULL; - - try { - // save current position - error_code = pStream->GetPos(pStream, ¤tPos); - JXR_CHECK(error_code); - - // ICC profile - if(0 != wmiDEMisc->uColorProfileByteCount) { - unsigned cbByteCount = wmiDEMisc->uColorProfileByteCount; - unsigned uOffset = wmiDEMisc->uColorProfileOffset; - error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile); - JXR_CHECK(error_code); - FreeImage_CreateICCProfile(dib, pbProfile, cbByteCount); - } - - // XMP metadata - if(0 != wmiDEMisc->uXMPMetadataByteCount) { - unsigned cbByteCount = wmiDEMisc->uXMPMetadataByteCount; - unsigned uOffset = wmiDEMisc->uXMPMetadataOffset; - error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile); - JXR_CHECK(error_code); - // store the tag as XMP - FITAG *tag = FreeImage_CreateTag(); - if(tag) { - FreeImage_SetTagLength(tag, cbByteCount); - FreeImage_SetTagCount(tag, cbByteCount); - FreeImage_SetTagType(tag, FIDT_ASCII); - FreeImage_SetTagValue(tag, pbProfile); - FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName); - FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag); - FreeImage_DeleteTag(tag); - } - } - - // IPTC metadata - if(0 != wmiDEMisc->uIPTCNAAMetadataByteCount) { - unsigned cbByteCount = wmiDEMisc->uIPTCNAAMetadataByteCount; - unsigned uOffset = wmiDEMisc->uIPTCNAAMetadataOffset; - error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile); - JXR_CHECK(error_code); - // decode the IPTC profile - read_iptc_profile(dib, pbProfile, cbByteCount); - } - - // Exif metadata - if(0 != wmiDEMisc->uEXIFMetadataByteCount) { - unsigned cbByteCount = wmiDEMisc->uEXIFMetadataByteCount; - unsigned uOffset = wmiDEMisc->uEXIFMetadataOffset; - error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile); - JXR_CHECK(error_code); - // decode the Exif profile - jpegxr_read_exif_profile(dib, pbProfile, cbByteCount, uOffset); - } - - // Exif-GPS metadata - if(0 != wmiDEMisc->uGPSInfoMetadataByteCount) { - unsigned cbByteCount = wmiDEMisc->uGPSInfoMetadataByteCount; - unsigned uOffset = wmiDEMisc->uGPSInfoMetadataOffset; - error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile); - JXR_CHECK(error_code); - // decode the Exif-GPS profile - jpegxr_read_exif_gps_profile(dib, pbProfile, cbByteCount, uOffset); - } - - // free profile buffer - free(pbProfile); - // restore initial position - error_code = pID->pStream->SetPos(pID->pStream, currentPos); - JXR_CHECK(error_code); - - // as a LAST STEP, read descriptive metadata - // these metadata overwrite possible identical Exif-TIFF metadata - // that could have been read inside the Exif IFD - - return ReadDescriptiveMetadata(pID, dib); - - } catch(...) { - // free profile buffer - free(pbProfile); - if(currentPos) { - // restore initial position - pStream->SetPos(pStream, currentPos); - } - return error_code; - } -} - -// ========================================================== -// Metadata saving -// ========================================================== - -/** -Convert a FITAG (coming from FIMD_EXIF_MAIN) to a DPKPROPVARIANT. -No allocation is needed here, the function just copy pointers when needed. -@see WriteDescriptiveMetadata -*/ -static BOOL -WritePropVariant(FIBITMAP *dib, WORD tag_id, DPKPROPVARIANT & varDst) { - FITAG *tag = NULL; - - TagLib& s = TagLib::instance(); - - // clear output DPKPROPVARIANT - varDst.vt = DPKVT_EMPTY; - - // given the tag id, get the tag key - const char *key = s.getTagFieldName(TagLib::EXIF_MAIN, tag_id, NULL); - // then, get the tag info - if(!FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, key, &tag)) { - return FALSE; - } - - // set the tag value - switch(FreeImage_GetTagType(tag)) { - case FIDT_ASCII: - varDst.vt = DPKVT_LPSTR; - varDst.VT.pszVal = (char*)FreeImage_GetTagValue(tag); - break; - case FIDT_BYTE: - case FIDT_UNDEFINED: - varDst.vt = DPKVT_LPWSTR; - varDst.VT.pwszVal = (U16*)FreeImage_GetTagValue(tag); - break; - case FIDT_SHORT: - varDst.vt = DPKVT_UI2; - varDst.VT.uiVal = *((U16*)FreeImage_GetTagValue(tag)); - break; - case FIDT_LONG: - varDst.vt = DPKVT_UI4; - varDst.VT.ulVal = *((U32*)FreeImage_GetTagValue(tag)); - break; - default: - break; - } - - return TRUE; -} - -/** -Write EXIF_MAIN metadata to JPEG-XR descriptive metadata -@see WritePropVariant -*/ -static ERR -WriteDescriptiveMetadata(PKImageEncode *pIE, FIBITMAP *dib) { - ERR error_code = 0; // error code as returned by the interface - DESCRIPTIVEMETADATA DescMetadata; - - // fill the DESCRIPTIVEMETADATA structure (use pointers to arrays when needed) - WritePropVariant(dib, WMP_tagImageDescription, DescMetadata.pvarImageDescription); - WritePropVariant(dib, WMP_tagCameraMake, DescMetadata.pvarCameraMake); - WritePropVariant(dib, WMP_tagCameraModel, DescMetadata.pvarCameraModel); - WritePropVariant(dib, WMP_tagSoftware, DescMetadata.pvarSoftware); - WritePropVariant(dib, WMP_tagDateTime, DescMetadata.pvarDateTime); - WritePropVariant(dib, WMP_tagArtist, DescMetadata.pvarArtist); - WritePropVariant(dib, WMP_tagCopyright, DescMetadata.pvarCopyright); - WritePropVariant(dib, WMP_tagRatingStars, DescMetadata.pvarRatingStars); - WritePropVariant(dib, WMP_tagRatingValue, DescMetadata.pvarRatingValue); - WritePropVariant(dib, WMP_tagCaption, DescMetadata.pvarCaption); - WritePropVariant(dib, WMP_tagDocumentName, DescMetadata.pvarDocumentName); - WritePropVariant(dib, WMP_tagPageName, DescMetadata.pvarPageName); - WritePropVariant(dib, WMP_tagPageNumber, DescMetadata.pvarPageNumber); - WritePropVariant(dib, WMP_tagHostComputer, DescMetadata.pvarHostComputer); - - // copy the structure to the encoder - error_code = pIE->SetDescriptiveMetadata(pIE, &DescMetadata); - - // no need to free anything here - return error_code; -} - -/** -Write ICC, XMP, Exif, Exif-GPS, IPTC, descriptive (i.e. Exif-TIFF) metadata -*/ -static ERR -WriteMetadata(PKImageEncode *pIE, FIBITMAP *dib) { - ERR error_code = 0; // error code as returned by the interface - BYTE *profile = NULL; - unsigned profile_size = 0; - - try { - // write ICC profile - { - FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib); - if(iccProfile->data) { - error_code = pIE->SetColorContext(pIE, (U8*)iccProfile->data, iccProfile->size); - JXR_CHECK(error_code); - } - } - - // write descriptive metadata - if(FreeImage_GetMetadataCount(FIMD_EXIF_MAIN, dib)) { - error_code = WriteDescriptiveMetadata(pIE, dib); - JXR_CHECK(error_code); - } - - // write IPTC metadata - if(FreeImage_GetMetadataCount(FIMD_IPTC, dib)) { - // create a binary profile - if(write_iptc_profile(dib, &profile, &profile_size)) { - // write the profile - error_code = PKImageEncode_SetIPTCNAAMetadata_WMP(pIE, profile, profile_size); - JXR_CHECK(error_code); - // release profile - free(profile); - profile = NULL; - } - } - - // write XMP metadata - { - FITAG *tag_xmp = NULL; - if(FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag_xmp)) { - error_code = PKImageEncode_SetXMPMetadata_WMP(pIE, (BYTE*)FreeImage_GetTagValue(tag_xmp), FreeImage_GetTagLength(tag_xmp)); - JXR_CHECK(error_code); - } - } - - // write Exif metadata - { - if(tiff_get_ifd_profile(dib, FIMD_EXIF_EXIF, &profile, &profile_size)) { - error_code = PKImageEncode_SetEXIFMetadata_WMP(pIE, profile, profile_size); - JXR_CHECK(error_code); - // release profile - free(profile); - profile = NULL; - } - } - - // write Exif GPS metadata - { - if(tiff_get_ifd_profile(dib, FIMD_EXIF_GPS, &profile, &profile_size)) { - error_code = PKImageEncode_SetGPSInfoMetadata_WMP(pIE, profile, profile_size); - JXR_CHECK(error_code); - // release profile - free(profile); - profile = NULL; - } - } - - return WMP_errSuccess; - - } catch(...) { - free(profile); - return error_code; - } -} - - - -// ========================================================== -// Quantization tables (Y, U, V, YHP, UHP, VHP), -// optimized for PSNR -// ========================================================== - -static const int DPK_QPS_420[11][6] = { // for 8 bit only - { 66, 65, 70, 72, 72, 77 }, - { 59, 58, 63, 64, 63, 68 }, - { 52, 51, 57, 56, 56, 61 }, - { 48, 48, 54, 51, 50, 55 }, - { 43, 44, 48, 46, 46, 49 }, - { 37, 37, 42, 38, 38, 43 }, - { 26, 28, 31, 27, 28, 31 }, - { 16, 17, 22, 16, 17, 21 }, - { 10, 11, 13, 10, 10, 13 }, - { 5, 5, 6, 5, 5, 6 }, - { 2, 2, 3, 2, 2, 2 } -}; - -static const int DPK_QPS_8[12][6] = { - { 67, 79, 86, 72, 90, 98 }, - { 59, 74, 80, 64, 83, 89 }, - { 53, 68, 75, 57, 76, 83 }, - { 49, 64, 71, 53, 70, 77 }, - { 45, 60, 67, 48, 67, 74 }, - { 40, 56, 62, 42, 59, 66 }, - { 33, 49, 55, 35, 51, 58 }, - { 27, 44, 49, 28, 45, 50 }, - { 20, 36, 42, 20, 38, 44 }, - { 13, 27, 34, 13, 28, 34 }, - { 7, 17, 21, 8, 17, 21 }, // Photoshop 100% - { 2, 5, 6, 2, 5, 6 } -}; - -static const int DPK_QPS_16[11][6] = { - { 197, 203, 210, 202, 207, 213 }, - { 174, 188, 193, 180, 189, 196 }, - { 152, 167, 173, 156, 169, 174 }, - { 135, 152, 157, 137, 153, 158 }, - { 119, 137, 141, 119, 138, 142 }, - { 102, 120, 125, 100, 120, 124 }, - { 82, 98, 104, 79, 98, 103 }, - { 60, 76, 81, 58, 76, 81 }, - { 39, 52, 58, 36, 52, 58 }, - { 16, 27, 33, 14, 27, 33 }, - { 5, 8, 9, 4, 7, 8 } -}; - -static const int DPK_QPS_16f[11][6] = { - { 148, 177, 171, 165, 187, 191 }, - { 133, 155, 153, 147, 172, 181 }, - { 114, 133, 138, 130, 157, 167 }, - { 97, 118, 120, 109, 137, 144 }, - { 76, 98, 103, 85, 115, 121 }, - { 63, 86, 91, 62, 96, 99 }, - { 46, 68, 71, 43, 73, 75 }, - { 29, 48, 52, 27, 48, 51 }, - { 16, 30, 35, 14, 29, 34 }, - { 8, 14, 17, 7, 13, 17 }, - { 3, 5, 7, 3, 5, 6 } -}; - -static const int DPK_QPS_32f[11][6] = { - { 194, 206, 209, 204, 211, 217 }, - { 175, 187, 196, 186, 193, 205 }, - { 157, 170, 177, 167, 180, 190 }, - { 133, 152, 156, 144, 163, 168 }, - { 116, 138, 142, 117, 143, 148 }, - { 98, 120, 123, 96, 123, 126 }, - { 80, 99, 102, 78, 99, 102 }, - { 65, 79, 84, 63, 79, 84 }, - { 48, 61, 67, 45, 60, 66 }, - { 27, 41, 46, 24, 40, 45 }, - { 3, 22, 24, 2, 21, 22 } -}; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "JPEG-XR"; -} - -static const char * DLL_CALLCONV -Description() { - return "JPEG XR image format"; -} - -static const char * DLL_CALLCONV -Extension() { - return "jxr,wdp,hdp"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/vnd.ms-photo"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE jxr_signature[3] = { 0x49, 0x49, 0xBC }; - BYTE signature[3] = { 0, 0, 0 }; - - io->read_proc(&signature, 1, 3, handle); - - return (memcmp(jxr_signature, signature, 3) == 0); -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return ( - (depth == 1) || - (depth == 8) || - (depth == 16) || - (depth == 24) || - (depth == 32) - ); -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return ( - (type == FIT_BITMAP) || - (type == FIT_UINT16) || - (type == FIT_RGB16) || - (type == FIT_RGBA16) || - (type == FIT_FLOAT) || - (type == FIT_RGBF) || - (type == FIT_RGBAF) - ); -} - -static BOOL DLL_CALLCONV -SupportsICCProfiles() { - return TRUE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ========================================================== -// Open & Close -// ========================================================== - -static void * DLL_CALLCONV -Open(FreeImageIO *io, fi_handle handle, BOOL read) { - WMPStream *pStream = NULL; // stream interface - if(io && handle) { - // allocate the FreeImageIO stream wrapper - FreeImageJXRIO *jxr_io = (FreeImageJXRIO*)malloc(sizeof(FreeImageJXRIO)); - if(jxr_io) { - jxr_io->io = io; - jxr_io->handle = handle; - // create a JXR stream wrapper - if(_jxr_io_Create(&pStream, jxr_io) != WMP_errSuccess) { - free(jxr_io); - return NULL; - } - } - } - return pStream; -} - -static void DLL_CALLCONV -Close(FreeImageIO *io, fi_handle handle, void *data) { - WMPStream *pStream = (WMPStream*)data; - if(pStream) { - // free the FreeImageIO stream wrapper - FreeImageJXRIO *jxr_io = (FreeImageJXRIO*)pStream->state.pvObj; - free(jxr_io); - // free the JXR stream wrapper - pStream->fMem = TRUE; - _jxr_io_Close(&pStream); - } -} - -// ========================================================== -// Load -// ========================================================== - -/** -Set decoder parameters -@param pDecoder Decoder handle -@param flags FreeImage load flags -*/ -static void -SetDecoderParameters(PKImageDecode *pDecoder, int flags) { - // load image & alpha for formats with alpha - pDecoder->WMP.wmiSCP.uAlphaMode = 2; - // more options to come ... -} - -/** -Copy or convert & copy decoded pixels into the dib -@param pDecoder Decoder handle -@param out_guid_format Target guid format -@param dib Output dib -@param width Image width -@param height Image height -@return Returns 0 if successful, returns ERR otherwise -*/ -static ERR -CopyPixels(PKImageDecode *pDecoder, PKPixelFormatGUID out_guid_format, FIBITMAP *dib, int width, int height) { - PKFormatConverter *pConverter = NULL; // pixel format converter - ERR error_code = 0; // error code as returned by the interface - BYTE *pb = NULL; // local buffer used for pixel format conversion - - // image dimensions - const PKRect rect = {0, 0, width, height}; - - try { - // get input file pixel format ... - PKPixelFormatGUID in_guid_format; - error_code = pDecoder->GetPixelFormat(pDecoder, &in_guid_format); - JXR_CHECK(error_code); - - // is a format conversion needed ? - - if(IsEqualGUID(out_guid_format, in_guid_format)) { - // no conversion, load bytes "as is" ... - - // get a pointer to dst pixel data - BYTE *dib_bits = FreeImage_GetBits(dib); - - // get dst pitch (count of BYTE for stride) - const unsigned cbStride = FreeImage_GetPitch(dib); - - // decode and copy bits to dst array - error_code = pDecoder->Copy(pDecoder, &rect, dib_bits, cbStride); - JXR_CHECK(error_code); - } - else { - // we need to use the conversion API ... - - // allocate the pixel format converter - error_code = PKCodecFactory_CreateFormatConverter(&pConverter); - JXR_CHECK(error_code); - - // set the conversion function - error_code = pConverter->Initialize(pConverter, pDecoder, NULL, out_guid_format); - JXR_CHECK(error_code); - - // get the maximum stride - unsigned cbStride = 0; - { - PKPixelInfo pPIFrom; - PKPixelInfo pPITo; - - pPIFrom.pGUIDPixFmt = &in_guid_format; - error_code = PixelFormatLookup(&pPIFrom, LOOKUP_FORWARD); - JXR_CHECK(error_code); - - pPITo.pGUIDPixFmt = &out_guid_format; - error_code = PixelFormatLookup(&pPITo, LOOKUP_FORWARD); - JXR_CHECK(error_code); - - unsigned cbStrideFrom = ((pPIFrom.cbitUnit + 7) >> 3) * width; - unsigned cbStrideTo = ((pPITo.cbitUnit + 7) >> 3) * width; - cbStride = MAX(cbStrideFrom, cbStrideTo); - } - - // allocate a local decoder / encoder buffer - error_code = PKAllocAligned((void **) &pb, cbStride * height, 128); - JXR_CHECK(error_code); - - // copy / convert pixels - error_code = pConverter->Copy(pConverter, &rect, pb, cbStride); - JXR_CHECK(error_code); - - // now copy pixels into the dib - const size_t line_size = FreeImage_GetLine(dib); - for(int y = 0; y < height; y++) { - BYTE *src_bits = (BYTE*)(pb + y * cbStride); - BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, y); - memcpy(dst_bits, src_bits, line_size); - } - - // free the local buffer - PKFreeAligned((void **) &pb); - - // free the pixel format converter - PKFormatConverter_Release(&pConverter); - } - - // FreeImage DIB are upside-down relative to usual graphic conventions - FreeImage_FlipVertical(dib); - - // post-processing ... - // ------------------- - - // swap RGB as needed - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - if(IsEqualGUID(out_guid_format, GUID_PKPixelFormat24bppRGB) || IsEqualGUID(out_guid_format, GUID_PKPixelFormat32bppRGB)) { - SwapRedBlue32(dib); - } -#elif FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - if(IsEqualGUID(out_guid_format, GUID_PKPixelFormat24bppBGR) || IsEqualGUID(out_guid_format, GUID_PKPixelFormat32bppBGR)) { - SwapRedBlue32(dib); - } -#endif - - return WMP_errSuccess; - - } catch(...) { - // free the local buffer - PKFreeAligned((void **) &pb); - // free the pixel format converter - PKFormatConverter_Release(&pConverter); - - return error_code; - } -} - -// -------------------------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - PKImageDecode *pDecoder = NULL; // decoder interface - ERR error_code = 0; // error code as returned by the interface - PKPixelFormatGUID guid_format; // loaded pixel format (== input file pixel format if no conversion needed) - - FREE_IMAGE_TYPE image_type = FIT_UNKNOWN; // input image type - unsigned bpp = 0; // input image bit depth - FIBITMAP *dib = NULL; - - // get the I/O stream wrapper - WMPStream *pDecodeStream = (WMPStream*)data; - - if(!handle || !pDecodeStream) { - return NULL; - } - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - try { - int width, height; // image dimensions (in pixels) - - // create a JXR decoder interface and initialize function pointers with *_WMP functions - error_code = PKImageDecode_Create_WMP(&pDecoder); - JXR_CHECK(error_code); - - // attach the stream to the decoder ... - // ... then read the image container and the metadata - error_code = pDecoder->Initialize(pDecoder, pDecodeStream); - JXR_CHECK(error_code); - - // set decoder parameters - SetDecoderParameters(pDecoder, flags); - - // get dst image format specifications - unsigned red_mask = 0, green_mask = 0, blue_mask = 0; - error_code = GetInputPixelFormat(pDecoder, &guid_format, &image_type, &bpp, &red_mask, &green_mask, &blue_mask); - JXR_CHECK(error_code); - - // get image dimensions - pDecoder->GetSize(pDecoder, &width, &height); - - // allocate dst image - { - dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, bpp, red_mask, green_mask, blue_mask); - if(!dib) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - if(FreeImage_GetBPP(dib) == 1) { - // BD_1 - build a FIC_MINISBLACK palette - RGBQUAD *pal = FreeImage_GetPalette(dib); - pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0; - pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; - } - } - - // get image resolution - { - float resX, resY; // image resolution (in dots per inch) - // convert from English units, i.e. dots per inch to universal units, i.e. dots per meter - pDecoder->GetResolution(pDecoder, &resX, &resY); - FreeImage_SetDotsPerMeterX(dib, (unsigned)(resX / 0.0254F + 0.5F)); - FreeImage_SetDotsPerMeterY(dib, (unsigned)(resY / 0.0254F + 0.5F)); - } - - // get metadata & ICC profile - error_code = ReadMetadata(pDecoder, dib); - JXR_CHECK(error_code); - - if(header_only) { - // header only mode ... - - // free the decoder - pDecoder->Release(&pDecoder); - assert(pDecoder == NULL); - - return dib; - } - - // copy pixels into the dib, perform pixel conversion if needed - error_code = CopyPixels(pDecoder, guid_format, dib, width, height); - JXR_CHECK(error_code); - - // free the decoder - pDecoder->Release(&pDecoder); - assert(pDecoder == NULL); - - return dib; - - } catch (const char *message) { - // unload the dib - FreeImage_Unload(dib); - // free the decoder - pDecoder->Release(&pDecoder); - - if(NULL != message) { - FreeImage_OutputMessageProc(s_format_id, message); - } - } - - return NULL; -} - -// ========================================================== -// Save -// ========================================================== - -/** -Configure compression parameters - -ImageQuality Q (BD==1) Q (BD==8) Q (BD==16) Q (BD==32F) Subsample Overlap -[0.0, 0.4] 8-IQ*5 (see table) (see table) (see table) 4:4:4 2 -(0.4, 0.8) 8-IQ*5 (see table) (see table) (see table) 4:4:4 1 -[0.8, 1.0) 8-IQ*5 (see table) (see table) (see table) 4:4:4 1 -[1.0, 1.0] 1 1 1 1 4:4:4 0 - -@param wmiSCP Encoder parameters -@param pixelInfo Image specifications -@param fltImageQuality Image output quality in [0..1), 1 means lossless -*/ -static void -SetCompression(CWMIStrCodecParam *wmiSCP, const PKPixelInfo *pixelInfo, float fltImageQuality) { - if(fltImageQuality < 1.0F) { - // overlap - if(fltImageQuality >= 0.5F) { - wmiSCP->olOverlap = OL_ONE; - } else { - wmiSCP->olOverlap = OL_TWO; - } - // chroma sub-sampling - if(fltImageQuality >= 0.5F || pixelInfo->uBitsPerSample > 8) { - wmiSCP->cfColorFormat = YUV_444; - } else { - wmiSCP->cfColorFormat = YUV_420; - } - - // bit depth - if(pixelInfo->bdBitDepth == BD_1) { - wmiSCP->uiDefaultQPIndex = (U8)(8 - 5.0F * fltImageQuality + 0.5F); - } - else { - // remap [0.8, 0.866, 0.933, 1.0] to [0.8, 0.9, 1.0, 1.1] - // to use 8-bit DPK QP table (0.933 == Photoshop JPEG 100) - if(fltImageQuality > 0.8F && pixelInfo->bdBitDepth == BD_8 && wmiSCP->cfColorFormat != YUV_420 && wmiSCP->cfColorFormat != YUV_422) { - fltImageQuality = 0.8F + (fltImageQuality - 0.8F) * 1.5F; - } - - const int qi = (int) (10.0F * fltImageQuality); - const float qf = 10.0F * fltImageQuality - (float)qi; - - const int *pQPs = - (wmiSCP->cfColorFormat == YUV_420 || wmiSCP->cfColorFormat == YUV_422) ? - DPK_QPS_420[qi] : - (pixelInfo->bdBitDepth == BD_8 ? DPK_QPS_8[qi] : - (pixelInfo->bdBitDepth == BD_16 ? DPK_QPS_16[qi] : - (pixelInfo->bdBitDepth == BD_16F ? DPK_QPS_16f[qi] : - DPK_QPS_32f[qi]))); - - wmiSCP->uiDefaultQPIndex = (U8) (0.5F + (float) pQPs[0] * (1.0F - qf) + (float) (pQPs + 6)[0] * qf); - wmiSCP->uiDefaultQPIndexU = (U8) (0.5F + (float) pQPs[1] * (1.0F - qf) + (float) (pQPs + 6)[1] * qf); - wmiSCP->uiDefaultQPIndexV = (U8) (0.5F + (float) pQPs[2] * (1.0F - qf) + (float) (pQPs + 6)[2] * qf); - wmiSCP->uiDefaultQPIndexYHP = (U8) (0.5F + (float) pQPs[3] * (1.0F - qf) + (float) (pQPs + 6)[3] * qf); - wmiSCP->uiDefaultQPIndexUHP = (U8) (0.5F + (float) pQPs[4] * (1.0F - qf) + (float) (pQPs + 6)[4] * qf); - wmiSCP->uiDefaultQPIndexVHP = (U8) (0.5F + (float) pQPs[5] * (1.0F - qf) + (float) (pQPs + 6)[5] * qf); - } - } // fltImageQuality < 1.0F - else { - // lossless mode - wmiSCP->uiDefaultQPIndex = 1; - } -} - -/** -Set encoder parameters -@param wmiSCP Encoder parameters -@param pixelInfo Image specifications -@param flags FreeImage save flags -@param bHasAlpha TRUE if an alpha layer is present -*/ -static void -SetEncoderParameters(CWMIStrCodecParam *wmiSCP, const PKPixelInfo *pixelInfo, int flags, BOOL bHasAlpha) { - float fltImageQuality = 1.0F; - - // all values have been set to zero by the API - // update default values for some attributes - wmiSCP->cfColorFormat = YUV_444; // color format - wmiSCP->bdBitDepth = BD_LONG; // internal bit depth - wmiSCP->bfBitstreamFormat = SPATIAL; // compressed image data in spatial order - wmiSCP->bProgressiveMode = FALSE; // sequential mode - wmiSCP->olOverlap = OL_ONE; // single level overlap processing - wmiSCP->cNumOfSliceMinus1H = 0; // # of horizontal slices - wmiSCP->cNumOfSliceMinus1V = 0; // # of vertical slices - wmiSCP->sbSubband = SB_ALL; // keep all subbands - wmiSCP->uAlphaMode = 0; // 0:no alpha 1: alpha only else: something + alpha - wmiSCP->uiDefaultQPIndex = 1; // quantization for grey or rgb layer(s), 1: lossless - wmiSCP->uiDefaultQPIndexAlpha = 1; // quantization for alpha layer, 1: lossless - - // process the flags - // ----------------- - - // progressive mode - if((flags & JXR_PROGRESSIVE) == JXR_PROGRESSIVE) { - // turn on progressive mode (instead of sequential mode) - wmiSCP->bProgressiveMode = TRUE; - } - - // quality in [0.01 - 1.0), 1.0 means lossless - default is 0.80 - int quality = flags & 0x7F; - if(quality == 0) { - // defaut to 0.80 - fltImageQuality = 0.8F; - } else if((flags & JXR_LOSSLESS) == JXR_LOSSLESS) { - fltImageQuality = 1.0F; - } else { - quality = (quality >= 100) ? 100 : quality; - fltImageQuality = quality / 100.0F; - } - SetCompression(wmiSCP, pixelInfo, fltImageQuality); - - // alpha compression - if(bHasAlpha) { - wmiSCP->uAlphaMode = 2; // encode with a planar alpha channel - } -} - -// -------------------------------------------------------------------------- - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - BOOL bIsFlipped = FALSE; // FreeImage DIB are upside-down relative to usual graphic conventions - PKPixelFormatGUID guid_format; // image format - PKPixelInfo pixelInfo; // image specifications - BOOL bHasAlpha = FALSE; // is alpha layer present ? - - PKImageEncode *pEncoder = NULL; // encoder interface - ERR error_code = 0; // error code as returned by the interface - - // get the I/O stream wrapper - WMPStream *pEncodeStream = (WMPStream*)data; - - if(!dib || !handle || !pEncodeStream) { - return FALSE; - } - - try { - // get image dimensions - unsigned width = FreeImage_GetWidth(dib); - unsigned height = FreeImage_GetHeight(dib); - - // check JPEG-XR limits - if((width < MB_WIDTH_PIXEL) || (height < MB_HEIGHT_PIXEL)) { - FreeImage_OutputMessageProc(s_format_id, "Unsupported image size: width x height = %d x %d", width, height); - throw (const char*)NULL; - } - - // get output pixel format - error_code = GetOutputPixelFormat(dib, &guid_format, &bHasAlpha); - JXR_CHECK(error_code); - pixelInfo.pGUIDPixFmt = &guid_format; - error_code = PixelFormatLookup(&pixelInfo, LOOKUP_FORWARD); - JXR_CHECK(error_code); - - // create a JXR encoder interface and initialize function pointers with *_WMP functions - error_code = PKImageEncode_Create_WMP(&pEncoder); - JXR_CHECK(error_code); - - // attach the stream to the encoder and set all encoder parameters to zero ... - error_code = pEncoder->Initialize(pEncoder, pEncodeStream, &pEncoder->WMP.wmiSCP, sizeof(CWMIStrCodecParam)); - JXR_CHECK(error_code); - - // ... then configure the encoder - SetEncoderParameters(&pEncoder->WMP.wmiSCP, &pixelInfo, flags, bHasAlpha); - - // set pixel format - pEncoder->SetPixelFormat(pEncoder, guid_format); - - // set image size - pEncoder->SetSize(pEncoder, width, height); - - // set resolution (convert from universal units to English units) - float resX = (float)(unsigned)(0.5F + 0.0254F * FreeImage_GetDotsPerMeterX(dib)); - float resY = (float)(unsigned)(0.5F + 0.0254F * FreeImage_GetDotsPerMeterY(dib)); - pEncoder->SetResolution(pEncoder, resX, resY); - - // set metadata - WriteMetadata(pEncoder, dib); - - // write metadata & pixels - // ----------------------- - - // dib coordinates are upside-down relative to usual conventions - bIsFlipped = FreeImage_FlipVertical(dib); - - // get a pointer to dst pixel data - BYTE *dib_bits = FreeImage_GetBits(dib); - - // get dst pitch (count of BYTE for stride) - const unsigned cbStride = FreeImage_GetPitch(dib); - - // write metadata + pixels on output - error_code = pEncoder->WritePixels(pEncoder, height, dib_bits, cbStride); - JXR_CHECK(error_code); - - // recover dib coordinates - FreeImage_FlipVertical(dib); - - // free the encoder - pEncoder->Release(&pEncoder); - assert(pEncoder == NULL); - - return TRUE; - - } catch (const char *message) { - if(bIsFlipped) { - // recover dib coordinates - FreeImage_FlipVertical(dib); - } - if(pEncoder) { - // free the encoder - pEncoder->Release(&pEncoder); - assert(pEncoder == NULL); - } - if(NULL != message) { - FreeImage_OutputMessageProc(s_format_id, message); - } - } - - return FALSE; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitJXR(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = Open; - plugin->close_proc = Close; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = SupportsICCProfiles; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} - diff --git a/plugins/AdvaImg/src/FreeImage/PluginKOALA.cpp b/plugins/AdvaImg/src/FreeImage/PluginKOALA.cpp deleted file mode 100644 index 6c3ae52254..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginKOALA.cpp +++ /dev/null @@ -1,243 +0,0 @@ -// ========================================================== -// KOALA Loader -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// -// 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" - -// ---------------------------------------------------------- -// Constants + headers -// ---------------------------------------------------------- - -#ifdef _WIN32 -#pragma pack(push, 1) -#else -#pragma pack(1) -#endif - -typedef struct tagKOALA { - BYTE image[8000]; // pixmap image - BYTE colour1[1000]; // first colourmap (colour 1 and 2) - BYTE colour2[1000]; // second colourmap (colour 3) - BYTE background; // background colour -} koala_t; - -struct colour_t { - int r; - int g; - int b; -}; - -#ifdef _WIN32 -#pragma pack(pop) -#else -#pragma pack() -#endif - -// ---------------------------------------------------------- - -#define CBM_WIDTH 320 -#define CBM_HEIGHT 200 - -// ---------------------------------------------------------- - -const colour_t c64colours[16] = { - { 0, 0, 0 }, // Black - { 255, 255, 255 }, // White - { 170, 17, 17 }, // Red - { 12, 204, 204 }, // Cyan - { 221, 51, 221 }, // Purple - { 0, 187, 0 }, // Green - { 0, 0, 204 }, // Blue - { 255, 255, 140 }, // Yellow - { 204, 119, 34 }, // Orange - { 136, 68, 0 }, // Brown - { 255, 153, 136 }, // Light red - { 92, 92, 92 }, // Gray 1 - { 170, 170, 170 }, // Gray 2 - { 140, 255, 178 }, // Light green - { 39, 148, 255 }, // Light blue - { 196, 196, 196 } // Gray 3 -}; - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -const char * DLL_CALLCONV -Format() { - return "KOALA"; -} - -const char * DLL_CALLCONV -Description() { - return "C64 Koala Graphics"; -} - -const char * DLL_CALLCONV -Extension() { - return "koa"; -} - -const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-koala"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE koala_signature[] = { 0x00, 0x60 }; - BYTE signature[2] = { 0, 0 }; - - io->read_proc(signature, 1, sizeof(koala_signature), handle); - - return (memcmp(koala_signature, signature, sizeof(koala_signature)) == 0); -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return FALSE; -} - -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - if (handle) { - koala_t image; - - // read the load address - - unsigned char load_address[2]; // highbit, lowbit - - io->read_proc(&load_address, 1, 2, handle); - - // if the load address is correct, skip it. otherwise ignore the load address - - if ((load_address[0] != 0x00) || (load_address[1] != 0x60)) { - ((BYTE *)&image)[0] = load_address[0]; - ((BYTE *)&image)[1] = load_address[1]; - - io->read_proc((BYTE *)&image + 2, 1, 10001 - 2, handle); - } else { - io->read_proc(&image, 1, 10001, handle); - } - - // build DIB in memory - - FIBITMAP *dib = FreeImage_Allocate(CBM_WIDTH, CBM_HEIGHT, 4); - - if (dib) { - // write out the commodore 64 color palette - - RGBQUAD *palette = FreeImage_GetPalette(dib); - - for (int i = 0; i < 16; i++) { - palette[i].rgbBlue = (BYTE)c64colours[i].b; - palette[i].rgbGreen = (BYTE)c64colours[i].g; - palette[i].rgbRed = (BYTE)c64colours[i].r; - } - - // write out bitmap data - - BYTE pixel_mask[4] = { 0xc0, 0x30, 0x0c, 0x03 }; - BYTE pixel_displacement[4] = { 6, 4, 2, 0 }; - int pixel, index, colourindex; - unsigned char found_color = 0; - - for (int y = 0; y < 200; y++) { - for (int x = 0; x < 160; x++) { - // Get value of pixel at (x,y) - - index = (x / 4) * 8 + (y % 8) + (y / 8) * CBM_WIDTH; - colourindex = (x / 4) + (y / 8) * 40; - pixel = (image.image[index] & pixel_mask[x % 4]) >> pixel_displacement[x % 4]; - - // Retrieve RGB values - - switch (pixel) { - case 0: // Background - found_color = image.background; - break; - - case 1: // Colour 1 - found_color = image.colour1[colourindex] >> 4; - break; - - case 2: // Colour 2 - found_color = image.colour1[colourindex] & 0xf; - break; - - case 3: // Colour 3 - found_color = image.colour2[colourindex] & 0xf; - break; - }; - - *(FreeImage_GetScanLine(dib, CBM_HEIGHT - y - 1) + x) = (found_color << 4) | found_color; - } - } - - return dib; - } - } - - return NULL; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitKOALA(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = NULL; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginMNG.cpp b/plugins/AdvaImg/src/FreeImage/PluginMNG.cpp deleted file mode 100644 index 6d2f50ecec..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginMNG.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// ========================================================== -// MNG loader -// -// Design and implementation by -// - Herve 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" - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ---------------------------------------------------------- - -#define MNG_SIGNATURE_SIZE 8 // size of the signature - -// ---------------------------------------------------------- - -// ---------------------------------------------------------- -// mng interface (see MNGHelper.cpp) -// ---------------------------------------------------------- - -FIBITMAP* mng_ReadChunks(int format_id, FreeImageIO *io, fi_handle handle, long Offset, int flags = 0); - - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "MNG"; -} - -static const char * DLL_CALLCONV -Description() { - return "Multiple-image Network Graphics"; -} - -static const char * DLL_CALLCONV -Extension() { - return "mng"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "video/x-mng"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE mng_signature[8] = { 138, 77, 78, 71, 13, 10, 26, 10 }; - BYTE signature[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - io->read_proc(&signature, 1, MNG_SIGNATURE_SIZE, handle); - - return (memcmp(mng_signature, signature, MNG_SIGNATURE_SIZE) == 0) ? TRUE : FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsICCProfiles() { - return TRUE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return FALSE; -} - - -// ---------------------------------------------------------- - -static void * DLL_CALLCONV -Open(FreeImageIO *io, fi_handle handle, BOOL read) { - return NULL; -} - -static void DLL_CALLCONV -Close(FreeImageIO *io, fi_handle handle, void *data) { -} - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - long offset = MNG_SIGNATURE_SIZE; // move to skip first 8 bytes of signature - - // check the signature (8 bytes) - if(Validate(io, handle) == FALSE) { - return NULL; - } - - // parse chunks and decode a jng or mng bitmap - return mng_ReadChunks(s_format_id, io, handle, offset, flags); -} - - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitMNG(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = Open; - plugin->close_proc = Close; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = NULL; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = SupportsICCProfiles; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginPCD.cpp b/plugins/AdvaImg/src/FreeImage/PluginPCD.cpp deleted file mode 100644 index ff0c5b8679..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginPCD.cpp +++ /dev/null @@ -1,251 +0,0 @@ -// ========================================================== -// Kodak PhotoCD Loader -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// -// Based on pascal code developed by Alex Kwak -// -// 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" - -// ========================================================== -// Internal functions -// ========================================================== - -static int -clamp(double x) { - int a = (int)floor(x + 0.5); - return (a < 0) ? 0 : (a > 255) ? 255 : a; -} - -static void -YUV2RGB(int y, int cb, int cr, int &r, int &g, int &b) { - double c11 = 0.0054980 * 256.0; - double c12 = 0.0000001 * 256.0; - double c13 = 0.0051681 * 256.0; - double c21 = 0.0054980 * 256.0; - double c22 = -0.0015446 * 256.0; - double c23 = -0.0026325 * 256.0; - double c31 = 0.0054980 * 256.0; - double c32 = 0.0079533 * 256.0; - double c33 = 0.0000001 * 256.0; - - r = clamp(c11 * y + c12 * (cb - 156) + c13 * (cr - 137)); - g = clamp(c21 * y + c22 * (cb - 156) + c23 * (cr - 137)); - b = clamp(c31 * y + c32 * (cb - 156) + c33 * (cr - 137)); -} - -static BOOL -VerticalOrientation(FreeImageIO *io, fi_handle handle) { - char buffer[128]; - - io->read_proc(buffer, 128, 1, handle); - - return (buffer[72] & 63) == 8; -} - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "PCD"; -} - -static const char * DLL_CALLCONV -Description() { - return "Kodak PhotoCD"; -} - -static const char * DLL_CALLCONV -Extension() { - return "pcd"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-photo-cd"; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - FIBITMAP *dib = NULL; - unsigned width; - unsigned height; - const unsigned bpp = 24; - int scan_line_add = 1; - int start_scan_line = 0; - - BYTE *y1 = NULL, *y2 = NULL, *cbcr = NULL; - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // to make absolute seeks possible we store the current position in the file - - long offset_in_file = io->tell_proc(handle); - long seek = 0; - - // decide which bitmap in the cabinet to load - - switch (flags) { - case PCD_BASEDIV4 : - seek = 0x2000; - width = 192; - height = 128; - break; - - case PCD_BASEDIV16 : - seek = 0xB800; - width = 384; - height = 256; - break; - - default : - seek = 0x30000; - width = 768; - height = 512; - break; - } - - try { - // allocate the dib and write out the header - dib = FreeImage_AllocateHeader(header_only, width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if(!dib) throw FI_MSG_ERROR_DIB_MEMORY; - - if(header_only) { - return dib; - } - - // check if the PCD is bottom-up - - if (VerticalOrientation(io, handle)) { - scan_line_add = -1; - start_scan_line = height - 1; - } - - // temporary stuff to load PCD - - BYTE *y1 = (BYTE*)malloc(width * sizeof(BYTE)); - BYTE *y2 = (BYTE*)malloc(width * sizeof(BYTE)); - BYTE *cbcr = (BYTE*)malloc(width * sizeof(BYTE)); - if(!y1 || !y2 || !cbcr) throw FI_MSG_ERROR_MEMORY; - - BYTE *yl[] = { y1, y2 }; - - // seek to the part where the bitmap data begins - - io->seek_proc(handle, offset_in_file, SEEK_SET); - io->seek_proc(handle, seek, SEEK_CUR); - - // read the data - - for (unsigned y = 0; y < height / 2; y++) { - io->read_proc(y1, width, 1, handle); - io->read_proc(y2, width, 1, handle); - io->read_proc(cbcr, width, 1, handle); - - for (int i = 0; i < 2; i++) { - BYTE *bits = FreeImage_GetScanLine(dib, start_scan_line); - for (unsigned x = 0; x < width; x++) { - int r, g, b; - - YUV2RGB(yl[i][x], cbcr[x / 2], cbcr[(width / 2) + (x / 2)], r, g, b); - - bits[FI_RGBA_BLUE] = (BYTE)b; - bits[FI_RGBA_GREEN] = (BYTE)g; - bits[FI_RGBA_RED] = (BYTE)r; - bits += 3; - } - - start_scan_line += scan_line_add; - } - } - - free(cbcr); - free(y2); - free(y1); - - return dib; - - } catch(const char *text) { - if(dib) FreeImage_Unload(dib); - if(cbcr) free(cbcr); - if(y2) free(y2); - if(y1) free(y1); - - FreeImage_OutputMessageProc(s_format_id, text); - - return NULL; - } -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitPCD(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = NULL; - plugin->validate_proc = NULL; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginPCX.cpp b/plugins/AdvaImg/src/FreeImage/PluginPCX.cpp deleted file mode 100644 index cd75629ddc..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginPCX.cpp +++ /dev/null @@ -1,659 +0,0 @@ -// ========================================================== -// PCX Loader -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Jani Kajala (janik@remedy.fi) -// - Markus Loibl (markus.loibl@epost.de) -// - Hervé Drolon (drolon@infonie.fr) -// - Juergen Riecker (j.riecker@gmx.de) -// -// 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" - -// ---------------------------------------------------------- -// Constants + headers -// ---------------------------------------------------------- - -#define IO_BUF_SIZE 2048 - -// ---------------------------------------------------------- - -#ifdef _WIN32 -#pragma pack(push, 1) -#else -#pragma pack(1) -#endif - -typedef struct tagPCXHEADER { - BYTE manufacturer; // Magic number (0x0A = ZSoft Z) - BYTE version; // Version 0 == 2.5 - // 2 == 2.8 with palette info - // 3 == 2.8 without palette info - // 5 == 3.0 with palette info - BYTE encoding; // Encoding: 0 = uncompressed, 1 = PCX rle compressed - BYTE bpp; // Bits per pixel per plane (only 1 or 8) - WORD window[4]; // left, upper, right,lower pixel coord. - WORD hdpi; // Horizontal resolution - WORD vdpi; // Vertical resolution - BYTE color_map[48]; // Colormap for 16-color images - BYTE reserved; - BYTE planes; // Number of planes (1, 3 or 4) - WORD bytes_per_line; // Bytes per row (always even) - WORD palette_info; // Palette information (1 = color or b&w; 2 = gray scale) - WORD h_screen_size; - WORD v_screen_size; - BYTE filler[54]; // Reserved filler -} PCXHEADER; - -#ifdef _WIN32 -#pragma pack(pop) -#else -#pragma pack() -#endif - -// ========================================================== -// Internal functions -// ========================================================== - -static BOOL -pcx_validate(FreeImageIO *io, fi_handle handle) { - BYTE pcx_signature = 0x0A; - BYTE signature[4] = { 0, 0, 0, 0 }; - - if(io->read_proc(&signature, 1, 4, handle) != 4) { - return FALSE; - } - // magic number (0x0A = ZSoft Z) - if(signature[0] == pcx_signature) { - // version - if(signature[1] <= 5) { - // encoding - if((signature[2] == 0) || (signature[2] == 1)) { - // bits per pixel per plane - if((signature[3] == 1) || (signature[3] == 8)) { - return TRUE; - } - } - } - } - - return FALSE; -} - -static unsigned -readline(FreeImageIO &io, fi_handle handle, BYTE *buffer, unsigned length, BOOL rle, BYTE * ReadBuf, int * ReadPos) { - // -----------------------------------------------------------// - // Read either run-length encoded or normal image data // - // // - // THIS IS HOW RUNTIME LENGTH ENCODING WORKS IN PCX: // - // // - // 1) If the upper 2 bits of a byte are set, // - // the lower 6 bits specify the count for the next byte // - // // - // 2) If the upper 2 bits of the byte are clear, // - // the byte is actual data with a count of 1 // - // // - // Note that a scanline always has an even number of bytes // - // ------------------------------------------------------------- - - BYTE count = 0, value = 0; - unsigned written = 0; - - if (rle) { - // run-length encoded read - - while (length--) { - if (count == 0) { - if (*ReadPos >= IO_BUF_SIZE - 1 ) { - if (*ReadPos == IO_BUF_SIZE - 1) { - // we still have one BYTE, copy it to the start pos - - *ReadBuf = ReadBuf[IO_BUF_SIZE - 1]; - - io.read_proc(ReadBuf + 1, 1, IO_BUF_SIZE - 1, handle); - } else { - // read the complete buffer - - io.read_proc(ReadBuf, 1, IO_BUF_SIZE, handle); - } - - *ReadPos = 0; - } - - value = *(ReadBuf + (*ReadPos)++); - - if ((value & 0xC0) == 0xC0) { - count = value & 0x3F; - value = *(ReadBuf + (*ReadPos)++); - } else { - count = 1; - } - } - - count--; - - *(buffer + written++) = value; - } - - } else { - // normal read - - written = io.read_proc(buffer, length, 1, handle); - } - - return written; -} - -#ifdef FREEIMAGE_BIGENDIAN -static void -SwapHeader(PCXHEADER *header) { - SwapShort(&header->window[0]); - SwapShort(&header->window[1]); - SwapShort(&header->window[2]); - SwapShort(&header->window[3]); - SwapShort(&header->hdpi); - SwapShort(&header->vdpi); - SwapShort(&header->bytes_per_line); - SwapShort(&header->palette_info); - SwapShort(&header->h_screen_size); - SwapShort(&header->v_screen_size); -} -#endif - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -/*! - Returns the format string for the plugin. Each plugin, - both internal in the DLL and external in a .fip file, must have - a unique format string to be addressable. -*/ - -static const char * DLL_CALLCONV -Format() { - return "PCX"; -} - -/*! - Returns a description string for the plugin. Though a - description is not necessary per-se, - it is advised to return an unique string in order to tell the - user what type of bitmaps this plugin will read and/or write. -*/ - -static const char * DLL_CALLCONV -Description() { - return "Zsoft Paintbrush"; -} - -/*! - Returns a comma separated list of file - extensions indicating what files this plugin can open. The - list, being used by FreeImage_GetFIFFromFilename, is usually - used as a last resort in finding the type of the bitmap we - are dealing with. Best is to check the first few bytes on - the low-level bits level first and compare them with a known - signature . If this fails, FreeImage_GetFIFFromFilename can be - used. -*/ - -static const char * DLL_CALLCONV -Extension() { - return "pcx"; -} - -/*! - Returns an (optional) regular expression to help - software identifying a bitmap type. The - expression can be applied to the first few bytes (header) of - the bitmap. FreeImage is not capable of processing regular expression itself, - but FreeImageQt, the FreeImage Trolltech support library, can. If RegExpr - returns NULL, FreeImageQt will automatically bypass Trolltech's regular - expression support and use its internal functions to find the bitmap type. -*/ - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-pcx"; -} - -/*! - Validates a bitmap by reading the first few bytes - and comparing them with a known bitmap signature. - TRUE is returned if the bytes match the signature, FALSE otherwise. - The Validate function is used by using FreeImage_GetFileType. - - Note: a plugin can safely read data any data from the bitmap without seeking back - to the original entry point; the entry point is stored prior to calling this - function and restored after. - - Note: because of FreeImage's io redirection support, the header for the bitmap - must be on the start of the bitmap or at least on a known part in the bitmap. It is - forbidden to seek to the end of the bitmap or to a point relative to the end of a bitmap, - because the end of the bitmap is not always known. -*/ - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - return pcx_validate(io, handle); -} - -/*! - This function is used to 'ask' the plugin if it can write - a bitmap in a certain bitdepth. Different bitmap types have different - capabilities, for example not all formats allow writing in palettized mode. - This function is there provide an uniform interface to the plugin's - capabilities. SupportsExportDepth returns TRUE if the plugin support writing - in the asked bitdepth, or FALSE if it doesn't. The function also - returns FALSE if bitmap saving is not supported by the plugin at all. -*/ - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -/*! - Loads a bitmap into memory. On entry it is assumed that - the bitmap to be loaded is of the correct type. If the bitmap - is of an incorrect type, the plugin might not gracefully fail but - crash or enter an endless loop. It is also assumed that all - the bitmap data is available at one time. If the bitmap is not complete, - for example because it is being downloaded while loaded, the plugin - might also not gracefully fail. - - The Load function has the following parameters: - - The first parameter (FreeImageIO *io) is a structure providing - function pointers in order to make use of FreeImage's IO redirection. Using - FreeImage's file i/o functions instead of standard ones it is garantueed - that all bitmap types, both current and future ones, can be loaded from - memory, file cabinets, the internet and more. The second parameter (fi_handle handle) - is a companion of FreeImageIO and can be best compared with the standard FILE* type, - in a generalized form. - - The third parameter (int page) indicates wether we will be loading a certain page - in the bitmap or if we will load the default one. This parameter is only used if - the plugin supports multi-paged bitmaps, e.g. cabinet bitmaps that contain a series - of images or pages. If the plugin does support multi-paging, the page parameter - can contain either a number higher or equal to 0 to load a certain page, or -1 to - load the default page. If the plugin does not support multi-paging, - the page parameter is always -1. - - The fourth parameter (int flags) manipulates the load function to load a bitmap - in a certain way. Every plugin has a different flag parameter with different meanings. - - The last parameter (void *data) can contain a special data block used when - the file is read multi-paged. Because not every plugin supports multi-paging - not every plugin will use the data parameter and it will be set to NULL.However, - when the plugin does support multi-paging the parameter contains a pointer to a - block of data allocated by the Open function. -*/ - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - FIBITMAP *dib = NULL; - BYTE *bits; // Pointer to dib data - RGBQUAD *pal; // Pointer to dib palette - BYTE *line = NULL; // PCX raster line - BYTE *ReadBuf = NULL; // buffer; - BOOL bIsRLE; // True if the file is run-length encoded - - if(!handle) { - return NULL; - } - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - try { - // check PCX identifier - - long start_pos = io->tell_proc(handle); - BOOL validated = pcx_validate(io, handle); - io->seek_proc(handle, start_pos, SEEK_SET); - if(!validated) { - throw FI_MSG_ERROR_MAGIC_NUMBER; - } - - // process the header - - PCXHEADER header; - - if(io->read_proc(&header, sizeof(PCXHEADER), 1, handle) != 1) { - throw FI_MSG_ERROR_PARSING; - } -#ifdef FREEIMAGE_BIGENDIAN - SwapHeader(&header); -#endif - - // allocate a new DIB - - unsigned width = header.window[2] - header.window[0] + 1; - unsigned height = header.window[3] - header.window[1] + 1; - unsigned bitcount = header.bpp * header.planes; - - if (bitcount == 24) { - dib = FreeImage_AllocateHeader(header_only, width, height, bitcount, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } else { - dib = FreeImage_AllocateHeader(header_only, width, height, bitcount); - } - - // if the dib couldn't be allocated, throw an error - - if (!dib) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // metrics handling code - - FreeImage_SetDotsPerMeterX(dib, (unsigned) (((float)header.hdpi) / 0.0254000 + 0.5)); - FreeImage_SetDotsPerMeterY(dib, (unsigned) (((float)header.vdpi) / 0.0254000 + 0.5)); - - // Set up the palette if needed - // ---------------------------- - - switch(bitcount) { - case 1: - { - pal = FreeImage_GetPalette(dib); - pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0; - pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; - break; - } - - case 4: - { - pal = FreeImage_GetPalette(dib); - - BYTE *pColormap = &header.color_map[0]; - - for (int i = 0; i < 16; i++) { - pal[i].rgbRed = pColormap[0]; - pal[i].rgbGreen = pColormap[1]; - pal[i].rgbBlue = pColormap[2]; - pColormap += 3; - } - - break; - } - - case 8: - { - BYTE palette_id; - - io->seek_proc(handle, -769L, SEEK_END); - io->read_proc(&palette_id, 1, 1, handle); - - if (palette_id == 0x0C) { - BYTE *cmap = (BYTE*)malloc(768 * sizeof(BYTE)); - io->read_proc(cmap, 768, 1, handle); - - pal = FreeImage_GetPalette(dib); - BYTE *pColormap = &cmap[0]; - - for(int i = 0; i < 256; i++) { - pal[i].rgbRed = pColormap[0]; - pal[i].rgbGreen = pColormap[1]; - pal[i].rgbBlue = pColormap[2]; - pColormap += 3; - } - - free(cmap); - } - - // wrong palette ID, perhaps a gray scale is needed ? - - else if (header.palette_info == 2) { - pal = FreeImage_GetPalette(dib); - - for(int i = 0; i < 256; i++) { - pal[i].rgbRed = (BYTE)i; - pal[i].rgbGreen = (BYTE)i; - pal[i].rgbBlue = (BYTE)i; - } - } - - io->seek_proc(handle, (long)sizeof(PCXHEADER), SEEK_SET); - } - break; - } - - if(header_only) { - // header only mode - return dib; - } - - // calculate the line length for the PCX and the DIB - - // length of raster line in bytes - unsigned linelength = header.bytes_per_line * header.planes; - // length of DIB line (rounded to DWORD) in bytes - unsigned pitch = FreeImage_GetPitch(dib); - - // run-length encoding ? - - bIsRLE = (header.encoding == 1) ? TRUE : FALSE; - - // load image data - // --------------- - - line = (BYTE*)malloc(linelength * sizeof(BYTE)); - if(!line) throw FI_MSG_ERROR_MEMORY; - - ReadBuf = (BYTE*)malloc(IO_BUF_SIZE * sizeof(BYTE)); - if(!ReadBuf) throw FI_MSG_ERROR_MEMORY; - - bits = FreeImage_GetScanLine(dib, height - 1); - - int ReadPos = IO_BUF_SIZE; - - if ((header.planes == 1) && ((header.bpp == 1) || (header.bpp == 8))) { - BYTE skip; - unsigned written; - - for (unsigned y = 0; y < height; y++) { - written = readline(*io, handle, bits, linelength, bIsRLE, ReadBuf, &ReadPos); - - // skip trailing garbage at the end of the scanline - - for (unsigned count = written; count < linelength; count++) { - if (ReadPos < IO_BUF_SIZE) { - ReadPos++; - } else { - io->read_proc(&skip, sizeof(BYTE), 1, handle); - } - } - - bits -= pitch; - } - } else if ((header.planes == 4) && (header.bpp == 1)) { - BYTE bit, mask, skip; - unsigned index; - BYTE *buffer; - unsigned x, y, written; - - buffer = (BYTE*)malloc(width * sizeof(BYTE)); - if(!buffer) throw FI_MSG_ERROR_MEMORY; - - for (y = 0; y < height; y++) { - written = readline(*io, handle, line, linelength, bIsRLE, ReadBuf, &ReadPos); - - // build a nibble using the 4 planes - - memset(buffer, 0, width * sizeof(BYTE)); - - for(int plane = 0; plane < 4; plane++) { - bit = (BYTE)(1 << plane); - - for (x = 0; x < width; x++) { - index = (unsigned)((x / 8) + plane * header.bytes_per_line); - mask = (BYTE)(0x80 >> (x & 0x07)); - buffer[x] |= (line[index] & mask) ? bit : 0; - } - } - - // then write the DIB row - - for (x = 0; x < width / 2; x++) { - bits[x] = (buffer[2*x] << 4) | buffer[2*x+1]; - } - - // skip trailing garbage at the end of the scanline - - for (unsigned count = written; count < linelength; count++) { - if (ReadPos < IO_BUF_SIZE) { - ReadPos++; - } else { - io->read_proc(&skip, sizeof(BYTE), 1, handle); - } - } - - bits -= pitch; - } - - free(buffer); - - } else if((header.planes == 3) && (header.bpp == 8)) { - BYTE *pline; - - for (unsigned y = 0; y < height; y++) { - readline(*io, handle, line, linelength, bIsRLE, ReadBuf, &ReadPos); - - // convert the plane stream to BGR (RRRRGGGGBBBB -> BGRBGRBGRBGR) - // well, now with the FI_RGBA_x macros, on BIGENDIAN we convert to RGB - - pline = line; - unsigned x; - - for (x = 0; x < width; x++) { - bits[x * 3 + FI_RGBA_RED] = pline[x]; - } - pline += header.bytes_per_line; - - for (x = 0; x < width; x++) { - bits[x * 3 + FI_RGBA_GREEN] = pline[x]; - } - pline += header.bytes_per_line; - - for (x = 0; x < width; x++) { - bits[x * 3 + FI_RGBA_BLUE] = pline[x]; - } - pline += header.bytes_per_line; - - bits -= pitch; - } - } else { - throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; - } - - free(line); - free(ReadBuf); - - return dib; - - } catch (const char *text) { - // free allocated memory - - if (dib != NULL) { - FreeImage_Unload(dib); - } - if (line != NULL) { - free(line); - } - if (ReadBuf != NULL) { - free(ReadBuf); - } - - FreeImage_OutputMessageProc(s_format_id, text); - } - - return NULL; -} - -// ========================================================== -// Init -// ========================================================== - -/*! - Initialises the plugin. The first parameter (Plugin *plugin) - contains a pointer to a pre-allocated Plugin structure - wherein pointers to the available plugin functions - has to be stored. The second parameter (int format_id) is an identification - number that the plugin may use to show plugin specific warning messages - or other information to the user. The plugin number - is generated by FreeImage and can differ everytime the plugin is - initialised. - - If you want to create your own plugin you have to take some - rules into account. Plugin functions have to be compiled - __stdcall using the multithreaded c runtime libraries. Throwing - exceptions in plugin functions is allowed, as long as those exceptions - are being caught inside the same plugin. It is forbidden for a plugin - function to directly call FreeImage functions or to allocate memory - and pass it to the main DLL. Exception to this rule is the special file data - block that may be allocated the Open function. Allocating a FIBITMAP inside a - plugin can be using the function allocate_proc in the FreeImage structure, - which will allocate the memory using the DLL's c runtime library. -*/ - -void DLL_CALLCONV -InitPCX(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = NULL; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginPFM.cpp b/plugins/AdvaImg/src/FreeImage/PluginPFM.cpp deleted file mode 100644 index ea3c46b14e..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginPFM.cpp +++ /dev/null @@ -1,409 +0,0 @@ -// ========================================================== -// PFM Loader and Writer -// -// 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" - -// ========================================================== -// Internal functions -// ========================================================== - -/** maximum size of a line in the header */ -#define PFM_MAXLINE 256 - -/** Big endian / Little endian float conversion */ -#define REVERSEBYTES(source, dest) \ -{ \ - char *j = (char *) source; \ - char *dj = (char *) dest; \ - dj[0] = j[3]; \ - dj[1] = j[2]; \ - dj[2] = j[1]; \ - dj[3] = j[0]; \ -} - -/** -Get a line from a ASCII io stream -*/ -static BOOL -pfm_get_line(FreeImageIO *io, fi_handle handle, char *buffer, int length) { - int i; - memset(buffer, 0, length); - for(i = 0; i < length; i++) { - if(!io->read_proc(&buffer[i], 1, 1, handle)) - return FALSE; - if(buffer[i] == 0x0A) - break; - } - - return (i < length) ? TRUE : FALSE; -} - -/** -Get an integer value from the actual position pointed by handle -*/ -static int -pfm_get_int(FreeImageIO *io, fi_handle handle) { - char c = 0; - BOOL bFirstChar; - - // skip forward to start of next number - - if(!io->read_proc(&c, 1, 1, handle)) { - throw FI_MSG_ERROR_PARSING; - } - - while (1) { - // eat comments - - if (c == '#') { - // if we're at a comment, read to end of line - - bFirstChar = TRUE; - - while (1) { - if(!io->read_proc(&c, 1, 1, handle)) { - throw FI_MSG_ERROR_PARSING; - } - - if (bFirstChar && c == ' ') { - // loop off 1 sp after # - bFirstChar = FALSE; - } else if (c == '\n') { - break; - } - } - } - - if (c >= '0' && c <='9') { - // we've found what we were looking for - break; - } - - if(!io->read_proc(&c, 1, 1, handle)) { - throw FI_MSG_ERROR_PARSING; - } - } - - // we're at the start of a number, continue until we hit a non-number - - int i = 0; - - while (1) { - i = (i * 10) + (c - '0'); - - if(!io->read_proc(&c, 1, 1, handle)) { - throw FI_MSG_ERROR_PARSING; - } - - if (c < '0' || c > '9') { - break; - } - } - - return i; -} - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "PFM"; -} - -static const char * DLL_CALLCONV -Description() { - return "Portable floatmap"; -} - -static const char * DLL_CALLCONV -Extension() { - return "pfm"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-portable-floatmap"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE pfm_id1[] = { 0x50, 0x46 }; - BYTE pfm_id2[] = { 0x50, 0x66 }; - BYTE signature[2] = { 0, 0 }; - - io->read_proc(signature, 1, sizeof(pfm_id1), handle); - - if (memcmp(pfm_id1, signature, sizeof(pfm_id1)) == 0) - return TRUE; - - if (memcmp(pfm_id2, signature, sizeof(pfm_id2)) == 0) - return TRUE; - - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return ( - (type == FIT_FLOAT) || - (type == FIT_RGBF) - ); -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - char line_buffer[PFM_MAXLINE]; - char id_one = 0, id_two = 0; - FIBITMAP *dib = NULL; - float *lineBuffer = NULL; - - if (!handle) { - return NULL; - } - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - try { - FREE_IMAGE_TYPE image_type = FIT_UNKNOWN; - - // Read the first two bytes of the file to determine the file format - // "PF" = color image - // "Pf" = greyscale image - - io->read_proc(&id_one, 1, 1, handle); - io->read_proc(&id_two, 1, 1, handle); - - if(id_one == 'P') { - if(id_two == 'F') { - image_type = FIT_RGBF; - } else if(id_two == 'f') { - image_type = FIT_FLOAT; - } - } - if(image_type == FIT_UNKNOWN) { - // signature error - throw FI_MSG_ERROR_MAGIC_NUMBER; - } - - // Read the header information: width, height and the scale value - unsigned width = (unsigned) pfm_get_int(io, handle); - unsigned height = (unsigned) pfm_get_int(io, handle); - float scalefactor = 1; - - BOOL bResult = pfm_get_line(io, handle, line_buffer, PFM_MAXLINE); - if(bResult) { - bResult = (sscanf(line_buffer, "%f", &scalefactor) == 1) ? TRUE : FALSE; - } - if(!bResult) { - throw "Read error: invalid PFM header"; - } - - // Create a new DIB - dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height); - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - if(header_only) { - // header only mode - return dib; - } - - // Read the image... - - if(image_type == FIT_RGBF) { - const unsigned lineWidth = 3 * width; - lineBuffer = (float*)malloc(lineWidth * sizeof(float)); - if(!lineBuffer) { - throw FI_MSG_ERROR_MEMORY; - } - - for (unsigned y = 0; y < height; y++) { - FIRGBF *bits = (FIRGBF*)FreeImage_GetScanLine(dib, height - 1 - y); - - if(io->read_proc(lineBuffer, sizeof(float), lineWidth, handle) != lineWidth) { - throw "Read error"; - } - float *channel = lineBuffer; - if(scalefactor > 0) { - // MSB - for (unsigned x = 0; x < width; x++) { - REVERSEBYTES(channel++, &bits[x].red); - REVERSEBYTES(channel++, &bits[x].green); - REVERSEBYTES(channel++, &bits[x].blue); - } - } else { - // LSB - for (unsigned x = 0; x < width; x++) { - bits[x].red = *channel++; - bits[x].green = *channel++; - bits[x].blue = *channel++; - } - } - } - - free(lineBuffer); - lineBuffer = NULL; - - } else if(image_type == FIT_FLOAT) { - const unsigned lineWidth = width; - lineBuffer = (float*)malloc(lineWidth * sizeof(float)); - if(!lineBuffer) { - throw FI_MSG_ERROR_MEMORY; - } - - for (unsigned y = 0; y < height; y++) { - float *bits = (float*)FreeImage_GetScanLine(dib, height - 1 - y); - - if(io->read_proc(lineBuffer, sizeof(float), lineWidth, handle) != lineWidth) { - throw "Read error"; - } - float *channel = lineBuffer; - if(scalefactor > 0) { - // MSB - File is Big endian - for (unsigned x = 0; x < width; x++) { - REVERSEBYTES(channel++, &bits[x]); - } - } else { - // LSB - File is Little Endian - for (unsigned x = 0; x < width; x++) { - bits[x] = *channel++; - } - } - } - - free(lineBuffer); - lineBuffer = NULL; - } - - return dib; - - } catch (const char *text) { - if(lineBuffer) free(lineBuffer); - if(dib) FreeImage_Unload(dib); - - if(NULL != text) { - FreeImage_OutputMessageProc(s_format_id, text); - } - - return NULL; - } - -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - if(!dib || !handle) return FALSE; - - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - if((image_type != FIT_RGBF) && (image_type != FIT_FLOAT)) { - return FALSE; - } - - unsigned width = FreeImage_GetWidth(dib); - unsigned height = FreeImage_GetHeight(dib); - unsigned lineWidth = FreeImage_GetLine(dib); - - // save image as Little Endian - const float scalefactor = -1.0F; - - char buffer[PFM_MAXLINE]; // temporary buffer whose size should be enough for what we need - - // Find the appropriate magic number for this file type - - char magic = 0; - - switch(image_type) { - case FIT_RGBF: - magic = 'F'; // RGBF - break; - case FIT_FLOAT: - magic = 'f'; // float greyscale - break; - default: - return FALSE; - } - - // Write the header info - - sprintf(buffer, "P%c\n%d %d\n%f\n", magic, width, height, scalefactor); - io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle); - - // Write the image data - for (unsigned y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y); - io->write_proc(bits, 1, lineWidth, handle); - } - - return TRUE; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitPFM(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginPICT.cpp b/plugins/AdvaImg/src/FreeImage/PluginPICT.cpp deleted file mode 100644 index 371056d20b..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginPICT.cpp +++ /dev/null @@ -1,1343 +0,0 @@ -// ========================================================== -// Apple Macintosh QuickDraw/PICT Loader -// -// Design and implementation by -// - Amir Ebrahimi (amir@unity3d.com) -// -// Based on PICT loading code from paintlib (http://www.paintlib.de/paintlib/). -// -// Paintlib License: -// The paintlib source code and all documentation are copyright (c) 1996-2002 -// Ulrich von Zadow and other contributors. -// -// The paintlib source code is supplied "AS IS". Ulrich von Zadow and other -// contributors disclaim all warranties, expressed or implied, including, without -// limitation, the warranties of merchantability and of fitness for any purpose. -// The authors assume no liability for direct, indirect, incidental, special, -// exemplary, or consequential damages, which may result from the use of paintlib, -// even if advised of the possibility of such damage. -// -// Permission is hereby granted to use, copy, modify, and distribute this source -// code, or portions hereof, for any purpose, without fee, subject to the following -// restrictions: -// -// 1. The origin of this source code must not be misrepresented. -// 2. Altered versions must be plainly marked as such and must not be misrepresented -// as being the original source. -// 3. This Copyright notice may not be removed or altered from any source or altered -// source distribution. -// 4. Executables containing paintlib or parts of it must state that the software -// "contains paintlib code. paintlib is copyright (c) 1996-2002 Ulrich von Zadow -// and other contributors.". This notice must be displayed in at least one place -// where the copyright for the software itself is displayed. The documentation must -// also contain this notice. -// -// Bug fixes were made to the original code to support version 2 PICT files -// properly. -// -// Additional resources: -// http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-458.html -// http://www.fileformat.info/format/macpict/egff.htm -// -// Notes (http://lists.apple.com/archives/java-dev/2006/Apr/msg00588.html): -// There are three main types of PICT files: -// - Version 1 -// - Version 2 -// - Extended Version 2 -// -// Some things to look out for: -// - The bounds and target DPI are stored in a different place in all three. -// - Some of the values are fixed-point shorts ( short / 65536f ) -// - Values are big endian -// - All of this may be *preceded* by a 512 byte header--sometimes it is -// there, and sometimes it isn't. You just have to check for the magic -// values in both places. -// -// 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" - -// ========================================================== -// Plugin Interface -// ========================================================== -static int s_format_id; - -static const int outputMessageSize = 256; - -// ========================================================== -// Internal functions -// ========================================================== - -static BYTE -Read8(FreeImageIO *io, fi_handle handle) { - BYTE i = 0; - io->read_proc(&i, 1, 1, handle); - return i; -} - -static WORD -Read16(FreeImageIO *io, fi_handle handle) { - // reads a two-byte big-endian integer from the given file and returns its value. - // assumes unsigned. - - unsigned hi = Read8(io, handle); - unsigned lo = Read8(io, handle); - return (WORD)(lo + (hi << 8)); -} - -static unsigned -Read32(FreeImageIO *io, fi_handle handle) { - // reads a four-byte big-endian integer from the given file and returns its value. - // assumes unsigned. - - unsigned b3 = Read8(io, handle); - unsigned b2 = Read8(io, handle); - unsigned b1 = Read8(io, handle); - unsigned b0 = Read8(io, handle); - return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0; -} - -// ---------------------------------------------------------- - -struct OpDef -{ - const char * name; - int len; - const char * description; -}; - -// for reserved opcodes -#define res(length) { "reserved", (length), "reserved for Apple use" } -#define RGB_LEN 6 -#define WORD_LEN -1 -#define NA 0 - -static OpDef optable[] = -{ -/* 0x00 */ { "NOP", 0, "nop" }, -/* 0x01 */ { "Clip", NA, "clip" }, -/* 0x02 */ { "BkPat", 8, "background pattern" }, -/* 0x03 */ { "TxFont", 2, "text font (word)" }, -/* 0x04 */ { "TxFace", 1, "text face (byte)" }, -/* 0x05 */ { "TxMode", 2, "text mode (word)" }, -/* 0x06 */ { "SpExtra", 4, "space extra (fixed point)" }, -/* 0x07 */ { "PnSize", 4, "pen size (point)" }, -/* 0x08 */ { "PnMode", 2, "pen mode (word)" }, -/* 0x09 */ { "PnPat", 8, "pen pattern" }, -/* 0x0a */ { "FillPat", 8, "fill pattern" }, -/* 0x0b */ { "OvSize", 4, "oval size (point)" }, -/* 0x0c */ { "Origin", 4, "dh, dv (word)" }, -/* 0x0d */ { "TxSize", 2, "text size (word)" }, -/* 0x0e */ { "FgColor", 4, "foreground color (longword)" }, -/* 0x0f */ { "BkColor", 4, "background color (longword)" }, -/* 0x10 */ { "TxRatio", 8, "numerator (point), denominator (point)" }, -/* 0x11 */ { "Version", 1, "version (byte)" }, -/* 0x12 */ { "BkPixPat", NA, "color background pattern" }, -/* 0x13 */ { "PnPixPat", NA, "color pen pattern" }, -/* 0x14 */ { "FillPixPat", NA, "color fill pattern" }, -/* 0x15 */ { "PnLocHFrac", 2, "fractional pen position" }, -/* 0x16 */ { "ChExtra", 2, "extra for each character" }, -/* 0x17 */ res(0), -/* 0x18 */ res(0), -/* 0x19 */ res(0), -/* 0x1a */ { "RGBFgCol", RGB_LEN, "RGB foreColor" }, -/* 0x1b */ { "RGBBkCol", RGB_LEN, "RGB backColor" }, -/* 0x1c */ { "HiliteMode", 0, "hilite mode flag" }, -/* 0x1d */ { "HiliteColor", RGB_LEN, "RGB hilite color" }, -/* 0x1e */ { "DefHilite", 0, "Use default hilite color" }, -/* 0x1f */ { "OpColor", 6, "RGB OpColor for arithmetic modes" }, -/* 0x20 */ { "Line", 8, "pnLoc (point), newPt (point)" }, -/* 0x21 */ { "LineFrom", 4, "newPt (point)" }, -/* 0x22 */ { "ShortLine", 6, "pnLoc (point, dh, dv (-128 .. 127))" }, -/* 0x23 */ { "ShortLineFrom", 2, "dh, dv (-128 .. 127)" }, -/* 0x24 */ res(WORD_LEN), -/* 0x25 */ res(WORD_LEN), -/* 0x26 */ res(WORD_LEN), -/* 0x27 */ res(WORD_LEN), -/* 0x28 */ { "LongText", NA, "txLoc (point), count (0..255), text" }, -/* 0x29 */ { "DHText", NA, "dh (0..255), count (0..255), text" }, -/* 0x2a */ { "DVText", NA, "dv (0..255), count (0..255), text" }, -/* 0x2b */ { "DHDVText", NA, "dh, dv (0..255), count (0..255), text" }, -/* 0x2c */ res(WORD_LEN), -/* 0x2d */ res(WORD_LEN), -/* 0x2e */ res(WORD_LEN), -/* 0x2f */ res(WORD_LEN), -/* 0x30 */ { "frameRect", 8, "rect" }, -/* 0x31 */ { "paintRect", 8, "rect" }, -/* 0x32 */ { "eraseRect", 8, "rect" }, -/* 0x33 */ { "invertRect", 8, "rect" }, -/* 0x34 */ { "fillRect", 8, "rect" }, -/* 0x35 */ res(8), -/* 0x36 */ res(8), -/* 0x37 */ res(8), -/* 0x38 */ { "frameSameRect", 0, "rect" }, -/* 0x39 */ { "paintSameRect", 0, "rect" }, -/* 0x3a */ { "eraseSameRect", 0, "rect" }, -/* 0x3b */ { "invertSameRect", 0, "rect" }, -/* 0x3c */ { "fillSameRect", 0, "rect" }, -/* 0x3d */ res(0), -/* 0x3e */ res(0), -/* 0x3f */ res(0), -/* 0x40 */ { "frameRRect", 8, "rect" }, -/* 0x41 */ { "paintRRect", 8, "rect" }, -/* 0x42 */ { "eraseRRect", 8, "rect" }, -/* 0x43 */ { "invertRRect", 8, "rect" }, -/* 0x44 */ { "fillRRrect", 8, "rect" }, -/* 0x45 */ res(8), -/* 0x46 */ res(8), -/* 0x47 */ res(8), -/* 0x48 */ { "frameSameRRect", 0, "rect" }, -/* 0x49 */ { "paintSameRRect", 0, "rect" }, -/* 0x4a */ { "eraseSameRRect", 0, "rect" }, -/* 0x4b */ { "invertSameRRect", 0, "rect" }, -/* 0x4c */ { "fillSameRRect", 0, "rect" }, -/* 0x4d */ res(0), -/* 0x4e */ res(0), -/* 0x4f */ res(0), -/* 0x50 */ { "frameOval", 8, "rect" }, -/* 0x51 */ { "paintOval", 8, "rect" }, -/* 0x52 */ { "eraseOval", 8, "rect" }, -/* 0x53 */ { "invertOval", 8, "rect" }, -/* 0x54 */ { "fillOval", 8, "rect" }, -/* 0x55 */ res(8), -/* 0x56 */ res(8), -/* 0x57 */ res(8), -/* 0x58 */ { "frameSameOval", 0, "rect" }, -/* 0x59 */ { "paintSameOval", 0, "rect" }, -/* 0x5a */ { "eraseSameOval", 0, "rect" }, -/* 0x5b */ { "invertSameOval", 0, "rect" }, -/* 0x5c */ { "fillSameOval", 0, "rect" }, -/* 0x5d */ res(0), -/* 0x5e */ res(0), -/* 0x5f */ res(0), -/* 0x60 */ { "frameArc", 12, "rect, startAngle, arcAngle" }, -/* 0x61 */ { "paintArc", 12, "rect, startAngle, arcAngle" }, -/* 0x62 */ { "eraseArc", 12, "rect, startAngle, arcAngle" }, -/* 0x63 */ { "invertArc", 12, "rect, startAngle, arcAngle" }, -/* 0x64 */ { "fillArc", 12, "rect, startAngle, arcAngle" }, -/* 0x65 */ res(12), -/* 0x66 */ res(12), -/* 0x67 */ res(12), -/* 0x68 */ { "frameSameArc", 4, "rect, startAngle, arcAngle" }, -/* 0x69 */ { "paintSameArc", 4, "rect, startAngle, arcAngle" }, -/* 0x6a */ { "eraseSameArc", 4, "rect, startAngle, arcAngle" }, -/* 0x6b */ { "invertSameArc", 4, "rect, startAngle, arcAngle" }, -/* 0x6c */ { "fillSameArc", 4, "rect, startAngle, arcAngle" }, -/* 0x6d */ res(4), -/* 0x6e */ res(4), -/* 0x6f */ res(4), -/* 0x70 */ { "framePoly", NA, "poly" }, -/* 0x71 */ { "paintPoly", NA, "poly" }, -/* 0x72 */ { "erasePoly", NA, "poly" }, -/* 0x73 */ { "invertPoly", NA, "poly" }, -/* 0x74 */ { "fillPoly", NA, "poly" }, -/* 0x75 */ res(NA), -/* 0x76 */ res(NA), -/* 0x77 */ res(NA), -/* 0x78 */ { "frameSamePoly", 0, "poly (NYI)" }, -/* 0x79 */ { "paintSamePoly", 0, "poly (NYI)" }, -/* 0x7a */ { "eraseSamePoly", 0, "poly (NYI)" }, -/* 0x7b */ { "invertSamePoly", 0, "poly (NYI)" }, -/* 0x7c */ { "fillSamePoly", 0, "poly (NYI)" }, -/* 0x7d */ res(0), -/* 0x7e */ res(0), -/* 0x7f */ res(0), -/* 0x80 */ { "frameRgn", NA, "region" }, -/* 0x81 */ { "paintRgn", NA, "region" }, -/* 0x82 */ { "eraseRgn", NA, "region" }, -/* 0x83 */ { "invertRgn", NA, "region" }, -/* 0x84 */ { "fillRgn", NA, "region" }, -/* 0x85 */ res(NA), -/* 0x86 */ res(NA), -/* 0x87 */ res(NA), -/* 0x88 */ { "frameSameRgn", 0, "region (NYI)" }, -/* 0x89 */ { "paintSameRgn", 0, "region (NYI)" }, -/* 0x8a */ { "eraseSameRgn", 0, "region (NYI)" }, -/* 0x8b */ { "invertSameRgn", 0, "region (NYI)" }, -/* 0x8c */ { "fillSameRgn", 0, "region (NYI)" }, -/* 0x8d */ res(0), -/* 0x8e */ res(0), -/* 0x8f */ res(0), -/* 0x90 */ { "BitsRect", NA, "copybits, rect clipped" }, -/* 0x91 */ { "BitsRgn", NA, "copybits, rgn clipped" }, -/* 0x92 */ res(WORD_LEN), -/* 0x93 */ res(WORD_LEN), -/* 0x94 */ res(WORD_LEN), -/* 0x95 */ res(WORD_LEN), -/* 0x96 */ res(WORD_LEN), -/* 0x97 */ res(WORD_LEN), -/* 0x98 */ { "PackBitsRect", NA, "packed copybits, rect clipped" }, -/* 0x99 */ { "PackBitsRgn", NA, "packed copybits, rgn clipped" }, -/* 0x9a */ { "Opcode_9A", NA, "the mysterious opcode 9A" }, -/* 0x9b */ res(WORD_LEN), -/* 0x9c */ res(WORD_LEN), -/* 0x9d */ res(WORD_LEN), -/* 0x9e */ res(WORD_LEN), -/* 0x9f */ res(WORD_LEN), -/* 0xa0 */ { "ShortComment", 2, "kind (word)" }, -/* 0xa1 */ { "LongComment", NA, "kind (word), size (word), data" } -}; - -// ---------------------------------------------------------- - -struct MacRect -{ - WORD top; - WORD left; - WORD bottom; - WORD right; -}; - -struct MacpixMap -{ - // Ptr baseAddr // Not used in file. - // short rowBytes // read in seperatly. - struct MacRect Bounds; - WORD version; - WORD packType; - LONG packSize; - LONG hRes; - LONG vRes; - WORD pixelType; - WORD pixelSize; - WORD cmpCount; - WORD cmpSize; - LONG planeBytes; - LONG pmTable; - LONG pmReserved; -}; - -struct MacRGBColour -{ - WORD red; - WORD green; - WORD blue; -}; - -struct MacPoint -{ - WORD x; - WORD y; -}; - -struct MacPattern // Klaube -{ - BYTE pix[64]; -}; - -// ---------------------------------------------------------- - -static void -ReadRect( FreeImageIO *io, fi_handle handle, MacRect* rect ) { - rect->top = Read16( io, handle ); - rect->left = Read16( io, handle ); - rect->bottom = Read16( io, handle ); - rect->right = Read16( io, handle ); -} - -static void -ReadPixmap( FreeImageIO *io, fi_handle handle, MacpixMap* pPixMap ) { - pPixMap->version = Read16( io, handle ); - pPixMap->packType = Read16( io, handle ); - pPixMap->packSize = Read32( io, handle ); - pPixMap->hRes = Read16( io, handle ); - Read16( io, handle ); - pPixMap->vRes = Read16( io, handle ); - Read16( io, handle ); - pPixMap->pixelType = Read16( io, handle ); - pPixMap->pixelSize = Read16( io, handle ); - pPixMap->cmpCount = Read16( io, handle ); - pPixMap->cmpSize = Read16( io, handle ); - pPixMap->planeBytes = Read32( io, handle ); - pPixMap->pmTable = Read32( io, handle ); - pPixMap->pmReserved = Read32( io, handle ); -} - -/** -Reads a mac color table into a bitmap palette. -*/ -static void -ReadColorTable( FreeImageIO *io, fi_handle handle, WORD* pNumColors, RGBQUAD* pPal ) { - LONG ctSeed; - WORD ctFlags; - WORD val; - int i; - - ctSeed = Read32( io, handle ); - ctFlags = Read16( io, handle ); - WORD numColors = Read16( io, handle )+1; - *pNumColors = numColors; - - for (i = 0; i < numColors; i++) { - val = Read16( io, handle ); - if (ctFlags & 0x8000) { - // The indicies in a device colour table are bogus and - // usually == 0, so I assume we allocate up the list of - // colours in order. - val = (WORD)i; - } - if (val >= numColors) { - throw "pixel value greater than color table size."; - } - // Mac colour tables contain 16-bit values for R, G, and B... - pPal[val].rgbRed = ((BYTE) (((WORD) (Read16( io, handle )) >> 8) & 0xFF)); - pPal[val].rgbGreen = ((BYTE) (((WORD) (Read16( io, handle )) >> 8) & 0xFF)); - pPal[val].rgbBlue = ((BYTE) (((WORD) (Read16( io, handle )) >> 8) & 0xFF)); - } -} - -/** -skips unneeded packbits. -pixelSize == Source bits per pixel. -*/ -static void -SkipBits( FreeImageIO *io, fi_handle handle, MacRect* bounds, WORD rowBytes, int pixelSize ) { - int i; - WORD pixwidth; // bytes per row when uncompressed. - - int height = bounds->bottom - bounds->top; - int width = bounds->right - bounds->left; - - // High bit of rowBytes is flag. - if (pixelSize <= 8) { - rowBytes &= 0x7fff; - } - pixwidth = (WORD)width; - - if (pixelSize == 16) { - pixwidth *= 2; - } - if (rowBytes == 0) { - rowBytes = pixwidth; - } - if (rowBytes < 8) { - io->seek_proc( handle, rowBytes*height, SEEK_CUR ); - } - else { - for (i = 0; i < height; i++) { - int lineLen; // length of source line in bytes. - if (rowBytes > 250) { - lineLen = Read16( io, handle ); - } else { - lineLen = Read8( io, handle ); - } - io->seek_proc( handle, lineLen, SEEK_CUR ); - } - } -} - -/** -Skip polygon or region -*/ -static void -SkipPolyOrRegion( FreeImageIO *io, fi_handle handle ) { - WORD len = Read16( io, handle ) - 2; - io->seek_proc(handle, len, SEEK_CUR); -} - -/** -Width in bytes for 8 bpp or less. -Width in pixels for 16 bpp. -Expands Width units to 32-bit pixel data. -*/ -static void -expandBuf( FreeImageIO *io, fi_handle handle, int width, int bpp, BYTE* dst ) { - switch (bpp) { - case 16: - for ( int i=0; i<width; i++) { - WORD src = Read16( io, handle ); - dst[ FI_RGBA_BLUE ] = (src & 31)*8; // Blue - dst[ FI_RGBA_GREEN ] = ((src >> 5) & 31)*8; // Green - dst[ FI_RGBA_RED ] = ((src >> 10) & 31)*8; // Red - dst[ FI_RGBA_ALPHA ] = 0xFF; // Alpha - dst += 4; - } - break; - default: - throw "Bad bits per pixel in expandBuf."; - } -} - -/** -Expands Width units to 8-bit pixel data. -Max. 8 bpp source format. -*/ -static void -expandBuf8( FreeImageIO *io, fi_handle handle, int width, int bpp, BYTE* dst ) -{ - switch (bpp) { - case 8: - io->read_proc( dst, width, 1, handle ); - break; - case 4: - for (int i = 0; i < width; i++) { - WORD src = Read8( io, handle ); - *dst = (src >> 4) & 15; - *(dst+1) = (src & 15); - dst += 2; - } - if (width & 1) { // Odd Width? - WORD src = Read8( io, handle ); - *dst = (src >> 4) & 15; - dst++; - } - break; - case 2: - for (int i = 0; i < width; i++) { - WORD src = Read8( io, handle ); - *dst = (src >> 6) & 3; - *(dst+1) = (src >> 4) & 3; - *(dst+2) = (src >> 2) & 3; - *(dst+3) = (src & 3); - dst += 4; - } - if (width & 3) { // Check for leftover pixels - for (int i = 6; i > 8 - (width & 3) * 2; i -= 2) { - WORD src = Read8( io, handle ); - *dst = (src >> i) & 3; - dst++; - } - } - break; - case 1: - for (int i = 0; i < width; i++) { - WORD src = Read8( io, handle ); - *dst = (src >> 7) & 1; - *(dst+1) = (src >> 6) & 1; - *(dst+2) = (src >> 5) & 1; - *(dst+3) = (src >> 4) & 1; - *(dst+4) = (src >> 3) & 1; - *(dst+5) = (src >> 2) & 1; - *(dst+6) = (src >> 1) & 1; - *(dst+7) = (src & 1); - dst += 8; - } - if (width & 7) { // Check for leftover pixels - for (int i = 7; i > (8-width & 7); i--) { - WORD src = Read8( io, handle ); - *dst = (src >> i) & 1; - dst++; - } - } - break; - default: - throw "Bad bits per pixel in expandBuf8."; - } -} - -static BYTE* -UnpackPictRow( FreeImageIO *io, fi_handle handle, BYTE* pLineBuf, int width, int rowBytes, int srcBytes ) { - - if (rowBytes < 8) { // Ah-ha! The bits aren't actually packed. This will be easy. - io->read_proc( pLineBuf, rowBytes, 1, handle ); - } - else { - BYTE* pCurPixel = pLineBuf; - - // Unpack RLE. The data is packed bytewise. - for (int j = 0; j < srcBytes; ) { - BYTE FlagCounter = Read8( io, handle ); - if (FlagCounter & 0x80) { - if (FlagCounter == 0x80) { - // Special case: repeat value of 0. - // Apple says ignore. - j++; - } else { - // Packed data. - int len = ((FlagCounter ^ 255) & 255) + 2; - BYTE p = Read8( io, handle ); - memset( pCurPixel, p, len); - pCurPixel += len; - j += 2; - } - } - else { - // Unpacked data - int len = (FlagCounter & 255) + 1; - io->read_proc( pCurPixel, len, 1, handle ); - pCurPixel += len; - j += len + 1; - } - } - } - - return pLineBuf; -} - -/** -This routine decompresses BitsRects with a packType of 4 (and 32 bits per pixel). -In this format, each line is separated into 8-bit-bitplanes and then compressed via RLE. -To decode, the routine decompresses each line & then juggles the bytes around to get pixel-oriented data. -NumBitPlanes == 3 if RGB, 4 if RGBA -*/ -static void -Unpack32Bits( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacRect* bounds, WORD rowBytes, int numPlanes ) { - int height = bounds->bottom - bounds->top; - int width = bounds->right - bounds->left; - - if (rowBytes == 0) { - rowBytes = (WORD)( width * 4 ); - } - - BYTE* pLineBuf = (BYTE*)malloc( rowBytes ); // Let's allocate enough for 4 bit planes - if ( pLineBuf ) { - try { - for ( int i = 0; i < height; i++ ) { - // for each line do... - int linelen; // length of source line in bytes. - if (rowBytes > 250) { - linelen = Read16( io, handle ); - } else { - linelen = Read8( io, handle); - } - - BYTE* pBuf = UnpackPictRow( io, handle, pLineBuf, width, rowBytes, linelen ); - - // Convert plane-oriented data into pixel-oriented data & - // copy into destination bitmap. - BYTE* dst = (BYTE*)FreeImage_GetScanLine( dib, height - 1 - i); - - if ( numPlanes == 3 ) { - for ( int j = 0; j < width; j++ ) { - // For each pixel in line... - dst[ FI_RGBA_BLUE ] = (*(pBuf+width*2)); // Blue - dst[ FI_RGBA_GREEN ] = (*(pBuf+width)); // Green - dst[ FI_RGBA_RED ] = (*pBuf); // Red - dst[ FI_RGBA_ALPHA ] = (0xFF); - dst += 4; - pBuf++; - } - } else { - for ( int j = 0; j < width; j++ ) { - // For each pixel in line... - dst[ FI_RGBA_BLUE ] = (*(pBuf+width*3)); // Blue - dst[ FI_RGBA_GREEN ] = (*(pBuf+width*2)); // Green - dst[ FI_RGBA_RED ] = (*(pBuf+width)); // Red - dst[ FI_RGBA_ALPHA ] = (*pBuf); - dst += 4; - pBuf++; - } - } - } - } - catch( ... ) { - free( pLineBuf ); - throw; - } - } - free( pLineBuf ); -} - -/** -Decompression routine for 8 bpp. -rowBytes is the number of bytes each source row would take if it were uncompressed. -This _isn't_ equal to the number of pixels in the row - it seems apple pads the data to a word boundary and then compresses it. -Of course, we have to decompress the excess data and then throw it away. -*/ -static void -Unpack8Bits( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacRect* bounds, WORD rowBytes ) { - int height = bounds->bottom - bounds->top; - int width = bounds->right - bounds->left; - - // High bit of rowBytes is flag. - rowBytes &= 0x7fff; - - if (rowBytes == 0) { - rowBytes = (WORD)width; - } - - for ( int i = 0; i < height; i++ ) { - int linelen; // length of source line in bytes. - if (rowBytes > 250) { - linelen = Read16( io, handle ); - } else { - linelen = Read8( io, handle ); - } - BYTE* dst = (BYTE*)FreeImage_GetScanLine( dib, height - 1 - i); - dst = UnpackPictRow( io, handle, dst, width, rowBytes, linelen ); - } -} - -/** -Decompression routine for everything but 8 & 32 bpp. -This routine is slower than the two routines above since it has to deal with a lot of special cases :-(. -It's also a bit chaotic because of these special cases... -unpack8bits is basically a dumber version of unpackbits. -pixelSize == Source bits per pixel. -*/ -static void -UnpackBits( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacRect* bounds, WORD rowBytes, int pixelSize ) { - WORD pixwidth; // bytes per row when uncompressed. - int pkpixsize; - int PixelPerRLEUnit; - - char outputMessage[ outputMessageSize ] = ""; - - int height = bounds->bottom - bounds->top; - int width = bounds->right - bounds->left; - - // High bit of rowBytes is flag. - if (pixelSize <= 8) { - rowBytes &= 0x7fff; - } - - pixwidth = (WORD)width; - pkpixsize = 1; // RLE unit: one byte for everything... - if (pixelSize == 16) { // ...except 16 bpp. - pkpixsize = 2; - pixwidth *= 2; - } - - if (rowBytes == 0) { - rowBytes = pixwidth; - } - - { - // I allocate the temporary line buffer here. I allocate too - // much memory to compensate for sloppy (& hence fast) decompression. - switch (pixelSize) { - case 1: - PixelPerRLEUnit = 8; - break; - case 2: - PixelPerRLEUnit = 4; - break; - case 4: - PixelPerRLEUnit = 2; - break; - case 8: - PixelPerRLEUnit = 1; - break; - case 16: - PixelPerRLEUnit = 1; - break; - default: - sprintf( outputMessage, "Illegal bpp value in unpackbits: %d\n", pixelSize ); - throw outputMessage; - } - - if (rowBytes < 8) { - // ah-ha! The bits aren't actually packed. This will be easy. - for ( int i = 0; i < height; i++ ) { - BYTE* dst = (BYTE*)FreeImage_GetScanLine( dib, height - 1 - i); - if (pixelSize == 16) { - expandBuf( io, handle, width, pixelSize, dst ); - } else { - expandBuf8( io, handle, width, pixelSize, dst ); - } - } - } - else { - for ( int i = 0; i < height; i++ ) { - // For each line do... - int linelen; // length of source line in bytes. - if (rowBytes > 250) { - linelen = Read16( io, handle ); - } else { - linelen = Read8( io, handle ); - } - - BYTE* dst = (BYTE*)FreeImage_GetScanLine( dib, height - 1 - i); - BYTE FlagCounter; - - // Unpack RLE. The data is packed bytewise - except for - // 16 bpp data, which is packed per pixel :-(. - for ( int j = 0; j < linelen; ) { - FlagCounter = Read8( io, handle ); - if (FlagCounter & 0x80) { - if (FlagCounter == 0x80) { - // Special case: repeat value of 0. - // Apple says ignore. - j++; - } - else { - // Packed data. - int len = ((FlagCounter ^ 255) & 255) + 2; - - // This is slow for some formats... - if (pixelSize == 16) { - expandBuf( io, handle, 1, pixelSize, dst ); - for ( int k = 1; k < len; k++ ) { - // Repeat the pixel len times. - memcpy( dst+(k*4*PixelPerRLEUnit), dst, 4*PixelPerRLEUnit); - } - dst += len*4*PixelPerRLEUnit; - } - else { - expandBuf8( io, handle, 1, pixelSize, dst ); - for ( int k = 1; k < len; k++ ) { - // Repeat the expanded byte len times. - memcpy( dst+(k*PixelPerRLEUnit), dst, PixelPerRLEUnit); - } - dst += len*PixelPerRLEUnit; - } - j += pkpixsize + 1; - } - } - else { - // Unpacked data - int len = (FlagCounter & 255) + 1; - if (pixelSize == 16) { - expandBuf( io, handle, len, pixelSize, dst ); - dst += len*4*PixelPerRLEUnit; - } - else { - expandBuf8( io, handle, len, pixelSize, dst ); - dst += len*PixelPerRLEUnit; - } - j += ( len * pkpixsize ) + 1; - } - } - } - } - } -} - -static void -DecodeOp9a( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacpixMap* pixMap ) { - // Do the actual unpacking. - switch ( pixMap->pixelSize ) { - case 32: - Unpack32Bits( io, handle, dib, &pixMap->Bounds, 0, pixMap->cmpCount ); - break; - case 8: - Unpack8Bits( io, handle, dib, &pixMap->Bounds, 0 ); - break; - default: - UnpackBits( io, handle, dib, &pixMap->Bounds, 0, pixMap->pixelSize ); - } -} - -static void -DecodeBitmap( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, BOOL isRegion, MacRect* bounds, WORD rowBytes ) { - WORD mode = Read16( io, handle ); - - if ( isRegion ) { - SkipPolyOrRegion( io, handle ); - } - - RGBQUAD* pal = FreeImage_GetPalette( dib ); - if ( !pal ) { - throw "No palette for bitmap!"; - } - - for (int i = 0; i < 2; i++) { - unsigned char val = i ? 0xFF : 0x0; - pal[i].rgbRed = val; - pal[i].rgbGreen = val; - pal[i].rgbBlue = val; - } - - UnpackBits( io, handle, dib, bounds, rowBytes, 1 ); -} - -static void -DecodePixmap( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, BOOL isRegion, MacpixMap* pixMap, WORD rowBytes ) { - // Read mac colour table into windows palette. - WORD numColors; // Palette size. - RGBQUAD ct[256]; - - ReadColorTable( io, handle, &numColors, ct ); - if ( FreeImage_GetBPP( dib ) == 8 ) { - RGBQUAD* pal = FreeImage_GetPalette( dib ); - if ( !pal ) { - throw "No palette for bitmap!"; - } - - for (int i = 0; i < numColors; i++) { - pal[i].rgbRed = ct[ i ].rgbRed; - pal[i].rgbGreen = ct[ i ].rgbGreen; - pal[i].rgbBlue = ct[ i ].rgbBlue; - } - } - - // Ignore source & destination rectangle as well as transfer mode. - MacRect tempRect; - ReadRect( io, handle, &tempRect ); - ReadRect( io, handle, &tempRect ); - WORD mode = Read16( io, handle ); - - if ( isRegion) { - SkipPolyOrRegion( io, handle ); - } - - switch ( pixMap->pixelSize ) { - case 32: - Unpack32Bits( io, handle, dib, &pixMap->Bounds, rowBytes, pixMap->cmpCount ); - break; - case 8: - Unpack8Bits( io, handle, dib, &pixMap->Bounds, rowBytes ); - break; - default: - UnpackBits( io, handle, dib, &pixMap->Bounds, rowBytes, pixMap->pixelSize ); - } -} - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "PICT"; -} - -static const char * DLL_CALLCONV -Description() { - return "Macintosh PICT"; -} - -static const char * DLL_CALLCONV -Extension() { - return "pct,pict,pic"; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-pict"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - if(io->seek_proc(handle, 522, SEEK_SET) == 0) { - BYTE pict_signature[] = { 0x00, 0x11, 0x02, 0xFF, 0x0C, 0X00 }; - BYTE signature[6]; - - if(io->read_proc(signature, 1, sizeof(pict_signature), handle)) { - // v1.0 files have 0x11 (version operator) followed by 0x01 (version number) - // v2.0 files have 0x0011 (version operator) followed by 0x02ff (version number) - // and additionally 0x0c00 as a header opcode - // Currently, we are only supporting v2.0 - return (memcmp(pict_signature, signature, sizeof(pict_signature)) == 0); - } else { - return FALSE; - } - } - - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsICCProfiles() { - return FALSE; -} - -/** -This plugin decodes macintosh PICT files with 1,2,4,8,16 and 32 bits per pixel as well as PICT/JPEG. -If an alpha channel is present in a 32-bit-PICT, it is decoded as well. -The PICT format is a general picture file format and can contain a lot of other elements besides bitmaps. -These elements are ignored. -*/ -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - char outputMessage[ outputMessageSize ] = ""; - FIBITMAP* dib = NULL; - try { - // Skip empty 512 byte header. - if ( !io->seek_proc(handle, 512, SEEK_CUR) == 0 ) - return NULL; - - // Read PICT header - Read16( io, handle ); // Skip version 1 picture size - - MacRect frame; - ReadRect( io, handle, &frame ); - - BYTE b = 0; - while ((b = Read8(io, handle)) == 0); - if ( b != 0x11 ) { - throw "invalid header: version number missing."; - } - - int version = Read8( io, handle ); - if ( version == 2 && Read8( io, handle ) != 0xff ) { - throw "invalid header: illegal version number."; - } - - enum PICTType {none, op9a, jpeg, pixmap, bitmap}; - PICTType pictType = none; - - MacRect bounds; - MacpixMap pixMap; - int hRes = 0x480000; // in pixels/inch (72 by default == 0x480000 in fixed point) - int vRes = 0x480000; // in pixels/inch (72 by default == 0x480000 in fixed point) - WORD rowBytes = 0; - BOOL isRegion = FALSE; - BOOL done = FALSE; - long currentPos = 0; - - while ( !done ) { - WORD opcode = 0; - - // get the current stream position (used to avoid infinite loops) - currentPos = io->tell_proc(handle); - - if ((version == 1) || ((io->tell_proc( handle ) % 2) != 0)) { - // align to word for version 2 - opcode = Read8( io, handle ); - } - if (version == 2) { - opcode = Read16( io, handle ); - } - - if (opcode == 0xFF || opcode == 0xFFFF) { - done = TRUE; - throw "PICT contained only vector data!"; - } - else if (opcode < 0xa2) { - switch (opcode) { - case 0x01: - { - // skip clipping rectangle - MacRect clipRect; - WORD len = Read16( io, handle ); - - if (len == 0x000a) { - /* null rgn */ - ReadRect( io, handle, &clipRect ); - } else { - io->seek_proc(handle, len - 2, SEEK_CUR); - } - break; - } - case 0x12: - case 0x13: - case 0x14: - { - // skip pattern definition - WORD patType; - WORD rowBytes; - MacpixMap p; - WORD numColors; - - patType = Read16( io, handle ); - - switch( patType ) { - case 2: - io->seek_proc(handle, 8, SEEK_CUR); - io->seek_proc(handle, 5, SEEK_CUR); - break; - case 1: - { - io->seek_proc(handle, 8, SEEK_CUR); - rowBytes = Read16( io, handle ); - ReadRect( io, handle, &p.Bounds ); - ReadPixmap( io, handle, &p); - - RGBQUAD ct[256]; - ReadColorTable(io, handle, &numColors, ct ); - SkipBits( io, handle, &p.Bounds, rowBytes, p.pixelSize ); - break; - } - default: - throw "Unknown pattern type."; - } - - break; - } - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - { - SkipPolyOrRegion( io, handle ); - break; - } - case 0x90: - case 0x98: - { - // Bitmap/pixmap data clipped by a rectangle. - rowBytes = Read16( io, handle ); // Bytes per row in source when uncompressed. - isRegion = FALSE; - - if ( rowBytes & 0x8000) { - pictType = pixmap; - } else { - pictType = bitmap; - } - done = TRUE; - break; - } - case 0x91: - case 0x99: - { - // Bitmap/pixmap data clipped by a region. - rowBytes = Read16( io, handle ); // Bytes per row in source when uncompressed. - isRegion = TRUE; - - if ( rowBytes & 0x8000) { - pictType = pixmap; - } else { - pictType = bitmap; - } - done = TRUE; - break; - } - case 0x9a: - { - // DirectBitsRect. - Read32( io, handle ); // Skip fake len and fake EOF. - Read16( io, handle ); // bogus row bytes. - - // Read in the PixMap fields. - ReadRect( io, handle, &pixMap.Bounds ); - ReadPixmap( io, handle, &pixMap ); - - // Ignore source & destination rectangle as well as transfer mode. - MacRect dummy; - ReadRect( io, handle, &dummy ); - ReadRect( io, handle, &dummy ); - WORD mode = Read16( io, handle ); - - pictType=op9a; - done = TRUE; - break; - } - case 0xa1: - { - // long comment - WORD type; - WORD len; - - type = Read16( io, handle ); - len = Read16( io, handle); - if (len > 0) { - io->seek_proc(handle, len, SEEK_CUR); - } - break; - } - default: - // No function => skip to next opcode - if (optable[opcode].len == WORD_LEN) { - WORD len = Read16( io, handle ); - io->seek_proc(handle, len, SEEK_CUR); - } else { - io->seek_proc(handle, optable[opcode].len, SEEK_CUR); - } - break; - } - } - else if (opcode == 0xc00) { - // version 2 header (26 bytes) - WORD minorVersion = Read16( io, handle ); // always FFFE (-2) for extended version 2 - Read16( io, handle ); // reserved - hRes = Read32( io, handle ); // original horizontal resolution in pixels/inch - vRes = Read32( io, handle ); // original horizontal resolution in pixels/inch - MacRect dummy; - ReadRect( io, handle, &dummy ); // frame bounds at original resolution - Read32( io, handle ); // reserved - } - else if (opcode == 0x8200) { - // jpeg - long opLen = Read32( io, handle ); - BOOL found = FALSE; - int i = 0; - - // skip to JPEG header. - while ( !found && i < opLen ) { -// io->seek_proc( handle, 24, SEEK_CUR ); -// MacRect dummy; -// ReadRect( io, handle, &dummy ); -// io->seek_proc( handle, 122, SEEK_CUR ); -// found = TRUE; - BYTE data[ 2 ]; - if( io->read_proc( data, 2, 1, handle ) ) { - io->seek_proc( handle, -2, SEEK_CUR ); - - if ( data[0] == 0xFF && data[1] == 0xD8 ) { - found = TRUE; - } else { - Read8( io, handle ); - i++; - } - } - } - - if ( found ) { - // Pass the data to the JPEG decoder. - pictType = jpeg; - } else { - throw "PICT file contains unrecognized quicktime data."; - } - done = TRUE; - } - else if (opcode >= 0xa2 && opcode <= 0xaf) { - // reserved - WORD len = Read16( io, handle ); - io->seek_proc(handle, len, SEEK_CUR); - } - else if ((opcode >= 0xb0 && opcode <= 0xcf) || (opcode >= 0x8000 && opcode <= 0x80ff)) { - // just a reserved opcode, no data - } - else if ((opcode >= 0xd0 && opcode <= 0xfe) || opcode >= 8100) { - // reserved - LONG len = Read32( io, handle ); - io->seek_proc(handle, len, SEEK_CUR); - } - else if (opcode >= 0x100 && opcode <= 0x7fff) { - // reserved - io->seek_proc(handle, ((opcode >> 7) & 255), SEEK_CUR); - } - else { - sprintf( outputMessage, "Can't handle opcode %x.\n", opcode ); - throw outputMessage; - } - - if(currentPos == io->tell_proc(handle)) { - // we probaly reached the end of file as we can no longer move forward ... - throw "Invalid PICT file"; - } - } - - switch ( pictType ) { - case op9a: - { - bounds = pixMap.Bounds; - int width = bounds.right - bounds.left; - int height = bounds.bottom - bounds.top; - - if ( pixMap.pixelSize > 8 ) { - dib = FreeImage_Allocate( width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } else { - dib = FreeImage_Allocate( width, height, 8); - } - hRes = pixMap.hRes << 16; - vRes = pixMap.vRes << 16; - break; - } - - case jpeg: - { - dib = FreeImage_LoadFromHandle( FIF_JPEG, io, handle ); - break; - } - - case pixmap: - { - // Decode version 2 pixmap - ReadRect( io, handle, &pixMap.Bounds ); - ReadPixmap( io, handle, &pixMap ); - - bounds = pixMap.Bounds; - int width = bounds.right - bounds.left; - int height = bounds.bottom - bounds.top; - - if ( pixMap.pixelSize > 8 ) { - dib = FreeImage_Allocate( width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } else { - dib = FreeImage_Allocate( width, height, 8); - } - hRes = pixMap.hRes << 16; - vRes = pixMap.vRes << 16; - break; - } - - case bitmap: - { - // Decode version 1 bitmap: 1 bpp. - MacRect srcRect; - MacRect dstRect; - WORD width; // Width in pixels - WORD height; // Height in pixels - - ReadRect( io, handle, &bounds ); - ReadRect( io, handle, &srcRect ); - ReadRect( io, handle, &dstRect ); - - width = bounds.right - bounds.left; - height = bounds.bottom - bounds.top; - - dib = FreeImage_Allocate(width, height, 8); - break; - } - } - - if ( dib ) { - // need to convert resolution figures from fixed point, pixels/inch - // to floating point, pixels/meter. - float hres_ppm = hRes * ((float)39.4 / (float)65536.0); - float vres_ppm = vRes * ((float)39.4 / (float)65536.0); - - FreeImage_SetDotsPerMeterX( dib, (LONG)hres_ppm ); - FreeImage_SetDotsPerMeterY( dib, (LONG)vres_ppm ); - - switch( pictType ) { - case op9a: - DecodeOp9a( io, handle, dib, &pixMap ); - break; - case jpeg: - // Already decoded if the embedded format was valid. - break; - case pixmap: - DecodePixmap( io, handle, dib, isRegion, &pixMap, rowBytes ); - break; - case bitmap: - DecodeBitmap( io, handle, dib, isRegion, &bounds, rowBytes ); - break; - default: - throw "invalid pict type"; - } - } - - return dib; - } - catch(const char *message) { - FreeImage_Unload( dib ); - FreeImage_OutputMessageProc(s_format_id, message); - } - - return NULL; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitPICT(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = NULL; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = NULL; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = SupportsICCProfiles; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginPNM.cpp b/plugins/AdvaImg/src/FreeImage/PluginPNM.cpp deleted file mode 100644 index 3b4d0de554..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginPNM.cpp +++ /dev/null @@ -1,838 +0,0 @@ -// ========================================================== -// PNM (PPM, PGM, PBM) Loader and Writer -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - 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" - -// ========================================================== -// Internal functions -// ========================================================== - -/** -Get an integer value from the actual position pointed by handle -*/ -static int -GetInt(FreeImageIO *io, fi_handle handle) { - char c = 0; - BOOL bFirstChar; - - // skip forward to start of next number - - if(!io->read_proc(&c, 1, 1, handle)) { - throw FI_MSG_ERROR_PARSING; - } - - while (1) { - // eat comments - - if (c == '#') { - // if we're at a comment, read to end of line - - bFirstChar = TRUE; - - while (1) { - if(!io->read_proc(&c, 1, 1, handle)) { - throw FI_MSG_ERROR_PARSING; - } - - if (bFirstChar && c == ' ') { - // loop off 1 sp after # - bFirstChar = FALSE; - } else if (c == '\n') { - break; - } - } - } - - if (c >= '0' && c <='9') { - // we've found what we were looking for - break; - } - - if(!io->read_proc(&c, 1, 1, handle)) { - throw FI_MSG_ERROR_PARSING; - } - } - - // we're at the start of a number, continue until we hit a non-number - - int i = 0; - - while (1) { - i = (i * 10) + (c - '0'); - - if(!io->read_proc(&c, 1, 1, handle)) { - throw FI_MSG_ERROR_PARSING; - } - - if (c < '0' || c > '9') { - break; - } - } - - return i; -} - -/** -Read a WORD value taking into account the endianess issue -*/ -static inline WORD -ReadWord(FreeImageIO *io, fi_handle handle) { - WORD level = 0; - io->read_proc(&level, 2, 1, handle); -#ifndef FREEIMAGE_BIGENDIAN - SwapShort(&level); // PNM uses the big endian convention -#endif - return level; -} - -/** -Write a WORD value taking into account the endianess issue -*/ -static inline void -WriteWord(FreeImageIO *io, fi_handle handle, const WORD value) { - WORD level = value; -#ifndef FREEIMAGE_BIGENDIAN - SwapShort(&level); // PNM uses the big endian convention -#endif - io->write_proc(&level, 2, 1, handle); -} - - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "PNM"; -} - -static const char * DLL_CALLCONV -Description() { - return "Portable Network Media"; -} - -static const char * DLL_CALLCONV -Extension() { - return "pbm,pgm,ppm"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/freeimage-pnm"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE pbm_id1[] = { 0x50, 0x31 }; - BYTE pbm_id2[] = { 0x50, 0x34 }; - BYTE pgm_id1[] = { 0x50, 0x32 }; - BYTE pgm_id2[] = { 0x50, 0x35 }; - BYTE ppm_id1[] = { 0x50, 0x33 }; - BYTE ppm_id2[] = { 0x50, 0x36 }; - BYTE signature[2] = { 0, 0 }; - - io->read_proc(signature, 1, sizeof(pbm_id1), handle); - - if (memcmp(pbm_id1, signature, sizeof(pbm_id1)) == 0) - return TRUE; - - if (memcmp(pbm_id2, signature, sizeof(pbm_id2)) == 0) - return TRUE; - - if (memcmp(pgm_id1, signature, sizeof(pgm_id1)) == 0) - return TRUE; - - if (memcmp(pgm_id2, signature, sizeof(pgm_id2)) == 0) - return TRUE; - - if (memcmp(ppm_id1, signature, sizeof(ppm_id1)) == 0) - return TRUE; - - if (memcmp(ppm_id2, signature, sizeof(ppm_id2)) == 0) - return TRUE; - - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return ( - (depth == 1) || - (depth == 8) || - (depth == 24) - ); -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return ( - (type == FIT_BITMAP) || - (type == FIT_UINT16) || - (type == FIT_RGB16) - ); -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - char id_one = 0, id_two = 0; - int x, y; - FIBITMAP *dib = NULL; - RGBQUAD *pal; // pointer to dib palette - int i; - - if (!handle) { - return NULL; - } - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - try { - FREE_IMAGE_TYPE image_type = FIT_BITMAP; // standard image: 1-, 8-, 24-bit - - // Read the first two bytes of the file to determine the file format - // "P1" = ascii bitmap, "P2" = ascii greymap, "P3" = ascii pixmap, - // "P4" = raw bitmap, "P5" = raw greymap, "P6" = raw pixmap - - io->read_proc(&id_one, 1, 1, handle); - io->read_proc(&id_two, 1, 1, handle); - - if ((id_one != 'P') || (id_two < '1') || (id_two > '6')) { - // signature error - throw FI_MSG_ERROR_MAGIC_NUMBER; - } - - // Read the header information: width, height and the 'max' value if any - - int width = GetInt(io, handle); - int height = GetInt(io, handle); - int maxval = 1; - - if((id_two == '2') || (id_two == '5') || (id_two == '3') || (id_two == '6')) { - maxval = GetInt(io, handle); - if((maxval <= 0) || (maxval > 65535)) { - FreeImage_OutputMessageProc(s_format_id, "Invalid max value : %d", maxval); - throw (const char*)NULL; - } - } - - // Create a new DIB - - switch (id_two) { - case '1': - case '4': - // 1-bit - dib = FreeImage_AllocateHeader(header_only, width, height, 1); - break; - - case '2': - case '5': - if(maxval > 255) { - // 16-bit greyscale - image_type = FIT_UINT16; - dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height); - } else { - // 8-bit greyscale - dib = FreeImage_AllocateHeader(header_only, width, height, 8); - } - break; - - case '3': - case '6': - if(maxval > 255) { - // 48-bit RGB - image_type = FIT_RGB16; - dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height); - } else { - // 24-bit RGB - dib = FreeImage_AllocateHeader(header_only, width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } - break; - } - - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // Build a greyscale palette if needed - - if(image_type == FIT_BITMAP) { - switch(id_two) { - case '1': - case '4': - pal = FreeImage_GetPalette(dib); - pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0; - pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; - break; - - case '2': - case '5': - pal = FreeImage_GetPalette(dib); - for (i = 0; i < 256; i++) { - pal[i].rgbRed = - pal[i].rgbGreen = - pal[i].rgbBlue = (BYTE)i; - } - break; - - default: - break; - } - } - - if(header_only) { - // header only mode - return dib; - } - - // Read the image... - - switch(id_two) { - case '1': - case '4': - // write the bitmap data - - if (id_two == '1') { // ASCII bitmap - for (y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - if (GetInt(io, handle) == 0) - bits[x >> 3] |= (0x80 >> (x & 0x7)); - else - bits[x >> 3] &= (0xFF7F >> (x & 0x7)); - } - } - } else { // Raw bitmap - int line = CalculateLine(width, 1); - - for (y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < line; x++) { - io->read_proc(&bits[x], 1, 1, handle); - - bits[x] = ~bits[x]; - } - } - } - - return dib; - - case '2': - case '5': - if(image_type == FIT_BITMAP) { - // write the bitmap data - - if(id_two == '2') { // ASCII greymap - int level = 0; - - for (y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - level = GetInt(io, handle); - bits[x] = (BYTE)((255 * level) / maxval); - } - } - } else { // Raw greymap - BYTE level = 0; - - for (y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - io->read_proc(&level, 1, 1, handle); - bits[x] = (BYTE)((255 * (int)level) / maxval); - } - } - } - } - else if(image_type == FIT_UINT16) { - // write the bitmap data - - if(id_two == '2') { // ASCII greymap - int level = 0; - - for (y = 0; y < height; y++) { - WORD *bits = (WORD*)FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - level = GetInt(io, handle); - bits[x] = (WORD)((65535 * (double)level) / maxval); - } - } - } else { // Raw greymap - WORD level = 0; - - for (y = 0; y < height; y++) { - WORD *bits = (WORD*)FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - level = ReadWord(io, handle); - bits[x] = (WORD)((65535 * (double)level) / maxval); - } - } - } - } - - return dib; - - case '3': - case '6': - if(image_type == FIT_BITMAP) { - // write the bitmap data - - if (id_two == '3') { // ASCII pixmap - int level = 0; - - for (y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - level = GetInt(io, handle); - bits[FI_RGBA_RED] = (BYTE)((255 * level) / maxval); // R - level = GetInt(io, handle); - bits[FI_RGBA_GREEN] = (BYTE)((255 * level) / maxval); // G - level = GetInt(io, handle); - bits[FI_RGBA_BLUE] = (BYTE)((255 * level) / maxval); // B - - bits += 3; - } - } - } else { // Raw pixmap - BYTE level = 0; - - for (y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - io->read_proc(&level, 1, 1, handle); - bits[FI_RGBA_RED] = (BYTE)((255 * (int)level) / maxval); // R - - io->read_proc(&level, 1, 1, handle); - bits[FI_RGBA_GREEN] = (BYTE)((255 * (int)level) / maxval); // G - - io->read_proc(&level, 1, 1, handle); - bits[FI_RGBA_BLUE] = (BYTE)((255 * (int)level) / maxval); // B - - bits += 3; - } - } - } - } - else if(image_type == FIT_RGB16) { - // write the bitmap data - - if (id_two == '3') { // ASCII pixmap - int level = 0; - - for (y = 0; y < height; y++) { - FIRGB16 *bits = (FIRGB16*)FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - level = GetInt(io, handle); - bits[x].red = (WORD)((65535 * (double)level) / maxval); // R - level = GetInt(io, handle); - bits[x].green = (WORD)((65535 * (double)level) / maxval); // G - level = GetInt(io, handle); - bits[x].blue = (WORD)((65535 * (double)level) / maxval); // B - } - } - } else { // Raw pixmap - WORD level = 0; - - for (y = 0; y < height; y++) { - FIRGB16 *bits = (FIRGB16*)FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - level = ReadWord(io, handle); - bits[x].red = (WORD)((65535 * (double)level) / maxval); // R - level = ReadWord(io, handle); - bits[x].green = (WORD)((65535 * (double)level) / maxval); // G - level = ReadWord(io, handle); - bits[x].blue = (WORD)((65535 * (double)level) / maxval); // B - } - } - } - } - - return dib; - } - - } catch (const char *text) { - if(dib) FreeImage_Unload(dib); - - if(NULL != text) { - switch(id_two) { - case '1': - case '4': - FreeImage_OutputMessageProc(s_format_id, text); - break; - - case '2': - case '5': - FreeImage_OutputMessageProc(s_format_id, text); - break; - - case '3': - case '6': - FreeImage_OutputMessageProc(s_format_id, text); - break; - } - } - } - - return NULL; -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - // ---------------------------------------------------------- - // PNM Saving - // ---------------------------------------------------------- - // - // Output format : - // - // Bit depth flags file format - // ------------- -------------- ----------- - // 1-bit / pixel PNM_SAVE_ASCII PBM (P1) - // 1-bit / pixel PNM_SAVE_RAW PBM (P4) - // 8-bit / pixel PNM_SAVE_ASCII PGM (P2) - // 8-bit / pixel PNM_SAVE_RAW PGM (P5) - // 24-bit / pixel PNM_SAVE_ASCII PPM (P3) - // 24-bit / pixel PNM_SAVE_RAW PPM (P6) - // ---------------------------------------------------------- - - int x, y; - - char buffer[256]; // temporary buffer whose size should be enough for what we need - - if(!dib || !handle) return FALSE; - - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - - int bpp = FreeImage_GetBPP(dib); - int width = FreeImage_GetWidth(dib); - int height = FreeImage_GetHeight(dib); - - // Find the appropriate magic number for this file type - - int magic = 0; - int maxval = 255; - - switch(image_type) { - case FIT_BITMAP: - switch (bpp) { - case 1 : - magic = 1; // PBM file (B & W) - break; - case 8 : - magic = 2; // PGM file (Greyscale) - break; - - case 24 : - magic = 3; // PPM file (RGB) - break; - - default: - return FALSE; // Invalid bit depth - } - break; - - case FIT_UINT16: - magic = 2; // PGM file (Greyscale) - maxval = 65535; - break; - - case FIT_RGB16: - magic = 3; // PPM file (RGB) - maxval = 65535; - break; - - default: - return FALSE; - } - - - if (flags == PNM_SAVE_RAW) - magic += 3; - - // Write the header info - - sprintf(buffer, "P%d\n%d %d\n", magic, width, height); - io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle); - - if (bpp != 1) { - sprintf(buffer, "%d\n", maxval); - io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle); - } - - // Write the image data - /////////////////////// - - if(image_type == FIT_BITMAP) { - switch(bpp) { - case 24 : // 24-bit RGB, 3 bytes per pixel - { - if (flags == PNM_SAVE_RAW) { - for (y = 0; y < height; y++) { - // write the scanline to disc - BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - io->write_proc(&bits[FI_RGBA_RED], 1, 1, handle); // R - io->write_proc(&bits[FI_RGBA_GREEN], 1, 1, handle); // G - io->write_proc(&bits[FI_RGBA_BLUE], 1, 1, handle); // B - - bits += 3; - } - } - } else { - int length = 0; - - for (y = 0; y < height; y++) { - // write the scanline to disc - BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - sprintf(buffer, "%3d %3d %3d ", bits[FI_RGBA_RED], bits[FI_RGBA_GREEN], bits[FI_RGBA_BLUE]); - - io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle); - - length += 12; - - if(length > 58) { - // No line should be longer than 70 characters - sprintf(buffer, "\n"); - io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle); - length = 0; - } - - bits += 3; - } - } - - } - } - break; - - case 8: // 8-bit greyscale - { - if (flags == PNM_SAVE_RAW) { - for (y = 0; y < height; y++) { - // write the scanline to disc - BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - io->write_proc(&bits[x], 1, 1, handle); - } - } - } else { - int length = 0; - - for (y = 0; y < height; y++) { - // write the scanline to disc - BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - sprintf(buffer, "%3d ", bits[x]); - - io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle); - - length += 4; - - if (length > 66) { - // No line should be longer than 70 characters - sprintf(buffer, "\n"); - io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle); - length = 0; - } - } - } - } - } - break; - - case 1: // 1-bit B & W - { - int color; - - if (flags == PNM_SAVE_RAW) { - for(y = 0; y < height; y++) { - // write the scanline to disc - BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y); - - for(x = 0; x < (int)FreeImage_GetLine(dib); x++) - io->write_proc(&bits[x], 1, 1, handle); - } - } else { - int length = 0; - - for (y = 0; y < height; y++) { - // write the scanline to disc - BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < (int)FreeImage_GetLine(dib) * 8; x++) { - color = (bits[x>>3] & (0x80 >> (x & 0x07))) != 0; - - sprintf(buffer, "%c ", color ? '1':'0'); - - io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle); - - length += 2; - - if (length > 68) { - // No line should be longer than 70 characters - sprintf(buffer, "\n"); - io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle); - length = 0; - } - } - } - } - } - - break; - } - } // if(FIT_BITMAP) - - else if(image_type == FIT_UINT16) { // 16-bit greyscale - if (flags == PNM_SAVE_RAW) { - for (y = 0; y < height; y++) { - // write the scanline to disc - WORD *bits = (WORD*)FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - WriteWord(io, handle, bits[x]); - } - } - } else { - int length = 0; - - for (y = 0; y < height; y++) { - // write the scanline to disc - WORD *bits = (WORD*)FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - sprintf(buffer, "%5d ", bits[x]); - - io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle); - - length += 6; - - if (length > 64) { - // No line should be longer than 70 characters - sprintf(buffer, "\n"); - io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle); - length = 0; - } - } - } - } - } - - else if(image_type == FIT_RGB16) { // 48-bit RGB - if (flags == PNM_SAVE_RAW) { - for (y = 0; y < height; y++) { - // write the scanline to disc - FIRGB16 *bits = (FIRGB16*)FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - WriteWord(io, handle, bits[x].red); // R - WriteWord(io, handle, bits[x].green); // G - WriteWord(io, handle, bits[x].blue); // B - } - } - } else { - int length = 0; - - for (y = 0; y < height; y++) { - // write the scanline to disc - FIRGB16 *bits = (FIRGB16*)FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < width; x++) { - sprintf(buffer, "%5d %5d %5d ", bits[x].red, bits[x].green, bits[x].blue); - - io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle); - - length += 18; - - if(length > 52) { - // No line should be longer than 70 characters - sprintf(buffer, "\n"); - io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle); - length = 0; - } - } - } - - } - } - - return TRUE; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitPNM(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginPSD.cpp b/plugins/AdvaImg/src/FreeImage/PluginPSD.cpp deleted file mode 100644 index e453a31789..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginPSD.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// ========================================================== -// Photoshop Loader -// -// Design and implementation by -// - HervĂŠ Drolon (drolon@infonie.fr) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// Based on LGPL code created and published by http://sourceforge.net/projects/elynx/ -// -// 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" -#include "PSDParser.h" - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "PSD"; -} - -static const char * DLL_CALLCONV -Description() { - return "Adobe Photoshop"; -} - -static const char * DLL_CALLCONV -Extension() { - return "psd"; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/vnd.adobe.photoshop"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE psd_id[] = { 0x38, 0x42, 0x50, 0x53 }; - BYTE signature[4] = { 0, 0, 0, 0 }; - - io->read_proc(signature, 1, 4, handle); - - if(memcmp(psd_id, signature, 4) == 0) - return TRUE; - - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsICCProfiles() { - return TRUE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - if(handle) { - psdParser parser; - - FIBITMAP *dib = parser.Load(io, handle, s_format_id, flags); - - return dib; - } - - return NULL; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitPSD(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = NULL; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = NULL; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = SupportsICCProfiles; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginRAS.cpp b/plugins/AdvaImg/src/FreeImage/PluginRAS.cpp deleted file mode 100644 index 08fd558450..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginRAS.cpp +++ /dev/null @@ -1,512 +0,0 @@ -// ========================================================== -// Sun rasterfile Loader -// -// 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" - -// ---------------------------------------------------------- -// Constants + headers -// ---------------------------------------------------------- - -#ifdef _WIN32 -#pragma pack(push, 1) -#else -#pragma pack(1) -#endif - -typedef struct tagSUNHEADER { - DWORD magic; // Magic number - DWORD width; // Image width in pixels - DWORD height; // Image height in pixels - DWORD depth; // Depth (1, 8, 24 or 32 bits) of each pixel - DWORD length; // Image length (in bytes) - DWORD type; // Format of file (see RT_* below) - DWORD maptype; // Type of colormap (see RMT_* below) - DWORD maplength; // Length of colormap (in bytes) -} SUNHEADER; - -#ifdef _WIN32 -#pragma pack(pop) -#else -#pragma pack() -#endif - -// ---------------------------------------------------------- - -// Following the header is the colormap, for maplength bytes (unless maplength is zero), -// then the image. Each row of the image is rounded to 2 bytes. - -#define RAS_MAGIC 0x59A66A95 // Magic number for Sun rasterfiles - -// Sun supported type's - -#define RT_OLD 0 // Old format (raw image in 68000 byte order) -#define RT_STANDARD 1 // Raw image in 68000 byte order -#define RT_BYTE_ENCODED 2 // Run-length encoding of bytes -#define RT_FORMAT_RGB 3 // XRGB or RGB instead of XBGR or BGR -#define RT_FORMAT_TIFF 4 // TIFF <-> standard rasterfile -#define RT_FORMAT_IFF 5 // IFF (TAAC format) <-> standard rasterfile - -#define RT_EXPERIMENTAL 0xffff // Reserved for testing - -// These are the possible colormap types. -// if it's in RGB format, the map is made up of three byte arrays -// (red, green, then blue) that are each 1/3 of the colormap length. - -#define RMT_NONE 0 // maplength is expected to be 0 -#define RMT_EQUAL_RGB 1 // red[maplength/3], green[maplength/3], blue[maplength/3] -#define RMT_RAW 2 // Raw colormap -#define RESC 128 // Run-length encoding escape character - -// ----- NOTES ----- -// Each line of the image is rounded out to a multiple of 16 bits. -// This corresponds to the rounding convention used by the memory pixrect -// package (/usr/include/pixrect/memvar.h) of the SunWindows system. -// The ras_encoding field (always set to 0 by Sun's supported software) -// was renamed to ras_length in release 2.0. As a result, rasterfiles -// of type 0 generated by the old software claim to have 0 length; for -// compatibility, code reading rasterfiles must be prepared to compute the -// TRUE length from the width, height, and depth fields. - -// ========================================================== -// Internal functions -// ========================================================== - -static void -ReadData(FreeImageIO *io, fi_handle handle, BYTE *buf, DWORD length, BOOL rle) { - // Read either Run-Length Encoded or normal image data - - static BYTE repchar, remaining= 0; - - if (rle) { - // Run-length encoded read - - while(length--) { - if (remaining) { - remaining--; - *(buf++)= repchar; - } else { - io->read_proc(&repchar, 1, 1, handle); - - if (repchar == RESC) { - io->read_proc(&remaining, 1, 1, handle); - - if (remaining == 0) { - *(buf++)= RESC; - } else { - io->read_proc(&repchar, 1, 1, handle); - - *(buf++)= repchar; - } - } else { - *(buf++)= repchar; - } - } - } - } else { - // Normal read - - io->read_proc(buf, length, 1, handle); - } -} - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "RAS"; -} - -static const char * DLL_CALLCONV -Description() { - return "Sun Raster Image"; -} - -static const char * DLL_CALLCONV -Extension() { - return "ras"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-cmu-raster"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE ras_signature[] = { 0x59, 0xA6, 0x6A, 0x95 }; - BYTE signature[4] = { 0, 0, 0, 0 }; - - io->read_proc(signature, 1, sizeof(ras_signature), handle); - - return (memcmp(ras_signature, signature, sizeof(ras_signature)) == 0); -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - SUNHEADER header; // Sun file header - WORD linelength; // Length of raster line in bytes - WORD fill; // Number of fill bytes per raster line - BOOL rle; // TRUE if RLE file - BOOL isRGB; // TRUE if file type is RT_FORMAT_RGB - BYTE fillchar; - - FIBITMAP *dib = NULL; - BYTE *bits; // Pointer to dib data - WORD x, y; - - if(!handle) { - return NULL; - } - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - try { - // Read SUN raster header - - io->read_proc(&header, sizeof(SUNHEADER), 1, handle); - -#ifndef FREEIMAGE_BIGENDIAN - // SUN rasterfiles are big endian only - - SwapLong(&header.magic); - SwapLong(&header.width); - SwapLong(&header.height); - SwapLong(&header.depth); - SwapLong(&header.length); - SwapLong(&header.type); - SwapLong(&header.maptype); - SwapLong(&header.maplength); -#endif - - // Verify SUN identifier - - if (header.magic != RAS_MAGIC) { - throw FI_MSG_ERROR_MAGIC_NUMBER; - } - - // Allocate a new DIB - - switch(header.depth) { - case 1: - case 8: - dib = FreeImage_AllocateHeader(header_only, header.width, header.height, header.depth); - break; - - case 24: - dib = FreeImage_AllocateHeader(header_only, header.width, header.height, header.depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - break; - - case 32: - dib = FreeImage_AllocateHeader(header_only, header.width, header.height, header.depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - break; - } - - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // Check the file format - - rle = FALSE; - isRGB = FALSE; - - switch(header.type) { - case RT_OLD: - case RT_STANDARD: - case RT_FORMAT_TIFF: // I don't even know what these format are... - case RT_FORMAT_IFF: //The TIFF and IFF format types indicate that the raster - //file was originally converted from either of these file formats. - //so lets at least try to process them as RT_STANDARD - break; - - case RT_BYTE_ENCODED: - rle = TRUE; - break; - - case RT_FORMAT_RGB: - isRGB = TRUE; - break; - - default: - throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; - } - - // set up the colormap if needed - - switch(header.maptype) { - case RMT_NONE : - { - if (header.depth < 24) { - // Create linear color ramp - - RGBQUAD *pal = FreeImage_GetPalette(dib); - - int numcolors = 1 << header.depth; - - for (int i = 0; i < numcolors; i++) { - pal[i].rgbRed = (BYTE)((255 * i) / (numcolors - 1)); - pal[i].rgbGreen = (BYTE)((255 * i) / (numcolors - 1)); - pal[i].rgbBlue = (BYTE)((255 * i) / (numcolors - 1)); - } - } - - break; - } - - case RMT_EQUAL_RGB: - { - BYTE *r, *g, *b; - - // Read SUN raster colormap - - int numcolors = 1 << header.depth; - if((DWORD)(3 * numcolors) > header.maplength) { - // some RAS may have less colors than the full palette - numcolors = header.maplength / 3; - } else { - throw "Invalid palette"; - } - - r = (BYTE*)malloc(3 * numcolors * sizeof(BYTE)); - g = r + numcolors; - b = g + numcolors; - - RGBQUAD *pal = FreeImage_GetPalette(dib); - - io->read_proc(r, 3 * numcolors, 1, handle); - - for (int i = 0; i < numcolors; i++) { - pal[i].rgbRed = r[i]; - pal[i].rgbGreen = g[i]; - pal[i].rgbBlue = b[i]; - } - - free(r); - break; - } - - case RMT_RAW: - { - BYTE *colormap; - - // Read (skip) SUN raster colormap. - - colormap = (BYTE *)malloc(header.maplength * sizeof(BYTE)); - - io->read_proc(colormap, header.maplength, 1, handle); - - free(colormap); - break; - } - } - - if(header_only) { - // header only mode - return dib; - } - - // Calculate the line + pitch - // Each row is multiple of 16 bits (2 bytes). - - if (header.depth == 1) { - linelength = (WORD)((header.width / 8) + (header.width % 8 ? 1 : 0)); - } else { - linelength = (WORD)header.width; - } - - fill = (linelength % 2) ? 1 : 0; - - unsigned pitch = FreeImage_GetPitch(dib); - - // Read the image data - - switch(header.depth) { - case 1: - case 8: - { - bits = FreeImage_GetBits(dib) + (header.height - 1) * pitch; - - for (y = 0; y < header.height; y++) { - ReadData(io, handle, bits, linelength, rle); - - bits -= pitch; - - if (fill) { - ReadData(io, handle, &fillchar, fill, rle); - } - } - - break; - } - - case 24: - { - BYTE *buf, *bp; - - buf = (BYTE*)malloc(header.width * 3); - - for (y = 0; y < header.height; y++) { - bits = FreeImage_GetBits(dib) + (header.height - 1 - y) * pitch; - - ReadData(io, handle, buf, header.width * 3, rle); - - bp = buf; - - if (isRGB) { - for (x = 0; x < header.width; x++) { - bits[FI_RGBA_RED] = *(bp++); // red - bits[FI_RGBA_GREEN] = *(bp++); // green - bits[FI_RGBA_BLUE] = *(bp++); // blue - - bits += 3; - } - } else { - for (x = 0; x < header.width; x++) { - bits[FI_RGBA_RED] = *(bp + 2); // red - bits[FI_RGBA_GREEN] = *(bp + 1);// green - bits[FI_RGBA_BLUE] = *bp; // blue - - bits += 3; bp += 3; - } - } - - if (fill) { - ReadData(io, handle, &fillchar, fill, rle); - } - } - - free(buf); - break; - } - - case 32: - { - BYTE *buf, *bp; - - buf = (BYTE*)malloc(header.width * 4); - - for (y = 0; y < header.height; y++) { - bits = FreeImage_GetBits(dib) + (header.height - 1 - y) * pitch; - - ReadData(io, handle, buf, header.width * 4, rle); - - bp = buf; - - if (isRGB) { - for (x = 0; x < header.width; x++) { - bits[FI_RGBA_ALPHA] = *(bp++); // alpha - bits[FI_RGBA_RED] = *(bp++); // red - bits[FI_RGBA_GREEN] = *(bp++); // green - bits[FI_RGBA_BLUE] = *(bp++); // blue - - bits += 4; - } - } - else { - for (x = 0; x < header.width; x++) { - bits[FI_RGBA_RED] = *(bp + 3); // red - bits[FI_RGBA_GREEN] = *(bp + 2); // green - bits[FI_RGBA_BLUE] = *(bp + 1); // blue - bits[FI_RGBA_ALPHA] = *bp; // alpha - - bits += 4; - bp += 4; - } - } - - if (fill) { - ReadData(io, handle, &fillchar, fill, rle); - } - } - - free(buf); - break; - } - } - - return dib; - - } catch (const char *text) { - if(dib) { - FreeImage_Unload(dib); - } - FreeImage_OutputMessageProc(s_format_id, text); - } - - return NULL; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitRAS(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = NULL; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginRAW.cpp b/plugins/AdvaImg/src/FreeImage/PluginRAW.cpp deleted file mode 100644 index e9bd5bfa77..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginRAW.cpp +++ /dev/null @@ -1,793 +0,0 @@ -// ========================================================== -// RAW camera image loader -// -// 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 "../LibRawLite/libraw/libraw.h" - -#include "FreeImage.h" -#include "Utilities.h" -#include "../Metadata/FreeImageTag.h" - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Internal functions -// ========================================================== - -// ---------------------------------------------------------- -// FreeImage datastream wrapper -// ---------------------------------------------------------- - -class LibRaw_freeimage_datastream : public LibRaw_abstract_datastream { -private: - FreeImageIO *_io; - fi_handle _handle; - long _eof; - INT64 _fsize; - -public: - LibRaw_freeimage_datastream(FreeImageIO *io, fi_handle handle) : _io(io), _handle(handle) { - long start_pos = io->tell_proc(handle); - io->seek_proc(handle, 0, SEEK_END); - _eof = io->tell_proc(handle); - _fsize = _eof - start_pos; - io->seek_proc(handle, start_pos, SEEK_SET); - } - - ~LibRaw_freeimage_datastream() { - } - - int valid() { - return (_io && _handle); - } - - int read(void *buffer, size_t size, size_t count) { - if(substream) return substream->read(buffer, size, count); - return _io->read_proc(buffer, (unsigned)size, (unsigned)count, _handle); - } - - int seek(INT64 offset, int origin) { - if(substream) return substream->seek(offset, origin); - return _io->seek_proc(_handle, (long)offset, origin); - } - - INT64 tell() { - if(substream) return substream->tell(); - return _io->tell_proc(_handle); - } - - INT64 size() { - return _fsize; - } - - int get_char() { - int c = 0; - if(substream) return substream->get_char(); - if(!_io->read_proc(&c, 1, 1, _handle)) return -1; - return c; - } - - char* gets(char *buffer, int length) { - if (substream) return substream->gets(buffer, length); - memset(buffer, 0, length); - for(int i = 0; i < length; i++) { - if(!_io->read_proc(&buffer[i], 1, 1, _handle)) - return NULL; - if(buffer[i] == 0x0A) - break; - } - return buffer; - } - - int scanf_one(const char *fmt, void* val) { - std::string buffer; - char element = 0; - bool bDone = false; - if(substream) return substream->scanf_one(fmt,val); - do { - if(_io->read_proc(&element, 1, 1, _handle) == 1) { - switch(element) { - case '0': - case '\n': - case ' ': - case '\t': - bDone = true; - break; - default: - break; - } - buffer.append(&element, 1); - } else { - return 0; - } - } while(!bDone); - - return sscanf(buffer.c_str(), fmt, val); - } - - int eof() { - if(substream) return substream->eof(); - return (_io->tell_proc(_handle) >= _eof); - } - - void * make_jas_stream() { - return NULL; - } -}; - -// ---------------------------------------------------------- - -/** -Convert a processed raw data array to a FIBITMAP -@param RawProcessor LibRaw handle containing the processed raw image -@return Returns the converted dib if successfull, returns NULL otherwise -*/ -static FIBITMAP * -libraw_ConvertProcessedRawToDib(LibRaw *RawProcessor) { - FIBITMAP *dib = NULL; - int width, height, colors, bpp; - - try { - int bgr = 0; // pixel copy order: RGB if (bgr == 0) and BGR otherwise - - // get image info - RawProcessor->get_mem_image_format(&width, &height, &colors, &bpp); - - // only 3-color images supported... - if(colors != 3) { - throw "LibRaw : only 3-color images supported"; - } - - if(bpp == 16) { - // allocate output dib - dib = FreeImage_AllocateT(FIT_RGB16, width, height); - if(!dib) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - } else if(bpp == 8) { -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - bgr = 1; // only useful for FIT_BITMAP types -#endif - - // allocate output dib - dib = FreeImage_AllocateT(FIT_BITMAP, width, height, 24); - if(!dib) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - } - - // copy post-processed bitmap data into FIBITMAP buffer - if(RawProcessor->copy_mem_image(FreeImage_GetBits(dib), FreeImage_GetPitch(dib), bgr) != LIBRAW_SUCCESS) { - throw "LibRaw : failed to copy data into dib"; - } - - // flip vertically - FreeImage_FlipVertical(dib); - - return dib; - - } catch(const char *text) { - FreeImage_Unload(dib); - FreeImage_OutputMessageProc(s_format_id, text); - return NULL; - } -} - - -/** -Convert a processed raw image to a FIBITMAP -@param image Processed raw image -@return Returns the converted dib if successfull, returns NULL otherwise -@see libraw_LoadEmbeddedPreview -*/ -static FIBITMAP * -libraw_ConvertProcessedImageToDib(libraw_processed_image_t *image) { - FIBITMAP *dib = NULL; - - try { - unsigned width = image->width; - unsigned height = image->height; - unsigned bpp = image->bits; - if(bpp == 16) { - // allocate output dib - dib = FreeImage_AllocateT(FIT_RGB16, width, height); - if(!dib) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - // write data - WORD *raw_data = (WORD*)image->data; - for(unsigned y = 0; y < height; y++) { - FIRGB16 *output = (FIRGB16*)FreeImage_GetScanLine(dib, height - 1 - y); - for(unsigned x = 0; x < width; x++) { - output[x].red = raw_data[0]; - output[x].green = raw_data[1]; - output[x].blue = raw_data[2]; - raw_data += 3; - } - } - } else if(bpp == 8) { - // allocate output dib - dib = FreeImage_AllocateT(FIT_BITMAP, width, height, 24); - if(!dib) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - // write data - BYTE *raw_data = (BYTE*)image->data; - for(unsigned y = 0; y < height; y++) { - RGBTRIPLE *output = (RGBTRIPLE*)FreeImage_GetScanLine(dib, height - 1 - y); - for(unsigned x = 0; x < width; x++) { - output[x].rgbtRed = raw_data[0]; - output[x].rgbtGreen = raw_data[1]; - output[x].rgbtBlue = raw_data[2]; - raw_data += 3; - } - } - } - - return dib; - - } catch(const char *text) { - FreeImage_Unload(dib); - FreeImage_OutputMessageProc(s_format_id, text); - return NULL; - } -} - -/** -Get the embedded JPEG preview image from RAW picture with included Exif Data. -@param RawProcessor Libraw handle -@param flags JPEG load flags -@return Returns the loaded dib if successfull, returns NULL otherwise -*/ -static FIBITMAP * -libraw_LoadEmbeddedPreview(LibRaw *RawProcessor, int flags) { - FIBITMAP *dib = NULL; - libraw_processed_image_t *thumb_image = NULL; - - try { - // unpack data - if(RawProcessor->unpack_thumb() != LIBRAW_SUCCESS) { - // run silently "LibRaw : failed to run unpack_thumb" - return NULL; - } - - // retrieve thumb image - int error_code = 0; - thumb_image = RawProcessor->dcraw_make_mem_thumb(&error_code); - if(thumb_image) { - if(thumb_image->type != LIBRAW_IMAGE_BITMAP) { - // attach the binary data to a memory stream - FIMEMORY *hmem = FreeImage_OpenMemory((BYTE*)thumb_image->data, (DWORD)thumb_image->data_size); - // get the file type - FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem, 0); - if(fif == FIF_JPEG) { - // rotate according to Exif orientation - flags |= JPEG_EXIFROTATE; - } - // load an image from the memory stream - dib = FreeImage_LoadFromMemory(fif, hmem, flags); - // close the stream - FreeImage_CloseMemory(hmem); - } else if((flags & FIF_LOAD_NOPIXELS) != FIF_LOAD_NOPIXELS) { - // convert processed data to output dib - dib = libraw_ConvertProcessedImageToDib(thumb_image); - } - } else { - throw "LibRaw : failed to run dcraw_make_mem_thumb"; - } - - // clean-up and return - RawProcessor->dcraw_clear_mem(thumb_image); - - return dib; - - } catch(const char *text) { - // clean-up and return - if(thumb_image) { - RawProcessor->dcraw_clear_mem(thumb_image); - } - if(text != NULL) { - FreeImage_OutputMessageProc(s_format_id, text); - } - } - - return NULL; -} -/** -Load raw data and convert to FIBITMAP -@param RawProcessor Libraw handle -@param bitspersample Output bitdepth (8- or 16-bit) -@return Returns the loaded dib if successfull, returns NULL otherwise -*/ -static FIBITMAP * -libraw_LoadRawData(LibRaw *RawProcessor, int bitspersample) { - FIBITMAP *dib = NULL; - - try { - // set decoding parameters - // ----------------------- - - // (-6) 16-bit or 8-bit - RawProcessor->imgdata.params.output_bps = bitspersample; - // (-g power toe_slope) - if(bitspersample == 16) { - // set -g 1 1 for linear curve - RawProcessor->imgdata.params.gamm[0] = 1; - RawProcessor->imgdata.params.gamm[1] = 1; - } else if(bitspersample == 8) { - // by default settings for rec. BT.709 are used: power 2.222 (i.e. gamm[0]=1/2.222) and slope 4.5 - RawProcessor->imgdata.params.gamm[0] = 1/2.222; - RawProcessor->imgdata.params.gamm[1] = 4.5; - } - // (-W) Don't use automatic increase of brightness by histogram - RawProcessor->imgdata.params.no_auto_bright = 1; - // (-a) Use automatic white balance obtained after averaging over the entire image - RawProcessor->imgdata.params.use_auto_wb = 1; - // (-q 3) Adaptive homogeneity-directed demosaicing algorithm (AHD) - RawProcessor->imgdata.params.user_qual = 3; - - // ----------------------- - - // unpack data - if(RawProcessor->unpack() != LIBRAW_SUCCESS) { - throw "LibRaw : failed to unpack data"; - } - - // process data (... most consuming task ...) - if(RawProcessor->dcraw_process() != LIBRAW_SUCCESS) { - throw "LibRaw : failed to process data"; - } - - // retrieve processed image - dib = libraw_ConvertProcessedRawToDib(RawProcessor); - - return dib; - - } catch(const char *text) { - FreeImage_OutputMessageProc(s_format_id, text); - return NULL; - } -} - -/** -Load the Bayer matrix (unprocessed raw data) as a FIT_UINT16 image. -Note that some formats don't have a Bayer matrix (e.g. Foveon, Canon sRAW, demosaiced DNG files). -@param RawProcessor Libraw handle -@return Returns the loaded dib if successfull, returns NULL otherwise -*/ -static FIBITMAP * -libraw_LoadUnprocessedData(LibRaw *RawProcessor) { - FIBITMAP *dib = NULL; - - try { - // unpack data - if(RawProcessor->unpack() != LIBRAW_SUCCESS) { - throw "LibRaw : failed to unpack data"; - } - - // check for a supported Bayer format - if(!(RawProcessor->imgdata.idata.filters || RawProcessor->imgdata.idata.colors == 1)) { - throw "LibRaw : only Bayer-pattern RAW files are supported"; - } - - // allocate output dib - const unsigned width = RawProcessor->imgdata.sizes.raw_width; - const unsigned height = RawProcessor->imgdata.sizes.raw_height; - const size_t line_size = width * sizeof(WORD); - const WORD *src_bits = (WORD*)RawProcessor->imgdata.rawdata.raw_image; - - if(src_bits) { - dib = FreeImage_AllocateT(FIT_UINT16, width, height); - } - if(!dib) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // retrieve the raw image - for(unsigned y = 0; y < height; y++) { - WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dib, height - 1 - y); - memcpy(dst_bits, src_bits, line_size); - src_bits += width; - } - - // store metadata needed for post-processing - { - char value[512]; - - const libraw_image_sizes_t *sizes = &RawProcessor->imgdata.sizes; - - // image output width & height - { - sprintf(value, "%d", sizes->iwidth); - FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Output.Width", value); - - sprintf(value, "%d", sizes->iheight); - FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Output.Height", value); - } - - // image output frame - { - const unsigned f_left = sizes->left_margin; - const unsigned f_top = sizes->top_margin; - const unsigned f_width = sizes->width; - const unsigned f_height = sizes->height; - - sprintf(value, "%d", f_left); - FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Left", value); - - sprintf(value, "%d", f_top); - FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Top", value); - - sprintf(value, "%d", f_width); - FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Width", value); - - sprintf(value, "%d", f_height); - FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Height", value); - } - - // Bayer pattern - // Mask describing the order of color pixels in the matrix. - // This field describe 16 pixels (8 rows with two pixels in each, from left to right and from top to bottom). - - if(RawProcessor->imgdata.idata.filters) { - // description of colors numbered from 0 to 3 (RGBG,RGBE,GMCY, or GBTG) - char *cdesc = RawProcessor->imgdata.idata.cdesc; - if(!cdesc[3]) { - cdesc[3] = 'G'; - } - char *pattern = &value[0]; - for(int i = 0; i < 16; i++) { - pattern[i] = cdesc[ RawProcessor->fcol(i >> 1, i & 1) ]; - } - pattern[16] = 0; - - FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.BayerPattern", value); - } - } - - return dib; - - } catch(const char *text) { - FreeImage_Unload(dib); - FreeImage_OutputMessageProc(s_format_id, text); - return NULL; - } -} - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "RAW"; -} - -static const char * DLL_CALLCONV -Description() { - return "RAW camera image"; -} - -static const char * DLL_CALLCONV -Extension() { - /** - Below are known RAW file extensions that you can check using FreeImage_GetFIFFromFormat. - If a file extension is not listed, that doesn't mean that you cannot load it. - Using FreeImage_GetFileType is the best way to know if a RAW file format is supported. - */ - static const char *raw_extensions = - "3fr," // Hasselblad Digital Camera Raw Image Format. - "arw," // Sony Digital Camera Raw Image Format for Alpha devices. - "bay," // Casio Digital Camera Raw File Format. - "bmq," // NuCore Raw Image File. - "cap," // Phase One Digital Camera Raw Image Format. - "cine," // Phantom Software Raw Image File. - "cr2," // Canon Digital Camera RAW Image Format version 2.0. These images are based on the TIFF image standard. - "crw," // Canon Digital Camera RAW Image Format version 1.0. - "cs1," // Sinar Capture Shop Raw Image File. - "dc2," // Kodak DC25 Digital Camera File. - "dcr," // Kodak Digital Camera Raw Image Format for these models: Kodak DSC Pro SLR/c, Kodak DSC Pro SLR/n, Kodak DSC Pro 14N, Kodak DSC PRO 14nx. - "drf," // Kodak Digital Camera Raw Image Format. - "dsc," // Kodak Digital Camera Raw Image Format. - "dng," // Adobe Digital Negative: DNG is publicly available archival format for the raw files generated by digital cameras. By addressing the lack of an open standard for the raw files created by individual camera models, DNG helps ensure that photographers will be able to access their files in the future. - "erf," // Epson Digital Camera Raw Image Format. - "fff," // Imacon Digital Camera Raw Image Format. - "ia," // Sinar Raw Image File. - "iiq," // Phase One Digital Camera Raw Image Format. - "k25," // Kodak DC25 Digital Camera Raw Image Format. - "kc2," // Kodak DCS200 Digital Camera Raw Image Format. - "kdc," // Kodak Digital Camera Raw Image Format. - "mdc," // Minolta RD175 Digital Camera Raw Image Format. - "mef," // Mamiya Digital Camera Raw Image Format. - "mos," // Leaf Raw Image File. - "mrw," // Minolta Dimage Digital Camera Raw Image Format. - "nef," // Nikon Digital Camera Raw Image Format. - "nrw," // Nikon Digital Camera Raw Image Format. - "orf," // Olympus Digital Camera Raw Image Format. - "pef," // Pentax Digital Camera Raw Image Format. - "ptx," // Pentax Digital Camera Raw Image Format. - "pxn," // Logitech Digital Camera Raw Image Format. - "qtk," // Apple Quicktake 100/150 Digital Camera Raw Image Format. - "raf," // Fuji Digital Camera Raw Image Format. - "raw," // Panasonic Digital Camera Image Format. - "rdc," // Digital Foto Maker Raw Image File. - "rw2," // Panasonic LX3 Digital Camera Raw Image Format. - "rwl," // Leica Camera Raw Image Format. - "rwz," // Rawzor Digital Camera Raw Image Format. - "sr2," // Sony Digital Camera Raw Image Format. - "srf," // Sony Digital Camera Raw Image Format for DSC-F828 8 megapixel digital camera or Sony DSC-R1. - "srw," // Samsung Raw Image Format. - "sti," // Sinar Capture Shop Raw Image File. - "x3f"; // Sigma Digital Camera Raw Image Format for devices based on Foveon X3 direct image sensor. - return raw_extensions; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-dcraw"; -} - -static BOOL -HasMagicHeader(FreeImageIO *io, fi_handle handle) { - const unsigned signature_size = 32; - BYTE signature[signature_size] = { 0 }; - /* - note: classic TIFF signature is - { 0x49, 0x49, 0x2A, 0x00 } Classic TIFF, little-endian - { 0x4D, 0x4D, 0x00, 0x2A } Classic TIFF, big-endian - */ - // Canon (CR2), little-endian byte order - const BYTE CR2_II[] = { 0x49, 0x49, 0x2A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x43, 0x52, 0x02, 0x00 }; - // Canon (CRW), little-endian byte order - const BYTE CRW_II[] = { 0x49, 0x49, 0x1A, 0x00, 0x00, 0x00, 0x48, 0x45, 0x41, 0x50, 0x43, 0x43, 0x44, 0x52, 0x02, 0x00 }; - // Minolta (MRW) - const BYTE MRW[] = { 0x00, 0x4D, 0x52, 0x4D, 0x00 }; - // Olympus (ORF), little-endian byte order - const BYTE ORF_IIRS[] = { 0x49, 0x49, 0x52, 0x53, 0x08, 0x00, 0x00, 0x00 }; - const BYTE ORF_IIRO[] = { 0x49, 0x49, 0x52, 0x4F, 0x08, 0x00, 0x00, 0x00 }; - // Olympus (ORF), big-endian byte order - const BYTE ORF_MMOR[] = { 0x4D, 0x4D, 0x4F, 0x52, 0x00, 0x00, 0x00, 0x08 }; - // Fujifilm (RAF) - const BYTE RAF[] = { 0x46, 0x55, 0x4A, 0x49, 0x46, 0x49, 0x4C, 0x4D, 0x43, 0x43, 0x44, 0x2D, 0x52, 0x41, 0x57, 0x20 }; - // Panasonic (RW2) or Leica (RWL), little-endian byte order - const BYTE RWx_II[] = { 0x49, 0x49, 0x55, 0x00, 0x18, 0x00, 0x00, 0x00, 0x88, 0xE7, 0x74, 0xD8, 0xF8, 0x25, 0x1D, 0x4D, 0x94, 0x7A, 0x6E, 0x77, 0x82, 0x2B, 0x5D, 0x6A }; - // Panasonic (RAW) or Leica (RAW), little-endian byte order - const BYTE RAW_II[] = { 0x49, 0x49, 0x55, 0x00, 0x08, 0x00, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00 }; - // Foveon (X3F) - const BYTE X3F[] = { 0x46, 0x4F, 0x56, 0x62 }; - - if(io->read_proc(signature, 1, signature_size, handle) != signature_size) { - return FALSE; - } - if(memcmp(CR2_II, signature, 12) == 0) - return TRUE; - if(memcmp(CRW_II, signature, 16) == 0) - return TRUE; - if(memcmp(MRW, signature, 5) == 0) - return TRUE; - if(memcmp(ORF_IIRS, signature, 8) == 0) - return TRUE; - if(memcmp(ORF_IIRO, signature, 8) == 0) - return TRUE; - if(memcmp(ORF_MMOR, signature, 8) == 0) - return TRUE; - if(memcmp(RAF, signature, 16) == 0) - return TRUE; - if(memcmp(RWx_II, signature, 24) == 0) - return TRUE; - if(memcmp(RAW_II, signature, 18) == 0) - return TRUE; - if(memcmp(X3F, signature, 4) == 0) - return TRUE; - - return FALSE; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - // some RAW files have a magic signature (most of them have a TIFF signature) - // try to check this in order to speed up the file identification - { - long tell = io->tell_proc(handle); - if( HasMagicHeader(io, handle) ) { - return TRUE; - } else { - io->seek_proc(handle, tell, SEEK_SET); - } - } - - // no magic signature : we need to open the file (it will take more time to identify it) - // do not declare RawProcessor on the stack as it may be huge (300 KB) - { - LibRaw *RawProcessor = new(std::nothrow) LibRaw; - - if(RawProcessor) { - BOOL bSuccess = TRUE; - - // wrap the input datastream - LibRaw_freeimage_datastream datastream(io, handle); - - // open the datastream - if(RawProcessor->open_datastream(&datastream) != LIBRAW_SUCCESS) { - bSuccess = FALSE; // LibRaw : failed to open input stream (unknown format) - } - - // clean-up internal memory allocations - RawProcessor->recycle(); - delete RawProcessor; - - return bSuccess; - } - } - - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsICCProfiles() { - return TRUE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - FIBITMAP *dib = NULL; - LibRaw *RawProcessor = NULL; - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - try { - // do not declare RawProcessor on the stack as it may be huge (300 KB) - RawProcessor = new(std::nothrow) LibRaw; - if(!RawProcessor) { - throw FI_MSG_ERROR_MEMORY; - } - - // wrap the input datastream - LibRaw_freeimage_datastream datastream(io, handle); - - // set decoding parameters - // the following parameters affect data reading - // -------------------------------------------- - - // (-s [0..N-1]) Select one raw image from input file - RawProcessor->imgdata.params.shot_select = 0; - // (-w) Use camera white balance, if possible (otherwise, fallback to auto_wb) - RawProcessor->imgdata.params.use_camera_wb = 1; - // (-M) Use any color matrix from the camera metadata. This option only affects Olympus, Leaf, and Phase One cameras. - RawProcessor->imgdata.params.use_camera_matrix = 1; - // (-h) outputs the image in 50% size - RawProcessor->imgdata.params.half_size = ((flags & RAW_HALFSIZE) == RAW_HALFSIZE) ? 1 : 0; - - // open the datastream - if(RawProcessor->open_datastream(&datastream) != LIBRAW_SUCCESS) { - throw "LibRaw : failed to open input stream (unknown format)"; - } - - if(header_only) { - // header only mode - dib = FreeImage_AllocateHeaderT(header_only, FIT_RGB16, RawProcessor->imgdata.sizes.width, RawProcessor->imgdata.sizes.height); - } - else if((flags & RAW_UNPROCESSED) == RAW_UNPROCESSED) { - // load raw data without post-processing (i.e. as a Bayer matrix) - dib = libraw_LoadUnprocessedData(RawProcessor); - } - else if((flags & RAW_PREVIEW) == RAW_PREVIEW) { - // try to get the embedded JPEG - dib = libraw_LoadEmbeddedPreview(RawProcessor, 0); - if(!dib) { - // no JPEG preview: try to load as 8-bit/sample (i.e. RGB 24-bit) - dib = libraw_LoadRawData(RawProcessor, 8); - } - } - else if((flags & RAW_DISPLAY) == RAW_DISPLAY) { - // load raw data as 8-bit/sample (i.e. RGB 24-bit) - dib = libraw_LoadRawData(RawProcessor, 8); - } - else { - // default: load raw data as linear 16-bit/sample (i.e. RGB 48-bit) - dib = libraw_LoadRawData(RawProcessor, 16); - } - - // save ICC profile if present - if(dib && (NULL != RawProcessor->imgdata.color.profile)) { - FreeImage_CreateICCProfile(dib, RawProcessor->imgdata.color.profile, RawProcessor->imgdata.color.profile_length); - } - - // try to get JPEG embedded Exif metadata - if(dib && !((flags & RAW_PREVIEW) == RAW_PREVIEW)) { - FIBITMAP *metadata_dib = libraw_LoadEmbeddedPreview(RawProcessor, FIF_LOAD_NOPIXELS); - if(metadata_dib) { - FreeImage_CloneMetadata(dib, metadata_dib); - FreeImage_Unload(metadata_dib); - } - } - - // clean-up internal memory allocations - RawProcessor->recycle(); - delete RawProcessor; - - return dib; - - } catch(const char *text) { - if(RawProcessor) { - RawProcessor->recycle(); - delete RawProcessor; - } - if(dib) { - FreeImage_Unload(dib); - } - FreeImage_OutputMessageProc(s_format_id, text); - } - - return NULL; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitRAW(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = NULL; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = SupportsICCProfiles; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginSGI.cpp b/plugins/AdvaImg/src/FreeImage/PluginSGI.cpp deleted file mode 100644 index 35fd2ec611..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginSGI.cpp +++ /dev/null @@ -1,425 +0,0 @@ -// ========================================================== -// SGI Loader -// -// Design and implementation by -// - Sherman Wilcox -// - Noam Gat -// -// References : -// ------------ -// - The SGI Image File Format, Version 1.0 -// http://astronomy.swin.edu.au/~pbourke/dataformats/sgirgb/sgiversion.html -// - SGI RGB Image Format -// http://astronomy.swin.edu.au/~pbourke/dataformats/sgirgb/ -// -// -// 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" - -// ---------------------------------------------------------- -// Constants + headers -// ---------------------------------------------------------- - -#ifdef _WIN32 -#pragma pack(push, 1) -#else -#pragma pack(1) -#endif - -typedef struct tagSGIHeader { - /** IRIS image file magic number. This should be decimal 474. */ - WORD magic; - /** Storage format: 0 for uncompressed, 1 for RLE compression. */ - BYTE storage; - /** Number of bytes per pixel channel. Legally 1 or 2. */ - BYTE bpc; - /** - Number of dimensions. Legally 1, 2, or 3. - 1 means a single row, XSIZE long - 2 means a single 2D image - 3 means multiple 2D images - */ - WORD dimension; - /** X size in pixels */ - WORD xsize; - /** Y size in pixels */ - WORD ysize; - /** - Number of channels. - 1 indicates greyscale - 3 indicates RGB - 4 indicates RGB and Alpha - */ - WORD zsize; - /** Minimum pixel value. This is the lowest pixel value in the image.*/ - LONG pixmin; - /** Maximum pixel value. This is the highest pixel value in the image.*/ - LONG pixmax; - /** Ignored. Normally set to 0. */ - char dummy[4]; - /** Image name. Must be null terminated, therefore at most 79 bytes. */ - char imagename[80]; - /** - Colormap ID. - 0 - normal mode - 1 - dithered, 3 mits for red and green, 2 for blue, obsolete - 2 - index colour, obsolete - 3 - not an image but a colourmap - */ - LONG colormap; - /** Ignored. Should be set to 0, makes the header 512 bytes. */ - char reserved[404]; -} SGIHeader; - -typedef struct tagRLEStatus { - int cnt; - int val; -} RLEStatus; - -#ifdef _WIN32 -#pragma pack(pop) -#else -#pragma pack() -#endif - -static const char *SGI_LESS_THAN_HEADER_LENGTH = "Incorrect header size"; -static const char *SGI_16_BIT_COMPONENTS_NOT_SUPPORTED = "No 16 bit support"; -static const char *SGI_COLORMAPS_NOT_SUPPORTED = "No colormap support"; -static const char *SGI_EOF_IN_RLE_INDEX = "EOF in run length encoding"; -static const char *SGI_EOF_IN_IMAGE_DATA = "EOF in image data"; -static const char *SGI_INVALID_CHANNEL_COUNT = "Invalid channel count"; - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -#ifndef FREEIMAGE_BIGENDIAN -static void -SwapHeader(SGIHeader *header) { - SwapShort(&header->magic); - SwapShort(&header->dimension); - SwapShort(&header->xsize); - SwapShort(&header->ysize); - SwapShort(&header->zsize); - SwapLong((DWORD*)&header->pixmin); - SwapLong((DWORD*)&header->pixmax); - SwapLong((DWORD*)&header->colormap); -} -#endif - -static int -get_rlechar(FreeImageIO *io, fi_handle handle, RLEStatus *pstatus) { - if (!pstatus->cnt) { - int cnt = 0; - while (0 == cnt) { - BYTE packed = 0; - if(io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1) { - return EOF; - } - cnt = packed; - } - if (cnt == EOF) { - return EOF; - } - pstatus->cnt = cnt & 0x7F; - if (cnt & 0x80) { - pstatus->val = -1; - } else { - BYTE packed = 0; - if(io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1) { - return EOF; - } - pstatus->val = packed; - } - } - pstatus->cnt--; - if (pstatus->val == -1) { - BYTE packed = 0; - if(io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1) { - return EOF; - } - return packed; - } - else { - return pstatus->val; - } -} - -static const char * DLL_CALLCONV -Format() { - return "SGI"; -} - -static const char * DLL_CALLCONV -Description() { - return "SGI Image Format"; -} - -static const char * DLL_CALLCONV -Extension() { - return "sgi,rgb,rgba,bw"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-sgi"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE sgi_signature[2] = { 0x01, 0xDA }; - BYTE signature[2] = { 0, 0 }; - - io->read_proc(signature, 1, sizeof(sgi_signature), handle); - - return (memcmp(sgi_signature, signature, sizeof(sgi_signature)) == 0); -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return FALSE; -} - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - int width = 0, height = 0, zsize = 0; - int i, dim; - int bitcount; - SGIHeader sgiHeader; - RLEStatus my_rle_status; - FIBITMAP *dib = NULL; - LONG *pRowIndex = NULL; - - try { - // read the header - memset(&sgiHeader, 0, sizeof(SGIHeader)); - if(io->read_proc(&sgiHeader, 1, sizeof(SGIHeader), handle) < sizeof(SGIHeader)) { - throw SGI_LESS_THAN_HEADER_LENGTH; - } -#ifndef FREEIMAGE_BIGENDIAN - SwapHeader(&sgiHeader); -#endif - if(sgiHeader.magic != 474) { - throw FI_MSG_ERROR_MAGIC_NUMBER; - } - - BOOL bIsRLE = (sgiHeader.storage == 1) ? TRUE : FALSE; - - // check for unsupported image types - if (sgiHeader.bpc != 1) { - // Expected one byte per color component - throw SGI_16_BIT_COMPONENTS_NOT_SUPPORTED; - } - if (sgiHeader.colormap != 0) { - // Indexed or dithered images not supported - throw SGI_COLORMAPS_NOT_SUPPORTED; - } - - // get the width & height - dim = sgiHeader.dimension; - width = sgiHeader.xsize; - if (dim < 3) { - zsize = 1; - } else { - zsize = sgiHeader.zsize; - } - - if (dim < 2) { - height = 1; - } else { - height = sgiHeader.ysize; - } - - if(bIsRLE) { - // read the Offset Tables - int index_len = height * zsize; - pRowIndex = (LONG*)malloc(index_len * sizeof(LONG)); - if(!pRowIndex) { - throw FI_MSG_ERROR_MEMORY; - } - - if ((unsigned)index_len != io->read_proc(pRowIndex, sizeof(LONG), index_len, handle)) { - throw SGI_EOF_IN_RLE_INDEX; - } - -#ifndef FREEIMAGE_BIGENDIAN - // Fix byte order in index - for (i = 0; i < index_len; i++) { - SwapLong((DWORD*)&pRowIndex[i]); - } -#endif - // Discard row size index - for (i = 0; i < (int)(index_len * sizeof(LONG)); i++) { - BYTE packed = 0; - if( io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1 ) { - throw SGI_EOF_IN_RLE_INDEX; - } - } - } - - switch(zsize) { - case 1: - bitcount = 8; - break; - case 2: - //Grayscale+Alpha. Need to fake RGBA - bitcount = 32; - break; - case 3: - bitcount = 24; - break; - case 4: - bitcount = 32; - break; - default: - throw SGI_INVALID_CHANNEL_COUNT; - } - - dib = FreeImage_Allocate(width, height, bitcount); - if(!dib) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - if (bitcount == 8) { - // 8-bit SGI files are grayscale images, so we'll generate - // a grayscale palette. - RGBQUAD *pclrs = FreeImage_GetPalette(dib); - for (i = 0; i < 256; i++) { - pclrs[i].rgbRed = (BYTE)i; - pclrs[i].rgbGreen = (BYTE)i; - pclrs[i].rgbBlue = (BYTE)i; - pclrs[i].rgbReserved = 0; - } - } - - // decode the image - - memset(&my_rle_status, 0, sizeof(RLEStatus)); - - int ns = FreeImage_GetPitch(dib); - BYTE *pStartRow = FreeImage_GetScanLine(dib, 0); - int offset_table[] = { 2, 1, 0, 3 }; - int numChannels = zsize; - if (zsize < 3) { - offset_table[0] = 0; - } - if (zsize == 2) - { - //This is how faked grayscale+alpha works. - //First channel goes into first - //second channel goes into alpha (4th channel) - //Two channels are left empty and will be copied later - offset_table[1] = 3; - numChannels = 4; - } - - LONG *pri = pRowIndex; - for (i = 0; i < zsize; i++) { - BYTE *pRow = pStartRow + offset_table[i]; - for (int j = 0; j < height; j++, pRow += ns, pri++) { - BYTE *p = pRow; - if (bIsRLE) { - my_rle_status.cnt = 0; - io->seek_proc(handle, *pri, SEEK_SET); - } - for (int k = 0; k < width; k++, p += numChannels) { - int ch; - BYTE packed = 0; - if (bIsRLE) { - ch = get_rlechar(io, handle, &my_rle_status); - packed = (BYTE)ch; - } - else { - ch = io->read_proc(&packed, sizeof(BYTE), 1, handle); - } - if (ch == EOF) { - throw SGI_EOF_IN_IMAGE_DATA; - } - *p = packed; - } - } - } - - if (zsize == 2) - { - BYTE *pRow = pStartRow; - //If faking RGBA from grayscale + alpha, copy first channel to second and third - for (int i=0; i<height; i++, pRow += ns) - { - BYTE *pPixel = pRow; - for (int j=0; j<width; j++) - { - pPixel[2] = pPixel[1] = pPixel[0]; - pPixel += 4; - } - } - } - if(pRowIndex) - free(pRowIndex); - - return dib; - - } catch(const char *text) { - if(pRowIndex) free(pRowIndex); - if(dib) FreeImage_Unload(dib); - FreeImage_OutputMessageProc(s_format_id, text); - return NULL; - } -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitSGI(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = NULL; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; -} - diff --git a/plugins/AdvaImg/src/FreeImage/PluginTARGA.cpp b/plugins/AdvaImg/src/FreeImage/PluginTARGA.cpp deleted file mode 100644 index 84864308e0..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginTARGA.cpp +++ /dev/null @@ -1,1591 +0,0 @@ -// ========================================================== -// TARGA Loader and Writer -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Jani Kajala (janik@remedy.fi) -// - Martin Weber (martweb@gmx.net) -// - Machiel ten Brinke (brinkem@uni-one.nl) -// - Peter Lemmens (peter.lemmens@planetinternet.be) -// - HervĂŠ Drolon (drolon@infonie.fr) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// 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" - -// ---------------------------------------------------------- -// Constants + headers -// ---------------------------------------------------------- - -#ifdef _WIN32 -#pragma pack(push, 1) -#else -#pragma pack(1) -#endif - -typedef struct tagTGAHEADER { - BYTE id_length; //! length of the image ID field - BYTE color_map_type; //! whether a color map is included - BYTE image_type; //! compression and color types - - WORD cm_first_entry; //! first entry index (offset into the color map table) - WORD cm_length; //! color map length (number of entries) - BYTE cm_size; //! color map entry size, in bits (number of bits per pixel) - - WORD is_xorigin; //! X-origin of image (absolute coordinate of lower-left corner for displays where origin is at the lower left) - WORD is_yorigin; //! Y-origin of image (as for X-origin) - WORD is_width; //! image width - WORD is_height; //! image height - BYTE is_pixel_depth; //! bits per pixel - BYTE is_image_descriptor; //! image descriptor, bits 3-0 give the alpha channel depth, bits 5-4 give direction -} TGAHEADER; - -typedef struct tagTGAEXTENSIONAREA { - WORD extension_size; // Size in bytes of the extension area, always 495 - char author_name[41]; // Name of the author. If not used, bytes should be set to NULL (\0) or spaces - char author_comments[324]; // A comment, organized as four lines, each consisting of 80 characters plus a NULL - WORD datetime_stamp[6]; // Date and time at which the image was created - char job_name[41]; // Job ID - WORD job_time[3]; // Hours, minutes and seconds spent creating the file (for billing, etc.) - char software_id[41]; // The application that created the file - BYTE software_version[3]; - DWORD key_color; - WORD pixel_aspect_ratio[2]; - WORD gamma_value[2]; - DWORD color_correction_offset; // Number of bytes from the beginning of the file to the color correction table if present - DWORD postage_stamp_offset; // Number of bytes from the beginning of the file to the postage stamp image if present - DWORD scan_line_offset; // Number of bytes from the beginning of the file to the scan lines table if present - BYTE attributes_type; // Specifies the alpha channel -} TGAEXTENSIONAREA; - -typedef struct tagTGAFOOTER { - DWORD extension_offset; // extension area offset : offset in bytes from the beginning of the file - DWORD developer_offset; // developer directory offset : offset in bytes from the beginning of the file - char signature[18]; // signature string : contains "TRUEVISION-XFILE.\0" -} TGAFOOTER; - -#ifdef _WIN32 -#pragma pack(pop) -#else -#pragma pack() -#endif - -static const char *FI_MSG_ERROR_CORRUPTED = "Image data corrupted"; - -// ---------------------------------------------------------- -// Image type -// -#define TGA_NULL 0 // no image data included -#define TGA_CMAP 1 // uncompressed, color-mapped image -#define TGA_RGB 2 // uncompressed, true-color image -#define TGA_MONO 3 // uncompressed, black-and-white image -#define TGA_RLECMAP 9 // run-length encoded, color-mapped image -#define TGA_RLERGB 10 // run-length encoded, true-color image -#define TGA_RLEMONO 11 // run-length encoded, black-and-white image -#define TGA_CMPCMAP 32 // compressed (Huffman/Delta/RLE) color-mapped image (e.g., VDA/D) - Obsolete -#define TGA_CMPCMAP4 33 // compressed (Huffman/Delta/RLE) color-mapped four pass image (e.g., VDA/D) - Obsolete - -// ========================================================== -// Thumbnail functions -// ========================================================== - -class TargaThumbnail -{ -public: - TargaThumbnail() : _w(0), _h(0), _depth(0), _data(NULL) { - } - ~TargaThumbnail() { - if(_data) { - free(_data); - } - } - - BOOL isNull() const { - return (_data == NULL); - } - - BOOL read(FreeImageIO *io, fi_handle handle, size_t size) { - io->read_proc(&_w, 1, 1, handle); - io->read_proc(&_h, 1, 1, handle); - - const size_t sizeofData = size - 2; - _data = (BYTE*)malloc(sizeofData); - if(_data) { - return (io->read_proc(_data, 1, (unsigned)sizeofData, handle) == sizeofData); - } - return FALSE; - } - - void setDepth(BYTE dp) { - _depth = dp; - } - - FIBITMAP* toFIBITMAP(); - -private: - BYTE _w; - BYTE _h; - BYTE _depth; - BYTE* _data; -}; - -#ifdef FREEIMAGE_BIGENDIAN -static void -swapShortPixels(FIBITMAP* dib) { - if(FreeImage_GetImageType(dib) != FIT_BITMAP) { - return; - } - - const unsigned Bpp = FreeImage_GetBPP(dib)/8; - if(Bpp != 2) { - return; - } - - BYTE* bits = FreeImage_GetBits(dib); - const unsigned height = FreeImage_GetHeight(dib); - const unsigned pitch = FreeImage_GetPitch(dib); - - BYTE* line = bits; - for(unsigned y = 0; y < height; y++, line += pitch) { - for(BYTE* pixel = line; pixel < line + pitch ; pixel += Bpp) { - SwapShort((WORD*)pixel); - } - } -} -#endif // FREEIMAGE_BIGENDIAN - -FIBITMAP* TargaThumbnail::toFIBITMAP() { - if(isNull() || _depth == 0) { - return NULL; - } - - const unsigned line_size = _depth * _w / 8; - FIBITMAP* dib = FreeImage_Allocate(_w, _h, _depth); - if(!dib) { - return NULL; - } - - const BYTE* line = _data; - const BYTE height = _h; - for (BYTE h = 0; h < height; ++h, line += line_size) { - BYTE* dst_line = FreeImage_GetScanLine(dib, height - 1 - h); - memcpy(dst_line, line, line_size); - } - -#ifdef FREEIMAGE_BIGENDIAN - swapShortPixels(dib); -#endif - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - SwapRedBlue32(dib); -#endif - - return dib; -} -// ========================================================== -// Internal functions -// ========================================================== - -/** This class is used when loading RLE compressed images, it implements io cache of fixed size. - In general RLE compressed images *should* be compressed line by line with line sizes stored in Scan Line Table section. - In reality, however there are images not obeying the specification, compressing image data continuously across lines, - making it impossible to load the file cached at every line. -*/ -class IOCache -{ -public: - IOCache(FreeImageIO *io, fi_handle handle, size_t size) : - _ptr(NULL), _begin(NULL), _end(NULL), _size(size), _io(io), _handle(handle) { - _begin = (BYTE*)malloc(size); - if (_begin) { - _end = _begin + _size; - _ptr = _end; // will force refill on first access - } - } - - ~IOCache() { - if (_begin != NULL) { - free(_begin); - } - } - - BOOL isNull() { return _begin == NULL;} - - inline - BYTE getByte() { - if (_ptr >= _end) { - // need refill - _ptr = _begin; - _io->read_proc(_ptr, sizeof(BYTE), (unsigned)_size, _handle); //### EOF - no problem? - } - - BYTE result = *_ptr; - - _ptr++; - - return result; - } - - inline - BYTE* getBytes(size_t count /*must be < _size!*/) { - if (_ptr + count >= _end) { - - // need refill - - // 'count' bytes might span two cache bounds, - // SEEK back to add the remains of the current cache again into the new one - - long read = long(_ptr - _begin); - long remaining = long(_size - read); - - _io->seek_proc(_handle, -remaining, SEEK_CUR); - - _ptr = _begin; - _io->read_proc(_ptr, sizeof(BYTE), (unsigned)_size, _handle); //### EOF - no problem? - } - - BYTE *result = _ptr; - - _ptr += count; - - return result; - } - -private: - IOCache& operator=(const IOCache& src); // deleted - IOCache(const IOCache& other); // deleted - -private: - BYTE *_ptr; - BYTE *_begin; - BYTE *_end; - const size_t _size; - const FreeImageIO *_io; - const fi_handle _handle; -}; - -#ifdef FREEIMAGE_BIGENDIAN -static void -SwapHeader(TGAHEADER *header) { - SwapShort(&header->cm_first_entry); - SwapShort(&header->cm_length); - SwapShort(&header->is_xorigin); - SwapShort(&header->is_yorigin); - SwapShort(&header->is_width); - SwapShort(&header->is_height); -} - -static void -SwapExtensionArea(TGAEXTENSIONAREA *ex) { - SwapShort(&ex->extension_size); - SwapShort(&ex->datetime_stamp[0]); - SwapShort(&ex->datetime_stamp[1]); - SwapShort(&ex->datetime_stamp[2]); - SwapShort(&ex->datetime_stamp[3]); - SwapShort(&ex->datetime_stamp[4]); - SwapShort(&ex->datetime_stamp[5]); - SwapShort(&ex->job_time[0]); - SwapShort(&ex->job_time[1]); - SwapShort(&ex->job_time[2]); - SwapLong (&ex->key_color); - SwapShort(&ex->pixel_aspect_ratio[0]); - SwapShort(&ex->pixel_aspect_ratio[1]); - SwapShort(&ex->gamma_value[0]); - SwapShort(&ex->gamma_value[1]); - SwapLong (&ex->color_correction_offset); - SwapLong (&ex->postage_stamp_offset); - SwapLong (&ex->scan_line_offset); -} - -static void -SwapFooter(TGAFOOTER *footer) { - SwapLong(&footer->extension_offset); - SwapLong(&footer->developer_offset); -} - -#endif // FREEIMAGE_BIGENDIAN - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "TARGA"; -} - -static const char * DLL_CALLCONV -Description() { - return "Truevision Targa"; -} - -static const char * DLL_CALLCONV -Extension() { - return "tga,targa"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-tga"; -} - -static BOOL -isTARGA20(FreeImageIO *io, fi_handle handle) { - const unsigned sizeofSig = 18; - BYTE signature[sizeofSig]; - // tga_signature = "TRUEVISION-XFILE." (TGA 2.0 only) - BYTE tga_signature[sizeofSig] = { 84, 82, 85, 69, 86, 73, 83, 73, 79, 78, 45, 88, 70, 73, 76, 69, 46, 0 }; - // get the start offset - const long start_offset = io->tell_proc(handle); - // get the end-of-file - io->seek_proc(handle, 0, SEEK_END); - const long eof = io->tell_proc(handle); - // read the signature - io->seek_proc(handle, start_offset + eof - sizeofSig, SEEK_SET); - io->read_proc(&signature, 1, sizeofSig, handle); - // rewind - io->seek_proc(handle, start_offset, SEEK_SET); - - return (memcmp(tga_signature, signature, sizeofSig) == 0); -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - if(isTARGA20(io, handle)) { - return TRUE; - } - - // not a 2.0 image, try testing if it's a valid TGA anyway (not robust) - { - const long start_offset = io->tell_proc(handle); - - // get the header - TGAHEADER header; - io->read_proc(&header, sizeof(tagTGAHEADER), 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapHeader(&header); -#endif - // rewind - io->seek_proc(handle, start_offset, SEEK_SET); - - // the color map type should be a 0 or a 1... - if(header.color_map_type != 0 && header.color_map_type != 1) { - return FALSE; - } - // if the color map type is 1 then we validate the map entry information... - if(header.color_map_type > 0) { - // it doesn't make any sense if the first entry is larger than the color map table - if(header.cm_first_entry >= header.cm_length) { - return FALSE; - } - // check header.cm_size, don't allow 0 or anything bigger than 32 - if(header.cm_size == 0 || header.cm_size > 32) { - return FALSE; - } - } - // the width/height shouldn't be 0, right ? - if(header.is_width == 0 || header.is_height == 0) { - return FALSE; - } - // let's now verify all the types that are supported by FreeImage (this is our final verification) - switch(header.image_type) { - case TGA_CMAP: - case TGA_RGB: - case TGA_MONO: - case TGA_RLECMAP: - case TGA_RLERGB: - case TGA_RLEMONO: - switch(header.is_pixel_depth) { - case 8 : - case 16: - case 24: - case 32: - return TRUE; - default: - return FALSE; - } - break; - default: - return FALSE; - } - } -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return ( - (depth == 8) || - (depth == 16) || - (depth == 24) || - (depth == 32) - ); -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return (type == FIT_BITMAP) ? TRUE : FALSE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -/** -Used for all 32 and 24 bit loading of uncompressed images -*/ -static void -loadTrueColor(FIBITMAP* dib, int width, int height, int file_pixel_size, FreeImageIO* io, fi_handle handle, BOOL as24bit) { - const int pixel_size = as24bit ? 3 : file_pixel_size; - - // input line cache - BYTE* file_line = (BYTE*)malloc( width * file_pixel_size); - - if (!file_line) { - throw FI_MSG_ERROR_MEMORY; - } - - for (int y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - io->read_proc(file_line, file_pixel_size, width, handle); - BYTE *bgra = file_line; - - for (int x = 0; x < width; x++) { - - bits[FI_RGBA_BLUE] = bgra[0]; - bits[FI_RGBA_GREEN] = bgra[1]; - bits[FI_RGBA_RED] = bgra[2]; - - if (!as24bit) { - bits[FI_RGBA_ALPHA] = bgra[3]; - } - - bgra += file_pixel_size; - - bits += pixel_size; - } - } - - free(file_line); -} - -/** -For the generic RLE loader we need to abstract away the pixel format. -We use a specific overload based on bits-per-pixel for each type of pixel -*/ - -template <int nBITS> -inline static void -_assignPixel(BYTE* bits, BYTE* val, BOOL as24bit = FALSE) { - // static assert should go here - assert(FALSE); -} - -template <> -inline void -_assignPixel<8>(BYTE* bits, BYTE* val, BOOL as24bit) { - *bits = *val; -} - -template <> -inline void -_assignPixel<16>(BYTE* bits, BYTE* val, BOOL as24bit) { - WORD value(*reinterpret_cast<WORD*>(val)); - -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&value); -#endif - - if (as24bit) { - bits[FI_RGBA_BLUE] = (BYTE)((((value & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F); - bits[FI_RGBA_GREEN] = (BYTE)((((value & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F); - bits[FI_RGBA_RED] = (BYTE)((((value & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F); - - } else { - *reinterpret_cast<WORD *>(bits) = 0x7FFF & value; - } -} - -template <> -inline void -_assignPixel<24>(BYTE* bits, BYTE* val, BOOL as24bit) { - bits[FI_RGBA_BLUE] = val[0]; - bits[FI_RGBA_GREEN] = val[1]; - bits[FI_RGBA_RED] = val[2]; -} - -template <> -inline void -_assignPixel<32>(BYTE* bits, BYTE* val, BOOL as24bit) { - if (as24bit) { - _assignPixel<24>(bits, val, TRUE); - - } else { -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - *(reinterpret_cast<unsigned*>(bits)) = *(reinterpret_cast<unsigned*> (val)); -#else // NOTE This is faster then doing reinterpret_cast to int + INPLACESWAP ! - bits[FI_RGBA_BLUE] = val[0]; - bits[FI_RGBA_GREEN] = val[1]; - bits[FI_RGBA_RED] = val[2]; - bits[FI_RGBA_ALPHA] = val[3]; -#endif - } -} - -/** -Generic RLE loader -*/ -template<int bPP> -static void -loadRLE(FIBITMAP* dib, int width, int height, FreeImageIO* io, fi_handle handle, long eof, BOOL as24bit) { - const int file_pixel_size = bPP/8; - const int pixel_size = as24bit ? 3 : file_pixel_size; - - const BYTE bpp = as24bit ? 24 : bPP; - const int line_size = CalculateLine(width, bpp); - - // Note, many of the params can be computed inside the function. - // However, because this is a template function, it will lead to redundant code duplication. - - BYTE rle; - BYTE *line_bits; - - // this is used to guard against writing beyond the end of the image (on corrupted rle block) - const BYTE* dib_end = FreeImage_GetScanLine(dib, height);//< one-past-end row - - // Compute the rough size of a line... - long pixels_offset = io->tell_proc(handle); - long sz = ((eof - pixels_offset) / height); - - // ...and allocate cache of this size (yields good results) - IOCache cache(io, handle, sz); - if(cache.isNull()) { - FreeImage_Unload(dib); - dib = NULL; - return; - } - - int x = 0, y = 0; - - line_bits = FreeImage_GetScanLine(dib, y); - - while (y < height) { - - rle = cache.getByte(); - - BOOL has_rle = rle & 0x80; - rle &= ~0x80; // remove type-bit - - BYTE packet_count = rle + 1; - - //packet_count might be corrupt, test if we are not about to write beyond the last image bit - - if ((line_bits+x) + packet_count*pixel_size > dib_end) { - FreeImage_OutputMessageProc(s_format_id, FI_MSG_ERROR_CORRUPTED); - // return what is left from the bitmap - return; - } - - if (has_rle) { - - // read a pixel value from file... - BYTE *val = cache.getBytes(file_pixel_size); - - //...and fill packet_count pixels with it - - for (int ix = 0; ix < packet_count; ix++) { - _assignPixel<bPP>((line_bits+x), val, as24bit); - x += pixel_size; - - if (x >= line_size) { - x = 0; - y++; - line_bits = FreeImage_GetScanLine(dib, y); - } - } - - } else { - // no rle commpresion - - // copy packet_count pixels from file to dib - for (int ix = 0; ix < packet_count; ix++) { - BYTE *val = cache.getBytes(file_pixel_size); - _assignPixel<bPP>((line_bits+x), val, as24bit); - x += pixel_size; - - if (x >= line_size) { - x = 0; - y++; - line_bits = FreeImage_GetScanLine(dib, y); - } - } //< packet_count - } //< has_rle - - } //< while height - -} - -// -------------------------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - FIBITMAP *dib = NULL; - - if (!handle) { - return NULL; - } - - try { - - const BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // remember the start offset - long start_offset = io->tell_proc(handle); - - // remember end-of-file (used for RLE cache) - io->seek_proc(handle, 0, SEEK_END); - long eof = io->tell_proc(handle); - io->seek_proc(handle, start_offset, SEEK_SET); - - // read and process the bitmap's footer - - TargaThumbnail thumbnail; - if(isTARGA20(io, handle)) { - TGAFOOTER footer; - const long footer_offset = start_offset + eof - sizeof(footer); - - io->seek_proc(handle, footer_offset, SEEK_SET); - io->read_proc(&footer, sizeof(tagTGAFOOTER), 1, handle); - -#ifdef FREEIMAGE_BIGENDIAN - SwapFooter(&footer); -#endif - BOOL hasExtensionArea = footer.extension_offset > 0; - if(hasExtensionArea) { - TGAEXTENSIONAREA extensionarea; - io->seek_proc(handle, footer.extension_offset, SEEK_SET); - io->read_proc(&extensionarea, sizeof(extensionarea), 1, handle); - -#ifdef FREEIMAGE_BIGENDIAN - SwapExtensionArea(&extensionarea); -#endif - - DWORD postage_stamp_offset = extensionarea.postage_stamp_offset; - BOOL hasThumbnail = (postage_stamp_offset > 0) && (postage_stamp_offset < (DWORD)footer_offset); - if(hasThumbnail) { - io->seek_proc(handle, postage_stamp_offset, SEEK_SET); - thumbnail.read(io, handle, footer_offset - postage_stamp_offset); - } - } - } - - // read and process the bitmap's header - - TGAHEADER header; - - io->seek_proc(handle, start_offset, SEEK_SET); - io->read_proc(&header, sizeof(tagTGAHEADER), 1, handle); - -#ifdef FREEIMAGE_BIGENDIAN - SwapHeader(&header); -#endif - - thumbnail.setDepth(header.is_pixel_depth); - - const int line = CalculateLine(header.is_width, header.is_pixel_depth); - const int pixel_bits = header.is_pixel_depth; - const int pixel_size = pixel_bits/8; - - int fliphoriz = (header.is_image_descriptor & 0x10) ? 1 : 0; - int flipvert = (header.is_image_descriptor & 0x20) ? 1 : 0; - - // skip comment - io->seek_proc(handle, header.id_length, SEEK_CUR); - - switch (header.is_pixel_depth) { - case 8 : { - dib = FreeImage_AllocateHeader(header_only, header.is_width, header.is_height, 8); - - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // read the palette (even if header only) - - RGBQUAD *palette = FreeImage_GetPalette(dib); - - if (header.color_map_type > 0) { - unsigned count, csize; - - // calculate the color map size - csize = header.cm_length * header.cm_size / 8; - - // read the color map - BYTE *cmap = (BYTE*)malloc(csize * sizeof(BYTE)); - if (cmap == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - io->read_proc(cmap, sizeof(BYTE), csize, handle); - - // build the palette - - switch (header.cm_size) { - case 16: { - WORD *rgb555 = (WORD*)&cmap[0]; - unsigned start = (unsigned)header.cm_first_entry; - unsigned stop = MIN((unsigned)256, (unsigned)header.cm_length); - - for (count = start; count < stop; count++) { - palette[count].rgbRed = (BYTE)((((*rgb555 & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F); - palette[count].rgbGreen = (BYTE)((((*rgb555 & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F); - palette[count].rgbBlue = (BYTE)((((*rgb555 & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F); - rgb555++; - } - } - break; - - case 24: { - FILE_BGR *bgr = (FILE_BGR*)&cmap[0]; - unsigned start = (unsigned)header.cm_first_entry; - unsigned stop = MIN((unsigned)256, (unsigned)header.cm_length); - - for (count = start; count < stop; count++) { - palette[count].rgbBlue = bgr->b; - palette[count].rgbGreen = bgr->g; - palette[count].rgbRed = bgr->r; - bgr++; - } - } - break; - - case 32: { - BYTE trns[256]; - - // clear the transparency table - memset(trns, 0xFF, 256); - - FILE_BGRA *bgra = (FILE_BGRA*)&cmap[0]; - unsigned start = (unsigned)header.cm_first_entry; - unsigned stop = MIN((unsigned)256, (unsigned)header.cm_length); - - for (count = start; count < stop; count++) { - palette[count].rgbBlue = bgra->b; - palette[count].rgbGreen = bgra->g; - palette[count].rgbRed = bgra->r; - // alpha - trns[count] = bgra->a; - bgra++; - } - - // set the tranparency table - FreeImage_SetTransparencyTable(dib, trns, 256); - } - break; - - } // switch(header.cm_size) - - free(cmap); - } - - // handle thumbnail - - FIBITMAP* th = thumbnail.toFIBITMAP(); - if(th) { - RGBQUAD* pal = FreeImage_GetPalette(dib); - RGBQUAD* dst_pal = FreeImage_GetPalette(th); - if(dst_pal && pal) { - for(unsigned i = 0; i < FreeImage_GetColorsUsed(dib); i++) { - dst_pal[i] = pal[i]; - } - } - - FreeImage_SetTransparencyTable(th, FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib)); - - FreeImage_SetThumbnail(dib, th); - FreeImage_Unload(th); - } - - if(header_only) { - return dib; - } - - // read in the bitmap bits - - switch (header.image_type) { - case TGA_CMAP: - case TGA_MONO: { - BYTE *bits = NULL; - - for (unsigned count = 0; count < header.is_height; count++) { - bits = FreeImage_GetScanLine(dib, count); - io->read_proc(bits, sizeof(BYTE), line, handle); - } - } - break; - - case TGA_RLECMAP: - case TGA_RLEMONO: { //(8 bit) - loadRLE<8>(dib, header.is_width, header.is_height, io, handle, eof, FALSE); - } - break; - - default : - FreeImage_Unload(dib); - return NULL; - } - } - break; // header.is_pixel_depth == 8 - - case 15 : - - case 16 : { - int pixel_bits = 16; - - // allocate the dib - - if (TARGA_LOAD_RGB888 & flags) { - pixel_bits = 24; - dib = FreeImage_AllocateHeader(header_only, header.is_width, header.is_height, pixel_bits, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - - } else { - dib = FreeImage_AllocateHeader(header_only, header.is_width, header.is_height, pixel_bits, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK); - } - - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // handle thumbnail - - FIBITMAP* th = thumbnail.toFIBITMAP(); - if(th) { - if(TARGA_LOAD_RGB888 & flags) { - FIBITMAP* t = FreeImage_ConvertTo24Bits(th); - FreeImage_Unload(th); - th = t; - } - - FreeImage_SetThumbnail(dib, th); - FreeImage_Unload(th); - } - - if(header_only) { - return dib; - } - - int line = CalculateLine(header.is_width, pixel_bits); - - const unsigned pixel_size = unsigned(pixel_bits) / 8; - const unsigned src_pixel_size = sizeof(WORD); - - // note header.cm_size is a misleading name, it should be seen as header.cm_bits - // ignore current position in file and set filepointer explicitly from the beginning of the file - - int garblen = 0; - - if (header.color_map_type != 0) { - garblen = (int)((header.cm_size + 7) / 8) * header.cm_length; /* should byte align */ - - } else { - garblen = 0; - } - - io->seek_proc(handle, start_offset, SEEK_SET); - io->seek_proc(handle, sizeof(tagTGAHEADER) + header.id_length + garblen, SEEK_SET); - - // read in the bitmap bits - - switch (header.image_type) { - case TGA_RGB: { //(16 bit) - // input line cache - BYTE *in_line = (BYTE*)malloc(header.is_width * sizeof(WORD)); - - if (!in_line) - throw FI_MSG_ERROR_MEMORY; - - const int h = header.is_height; - - for (int y = 0; y < h; y++) { - - BYTE *bits = FreeImage_GetScanLine(dib, y); - io->read_proc(in_line, src_pixel_size, header.is_width, handle); - - BYTE *val = in_line; - for (int x = 0; x < line; x += pixel_size) { - - _assignPixel<16>(bits+x, val, TARGA_LOAD_RGB888 & flags); - - val += src_pixel_size; - } - } - - free(in_line); - } - break; - - case TGA_RLERGB: { //(16 bit) - loadRLE<16>(dib, header.is_width, header.is_height, io, handle, eof, TARGA_LOAD_RGB888 & flags); - } - break; - - default : - FreeImage_Unload(dib); - return NULL; - } - } - break; // header.is_pixel_depth == 15 or 16 - - case 24 : { - - dib = FreeImage_AllocateHeader(header_only, header.is_width, header.is_height, pixel_bits, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - FIBITMAP* th = thumbnail.toFIBITMAP(); - if(th) { - FreeImage_SetThumbnail(dib, th); - FreeImage_Unload(th); - } - - if(header_only) { - return dib; - } - - // read in the bitmap bits - - switch (header.image_type) { - case TGA_RGB: { //(24 bit) - //uncompressed - loadTrueColor(dib, header.is_width, header.is_height, pixel_size,io, handle, TRUE); - } - break; - - case TGA_RLERGB: { //(24 bit) - loadRLE<24>(dib, header.is_width, header.is_height, io, handle, eof, TRUE); - } - break; - - default : - FreeImage_Unload(dib); - return NULL; - } - } - break; // header.is_pixel_depth == 24 - - case 32 : { - int pixel_bits = 32; - - if (TARGA_LOAD_RGB888 & flags) { - pixel_bits = 24; - } - - dib = FreeImage_AllocateHeader(header_only, header.is_width, header.is_height, pixel_bits, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // handle thumbnail - - FIBITMAP* th = thumbnail.toFIBITMAP(); - if(th) { - if(TARGA_LOAD_RGB888 & flags) { - FIBITMAP* t = FreeImage_ConvertTo24Bits(th); - FreeImage_Unload(th); - th = t; - } - FreeImage_SetThumbnail(dib, th); - FreeImage_Unload(th); - } - - if(header_only) { - return dib; - } - - // read in the bitmap bits - - switch (header.image_type) { - case TGA_RGB: { //(32 bit) - // uncompressed - loadTrueColor(dib, header.is_width, header.is_height, 4 /*file_pixel_size*/, io, handle, TARGA_LOAD_RGB888 & flags); - } - break; - - case TGA_RLERGB: { //(32 bit) - loadRLE<32>(dib, header.is_width, header.is_height, io, handle, eof, TARGA_LOAD_RGB888 & flags); - } - break; - - default : - FreeImage_Unload(dib); - return NULL; - } - } - break; // header.is_pixel_depth == 32 - - } // switch(header.is_pixel_depth) - - if (flipvert) { - FreeImage_FlipVertical(dib); - } - - if (fliphoriz) { - FreeImage_FlipHorizontal(dib); - } - - return dib; - - } catch (const char *message) { - if (dib) { - FreeImage_Unload(dib); - } - - FreeImage_OutputMessageProc(s_format_id, message); - - return NULL; - } -} - -// -------------------------------------------------------------------------- - -static BOOL -hasValidThumbnail(FIBITMAP* dib) { - FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib); - - return thumbnail - && SupportsExportType(FreeImage_GetImageType(thumbnail)) - && SupportsExportDepth(FreeImage_GetBPP(thumbnail)) - // Requirements according to the specification: - && FreeImage_GetBPP(thumbnail) == FreeImage_GetBPP(dib) - && FreeImage_GetImageType(thumbnail) == FreeImage_GetImageType(dib) - && FreeImage_GetWidth(thumbnail) <= 255 - && FreeImage_GetHeight(thumbnail) <= 255; -} - -/** -Writes the ready RLE packet to buffer -*/ -static inline void -flushPacket(BYTE*& dest, unsigned pixel_size, BYTE* packet_begin, BYTE*& packet, BYTE& packet_count, BOOL& has_rle) { - if (packet_count) { - const BYTE type_bit = has_rle ? 0x80 : 0x0; - const BYTE write_count = has_rle ? 1 : packet_count; - - // build packet header: zero-based count + type bit - assert(packet_count >= 1); - BYTE rle = packet_count - 1; - rle |= type_bit; - - // write packet header - *dest = rle; - ++dest; - - // write packet data - memcpy(dest, packet_begin, write_count * pixel_size); - dest += write_count * pixel_size; - - // reset state - packet_count = 0; - packet = packet_begin; - has_rle = FALSE; - } -} - - -static inline void -writeToPacket(BYTE* packet, BYTE* pixel, unsigned pixel_size) { - // Take care of channel and byte order here, because packet will be flushed straight to the file - switch (pixel_size) { - case 1: - *packet = *pixel; - break; - - case 2: { - WORD val(*(WORD*)pixel); -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&val); -#endif - *(WORD*)packet = val; - } - break; - - case 3: { - packet[0] = pixel[FI_RGBA_BLUE]; - packet[1] = pixel[FI_RGBA_GREEN]; - packet[2] = pixel[FI_RGBA_RED]; - } - break; - - case 4: { -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - *(reinterpret_cast<unsigned*>(packet)) = *(reinterpret_cast<unsigned*> (pixel)); -#else - packet[0] = pixel[FI_RGBA_BLUE]; - packet[1] = pixel[FI_RGBA_GREEN]; - packet[2] = pixel[FI_RGBA_RED]; - packet[3] = pixel[FI_RGBA_ALPHA]; -#endif - } - break; - - default: - assert(FALSE); - } -} - -static inline BOOL -isEqualPixel(BYTE* lhs, BYTE* rhs, unsigned pixel_size) { - switch (pixel_size) { - case 1: - return *lhs == *rhs; - - case 2: - return *(WORD*)lhs == *(WORD*)rhs; - - case 3: - return *(WORD*)lhs == *(WORD*)rhs && lhs[2] == rhs[2]; - - case 4: - return *(unsigned*)lhs == *(unsigned*)rhs; - - default: - assert(FALSE); - return FALSE; - } -} - -static void -saveRLE(FIBITMAP* dib, FreeImageIO* io, fi_handle handle) { - // Image is compressed line by line, packets don't span multiple lines (TGA2.0 recommendation) - - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - const unsigned pixel_size = FreeImage_GetBPP(dib)/8; - const unsigned line_size = FreeImage_GetLine(dib); - - const BYTE max_packet_size = 128; - BYTE packet_count = 0; - BOOL has_rle = FALSE; - - // packet (compressed or not) to be written to line - - BYTE* const packet_begin = (BYTE*)malloc(max_packet_size * pixel_size); - BYTE* packet = packet_begin; - - // line to be written to disk - // Note: we need some extra bytes for anti-commpressed lines. The worst case is: - // 8 bit images were every 3th pixel is different. - // Rle packet becomes two pixels, but nothing is compressed: two byte pixels are transformed into byte header and byte pixel value - // After every rle packet there is a non-rle packet of one pixel: an extra byte for the header will be added for it - // In the end we gain no bytes from compression, but also must insert a byte at every 3th pixel - - // add extra space for anti-commpressed lines - size_t extra_space = (size_t)ceil(width / 3.0); - BYTE* const line_begin = (BYTE*)malloc(width * pixel_size + extra_space); - BYTE* line = line_begin; - - BYTE *current = (BYTE*)malloc(pixel_size); - BYTE *next = (BYTE*)malloc(pixel_size); - - for(unsigned y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - - // rewind line pointer - line = line_begin; - - for(unsigned x = 0; x < line_size; x += pixel_size) { - - AssignPixel(current, (bits + x), pixel_size); - - // read next pixel from dib - - if( x + 1*pixel_size < line_size) { - AssignPixel(next, (bits + x + 1*pixel_size), pixel_size); - - } else { - // last pixel in line - - // include current pixel and flush - if(!has_rle) { - - writeToPacket(packet, current, pixel_size); - packet += pixel_size; - - } - - assert(packet_count < max_packet_size); - - ++packet_count; - - flushPacket(line, pixel_size, packet_begin, packet, packet_count, has_rle); - - // start anew on next line - break; - } - - if(isEqualPixel(current, next, pixel_size)) { - - // has rle - - if(!has_rle) { - // flush non rle packet - - flushPacket(line, pixel_size, packet_begin, packet, packet_count, has_rle); - - // start a rle packet - - has_rle = TRUE; - - writeToPacket(packet, current, pixel_size); - packet += pixel_size; - } - - // otherwise do nothing. We will just increase the count at the end - - } else { - - // no rle - - if(has_rle) { - // flush rle packet - - // include current pixel first - assert(packet_count < max_packet_size); - ++packet_count; - - flushPacket(line, pixel_size, packet_begin, packet, packet_count, has_rle); - - // start anew on the next pixel - continue; - - } else { - - writeToPacket(packet, current, pixel_size); - packet += pixel_size; - } - - } - - // increase counter on every pixel - - ++packet_count; - - if(packet_count == max_packet_size) { - flushPacket(line, pixel_size, packet_begin, packet, packet_count, has_rle); - } - - }//for width - - // write line to disk - io->write_proc(line_begin, 1, (unsigned)(line - line_begin), handle); - - }//for height - - free(line_begin); - free(packet_begin); - free(current); - free(next); -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - if ((dib == NULL) || (handle == NULL)) { - return FALSE; - } - - RGBQUAD *palette = FreeImage_GetPalette(dib); - const unsigned bpp = FreeImage_GetBPP(dib); - - // write the file header - - TGAHEADER header; - - header.id_length = 0; - header.cm_first_entry = 0; - header.is_xorigin = 0; - header.is_yorigin = 0; - header.is_width = (WORD)FreeImage_GetWidth(dib); - header.is_height = (WORD)FreeImage_GetHeight(dib); - header.is_pixel_depth = (BYTE)bpp; - header.is_image_descriptor = (bpp == 32 ? 8 : 0); - - if (palette) { - header.color_map_type = 1; - header.image_type = (TARGA_SAVE_RLE & flags) ? TGA_RLECMAP : TGA_CMAP; - header.cm_length = (WORD)(1 << bpp); - - if (FreeImage_IsTransparent(dib)) { - header.cm_size = 32; - } else { - header.cm_size = 24; - } - - } else { - header.color_map_type = 0; - header.image_type = (TARGA_SAVE_RLE & flags) ? TGA_RLERGB : TGA_RGB; - header.cm_length = 0; - header.cm_size = 0; - } - - // write the header - -#ifdef FREEIMAGE_BIGENDIAN - SwapHeader(&header); -#endif - - io->write_proc(&header, sizeof(header), 1, handle); - -#ifdef FREEIMAGE_BIGENDIAN - SwapHeader(&header); -#endif - - // write the palette - - if (palette) { - if (FreeImage_IsTransparent(dib)) { - FILE_BGRA *bgra_pal = (FILE_BGRA*)malloc(header.cm_length * sizeof(FILE_BGRA)); - - // get the transparency table - BYTE *trns = FreeImage_GetTransparencyTable(dib); - - for (unsigned i = 0; i < header.cm_length; i++) { - bgra_pal[i].b = palette[i].rgbBlue; - bgra_pal[i].g = palette[i].rgbGreen; - bgra_pal[i].r = palette[i].rgbRed; - bgra_pal[i].a = trns[i]; - } - - io->write_proc(bgra_pal, sizeof(FILE_BGRA), header.cm_length, handle); - - free(bgra_pal); - - } else { - FILE_BGR *bgr_pal = (FILE_BGR*)malloc(header.cm_length * sizeof(FILE_BGR)); - - for (unsigned i = 0; i < header.cm_length; i++) { - bgr_pal[i].b = palette[i].rgbBlue; - bgr_pal[i].g = palette[i].rgbGreen; - bgr_pal[i].r = palette[i].rgbRed; - } - - io->write_proc(bgr_pal, sizeof(FILE_BGR), header.cm_length, handle); - - free(bgr_pal); - } - } - - // write the data bits - - - if (TARGA_SAVE_RLE & flags) { - - saveRLE(dib, io, handle); - - } else { - - // -- no rle compression -- - - const unsigned width = header.is_width; - const unsigned height = header.is_height; - const unsigned pixel_size = bpp/8; - - BYTE *line, *const line_begin = (BYTE*)malloc(width * pixel_size); - BYTE *line_source = line_begin; - - for (unsigned y = 0; y < height; y++) { - BYTE *scanline = FreeImage_GetScanLine(dib, y); - - // rewind the line pointer - line = line_begin; - - switch (bpp) { - case 8: { - // don't copy line, read straight from dib - line_source = scanline; - } - break; - - case 16: { - for (unsigned x = 0; x < width; x++) { - WORD pixel = *(((WORD *)scanline) + x); - -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&pixel); -#endif - *(WORD*)line = pixel; - - line += pixel_size; - } - } - break; - - case 24: { - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - line_source = scanline; -#else - for (unsigned x = 0; x < width; ++x) { - RGBTRIPLE* trip = ((RGBTRIPLE *)scanline) + x; - line[0] = trip->rgbtBlue; - line[1] = trip->rgbtGreen; - line[2] = trip->rgbtRed; - - line += pixel_size; - } -#endif - } - break; - - case 32: { - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - line_source = scanline; -#else - for (unsigned x = 0; x < width; ++x) { - RGBQUAD* quad = ((RGBQUAD *)scanline) + x; - line[0] = quad->rgbBlue; - line[1] = quad->rgbGreen; - line[2] = quad->rgbRed; - line[3] = quad->rgbReserved; - - line += pixel_size; - } -#endif - } - break; - - }//switch(bpp) - - // write line to disk - - io->write_proc(line_source, pixel_size, width, handle); - - }//for height - - free(line_begin); - } - - - long extension_offset = 0 ; - if(hasValidThumbnail(dib)) { - // write extension area - - extension_offset = io->tell_proc(handle); - - TGAEXTENSIONAREA ex; - memset(&ex, 0, sizeof(ex)); - - assert(sizeof(ex) == 495); - ex.extension_size = sizeof(ex); - ex.postage_stamp_offset = extension_offset + ex.extension_size + 0 /*< no Scan Line Table*/; - ex.attributes_type = FreeImage_GetBPP(dib) == 32 ? 3 /*< useful Alpha channel data*/ : 0 /*< no Alpha data*/; - -#ifdef FREEIMAGE_BIGENDIAN - SwapExtensionArea(&ex); -#endif - - io->write_proc(&ex, sizeof(ex), 1, handle); - - // (no Scan Line Table) - - // write thumbnail - - io->seek_proc(handle, ex.postage_stamp_offset, SEEK_SET); - - FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib); - BYTE width = (BYTE)FreeImage_GetWidth(thumbnail); - BYTE height = (BYTE)FreeImage_GetHeight(thumbnail); - - io->write_proc(&width, 1, 1, handle); - io->write_proc(&height, 1, 1, handle); - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - SwapRedBlue32(dib); -#endif - -#ifdef FREEIMAGE_BIGENDIAN - swapShortPixels(dib); -#endif - - const unsigned line_size = FreeImage_GetLine(thumbnail); - - for (BYTE h = 0; h < height; ++h) { - BYTE* src_line = FreeImage_GetScanLine(thumbnail, height - 1 - h); - io->write_proc(src_line, 1, line_size, handle); - } - } - - // (no Color Correction Table) - - // write the footer - - TGAFOOTER footer; - footer.extension_offset = extension_offset; - footer.developer_offset = 0; - strcpy(footer.signature, "TRUEVISION-XFILE."); - - -#ifdef FREEIMAGE_BIGENDIAN - SwapFooter(&footer); -#endif - - io->write_proc(&footer, sizeof(footer), 1, handle); - - return TRUE; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitTARGA(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginTIFF.cpp b/plugins/AdvaImg/src/FreeImage/PluginTIFF.cpp deleted file mode 100644 index 1b454531c1..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginTIFF.cpp +++ /dev/null @@ -1,2631 +0,0 @@ -// ========================================================== -// TIFF Loader and Writer -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - HervĂŠ Drolon (drolon@infonie.fr) -// - Markus Loibl (markus.loibl@epost.de) -// - Luca Piergentili (l.pierge@terra.es) -// - Detlev Vendt (detlev.vendt@brillit.de) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// 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! -// ========================================================== - -#ifdef _MSC_VER -#pragma warning (disable : 4786) // identifier was truncated to 'number' characters -#endif - -#ifdef unix -#undef unix -#endif -#ifdef __unix -#undef __unix -#endif - -#include "FreeImage.h" -#include "Utilities.h" -#include "../LibTIFF4/tiffiop.h" -#include "../Metadata/FreeImageTag.h" -#include "../OpenEXR/Half/half.h" - -#include "FreeImageIO.h" -#include "PSDParser.h" - -// -------------------------------------------------------------------------- -// GeoTIFF profile (see XTIFF.cpp) -// -------------------------------------------------------------------------- -void XTIFFInitialize(); -BOOL tiff_read_geotiff_profile(TIFF *tif, FIBITMAP *dib); -BOOL tiff_write_geotiff_profile(TIFF *tif, FIBITMAP *dib); - -// -------------------------------------------------------------------------- -// TIFF Exif profile (see XTIFF.cpp) -// ---------------------------------------------------------- -BOOL tiff_read_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib); -BOOL tiff_write_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib); - -// -------------------------------------------------------------------------- -// LogLuv conversion functions interface (see TIFFLogLuv.cpp) -// -------------------------------------------------------------------------- -void tiff_ConvertLineXYZToRGB(BYTE *target, BYTE *source, double stonits, int width_in_pixels); -void tiff_ConvertLineRGBToXYZ(BYTE *target, BYTE *source, int width_in_pixels); - -// ---------------------------------------------------------- - -/** Supported loading methods */ -typedef enum { - LoadAsRBGA = 0, - LoadAsCMYK = 1, - LoadAs8BitTrns = 2, - LoadAsGenericStrip = 3, - LoadAsTiled = 4, - LoadAsLogLuv = 5, - LoadAsHalfFloat = 6 -} TIFFLoadMethod; - -// ---------------------------------------------------------- -// local prototypes -// ---------------------------------------------------------- - -static tmsize_t _tiffReadProc(thandle_t handle, void* buf, tmsize_t size); -static tmsize_t _tiffWriteProc(thandle_t handle, void* buf, tmsize_t size); -static toff_t _tiffSeekProc(thandle_t handle, toff_t off, int whence); -static int _tiffCloseProc(thandle_t fd); -static int _tiffMapProc(thandle_t fd, void** pbase, toff_t* psize); -static void _tiffUnmapProc(thandle_t fd, void* base, toff_t size); - -static uint16 CheckColormap(int n, uint16* r, uint16* g, uint16* b); -static uint16 GetPhotometric(FIBITMAP *dib); - -static void ReadResolution(TIFF *tiff, FIBITMAP *dib); -static void WriteResolution(TIFF *tiff, FIBITMAP *dib); - -static void ReadPalette(TIFF *tiff, uint16 photometric, uint16 bitspersample, FIBITMAP *dib); - -static FIBITMAP* CreateImageType(BOOL header_only, FREE_IMAGE_TYPE fit, int width, int height, uint16 bitspersample, uint16 samplesperpixel); -static FREE_IMAGE_TYPE ReadImageType(TIFF *tiff, uint16 bitspersample, uint16 samplesperpixel); -static void WriteImageType(TIFF *tiff, FREE_IMAGE_TYPE fit); - -static void WriteCompression(TIFF *tiff, uint16 bitspersample, uint16 samplesperpixel, uint16 photometric, int flags); - -static BOOL tiff_read_iptc_profile(TIFF *tiff, FIBITMAP *dib); -static BOOL tiff_read_xmp_profile(TIFF *tiff, FIBITMAP *dib); -static BOOL tiff_read_exif_profile(TIFF *tiff, FIBITMAP *dib); -static void ReadMetadata(TIFF *tiff, FIBITMAP *dib); - -static BOOL tiff_write_iptc_profile(TIFF *tiff, FIBITMAP *dib); -static BOOL tiff_write_xmp_profile(TIFF *tiff, FIBITMAP *dib); -static void WriteMetadata(TIFF *tiff, FIBITMAP *dib); - -static TIFFLoadMethod FindLoadMethod(TIFF *tif, uint16 photometric, uint16 bitspersample, uint16 samplesperpixel, FREE_IMAGE_TYPE image_type, int flags); - -static void ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *tiff, FIBITMAP *dib); - - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -typedef struct { - FreeImageIO *io; - fi_handle handle; - TIFF *tif; -} fi_TIFFIO; - -// ---------------------------------------------------------- -// libtiff interface -// ---------------------------------------------------------- - -static tmsize_t -_tiffReadProc(thandle_t handle, void *buf, tmsize_t size) { - fi_TIFFIO *fio = (fi_TIFFIO*)handle; - return fio->io->read_proc(buf, (unsigned)size, 1, fio->handle) * size; -} - -static tmsize_t -_tiffWriteProc(thandle_t handle, void *buf, tmsize_t size) { - fi_TIFFIO *fio = (fi_TIFFIO*)handle; - return fio->io->write_proc(buf, (unsigned)size, 1, fio->handle) * size; -} - -static toff_t -_tiffSeekProc(thandle_t handle, toff_t off, int whence) { - fi_TIFFIO *fio = (fi_TIFFIO*)handle; - fio->io->seek_proc(fio->handle, (long)off, whence); - return fio->io->tell_proc(fio->handle); -} - -static int -_tiffCloseProc(thandle_t fd) { - return 0; -} - -#include <sys/stat.h> - -static toff_t -_tiffSizeProc(thandle_t handle) { - fi_TIFFIO *fio = (fi_TIFFIO*)handle; - long currPos = fio->io->tell_proc(fio->handle); - fio->io->seek_proc(fio->handle, 0, SEEK_END); - long fileSize = fio->io->tell_proc(fio->handle); - fio->io->seek_proc(fio->handle, currPos, SEEK_SET); - return fileSize; -} - -static int -_tiffMapProc(thandle_t, void** base, toff_t* size) { - return 0; -} - -static void -_tiffUnmapProc(thandle_t, void* base, toff_t size) { -} - -/** -Open a TIFF file descriptor for reading or writing -@param handle File handle -@param name Name of the file handle -@param mode Specifies if the file is to be opened for reading ("r") or writing ("w") -*/ -TIFF * -TIFFFdOpen(thandle_t handle, const char *name, const char *mode) { - TIFF *tif; - - // Open the file; the callback will set everything up - tif = TIFFClientOpen(name, mode, handle, - _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc, - _tiffSizeProc, _tiffMapProc, _tiffUnmapProc); - - return tif; -} - -/** -Open a TIFF file for reading or writing -@param name -@param mode -*/ -TIFF* -TIFFOpen(const char* name, const char* mode) { - return 0; -} - -// ---------------------------------------------------------- -// TIFF library FreeImage-specific routines. -// ---------------------------------------------------------- - -void* -_TIFFmalloc(tmsize_t s) { - return malloc(s); -} - -void -_TIFFfree(void *p) { - free(p); -} - -void* -_TIFFrealloc(void* p, tmsize_t s) { - return realloc(p, s); -} - -void -_TIFFmemset(void* p, int v, tmsize_t c) { - memset(p, v, (size_t) c); -} - -void -_TIFFmemcpy(void* d, const void* s, tmsize_t c) { - memcpy(d, s, (size_t) c); -} - -int -_TIFFmemcmp(const void* p1, const void* p2, tmsize_t c) { - return (memcmp(p1, p2, (size_t) c)); -} - -// ---------------------------------------------------------- -// in FreeImage warnings and errors are disabled -// ---------------------------------------------------------- - -static void -msdosWarningHandler(const char* module, const char* fmt, va_list ap) { -} - -TIFFErrorHandler _TIFFwarningHandler = msdosWarningHandler; - -static void -msdosErrorHandler(const char* module, const char* fmt, va_list ap) { - - // use this for diagnostic only (do not use otherwise, even in DEBUG mode) - /* - if (module != NULL) { - char msg[1024]; - vsprintf(msg, fmt, ap); - FreeImage_OutputMessageProc(s_format_id, "%s: %s", module, msg); - } - */ -} - -TIFFErrorHandler _TIFFerrorHandler = msdosErrorHandler; - -// ---------------------------------------------------------- - -#define CVT(x) (((x) * 255L) / ((1L<<16)-1)) -#define SCALE(x) (((x)*((1L<<16)-1))/255) - -// ========================================================== -// Internal functions -// ========================================================== - -static uint16 -CheckColormap(int n, uint16* r, uint16* g, uint16* b) { - while (n-- > 0) { - if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256) { - return 16; - } - } - - return 8; -} - -/** -Get the TIFFTAG_PHOTOMETRIC value from the dib -*/ -static uint16 -GetPhotometric(FIBITMAP *dib) { - FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib); - switch(color_type) { - case FIC_MINISWHITE: // min value is white - return PHOTOMETRIC_MINISWHITE; - case FIC_MINISBLACK: // min value is black - return PHOTOMETRIC_MINISBLACK; - case FIC_PALETTE: // color map indexed - return PHOTOMETRIC_PALETTE; - case FIC_RGB: // RGB color model - case FIC_RGBALPHA: // RGB color model with alpha channel - return PHOTOMETRIC_RGB; - case FIC_CMYK: // CMYK color model - return PHOTOMETRIC_RGB; // default to RGB unless the save flag is set to TIFF_CMYK - default: - return PHOTOMETRIC_MINISBLACK; - } -} - -/** -Get the resolution from the TIFF and fill the dib with universal units -*/ -static void -ReadResolution(TIFF *tiff, FIBITMAP *dib) { - float fResX = 300.0; - float fResY = 300.0; - uint16 resUnit = RESUNIT_INCH; - - TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit); - TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &fResX); - TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &fResY); - - // If we don't have a valid resolution unit and valid resolution is specified then assume inch - if (resUnit == RESUNIT_NONE && fResX > 0.0 && fResY > 0.0) { - resUnit = RESUNIT_INCH; - } - if (resUnit == RESUNIT_INCH) { - FreeImage_SetDotsPerMeterX(dib, (unsigned) (fResX/0.0254000 + 0.5)); - FreeImage_SetDotsPerMeterY(dib, (unsigned) (fResY/0.0254000 + 0.5)); - } else if(resUnit == RESUNIT_CENTIMETER) { - FreeImage_SetDotsPerMeterX(dib, (unsigned) (fResX*100.0 + 0.5)); - FreeImage_SetDotsPerMeterY(dib, (unsigned) (fResY*100.0 + 0.5)); - } -} - -/** -Set the resolution to the TIFF using english units -*/ -static void -WriteResolution(TIFF *tiff, FIBITMAP *dib) { - double res; - - TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); - - res = (unsigned long) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterX(dib)); - TIFFSetField(tiff, TIFFTAG_XRESOLUTION, res); - - res = (unsigned long) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterY(dib)); - TIFFSetField(tiff, TIFFTAG_YRESOLUTION, res); -} - -/** -Fill the dib palette according to the TIFF photometric -*/ -static void -ReadPalette(TIFF *tiff, uint16 photometric, uint16 bitspersample, FIBITMAP *dib) { - RGBQUAD *pal = FreeImage_GetPalette(dib); - - switch(photometric) { - case PHOTOMETRIC_MINISBLACK: // bitmap and greyscale image types - case PHOTOMETRIC_MINISWHITE: - // Monochrome image - - if (bitspersample == 1) { - if (photometric == PHOTOMETRIC_MINISWHITE) { - pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255; - pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 0; - } else { - pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0; - pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; - } - - } else if ((bitspersample == 4) ||(bitspersample == 8)) { - // need to build the scale for greyscale images - int ncolors = FreeImage_GetColorsUsed(dib); - - if (photometric == PHOTOMETRIC_MINISBLACK) { - for (int i = 0; i < ncolors; i++) { - pal[i].rgbRed = - pal[i].rgbGreen = - pal[i].rgbBlue = (BYTE)(i*(255/(ncolors-1))); - } - } else { - for (int i = 0; i < ncolors; i++) { - pal[i].rgbRed = - pal[i].rgbGreen = - pal[i].rgbBlue = (BYTE)(255-i*(255/(ncolors-1))); - } - } - } - - break; - - case PHOTOMETRIC_PALETTE: // color map indexed - uint16 *red; - uint16 *green; - uint16 *blue; - - TIFFGetField(tiff, TIFFTAG_COLORMAP, &red, &green, &blue); - - // load the palette in the DIB - - if (CheckColormap(1<<bitspersample, red, green, blue) == 16) { - for (int i = (1 << bitspersample) - 1; i >= 0; i--) { - pal[i].rgbRed =(BYTE) CVT(red[i]); - pal[i].rgbGreen = (BYTE) CVT(green[i]); - pal[i].rgbBlue = (BYTE) CVT(blue[i]); - } - } else { - for (int i = (1 << bitspersample) - 1; i >= 0; i--) { - pal[i].rgbRed = (BYTE) red[i]; - pal[i].rgbGreen = (BYTE) green[i]; - pal[i].rgbBlue = (BYTE) blue[i]; - } - } - - break; - } -} - -/** -Allocate a FIBITMAP -@param header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full FIBITMAP -@param fit Image type -@param width Image width in pixels -@param height Image height in pixels -@param bitspersample # bits per sample -@param samplesperpixel # samples per pixel -@return Returns the allocated image if successful, returns NULL otherwise -*/ -static FIBITMAP* -CreateImageType(BOOL header_only, FREE_IMAGE_TYPE fit, int width, int height, uint16 bitspersample, uint16 samplesperpixel) { - FIBITMAP *dib = NULL; - - if((width < 0) || (height < 0)) { - // check for malicious images - return NULL; - } - - int bpp = bitspersample * samplesperpixel; - - if(fit == FIT_BITMAP) { - // standard bitmap type - - if(bpp == 16) { - - if((samplesperpixel == 2) && (bitspersample == 8)) { - // 8-bit indexed + 8-bit alpha channel -> convert to 8-bit transparent - dib = FreeImage_AllocateHeader(header_only, width, height, 8); - } else { - // 16-bit RGB -> expect it to be 565 - dib = FreeImage_AllocateHeader(header_only, width, height, bpp, FI16_565_RED_MASK, FI16_565_GREEN_MASK, FI16_565_BLUE_MASK); - } - - } - else { - - dib = FreeImage_AllocateHeader(header_only, width, height, MIN(bpp, 32), FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } - - - } else { - // other bitmap types - - dib = FreeImage_AllocateHeaderT(header_only, fit, width, height, bpp); - } - - return dib; -} - -/** -Read the TIFFTAG_SAMPLEFORMAT tag and convert to FREE_IMAGE_TYPE -@param tiff LibTIFF TIFF Handle -@param bitspersample # bit per sample -@param samplesperpixel # samples per pixel -@return Returns the image type as a FREE_IMAGE_TYPE value -*/ -static FREE_IMAGE_TYPE -ReadImageType(TIFF *tiff, uint16 bitspersample, uint16 samplesperpixel) { - uint16 sampleformat = 0; - FREE_IMAGE_TYPE fit = FIT_BITMAP ; - - uint16 bpp = bitspersample * samplesperpixel; - - // try the sampleformat tag - if(TIFFGetField(tiff, TIFFTAG_SAMPLEFORMAT, &sampleformat)) { - - switch (sampleformat) { - case SAMPLEFORMAT_UINT: - switch (bpp) { - case 1: - case 4: - case 8: - case 24: - fit = FIT_BITMAP; - break; - case 16: - // 8-bit + alpha or 16-bit greyscale - if(samplesperpixel == 2) { - fit = FIT_BITMAP; - } else { - fit = FIT_UINT16; - } - break; - case 32: - if(samplesperpixel == 4) { - fit = FIT_BITMAP; - } else { - fit = FIT_UINT32; - } - break; - case 48: - if(samplesperpixel == 3) { - fit = FIT_RGB16; - } - break; - case 64: - if(samplesperpixel == 4) { - fit = FIT_RGBA16; - } - break; - } - break; - - case SAMPLEFORMAT_INT: - switch (bpp) { - case 16: - if(samplesperpixel == 3) { - fit = FIT_BITMAP; - } else { - fit = FIT_INT16; - } - break; - case 32: - fit = FIT_INT32; - break; - } - break; - - case SAMPLEFORMAT_IEEEFP: - switch (bpp) { - case 32: - fit = FIT_FLOAT; - break; - case 48: - // 3 x half float => convert to RGBF - if((samplesperpixel == 3) && (bitspersample == 16)) { - fit = FIT_RGBF; - } - break; - case 64: - if(samplesperpixel == 2) { - fit = FIT_FLOAT; - } else { - fit = FIT_DOUBLE; - } - break; - case 96: - fit = FIT_RGBF; - break; - default: - if(bpp >= 128) { - fit = FIT_RGBAF; - } - break; - } - break; - case SAMPLEFORMAT_COMPLEXIEEEFP: - switch (bpp) { - case 64: - break; - case 128: - fit = FIT_COMPLEX; - break; - } - break; - - } - } - // no sampleformat tag : assume SAMPLEFORMAT_UINT - else { - if(samplesperpixel == 1) { - switch (bpp) { - case 16: - fit = FIT_UINT16; - break; - - case 32: - fit = FIT_UINT32; - break; - } - } - else if(samplesperpixel == 3) { - if(bpp == 48) fit = FIT_RGB16; - } - else if(samplesperpixel >= 4) { - if(bitspersample == 16) { - fit = FIT_RGBA16; - } - } - - } - - return fit; -} - -/** -Convert FREE_IMAGE_TYPE and write TIFFTAG_SAMPLEFORMAT -@param tiff LibTIFF TIFF Handle -@param fit Image type as a FREE_IMAGE_TYPE value -*/ -static void -WriteImageType(TIFF *tiff, FREE_IMAGE_TYPE fit) { - switch(fit) { - case FIT_BITMAP: // standard image: 1-, 4-, 8-, 16-, 24-, 32-bit - case FIT_UINT16: // array of unsigned short : unsigned 16-bit - case FIT_UINT32: // array of unsigned long : unsigned 32-bit - case FIT_RGB16: // 48-bit RGB image : 3 x 16-bit - case FIT_RGBA16: // 64-bit RGBA image : 4 x 16-bit - TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); - break; - - case FIT_INT16: // array of short : signed 16-bit - case FIT_INT32: // array of long : signed 32-bit - TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT); - break; - - case FIT_FLOAT: // array of float : 32-bit - case FIT_DOUBLE: // array of double : 64-bit - case FIT_RGBF: // 96-bit RGB float image : 3 x 32-bit IEEE floating point - case FIT_RGBAF: // 128-bit RGBA float image : 4 x 32-bit IEEE floating point - TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); - break; - - case FIT_COMPLEX: // array of COMPLEX : 2 x 64-bit - TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_COMPLEXIEEEFP); - break; - } -} - -/** -Select the compression algorithm -@param tiff LibTIFF TIFF Handle -@param -*/ -static void -WriteCompression(TIFF *tiff, uint16 bitspersample, uint16 samplesperpixel, uint16 photometric, int flags) { - uint16 compression; - uint16 bitsperpixel = bitspersample * samplesperpixel; - - if(photometric == PHOTOMETRIC_LOGLUV) { - compression = COMPRESSION_SGILOG; - } else if ((flags & TIFF_PACKBITS) == TIFF_PACKBITS) { - compression = COMPRESSION_PACKBITS; - } else if ((flags & TIFF_DEFLATE) == TIFF_DEFLATE) { - compression = COMPRESSION_DEFLATE; - } else if ((flags & TIFF_ADOBE_DEFLATE) == TIFF_ADOBE_DEFLATE) { - compression = COMPRESSION_ADOBE_DEFLATE; - } else if ((flags & TIFF_NONE) == TIFF_NONE) { - compression = COMPRESSION_NONE; - } else if ((bitsperpixel == 1) && ((flags & TIFF_CCITTFAX3) == TIFF_CCITTFAX3)) { - compression = COMPRESSION_CCITTFAX3; - } else if ((bitsperpixel == 1) && ((flags & TIFF_CCITTFAX4) == TIFF_CCITTFAX4)) { - compression = COMPRESSION_CCITTFAX4; - } else if ((flags & TIFF_LZW) == TIFF_LZW) { - compression = COMPRESSION_LZW; - } else if ((flags & TIFF_JPEG) == TIFF_JPEG) { - if(((bitsperpixel == 8) && (photometric != PHOTOMETRIC_PALETTE)) || (bitsperpixel == 24)) { - compression = COMPRESSION_JPEG; - // RowsPerStrip must be multiple of 8 for JPEG - uint32 rowsperstrip = (uint32) -1; - rowsperstrip = TIFFDefaultStripSize(tiff, rowsperstrip); - rowsperstrip = rowsperstrip + (8 - (rowsperstrip % 8)); - // overwrite previous RowsPerStrip - TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, rowsperstrip); - } else { - // default to LZW - compression = COMPRESSION_LZW; - } - } - else { - // default compression scheme - - switch(bitsperpixel) { - case 1: - compression = COMPRESSION_CCITTFAX4; - break; - - case 4: - case 8: - case 16: - case 24: - case 32: - compression = COMPRESSION_LZW; - break; - case 48: - case 64: - case 96: - case 128: - compression = COMPRESSION_LZW; - break; - - default : - compression = COMPRESSION_NONE; - break; - } - } - - TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression); - - if(compression == COMPRESSION_LZW) { - // This option is only meaningful with LZW compression: a predictor value of 2 - // causes each scanline of the output image to undergo horizontal differencing - // before it is encoded; a value of 1 forces each scanline to be encoded without differencing. - - // Found on LibTIFF mailing list : - // LZW without differencing works well for 1-bit images, 4-bit grayscale images, - // and many palette-color images. But natural 24-bit color images and some 8-bit - // grayscale images do much better with differencing. - - if((bitspersample == 8) || (bitspersample == 16)) { - if ((bitsperpixel >= 8) && (photometric != PHOTOMETRIC_PALETTE)) { - TIFFSetField(tiff, TIFFTAG_PREDICTOR, 2); - } else { - TIFFSetField(tiff, TIFFTAG_PREDICTOR, 1); - } - } else { - TIFFSetField(tiff, TIFFTAG_PREDICTOR, 1); - } - } - else if((compression == COMPRESSION_CCITTFAX3) || (compression == COMPRESSION_CCITTFAX4)) { - uint32 imageLength = 0; - TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &imageLength); - // overwrite previous RowsPerStrip - TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, imageLength); - - if(compression == COMPRESSION_CCITTFAX3) { - // try to be compliant with the TIFF Class F specification - // that documents the TIFF tags specific to FAX applications - // see http://palimpsest.stanford.edu/bytopic/imaging/std/tiff-f.html - uint32 group3options = GROUP3OPT_2DENCODING | GROUP3OPT_FILLBITS; - TIFFSetField(tiff, TIFFTAG_GROUP3OPTIONS, group3options); // 2d-encoded, has aligned EOL - TIFFSetField(tiff, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB); // lsb-to-msb fillorder - } - } -} - -// ========================================================== -// TIFF metadata routines -// ========================================================== - -/** - Read the TIFFTAG_RICHTIFFIPTC tag (IPTC/NAA or Adobe Photoshop profile) -*/ -static BOOL -tiff_read_iptc_profile(TIFF *tiff, FIBITMAP *dib) { - BYTE *profile = NULL; - uint32 profile_size = 0; - - if(TIFFGetField(tiff,TIFFTAG_RICHTIFFIPTC, &profile_size, &profile) == 1) { - if (TIFFIsByteSwapped(tiff) != 0) { - TIFFSwabArrayOfLong((uint32 *) profile, (unsigned long)profile_size); - } - - return read_iptc_profile(dib, profile, 4 * profile_size); - } - - return FALSE; -} - -/** - Read the TIFFTAG_XMLPACKET tag (XMP profile) - @param dib Input FIBITMAP - @param tiff LibTIFF TIFF handle - @return Returns TRUE if successful, FALSE otherwise -*/ -static BOOL -tiff_read_xmp_profile(TIFF *tiff, FIBITMAP *dib) { - BYTE *profile = NULL; - uint32 profile_size = 0; - - if (TIFFGetField(tiff, TIFFTAG_XMLPACKET, &profile_size, &profile) == 1) { - // create a tag - FITAG *tag = FreeImage_CreateTag(); - if(!tag) return FALSE; - - FreeImage_SetTagID(tag, TIFFTAG_XMLPACKET); // 700 - FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName); - FreeImage_SetTagLength(tag, profile_size); - FreeImage_SetTagCount(tag, profile_size); - FreeImage_SetTagType(tag, FIDT_ASCII); - FreeImage_SetTagValue(tag, profile); - - // store the tag - FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag); - - // destroy the tag - FreeImage_DeleteTag(tag); - - return TRUE; - } - - return FALSE; -} - -/** - Read the Exif profile embedded in a TIFF - @param dib Input FIBITMAP - @param tiff LibTIFF TIFF handle - @return Returns TRUE if successful, FALSE otherwise -*/ -static BOOL -tiff_read_exif_profile(TIFF *tiff, FIBITMAP *dib) { - BOOL bResult = FALSE; - toff_t exif_offset = 0; - - // read EXIF-TIFF tags - bResult = tiff_read_exif_tags(tiff, TagLib::EXIF_MAIN, dib); - - // get the IFD offset - if(TIFFGetField(tiff, TIFFTAG_EXIFIFD, &exif_offset)) { - - // read EXIF tags - if(!TIFFReadEXIFDirectory(tiff, exif_offset)) { - return FALSE; - } - - // read all known exif tags - bResult = tiff_read_exif_tags(tiff, TagLib::EXIF_EXIF, dib); - } - - return bResult; -} - -/** -Read TIFF special profiles -*/ -static void -ReadMetadata(TIFF *tiff, FIBITMAP *dib) { - - // IPTC/NAA - tiff_read_iptc_profile(tiff, dib); - - // Adobe XMP - tiff_read_xmp_profile(tiff, dib); - - // GeoTIFF - tiff_read_geotiff_profile(tiff, dib); - - // Exif-TIFF - tiff_read_exif_profile(tiff, dib); -} - -// ---------------------------------------------------------- - -/** - Write the TIFFTAG_RICHTIFFIPTC tag (IPTC/NAA or Adobe Photoshop profile) -*/ -static BOOL -tiff_write_iptc_profile(TIFF *tiff, FIBITMAP *dib) { - if(FreeImage_GetMetadataCount(FIMD_IPTC, dib)) { - BYTE *profile = NULL; - uint32 profile_size = 0; - // create a binary profile - if(write_iptc_profile(dib, &profile, &profile_size)) { - uint32 iptc_size = profile_size; - iptc_size += (4-(iptc_size & 0x03)); // Round up for long word alignment - BYTE *iptc_profile = (BYTE*)malloc(iptc_size); - if(!iptc_profile) { - free(profile); - return FALSE; - } - memset(iptc_profile, 0, iptc_size); - memcpy(iptc_profile, profile, profile_size); - if (TIFFIsByteSwapped(tiff)) { - TIFFSwabArrayOfLong((uint32 *) iptc_profile, (unsigned long)iptc_size/4); - } - // Tag is type TIFF_LONG so byte length is divided by four - TIFFSetField(tiff, TIFFTAG_RICHTIFFIPTC, iptc_size/4, iptc_profile); - // release the profile data - free(iptc_profile); - free(profile); - - return TRUE; - } - } - - return FALSE; -} - -/** - Write the TIFFTAG_XMLPACKET tag (XMP profile) - @param dib Input FIBITMAP - @param tiff LibTIFF TIFF handle - @return Returns TRUE if successful, FALSE otherwise -*/ -static BOOL -tiff_write_xmp_profile(TIFF *tiff, FIBITMAP *dib) { - FITAG *tag_xmp = NULL; - FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag_xmp); - - if(tag_xmp && (NULL != FreeImage_GetTagValue(tag_xmp))) { - - TIFFSetField(tiff, TIFFTAG_XMLPACKET, (uint32)FreeImage_GetTagLength(tag_xmp), (BYTE*)FreeImage_GetTagValue(tag_xmp)); - - return TRUE; - } - - return FALSE; -} - -/** - Write the Exif profile to TIFF - @param dib Input FIBITMAP - @param tiff LibTIFF TIFF handle - @return Returns TRUE if successful, FALSE otherwise -*/ -static BOOL -tiff_write_exif_profile(TIFF *tiff, FIBITMAP *dib) { - BOOL bResult = FALSE; - - // write EXIF_MAIN tags, EXIF_EXIF not supported yet - bResult = tiff_write_exif_tags(tiff, TagLib::EXIF_MAIN, dib); - - return bResult; -} - -/** -Write TIFF special profiles -*/ -static void -WriteMetadata(TIFF *tiff, FIBITMAP *dib) { - // IPTC - tiff_write_iptc_profile(tiff, dib); - - // Adobe XMP - tiff_write_xmp_profile(tiff, dib); - - // EXIF_MAIN tags - tiff_write_exif_profile(tiff, dib); - - // GeoTIFF tags - tiff_write_geotiff_profile(tiff, dib); -} - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "TIFF"; -} - -static const char * DLL_CALLCONV -Description() { - return "Tagged Image File Format"; -} - -static const char * DLL_CALLCONV -Extension() { - return "tif,tiff"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return "^[MI][MI][\\x01*][\\x01*]"; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/tiff"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE tiff_id1[] = { 0x49, 0x49, 0x2A, 0x00 }; // Classic TIFF, little-endian - BYTE tiff_id2[] = { 0x4D, 0x4D, 0x00, 0x2A }; // Classic TIFF, big-endian - BYTE tiff_id3[] = { 0x49, 0x49, 0x2B, 0x00 }; // Big TIFF, little-endian - BYTE tiff_id4[] = { 0x4D, 0x4D, 0x00, 0x2B }; // Big TIFF, big-endian - BYTE signature[4] = { 0, 0, 0, 0 }; - - io->read_proc(signature, 1, 4, handle); - - if(memcmp(tiff_id1, signature, 4) == 0) - return TRUE; - if(memcmp(tiff_id2, signature, 4) == 0) - return TRUE; - if(memcmp(tiff_id3, signature, 4) == 0) - return TRUE; - if(memcmp(tiff_id4, signature, 4) == 0) - return TRUE; - - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return ( - (depth == 1) || - (depth == 4) || - (depth == 8) || - (depth == 24) || - (depth == 32) - ); -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return ( - (type == FIT_BITMAP) || - (type == FIT_UINT16) || - (type == FIT_INT16) || - (type == FIT_UINT32) || - (type == FIT_INT32) || - (type == FIT_FLOAT) || - (type == FIT_DOUBLE) || - (type == FIT_COMPLEX) || - (type == FIT_RGB16) || - (type == FIT_RGBA16) || - (type == FIT_RGBF) || - (type == FIT_RGBAF) - ); -} - -static BOOL DLL_CALLCONV -SupportsICCProfiles() { - return TRUE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static void * DLL_CALLCONV -Open(FreeImageIO *io, fi_handle handle, BOOL read) { - // wrapper for TIFF I/O - fi_TIFFIO *fio = (fi_TIFFIO*)malloc(sizeof(fi_TIFFIO)); - if(!fio) return NULL; - fio->io = io; - fio->handle = handle; - - if (read) { - fio->tif = TIFFFdOpen((thandle_t)fio, "", "r"); - } else { - // mode = "w" : write Classic TIFF - // mode = "w8" : write Big TIFF - fio->tif = TIFFFdOpen((thandle_t)fio, "", "w"); - } - if(fio->tif == NULL) { - free(fio); - FreeImage_OutputMessageProc(s_format_id, "Error while opening TIFF: data is invalid"); - return NULL; - } - return fio; -} - -static void DLL_CALLCONV -Close(FreeImageIO *io, fi_handle handle, void *data) { - if(data) { - fi_TIFFIO *fio = (fi_TIFFIO*)data; - TIFFClose(fio->tif); - free(fio); - } -} - -// ---------------------------------------------------------- - -static int DLL_CALLCONV -PageCount(FreeImageIO *io, fi_handle handle, void *data) { - if(data) { - fi_TIFFIO *fio = (fi_TIFFIO*)data; - TIFF *tif = (TIFF *)fio->tif; - int nr_ifd = 0; - - do { - nr_ifd++; - } while (TIFFReadDirectory(tif)); - - return nr_ifd; - } - - return 0; -} - -// ---------------------------------------------------------- - -/** -check for uncommon bitspersample values (e.g. 10, 12, ...) -@param photometric TIFFTAG_PHOTOMETRIC tiff tag -@param bitspersample TIFFTAG_BITSPERSAMPLE tiff tag -@return Returns FALSE if a uncommon bit-depth is encountered, returns TRUE otherwise -*/ -static BOOL -IsValidBitsPerSample(uint16 photometric, uint16 bitspersample) { - - switch(bitspersample) { - case 1: - case 4: - if((photometric == PHOTOMETRIC_MINISWHITE) || (photometric == PHOTOMETRIC_MINISBLACK) || (photometric == PHOTOMETRIC_PALETTE)) { - return TRUE; - } else { - return FALSE; - } - break; - case 8: - return TRUE; - case 16: - if(photometric != PHOTOMETRIC_PALETTE) { - return TRUE; - } else { - return FALSE; - } - break; - case 32: - if((photometric == PHOTOMETRIC_MINISWHITE) || (photometric == PHOTOMETRIC_MINISBLACK) || (photometric == PHOTOMETRIC_LOGLUV)) { - return TRUE; - } else { - return FALSE; - } - break; - case 64: - case 128: - if(photometric == PHOTOMETRIC_MINISBLACK) { - return TRUE; - } else { - return FALSE; - } - break; - default: - return FALSE; - } -} - -static TIFFLoadMethod -FindLoadMethod(TIFF *tif, FREE_IMAGE_TYPE image_type, int flags) { - uint16 bitspersample = (uint16)-1; - uint16 samplesperpixel = (uint16)-1; - uint16 photometric = (uint16)-1; - uint16 planar_config = (uint16)-1; - - TIFFLoadMethod loadMethod = LoadAsGenericStrip; - - TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric); - TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); - TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample); - TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planar_config); - - BOOL bIsTiled = (TIFFIsTiled(tif) == 0) ? FALSE:TRUE; - - switch(photometric) { - // convert to 24 or 32 bits RGB if the image is full color - case PHOTOMETRIC_RGB: - if((image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) { - // load 48-bit RGB and 64-bit RGBA without conversion - loadMethod = LoadAsGenericStrip; - } - else if(image_type == FIT_RGBF) { - if((samplesperpixel == 3) && (bitspersample == 16)) { - // load 3 x 16-bit half as RGBF - loadMethod = LoadAsHalfFloat; - } - } - break; - case PHOTOMETRIC_YCBCR: - case PHOTOMETRIC_CIELAB: - case PHOTOMETRIC_ICCLAB: - case PHOTOMETRIC_ITULAB: - loadMethod = LoadAsRBGA; - break; - case PHOTOMETRIC_LOGLUV: - loadMethod = LoadAsLogLuv; - break; - case PHOTOMETRIC_SEPARATED: - // if image is PHOTOMETRIC_SEPARATED _and_ comes with an ICC profile, - // then the image should preserve its original (CMYK) colour model and - // should be read as CMYK (to keep the match of pixel and profile and - // to avoid multiple conversions. Conversion can be done by changing - // the profile from it's original CMYK to an RGB profile with an - // apropriate color management system. Works with non-tiled TIFFs. - if(!bIsTiled) { - loadMethod = LoadAsCMYK; - } - break; - case PHOTOMETRIC_MINISWHITE: - case PHOTOMETRIC_MINISBLACK: - case PHOTOMETRIC_PALETTE: - // When samplesperpixel = 2 and bitspersample = 8, set the image as a - // 8-bit indexed image + 8-bit alpha layer image - // and convert to a 8-bit image with a transparency table - if((samplesperpixel > 1) && (bitspersample == 8)) { - loadMethod = LoadAs8BitTrns; - } else { - loadMethod = LoadAsGenericStrip; - } - break; - default: - loadMethod = LoadAsGenericStrip; - break; - } - - if((loadMethod == LoadAsGenericStrip) && bIsTiled) { - loadMethod = LoadAsTiled; - } - - return loadMethod; -} - -// ========================================================== -// TIFF thumbnail routines -// ========================================================== - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data); - -/** -Read embedded thumbnail -*/ -static void -ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *tiff, FIBITMAP *dib) { - FIBITMAP* thumbnail = NULL; - - // read exif thumbnail (IFD 1) ... - - uint32 exif_offset = 0; - if(TIFFGetField(tiff, TIFFTAG_EXIFIFD, &exif_offset)) { - - if(TIFFLastDirectory(tiff) != 0) { - // save current position - long tell_pos = io->tell_proc(handle); - uint16 cur_dir = TIFFCurrentDirectory(tiff); - - // load the thumbnail - int page = 1; - int flags = TIFF_DEFAULT; - thumbnail = Load(io, handle, page, flags, data); - // store the thumbnail (remember to release it later ...) - FreeImage_SetThumbnail(dib, thumbnail); - - // restore current position - io->seek_proc(handle, tell_pos, SEEK_SET); - TIFFSetDirectory(tiff, cur_dir); - } - } - - // ... or read the first subIFD - - if(!thumbnail) { - uint16 subIFD_count = 0; - uint64* subIFD_offsets = NULL; - // ### Theoretically this should also read the first subIFD from a Photoshop-created file with "pyramid". - // It does not however - the tag is there (using Tag Viewer app) but libtiff refuses to read it - if(TIFFGetField(tiff, TIFFTAG_SUBIFD, &subIFD_count, &subIFD_offsets)) { - if(subIFD_count > 0) { - // save current position - long tell_pos = io->tell_proc(handle); - uint16 cur_dir = TIFFCurrentDirectory(tiff); - if(TIFFSetSubDirectory(tiff, subIFD_offsets[0])) { - // load the thumbnail - int page = -1; - int flags = TIFF_DEFAULT; - thumbnail = Load(io, handle, page, flags, data); - // store the thumbnail (remember to release it later ...) - FreeImage_SetThumbnail(dib, thumbnail); - } - // restore current position - io->seek_proc(handle, tell_pos, SEEK_SET); - TIFFSetDirectory(tiff, cur_dir); - } - } - } - - // ... or read Photoshop thumbnail - - if(!thumbnail) { - uint32 ps_size = 0; - void *ps_data = NULL; - - if(TIFFGetField(tiff, TIFFTAG_PHOTOSHOP, &ps_size, &ps_data)) { - FIMEMORY *handle = FreeImage_OpenMemory((BYTE*)ps_data, ps_size); - - FreeImageIO io; - SetMemoryIO(&io); - - psdParser parser; - parser.ReadImageResources(&io, handle, ps_size); - - FreeImage_SetThumbnail(dib, parser.GetThumbnail()); - - FreeImage_CloseMemory(handle); - } - - } - - // release thumbnail - FreeImage_Unload(thumbnail); -} - -// -------------------------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - if (!handle || !data ) { - return NULL; - } - - TIFF *tif = NULL; - uint32 height = 0; - uint32 width = 0; - uint16 bitspersample = 1; - uint16 samplesperpixel = 1; - uint32 rowsperstrip = (uint32)-1; - uint16 photometric = PHOTOMETRIC_MINISWHITE; - uint16 compression = (uint16)-1; - uint16 planar_config; - - FIBITMAP *dib = NULL; - uint32 iccSize = 0; // ICC profile length - void *iccBuf = NULL; // ICC profile data - - const BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - try { - fi_TIFFIO *fio = (fi_TIFFIO*)data; - tif = fio->tif; - - if (page != -1) { - if (!tif || !TIFFSetDirectory(tif, (uint16)page)) { - throw "Error encountered while opening TIFF file"; - } - } - - const BOOL asCMYK = (flags & TIFF_CMYK) == TIFF_CMYK; - - // first, get the photometric, the compression and basic metadata - // --------------------------------------------------------------------------------- - - TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric); - TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression); - - // check for HDR formats - // --------------------------------------------------------------------------------- - - if(photometric == PHOTOMETRIC_LOGLUV) { - // check the compression - if(compression != COMPRESSION_SGILOG && compression != COMPRESSION_SGILOG24) { - throw "Only support SGILOG compressed LogLuv data"; - } - // set decoder to output in IEEE 32-bit float XYZ values - TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT); - } - - // --------------------------------------------------------------------------------- - - TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width); - TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height); - TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); - TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample); - TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); - TIFFGetField(tif, TIFFTAG_ICCPROFILE, &iccSize, &iccBuf); - TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planar_config); - - // check for unsupported formats - // --------------------------------------------------------------------------------- - - if(IsValidBitsPerSample(photometric, bitspersample) == FALSE) { - FreeImage_OutputMessageProc(s_format_id, - "Unable to handle this format: bitspersample = %d, samplesperpixel = %d, photometric = %d", - (int)bitspersample, (int)samplesperpixel, (int)photometric); - throw (char*)NULL; - } - - // --------------------------------------------------------------------------------- - - // get image data type - - FREE_IMAGE_TYPE image_type = ReadImageType(tif, bitspersample, samplesperpixel); - - // get the most appropriate loading method - - TIFFLoadMethod loadMethod = FindLoadMethod(tif, image_type, flags); - - // --------------------------------------------------------------------------------- - - if(loadMethod == LoadAsRBGA) { - // --------------------------------------------------------------------------------- - // RGB[A] loading using the TIFFReadRGBAImage() API - // --------------------------------------------------------------------------------- - - BOOL has_alpha = FALSE; - - // Read the whole image into one big RGBA buffer and then - // convert it to a DIB. This is using the traditional - // TIFFReadRGBAImage() API that we trust. - - uint32 *raster = NULL; - - if(!header_only) { - - raster = (uint32*)_TIFFmalloc(width * height * sizeof(uint32)); - if (raster == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - // read the image in one chunk into an RGBA array - - if (!TIFFReadRGBAImage(tif, width, height, raster, 1)) { - _TIFFfree(raster); - throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; - } - } - // TIFFReadRGBAImage always deliveres 3 or 4 samples per pixel images - // (RGB or RGBA, see below). Cut-off possibly present channels (additional - // alpha channels) from e.g. Photoshop. Any CMYK(A..) is now treated as RGB, - // any additional alpha channel on RGB(AA..) is lost on conversion to RGB(A) - - if(samplesperpixel > 4) { // TODO Write to Extra Channels - FreeImage_OutputMessageProc(s_format_id, "Warning: %d additional alpha channel(s) ignored", samplesperpixel-4); - samplesperpixel = 4; - } - - // create a new DIB (take care of different samples-per-pixel in case - // of converted CMYK image (RGB conversion is on sample per pixel less) - - if (photometric == PHOTOMETRIC_SEPARATED && samplesperpixel == 4) { - samplesperpixel = 3; - } - - dib = CreateImageType(header_only, image_type, width, height, bitspersample, samplesperpixel); - if (dib == NULL) { - // free the raster pointer and output an error if allocation failed - if(raster) { - _TIFFfree(raster); - } - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // fill in the resolution (english or universal) - - ReadResolution(tif, dib); - - if(!header_only) { - - // read the raster lines and save them in the DIB - // with RGB mode, we have to change the order of the 3 samples RGB - // We use macros for extracting components from the packed ABGR - // form returned by TIFFReadRGBAImage. - - uint32 *row = &raster[0]; - - if (samplesperpixel == 4) { - // 32-bit RGBA - for (uint32 y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - for (uint32 x = 0; x < width; x++) { - bits[FI_RGBA_BLUE] = (BYTE)TIFFGetB(row[x]); - bits[FI_RGBA_GREEN] = (BYTE)TIFFGetG(row[x]); - bits[FI_RGBA_RED] = (BYTE)TIFFGetR(row[x]); - bits[FI_RGBA_ALPHA] = (BYTE)TIFFGetA(row[x]); - - if (bits[FI_RGBA_ALPHA] != 0) { - has_alpha = TRUE; - } - - bits += 4; - } - row += width; - } - } else { - // 24-bit RGB - for (uint32 y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - for (uint32 x = 0; x < width; x++) { - bits[FI_RGBA_BLUE] = (BYTE)TIFFGetB(row[x]); - bits[FI_RGBA_GREEN] = (BYTE)TIFFGetG(row[x]); - bits[FI_RGBA_RED] = (BYTE)TIFFGetR(row[x]); - - bits += 3; - } - row += width; - } - } - - _TIFFfree(raster); - } - - // ### Not correct when header only - FreeImage_SetTransparent(dib, has_alpha); - - } else if(loadMethod == LoadAs8BitTrns) { - // --------------------------------------------------------------------------------- - // 8-bit + 8-bit alpha layer loading - // --------------------------------------------------------------------------------- - - // create a new 8-bit DIB - dib = CreateImageType(header_only, image_type, width, height, bitspersample, MIN<uint16>(2, samplesperpixel)); - if (dib == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - // fill in the resolution (english or universal) - - ReadResolution(tif, dib); - - // set up the colormap based on photometric - - ReadPalette(tif, photometric, bitspersample, dib); - - // calculate the line + pitch (separate for scr & dest) - - const tmsize_t src_line = TIFFScanlineSize(tif); - // here, the pitch is 2x less than the original as we only keep the first layer - int dst_pitch = FreeImage_GetPitch(dib); - - // transparency table for 8-bit + 8-bit alpha images - - BYTE trns[256]; - // clear the transparency table - memset(trns, 0xFF, 256 * sizeof(BYTE)); - - // In the tiff file the lines are saved from up to down - // In a DIB the lines must be saved from down to up - - BYTE *bits = FreeImage_GetScanLine(dib, height - 1); - - // read the tiff lines and save them in the DIB - - if(planar_config == PLANARCONFIG_CONTIG && !header_only) { - - BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE)); - if(buf == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - for (uint32 y = 0; y < height; y += rowsperstrip) { - int32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip); - - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, nrow * src_line) == -1) { - free(buf); - throw FI_MSG_ERROR_PARSING; - } - for (int l = 0; l < nrow; l++) { - BYTE *p = bits; - BYTE *b = buf + l * src_line; - - for(uint32 x = 0; x < (uint32)(src_line / samplesperpixel); x++) { - // copy the 8-bit layer - *p = b[0]; - // convert the 8-bit alpha layer to a trns table - trns[ b[0] ] = b[1]; - - p++; - b += samplesperpixel; - } - bits -= dst_pitch; - } - } - - free(buf); - } - else if(planar_config == PLANARCONFIG_SEPARATE && !header_only) { - tmsize_t stripsize = TIFFStripSize(tif) * sizeof(BYTE); - BYTE *buf = (BYTE*)malloc(2 * stripsize); - if(buf == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - BYTE *grey = buf; - BYTE *alpha = buf + stripsize; - - for (uint32 y = 0; y < height; y += rowsperstrip) { - int32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip); - - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), grey, nrow * src_line) == -1) { - free(buf); - throw FI_MSG_ERROR_PARSING; - } - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 1), alpha, nrow * src_line) == -1) { - free(buf); - throw FI_MSG_ERROR_PARSING; - } - - for (int l = 0; l < nrow; l++) { - BYTE *p = bits; - BYTE *g = grey + l * src_line; - BYTE *a = alpha + l * src_line; - - for(uint32 x = 0; x < (uint32)(src_line); x++) { - // copy the 8-bit layer - *p = g[0]; - // convert the 8-bit alpha layer to a trns table - trns[ g[0] ] = a[0]; - - p++; - g++; - a++; - } - bits -= dst_pitch; - } - } - - free(buf); - - } - - FreeImage_SetTransparencyTable(dib, &trns[0], 256); - FreeImage_SetTransparent(dib, TRUE); - - } else if(loadMethod == LoadAsCMYK) { - // --------------------------------------------------------------------------------- - // CMYK loading - // --------------------------------------------------------------------------------- - - // At this place, samplesperpixel could be > 4, esp. when a CMYK(A) format - // is recognized. Where all other formats are handled straight-forward, this - // format has to be handled special - - BOOL isCMYKA = (photometric == PHOTOMETRIC_SEPARATED) && (samplesperpixel > 4); - - // We use a temp dib to store the alpha for the CMYKA to RGBA conversion - // NOTE this is until we have Extra channels implementation. - // Also then it will be possible to merge LoadAsCMYK with LoadAsGenericStrip - - FIBITMAP *alpha = NULL; - unsigned alpha_pitch = 0; - BYTE *alpha_bits = NULL; - unsigned alpha_Bpp = 0; - - if(isCMYKA && !asCMYK && !header_only) { - if(bitspersample == 16) { - alpha = FreeImage_AllocateT(FIT_UINT16, width, height); - } else if (bitspersample == 8) { - alpha = FreeImage_Allocate(width, height, 8); - } - - if(!alpha) { - FreeImage_OutputMessageProc(s_format_id, "Failed to allocate temporary alpha channel"); - } else { - alpha_bits = FreeImage_GetScanLine(alpha, height - 1); - alpha_pitch = FreeImage_GetPitch(alpha); - alpha_Bpp = FreeImage_GetBPP(alpha) / 8; - } - - } - - // create a new DIB - const uint16 chCount = MIN<uint16>(samplesperpixel, 4); - dib = CreateImageType(header_only, image_type, width, height, bitspersample, chCount); - if (dib == NULL) { - FreeImage_Unload(alpha); - throw FI_MSG_ERROR_MEMORY; - } - - // fill in the resolution (english or universal) - - ReadResolution(tif, dib); - - if(!header_only) { - - // calculate the line + pitch (separate for scr & dest) - - const tmsize_t src_line = TIFFScanlineSize(tif); - const tmsize_t dst_line = FreeImage_GetLine(dib); - const unsigned dib_pitch = FreeImage_GetPitch(dib); - const unsigned dibBpp = FreeImage_GetBPP(dib) / 8; - const unsigned Bpc = dibBpp / chCount; - const unsigned srcBpp = bitspersample * samplesperpixel / 8; - - assert(Bpc <= 2); //< CMYK is only BYTE or SHORT - - // In the tiff file the lines are save from up to down - // In a DIB the lines must be saved from down to up - - BYTE *bits = FreeImage_GetScanLine(dib, height - 1); - - // read the tiff lines and save them in the DIB - - BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE)); - if(buf == NULL) { - FreeImage_Unload(alpha); - throw FI_MSG_ERROR_MEMORY; - } - - if(planar_config == PLANARCONFIG_CONTIG) { - - // - loop for strip blocks - - - for (uint32 y = 0; y < height; y += rowsperstrip) { - const int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip); - - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, strips * src_line) == -1) { - free(buf); - FreeImage_Unload(alpha); - throw FI_MSG_ERROR_PARSING; - } - - // - loop for strips - - - if(src_line != dst_line) { - // CMYKA+ - if(alpha) { - for (int l = 0; l < strips; l++) { - for(BYTE *pixel = bits, *al_pixel = alpha_bits, *src_pixel = buf + l * src_line; pixel < bits + dib_pitch; pixel += dibBpp, al_pixel += alpha_Bpp, src_pixel += srcBpp) { - // copy pixel byte by byte - BYTE b = 0; - for( ; b < dibBpp; ++b) { - pixel[b] = src_pixel[b]; - } - // TODO write the remaining bytes to extra channel(s) - - // HACK write the first alpha to a separate dib (assume BYTE or WORD) - al_pixel[0] = src_pixel[b]; - if(Bpc > 1) { - al_pixel[1] = src_pixel[b + 1]; - } - - } - bits -= dib_pitch; - alpha_bits -= alpha_pitch; - } - } - else { - // alpha/extra channels alloc failed - for (int l = 0; l < strips; l++) { - for(BYTE* pixel = bits, * src_pixel = buf + l * src_line; pixel < bits + dst_line; pixel += dibBpp, src_pixel += srcBpp) { - AssignPixel(pixel, src_pixel, dibBpp); - } - bits -= dib_pitch; - } - } - } - else { - // CMYK to CMYK - for (int l = 0; l < strips; l++) { - BYTE *b = buf + l * src_line; - memcpy(bits, b, src_line); - bits -= dib_pitch; - } - } - - } // height - - } - else if(planar_config == PLANARCONFIG_SEPARATE) { - - BYTE *dib_strip = bits; - BYTE *al_strip = alpha_bits; - - // - loop for strip blocks - - - for (uint32 y = 0; y < height; y += rowsperstrip) { - const int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip); - - // - loop for channels (planes) - - - for(uint16 sample = 0; sample < samplesperpixel; sample++) { - - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, sample), buf, strips * src_line) == -1) { - free(buf); - FreeImage_Unload(alpha); - throw FI_MSG_ERROR_PARSING; - } - - BYTE *dst_strip = dib_strip; - unsigned dst_pitch = dib_pitch; - uint16 ch = sample; - unsigned Bpp = dibBpp; - - if(sample >= chCount) { - // TODO Write to Extra Channel - - // HACK redirect write to temp alpha - if(alpha && sample == chCount) { - - dst_strip = al_strip; - dst_pitch = alpha_pitch; - - ch = 0; - Bpp = alpha_Bpp; - } - else { - break; - } - } - - const unsigned channelOffset = ch * Bpc; - - // - loop for strips in block - - - BYTE *src_line_begin = buf; - BYTE *dst_line_begin = dst_strip; - for (int l = 0; l < strips; l++, src_line_begin += src_line, dst_line_begin -= dst_pitch ) { - // - loop for pixels in strip - - - const BYTE* const src_line_end = src_line_begin + src_line; - for (BYTE *src_bits = src_line_begin, * dst_bits = dst_line_begin; src_bits < src_line_end; src_bits += Bpc, dst_bits += Bpp) { - AssignPixel(dst_bits + channelOffset, src_bits, Bpc); - } // line - - } // strips - - } // channels - - // done with a strip block, incr to the next - dib_strip -= strips * dib_pitch; - al_strip -= strips * alpha_pitch; - - } //< height - - } - - free(buf); - - if(!asCMYK) { - ConvertCMYKtoRGBA(dib); - - // The ICC Profile is invalid, clear it - iccSize = 0; - iccBuf = NULL; - - if(isCMYKA) { - // HACK until we have Extra channels. (ConvertCMYKtoRGBA will then do the work) - - FreeImage_SetChannel(dib, alpha, FICC_ALPHA); - FreeImage_Unload(alpha); - alpha = NULL; - } - else { - FIBITMAP *t = RemoveAlphaChannel(dib); - if(t) { - FreeImage_Unload(dib); - dib = t; - } - else { - FreeImage_OutputMessageProc(s_format_id, "Cannot allocate memory for buffer. CMYK image converted to RGB + pending Alpha"); - } - } - } - - } // !header_only - - } else if(loadMethod == LoadAsGenericStrip) { - // --------------------------------------------------------------------------------- - // Generic loading - // --------------------------------------------------------------------------------- - - // create a new DIB - const uint16 chCount = MIN<uint16>(samplesperpixel, 4); - dib = CreateImageType(header_only, image_type, width, height, bitspersample, chCount); - if (dib == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - // fill in the resolution (english or universal) - - ReadResolution(tif, dib); - - // set up the colormap based on photometric - - ReadPalette(tif, photometric, bitspersample, dib); - - if(!header_only) { - // calculate the line + pitch (separate for scr & dest) - - const tmsize_t src_line = TIFFScanlineSize(tif); - const tmsize_t dst_line = FreeImage_GetLine(dib); - const unsigned dst_pitch = FreeImage_GetPitch(dib); - const unsigned Bpp = FreeImage_GetBPP(dib) / 8; - const unsigned srcBpp = bitspersample * samplesperpixel / 8; - - // In the tiff file the lines are save from up to down - // In a DIB the lines must be saved from down to up - - BYTE *bits = FreeImage_GetScanLine(dib, height - 1); - - // read the tiff lines and save them in the DIB - - BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE)); - if(buf == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - memset(buf, 0, TIFFStripSize(tif) * sizeof(BYTE)); - - BOOL bThrowMessage = FALSE; - - if(planar_config == PLANARCONFIG_CONTIG) { - - for (uint32 y = 0; y < height; y += rowsperstrip) { - int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip); - - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, strips * src_line) == -1) { - // ignore errors as they can be frequent and not really valid errors, especially with fax images - bThrowMessage = TRUE; - /* - free(buf); - throw FI_MSG_ERROR_PARSING; - */ - } - if(src_line == dst_line) { - // channel count match - for (int l = 0; l < strips; l++) { - memcpy(bits, buf + l * src_line, src_line); - bits -= dst_pitch; - } - } - else { - for (int l = 0; l < strips; l++) { - for(BYTE *pixel = bits, *src_pixel = buf + l * src_line; pixel < bits + dst_pitch; pixel += Bpp, src_pixel += srcBpp) { - AssignPixel(pixel, src_pixel, Bpp); - } - bits -= dst_pitch; - } - } - } - } - else if(planar_config == PLANARCONFIG_SEPARATE) { - - const unsigned Bpc = bitspersample / 8; - BYTE* dib_strip = bits; - // - loop for strip blocks - - - for (uint32 y = 0; y < height; y += rowsperstrip) { - const int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip); - - // - loop for channels (planes) - - - for(uint16 sample = 0; sample < samplesperpixel; sample++) { - - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, sample), buf, strips * src_line) == -1) { - // ignore errors as they can be frequent and not really valid errors, especially with fax images - bThrowMessage = TRUE; - } - - if(sample >= chCount) { - // TODO Write to Extra Channel - break; - } - - const unsigned channelOffset = sample * Bpc; - - // - loop for strips in block - - - BYTE* src_line_begin = buf; - BYTE* dst_line_begin = dib_strip; - for (int l = 0; l < strips; l++, src_line_begin += src_line, dst_line_begin -= dst_pitch ) { - - // - loop for pixels in strip - - - const BYTE* const src_line_end = src_line_begin + src_line; - - for (BYTE* src_bits = src_line_begin, * dst_bits = dst_line_begin; src_bits < src_line_end; src_bits += Bpc, dst_bits += Bpp) { - // actually assigns channel - AssignPixel(dst_bits + channelOffset, src_bits, Bpc); - } // line - - } // strips - - } // channels - - // done with a strip block, incr to the next - dib_strip -= strips * dst_pitch; - - } // height - - } - free(buf); - - if(bThrowMessage) { - FreeImage_OutputMessageProc(s_format_id, "Warning: parsing error. Image may be incomplete or contain invalid data !"); - } - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - SwapRedBlue32(dib); -#endif - - } // !header only - - } else if(loadMethod == LoadAsTiled) { - // --------------------------------------------------------------------------------- - // Tiled image loading - // --------------------------------------------------------------------------------- - - uint32 tileWidth, tileHeight; - uint32 src_line = 0; - - // create a new DIB - dib = CreateImageType( header_only, image_type, width, height, bitspersample, samplesperpixel); - if (dib == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - // fill in the resolution (english or universal) - - ReadResolution(tif, dib); - - // set up the colormap based on photometric - - ReadPalette(tif, photometric, bitspersample, dib); - - // get the tile geometry - if(!TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tileWidth) || !TIFFGetField(tif, TIFFTAG_TILELENGTH, &tileHeight)) { - throw "Invalid tiled TIFF image"; - } - - // read the tiff lines and save them in the DIB - - if(planar_config == PLANARCONFIG_CONTIG && !header_only) { - - // get the maximum number of bytes required to contain a tile - tmsize_t tileSize = TIFFTileSize(tif); - - // allocate tile buffer - BYTE *tileBuffer = (BYTE*)malloc(tileSize * sizeof(BYTE)); - if(tileBuffer == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - // calculate src line and dst pitch - int dst_pitch = FreeImage_GetPitch(dib); - uint32 tileRowSize = (uint32)TIFFTileRowSize(tif); - uint32 imageRowSize = (uint32)TIFFScanlineSize(tif); - - - // In the tiff file the lines are saved from up to down - // In a DIB the lines must be saved from down to up - - BYTE *bits = FreeImage_GetScanLine(dib, height - 1); - - for (uint32 y = 0; y < height; y += tileHeight) { - int32 nrows = (y + tileHeight > height ? height - y : tileHeight); - - for (uint32 x = 0, rowSize = 0; x < width; x += tileWidth, rowSize += tileRowSize) { - memset(tileBuffer, 0, tileSize); - - // read one tile - if (TIFFReadTile(tif, tileBuffer, x, y, 0, 0) < 0) { - free(tileBuffer); - throw "Corrupted tiled TIFF file"; - } - // convert to strip - if(x + tileWidth > width) { - src_line = imageRowSize - rowSize; - } else { - src_line = tileRowSize; - } - BYTE *src_bits = tileBuffer; - BYTE *dst_bits = bits + rowSize; - for(int k = 0; k < nrows; k++) { - memcpy(dst_bits, src_bits, src_line); - src_bits += tileRowSize; - dst_bits -= dst_pitch; - } - } - - bits -= nrows * dst_pitch; - } - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - SwapRedBlue32(dib); -#endif - free(tileBuffer); - } - else if(planar_config == PLANARCONFIG_SEPARATE) { - throw "Separated tiled TIFF images are not supported"; - } - - - } else if(loadMethod == LoadAsLogLuv) { - // --------------------------------------------------------------------------------- - // RGBF LogLuv compressed loading - // --------------------------------------------------------------------------------- - - double stonits; // input conversion to nits - if (!TIFFGetField(tif, TIFFTAG_STONITS, &stonits)) { - stonits = 1; - } - - // create a new DIB - dib = CreateImageType(header_only, image_type, width, height, bitspersample, samplesperpixel); - if (dib == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - // fill in the resolution (english or universal) - - ReadResolution(tif, dib); - - if(planar_config == PLANARCONFIG_CONTIG && !header_only) { - // calculate the line + pitch (separate for scr & dest) - - tmsize_t src_line = TIFFScanlineSize(tif); - int dst_pitch = FreeImage_GetPitch(dib); - - // In the tiff file the lines are save from up to down - // In a DIB the lines must be saved from down to up - - BYTE *bits = FreeImage_GetScanLine(dib, height - 1); - - // read the tiff lines and save them in the DIB - - BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE)); - if(buf == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - for (uint32 y = 0; y < height; y += rowsperstrip) { - int32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip); - - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, nrow * src_line) == -1) { - free(buf); - throw FI_MSG_ERROR_PARSING; - } - // convert from XYZ to RGB - for (int l = 0; l < nrow; l++) { - tiff_ConvertLineXYZToRGB(bits, buf + l * src_line, stonits, width); - bits -= dst_pitch; - } - } - - free(buf); - } - else if(planar_config == PLANARCONFIG_SEPARATE) { - // this cannot happen according to the LogLuv specification - throw "Unable to handle PLANARCONFIG_SEPARATE LogLuv images"; - } - - } else if(loadMethod == LoadAsHalfFloat) { - // --------------------------------------------------------------------------------- - // RGBF loading from a half format - // --------------------------------------------------------------------------------- - - // create a new DIB - dib = CreateImageType(header_only, image_type, width, height, bitspersample, samplesperpixel); - if (dib == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - // fill in the resolution (english or universal) - - ReadResolution(tif, dib); - - if(!header_only) { - - // calculate the line + pitch (separate for scr & dest) - - tmsize_t src_line = TIFFScanlineSize(tif); - unsigned dst_pitch = FreeImage_GetPitch(dib); - - // In the tiff file the lines are save from up to down - // In a DIB the lines must be saved from down to up - - BYTE *bits = FreeImage_GetScanLine(dib, height - 1); - - // read the tiff lines and save them in the DIB - - if(planar_config == PLANARCONFIG_CONTIG) { - - BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE)); - if(buf == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - for (uint32 y = 0; y < height; y += rowsperstrip) { - uint32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip); - - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, nrow * src_line) == -1) { - free(buf); - throw FI_MSG_ERROR_PARSING; - } - - // convert from half (16-bit) to float (32-bit) - // !!! use OpenEXR half helper class - - half half_value; - - for (uint32 l = 0; l < nrow; l++) { - WORD *src_pixel = (WORD*)(buf + l * src_line); - float *dst_pixel = (float*)bits; - - for(tmsize_t x = 0; x < (tmsize_t)(src_line / sizeof(WORD)); x++) { - half_value.setBits(src_pixel[x]); - dst_pixel[x] = half_value; - } - - bits -= dst_pitch; - } - } - - free(buf); - } - else if(planar_config == PLANARCONFIG_SEPARATE) { - // this use case was never encountered yet - throw "Unable to handle PLANARCONFIG_SEPARATE RGB half float images"; - } - - } // !header only - - } else { - // --------------------------------------------------------------------------------- - // Unknown or unsupported format - // --------------------------------------------------------------------------------- - - throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; - } - - // copy ICC profile data (must be done after FreeImage_Allocate) - - FreeImage_CreateICCProfile(dib, iccBuf, iccSize); - if (photometric == PHOTOMETRIC_SEPARATED && asCMYK) { - FreeImage_GetICCProfile(dib)->flags |= FIICC_COLOR_IS_CMYK; - } - - // copy TIFF metadata (must be done after FreeImage_Allocate) - - ReadMetadata(tif, dib); - - // copy TIFF thumbnail (must be done after FreeImage_Allocate) - - ReadThumbnail(io, handle, data, tif, dib); - - return (FIBITMAP *)dib; - - } catch (const char *message) { - if(dib) { - FreeImage_Unload(dib); - } - if(message) { - FreeImage_OutputMessageProc(s_format_id, message); - } - return NULL; - } - -} - -// -------------------------------------------------------------------------- - -static BOOL -SaveOneTIFF(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data, unsigned ifd, unsigned ifdCount) { - if (!dib || !handle || !data) { - return FALSE; - } - - try { - fi_TIFFIO *fio = (fi_TIFFIO*)data; - TIFF *out = fio->tif; - - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - - const uint32 width = FreeImage_GetWidth(dib); - const uint32 height = FreeImage_GetHeight(dib); - const uint16 bitsperpixel = (uint16)FreeImage_GetBPP(dib); - - const FIICCPROFILE* iccProfile = FreeImage_GetICCProfile(dib); - - // setup out-variables based on dib and flag options - - uint16 bitspersample; - uint16 samplesperpixel; - uint16 photometric; - - if(image_type == FIT_BITMAP) { - // standard image: 1-, 4-, 8-, 16-, 24-, 32-bit - - samplesperpixel = ((bitsperpixel == 24) ? 3 : ((bitsperpixel == 32) ? 4 : 1)); - bitspersample = bitsperpixel / samplesperpixel; - photometric = GetPhotometric(dib); - - if((bitsperpixel == 8) && FreeImage_IsTransparent(dib)) { - // 8-bit transparent picture : convert later to 8-bit + 8-bit alpha - samplesperpixel = 2; - bitspersample = 8; - } - else if(bitsperpixel == 32) { - // 32-bit images : check for CMYK or alpha transparency - - if((((iccProfile->flags & FIICC_COLOR_IS_CMYK) == FIICC_COLOR_IS_CMYK) || ((flags & TIFF_CMYK) == TIFF_CMYK))) { - // CMYK support - photometric = PHOTOMETRIC_SEPARATED; - TIFFSetField(out, TIFFTAG_INKSET, INKSET_CMYK); - TIFFSetField(out, TIFFTAG_NUMBEROFINKS, 4); - } - else if(photometric == PHOTOMETRIC_RGB) { - // transparency mask support - uint16 sampleinfo[1]; - // unassociated alpha data is transparency information - sampleinfo[0] = EXTRASAMPLE_UNASSALPHA; - TIFFSetField(out, TIFFTAG_EXTRASAMPLES, 1, sampleinfo); - } - } - } else if(image_type == FIT_RGB16) { - // 48-bit RGB - - samplesperpixel = 3; - bitspersample = bitsperpixel / samplesperpixel; - photometric = PHOTOMETRIC_RGB; - } else if(image_type == FIT_RGBA16) { - // 64-bit RGBA - - samplesperpixel = 4; - bitspersample = bitsperpixel / samplesperpixel; - if((((iccProfile->flags & FIICC_COLOR_IS_CMYK) == FIICC_COLOR_IS_CMYK) || ((flags & TIFF_CMYK) == TIFF_CMYK))) { - // CMYK support - photometric = PHOTOMETRIC_SEPARATED; - TIFFSetField(out, TIFFTAG_INKSET, INKSET_CMYK); - TIFFSetField(out, TIFFTAG_NUMBEROFINKS, 4); - } - else { - photometric = PHOTOMETRIC_RGB; - // transparency mask support - uint16 sampleinfo[1]; - // unassociated alpha data is transparency information - sampleinfo[0] = EXTRASAMPLE_UNASSALPHA; - TIFFSetField(out, TIFFTAG_EXTRASAMPLES, 1, sampleinfo); - } - } else if(image_type == FIT_RGBF) { - // 96-bit RGBF => store with a LogLuv encoding ? - - samplesperpixel = 3; - bitspersample = bitsperpixel / samplesperpixel; - // the library converts to and from floating-point XYZ CIE values - if((flags & TIFF_LOGLUV) == TIFF_LOGLUV) { - photometric = PHOTOMETRIC_LOGLUV; - TIFFSetField(out, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT); - // TIFFSetField(out, TIFFTAG_STONITS, 1.0); // assume unknown - } - else { - // store with default compression (LZW) or with input compression flag - photometric = PHOTOMETRIC_RGB; - } - - } else if (image_type == FIT_RGBAF) { - // 128-bit RGBAF => store with default compression (LZW) or with input compression flag - - samplesperpixel = 4; - bitspersample = bitsperpixel / samplesperpixel; - photometric = PHOTOMETRIC_RGB; - } else { - // special image type (int, long, double, ...) - - samplesperpixel = 1; - bitspersample = bitsperpixel; - photometric = PHOTOMETRIC_MINISBLACK; - } - - // set image data type - - WriteImageType(out, image_type); - - // write possible ICC profile - - if (iccProfile->size && iccProfile->data) { - TIFFSetField(out, TIFFTAG_ICCPROFILE, iccProfile->size, iccProfile->data); - } - - // handle standard width/height/bpp stuff - - TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width); - TIFFSetField(out, TIFFTAG_IMAGELENGTH, height); - TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel); - TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, bitspersample); - TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric); - TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); // single image plane - TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); - TIFFSetField(out, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); - TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(out, (uint32) -1)); - - // handle metrics - - WriteResolution(out, dib); - - // multi-paging - - if (page >= 0) { - char page_number[20]; - sprintf(page_number, "Page %d", page); - - TIFFSetField(out, TIFFTAG_SUBFILETYPE, (uint32)FILETYPE_PAGE); - TIFFSetField(out, TIFFTAG_PAGENUMBER, (uint16)page, (uint16)0); - TIFFSetField(out, TIFFTAG_PAGENAME, page_number); - - } else { - // is it a thumbnail ? - TIFFSetField(out, TIFFTAG_SUBFILETYPE, (ifd == 0) ? (uint32)0 : (uint32)FILETYPE_REDUCEDIMAGE); - } - - // palettes (image colormaps are automatically scaled to 16-bits) - - if (photometric == PHOTOMETRIC_PALETTE) { - uint16 *r, *g, *b; - uint16 nColors = (uint16)FreeImage_GetColorsUsed(dib); - RGBQUAD *pal = FreeImage_GetPalette(dib); - - r = (uint16 *) _TIFFmalloc(sizeof(uint16) * 3 * nColors); - if(r == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - g = r + nColors; - b = g + nColors; - - for (int i = nColors - 1; i >= 0; i--) { - r[i] = SCALE((uint16)pal[i].rgbRed); - g[i] = SCALE((uint16)pal[i].rgbGreen); - b[i] = SCALE((uint16)pal[i].rgbBlue); - } - - TIFFSetField(out, TIFFTAG_COLORMAP, r, g, b); - - _TIFFfree(r); - } - - // compression tag - - WriteCompression(out, bitspersample, samplesperpixel, photometric, flags); - - // metadata - - WriteMetadata(out, dib); - - // thumbnail tag - - if((ifd == 0) && (ifdCount > 1)) { - uint16 nsubifd = 1; - uint64 subifd[1]; - subifd[0] = 0; - TIFFSetField(out, TIFFTAG_SUBIFD, nsubifd, subifd); - } - - // read the DIB lines from bottom to top - // and save them in the TIF - // ------------------------------------- - - const uint32 pitch = FreeImage_GetPitch(dib); - - if(image_type == FIT_BITMAP) { - // standard bitmap type - - switch(bitsperpixel) { - case 1 : - case 4 : - case 8 : - { - if((bitsperpixel == 8) && FreeImage_IsTransparent(dib)) { - // 8-bit transparent picture : convert to 8-bit + 8-bit alpha - - // get the transparency table - BYTE *trns = FreeImage_GetTransparencyTable(dib); - - BYTE *buffer = (BYTE *)malloc(2 * width * sizeof(BYTE)); - if(buffer == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - for (int y = height - 1; y >= 0; y--) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - - BYTE *p = bits, *b = buffer; - - for(uint32 x = 0; x < width; x++) { - // copy the 8-bit layer - b[0] = *p; - // convert the trns table to a 8-bit alpha layer - b[1] = trns[ b[0] ]; - - p++; - b += samplesperpixel; - } - - // write the scanline to disc - - TIFFWriteScanline(out, buffer, height - y - 1, 0); - } - - free(buffer); - } - else { - // other cases - BYTE *buffer = (BYTE *)malloc(pitch * sizeof(BYTE)); - if(buffer == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - for (uint32 y = 0; y < height; y++) { - // get a copy of the scanline - memcpy(buffer, FreeImage_GetScanLine(dib, height - y - 1), pitch); - // write the scanline to disc - TIFFWriteScanline(out, buffer, y, 0); - } - free(buffer); - } - - break; - } - - case 24: - case 32: - { - BYTE *buffer = (BYTE *)malloc(pitch * sizeof(BYTE)); - if(buffer == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - for (uint32 y = 0; y < height; y++) { - // get a copy of the scanline - - memcpy(buffer, FreeImage_GetScanLine(dib, height - y - 1), pitch); - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - if (photometric != PHOTOMETRIC_SEPARATED) { - // TIFFs store color data RGB(A) instead of BGR(A) - - BYTE *pBuf = buffer; - - for (uint32 x = 0; x < width; x++) { - INPLACESWAP(pBuf[0], pBuf[2]); - pBuf += samplesperpixel; - } - } -#endif - // write the scanline to disc - - TIFFWriteScanline(out, buffer, y, 0); - } - - free(buffer); - - break; - } - }//< switch (bitsperpixel) - - } else if(image_type == FIT_RGBF && (flags & TIFF_LOGLUV) == TIFF_LOGLUV) { - // RGBF image => store as XYZ using a LogLuv encoding - - BYTE *buffer = (BYTE *)malloc(pitch * sizeof(BYTE)); - if(buffer == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - for (uint32 y = 0; y < height; y++) { - // get a copy of the scanline and convert from RGB to XYZ - tiff_ConvertLineRGBToXYZ(buffer, FreeImage_GetScanLine(dib, height - y - 1), width); - // write the scanline to disc - TIFFWriteScanline(out, buffer, y, 0); - } - free(buffer); - } else { - // just dump the dib (tiff supports all dib types) - - BYTE *buffer = (BYTE *)malloc(pitch * sizeof(BYTE)); - if(buffer == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - for (uint32 y = 0; y < height; y++) { - // get a copy of the scanline - memcpy(buffer, FreeImage_GetScanLine(dib, height - y - 1), pitch); - // write the scanline to disc - TIFFWriteScanline(out, buffer, y, 0); - } - free(buffer); - } - - // write out the directory tag if we wrote a page other than -1 or if we have a thumbnail to write later - - if( (page >= 0) || ((ifd == 0) && (ifdCount > 1)) ) { - TIFFWriteDirectory(out); - // else: TIFFClose will WriteDirectory - } - - return TRUE; - - } catch(const char *text) { - FreeImage_OutputMessageProc(s_format_id, text); - return FALSE; - } -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - BOOL bResult = FALSE; - - // handle thumbnail as SubIFD - const BOOL bHasThumbnail = (FreeImage_GetThumbnail(dib) != NULL); - const unsigned ifdCount = bHasThumbnail ? 2 : 1; - - FIBITMAP *bitmap = dib; - - for(unsigned ifd = 0; ifd < ifdCount; ifd++) { - // redirect dib to thumbnail for the second pass - if(ifd == 1) { - bitmap = FreeImage_GetThumbnail(dib); - } - - bResult = SaveOneTIFF(io, bitmap, handle, page, flags, data, ifd, ifdCount); - if(!bResult) { - return FALSE; - } - } - - return bResult; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitTIFF(Plugin *plugin, int format_id) { - s_format_id = format_id; - - // Set up the callback for extended TIFF directory tag support (see XTIFF.cpp) - // Must be called before using libtiff - XTIFFInitialize(); - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = Open; - plugin->close_proc = Close; - plugin->pagecount_proc = PageCount; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = SupportsICCProfiles; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginWBMP.cpp b/plugins/AdvaImg/src/FreeImage/PluginWBMP.cpp deleted file mode 100644 index 2ff8f023c3..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginWBMP.cpp +++ /dev/null @@ -1,372 +0,0 @@ -// ========================================================== -// Wireless Bitmap Format Loader and Writer -// -// 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" - -// ---------------------------------------------------------- -// Wireless Bitmap Format -// ---------------------- -// The WBMP format enables graphical information to be sent to a variety of handsets. -// The WBMP format is terminal independent and describes only graphical information. - -// IMPLEMENTATION NOTES: -// ------------------------ -// The WBMP format is configured according to a type field value (TypeField below), -// which maps to all relevant image encoding information, such as: -// ˇ Pixel organisation and encoding -// ˇ Palette organisation and encoding -// ˇ Compression characteristics -// ˇ Animation encoding -// For each TypeField value, all relevant image characteristics are -// fully specified as part of the WAP documentation. -// Currently, a simple compact, monochrome image format is defined -// within the WBMP type space : -// -// Image Type Identifier, multi-byte integer 0 -// Image Format description 0 B/W, no compression -// ------------------------------------------------------------------------------- - -// WBMP Header - -#ifdef _WIN32 -#pragma pack(push, 1) -#else -#pragma pack(1) -#endif - -typedef struct tagWBMPHEADER { - WORD TypeField; // Image type identifier of multi-byte length - BYTE FixHeaderField; // Octet of general header information - BYTE ExtHeaderFields; // Zero or more extension header fields - WORD Width; // Multi-byte width field - WORD Height; // Multi-byte height field -} WBMPHEADER; - -#ifdef _WIN32 -#pragma pack(pop) -#else -#pragma pack() -#endif - -// The extension headers may be of type binary 00 through binary 11, defined as follows. - -// - Type 00 indicates a multi-byte bitfield used to specify additional header information. -// The first bit is set if a type 00, extension header is set if more data follows. -// The other bits are reserved for future use. -// - Type 01 - reserved for future use. -// - Type 10 - reserved for future use. -// - Type 11 indicates a sequence of parameter/value pairs. These can be used for -// optimisations and special purpose extensions, eg, animation image formats. -// The parameter size tells the length (1-8 bytes) of the following parameter name. -// The value size gives the length (1-16 bytes) of the following parameter value. -// The concatenation flag indicates whether another parameter/value pair will follow -// after reading the specified bytes of data. - -// ========================================================== -// Internal functions -// ========================================================== - -static DWORD -multiByteRead(FreeImageIO *io, fi_handle handle) { - // Multi-byte encoding / decoding - // ------------------------------- - // A multi-byte integer consists of a series of octets, where the most significant bit - // is the continuation flag, and the remaining seven bits are a scalar value. - // The continuation flag is used to indicate that an octet is not the end of the multi-byte - // sequence. - - DWORD Out = 0; - BYTE In = 0; - - while (io->read_proc(&In, 1, 1, handle)) { - Out += (In & 0x7F); - - if ((In & 0x80) == 0x00) - break; - - Out <<= 7; - } - - return Out; -} - -static void -multiByteWrite(FreeImageIO *io, fi_handle handle, DWORD In) { - BYTE Out, k = 1; - - while (In & (0x7F << 7*k)) - k++; - - while (k > 1) { - k--; - - Out = (BYTE)(0x80 | (In >> 7*k) & 0xFF); - - io->write_proc(&Out, 1, 1, handle); - } - - Out = (BYTE)(In & 0x7F); - - io->write_proc(&Out, 1, 1, handle); -} - -static void -readExtHeader(FreeImageIO *io, fi_handle handle, BYTE b) { - // Extension header fields - // ------------------------ - // Read the extension header fields - // (since we don't use them for the moment, we skip them). - - switch (b & 0x60) { - // Type 00: read multi-byte bitfield - - case 0x00: - { - DWORD info = multiByteRead(io, handle); - break; - } - - // Type 11: read a sequence of parameter/value pairs. - - case 0x60: - { - BYTE sizeParamIdent = (b & 0x70) >> 4; // Size of Parameter Identifier (in bytes) - BYTE sizeParamValue = (b & 0x0F); // Size of Parameter Value (in bytes) - - BYTE *Ident = (BYTE*)malloc(sizeParamIdent * sizeof(BYTE)); - BYTE *Value = (BYTE*)malloc(sizeParamValue * sizeof(BYTE)); - - io->read_proc(Ident, sizeParamIdent, 1, handle); - io->read_proc(Value, sizeParamValue, 1, handle); - - free(Ident); - free(Value); - break; - } - - // reserved for future use - - case 0x20: // Type 01 - case 0x40: // Type 10 - break; - } -} - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "WBMP"; -} - -static const char * DLL_CALLCONV -Description() { - return "Wireless Bitmap"; -} - -static const char * DLL_CALLCONV -Extension() { - return "wap,wbmp,wbm"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/vnd.wap.wbmp"; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return ( - (depth == 1) - ); -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return (type == FIT_BITMAP) ? TRUE : FALSE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - WORD x, y, width, height; - FIBITMAP *dib; - BYTE *bits; // pointer to dib data - RGBQUAD *pal; // pointer to dib palette - - WBMPHEADER header; - - if (handle) { - try { - // Read header information - // ----------------------- - - // Type - - header.TypeField = (WORD)multiByteRead(io, handle); - - if (header.TypeField != 0) { - throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; - } - - // FixHeaderField - - io->read_proc(&header.FixHeaderField, 1, 1, handle); - - // ExtHeaderFields - // 1 = more will follow, 0 = last octet - - if (header.FixHeaderField & 0x80) { - header.ExtHeaderFields = 0x80; - - while(header.ExtHeaderFields & 0x80) { - io->read_proc(&header.ExtHeaderFields, 1, 1, handle); - - readExtHeader(io, handle, header.ExtHeaderFields); - } - } - - // width & height - - width = (WORD)multiByteRead(io, handle); - height = (WORD)multiByteRead(io, handle); - - // Allocate a new dib - - dib = FreeImage_Allocate(width, height, 1); - if (!dib) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // write the palette data - - pal = FreeImage_GetPalette(dib); - pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0; - pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; - - // read the bitmap data - - int line = FreeImage_GetLine(dib); - - for (y = 0; y < height; y++) { - bits = FreeImage_GetScanLine(dib, height - 1 - y); - - for (x = 0; x < line; x++) { - io->read_proc(&bits[x], 1, 1, handle); - } - } - - return dib; - - } catch(const char *text) { - FreeImage_OutputMessageProc(s_format_id, text); - - return NULL; - } - - } - - return NULL; -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - BYTE *bits; // pointer to dib data - - if ((dib) && (handle)) { - try { - if (FreeImage_GetBPP(dib) != 1) - throw "Only 1-bit depth bitmaps can be saved as WBMP"; - - // write the header - - WBMPHEADER header; - header.TypeField = 0; // Type 0: B/W, no compression - header.FixHeaderField = 0; // No ExtHeaderField - header.Width = (WORD)FreeImage_GetWidth(dib); // Image width - header.Height = (WORD)FreeImage_GetHeight(dib); // Image height - - multiByteWrite(io, handle, header.TypeField); - - io->write_proc(&header.FixHeaderField, 1, 1, handle); - - multiByteWrite(io, handle, header.Width); - multiByteWrite(io, handle, header.Height); - - // write the bitmap data - - WORD linelength = (WORD)FreeImage_GetLine(dib); - - for (WORD y = 0; y < header.Height; y++) { - bits = FreeImage_GetScanLine(dib, header.Height - 1 - y); - - io->write_proc(&bits[0], linelength, 1, handle); - } - - return TRUE; - - } catch (const char* text) { - FreeImage_OutputMessageProc(s_format_id, text); - } - } - - return FALSE; -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitWBMP(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = NULL; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; -} diff --git a/plugins/AdvaImg/src/FreeImage/PluginWebP.cpp b/plugins/AdvaImg/src/FreeImage/PluginWebP.cpp deleted file mode 100644 index 9fb0b69447..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginWebP.cpp +++ /dev/null @@ -1,698 +0,0 @@ -// ========================================================== -// Google WebP Loader & Writer -// -// Design and implementation by -// - Herve 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" - -#include "../Metadata/FreeImageTag.h" - -#include "../LibWebP/src/webp/decode.h" -#include "../LibWebP/src/webp/encode.h" -#include "../LibWebP/src/enc/vp8enci.h" -#include "../LibWebP/src/webp/mux.h" - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ---------------------------------------------------------- -// Helpers for the load function -// ---------------------------------------------------------- - -/** -Read the whole file into memory -*/ -static BOOL -ReadFileToWebPData(FreeImageIO *io, fi_handle handle, WebPData * const bitstream) { - uint8_t *raw_data = NULL; - - try { - // Read the input file and put it in memory - long start_pos = io->tell_proc(handle); - io->seek_proc(handle, 0, SEEK_END); - size_t file_length = (size_t)(io->tell_proc(handle) - start_pos); - io->seek_proc(handle, start_pos, SEEK_SET); - raw_data = (uint8_t*)malloc(file_length * sizeof(uint8_t)); - if(!raw_data) { - throw FI_MSG_ERROR_MEMORY; - } - if(io->read_proc(raw_data, 1, (unsigned)file_length, handle) != file_length) { - throw "Error while reading input stream"; - } - - // copy pointers (must be released later using free) - bitstream->bytes = raw_data; - bitstream->size = file_length; - - return TRUE; - - } catch(const char *text) { - if(raw_data) { - free(raw_data); - } - memset(bitstream, 0, sizeof(WebPData)); - if(NULL != text) { - FreeImage_OutputMessageProc(s_format_id, text); - } - return FALSE; - } -} - -// ---------------------------------------------------------- -// Helpers for the save function -// ---------------------------------------------------------- - -/** -Output function. Should return 1 if writing was successful. -data/data_size is the segment of data to write, and 'picture' is for -reference (and so one can make use of picture->custom_ptr). -*/ -static int -WebP_MemoryWriter(const BYTE *data, size_t data_size, const WebPPicture* const picture) { - FIMEMORY *hmem = (FIMEMORY*)picture->custom_ptr; - return data_size ? (FreeImage_WriteMemory(data, 1, (unsigned)data_size, hmem) == data_size) : 0; -} - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "WebP"; -} - -static const char * DLL_CALLCONV -Description() { - return "Google WebP image format"; -} - -static const char * DLL_CALLCONV -Extension() { - return "webp"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/webp"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - BYTE riff_signature[4] = { 0x52, 0x49, 0x46, 0x46 }; - BYTE webp_signature[4] = { 0x57, 0x45, 0x42, 0x50 }; - BYTE signature[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - io->read_proc(signature, 1, 12, handle); - - if(memcmp(riff_signature, signature, 4) == 0) { - if(memcmp(webp_signature, signature + 8, 4) == 0) { - return TRUE; - } - } - - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return ( - (depth == 24) || - (depth == 32) - ); -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return (type == FIT_BITMAP) ? TRUE : FALSE; -} - -static BOOL DLL_CALLCONV -SupportsICCProfiles() { - return TRUE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static void * DLL_CALLCONV -Open(FreeImageIO *io, fi_handle handle, BOOL read) { - WebPMux *mux = NULL; - int copy_data = 1; // 1 : copy data into the mux, 0 : keep a link to local data - - if(read) { - // create the MUX object from the input stream - WebPData bitstream; - // read the input file and put it in memory - if(!ReadFileToWebPData(io, handle, &bitstream)) { - return NULL; - } - // create the MUX object - mux = WebPMuxCreate(&bitstream, copy_data); - // no longer needed since copy_data == 1 - free((void*)bitstream.bytes); - if(mux == NULL) { - FreeImage_OutputMessageProc(s_format_id, "Failed to create mux object from file"); - return NULL; - } - } else { - // creates an empty mux object - mux = WebPMuxNew(); - if(mux == NULL) { - FreeImage_OutputMessageProc(s_format_id, "Failed to create empty mux object"); - return NULL; - } - } - - return mux; -} - -static void DLL_CALLCONV -Close(FreeImageIO *io, fi_handle handle, void *data) { - WebPMux *mux = (WebPMux*)data; - if(mux != NULL) { - // free the MUX object - WebPMuxDelete(mux); - } -} - -// ---------------------------------------------------------- - -/** -Decode a WebP image and returns a FIBITMAP image -@param webp_image Raw WebP image -@param flags FreeImage load flags -@return Returns a dib if successfull, returns NULL otherwise -*/ -static FIBITMAP * -DecodeImage(WebPData *webp_image, int flags) { - FIBITMAP *dib = NULL; - - const uint8_t* data = webp_image->bytes; // raw image data - const size_t data_size = webp_image->size; // raw image size - - VP8StatusCode webp_status = VP8_STATUS_OK; - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // Main object storing the configuration for advanced decoding - WebPDecoderConfig decoder_config; - // Output buffer - WebPDecBuffer* const output_buffer = &decoder_config.output; - // Features gathered from the bitstream - WebPBitstreamFeatures* const bitstream = &decoder_config.input; - - try { - // Initialize the configuration as empty - // This function must always be called first, unless WebPGetFeatures() is to be called - if(!WebPInitDecoderConfig(&decoder_config)) { - throw "Library version mismatch"; - } - - // Retrieve features from the bitstream - // The bitstream structure is filled with information gathered from the bitstream - webp_status = WebPGetFeatures(data, data_size, bitstream); - if(webp_status != VP8_STATUS_OK) { - throw FI_MSG_ERROR_PARSING; - } - - // Allocate output dib - - unsigned bpp = bitstream->has_alpha ? 32 : 24; - unsigned width = (unsigned)bitstream->width; - unsigned height = (unsigned)bitstream->height; - - dib = FreeImage_AllocateHeader(header_only, width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if(!dib) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - if(header_only) { - WebPFreeDecBuffer(output_buffer); - return dib; - } - - // --- Set decoding options --- - - // use multi-threaded decoding - decoder_config.options.use_threads = 1; - // set output color space - output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR; - - // --- - - // decode the input stream, taking 'config' into account. - - webp_status = WebPDecode(data, data_size, &decoder_config); - if(webp_status != VP8_STATUS_OK) { - throw FI_MSG_ERROR_PARSING; - } - - // fill the dib with the decoded data - - const BYTE *src_bitmap = output_buffer->u.RGBA.rgba; - const unsigned src_pitch = (unsigned)output_buffer->u.RGBA.stride; - - switch(bpp) { - case 24: - for(unsigned y = 0; y < height; y++) { - const BYTE *src_bits = src_bitmap + y * src_pitch; - BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, height-1-y); - for(unsigned x = 0; x < width; x++) { - dst_bits[FI_RGBA_BLUE] = src_bits[0]; // B - dst_bits[FI_RGBA_GREEN] = src_bits[1]; // G - dst_bits[FI_RGBA_RED] = src_bits[2]; // R - src_bits += 3; - dst_bits += 3; - } - } - break; - case 32: - for(unsigned y = 0; y < height; y++) { - const BYTE *src_bits = src_bitmap + y * src_pitch; - BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, height-1-y); - for(unsigned x = 0; x < width; x++) { - dst_bits[FI_RGBA_BLUE] = src_bits[0]; // B - dst_bits[FI_RGBA_GREEN] = src_bits[1]; // G - dst_bits[FI_RGBA_RED] = src_bits[2]; // R - dst_bits[FI_RGBA_ALPHA] = src_bits[3]; // A - src_bits += 4; - dst_bits += 4; - } - } - break; - } - - // Free the decoder - WebPFreeDecBuffer(output_buffer); - - return dib; - - } catch (const char *text) { - if(dib) { - FreeImage_Unload(dib); - } - WebPFreeDecBuffer(output_buffer); - - if(NULL != text) { - FreeImage_OutputMessageProc(s_format_id, text); - } - - return NULL; - } -} - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - WebPMux *mux = NULL; - WebPMuxFrameInfo webp_frame = { 0 }; // raw image - WebPData color_profile; // ICC raw data - WebPData xmp_metadata; // XMP raw data - WebPData exif_metadata; // EXIF raw data - FIBITMAP *dib = NULL; - WebPMuxError error_status; - - if(!handle) { - return NULL; - } - - try { - // get the MUX object - mux = (WebPMux*)data; - if(!mux) { - throw (1); - } - - // gets the feature flags from the mux object - uint32_t webp_flags = 0; - error_status = WebPMuxGetFeatures(mux, &webp_flags); - if(error_status != WEBP_MUX_OK) { - throw (1); - } - - // get image data - error_status = WebPMuxGetFrame(mux, 1, &webp_frame); - - if(error_status == WEBP_MUX_OK) { - // decode the data (can be limited to the header if flags uses FIF_LOAD_NOPIXELS) - dib = DecodeImage(&webp_frame.bitstream, flags); - if(!dib) { - throw (1); - } - - // get ICC profile - if(webp_flags & ICCP_FLAG) { - error_status = WebPMuxGetChunk(mux, "ICCP", &color_profile); - if(error_status == WEBP_MUX_OK) { - FreeImage_CreateICCProfile(dib, (void*)color_profile.bytes, (long)color_profile.size); - } - } - - // get XMP metadata - if(webp_flags & XMP_FLAG) { - error_status = WebPMuxGetChunk(mux, "XMP ", &xmp_metadata); - if(error_status == WEBP_MUX_OK) { - // create a tag - FITAG *tag = FreeImage_CreateTag(); - if(tag) { - FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName); - FreeImage_SetTagLength(tag, (DWORD)xmp_metadata.size); - FreeImage_SetTagCount(tag, (DWORD)xmp_metadata.size); - FreeImage_SetTagType(tag, FIDT_ASCII); - FreeImage_SetTagValue(tag, xmp_metadata.bytes); - - // store the tag - FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag); - - // destroy the tag - FreeImage_DeleteTag(tag); - } - } - } - - // get Exif metadata - if(webp_flags & EXIF_FLAG) { - error_status = WebPMuxGetChunk(mux, "EXIF", &exif_metadata); - if(error_status == WEBP_MUX_OK) { - // read the Exif raw data as a blob - jpeg_read_exif_profile_raw(dib, exif_metadata.bytes, (unsigned)exif_metadata.size); - // read and decode the Exif data - jpeg_read_exif_profile(dib, exif_metadata.bytes, (unsigned)exif_metadata.size); - } - } - } - - WebPDataClear(&webp_frame.bitstream); - - return dib; - - } catch(int) { - WebPDataClear(&webp_frame.bitstream); - return NULL; - } -} - -// -------------------------------------------------------------------------- - -/** -Encode a FIBITMAP to a WebP image -@param hmem Memory output stream, containing on return the encoded image -@param dib The FIBITMAP to encode -@param flags FreeImage save flags -@return Returns TRUE if successfull, returns FALSE otherwise -*/ -static BOOL -EncodeImage(FIMEMORY *hmem, FIBITMAP *dib, int flags) { - WebPPicture picture; // Input buffer - WebPConfig config; // Coding parameters - - BOOL bIsFlipped = FALSE; - - try { - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - const unsigned bpp = FreeImage_GetBPP(dib); - const unsigned pitch = FreeImage_GetPitch(dib); - - // check image type - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - - if( !((image_type == FIT_BITMAP) && ((bpp == 24) || (bpp == 32))) ) { - throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; - } - - // check format limits - if(MAX(width, height) > WEBP_MAX_DIMENSION) { - FreeImage_OutputMessageProc(s_format_id, "Unsupported image size: width x height = %d x %d", width, height); - return FALSE; - } - - // Initialize output I/O - if(WebPPictureInit(&picture) == 1) { - picture.writer = WebP_MemoryWriter; - picture.custom_ptr = hmem; - picture.width = (int)width; - picture.height = (int)height; - } else { - throw "Couldn't initialize WebPPicture"; - } - - // --- Set encoding parameters --- - - // Initialize encoding parameters to default values - WebPConfigInit(&config); - - // quality/speed trade-off (0=fast, 6=slower-better) - config.method = 6; - - if((flags & WEBP_LOSSLESS) == WEBP_LOSSLESS) { - // lossless encoding - config.lossless = 1; - picture.use_argb = 1; - } else if((flags & 0x7F) > 0) { - // lossy encoding - config.lossless = 0; - // quality is between 1 (smallest file) and 100 (biggest) - default to 75 - config.quality = (float)(flags & 0x7F); - if(config.quality > 100) { - config.quality = 100; - } - } - - // validate encoding parameters - if(WebPValidateConfig(&config) == 0) { - throw "Failed to initialize encoder"; - } - - // --- Perform encoding --- - - // Invert dib scanlines - bIsFlipped = FreeImage_FlipVertical(dib); - - - // convert dib buffer to output stream - - const BYTE *bits = FreeImage_GetBits(dib); - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - switch(bpp) { - case 24: - WebPPictureImportBGR(&picture, bits, pitch); - break; - case 32: - WebPPictureImportBGRA(&picture, bits, pitch); - break; - } -#else - switch(bpp) { - case 24: - WebPPictureImportRGB(&picture, bits, pitch); - break; - case 32: - WebPPictureImportRGBA(&picture, bits, pitch); - break; - } - -#endif // FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - - if(!WebPEncode(&config, &picture)) { - throw "Failed to encode image"; - } - - WebPPictureFree(&picture); - - if(bIsFlipped) { - // invert dib scanlines - FreeImage_FlipVertical(dib); - } - - return TRUE; - - } catch (const char* text) { - - WebPPictureFree(&picture); - - if(bIsFlipped) { - // invert dib scanlines - FreeImage_FlipVertical(dib); - } - - if(NULL != text) { - FreeImage_OutputMessageProc(s_format_id, text); - } - } - - 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; - } -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitWEBP(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = Open; - plugin->close_proc = Close; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = SupportsICCProfiles; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} - diff --git a/plugins/AdvaImg/src/FreeImage/PluginXBM.cpp b/plugins/AdvaImg/src/FreeImage/PluginXBM.cpp deleted file mode 100644 index 0aac48ca27..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginXBM.cpp +++ /dev/null @@ -1,399 +0,0 @@ -// ========================================================== -// XBM Loader -// -// Design and implementation by -// - Hervé Drolon <drolon@infonie.fr> -// part of the code adapted from the netPBM package (xbmtopbm.c) -// -// 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" - -// ========================================================== -// Internal functions -// ========================================================== - -#define MAX_LINE 512 - -static const char *ERR_XBM_SYNTAX = "Syntax error"; -static const char *ERR_XBM_LINE = "Line too long"; -static const char *ERR_XBM_DECL = "Unable to find a line in the file containing the start of C array declaration (\"static char\" or whatever)"; -static const char *ERR_XBM_EOFREAD = "EOF / read error"; -static const char *ERR_XBM_WIDTH = "Invalid width"; -static const char *ERR_XBM_HEIGHT = "Invalid height"; -static const char *ERR_XBM_MEMORY = "Out of memory"; - -/** -Get a string from a stream. -Read the string from the current stream to the first newline character. -The result stored in str is appended with a null character. -@param str Storage location for data -@param n Maximum number of characters to read -@param io Pointer to the FreeImageIO structure -@param handle Handle to the stream -@return Returns str. NULL is returned to indicate an error or an end-of-file condition. -*/ -static char* -readLine(char *str, int n, FreeImageIO *io, fi_handle handle) { - char c; - int count, i = 0; - do { - count = io->read_proc(&c, 1, 1, handle); - str[i++] = c; - } while((c != '\n') && (i < n)); - if(count <= 0) - return NULL; - str[i] = '\0'; - return str; -} - -/** -Get a char from the stream -@param io Pointer to the FreeImageIO structure -@param handle Handle to the stream -@return Returns the next character in the stream -*/ -static int -readChar(FreeImageIO *io, fi_handle handle) { - BYTE c; - io->read_proc(&c, 1, 1, handle); - return c; -} - -/** -Read an XBM file into a buffer -@param io Pointer to the FreeImageIO structure -@param handle Handle to the stream -@param widthP (return value) Pointer to the bitmap width -@param heightP (return value) Pointer to the bitmap height -@param dataP (return value) Pointer to the bitmap buffer -@return Returns NULL if OK, returns an error message otherwise -*/ -static const char* -readXBMFile(FreeImageIO *io, fi_handle handle, int *widthP, int *heightP, char **dataP) { - char line[MAX_LINE], name_and_type[MAX_LINE]; - char* ptr; - char* t; - int version = 0; - int raster_length, v; - int bytes, bytes_per_line, padding; - int c1, c2, value1, value2; - int hex_table[256]; - BOOL found_declaration; - /* in scanning through the bitmap file, we have found the first - line of the C declaration of the array (the "static char ..." - or whatever line) - */ - BOOL eof; // we've encountered end of file while searching file - - *widthP = *heightP = -1; - - found_declaration = FALSE; // haven't found it yet; haven't even looked - eof = FALSE; // haven't encountered end of file yet - - while(!found_declaration && !eof) { - - if( readLine(line, MAX_LINE, io, handle) == NULL) { - eof = TRUE; - } - else { - if( strlen( line ) == MAX_LINE - 1 ) - return( ERR_XBM_LINE ); - if( sscanf(line, "#define %s %d", name_and_type, &v) == 2 ) { - if( ( t = strrchr( name_and_type, '_' ) ) == NULL ) - t = name_and_type; - else - t++; - if ( ! strcmp( "width", t ) ) - *widthP = v; - else if ( ! strcmp( "height", t ) ) - *heightP = v; - continue; - } - - if( sscanf( line, "static short %s = {", name_and_type ) == 1 ) { - version = 10; - found_declaration = TRUE; - } - else if( sscanf( line, "static char %s = {", name_and_type ) == 1 ) { - version = 11; - found_declaration = TRUE; - } - else if(sscanf(line, "static unsigned char %s = {", name_and_type ) == 1 ) { - version = 11; - found_declaration = TRUE; - } - } - } - - if(!found_declaration) - return( ERR_XBM_DECL ); - - if(*widthP == -1 ) - return( ERR_XBM_WIDTH ); - if( *heightP == -1 ) - return( ERR_XBM_HEIGHT ); - - padding = 0; - if ( ((*widthP % 16) >= 1) && ((*widthP % 16) <= 8) && (version == 10) ) - padding = 1; - - bytes_per_line = (*widthP + 7) / 8 + padding; - - raster_length = bytes_per_line * *heightP; - *dataP = (char*) malloc( raster_length ); - if ( *dataP == (char*) 0 ) - return( ERR_XBM_MEMORY ); - - // initialize hex_table - for ( c1 = 0; c1 < 256; c1++ ) { - hex_table[c1] = 256; - } - hex_table['0'] = 0; - hex_table['1'] = 1; - hex_table['2'] = 2; - hex_table['3'] = 3; - hex_table['4'] = 4; - hex_table['5'] = 5; - hex_table['6'] = 6; - hex_table['7'] = 7; - hex_table['8'] = 8; - hex_table['9'] = 9; - hex_table['A'] = 10; - hex_table['B'] = 11; - hex_table['C'] = 12; - hex_table['D'] = 13; - hex_table['E'] = 14; - hex_table['F'] = 15; - hex_table['a'] = 10; - hex_table['b'] = 11; - hex_table['c'] = 12; - hex_table['d'] = 13; - hex_table['e'] = 14; - hex_table['f'] = 15; - - if(version == 10) { - for( bytes = 0, ptr = *dataP; bytes < raster_length; bytes += 2 ) { - while( ( c1 = readChar(io, handle) ) != 'x' ) { - if ( c1 == EOF ) - return( ERR_XBM_EOFREAD ); - } - - c1 = readChar(io, handle); - c2 = readChar(io, handle); - if( c1 == EOF || c2 == EOF ) - return( ERR_XBM_EOFREAD ); - value1 = ( hex_table[c1] << 4 ) + hex_table[c2]; - if ( value1 >= 256 ) - return( ERR_XBM_SYNTAX ); - c1 = readChar(io, handle); - c2 = readChar(io, handle); - if( c1 == EOF || c2 == EOF ) - return( ERR_XBM_EOFREAD ); - value2 = ( hex_table[c1] << 4 ) + hex_table[c2]; - if ( value2 >= 256 ) - return( ERR_XBM_SYNTAX ); - *ptr++ = (char)value2; - if ( ( ! padding ) || ( ( bytes + 2 ) % bytes_per_line ) ) - *ptr++ = (char)value1; - } - } - else { - for(bytes = 0, ptr = *dataP; bytes < raster_length; bytes++ ) { - /* - ** skip until digit is found - */ - for( ; ; ) { - c1 = readChar(io, handle); - if ( c1 == EOF ) - return( ERR_XBM_EOFREAD ); - value1 = hex_table[c1]; - if ( value1 != 256 ) - break; - } - /* - ** loop on digits - */ - for( ; ; ) { - c2 = readChar(io, handle); - if ( c2 == EOF ) - return( ERR_XBM_EOFREAD ); - value2 = hex_table[c2]; - if ( value2 != 256 ) { - value1 = (value1 << 4) | value2; - if ( value1 >= 256 ) - return( ERR_XBM_SYNTAX ); - } - else if ( c2 == 'x' || c2 == 'X' ) { - if ( value1 == 0 ) - continue; - else return( ERR_XBM_SYNTAX ); - } - else break; - } - *ptr++ = (char)value1; - } - } - - return NULL; -} - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "XBM"; -} - -static const char * DLL_CALLCONV -Description() { - return "X11 Bitmap Format"; -} - -static const char * DLL_CALLCONV -Extension() { - return "xbm"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-xbitmap"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - char magic[8]; - if(readLine(magic, 7, io, handle)) { - if(strcmp(magic, "#define") == 0) - return TRUE; - } - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return FALSE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - char *buffer = NULL; - int width, height; - FIBITMAP *dib = NULL; - - try { - - // load the bitmap data - const char* error = readXBMFile(io, handle, &width, &height, &buffer); - // Microsoft doesn't implement throw between functions :( - if(error) throw (char*)error; - - - // allocate a new dib - dib = FreeImage_Allocate(width, height, 1); - if(!dib) throw (char*)ERR_XBM_MEMORY; - - // write the palette data - RGBQUAD *pal = FreeImage_GetPalette(dib); - pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0; - pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; - - // copy the bitmap - BYTE *bP = (BYTE*)buffer; - for(int y = 0; y < height; y++) { - BYTE count = 0; - BYTE mask = 1; - BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y); - - for(int x = 0; x < width; x++) { - if(count >= 8) { - bP++; - count = 0; - mask = 1; - } - if(*bP & mask) { - // Set bit(x, y) to 0 - bits[x >> 3] &= (0xFF7F >> (x & 0x7)); - } else { - // Set bit(x, y) to 1 - bits[x >> 3] |= (0x80 >> (x & 0x7)); - } - count++; - mask <<= 1; - } - bP++; - } - - free(buffer); - return dib; - - } catch(const char *text) { - if(buffer) free(buffer); - if(dib) FreeImage_Unload(dib); - FreeImage_OutputMessageProc(s_format_id, text); - return NULL; - } -} - - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitXBM(Plugin *plugin, int format_id) { - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = NULL; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; -} - diff --git a/plugins/AdvaImg/src/FreeImage/PluginXPM.cpp b/plugins/AdvaImg/src/FreeImage/PluginXPM.cpp deleted file mode 100644 index a698321958..0000000000 --- a/plugins/AdvaImg/src/FreeImage/PluginXPM.cpp +++ /dev/null @@ -1,487 +0,0 @@ -// ========================================================== -// XPM Loader and Writer -// -// Design and implementation by -// - Ryan Rubley (ryan@lostreality.org) -// -// 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! -// ========================================================== - -#ifdef _MSC_VER -#pragma warning (disable : 4786) // identifier was truncated to 'number' characters -#endif - -// IMPLEMENTATION NOTES: -// ------------------------ -// Initial design and implementation by -// - Karl-Heinz Bussian (khbussian@moss.de) -// - Hervé Drolon (drolon@infonie.fr) -// Completely rewritten from scratch by Ryan Rubley (ryan@lostreality.org) -// in order to address the following major fixes: -// * Supports any number of chars per pixel (not just 1 or 2) -// * Files with 2 chars per pixel but <= 256colors are loaded as 256 color (not 24bit) -// * Loads much faster, uses much less memory -// * supports #rgb #rrrgggbbb and #rrrrggggbbbb colors (not just #rrggbb) -// * supports symbolic color names -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ========================================================== -// Plugin Interface -// ========================================================== -static int s_format_id; - -// ========================================================== -// Internal Functions -// ========================================================== - -// read in and skip all junk until we find a certain char -static BOOL -FindChar(FreeImageIO *io, fi_handle handle, BYTE look_for) { - BYTE c; - io->read_proc(&c, sizeof(BYTE), 1, handle); - while(c != look_for) { - if( io->read_proc(&c, sizeof(BYTE), 1, handle) != 1 ) - return FALSE; - } - return TRUE; -} - -// find start of string, read data until ending quote found, allocate memory and return a string -static char * -ReadString(FreeImageIO *io, fi_handle handle) { - if( !FindChar(io, handle,'"') ) - return NULL; - BYTE c; - std::string s; - io->read_proc(&c, sizeof(BYTE), 1, handle); - while(c != '"') { - s += c; - if( io->read_proc(&c, sizeof(BYTE), 1, handle) != 1 ) - return NULL; - } - char *cstr = (char *)malloc(s.length()+1); - strcpy(cstr,s.c_str()); - return cstr; -} - -static char * -Base92(unsigned int num) { - static char b92[16]; //enough for more then 64 bits - static char digit[] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|"; - b92[15] = '\0'; - int i = 14; - do { - b92[i--] = digit[num % 92]; - num /= 92; - } while( num && i >= 0 ); - return b92+i+1; -} - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "XPM"; -} - -static const char * DLL_CALLCONV -Description() { - return "X11 Pixmap Format"; -} - -static const char * DLL_CALLCONV -Extension() { - return "xpm"; -} - -static const char * DLL_CALLCONV -RegExpr() { - return "^[ \\t]*/\\* XPM \\*/[ \\t]$"; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-xpixmap"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - char buffer[256]; - - // checks the first 256 characters for the magic string - int count = io->read_proc(buffer, 1, 256, handle); - if(count <= 9) return FALSE; - for(int i = 0; i < (count - 9); i++) { - if(strncmp(&buffer[i], "/* XPM */", 9) == 0) - return TRUE; - } - return FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportDepth(int depth) { - return ( - (depth == 8) || - (depth == 24) - ); -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return (type == FIT_BITMAP) ? TRUE : FALSE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - char msg[256]; - FIBITMAP *dib = NULL; - - if (!handle) return NULL; - - try { - char *str; - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - //find the starting brace - if( !FindChar(io, handle,'{') ) - throw "Could not find starting brace"; - - //read info string - str = ReadString(io, handle); - if(!str) - throw "Error reading info string"; - - int width, height, colors, cpp; - if( sscanf(str, "%d %d %d %d", &width, &height, &colors, &cpp) != 4 ) { - free(str); - throw "Improperly formed info string"; - } - free(str); - - if (colors > 256) { - dib = FreeImage_AllocateHeader(header_only, width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } else { - dib = FreeImage_AllocateHeader(header_only, width, height, 8); - } - - //build a map of color chars to rgb values - std::map<std::string,FILE_RGBA> rawpal; //will store index in Alpha if 8bpp - for(int i = 0; i < colors; i++ ) { - FILE_RGBA rgba; - - str = ReadString(io, handle); - if(!str) - throw "Error reading color strings"; - - std::string chrs(str,cpp); //create a string for the color chars using the first cpp chars - char *keys = str + cpp; //the color keys for these chars start after the first cpp chars - - //translate all the tabs to spaces - char *tmp = keys; - while( strchr(tmp,'\t') ) { - tmp = strchr(tmp,'\t'); - *tmp++ = ' '; - } - - //prefer the color visual - if( strstr(keys," c ") ) { - char *clr = strstr(keys," c ") + 3; - while( *clr == ' ' ) clr++; //find the start of the hex rgb value - if( *clr == '#' ) { - int red = 0, green = 0, blue = 0, n; - clr++; - //end string at first space, if any found - if( strchr(clr,' ') ) - *(strchr(clr,' ')) = '\0'; - //parse hex color, it can be #rgb #rrggbb #rrrgggbbb or #rrrrggggbbbb - switch( strlen(clr) ) { - case 3: n = sscanf(clr,"%01x%01x%01x",&red,&green,&blue); - red |= (red << 4); - green |= (green << 4); - blue |= (blue << 4); - break; - case 6: n = sscanf(clr,"%02x%02x%02x",&red,&green,&blue); - break; - case 9: n = sscanf(clr,"%03x%03x%03x",&red,&green,&blue); - red >>= 4; - green >>= 4; - blue >>= 4; - break; - case 12: n = sscanf(clr,"%04x%04x%04x",&red,&green,&blue); - red >>= 8; - green >>= 8; - blue >>= 8; - break; - default: - n = 0; - break; - } - if( n != 3 ) { - free(str); - throw "Improperly formed hex color value"; - } - rgba.r = (BYTE)red; - rgba.g = (BYTE)green; - rgba.b = (BYTE)blue; - } else if( !strncmp(clr,"None",4) || !strncmp(clr,"none",4) ) { - rgba.r = rgba.g = rgba.b = 0xFF; - } else { - char *tmp = clr; - - //scan forward for each space, if its " x " or " xx " end the string there - //this means its probably some other visual data beyond that point and not - //part of the color name. How many named color end with a 1 or 2 character - //word? Probably none in our list at least. - while( (tmp = strchr(tmp,' ')) != NULL ) { - if( tmp[1] != ' ' ) { - if( (tmp[2] == ' ') || (tmp[2] != ' ' && tmp[3] == ' ') ) { - tmp[0] = '\0'; - break; - } - } - tmp++; - } - - //remove any trailing spaces - tmp = clr+strlen(clr)-1; - while( *tmp == ' ' ) { - *tmp = '\0'; - tmp--; - } - - if (!FreeImage_LookupX11Color(clr, &rgba.r, &rgba.g, &rgba.b)) { - sprintf(msg, "Unknown color name '%s'", str); - free(str); - throw msg; - } - } - } else { - free(str); - throw "Only color visuals are supported"; - } - - //add color to map - rgba.a = (BYTE)((colors > 256) ? 0 : i); - rawpal[chrs] = rgba; - - //build palette if needed - if( colors <= 256 ) { - RGBQUAD *pal = FreeImage_GetPalette(dib); - pal[i].rgbBlue = rgba.b; - pal[i].rgbGreen = rgba.g; - pal[i].rgbRed = rgba.r; - } - - free(str); - } - //done parsing color map - - if(header_only) { - // header only mode - return dib; - } - - //read in pixel data - for(int y = 0; y < height; y++ ) { - BYTE *line = FreeImage_GetScanLine(dib, height - y - 1); - str = ReadString(io, handle); - if(!str) - throw "Error reading pixel strings"; - char *pixel_ptr = str; - - for(int x = 0; x < width; x++ ) { - //locate the chars in the color map - std::string chrs(pixel_ptr,cpp); - FILE_RGBA rgba = rawpal[chrs]; - - if( colors > 256 ) { - line[FI_RGBA_BLUE] = rgba.b; - line[FI_RGBA_GREEN] = rgba.g; - line[FI_RGBA_RED] = rgba.r; - line += 3; - } else { - *line = rgba.a; - line++; - } - - pixel_ptr += cpp; - } - - free(str); - } - //done reading pixel data - - return dib; - } catch(const char *text) { - FreeImage_OutputMessageProc(s_format_id, text); - - if( dib != NULL ) - FreeImage_Unload(dib); - - return NULL; - } -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - if ((dib != NULL) && (handle != NULL)) { - char header[] = "/* XPM */\nstatic char *freeimage[] = {\n/* width height num_colors chars_per_pixel */\n\"", - start_colors[] = "\",\n/* colors */\n\"", - start_pixels[] = "\",\n/* pixels */\n\"", - new_line[] = "\",\n\"", - footer[] = "\"\n};\n", - buf[256]; //256 is more then enough to sprintf 4 ints into, or the base-92 chars and #rrggbb line - - if( io->write_proc(header, (unsigned int)strlen(header), 1, handle) != 1 ) - return FALSE; - - int width = FreeImage_GetWidth(dib), height = FreeImage_GetHeight(dib), bpp = FreeImage_GetBPP(dib); - RGBQUAD *pal = FreeImage_GetPalette(dib); - int x,y; - - //map base92 chrs to the rgb value to create the palette - std::map<DWORD,FILE_RGB> chrs2color; - //map 8bpp index or 24bpp rgb value to the base92 chrs to create pixel data - typedef union { - DWORD index; - FILE_RGBA rgba; - } DWORDRGBA; - std::map<DWORD,std::string> color2chrs; - - //loop thru entire dib, if new color, inc num_colors and add to both maps - int num_colors = 0; - for(y = 0; y < height; y++ ) { - BYTE *line = FreeImage_GetScanLine(dib, height - y - 1); - for(x = 0; x < width; x++ ) { - FILE_RGB rgb; - DWORDRGBA u; - if( bpp > 8 ) { - u.rgba.b = rgb.b = line[FI_RGBA_BLUE]; - u.rgba.g = rgb.g = line[FI_RGBA_GREEN]; - u.rgba.r = rgb.r = line[FI_RGBA_RED]; - u.rgba.a = 0; - line += 3; - } else { - u.index = *line; - rgb.b = pal[u.index].rgbBlue; - rgb.g = pal[u.index].rgbGreen; - rgb.r = pal[u.index].rgbRed; - line++; - } - if( color2chrs.find(u.index) == color2chrs.end() ) { //new color - std::string chrs(Base92(num_colors)); - color2chrs[u.index] = chrs; - chrs2color[num_colors] = rgb; - num_colors++; - } - } - } - - int cpp = (int)(log((double)num_colors)/log(92.0)) + 1; - - sprintf(buf, "%d %d %d %d", FreeImage_GetWidth(dib), FreeImage_GetHeight(dib), num_colors, cpp ); - if( io->write_proc(buf, (unsigned int)strlen(buf), 1, handle) != 1 ) - return FALSE; - - if( io->write_proc(start_colors, (unsigned int)strlen(start_colors), 1, handle) != 1 ) - return FALSE; - - //write colors, using map of chrs->rgb - for(x = 0; x < num_colors; x++ ) { - sprintf(buf, "%*s c #%02x%02x%02x", cpp, Base92(x), chrs2color[x].r, chrs2color[x].g, chrs2color[x].b ); - if( io->write_proc(buf, (unsigned int)strlen(buf), 1, handle) != 1 ) - return FALSE; - if( x == num_colors - 1 ) { - if( io->write_proc(start_pixels, (unsigned int)strlen(start_pixels), 1, handle) != 1 ) - return FALSE; - } else { - if( io->write_proc(new_line, (unsigned int)strlen(new_line), 1, handle) != 1 ) - return FALSE; - } - } - - - //write pixels, using map of rgb(if 24bpp) or index(if 8bpp)->chrs - for(y = 0; y < height; y++ ) { - BYTE *line = FreeImage_GetScanLine(dib, height - y - 1); - for(x = 0; x < width; x++ ) { - DWORDRGBA u; - if( bpp > 8 ) { - u.rgba.b = line[FI_RGBA_BLUE]; - u.rgba.g = line[FI_RGBA_GREEN]; - u.rgba.r = line[FI_RGBA_RED]; - u.rgba.a = 0; - line += 3; - } else { - u.index = *line; - line++; - } - sprintf(buf, "%*s", cpp, (char *)color2chrs[u.index].c_str()); - if( io->write_proc(buf, cpp, 1, handle) != 1 ) - return FALSE; - } - if( y == height - 1 ) { - if( io->write_proc(footer, (unsigned int)strlen(footer), 1, handle) != 1 ) - return FALSE; - } else { - if( io->write_proc(new_line, (unsigned int)strlen(new_line), 1, handle) != 1 ) - return FALSE; - } - } - - return TRUE; - } else { - return FALSE; - } -} - -// ========================================================== -// Init -// ========================================================== - -void DLL_CALLCONV -InitXPM(Plugin *plugin, int format_id) -{ - s_format_id = format_id; - - plugin->format_proc = Format; - plugin->description_proc = Description; - plugin->extension_proc = Extension; - plugin->regexpr_proc = RegExpr; - plugin->open_proc = NULL; - plugin->close_proc = NULL; - plugin->pagecount_proc = NULL; - plugin->pagecapability_proc = NULL; - plugin->load_proc = Load; - plugin->save_proc = Save; - plugin->validate_proc = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = NULL; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} - |