Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

plpsddec.cpp

Go to the documentation of this file.
00001 /*
00002 /--------------------------------------------------------------------
00003 |
00004 |      $Id: plpsddec.cpp,v 1.1 2004/05/21 21:02:53 maxx Exp $
00005 |
00006 |      Copyright (c) 1996-1998 Ulrich von Zadow
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;       // Actually fixed-point
00037   PLWORD hResUnit;
00038   PLWORD widthUnit;
00039   int    vRes;       // Actually fixed-point
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     // Creates a decoder
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   // Was OpenImage called?
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   // Read row lengths into temp array;
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         // We shouldn't have arrived here.
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 |      $Log: plpsddec.cpp,v $
00548 |      Revision 1.1  2004/05/21 21:02:53  maxx
00549 |      Initial Version of vuVolume, moderatly changed to make it compile on my windows and linux machine.
00550 |
00551 |      Revision 1.2  2003/01/07 16:14:58  sbergner
00552 |      *** empty log message ***
00553 |
00554 |      Revision 1.1  2002/11/13 01:58:22  mspindle
00555 |      *** empty log message ***
00556 |
00557 |      Revision 1.2  2001/10/21 17:54:40  uzadow
00558 |      Linux compatibility
00559 |
00560 |      Revision 1.1  2001/10/21 17:12:40  uzadow
00561 |      Added PSD decoder beta, removed BPPWanted from all decoders, added PLFilterPixel.
00562 |
00563 |
00564 \--------------------------------------------------------------------
00565 */

Generated on Wed Dec 15 21:20:30 2004 for vuVolume by  doxygen 1.3.9.1