aboutsummaryrefslogtreecommitdiff
path: root/archive/hge/CxImage/ximapsd.cpp
diff options
context:
space:
mode:
authorGravatar Chris Xiong <chirs241097@gmail.com> 2015-10-26 22:52:36 +0800
committerGravatar Chris Xiong <chirs241097@gmail.com> 2015-10-26 22:52:36 +0800
commit3bd383baf6a17e734329e1fc677c7e86283db772 (patch)
tree69a9148087577f797624ceb9c71323a2563d6bb4 /archive/hge/CxImage/ximapsd.cpp
parent543e4f570be9b279ba558ca61cc02cda251af384 (diff)
downloadbullet-lab-remix-3bd383baf6a17e734329e1fc677c7e86283db772.tar.xz
Added support for relative line numbers.
Added instructions for, brk and cont. (They are still untested...) Parser code cleanup. Removed garbage output to stderr. Reorganize the repository structure. Updated BLR2 code move it into archive. Added BLR1 files.
Diffstat (limited to 'archive/hge/CxImage/ximapsd.cpp')
-rw-r--r--archive/hge/CxImage/ximapsd.cpp1307
1 files changed, 1307 insertions, 0 deletions
diff --git a/archive/hge/CxImage/ximapsd.cpp b/archive/hge/CxImage/ximapsd.cpp
new file mode 100644
index 0000000..2d8417b
--- /dev/null
+++ b/archive/hge/CxImage/ximapsd.cpp
@@ -0,0 +1,1307 @@
+/*
+ * File: ximapsd.cpp
+ * Purpose: Platform Independent PSD Image Class Loader
+ * Dec/2010 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ *
+ * libpsd (c) 2004-2007 Graphest Software
+ *
+ * Based on MyPSD class by Iosif Hamlatzis
+ * Details: http://www.codeproject.com/KB/graphics/MyPSD.aspx
+ * Cleaned up a bit and ported to CxImage by Vitaly Ovchinnikov
+ * Send feedback to vitaly(dot)ovchinnikov(at)gmail.com
+ */
+
+#include "ximapsd.h"
+
+#if CXIMAGE_SUPPORT_PSD
+
+enum {
+ PSD_FILE_HEADER,
+ PSD_COLOR_MODE_DATA,
+ PSD_IMAGE_RESOURCE,
+ PSD_LAYER_AND_MASK_INFORMATION,
+ PSD_IMAGE_DATA,
+ PSD_DONE
+};
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_USE_LIBPSD == 0
+// MyPSD.h /////////////////////////////////////////////////////////////////////
+
+#ifndef __MyPSD_H__
+#define __MyPSD_H__
+
+namespace MyPSD
+{
+
+ class CPSD
+ {
+ struct HEADER_INFO
+ {
+ //Table 2-12: HeaderInfo Color spaces
+ // Color-ID Name Description
+ //-------------------------------------------
+ // 0 Bitmap // Probably means black & white
+ // 1 Grayscale The first value in the color data is the gray value, from 0...10000.
+ // 2 Indexed
+ // 3 RGB The first three values in the color data are red, green, and blue.
+ // They are full unsigned 16–bit values as in Apple’s RGBColor data
+ // structure. Pure red=65535,0,0.
+ // 4 CMYK The four values in the color data are cyan, magenta, yellow, and
+ // black. They are full unsigned 16–bit values. 0=100% ink. Pure
+ // cyan=0,65535,65535,65535.
+ // 7 Multichannel // Have no idea
+ // 8 Duotone
+ // 9 Lab The first three values in the color data are lightness, a chrominance,
+ // and b chrominance.
+ // Lightness is a 16–bit value from 0...100. The chromanance components
+ // are each 16–bit values from –128...127. Gray values
+ // are represented by chrominance components of 0. Pure
+ // white=100,0,0.
+ short nChannels;
+ int nHeight;
+ int nWidth;
+ short nBitsPerPixel;
+ short nColourMode;
+ HEADER_INFO();
+ };
+
+ struct COLOUR_MODE_DATA
+ {
+ int nLength;
+ unsigned char* ColourData;
+ COLOUR_MODE_DATA();
+ };
+
+
+ struct IMAGE_RESOURCE
+ {
+ // Table 2–1: Image resource block
+ // Type Name Description
+ //-------------------------------------------
+ // OSType Type Photoshop always uses its signature, 8BIM
+ // int16 ID Unique identifier
+ // PString Name A pascal string, padded to make size even (a null name consists of two bytes of 0)
+ // Pascal style string where the first byte gives the length of the
+ // string and the content bytes follow.
+ // int32 Size Actual size of resource data. This does not include the
+ // Type, ID, Name, or Size fields.
+ // Variable Data Resource data, padded to make size even
+ int nLength;
+ char OSType[4];
+ short nID;
+ unsigned char* Name;
+ int nSize;
+ IMAGE_RESOURCE();
+ void Reset();
+ };
+
+ struct RESOLUTION_INFO
+ {
+ // Table A-6: ResolutionInfo structure
+ // Type Name Description
+ //-------------------------------------------
+ // Fixed hRes Horizontal resolution in pixels per inch.
+ // int hResUnit 1=display horizontal resolution in pixels per inch;
+ // 2=display horizontal resolution in pixels per cm.
+ // short widthUnit Display width as 1=inches; 2=cm; 3=points; 4=picas; 5=columns.
+ // Fixed vRes Vertical resolution in pixels per inch.
+ // int vResUnit 1=display vertical resolution in pixels per inch;
+ // 2=display vertical resolution in pixels per cm.
+ // short heightUnit Display height as 1=inches; 2=cm; 3=points; 4=picas; 5=columns.
+ short hRes;
+ int hResUnit;
+ short widthUnit;
+
+ short vRes;
+ int vResUnit;
+ short heightUnit;
+ RESOLUTION_INFO();
+ };
+
+ struct RESOLUTION_INFO_v2 // Obsolete - Photoshop 2.0
+ {
+ short nChannels;
+ short nRows;
+ short nColumns;
+ short nDepth;
+ short nMode;
+ RESOLUTION_INFO_v2();
+ };
+
+ struct DISPLAY_INFO
+ {
+ // This structure contains display information about each channel.
+ //Table A-7: DisplayInfo Color spaces
+ // Color-ID Name Description
+ //-------------------------------------------
+ // 0 RGB The first three values in the color data are red, green, and blue.
+ // They are full unsigned 16–bit values as in Apple’s RGBColor data
+ // structure. Pure red=65535,0,0.
+ // 1 HSB The first three values in the color data are hue, saturation, and
+ // brightness. They are full unsigned 16–bit values as in Apple’s
+ // HSVColor data structure. Pure red=0,65535, 65535.
+ // 2 CMYK The four values in the color data are cyan, magenta, yellow, and
+ // black. They are full unsigned 16–bit values. 0=100% ink. Pure
+ // cyan=0,65535,65535,65535.
+ // 7 Lab The first three values in the color data are lightness, a chrominance,
+ // and b chrominance.
+ // Lightness is a 16–bit value from 0...10000. The chromanance components
+ // are each 16–bit values from –12800...12700. Gray values
+ // are represented by chrominance components of 0. Pure
+ // white=10000,0,0.
+ // 8 grayscale The first value in the color data is the gray value, from 0...10000.
+ short ColourSpace;
+ short Colour[4];
+ short Opacity; // 0..100
+ bool kind; // selected = 0, protected = 1
+ unsigned char padding; // should be zero
+ DISPLAY_INFO();
+ };
+ struct THUMBNAIL
+ {
+ // Adobe Photoshop 5.0 and later stores thumbnail information for preview
+ // display in an image resource block. These resource blocks consist of an
+ // 28 byte header, followed by a JFIF thumbnail in RGB (red, green, blue)
+ // for both Macintosh and Windows. Adobe Photoshop 4.0 stored the
+ // thumbnail information in the same format except the data section is
+ // (blue, green, red). The Adobe Photoshop 4.0 format is at resource ID
+ // and the Adobe Photoshop 5.0 format is at resource ID 1036.
+ // Table 2–5: Thumnail resource header
+ // Type Name Description
+ //-------------------------------------------
+ // 4 bytes format = 1 (kJpegRGB). Also supports kRawRGB (0).
+ // 4 bytes width Width of thumbnail in pixels.
+ // 4 bytes height Height of thumbnail in pixels.
+ // 4 bytes widthbytes Padded row bytes as (width * bitspixel + 31) / 32 * 4.
+ // 4 bytes size Total size as widthbytes * height * planes
+ // 4 bytes compressedsize Size after compression. Used for consistentcy check.
+ // 2 bytes bitspixel = 24. Bits per pixel.
+ // 2 bytes planes = 1. Number of planes.
+ // Variable Data JFIF data in RGB format.
+ // Note: For resource ID 1033 the data is in BGR format.
+ int nFormat;
+ int nWidth;
+ int nHeight;
+ int nWidthBytes;
+ int nSize;
+ int nCompressedSize;
+ short nBitPerPixel;
+ short nPlanes;
+ unsigned char* Data;
+ THUMBNAIL();
+ };
+
+
+ CxImage &m_image;
+
+ HEADER_INFO header_info;
+
+ COLOUR_MODE_DATA colour_mode_data;
+ short mnColourCount;
+ short mnTransparentIndex;
+
+ IMAGE_RESOURCE image_resource;
+
+ int mnGlobalAngle;
+
+ RESOLUTION_INFO resolution_info;
+ bool mbResolutionInfoFilled;
+
+ RESOLUTION_INFO_v2 resolution_info_v2;
+ bool mbResolutionInfoFilled_v2;
+
+ DISPLAY_INFO display_info;
+ bool mbDisplayInfoFilled;
+
+ THUMBNAIL thumbnail;
+ bool mbThumbNailFilled;
+
+ bool mbCopyright;
+
+ int Calculate(unsigned char* c, int nDigits);
+ void XYZToRGB(const double X, const double Y, const double Z, int &R, int &G, int &B);
+ void LabToRGB(const int L, const int a, const int b, int &R, int &G, int &B );
+ void CMYKToRGB(const double C, const double M, const double Y, const double K, int &R, int &G, int &B);
+
+ bool ReadHeader(CxFile &f, HEADER_INFO& header_info);
+ bool ReadColourModeData(CxFile &f, COLOUR_MODE_DATA& colour_mode_data);
+ bool ReadImageResource(CxFile &f, IMAGE_RESOURCE& image_resource);
+ bool ReadLayerAndMaskInfoSection(CxFile &f); // Actually ignore it
+ int ReadImageData(CxFile &f);
+
+ int DecodeRawData(CxFile &pFile);
+ int DecodeRLEData(CxFile &pFile);
+
+ void ProccessBuffer(unsigned char* pData = 0);
+
+ public:
+ CPSD(CxImage &image);
+ ~CPSD();
+
+ int Load(LPCTSTR szPathName);
+ int Load(CxFile &file);
+
+ bool ThumbNailIncluded() const { return mbThumbNailFilled; }
+ void DPI(int &x, int &y) const { x = resolution_info.hRes; y = resolution_info.vRes; }
+ void Dimensions(int &cx, int &cy) const { cx = header_info.nWidth; cy = header_info.nHeight; }
+ int BitsPerPixel() const { return header_info.nBitsPerPixel; }
+ int GlobalAngle() const { return mnGlobalAngle; }
+ bool IsCopyright() const { return mbCopyright; }
+ HBITMAP Detach();
+ };
+}
+
+#endif // __MyPSD_H__
+
+// MyPSD.cpp ///////////////////////////////////////////////////////////////////
+
+
+inline int dti(double value) { return (int)floor(value+.5f); }
+
+#define assert(a)
+
+#define mypsd_fread(a, b, c, d) d.Read(a, b, c)
+#define mypsd_fseek(a, b, c) a.Seek(b, c)
+#define mypsd_feof(a) a.Eof()
+
+namespace MyPSD
+{
+ CPSD::CPSD(CxImage &image) : m_image(image)
+ {
+ mbThumbNailFilled = false;
+ mbDisplayInfoFilled = false;
+ mbResolutionInfoFilled = false;
+ mbResolutionInfoFilled_v2 = false;
+ mnGlobalAngle = 30;
+ mbCopyright = false;
+ mnColourCount = -1;
+ mnTransparentIndex = -1;
+ }
+ CPSD::~CPSD()
+ {
+ // free memory
+ if ( 0 < colour_mode_data.nLength )
+ delete[] colour_mode_data.ColourData;
+ colour_mode_data.ColourData = 0;
+
+ if ( image_resource.Name )
+ delete[] image_resource.Name;
+ image_resource.Name = 0;
+ }
+
+ int CPSD::Calculate(unsigned char* c, int nDigits)
+ {
+ int nValue = 0;
+
+ for(int n = 0; n < nDigits; ++n)
+ nValue = ( nValue << 8 ) | *(c+n);
+
+ return nValue;
+ };
+
+ void CPSD::XYZToRGB(const double X, const double Y, const double Z, int &R, int &G, int &B)
+ {
+ // Standards used Observer = 2, Illuminant = D65
+ // ref_X = 95.047, ref_Y = 100.000, ref_Z = 108.883
+ const double ref_X = 95.047;
+ const double ref_Y = 100.000;
+ const double ref_Z = 108.883;
+
+ double var_X = X / 100.0;
+ double var_Y = Y / 100.0;
+ double var_Z = Z / 100.0;
+
+ double var_R = var_X * 3.2406 + var_Y * (-1.5372) + var_Z * (-0.4986);
+ double var_G = var_X * (-0.9689) + var_Y * 1.8758 + var_Z * 0.0415;
+ double var_B = var_X * 0.0557 + var_Y * (-0.2040) + var_Z * 1.0570;
+
+ if ( var_R > 0.0031308 )
+ var_R = 1.055 * ( pow(var_R, 1/2.4) ) - 0.055;
+ else
+ var_R = 12.92 * var_R;
+
+ if ( var_G > 0.0031308 )
+ var_G = 1.055 * ( pow(var_G, 1/2.4) ) - 0.055;
+ else
+ var_G = 12.92 * var_G;
+
+ if ( var_B > 0.0031308 )
+ var_B = 1.055 * ( pow(var_B, 1/2.4) )- 0.055;
+ else
+ var_B = 12.92 * var_B;
+
+ R = (int)(var_R * 256.0);
+ G = (int)(var_G * 256.0);
+ B = (int)(var_B * 256.0);
+ };
+
+ void CPSD::LabToRGB(const int L, const int a, const int b, int &R, int &G, int &B )
+ {
+ // For the conversion we first convert values to XYZ and then to RGB
+ // Standards used Observer = 2, Illuminant = D65
+ // ref_X = 95.047, ref_Y = 100.000, ref_Z = 108.883
+ const double ref_X = 95.047;
+ const double ref_Y = 100.000;
+ const double ref_Z = 108.883;
+
+ double var_Y = ( (double)L + 16.0 ) / 116.0;
+ double var_X = (double)a / 500.0 + var_Y;
+ double var_Z = var_Y - (double)b / 200.0;
+
+ if ( pow(var_Y, 3) > 0.008856 )
+ var_Y = pow(var_Y, 3);
+ else
+ var_Y = ( var_Y - 16 / 116 ) / 7.787;
+
+ if ( pow(var_X, 3) > 0.008856 )
+ var_X = pow(var_X, 3);
+ else
+ var_X = ( var_X - 16 / 116 ) / 7.787;
+
+ if ( pow(var_Z, 3) > 0.008856 )
+ var_Z = pow(var_Z, 3);
+ else
+ var_Z = ( var_Z - 16 / 116 ) / 7.787;
+
+ double X = ref_X * var_X;
+ double Y = ref_Y * var_Y;
+ double Z = ref_Z * var_Z;
+
+ XYZToRGB(X, Y, Z, R, G, B);
+ };
+
+ void CPSD::CMYKToRGB(const double C, const double M, const double Y, const double K, int &R, int &G, int &B )
+ {
+ R = dti( ( 1.0f - ( C *( 1.0f - K ) + K ) ) * 255.0f );
+ G = dti( ( 1.0f - ( M *( 1.0f - K ) + K ) ) * 255.0f );
+ B = dti( ( 1.0f - ( Y *( 1.0f - K ) + K ) ) * 255.0f );
+ };
+
+ bool CPSD::ReadLayerAndMaskInfoSection(CxFile &pFile) // Actually ignore it
+ {
+ bool bSuccess = false;
+
+ unsigned char DataLength[4];
+ int nBytesRead = 0;
+ int nItemsRead = (int)(int)mypsd_fread(&DataLength, sizeof(DataLength), 1, pFile);
+
+ int nTotalBytes = Calculate( DataLength, sizeof(DataLength) );
+
+ unsigned char data[1];
+ while( !mypsd_feof( pFile ) && ( nBytesRead < nTotalBytes ) )
+ {
+ data[0] = '\0';
+ nItemsRead = (int)(int)mypsd_fread(&data, sizeof(data), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(data);
+ }
+
+ assert ( nBytesRead == nTotalBytes );
+ if ( nBytesRead == nTotalBytes )
+ bSuccess = true;
+
+ return bSuccess;
+ }
+ bool CPSD::ReadImageResource(CxFile &pFile, IMAGE_RESOURCE& image_resource)
+ {
+ bool bSuccess = false;
+
+ unsigned char Length[4];
+ int nItemsRead = (int)(int)mypsd_fread(&Length, sizeof(Length), 1, pFile);
+
+ image_resource.nLength = Calculate( Length, sizeof(image_resource.nLength) );
+
+ int nBytesRead = 0;
+ int nTotalBytes = image_resource.nLength;
+
+ while( !mypsd_feof( pFile ) && ( nBytesRead < nTotalBytes ) )
+ {
+ nItemsRead = 0;
+ image_resource.Reset();
+
+ nItemsRead = (int)(int)mypsd_fread(&image_resource.OSType, sizeof(image_resource.OSType), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(image_resource.OSType);
+
+ assert ( 0 == (nBytesRead % 2) );
+ if (::memcmp(image_resource.OSType, "8BIM", 4) == 0)
+ {
+ unsigned char ID[2];
+ nItemsRead = (int)(int)mypsd_fread(&ID, sizeof(ID), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ID);
+
+ image_resource.nID = (short)Calculate( ID, sizeof(ID) );
+
+ unsigned char SizeOfName;
+ nItemsRead = (int)(int)mypsd_fread(&SizeOfName, sizeof(SizeOfName), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(SizeOfName);
+
+ int nSizeOfName = Calculate( &SizeOfName, sizeof(SizeOfName) );
+ if ( 0 < nSizeOfName )
+ {
+ image_resource.Name = new unsigned char[nSizeOfName];
+ nItemsRead = (int)(int)mypsd_fread(image_resource.Name, nSizeOfName, 1, pFile);
+ nBytesRead += nItemsRead * nSizeOfName;
+ }
+
+ if ( 0 == (nSizeOfName % 2) )
+ {
+ nItemsRead = (int)(int)mypsd_fread(&SizeOfName, sizeof(SizeOfName), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(SizeOfName);
+ }
+
+ unsigned char Size[4];
+ nItemsRead = (int)(int)mypsd_fread(&Size, sizeof(Size), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(Size);
+
+ image_resource.nSize = Calculate( Size, sizeof(image_resource.nSize) );
+
+ if ( 0 != (image_resource.nSize % 2) ) // resource data must be even
+ image_resource.nSize++;
+ if ( 0 < image_resource.nSize )
+ {
+ unsigned char IntValue[4];
+ unsigned char ShortValue[2];
+
+ switch( image_resource.nID )
+ {
+ case 1000:
+ {
+ // Obsolete - Photoshop 2.0
+ mbResolutionInfoFilled_v2 = true;
+
+ nItemsRead = (int)(int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info_v2.nChannels = (short)Calculate(ShortValue, sizeof(resolution_info_v2.nChannels) );
+ nItemsRead = (int)(int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info_v2.nRows = (short)Calculate(ShortValue, sizeof(resolution_info_v2.nRows) );
+ nItemsRead = (int)(int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info_v2.nColumns = (short)Calculate(ShortValue, sizeof(resolution_info_v2.nColumns) );
+ nItemsRead = (int)(int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info_v2.nDepth = (short)Calculate(ShortValue, sizeof(resolution_info_v2.nDepth) );
+ nItemsRead = (int)(int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info_v2.nMode = (short)Calculate(ShortValue, sizeof(resolution_info_v2.nMode) );
+ }
+ break;
+ case 1005:
+ {
+ mbResolutionInfoFilled = true;
+
+ nItemsRead = (int)(int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info.hRes = (short)Calculate(ShortValue, sizeof(resolution_info.hRes) );
+ nItemsRead = (int)(int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ resolution_info.hResUnit = Calculate(IntValue, sizeof(resolution_info.hResUnit) );
+ nItemsRead = (int)(int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info.widthUnit = (short)Calculate(ShortValue, sizeof(resolution_info.widthUnit) );
+
+ nItemsRead = (int)(int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info.vRes = (short)Calculate(ShortValue, sizeof(resolution_info.vRes) );
+ nItemsRead = (int)(int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ resolution_info.vResUnit = Calculate(IntValue, sizeof(resolution_info.vResUnit) );
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info.heightUnit = (short)Calculate(ShortValue, sizeof(resolution_info.heightUnit) );
+ }
+ break;
+ case 1007:
+ {
+ mbDisplayInfoFilled = true;
+
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ display_info.ColourSpace = (short)Calculate(ShortValue, sizeof(display_info.ColourSpace) );
+
+ for ( unsigned int n = 0; n < 4; ++n )
+ {
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ display_info.Colour[n] = (short)Calculate(ShortValue, sizeof(display_info.Colour[n]) );
+ }
+
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ display_info.Opacity = (short)Calculate(ShortValue, sizeof(display_info.Opacity) );
+ assert ( 0 <= display_info.Opacity );
+ assert ( 100 >= display_info.Opacity );
+
+ unsigned char c[1];
+ nItemsRead = (int)mypsd_fread(&c, sizeof(c), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(c);
+ ( 1 == Calculate(c, sizeof(c) ) ) ? display_info.kind = true : display_info.kind = false;
+
+ nItemsRead = (int)mypsd_fread(&c, sizeof(c), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(c);
+ display_info.padding = (unsigned int)Calculate(c, sizeof(c) );
+ assert ( 0 == display_info.padding );
+ }
+ break;
+ case 1034:
+ {
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ ( 1 == Calculate(ShortValue, sizeof(ShortValue) ) ) ? mbCopyright = true : mbCopyright = false;
+ }
+ break;
+ case 1033:
+ case 1036:
+ {
+ mbThumbNailFilled = true;
+
+ nItemsRead = (int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ thumbnail.nFormat = Calculate(IntValue, sizeof(thumbnail.nFormat) );
+
+ nItemsRead = (int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ thumbnail.nWidth = Calculate(IntValue, sizeof(thumbnail.nWidth) );
+
+ nItemsRead = (int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ thumbnail.nHeight = Calculate(IntValue, sizeof(thumbnail.nHeight) );
+
+ nItemsRead = (int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ thumbnail.nWidthBytes = Calculate(IntValue, sizeof(thumbnail.nWidthBytes) );
+
+ nItemsRead = (int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ thumbnail.nSize = Calculate(IntValue, sizeof(thumbnail.nSize) );
+
+ nItemsRead = (int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ thumbnail.nCompressedSize = Calculate(IntValue, sizeof(thumbnail.nCompressedSize) );
+
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ thumbnail.nBitPerPixel = (short)Calculate(ShortValue, sizeof(thumbnail.nBitPerPixel) );
+
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ thumbnail.nPlanes = (short)Calculate(ShortValue, sizeof(thumbnail.nPlanes) );
+
+ int nTotalData = image_resource.nSize - 28; // header
+ unsigned char* buffer = new unsigned char[nTotalData];
+ unsigned char c[1];
+ if ( 1033 == image_resource.nID )
+ {
+ // In BGR format
+ for (int n = 0; n < nTotalData; n = n +3 )
+ {
+ nItemsRead = (int)mypsd_fread(&c, sizeof(unsigned char), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(unsigned char);
+ buffer[n+2] = (unsigned char)Calculate(c, sizeof(unsigned char) );
+ nItemsRead = (int)mypsd_fread(&c, sizeof(unsigned char), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(unsigned char);
+ buffer[n+1] = (unsigned char)Calculate(c, sizeof(BYTE) );
+ nItemsRead = (int)mypsd_fread(&c, sizeof(unsigned char), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(unsigned char);
+ buffer[n] = (unsigned char)Calculate(c, sizeof(unsigned char) );
+ }
+ }
+ else if ( 1036 == image_resource.nID )
+ {
+ // In RGB format
+ for (int n = 0; n < nTotalData; ++n )
+ {
+ nItemsRead = (int)mypsd_fread(&c, sizeof(BYTE), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(BYTE);
+ buffer[n] = (BYTE)Calculate(c, sizeof(BYTE) );
+ }
+ }
+
+ delete[] buffer;
+ buffer = 0;
+ }
+ break;
+ case 1037:
+ {
+ nItemsRead = (int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ mnGlobalAngle = Calculate(IntValue, sizeof(mnGlobalAngle) );
+ }
+ break;
+ case 1046:
+ {
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ mnColourCount = (short)Calculate(ShortValue, sizeof(ShortValue) );
+ }
+ break;
+ case 1047:
+ {
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ mnTransparentIndex = (short)Calculate(ShortValue, sizeof(ShortValue) );
+ }
+ break;
+
+ default:
+ pFile.Seek(image_resource.nSize, SEEK_CUR);
+ nBytesRead += image_resource.nSize;
+ break;
+ }
+ }
+ }
+ }
+
+ assert ( nBytesRead == nTotalBytes );
+ if ( nBytesRead == nTotalBytes )
+ bSuccess = true;
+
+ return bSuccess;
+ }
+ bool CPSD::ReadColourModeData(CxFile &pFile, COLOUR_MODE_DATA& colour_mode_data)
+ {
+ // Only indexed colour and duotone have colour mode data,
+ // for all other modes this section is 4 bytes length, the length field is set to zero
+
+ // For indexed color images, the length will be equal to 768, and the color
+ // will contain the color table for the image, in non–interleaved order.
+
+ // For duotone images, the color data will contain the duotone specification,
+ // the format of which is not documented. Other applications that read
+ // Photoshop files can treat a duotone image as a grayscale image, and just
+ // preserve the contents of the duotone information when reading and writing
+ // the file.
+
+ // free memory
+ if ( 0 < colour_mode_data.nLength )
+ delete[] colour_mode_data.ColourData;
+ colour_mode_data.ColourData = 0;
+
+ unsigned char Length[4];
+ int nItemsRead = (int)mypsd_fread(&Length, sizeof(Length), 1, pFile);
+
+ colour_mode_data.nLength = Calculate( Length, sizeof(colour_mode_data.nLength) );
+ if ( 0 < colour_mode_data.nLength )
+ {
+ colour_mode_data.ColourData = new unsigned char[colour_mode_data.nLength];
+ nItemsRead = 0;
+ memset(colour_mode_data.ColourData, 254, colour_mode_data.nLength);
+
+ nItemsRead += (int)mypsd_fread( colour_mode_data.ColourData, colour_mode_data.nLength, 1, pFile);
+
+ }
+
+ return true;
+ }
+
+ bool CPSD::ReadHeader(CxFile &pFile, HEADER_INFO& header_info)
+ {
+ bool bSuccess = false;
+
+ struct HEADER
+ {
+ char Signature[4]; // always equal 8BPS, do not read file if not
+ unsigned char Version[2]; // always equal 1, do not read file if not
+ char Reserved[6]; // must be zero
+ unsigned char Channels[2]; // numer of channels including any alpha channels, supported range 1 to 24
+ unsigned char Rows[4]; // height in PIXELS, supported range 1 to 30000
+ unsigned char Columns[4]; // width in PIXELS, supported range 1 to 30000
+ unsigned char Depth[2]; // number of bpp
+ unsigned char Mode[2]; // colour mode of the file,
+ // Btmap=0, Grayscale=1, Indexed=2, RGB=3,
+ // CMYK=4, Multichannel=7, Duotone=8, Lab=9
+ };
+
+ HEADER header;
+ int nItemsRead = (int)mypsd_fread(&header, sizeof(HEADER), 1, pFile);
+ if ( nItemsRead )
+ {
+ if ( 0 == ::memcmp(header.Signature, "8BPS", 4))
+ {
+ int nVersion = Calculate( header.Version, sizeof(header.Version) );
+
+ if ( 1 == nVersion )
+ {
+ unsigned int n = 0;
+ bool bOK = true;
+ while ( (n < 6) && bOK )
+ {
+ if ( '\0' != header.Reserved[n] )
+ bOK = false;
+ n++;
+ }
+ bSuccess = bOK;
+
+ if ( bSuccess )
+ {
+ header_info.nChannels = (short)Calculate( header.Channels, sizeof(header.Channels) );
+ header_info.nHeight = Calculate( header.Rows, sizeof(header.Rows) );
+ header_info.nWidth = Calculate( header.Columns, sizeof(header.Columns) );
+ header_info.nBitsPerPixel = (short)Calculate( header.Depth, sizeof(header.Depth) );
+ header_info.nColourMode = (short)Calculate( header.Mode, sizeof(header.Mode) );
+ }
+ }
+ }
+ }
+
+ return bSuccess;
+ }
+
+
+ void CPSD::ProccessBuffer(unsigned char* pData )
+ {
+ if (!pData) return;
+
+ switch ( header_info.nColourMode )
+ {
+ case 1: // Grayscale
+ case 8: // Duotone
+ {
+ bool bAlpha = header_info.nChannels > 1;
+
+ int nPixels = header_info.nWidth * header_info.nHeight;
+ byte *pRGBA = new byte[nPixels * (bAlpha ? 4 : 3)];
+ byte *pSrc = pData, *pDst = pRGBA;
+ for (int i = 0; i < nPixels; i++, pSrc += header_info.nChannels, pDst += bAlpha ? 4 : 3)
+ {
+ pDst[0] = pDst[1] = pDst[2] = pSrc[0];
+ if (bAlpha) pDst[3] = pSrc[1];
+ }
+
+ m_image.CreateFromArray(pRGBA, header_info.nWidth, header_info.nHeight, bAlpha ? 32 : 24, header_info.nWidth * (bAlpha ? 4 : 3), true);
+
+ delete [] pRGBA;
+ }
+ break;
+ case 2: // Indexed
+ {
+ if (!colour_mode_data.ColourData) break;
+ if (colour_mode_data.nLength != 768) break;
+ if (mnColourCount == 0) break;
+
+ int nPixels = header_info.nWidth * header_info.nHeight;
+ byte *pRGB = new byte[nPixels * 3];
+ ::memset(pRGB, 0, nPixels * 3);
+ byte *pSrc = pData, *pDst = pRGB;
+ for (int i = 0; i < nPixels; i++, pSrc += header_info.nChannels, pDst += 3)
+ {
+ int nIndex = *pSrc;
+ pDst[2] = colour_mode_data.ColourData[nIndex + 0 * 256];
+ pDst[1] = colour_mode_data.ColourData[nIndex + 1 * 256];
+ pDst[0] = colour_mode_data.ColourData[nIndex + 2 * 256];
+ }
+
+ m_image.CreateFromArray(pRGB, header_info.nWidth, header_info.nHeight, 24, header_info.nWidth * 3, true);
+ delete [] pRGB;
+ }
+ break;
+ case 3: // RGB
+ {
+ m_image.CreateFromArray(pData, header_info.nWidth, header_info.nHeight, header_info.nChannels == 3 ? 24 : 32, header_info.nWidth * header_info.nChannels, true);
+ m_image.SwapRGB2BGR();
+ }
+ break;
+ case 4: // CMYK
+ {
+ bool bAlpha = header_info.nChannels > 4;
+
+ int nPixels = header_info.nWidth * header_info.nHeight;
+ byte *pRGBA = new byte[nPixels * (bAlpha ? 4 : 3)];
+ byte *pSrc = pData, *pDst = pRGBA;
+ double C, M, Y, K;
+ int nRed, nGreen, nBlue;
+ for (int i = 0; i < nPixels; i++, pSrc += header_info.nChannels, pDst += bAlpha ? 4 : 3)
+ {
+ C = (1.0 - (double)pSrc[0] / 256);
+ M = (1.0 - (double)pSrc[1] / 256);
+ Y = (1.0 - (double)pSrc[2] / 256);
+ K = (1.0 - (double)pSrc[3] / 256);
+
+ CMYKToRGB(C, M, Y, K, nRed, nGreen, nBlue);
+
+ if (0 > nRed) nRed = 0; else if (255 < nRed) nRed = 255;
+ if (0 > nGreen) nGreen = 0; else if (255 < nGreen) nGreen = 255;
+ if (0 > nBlue) nBlue = 0; else if (255 < nBlue) nBlue = 255;
+
+ pDst[0] = nBlue; pDst[1] = nGreen; pDst[2] = nRed;
+ if (bAlpha) pDst[3] = pSrc[4];
+ }
+
+ m_image.CreateFromArray(pRGBA, header_info.nWidth, header_info.nHeight, bAlpha ? 32 : 24, header_info.nWidth * (bAlpha ? 4 : 3), true);
+
+ delete [] pRGBA;
+ }
+ break;
+ case 7: // Multichannel
+ {
+ if (header_info.nChannels == 0 || header_info.nChannels > 4) break; // ???
+
+ int nPixels = header_info.nWidth * header_info.nHeight;
+ byte *pRGB = new byte[nPixels * 3];
+ byte *pSrc = pData, *pDst = pRGB;
+ double C, M, Y, K;
+ int nRed, nGreen, nBlue;
+ for (int i = 0; i < nPixels; i++, pSrc += header_info.nChannels, pDst += 3)
+ {
+ C = M = Y = K = 0;
+ C = (1.0 - (double)pSrc[0] / 256);
+ if (header_info.nChannels > 1) M = (1.0 - (double)pSrc[1] / 256);
+ if (header_info.nChannels > 2) Y = (1.0 - (double)pSrc[2] / 256);
+ if (header_info.nChannels > 3) K = (1.0 - (double)pSrc[3] / 256);
+
+ CMYKToRGB(C, M, Y, K, nRed, nGreen, nBlue);
+
+ if (0 > nRed) nRed = 0; else if (255 < nRed) nRed = 255;
+ if (0 > nGreen) nGreen = 0; else if (255 < nGreen) nGreen = 255;
+ if (0 > nBlue) nBlue = 0; else if (255 < nBlue) nBlue = 255;
+
+ pDst[0] = nBlue; pDst[1] = nGreen; pDst[2] = nRed;
+ }
+
+ m_image.CreateFromArray(pRGB, header_info.nWidth, header_info.nHeight, 24, header_info.nWidth * 3, true);
+
+ delete [] pRGB;
+ }
+ break;
+ case 9: // Lab
+ {
+ bool bAlpha = header_info.nChannels > 3;
+
+ int nPixels = header_info.nWidth * header_info.nHeight;
+ byte *pRGBA = new byte[nPixels * (bAlpha ? 4 : 3)];
+ byte *pSrc = pData, *pDst = pRGBA;
+
+ double L_coef = 256.f / 100.f, a_coef = 256.f / 256.f, b_coef = 256.f / 256.f;
+ int L, a, b;
+ int nRed, nGreen, nBlue;
+ for (int i = 0; i < nPixels; i++, pSrc += header_info.nChannels, pDst += bAlpha ? 4 : 3)
+ {
+ L = (int)((float)pSrc[0] / L_coef);
+ a = (int)((float)pSrc[1] / a_coef - 128.0);
+ b = (int)((float)pSrc[2] / b_coef - 128.0);
+
+ LabToRGB(L, a, b, nRed, nGreen, nBlue );
+
+ if (0 > nRed) nRed = 0; else if (255 < nRed) nRed = 255;
+ if (0 > nGreen) nGreen = 0; else if (255 < nGreen) nGreen = 255;
+ if (0 > nBlue) nBlue = 0; else if (255 < nBlue) nBlue = 255;
+
+ pDst[0] = nBlue; pDst[1] = nGreen; pDst[2] = nRed;
+ if (bAlpha) pDst[3] = pSrc[3];
+ }
+
+ m_image.CreateFromArray(pRGBA, header_info.nWidth, header_info.nHeight, bAlpha ? 32 : 24, header_info.nWidth * (bAlpha ? 4 : 3), true);
+
+ delete [] pRGBA;
+ }
+ break;
+ }
+ }
+
+ int CPSD::Load(LPCTSTR szPathName)
+ {
+ CxIOFile f;
+ if (!f.Open(szPathName, _T("rb"))) return -1;
+ return Load(f);
+ }
+
+ int CPSD::Load(CxFile &f)
+ {
+ if (!ReadHeader(f, header_info)) return -2; // Error in header
+ if (!ReadColourModeData(f, colour_mode_data)) return -3; // Error in ColourMode Data
+ if (!ReadImageResource(f, image_resource)) return -4; // Error in Image Resource
+ if (!ReadLayerAndMaskInfoSection(f)) return -5; // Error in Mask Info
+ if (ReadImageData(f) != 0) return -6; // Error in Image Data
+ return 0; // all right
+ }
+
+ int CPSD::DecodeRawData( CxFile &pFile)
+ {
+ if (header_info.nBitsPerPixel != 8 && header_info.nBitsPerPixel != 16) return -7; // can't read this
+
+ int nWidth = header_info.nWidth;
+ int nHeight = header_info.nHeight;
+ int bytesPerPixelPerChannel = header_info.nBitsPerPixel / 8;
+
+ int nPixels = nWidth * nHeight;
+ int nTotalBytes = 0;
+
+ byte* pData = NULL;
+
+ switch ( header_info.nColourMode )
+ {
+ case 1: // Grayscale
+ case 2: // Indexed
+ case 3: // RGB
+ case 4: // CMYK
+ case 8: // Duotone
+ case 9: // Lab
+ {
+ // read RRRRRRRGGGGGGGBBBBBBAAAAAA data
+ int nAllDataSize = nPixels * bytesPerPixelPerChannel * header_info.nChannels;
+ byte *pFileData = new byte[nAllDataSize];
+ ::memset(pFileData, 0, nAllDataSize);
+ if (pFile.Read(pFileData, nAllDataSize, 1) != 1)
+ {
+ delete [] pFileData;
+ return -1; // bad data
+ }
+
+ // and convert them to RGBARGBARGBA data (depends on number of channels)
+ nTotalBytes = nPixels * header_info.nChannels;
+ pData = new byte[nTotalBytes];
+ byte *pSource = pFileData;
+ for (int nChannel = 0; nChannel < header_info.nChannels; nChannel++)
+ {
+ byte *pDest = pData + nChannel;
+ for (int pos = 0; pos < nPixels; pos++, pDest += header_info.nChannels, pSource += bytesPerPixelPerChannel) *pDest = *pSource;
+ }
+ delete [] pFileData;
+ }
+ break;
+ default:
+ return -1; // unsupported format
+ }
+
+ ProccessBuffer(pData);
+ delete [] pData;
+
+ // dpi related things
+ int ppm_x = 3780; // 96 dpi
+ int ppm_y = 3780; // 96 dpi
+ if (mbResolutionInfoFilled)
+ {
+ int nHorResolution = (int)resolution_info.hRes;
+ int nVertResolution = (int)resolution_info.vRes;
+ ppm_x = (nHorResolution * 10000) / 254;
+ ppm_y = (nVertResolution * 10000) / 254;
+ }
+ m_image.SetXDPI(ppm_x);
+ m_image.SetYDPI(ppm_y);
+
+ return 0;
+ }
+
+
+ int CPSD::DecodeRLEData(CxFile & pFile)
+ {
+ if (header_info.nBitsPerPixel != 8) return -7; // can't read this
+
+ int nWidth = header_info.nWidth;
+ int nHeight = header_info.nHeight;
+ int nPixels = nWidth * nHeight;
+
+ // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data
+ // read them and compute size of RLE data
+ int nLengthDataSize = nHeight * header_info.nChannels * 2;
+ byte *pLengthData = new byte[nLengthDataSize];
+ if (pFile.Read(pLengthData, nLengthDataSize, 1) != 1)
+ {
+ delete [] pLengthData;
+ return -1; // error while reading
+ }
+ int nRLEDataSize = 0;
+ for (int i = 0; i < nHeight * header_info.nChannels * 2; i += 2)
+ nRLEDataSize += Calculate(pLengthData + i, 2);
+ delete [] pLengthData;
+
+ // now read RLE data to the buffer for fast access
+ byte *pRLEData = new byte[nRLEDataSize];
+ if (pFile.Read(pRLEData, nRLEDataSize, 1) != 1)
+ {
+ delete [] pRLEData;
+ return -1;
+ }
+
+ // allocate buffer for raw data (RRRRRRR...RRRGGGGG...GGGGGGBBBBB...BBBBBAAAAA....AAAAA) it has the same size as the final buffer
+ // and the perform RLE-decoding
+ int nTotalBytes = nPixels * header_info.nChannels;
+ byte* pRawData = new byte[nTotalBytes];
+ byte *pRLESource = pRLEData, *pRLEDest = pRawData;
+ for (int channel = 0; channel < header_info.nChannels; channel++)
+ {
+ int nCount = 0;
+ while (nCount < nPixels)
+ {
+ int len = *pRLESource++;
+ if ( 128 > len )
+ { // copy next (len + 1) bytes as is
+ len++;
+ nCount += len;
+ ::memcpy(pRLEDest, pRLESource, len);
+ pRLEDest += len; pRLESource += len;
+ }
+ else if ( 128 < len )
+ {
+ // Next -len+1 bytes in the dest are replicated from next source byte.
+ // (Interpret len as a negative 8-bit int.)
+ len ^= 0x0FF;
+ len += 2;
+ nCount += len;
+ ::memset(pRLEDest, *pRLESource++, len);
+ pRLEDest += len;
+ }
+ else if ( 128 == len ) { /* Do nothing */ }
+ }
+ }
+ delete [] pRLEData;
+
+ // transform raw data to the good one (RGBARGBARGBA...RGBA)
+ byte *pRawSource = pRawData;
+ byte *pData = new byte[nTotalBytes];
+ int nPixelCounter = 0;
+ for( int nColour = 0; nColour < header_info.nChannels; ++nColour )
+ {
+ nPixelCounter = nColour;
+ for (int nPos = 0; nPos < nPixels; nPos++, pRawSource++)
+ {
+ pData[nPixelCounter] = *pRawSource;
+ nPixelCounter += header_info.nChannels;
+ }
+ }
+ delete[] pRawData;
+
+ // create image
+ ProccessBuffer(pData);
+ delete [] pData;
+
+ // dpi related things
+ int ppm_x = 3780; // 96 dpi
+ int ppm_y = 3780; // 96 dpi
+ if (mbResolutionInfoFilled)
+ {
+ int nHorResolution = (int)resolution_info.hRes;
+ int nVertResolution = (int)resolution_info.vRes;
+ ppm_x = (nHorResolution * 10000) / 254;
+ ppm_y = (nVertResolution * 10000) / 254;
+ }
+ m_image.SetXDPI(ppm_x);
+ m_image.SetYDPI(ppm_y);
+
+ return 0;
+ }
+
+ int CPSD::ReadImageData(CxFile &pFile)
+ {
+ int nErrorCode = 0; // No Errors
+
+ if ( !mypsd_feof(pFile) )
+ {
+ unsigned char ShortValue[2];
+ int nBytesRead = 0;
+ int nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ short nCompression = (short)Calculate( ShortValue, sizeof(ShortValue) );
+
+ switch ( nCompression )
+ {
+ case 0: // raw data
+ nErrorCode = DecodeRawData(pFile);
+ break;
+ case 1: // RLE compression
+ nErrorCode = DecodeRLEData(pFile);
+ break;
+ case 2: // ZIP without prediction
+ nErrorCode = -10; // ZIP without prediction, no specification
+ break;
+ case 3: // ZIP with prediction
+ nErrorCode = -11; // ZIP with prediction, no specification
+ break;
+ default:
+ nErrorCode = -12; // Unknown format
+ }
+ }
+ return nErrorCode;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////
+ CPSD::HEADER_INFO::HEADER_INFO()
+ {
+ nChannels = -1;
+ nHeight = -1;
+ nWidth = -1;
+ nBitsPerPixel = -1;
+ nColourMode = -1;
+ }
+
+ CPSD::COLOUR_MODE_DATA::COLOUR_MODE_DATA()
+ {
+ nLength = -1;
+ ColourData = 0;
+ }
+
+ CPSD::IMAGE_RESOURCE::IMAGE_RESOURCE()
+ {
+ Name = 0;
+ Reset();
+ }
+
+ void CPSD::IMAGE_RESOURCE::Reset()
+ {
+ nLength = -1;
+ memset( OSType, '\0', sizeof(OSType) );
+ nID = -1;
+ if ( Name )
+ delete[] Name;
+ Name = 0;
+ nSize = -1;
+ }
+
+ CPSD::RESOLUTION_INFO::RESOLUTION_INFO()
+ {
+ hRes = -1;
+ hResUnit = -1;
+ widthUnit = -1;
+ vRes = -1;
+ vResUnit = -1;
+ heightUnit = -1;
+ }
+
+ CPSD::RESOLUTION_INFO_v2::RESOLUTION_INFO_v2()
+ {
+ nChannels = -1;
+ nRows = -1;
+ nColumns = -1;
+ nDepth = -1;
+ nMode = -1;
+ }
+
+ CPSD::DISPLAY_INFO::DISPLAY_INFO()
+ {
+ ColourSpace = -1;
+ for ( unsigned int n = 0; n < 4; ++n)
+ Colour[n] = 0;
+ Opacity = -1;
+ kind = false;
+ padding = '0';
+ }
+
+ CPSD::THUMBNAIL::THUMBNAIL()
+ {
+ nFormat = -1;
+ nWidth = -1;
+ nHeight = -1;
+ nWidthBytes = -1;
+ nSize = -1;
+ nCompressedSize = -1;
+ nBitPerPixel = -1;
+ nPlanes = -1;
+ Data = 0;
+ }
+} // MyPSD
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_USE_LIBPSD
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImagePSD::Decode(CxFile *hFile)
+{
+ if (hFile==NULL)
+ return false;
+
+#if CXIMAGE_USE_LIBPSD
+ psd_context* context = NULL;
+#endif
+
+ cx_try
+ {
+#if CXIMAGE_USE_LIBPSD
+
+ psd_status status;
+
+ context = (psd_context *)malloc(sizeof(psd_context));
+ if(context == NULL){
+ cx_throw("CxImagePSD: psd_status_malloc_failed");
+ }
+ memset(context, 0, sizeof(psd_context));
+
+ // install file manager
+ CxFilePsd src(hFile,context);
+
+ context->state = PSD_FILE_HEADER;
+ context->stream.file_length = hFile->Size();
+ context->load_tag = psd_load_tag_all;
+ status = psd_main_loop(context);
+
+ if(status != psd_status_done){
+ cx_throw("CxImagePSD: psd_main_loop failed");
+ }
+
+ Create(context->width,context->height,24,CXIMAGE_FORMAT_PSD);
+
+ uint8_t* rgba = (uint8_t*)context->merged_image_data;
+ uint8_t* alpha = NULL;
+ if (context->alpha_channel_info)
+ alpha = (uint8_t*)context->alpha_channel_info->channel_data;
+ if (alpha)
+ AlphaCreate();
+
+ int32_t x,y;
+ RGBQUAD c;
+ c.rgbReserved = 0;
+ if (rgba){
+ for(y =context->height-1; y--;){
+ for (x=0; x<context->width; x++){
+ c.rgbBlue = *rgba++;
+ c.rgbGreen = *rgba++;
+ c.rgbRed = *rgba++;
+ rgba++;
+ SetPixelColor(x,y,c);
+#if CXIMAGE_SUPPORT_ALPHA
+ if (alpha) AlphaSet(x,y,*alpha++);
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+ }
+ }
+
+ psd_image_free(context);
+ free(context);
+
+#else //CXIMAGE_USE_LIBPSD == 0
+
+ MyPSD::CPSD psd(*this);
+ int nErrorCode = psd.Load(*hFile);
+ if (nErrorCode != 0) cx_throw("error loading PSD file");
+
+#endif //CXIMAGE_USE_LIBPSD
+
+ } cx_catch {
+
+#if CXIMAGE_USE_LIBPSD
+ psd_image_free(context);
+ if (context) free(context);
+#endif //CXIMAGE_USE_LIBPSD
+
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ if (info.nEscape == -1 && info.dwType == CXIMAGE_FORMAT_PSD) return true;
+ return false;
+ }
+ /* that's it */
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImagePSD::Encode(CxFile * hFile)
+{
+ if (hFile == NULL) return false;
+ strcpy(info.szLastError, "Save PSD not supported");
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_PSD
+