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; }
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) ); assert( 0 <= _Opacity ); assert( 100 >= _Opacity ); 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)); assert( 0 == _padding ); return nBytes; }
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; }
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; }
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; }
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 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 psdHeaderInfo::Read(FreeImageIO *io, fi_handle handle) { bool bSuccess = false; 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 unsigned i = 0; bool bOK = true; while ( (i < 6) && bOK ) { if ( '\0' != header.Reserved[i] ) { bOK = false; break; } i++; } bSuccess = bOK; if (bSuccess) { // 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) ); _BitsPerPixel = (short)psdGetValue( header.Depth, sizeof(header.Depth) ); _ColourMode = (short)psdGetValue( header.Mode, sizeof(header.Mode) ); } } } 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]; //UNUSED F*****G VARIABLE. F**K F*****G EVERYONE F*****G ELSE GOD F*****G DAMN IT YOU F*****G MOTHER FUCKERS //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); if(n != 1) { FreeImage_OutputMessageProc(_fi_format_id, "This file contains damaged data causing an unexpected end-of-file - stop reading resources"); return false; } 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; }
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; }
FIBITMAP* psdParser::ProcessBuffer(BYTE * iprData) { assert(NULL != iprData); FIBITMAP *Bitmap = NULL; int nHeight = _headerInfo._Height; int nWidth = _headerInfo._Width; unsigned bytes = _headerInfo._BitsPerPixel / 8; int nChannels = _headerInfo._Channels; switch (_headerInfo._ColourMode) { case PSD_BITMAP: // Bitmap { // monochrome 1-bit FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 1); if (NULL != dib) { // fill the palette RGBQUAD *pal = FreeImage_GetPalette(dib); if(pal) { for (int i = 0; i < 2; i++) { BYTE val = i ? 0x0 : 0xFF; pal[i].rgbRed = val; pal[i].rgbGreen = val; pal[i].rgbBlue = val; } } // copy buffer BYTE *src_bits = (BYTE*)iprData; BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1); unsigned src_pitch = (nWidth + 7) / 8; unsigned dst_pitch = FreeImage_GetPitch(dib); for(int y = 0; y < nHeight; y++) { memcpy(dst_bits, src_bits, src_pitch); src_bits += src_pitch; dst_bits -= dst_pitch; } } Bitmap = dib; } break; case PSD_GRAYSCALE: // Grayscale case PSD_DUOTONE: // Duotone case PSD_RGB: // RGB { // 16-bit / channel // -------------------------------------------------------------- if (16 == _headerInfo._BitsPerPixel) { if (1 == nChannels) { // L 16-bit FIBITMAP *dib = FreeImage_AllocateT(FIT_UINT16, nWidth, nHeight); if (NULL != dib) { // just copy buffer BYTE *src_bits = (BYTE*)iprData; BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1); unsigned src_pitch = nChannels * nWidth * bytes; unsigned dst_pitch = FreeImage_GetPitch(dib); for(int y = 0; y < nHeight; y++) { memcpy(dst_bits, src_bits, src_pitch); src_bits += src_pitch; dst_bits -= dst_pitch; } Bitmap = dib; } } else if (2 == nChannels) { // LA 16-bit : convert to RGBA 16-bit FIBITMAP *dib = FreeImage_AllocateT(FIT_RGBA16, nWidth, nHeight); if (NULL != dib) { unsigned short *src_bits = (unsigned short*)iprData; FIRGBA16 *dst_bits = (FIRGBA16*)FreeImage_GetScanLine(dib, nHeight-1); unsigned pitch = FreeImage_GetPitch(dib) / sizeof(FIRGBA16); for(int y = 0; y < nHeight; y++) { for(int x = 0; x < nWidth; x++) { dst_bits[x].red = src_bits[0]; dst_bits[x].green = src_bits[0]; dst_bits[x].blue = src_bits[0]; dst_bits[x].alpha = src_bits[1]; src_bits += nChannels; } dst_bits -= pitch; } Bitmap = dib; } } else if (3 == nChannels) { // RGB 16-bit FIBITMAP *dib = FreeImage_AllocateT(FIT_RGB16, nWidth, nHeight); if (NULL != dib) { // just copy buffer BYTE *src_bits = (BYTE*)iprData; BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1); unsigned src_pitch = nChannels * nWidth * bytes; unsigned dst_pitch = FreeImage_GetPitch(dib); for(int y = 0; y < nHeight; y++) { memcpy(dst_bits, src_bits, src_pitch); src_bits += src_pitch; dst_bits -= dst_pitch; } Bitmap = dib; } } else if (4 == nChannels) { // RGBA 16-bit FIBITMAP *dib = FreeImage_AllocateT(FIT_RGBA16, nWidth, nHeight); if (NULL != dib) { // just copy buffer BYTE *src_bits = (BYTE*)iprData; BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1); unsigned src_pitch = nChannels * nWidth * bytes; unsigned dst_pitch = FreeImage_GetPitch(dib); for(int y = 0; y < nHeight; y++) { memcpy(dst_bits, src_bits, src_pitch); src_bits += src_pitch; dst_bits -= dst_pitch; } Bitmap = dib; } } } // 8-bit / channel // -------------------------------------------------------------- else if (8 == _headerInfo._BitsPerPixel) { if (1 == nChannels) { // L 8-bit FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 8); if (NULL != dib) { // build a greyscale palette RGBQUAD *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; } // just copy buffer BYTE *src_bits = (BYTE*)iprData; BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1); unsigned src_pitch = nChannels * nWidth * bytes; unsigned dst_pitch = FreeImage_GetPitch(dib); for(int y = 0; y < nHeight; y++) { memcpy(dst_bits, src_bits, src_pitch); src_bits += src_pitch; dst_bits -= dst_pitch; } Bitmap = dib; } } else if (2 == nChannels) { // LA 8-bit : convert to RGBA 32-bit FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 32); if (NULL != dib) { BYTE *src_bits = (BYTE*)iprData; BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1); unsigned src_pitch = nChannels * nWidth * bytes; unsigned dst_pitch = FreeImage_GetPitch(dib); for(int y = 0; y < nHeight; y++) { BYTE *p_src = src_bits; BYTE *p_dst = dst_bits; for(int x = 0; x < nWidth; x++) { p_dst[FI_RGBA_RED] = p_src[0]; p_dst[FI_RGBA_GREEN] = p_src[0]; p_dst[FI_RGBA_BLUE] = p_src[0]; p_dst[FI_RGBA_ALPHA] = p_src[1]; p_src += nChannels; p_dst += 4; } src_bits += src_pitch; dst_bits -= dst_pitch; } Bitmap = dib; } } else if (3 == nChannels) { // RGB 8-bit FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 24); if (NULL != dib) { // just copy buffer BYTE *src_bits = (BYTE*)iprData; BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1); unsigned src_pitch = nChannels * nWidth * bytes; unsigned dst_pitch = FreeImage_GetPitch(dib); for(int y = 0; y < nHeight; y++) { BYTE *p_src = src_bits; BYTE *p_dst = dst_bits; for(int x = 0; x < nWidth; x++) { p_dst[FI_RGBA_RED] = p_src[0]; p_dst[FI_RGBA_GREEN] = p_src[1]; p_dst[FI_RGBA_BLUE] = p_src[2]; p_src += nChannels; p_dst += nChannels; } src_bits += src_pitch; dst_bits -= dst_pitch; } Bitmap = dib; } } else if (4 == nChannels) { // RGBA 8-bit FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 32); if (NULL != dib) { // just copy buffer BYTE *src_bits = (BYTE*)iprData; BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1); unsigned src_pitch = nChannels * nWidth * bytes; unsigned dst_pitch = FreeImage_GetPitch(dib); for(int y = 0; y < nHeight; y++) { BYTE *p_src = src_bits; BYTE *p_dst = dst_bits; for(int x = 0; x < nWidth; x++) { p_dst[FI_RGBA_RED] = p_src[0]; p_dst[FI_RGBA_GREEN] = p_src[1]; p_dst[FI_RGBA_BLUE] = p_src[2]; p_dst[FI_RGBA_ALPHA] = p_src[3]; p_src += nChannels; p_dst += nChannels; } src_bits += src_pitch; dst_bits -= dst_pitch; } Bitmap = dib; } } else { assert(false);// do nothing } } // 32-bit / channel => undocumented HDR // -------------------------------------------------------------- else if (32 == _headerInfo._BitsPerPixel) { if (3 == nChannels) { // RGBF 32-bit FIBITMAP *dib = FreeImage_AllocateT(FIT_RGBF, nWidth, nHeight); if (NULL != dib) { // just copy buffer BYTE *src_bits = (BYTE*)iprData; BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1); unsigned src_pitch = nChannels * nWidth * bytes; unsigned dst_pitch = FreeImage_GetPitch(dib); for(int y = 0; y < nHeight; y++) { memcpy(dst_bits, src_bits, src_pitch); src_bits += src_pitch; dst_bits -= dst_pitch; } Bitmap = dib; } } } } break; case PSD_INDEXED: // Indexed { // iprData holds the indices of loop through the palette assert(0 != _colourModeData._plColourData); assert(768 == _colourModeData._Length); assert(0 < _ColourCount); // grey or palettised 8 bits FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 8); if (NULL != dib) { // get the palette if (_colourModeData.FillPalette(dib)) { // copy buffer BYTE *src_bits = (BYTE*)iprData; BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1); unsigned src_pitch = nChannels * nWidth * bytes; unsigned dst_pitch = FreeImage_GetPitch(dib); for(int y = 0; y < nHeight; y++) { memcpy(dst_bits, src_bits, src_pitch); src_bits += src_pitch; dst_bits -= dst_pitch; } } } Bitmap = dib; } break; case PSD_CMYK: // CMYK { float C, M, Y, K; float s = 1.f / pow( 2.0f, _headerInfo._BitsPerPixel); if (16 == _headerInfo._BitsPerPixel) { // CMYK 16-bit : convert to RGB 16-bit FIBITMAP *dib = FreeImage_AllocateT(FIT_RGB16, nWidth, nHeight); if (NULL != dib) { BYTE *src_bits = (BYTE*)iprData; BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1); unsigned src_pitch = nChannels * nWidth * bytes; unsigned dst_pitch = FreeImage_GetPitch(dib); for(int y = 0; y < nHeight; y++) { unsigned short *src_line = (unsigned short*)src_bits; FIRGB16 *dst_line = (FIRGB16*)dst_bits; for(int x = 0; x < nWidth; x++) { C = (1.f - (float)psdGetValue((BYTE*)&src_line[0], bytes ) * s ); M = (1.f - (float)psdGetValue((BYTE*)&src_line[1], bytes ) * s ); Y = (1.f - (float)psdGetValue((BYTE*)&src_line[2], bytes ) * s ); K = (1.f - (float)psdGetValue((BYTE*)&src_line[3], bytes ) * s ); CMYKToRGB16(C, M, Y, K, &dst_line[x]); src_line += nChannels; } src_bits += src_pitch; dst_bits -= dst_pitch; } Bitmap = dib; } } else { // CMYK 8-bit : convert to RGB 8-bit FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 24); if (NULL != dib) { BYTE *src_bits = (BYTE*)iprData; BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1); unsigned src_pitch = nChannels * nWidth * bytes; unsigned dst_pitch = FreeImage_GetPitch(dib); for(int y = 0; y < nHeight; y++) { BYTE *src_line = (BYTE*)src_bits; RGBTRIPLE *dst_line = (RGBTRIPLE*)dst_bits; for(int x = 0; x < nWidth; x++) { C = (1.f - (float)psdGetValue((BYTE*)&src_line[0], bytes ) * s ); M = (1.f - (float)psdGetValue((BYTE*)&src_line[1], bytes ) * s ); Y = (1.f - (float)psdGetValue((BYTE*)&src_line[2], bytes ) * s ); K = (1.f - (float)psdGetValue((BYTE*)&src_line[3], bytes ) * s ); CMYKToRGB8(C, M, Y, K, &dst_line[x]); src_line += nChannels; } src_bits += src_pitch; dst_bits -= dst_pitch; } Bitmap = dib; } } } break; case PSD_MULTICHANNEL: // Multichannel { // assume format is in either CMY or CMYK assert(3 <= nChannels); float C, M, Y, K; float s = 1.f / pow( 2.0f, _headerInfo._BitsPerPixel); if (16 == _headerInfo._BitsPerPixel) { // CMY(K) 16-bit : convert to RGB 16-bit FIBITMAP *dib = FreeImage_AllocateT(FIT_RGB16, nWidth, nHeight); if (NULL != dib) { BYTE *src_bits = (BYTE*)iprData; BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1); unsigned src_pitch = nChannels * nWidth * bytes; unsigned dst_pitch = FreeImage_GetPitch(dib); for(int y = 0; y < nHeight; y++) { unsigned short *src_line = (unsigned short*)src_bits; FIRGB16 *dst_line = (FIRGB16*)dst_bits; for(int x = 0; x < nWidth; x++) { C = (1.f - (float)psdGetValue((BYTE*)&src_line[0], bytes ) * s ); M = (1.f - (float)psdGetValue((BYTE*)&src_line[1], bytes ) * s ); Y = (1.f - (float)psdGetValue((BYTE*)&src_line[2], bytes ) * s ); K = (4 <= nChannels) ? (1.f - (float)psdGetValue((BYTE*)&src_line[nChannels], bytes )*s ) : 0; CMYKToRGB16(C, M, Y, K, &dst_line[x]); src_line += nChannels; } src_bits += src_pitch; dst_bits -= dst_pitch; } Bitmap = dib; } } else { // CMY(K) 8-bit : convert to RGB 8-bit FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 24); if (NULL != dib) { BYTE *src_bits = (BYTE*)iprData; BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1); unsigned src_pitch = nChannels * nWidth * bytes; unsigned dst_pitch = FreeImage_GetPitch(dib); for(int y = 0; y < nHeight; y++) { BYTE *src_line = (BYTE*)src_bits; RGBTRIPLE *dst_line = (RGBTRIPLE*)dst_bits; for(int x = 0; x < nWidth; x++) { C = (1.f - (float)psdGetValue((BYTE*)&src_line[0], bytes ) * s ); M = (1.f - (float)psdGetValue((BYTE*)&src_line[1], bytes ) * s ); Y = (1.f - (float)psdGetValue((BYTE*)&src_line[2], bytes ) * s ); K = (4 <= nChannels) ? (1.f - (float)psdGetValue((BYTE*)&src_line[nChannels], bytes )*s ) : 0; CMYKToRGB8(C, M, Y, K, &dst_line[x]); src_line += nChannels; } src_bits += src_pitch; dst_bits -= dst_pitch; } Bitmap = dib; } } } break; case PSD_LAB: // Lab { const unsigned dMaxColours = 1 << _headerInfo._BitsPerPixel; const float sL = 100.F / dMaxColours; const float sa = 256.F / dMaxColours; const float sb = 256.F / dMaxColours; float L, a, b; if (16 == _headerInfo._BitsPerPixel) { // CIE Lab 16-bit : convert to RGB 16-bit FIBITMAP *dib = FreeImage_AllocateT(FIT_RGB16, nWidth, nHeight); if (NULL != dib) { BYTE *src_bits = (BYTE*)iprData; BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1); unsigned src_pitch = nChannels * nWidth * bytes; unsigned dst_pitch = FreeImage_GetPitch(dib); for(int y = 0; y < nHeight; y++) { unsigned short *src_line = (unsigned short*)src_bits; FIRGB16 *dst_line = (FIRGB16*)dst_bits; for(int x = 0; x < nWidth; x++) { L = (float)psdGetValue((BYTE*)&src_line[0], bytes ) * sL; a = (float)psdGetValue((BYTE*)&src_line[1], bytes ) * sa - 128.F; b = (float)psdGetValue((BYTE*)&src_line[2], bytes ) * sb - 128.F; CIELabToRGB16(L, a, b, &dst_line[x]); src_line += nChannels; } src_bits += src_pitch; dst_bits -= dst_pitch; } Bitmap = dib; } } else { // CIE Lab 8-bit : convert to RGB 8-bit FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 24); if (NULL != dib) { BYTE *src_bits = (BYTE*)iprData; BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1); unsigned src_pitch = nChannels * nWidth * bytes; unsigned dst_pitch = FreeImage_GetPitch(dib); for(int y = 0; y < nHeight; y++) { BYTE *src_line = (BYTE*)src_bits; RGBTRIPLE *dst_line = (RGBTRIPLE*)dst_bits; for(int x = 0; x < nWidth; x++) { L = (float)psdGetValue((BYTE*)&src_line[0], bytes ) * sL; a = (float)psdGetValue((BYTE*)&src_line[1], bytes ) * sa - 128.F; b = (float)psdGetValue((BYTE*)&src_line[2], bytes ) * sb - 128.F; CIELabToRGB8(L, a, b, &dst_line[x]); src_line += nChannels; } src_bits += src_pitch; dst_bits -= dst_pitch; } Bitmap = dib; } } } break; default: break; } return Bitmap; }
bool psdParser::ReadImageResource(FreeImageIO *io, fi_handle handle) { psdImageResource oResource; bool bSuccess = false; 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) { n = 0; oResource.Reset(); n = (int)io->read_proc(&oResource._OSType, sizeof(oResource._OSType), 1, handle); nBytes += n * sizeof(oResource._OSType); assert( 0 == (nBytes % 2) ); 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); int nTotalData = oResource._Size - 28; // header nBytes += _thumbnail.Read(io, handle, nTotalData, 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 BYTE c[1]; for(int i=0; i<oResource._Size; ++i) { n = (int)io->read_proc(&c, sizeof(c), 1, handle); nBytes += n * sizeof(c); } } break; } } } } assert(nBytes == nTotalBytes); if (nBytes == nTotalBytes) { bSuccess = true; } return bSuccess; }
int psdThumbnail::Read(FreeImageIO *io, fi_handle handle, int iTotalData, bool isBGR) { BYTE c[1], ShortValue[2], IntValue[4]; int nBytes=0, n; 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) ); _plData = new BYTE[iTotalData]; if (isBGR) { // In BGR format for (int i=0; i<iTotalData; i+=3 ) { n = (int)io->read_proc(&c, sizeof(BYTE), 1, handle); nBytes += n * sizeof(BYTE); _plData[i+2] = (BYTE)psdGetValue(c, sizeof(BYTE) ); n = (int)io->read_proc(&c, sizeof(BYTE), 1, handle); nBytes += n * sizeof(BYTE); _plData[i+1] = (BYTE)psdGetValue(c, sizeof(BYTE) ); n = (int)io->read_proc(&c, sizeof(BYTE), 1, handle); nBytes += n * sizeof(BYTE); _plData[i+0] = (BYTE)psdGetValue(c, sizeof(BYTE) ); } } else { // In RGB format for (int i=0; i<iTotalData; ++i) { n = (int)io->read_proc(&c, sizeof(BYTE), 1, handle); nBytes += n * sizeof(BYTE); _plData[i] = (BYTE)psdGetValue(c, sizeof(BYTE) ); } } return nBytes; }
FIBITMAP* psdParser::ReadImageData(FreeImageIO *io, fi_handle handle) { FIBITMAP *Bitmap = NULL; if(handle != NULL) { BYTE ShortValue[2]; int n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); short nCompression = (short)psdGetValue( ShortValue, sizeof(ShortValue) ); switch ( nCompression ) { case PSD_COMPRESSION_NONE: // raw data { int nWidth = _headerInfo._Width; int nHeight = _headerInfo._Height; int bytes = _headerInfo._BitsPerPixel / 8; int nPixels = nWidth * nHeight; int nTotalBytes = nPixels * bytes * _headerInfo._Channels; if(_headerInfo._BitsPerPixel == 1) { // special case for PSD_BITMAP mode bytes = 1; nWidth = (nWidth + 7) / 8; nWidth = ( nWidth > 0 ) ? nWidth : 1; nPixels = nWidth * nHeight; nTotalBytes = nWidth * nHeight; } BYTE * plData = 0; BYTE * plPixel = 0; int nBytes = 0; switch (_headerInfo._ColourMode) { case PSD_BITMAP: { plData = new BYTE [nTotalBytes]; plPixel = new BYTE [bytes]; while(nBytes < nTotalBytes) { n = (int)io->read_proc(plPixel, bytes, 1, handle); memcpy(plData+nBytes, plPixel, bytes ); nBytes += n * bytes; } SAFE_DELETE_ARRAY(plPixel); } break; case PSD_INDEXED: // Indexed { assert( (-1 != _ColourCount) && (0 < _ColourCount) ); assert( NULL != _colourModeData._plColourData ); plData = new BYTE [nTotalBytes]; plPixel = new BYTE [bytes]; while(nBytes < nTotalBytes) { n = (int)io->read_proc(plPixel, bytes, 1, handle); memcpy(plData+nBytes, plPixel, bytes ); nBytes += n * bytes; } SAFE_DELETE_ARRAY(plPixel); } break; case PSD_GRAYSCALE: // Grayscale case PSD_DUOTONE: // Duotone case PSD_RGB: // RGB { plData = new BYTE [nTotalBytes]; plPixel = new BYTE [bytes]; int nPixelCounter = 0; int nChannels = _headerInfo._Channels; for(int c = 0; c < nChannels; c++) { nPixelCounter = c * bytes; for(int nPos = 0; nPos < nPixels; ++nPos) { n = (int)io->read_proc(plPixel, bytes, 1, handle); if(n == 0) { break; } if(2 == bytes) { // swap for uint16 SwapShort((WORD*)&plPixel[0]); } else if(4 == bytes) { // swap for float SwapLong((DWORD*)&plPixel[0]); } memcpy( plData + nPixelCounter, plPixel, bytes ); nBytes += n * bytes; nPixelCounter += nChannels*bytes; } } SAFE_DELETE_ARRAY(plPixel); } break; case PSD_CMYK: // CMYK case PSD_MULTICHANNEL: // Multichannel { plPixel = new BYTE[bytes]; plData = new BYTE[nTotalBytes]; int nPixelCounter = 0; for (int c=0; c<_headerInfo._Channels; c++) { nPixelCounter = c*bytes; for ( int nPos = 0; nPos < nPixels; ++nPos ) { n = (int)io->read_proc(plPixel, bytes, 1, handle); if(n == 0) { break; } memcpy(plData + nPixelCounter, plPixel, bytes ); nBytes += n * bytes; nPixelCounter += _headerInfo._Channels*bytes; } } SAFE_DELETE_ARRAY(plPixel); } break; case PSD_LAB: // Lab { plPixel = new BYTE[bytes]; plData = new BYTE[nTotalBytes]; int nPixelCounter = 0; for(int c = 0; c < 3; c++) { nPixelCounter = c*bytes; for ( int nPos = 0; nPos < nPixels; ++nPos ) { n = (int)io->read_proc(plPixel, bytes, 1, handle); if(n == 0) { break; } memcpy(plData + nPixelCounter, plPixel, bytes); nBytes += n * bytes; nPixelCounter += 3*bytes; } } SAFE_DELETE_ARRAY(plPixel); } break; } assert( nBytes == nTotalBytes ); if (nBytes == nTotalBytes) { if (plData) { switch (_headerInfo._BitsPerPixel) { case 1: case 8: case 16: case 32: Bitmap = ProcessBuffer(plData); break; default: // Unsupported break; } } } SAFE_DELETE_ARRAY(plData); } break; case PSD_COMPRESSION_RLE: // RLE compression { int nWidth = _headerInfo._Width; int nHeight = _headerInfo._Height; int bytes = _headerInfo._BitsPerPixel / 8; int nPixels = nWidth * nHeight; int nTotalBytes = nPixels * bytes * _headerInfo._Channels; if(_headerInfo._BitsPerPixel == 1) { // special case for PSD_BITMAP mode bytes = 1; nWidth = (nWidth + 7) / 8; nWidth = ( nWidth > 0 ) ? nWidth : 1; nPixels = nWidth * nHeight; nTotalBytes = nWidth * nHeight; } BYTE * plData = new BYTE[nTotalBytes]; BYTE * p = plData; int nValue = 0; BYTE ByteValue[1]; int Count = 0; // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data, // which we're going to just skip. io->seek_proc(handle, nHeight * _headerInfo._Channels * 2, SEEK_CUR); for (int channel = 0; channel < _headerInfo._Channels; channel++) { // Read the RLE data. Count = 0; while (Count < nPixels) { io->read_proc(&ByteValue, sizeof(ByteValue), 1, handle); int len = psdGetValue( ByteValue, sizeof(ByteValue) ); if ( 128 > len ) { len++; Count += len; while (len) { io->read_proc(&ByteValue, sizeof(ByteValue), 1, handle); nValue = psdGetValue( ByteValue, sizeof(ByteValue) ); *p = (BYTE)nValue; p += sizeof(ByteValue); 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; io->read_proc(&ByteValue, sizeof(ByteValue), 1, handle); nValue = psdGetValue( ByteValue, sizeof(ByteValue) ); Count += len; while (len) { *p = (BYTE)nValue; p += sizeof(ByteValue); len--; } } else if ( 128 == len ) { // Do nothing } } } BYTE * prSource = plData; BYTE * plDest = new BYTE[nTotalBytes]; memset(plDest, 254, nTotalBytes); int nPixelCounter = 0; for(int c=0; c<_headerInfo._Channels; c++) { nPixelCounter = c*bytes; for (int nPos = 0; nPos<nPixels; ++nPos) { memcpy( plDest + nPixelCounter, prSource, bytes ); prSource++; nPixelCounter += _headerInfo._Channels*bytes; } } SAFE_DELETE_ARRAY(plData); if (plDest) { switch (_headerInfo._BitsPerPixel) { case 1: case 8: case 16: Bitmap = ProcessBuffer(plDest); break; default: // Unsupported format break; } } SAFE_DELETE_ARRAY(plDest); } break; case 2: // ZIP without prediction, no specification break; case 3: // ZIP with prediction, no specification break; default: // Unknown format break; } } return Bitmap; }