diff options
Diffstat (limited to 'plugins/FreeImage/Source/FreeImage/PSDParser.cpp')
-rw-r--r-- | plugins/FreeImage/Source/FreeImage/PSDParser.cpp | 1053 |
1 files changed, 0 insertions, 1053 deletions
diff --git a/plugins/FreeImage/Source/FreeImage/PSDParser.cpp b/plugins/FreeImage/Source/FreeImage/PSDParser.cpp deleted file mode 100644 index 93573d01c0..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PSDParser.cpp +++ /dev/null @@ -1,1053 +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" - -// -------------------------------------------------------------------------- - -// PSD signature (= '8BPS') -#define PSD_SIGNATURE 0x38425053 -// Image resource block signature (= '8BIM') -#define PSD_RESOURCE 0x3842494D - -// PSD color modes -#define PSDP_BITMAP 0 -#define PSDP_GRAYSCALE 1 -#define PSDP_INDEXED 2 -#define PSDP_RGB 3 -#define PSDP_CMYK 4 -#define PSDP_MULTICHANNEL 7 -#define PSDP_DUOTONE 8 -#define PSDP_LAB 9 - -// PSD compression schemes -#define PSDP_COMPRESSION_NONE 0 // Raw data -#define PSDP_COMPRESSION_RLE 1 // RLE compression (same as TIFF packed bits) - -#define SAFE_DELETE_ARRAY(_p_) { if (NULL != (_p_)) { delete [] (_p_); (_p_) = NULL; } } - -// -------------------------------------------------------------------------- - -static inline int -psdGetValue(const BYTE * iprBuffer, const int iBytes) { - int v = iprBuffer[0]; - for (int i=1; i<iBytes; ++i) { - v = (v << 8) | iprBuffer[i]; - } - return v; -} - -// -------------------------------------------------------------------------- - -psdHeaderInfo::psdHeaderInfo() : _Channels(-1), _Height(-1), _Width(-1), _BitsPerChannel(-1), _ColourMode(-1) { -} - -psdHeaderInfo::~psdHeaderInfo() { -} - -bool psdHeaderInfo::Read(FreeImageIO *io, fi_handle handle) { - psdHeader header; - - const int n = (int)io->read_proc(&header, sizeof(header), 1, handle); - if (!n) { - return false; - } - - // check the signature - int nSignature = psdGetValue(header.Signature, sizeof(header.Signature)); - if (PSD_SIGNATURE == nSignature) { - // check the version - int nVersion = psdGetValue( header.Version, sizeof(header.Version) ); - if (1 == nVersion) { - // header.Reserved must be zero - BYTE psd_reserved[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - if(memcmp(header.Reserved, psd_reserved, 6) != 0) { - FreeImage_OutputMessageProc(FIF_PSD, "Warning: file header reserved member is not equal to zero"); - } - // read the header - _Channels = (short)psdGetValue( header.Channels, sizeof(header.Channels) ); - _Height = psdGetValue( header.Rows, sizeof(header.Rows) ); - _Width = psdGetValue( header.Columns, sizeof(header.Columns) ); - _BitsPerChannel = (short)psdGetValue( header.Depth, sizeof(header.Depth) ); - _ColourMode = (short)psdGetValue( header.Mode, sizeof(header.Mode) ); - - return true; - } - } - - return false; -} - -// -------------------------------------------------------------------------- - -psdColourModeData::psdColourModeData() : _Length(-1), _plColourData(NULL) { -} - -psdColourModeData::~psdColourModeData() { - SAFE_DELETE_ARRAY(_plColourData); -} - -bool psdColourModeData::Read(FreeImageIO *io, fi_handle handle) { - if (0 < _Length) { - SAFE_DELETE_ARRAY(_plColourData); - } - - BYTE Length[4]; - io->read_proc(&Length, sizeof(Length), 1, handle); - - _Length = psdGetValue( Length, sizeof(_Length) ); - if (0 < _Length) { - _plColourData = new BYTE[_Length]; - io->read_proc(_plColourData, _Length, 1, handle); - } - - return true; -} - -bool psdColourModeData::FillPalette(FIBITMAP *dib) { - RGBQUAD *pal = FreeImage_GetPalette(dib); - if(pal) { - for (int i = 0; i < 256; i++) { - pal[i].rgbRed = _plColourData[i + 0*256]; - pal[i].rgbGreen = _plColourData[i + 1*256]; - pal[i].rgbBlue = _plColourData[i + 2*256]; - } - return true; - } - return false; -} - -// -------------------------------------------------------------------------- - -psdImageResource::psdImageResource() : _plName (0) { - Reset(); -} - -psdImageResource::~psdImageResource() { - SAFE_DELETE_ARRAY(_plName); -} - -void psdImageResource::Reset() { - _Length = -1; - memset( _OSType, '\0', sizeof(_OSType) ); - _ID = -1; - SAFE_DELETE_ARRAY(_plName); - _Size = -1; -} - -// -------------------------------------------------------------------------- - -psdResolutionInfo::psdResolutionInfo() : _widthUnit(-1), _heightUnit(-1), _hRes(-1), _vRes(-1), _hResUnit(-1), _vResUnit(-1) { -} - -psdResolutionInfo::~psdResolutionInfo() { -} - -int psdResolutionInfo::Read(FreeImageIO *io, fi_handle handle) { - BYTE IntValue[4], ShortValue[2]; - int nBytes=0, n; - - // Horizontal resolution in pixels per inch. - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _hRes = (short)psdGetValue(ShortValue, sizeof(_hRes) ); - // 1=display horizontal resolution in pixels per inch; 2=display horizontal resolution in pixels per cm. - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _hResUnit = psdGetValue(IntValue, sizeof(_hResUnit) ); - // Display width as 1=inches; 2=cm; 3=points; 4=picas; 5=columns. - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _widthUnit = (short)psdGetValue(ShortValue, sizeof(_widthUnit) ); - // Vertical resolution in pixels per inch. - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _vRes = (short)psdGetValue(ShortValue, sizeof(_vRes) ); - // 1=display vertical resolution in pixels per inch; 2=display vertical resolution in pixels per cm. - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _vResUnit = psdGetValue(IntValue, sizeof(_vResUnit) ); - // Display height as 1=inches; 2=cm; 3=points; 4=picas; 5=columns. - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _heightUnit = (short)psdGetValue(ShortValue, sizeof(_heightUnit) ); - - return nBytes; -} - -void psdResolutionInfo::GetResolutionInfo(unsigned &res_x, unsigned &res_y) { - if(_hResUnit == 1) { - // convert pixels / inch to pixel / m - res_x = (unsigned) (_hRes / 0.0254000 + 0.5); - } else if(_hResUnit == 2) { - // convert pixels / cm to pixel / m - res_x = (unsigned) (_hRes * 100.0 + 0.5); - } - if(_vResUnit == 1) { - // convert pixels / inch to pixel / m - res_y = (unsigned) (_vRes / 0.0254000 + 0.5); - } else if(_vResUnit == 2) { - // convert pixels / cm to pixel / m - res_y = (unsigned) (_vRes * 100.0 + 0.5); - } -} - -// -------------------------------------------------------------------------- - -psdResolutionInfo_v2::psdResolutionInfo_v2() { - _Channels = _Rows = _Columns = _Depth = _Mode = -1; -} - -psdResolutionInfo_v2::~psdResolutionInfo_v2() { -} - -int psdResolutionInfo_v2::Read(FreeImageIO *io, fi_handle handle) { - BYTE ShortValue[2]; - int nBytes=0, n; - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _Channels = (short)psdGetValue(ShortValue, sizeof(_Channels) ); - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _Rows = (short)psdGetValue(ShortValue, sizeof(_Rows) ); - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _Columns = (short)psdGetValue(ShortValue, sizeof(_Columns) ); - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _Depth = (short)psdGetValue(ShortValue, sizeof(_Depth) ); - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _Mode = (short)psdGetValue(ShortValue, sizeof(_Mode) ); - - return nBytes; -} - -// -------------------------------------------------------------------------- - -psdDisplayInfo::psdDisplayInfo() { - _Opacity = _ColourSpace = -1; - for (unsigned n = 0; n < 4; ++n) { - _Colour[n] = 0; - } - _Kind = 0; - _padding = '0'; -} - -psdDisplayInfo::~psdDisplayInfo() { -} - -int psdDisplayInfo::Read(FreeImageIO *io, fi_handle handle) { - BYTE ShortValue[2]; - int nBytes=0, n; - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _ColourSpace = (short)psdGetValue(ShortValue, sizeof(_ColourSpace) ); - - for (unsigned i = 0; i < 4; ++i) { - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _Colour[i] = (short)psdGetValue(ShortValue, sizeof(_Colour[i]) ); - } - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _Opacity = (short)psdGetValue(ShortValue, sizeof(_Opacity) ); - if ((_Opacity < 0) || (_Opacity > 100)) { - throw "Invalid DisplayInfo::Opacity value"; - } - - BYTE c[1]; - n = (int)io->read_proc(&c, sizeof(c), 1, handle); - nBytes += n * sizeof(c); - _Kind = (BYTE)psdGetValue(c, sizeof(c)); - - n = (int)io->read_proc(&c, sizeof(c), 1, handle); - nBytes += n * sizeof(c); - _padding = (BYTE)psdGetValue(c, sizeof(c)); - if(_padding != 0) { - throw "Invalid DisplayInfo::Padding value"; - } - - return nBytes; -} - -// -------------------------------------------------------------------------- - -psdThumbnail::psdThumbnail() : -_Format(-1), _Width(-1), _Height(-1), _WidthBytes(-1), _Size(-1), _CompressedSize(-1), _BitPerPixel(-1), _Planes(-1), _dib(NULL) { -} - -psdThumbnail::~psdThumbnail() { - FreeImage_Unload(_dib); -} - -int psdThumbnail::Read(FreeImageIO *io, fi_handle handle, int iResourceSize, bool isBGR) { - BYTE ShortValue[2], IntValue[4]; - int nBytes=0, n; - - // remove the header size (28 bytes) from the total data size - int iTotalData = iResourceSize - 28; - - const long block_end = io->tell_proc(handle) + iTotalData; - - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _Format = psdGetValue(IntValue, sizeof(_Format) ); - - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _Width = psdGetValue(IntValue, sizeof(_Width) ); - - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _Height = psdGetValue(IntValue, sizeof(_Height) ); - - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _WidthBytes = psdGetValue(IntValue, sizeof(_WidthBytes) ); - - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _Size = psdGetValue(IntValue, sizeof(_Size) ); - - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _CompressedSize = psdGetValue(IntValue, sizeof(_CompressedSize) ); - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _BitPerPixel = (short)psdGetValue(ShortValue, sizeof(_BitPerPixel) ); - - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _Planes = (short)psdGetValue(ShortValue, sizeof(_Planes) ); - - const long JFIF_startpos = io->tell_proc(handle); - - if(_dib) { - FreeImage_Unload(_dib); - } - - if(_Format == 1) { - // kJpegRGB thumbnail image - _dib = FreeImage_LoadFromHandle(FIF_JPEG, io, handle); - if(isBGR) { - SwapRedBlue32(_dib); - } - // HACK: manually go to end of thumbnail, because (for some reason) LoadFromHandle consumes more bytes then available! - io->seek_proc(handle, block_end, SEEK_SET); - } - else { - // kRawRGB thumbnail image - // ### Unimplemented (should be trivial) - - // skip the thumbnail part - io->seek_proc(handle, iTotalData, SEEK_CUR); - return iResourceSize; - } - - nBytes += (block_end - JFIF_startpos); - - return nBytes; -} - -//--------------------------------------------------------------------------- - -psdICCProfile::psdICCProfile() : _ProfileSize(0), _ProfileData(NULL) { -} - -psdICCProfile::~psdICCProfile() { - clear(); -} - -void psdICCProfile::clear() { SAFE_DELETE_ARRAY(_ProfileData); _ProfileSize = 0;} - -int psdICCProfile::Read(FreeImageIO *io, fi_handle handle, int size) { - int nBytes = 0, n; - - clear(); - - _ProfileData = new (std::nothrow) BYTE[size]; - if(NULL != _ProfileData) { - n = (int)io->read_proc(_ProfileData, 1, size, handle); - _ProfileSize = size; - nBytes += n * sizeof(BYTE); - } - - return nBytes; -} - -//--------------------------------------------------------------------------- - -/** -Invert only color components, skipping Alpha/Black -(Can be useful as public/utility function) -*/ -static -BOOL invertColor(FIBITMAP* dib) { - FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib); - const unsigned Bpp = FreeImage_GetBPP(dib)/8; - - if ((type == FIT_BITMAP && Bpp == 4) || type == FIT_RGBA16) { - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - BYTE *line_start = FreeImage_GetScanLine(dib, 0); - const unsigned pitch = FreeImage_GetPitch(dib); - const unsigned triBpp = Bpp - (Bpp == 4 ? 1 : 2); - - for(unsigned y = 0; y < height; y++) { - BYTE *line = line_start; - - for(unsigned x = 0; x < width; x++) { - for(unsigned b=0; b < triBpp; ++b) { - line[b] = ~line[b]; - } - - line += Bpp; - } - line_start += pitch; - } - - return TRUE; - } - else { - return FreeImage_Invert(dib); - } -} - -//--------------------------------------------------------------------------- - -psdParser::psdParser() { - _bThumbnailFilled = false; - _bDisplayInfoFilled = false; - _bResolutionInfoFilled = false; - _bResolutionInfoFilled_v2 = false; - _bCopyright = false; - _GlobalAngle = 30; - _ColourCount = -1; - _TransparentIndex = -1; - _fi_flags = 0; - _fi_format_id = FIF_UNKNOWN; -} - -psdParser::~psdParser() { -} - -bool psdParser::ReadLayerAndMaskInfoSection(FreeImageIO *io, fi_handle handle) { - bool bSuccess = false; - - BYTE DataLength[4]; - int nBytes = 0; - int n = (int)io->read_proc(&DataLength, sizeof(DataLength), 1, handle); - int nTotalBytes = psdGetValue( DataLength, sizeof(DataLength) ); - - BYTE data[1]; - while( n && ( nBytes < nTotalBytes ) ) { - data[0] = '\0'; - n = (int)io->read_proc(&data, sizeof(data), 1, handle); - nBytes += n * sizeof(data); - } - - if ( nBytes == nTotalBytes ) { - bSuccess = true; - } - - return bSuccess; -} - -bool psdParser::ReadImageResources(FreeImageIO *io, fi_handle handle, LONG length) { - psdImageResource oResource; - bool bSuccess = false; - - if(length > 0) { - oResource._Length = length; - } else { - BYTE Length[4]; - int n = (int)io->read_proc(&Length, sizeof(Length), 1, handle); - - oResource._Length = psdGetValue( Length, sizeof(oResource._Length) ); - } - - int nBytes = 0; - int nTotalBytes = oResource._Length; - - while(nBytes < nTotalBytes) { - int n = 0; - oResource.Reset(); - - n = (int)io->read_proc(&oResource._OSType, sizeof(oResource._OSType), 1, handle); - nBytes += n * sizeof(oResource._OSType); - - if ( (nBytes % 2) != 0 ) { - return false; - } - - int nOSType = psdGetValue((BYTE*)&oResource._OSType, sizeof(oResource._OSType)); - - if ( PSD_RESOURCE == nOSType ) { - BYTE ID[2]; - n = (int)io->read_proc(&ID, sizeof(ID), 1, handle); - nBytes += n * sizeof(ID); - - oResource._ID = (short)psdGetValue( ID, sizeof(ID) ); - - BYTE SizeOfName; - n = (int)io->read_proc(&SizeOfName, sizeof(SizeOfName), 1, handle); - nBytes += n * sizeof(SizeOfName); - - int nSizeOfName = psdGetValue( &SizeOfName, sizeof(SizeOfName) ); - if ( 0 < nSizeOfName ) { - oResource._plName = new BYTE[nSizeOfName]; - n = (int)io->read_proc(oResource._plName, nSizeOfName, 1, handle); - nBytes += n * nSizeOfName; - } - - if ( 0 == (nSizeOfName % 2) ) { - n = (int)io->read_proc(&SizeOfName, sizeof(SizeOfName), 1, handle); - nBytes += n * sizeof(SizeOfName); - } - - BYTE Size[4]; - n = (int)io->read_proc(&Size, sizeof(Size), 1, handle); - nBytes += n * sizeof(Size); - - oResource._Size = psdGetValue( Size, sizeof(oResource._Size) ); - - if ( 0 != (oResource._Size % 2) ) { - // resource data must be even - oResource._Size++; - } - if ( 0 < oResource._Size ) { - BYTE IntValue[4]; - BYTE ShortValue[2]; - - switch( oResource._ID ) { - case 1000: - // Obsolete - Photoshop 2.0 - _bResolutionInfoFilled_v2 = true; - nBytes += _resolutionInfo_v2.Read(io, handle); - break; - - // ResolutionInfo structure - case 1005: - _bResolutionInfoFilled = true; - nBytes += _resolutionInfo.Read(io, handle); - break; - - // DisplayInfo structure - case 1007: - _bDisplayInfoFilled = true; - nBytes += _displayInfo.Read(io, handle); - break; - - // (Photoshop 4.0) Copyright flag - // Boolean indicating whether image is copyrighted. Can be set via Property suite or by user in File Info... - case 1034: - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _bCopyright = (1 == psdGetValue(ShortValue, sizeof(ShortValue))); - break; - - // (Photoshop 4.0) Thumbnail resource for Photoshop 4.0 only - case 1033: - // (Photoshop 5.0) Thumbnail resource (supersedes resource 1033) - case 1036: - { - _bThumbnailFilled = true; - bool bBGR = (1033==oResource._ID); - nBytes += _thumbnail.Read(io, handle, oResource._Size, bBGR); - break; - } - - // (Photoshop 5.0) Global Angle - // 4 bytes that contain an integer between 0 and 359, which is the global - // lighting angle for effects layer. If not present, assumed to be 30. - case 1037: - n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle); - nBytes += n * sizeof(IntValue); - _GlobalAngle = psdGetValue(IntValue, sizeof(_GlobalAngle) ); - break; - - // ICC profile - case 1039: - nBytes += _iccProfile.Read(io, handle, oResource._Size); - break; - - // (Photoshop 6.0) Indexed Color Table Count - // 2 bytes for the number of colors in table that are actually defined - case 1046: - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _ColourCount = (short)psdGetValue(ShortValue, sizeof(ShortValue) ); - break; - - // (Photoshop 6.0) Transparency Index. - // 2 bytes for the index of transparent color, if any. - case 1047: - n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); - nBytes += n * sizeof(ShortValue); - _TransparentIndex = (short)psdGetValue(ShortValue, sizeof(ShortValue) ); - break; - - default: - { - // skip resource - unsigned skip_length = MIN(oResource._Size, nTotalBytes - nBytes); - io->seek_proc(handle, skip_length, SEEK_CUR); - nBytes += skip_length; - } - break; - } - } - } - } - - if (nBytes == nTotalBytes) { - bSuccess = true; - } - - return bSuccess; - -} - -FIBITMAP* psdParser::ReadImageData(FreeImageIO *io, fi_handle handle) { - if(handle == NULL) - return NULL; - - bool header_only = (_fi_flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - WORD nCompression = 0; - io->read_proc(&nCompression, sizeof(nCompression), 1, handle); - -#ifndef FREEIMAGE_BIGENDIAN - SwapShort(&nCompression); -#endif - - if ((nCompression != PSDP_COMPRESSION_NONE && nCompression != PSDP_COMPRESSION_RLE)) { - FreeImage_OutputMessageProc(_fi_format_id, "Unsupported compression %d", nCompression); - return NULL; - } - - const unsigned nWidth = _headerInfo._Width; - const unsigned nHeight = _headerInfo._Height; - const unsigned nChannels = _headerInfo._Channels; - const unsigned depth = _headerInfo._BitsPerChannel; - const unsigned bytes = (depth == 1) ? 1 : depth / 8; - - // channel(plane) line (BYTE aligned) - const unsigned lineSize = (_headerInfo._BitsPerChannel == 1) ? (nWidth + 7) / 8 : nWidth * bytes; - - if(nCompression == PSDP_COMPRESSION_RLE && depth > 16) { - FreeImage_OutputMessageProc(_fi_format_id, "Unsupported RLE with depth %d", depth); - return NULL; - } - - // build output buffer - - FIBITMAP* bitmap = NULL; - unsigned dstCh = 0; - - short mode = _headerInfo._ColourMode; - - if(mode == PSDP_MULTICHANNEL && nChannels < 3) { - // CM - mode = PSDP_GRAYSCALE; // C as gray, M as extra channel - } - - bool needPalette = false; - switch (mode) { - case PSDP_BITMAP: - case PSDP_DUOTONE: - case PSDP_INDEXED: - case PSDP_GRAYSCALE: - dstCh = 1; - switch(depth) { - case 16: - bitmap = FreeImage_AllocateHeaderT(header_only, FIT_UINT16, nWidth, nHeight, depth*dstCh); - break; - case 32: - bitmap = FreeImage_AllocateHeaderT(header_only, FIT_FLOAT, nWidth, nHeight, depth*dstCh); - break; - default: // 1-, 8- - needPalette = true; - bitmap = FreeImage_AllocateHeader(header_only, nWidth, nHeight, depth*dstCh); - break; - } - break; - case PSDP_RGB: - case PSDP_LAB: - case PSDP_CMYK : - case PSDP_MULTICHANNEL : - // force PSDP_MULTICHANNEL CMY as CMYK - dstCh = (mode == PSDP_MULTICHANNEL && !header_only) ? 4 : MIN<unsigned>(nChannels, 4); - if(dstCh < 3) { - throw "Invalid number of channels"; - } - - switch(depth) { - case 16: - bitmap = FreeImage_AllocateHeaderT(header_only, dstCh < 4 ? FIT_RGB16 : FIT_RGBA16, nWidth, nHeight, depth*dstCh); - break; - case 32: - bitmap = FreeImage_AllocateHeaderT(header_only, dstCh < 4 ? FIT_RGBF : FIT_RGBAF, nWidth, nHeight, depth*dstCh); - break; - default: - bitmap = FreeImage_AllocateHeader(header_only, nWidth, nHeight, depth*dstCh); - break; - } - break; - default: - throw "Unsupported color mode"; - break; - } - if (!bitmap) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // write thumbnail - FreeImage_SetThumbnail(bitmap, _thumbnail.getDib()); - - // @todo Add some metadata model - - if(header_only) { - return bitmap; - } - - // Load pixels data - - const unsigned dstChannels = dstCh; - - const unsigned dstBpp = (depth == 1) ? 1 : FreeImage_GetBPP(bitmap)/8; - const unsigned dstLineSize = FreeImage_GetPitch(bitmap); - BYTE* const dst_first_line = FreeImage_GetScanLine(bitmap, nHeight - 1);//<*** flipped - - BYTE* line_start = new BYTE[lineSize]; //< fileline cache - - switch ( nCompression ) { - case PSDP_COMPRESSION_NONE: // raw data - { - for(unsigned c = 0; c < nChannels; c++) { - if(c >= dstChannels) { - // @todo write extra channels - break; - } - - const unsigned channelOffset = c * bytes; - - BYTE* dst_line_start = dst_first_line; - for(unsigned h = 0; h < nHeight; ++h, dst_line_start -= dstLineSize) {//<*** flipped - - io->read_proc(line_start, lineSize, 1, handle); - - for (BYTE *line = line_start, *dst_line = dst_line_start; line < line_start + lineSize; - line += bytes, dst_line += dstBpp) { -#ifdef FREEIMAGE_BIGENDIAN - memcpy(dst_line + channelOffset, line, bytes); -#else - // reverse copy bytes - for (unsigned b = 0; b < bytes; ++b) { - dst_line[channelOffset + b] = line[(bytes-1) - b]; - } -#endif // FREEIMAGE_BIGENDIAN - } - } //< h - }//< ch - - SAFE_DELETE_ARRAY(line_start); - - } - break; - - case PSDP_COMPRESSION_RLE: // RLE compression - { - - // The RLE-compressed data is preceeded by a 2-byte line size for each row in the data, - // store an array of these - - // later use this array as WORD rleLineSizeList[nChannels][nHeight]; - WORD *rleLineSizeList = new (std::nothrow) WORD[nChannels*nHeight]; - - if (!rleLineSizeList) { - FreeImage_Unload(bitmap); - SAFE_DELETE_ARRAY(line_start); - throw std::bad_alloc(); - } - - io->read_proc(rleLineSizeList, 2, nChannels * nHeight, handle); - - WORD largestRLELine = 0; - for(unsigned ch = 0; ch < nChannels; ++ch) { - for(unsigned h = 0; h < nHeight; ++h) { - const unsigned index = ch * nHeight + h; - -#ifndef FREEIMAGE_BIGENDIAN - SwapShort(&rleLineSizeList[index]); -#endif - if(largestRLELine < rleLineSizeList[index]) { - largestRLELine = rleLineSizeList[index]; - } - } - } - - BYTE* rle_line_start = new (std::nothrow) BYTE[largestRLELine]; - if (!rle_line_start) { - FreeImage_Unload(bitmap); - SAFE_DELETE_ARRAY(line_start); - SAFE_DELETE_ARRAY(rleLineSizeList); - throw std::bad_alloc(); - } - - // Read the RLE data (assume 8-bit) - - const BYTE* const line_end = line_start + lineSize; - - for (unsigned ch = 0; ch < nChannels; ch++) { - const unsigned channelOffset = ch * bytes; - - BYTE* dst_line_start = dst_first_line; - for(unsigned h = 0; h < nHeight; ++h, dst_line_start -= dstLineSize) {//<*** flipped - const unsigned index = ch * nHeight + h; - - // - read and uncompress line - - - const WORD rleLineSize = rleLineSizeList[index]; - - io->read_proc(rle_line_start, rleLineSize, 1, handle); - - for (BYTE* rle_line = rle_line_start, *line = line_start; - rle_line < rle_line_start + rleLineSize, line < line_end;) { - - int len = *rle_line++; - - // NOTE len is signed byte in PackBits RLE - - if ( len < 128 ) { //<- MSB is not set - // uncompressed packet - - // (len + 1) bytes of data are copied - - ++len; - - // assert we don't write beyound eol - memcpy(line, rle_line, line + len > line_end ? line_end - line : len); - line += len; - rle_line += len; - } - else if ( len > 128 ) { //< MSB is set - - // RLE compressed packet - - // One byte of data is repeated (–len + 1) times - - len ^= 0xFF; // same as (-len + 1) & 0xFF - len += 2; // - - // assert we don't write beyound eol - memset(line, *rle_line++, line + len > line_end ? line_end - line : len); - line += len; - - } - else if ( 128 == len ) { - // Do nothing - } - }//< rle_line - - // - write line to destination - - - if(ch >= dstChannels) { - // @todo write to extra channels - break; - } - - // byte by byte copy a single channel to pixel - for (BYTE *line = line_start, *dst_line = dst_line_start; line < line_start + lineSize; - line += bytes, dst_line += dstBpp) { - -#ifdef FREEIMAGE_BIGENDIAN - memcpy(dst_line + channelOffset, line, bytes); -#else - // reverse copy bytes - for (unsigned b = 0; b < bytes; ++b) { - dst_line[channelOffset + b] = line[(bytes-1) - b]; - } -#endif // FREEIMAGE_BIGENDIAN - } - }//< h - }//< ch - - SAFE_DELETE_ARRAY(line_start); - SAFE_DELETE_ARRAY(rleLineSizeList); - SAFE_DELETE_ARRAY(rle_line_start); - } - break; - - case 2: // ZIP without prediction, no specification - break; - - case 3: // ZIP with prediction, no specification - break; - - default: // Unknown format - break; - - } - - // --- Further process the bitmap --- - - if ((mode == PSDP_CMYK || mode == PSDP_MULTICHANNEL)) { - // CMYK values are "inverted", invert them back - - if(mode == PSDP_MULTICHANNEL) { - invertColor(bitmap); - } else { - FreeImage_Invert(bitmap); - } - - if ((_fi_flags & PSD_CMYK) == PSD_CMYK) { - // keep as CMYK - - if(mode == PSDP_MULTICHANNEL) { - //### we force CMY to be CMYK, but CMY has no ICC. - // Create empty profile and add the flag. - FreeImage_CreateICCProfile(bitmap, NULL, 0); - FreeImage_GetICCProfile(bitmap)->flags |= FIICC_COLOR_IS_CMYK; - } - } - else { - // convert to RGB - - ConvertCMYKtoRGBA(bitmap); - - // The ICC Profile is no longer valid - _iccProfile.clear(); - - // remove the pending A if not present in source - if(nChannels == 4 || nChannels == 3 ) { - FIBITMAP* t = RemoveAlphaChannel(bitmap); - if(t) { - FreeImage_Unload(bitmap); - bitmap = t; - } // else: silently fail - } - } - } - else if ( mode == PSDP_LAB && !((_fi_flags & PSD_LAB) == PSD_LAB)) { - ConvertLABtoRGB(bitmap); - } - else { - if (needPalette && FreeImage_GetPalette(bitmap)) { - - if(mode == PSDP_BITMAP) { - CREATE_GREYSCALE_PALETTE_REVERSE(FreeImage_GetPalette(bitmap), 2); - } - else if(mode == PSDP_INDEXED) { - if (!_colourModeData._plColourData || _colourModeData._Length != 768 || _ColourCount < 0) { - FreeImage_OutputMessageProc(_fi_format_id, "Indexed image has no palette. Using the default grayscale one."); - } else { - _colourModeData.FillPalette(bitmap); - } - } - // GRAYSCALE, DUOTONE - use default grayscale palette - } - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - if(FreeImage_GetImageType(bitmap) == FIT_BITMAP) { - SwapRedBlue32(bitmap); - } -#endif - } - - return bitmap; -} - -FIBITMAP* psdParser::Load(FreeImageIO *io, fi_handle handle, int s_format_id, int flags) { - FIBITMAP *Bitmap = NULL; - - _fi_flags = flags; - _fi_format_id = s_format_id; - - try { - if (NULL == handle) { - throw("Cannot open file"); - } - - if (!_headerInfo.Read(io, handle)) { - throw("Error in header"); - } - - if (!_colourModeData.Read(io, handle)) { - throw("Error in ColourMode Data"); - } - - if (!ReadImageResources(io, handle)) { - throw("Error in Image Resource"); - } - - if (!ReadLayerAndMaskInfoSection(io, handle)) { - throw("Error in Mask Info"); - } - - Bitmap = ReadImageData(io, handle); - if (NULL == Bitmap) { - throw("Error in Image Data"); - } - - // set resolution info - if(NULL != Bitmap) { - unsigned res_x = 2835; // 72 dpi - unsigned res_y = 2835; // 72 dpi - if (_bResolutionInfoFilled) { - _resolutionInfo.GetResolutionInfo(res_x, res_y); - } - FreeImage_SetDotsPerMeterX(Bitmap, res_x); - FreeImage_SetDotsPerMeterY(Bitmap, res_y); - } - - // set ICC profile - FreeImage_CreateICCProfile(Bitmap, _iccProfile._ProfileData, _iccProfile._ProfileSize); - if ((flags & PSD_CMYK) == PSD_CMYK) { - short mode = _headerInfo._ColourMode; - if ((mode == PSDP_CMYK) || (mode == PSDP_MULTICHANNEL)) { - FreeImage_GetICCProfile(Bitmap)->flags |= FIICC_COLOR_IS_CMYK; - } - } - - } catch(const char *text) { - FreeImage_OutputMessageProc(s_format_id, text); - } - catch(const std::exception& e) { - FreeImage_OutputMessageProc(s_format_id, "%s", e.what()); - } - - return Bitmap; -} |