00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "plstdpch.h"
00012 #include "plpsddec.h"
00013 #include "plexcept.h"
00014 #include "plpixel32.h"
00015 #include "plpixel8.h"
00016 #include "plfilesrc.h"
00017
00018 #include <stdio.h>
00019
00020 using namespace std;
00021
00022 enum PLPSDMode
00023 {
00024 Bitmap,
00025 Greyscale,
00026 Indexed,
00027 RGB,
00028 CYMK,
00029 Multichannel,
00030 Duotone,
00031 Lab
00032 };
00033
00034 struct PLPSDResolutionInfo
00035 {
00036 int hRes;
00037 PLWORD hResUnit;
00038 PLWORD widthUnit;
00039 int vRes;
00040 PLWORD vResUnit;
00041 PLWORD heightUnit;
00042 };
00043
00044 struct PLPSDChannelInfo
00045 {
00046 PLWORD ChannelID;
00047 int ChannelDataLen;
00048 };
00049
00050 struct PLPSDLayerInfo
00051 {
00052 int Top;
00053 int Left;
00054 int Bottom;
00055 int Right;
00056 PLWORD NumChannels;
00057 vector<PLPSDChannelInfo> ChannelInfo;
00058 char BlendModeSig[4];
00059 char BlendModeKey[4];
00060 PLBYTE Opacity;
00061 PLBYTE Clipping;
00062 PLBYTE Flags;
00063 int ExtraDataSize;
00064 };
00065
00066 PLPSDDecoder::PLPSDDecoder
00067 ()
00068 : PLPicDecoder()
00069
00070 {
00071 }
00072
00073
00074 PLPSDDecoder::~PLPSDDecoder
00075 ()
00076 {
00077 }
00078
00079 int PLPSDDecoder::GetNumLayers
00080 ()
00081 {
00082 try
00083 {
00084 readHeader (m_pDataSrc, &m_PSDHeader);
00085 readColorModeData (m_pDataSrc);
00086
00087 readImageResData (m_pDataSrc, m_Resolution);
00088 readLayerHeader (m_pDataSrc);
00089 }
00090 catch (PLTextException)
00091 {
00092 Close();
00093 throw;
00094 }
00095 return m_NumLayers;
00096 }
00097
00098 void PLPSDDecoder::GetNextLayer
00099 ( PLBmp& Bmp
00100 )
00101 {
00102 PLASSERT (m_pDataSrc);
00103 try
00104 {
00105 readLayer (m_pDataSrc, Bmp, m_PSDHeader.Mode);
00106 }
00107 catch (PLTextException)
00108 {
00109 Close();
00110 throw;
00111 }
00112 }
00113
00114 PLPoint PLPSDDecoder::GetLayerOffset
00115 ()
00116 {
00117 PLPSDLayerInfo * pLayerInfo = m_pLayerInfo[m_LayersRead-1];
00118 return PLPoint (pLayerInfo->Left, pLayerInfo->Top);
00119 }
00120
00121 void PLPSDDecoder::GetImage
00122 ( PLBmp& Bmp
00123 )
00124 {
00125
00126 PLASSERT (m_pDataSrc);
00127
00128 try
00129 {
00130 skipLayerData (m_pDataSrc);
00131 createBmp (&Bmp, m_PSDHeader.Mode, m_PSDHeader.Rows, m_PSDHeader.Columns,
00132 m_PSDHeader.Channels, m_Resolution);
00133 readImageData (m_pDataSrc, &Bmp, m_PSDHeader.Mode,
00134 m_PSDHeader.Rows, m_PSDHeader.Columns,
00135 m_PSDHeader.Channels);
00136 }
00137 catch (PLTextException)
00138 {
00139 cleanup ();
00140 Close();
00141 throw;
00142 }
00143 cleanup ();
00144 }
00145
00146 void PLPSDDecoder::DoDecode
00147 ( PLBmp * pBmp,
00148 PLDataSource * pDataSrc
00149 )
00150 {
00151 readHeader (pDataSrc, &m_PSDHeader);
00152 readColorModeData (pDataSrc);
00153
00154 readImageResData (pDataSrc, m_Resolution);
00155 readLayerHeader (pDataSrc);
00156 skipLayerData (pDataSrc);
00157 createBmp (pBmp, m_PSDHeader.Mode, m_PSDHeader.Rows, m_PSDHeader.Columns,
00158 m_PSDHeader.Channels, m_Resolution);
00159 readImageData (pDataSrc, pBmp, m_PSDHeader.Mode,
00160 m_PSDHeader.Rows, m_PSDHeader.Columns,
00161 m_PSDHeader.Channels);
00162 cleanup ();
00163 }
00164
00165 void PLPSDDecoder::readHeader
00166 ( PLDataSource * pDataSrc,
00167 PLPSDHeader * pPSDHeader
00168 )
00169 {
00170 memcpy (pPSDHeader->Signature, pDataSrc->Read4Bytes (), 4);
00171 pPSDHeader->Version = ReadMWord (pDataSrc);
00172 memcpy (pPSDHeader->Reserved, pDataSrc->ReadNBytes (6), 6);
00173 pPSDHeader->Channels = ReadMWord (pDataSrc);
00174 pPSDHeader->Rows = ReadMLong (pDataSrc);
00175 pPSDHeader->Columns = ReadMLong (pDataSrc);
00176 pPSDHeader->BPP = ReadMWord (pDataSrc);
00177 pPSDHeader->Mode = ReadMWord (pDataSrc);
00178
00179 if (strncmp (pPSDHeader->Signature, "8BPS", 4))
00180 {
00181 raiseError (PL_ERRFORMAT_UNKNOWN,
00182 "PSD decoder: This isn't a photoshop file.");
00183 }
00184 }
00185
00186 void PLPSDDecoder::readColorModeData
00187 ( PLDataSource * pDataSrc
00188 )
00189 {
00190 int PalLen = ReadMLong (pDataSrc);
00191 if (PalLen != 0)
00192 {
00193 PLASSERT (PalLen == 768);
00194 PLBYTE * pSrcPal = pDataSrc->ReadNBytes (768);
00195 for (int i=0; i<256; i++)
00196 {
00197 m_pPal[i].Set (pSrcPal[0], pSrcPal[256], pSrcPal[512], 0xff);
00198 pSrcPal ++;
00199 }
00200 }
00201 }
00202
00203 void PLPSDDecoder::createBmp
00204 ( PLBmp *pBmp,
00205 int Mode,
00206 int Height,
00207 int Width,
00208 int Channels,
00209 const PLPoint& Resolution
00210 )
00211 {
00212 int BPP=0;
00213 bool bAlpha=false;
00214 switch (PLPSDMode(Mode))
00215 {
00216 case Greyscale:
00217 {
00218 BPP = 8;
00219 bAlpha = false;
00220 for (int i=0; i<256; i++)
00221 m_pPal[i].Set (i, i, i, 0xFF);
00222 }
00223 break;
00224 case Indexed:
00225 BPP = 8;
00226 bAlpha = false;
00227 break;
00228 case RGB:
00229 BPP = 32;
00230 bAlpha = (Channels > 3);
00231 break;
00232 default:
00233 raiseError (PL_ERRFORMAT_NOT_SUPPORTED,
00234 "This PSD color mode is not supported.");
00235 }
00236 pBmp->Create (Width, Height, BPP, bAlpha, Resolution);
00237 if (BPP == 8)
00238 pBmp->SetPalette(m_pPal);
00239 }
00240
00241 void PLPSDDecoder::readImageResData
00242 ( PLDataSource * pDataSrc,
00243 PLPoint& Resolution
00244 )
00245 {
00246 int ResLen = ReadMLong (pDataSrc);
00247 int BytesRead = 0;
00248 while (BytesRead < ResLen)
00249 {
00250 char ResSignature[4];
00251 memcpy (ResSignature, pDataSrc->Read4Bytes (), 4);
00252 if (strncmp (ResSignature, "8BIM", 4))
00253 raiseError (PL_ERRFORMAT_UNKNOWN,
00254 "PSD decoder: Wrong signature in resource data block.");
00255 PLWORD ResID = ReadMWord (pDataSrc);
00256 PLBYTE NameLen = ReadByte (pDataSrc);
00257 char * pszName = new char[NameLen+1];
00258 memcpy (pszName, pDataSrc->ReadNBytes(NameLen), NameLen);
00259 pszName[NameLen] = 0;
00260 Trace (2, "Reading resource:");
00261 Trace (2, pszName);
00262 Trace (2, "\n");
00263 delete[] pszName;
00264 if (!(NameLen&1))
00265 {
00266 ReadByte(pDataSrc);
00267 BytesRead++;
00268 }
00269 int Size = ReadMLong (pDataSrc);
00270 BytesRead += 4+2+1+NameLen+4;
00271 switch (ResID)
00272 {
00273 case 1005:
00274 {
00275 PLPSDResolutionInfo ResInfo;
00276 ResInfo.hRes = ReadMLong (pDataSrc);
00277 ResInfo.hResUnit = ReadMWord (pDataSrc);
00278 ResInfo.widthUnit = ReadMWord (pDataSrc);
00279 ResInfo.vRes = ReadMLong (pDataSrc);
00280 ResInfo.vResUnit = ReadMWord (pDataSrc);
00281 ResInfo.heightUnit = ReadMWord (pDataSrc);
00282 Resolution = PLPoint (ResInfo.hRes/65536, ResInfo.vRes/65536);
00283 }
00284 break;
00285 default:
00286 pDataSrc->ReadNBytes (Size);
00287 }
00288 if (Size&1)
00289 {
00290 ReadByte(pDataSrc);
00291 BytesRead++;
00292 }
00293 BytesRead += Size;
00294 }
00295 }
00296
00297 void PLPSDDecoder::readLayerHeader
00298 ( PLDataSource * pDataSrc
00299 )
00300 {
00301 m_MiscDataSize = ReadMLong (pDataSrc);
00302 if(m_MiscDataSize > 0)
00303 {
00304 m_pMiscDataStart = pDataSrc->GetBufferPtr(0);
00305 int LayerDataSize = ReadMLong (pDataSrc);
00306 if (LayerDataSize > 0)
00307 {
00308 m_NumLayers = ReadMWord (pDataSrc);
00309 if (m_NumLayers > 32767)
00310 m_NumLayers -= 65536;
00311 if (m_NumLayers<0)
00312 m_NumLayers = -m_NumLayers;
00313 m_LayersRead = 0;
00314 char sz[256];
00315 sprintf (sz, "Number of layers: %i\n", m_NumLayers);
00316 Trace (2, sz);
00317
00318 for (int i=0; i<m_NumLayers; i++)
00319 {
00320 PLPSDLayerInfo* pLayerInfo = new PLPSDLayerInfo;
00321 m_pLayerInfo.push_back (pLayerInfo);
00322 pLayerInfo->Top = ReadMLong (pDataSrc);
00323 pLayerInfo->Left = ReadMLong (pDataSrc);
00324 pLayerInfo->Bottom = ReadMLong (pDataSrc);
00325 pLayerInfo->Right = ReadMLong (pDataSrc);
00326 pLayerInfo->NumChannels = ReadMWord (pDataSrc);
00327 for (int j=0; j<pLayerInfo->NumChannels; j++)
00328 {
00329 PLPSDChannelInfo ChannelInfo;
00330 ChannelInfo.ChannelID = ReadMWord (pDataSrc);
00331 ChannelInfo.ChannelDataLen = ReadMLong (pDataSrc);
00332 pLayerInfo->ChannelInfo.push_back(ChannelInfo);
00333 }
00334 memcpy (pLayerInfo->BlendModeSig, pDataSrc->Read4Bytes (), 4);
00335 memcpy (pLayerInfo->BlendModeKey, pDataSrc->Read4Bytes (), 4);
00336 pLayerInfo->Opacity = ReadByte (pDataSrc);
00337 pLayerInfo->Clipping = ReadByte (pDataSrc);
00338 pLayerInfo->Flags = ReadByte (pDataSrc);
00339 ReadByte (pDataSrc);
00340 pLayerInfo->ExtraDataSize = ReadMLong (pDataSrc);
00341 pDataSrc->Skip (pLayerInfo->ExtraDataSize);
00342 }
00343 }
00344 }
00345 }
00346
00347 void PLPSDDecoder::skipLayerData
00348 ( PLDataSource * pDataSrc
00349 )
00350 {
00351 if (m_MiscDataSize > 0)
00352 {
00353 int BytesLeft = m_MiscDataSize + (m_pMiscDataStart - pDataSrc->GetBufferPtr(0));
00354 pDataSrc->Skip (BytesLeft);
00355 }
00356
00357 }
00358
00359 void PLPSDDecoder::skipMaskData
00360 ( PLDataSource * pDataSrc
00361 )
00362 {
00363 int MaskDataLen = ReadMLong (pDataSrc);
00364 pDataSrc->ReadNBytes (MaskDataLen);
00365 }
00366
00367 void PLPSDDecoder::readLayer
00368 ( PLDataSource * pDataSrc,
00369 PLBmp& Bmp,
00370 int Mode
00371 )
00372 {
00373 m_LayersRead++;
00374 PLASSERT (m_LayersRead <= m_NumLayers);
00375 int CurLayer = m_LayersRead-1;
00376 PLPSDLayerInfo * pLayerInfo = m_pLayerInfo[CurLayer];
00377
00378 char sz[256];
00379 sprintf (sz, "Reading Layer %i\n", CurLayer);
00380 Trace (2, sz);
00381
00382 int Width = pLayerInfo->Right-pLayerInfo->Left;
00383 int Height = pLayerInfo->Bottom-pLayerInfo->Top;
00384 createBmp (&Bmp, Mode, Height, Width, pLayerInfo->NumChannels, m_Resolution);
00385 int * pRowLengths = new int [Height];
00386
00387 for (int l=0; l<pLayerInfo->NumChannels; l++)
00388 {
00389 char sz[256];
00390 sprintf (sz, "Reading Channel %i\n", l);
00391 Trace (2, sz);
00392
00393 PLWORD CompressionMethod = ReadMWord (pDataSrc);
00394 traceCompressionMethod (CompressionMethod);
00395 if (CompressionMethod == 1)
00396 {
00397 for (int y=0; y<Height; y++)
00398 pRowLengths[y] = ReadMWord (pDataSrc);
00399 readRLEChannel (pDataSrc, &Bmp, Mode, Height, Width, l, pRowLengths);
00400 }
00401 else
00402 raiseError (PL_ERRFORMAT_UNKNOWN,
00403 "PSD decoder: Compression type not supported.");
00404 }
00405
00406 delete[] pRowLengths;
00407 }
00408
00409 void PLPSDDecoder::readImageData
00410 ( PLDataSource * pDataSrc,
00411 PLBmp * pBmp,
00412 int Mode,
00413 int Height,
00414 int Width,
00415 int Channels
00416 )
00417 {
00418 PLWORD CompressionMethod = ReadMWord (pDataSrc);
00419 traceCompressionMethod (CompressionMethod);
00420 if (CompressionMethod == 1)
00421 readRLEImage (pDataSrc, pBmp, Mode, Height,
00422 Width, Channels);
00423 else
00424 raiseError (PL_ERRFORMAT_UNKNOWN,
00425 "PSD decoder: Compression type not supported.");
00426 }
00427
00428 void PLPSDDecoder::traceCompressionMethod
00429 ( PLWORD CompressionMethod
00430 )
00431 {
00432 switch (CompressionMethod)
00433 {
00434 case 0:
00435 Trace (2, "No compression\n");
00436 break;
00437 case 1:
00438 Trace (2, "RLE compression\n");
00439 break;
00440 case 2:
00441 Trace (2, "ZIP compression, no prediction\n");
00442 break;
00443 case 3:
00444 Trace (2, "ZIP compression, prediction\n");
00445 break;
00446 default:
00447 raiseError (PL_ERRFORMAT_UNKNOWN,
00448 "PSD decoder: Compression unknown.");
00449 }
00450 }
00451
00452 void PLPSDDecoder::readRLEImage
00453 ( PLDataSource * pDataSrc,
00454 PLBmp * pBmp,
00455 int Mode,
00456 int Height,
00457 int Width,
00458 int Channels
00459 )
00460 {
00461
00462 int * pRowLengths = new int [Height*Channels];
00463 int l;
00464 for (l=0; l<Channels; l++)
00465 for (int y=0; y<Height; y++)
00466 pRowLengths[l*Height+y] = ReadMWord (pDataSrc);
00467
00468 for (l=0; l<Channels; l++)
00469 {
00470 readRLEChannel (pDataSrc, pBmp, Mode, Height, Width, l, pRowLengths +l*Height);
00471 }
00472
00473 delete[] pRowLengths;
00474 }
00475
00476
00477 void PLPSDDecoder::readRLEChannel
00478 ( PLDataSource * pDataSrc,
00479 PLBmp * pBmp,
00480 int Mode,
00481 int Height,
00482 int Width,
00483 int ChannelNum,
00484 int * pRowLengths
00485 )
00486 {
00487 PLBYTE * pLineBuf = new PLBYTE [Width];
00488 for (int y=0; y<Height; y++)
00489 {
00490 PLBYTE * pRawLine = unpackPictRow (pLineBuf, pDataSrc, Width,
00491 Width, pRowLengths[y]);
00492 int x;
00493 switch (Mode)
00494 {
00495 case Indexed:
00496 case Greyscale:
00497 if (ChannelNum == 0)
00498 {
00499 PLPixel8 * pBmpLine = (PLPixel8*)pBmp->GetLineArray()[y];
00500 for (x=0; x<Width; x++)
00501 pBmpLine[x].Set (pRawLine[x]);
00502 }
00503 break;
00504 case RGB:
00505 {
00506 PLPixel32 * pBmpLine = pBmp->GetLineArray32()[y];
00507 switch (ChannelNum)
00508 {
00509 case 0:
00510 for (x=0; x<Width; x++)
00511 pBmpLine[x].SetR (pRawLine[x]);
00512 break;
00513 case 1:
00514 for (x=0; x<Width; x++)
00515 pBmpLine[x].SetG (pRawLine[x]);
00516 break;
00517 case 2:
00518 for (x=0; x<Width; x++)
00519 pBmpLine[x].SetB (pRawLine[x]);
00520 break;
00521 case 3:
00522 for (x=0; x<Width; x++)
00523 pBmpLine[x].SetA (pRawLine[x]);
00524 break;
00525 }
00526 }
00527 break;
00528 default:
00529
00530 PLASSERT (false);
00531 }
00532 }
00533 delete[] pLineBuf;
00534 }
00535
00536 void PLPSDDecoder::cleanup
00537 ()
00538 {
00539 for (int i=0; (unsigned int)i<m_pLayerInfo.size(); i++)
00540 delete m_pLayerInfo[i];
00541 m_pLayerInfo.clear();
00542 }
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565