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

pltgadec.cpp

Go to the documentation of this file.
00001 /*
00002 /--------------------------------------------------------------------
00003 |
00004 |      $Id: pltgadec.cpp,v 1.1 2004/05/21 21:02:53 maxx Exp $
00005 |      Targa Decoder Class
00006 |
00007 |      Targa file decoder. Decodes 8, 15, 16, 24 and 32 bpp
00008 |      targa files (compressed and uncompressed) and returns a 32
00009 |      bpp bitmap. Preserves the alpha channel.
00010 |
00011 |      Copyright (c) 1996-1998 Ulrich von Zadow
00012 |
00013 \--------------------------------------------------------------------
00014 */
00015 
00016 #include "plstdpch.h"
00017 #include "pltgadec.h"
00018 #include "plexcept.h"
00019 
00020 
00021 PLTGADecoder::PLTGADecoder
00022     ()
00023     : PLPicDecoder()
00024     // Creates a decoder
00025 {
00026 }
00027 
00028 
00029 PLTGADecoder::~PLTGADecoder
00030     ()
00031 {
00032 }
00033 
00034 
00035 void PLTGADecoder::DoDecode
00036     ( PLBmp * pBmp,
00037       PLDataSource * pDataSrc
00038     )
00039 {
00040   TGAHEADER TgaHead;
00041 
00042   Trace (2, "Decoding TGA.\n");
00043 
00044   readTgaHeader (&TgaHead, pDataSrc);
00045 
00046   int DestBPP = 8;
00047   bool bAlpha = false;
00048 
00049   switch (TgaHead.PixelDepth)
00050   {
00051     case 16:
00052     case 32:
00053       bAlpha = true;
00054       DestBPP = 32;
00055       // Image has alpha channel
00056       break;
00057     case 15:
00058     case 24:
00059       // Image doesn't have alpha channel
00060       DestBPP = 32;
00061   }
00062   pBmp->Create (TgaHead.ImageWidth, TgaHead.ImageHeight,
00063                 DestBPP, bAlpha);
00064 
00065   // Read the color map data (Version 1.0 and 2.0).
00066   if (TgaHead.CmapType != 0)
00067     readPalette (TgaHead.CmapIndex,
00068                  TgaHead.CmapLength,
00069                  TgaHead.CmapEntrySize,
00070                  pBmp,
00071                  pDataSrc);
00072 
00073   readImage (&TgaHead, pBmp, pDataSrc);
00074 }
00075 
00076 
00077 void PLTGADecoder::readTgaHeader
00078     ( TGAHEADER * pTgaHead,       // Pointer to TGA header structure
00079       PLDataSource * pDataSrc
00080     )
00081 {
00082   // Read the TGA header (Version 1.0 and 2.0).
00083   pTgaHead->IdLength      = ReadByte (pDataSrc);
00084   pTgaHead->CmapType      = ReadByte (pDataSrc);
00085   pTgaHead->ImageType     = ReadByte (pDataSrc);
00086   pTgaHead->CmapIndex     = ReadIWord (pDataSrc);
00087   pTgaHead->CmapLength    = ReadIWord (pDataSrc);
00088   pTgaHead->CmapEntrySize = ReadByte (pDataSrc);
00089   pTgaHead->X_Origin      = ReadIWord (pDataSrc);
00090   pTgaHead->Y_Origin      = ReadIWord (pDataSrc);
00091   pTgaHead->ImageWidth    = ReadIWord (pDataSrc);
00092   pTgaHead->ImageHeight   = ReadIWord (pDataSrc);
00093   pTgaHead->PixelDepth    = ReadByte (pDataSrc);
00094   pTgaHead->ImagDesc      = ReadByte (pDataSrc);
00095 
00096   // Skip image ID
00097   pDataSrc->Skip (pTgaHead->IdLength);
00098 }
00099 
00100 
00101 void PLTGADecoder::readPalette
00102     ( int StartIndex,           // Index of first palette entry.
00103       int Length,               // Number of palette entries stored.
00104       int EntrySize,            // Size of palette entries in bits.
00105       PLBmp * pBmp,
00106       PLDataSource * pDataSrc
00107     )
00108     // Reads the TGA palette and creates a windows palette.
00109 {
00110   int   i;
00111 
00112   for (i=StartIndex; i<StartIndex+Length; i++)
00113   {
00114     PLPixel32 CurEntry = readPixel32 (EntrySize, pDataSrc);
00115     pBmp->SetPaletteEntry (i, CurEntry);
00116   }
00117 }
00118 
00119 
00120 void PLTGADecoder::readImage
00121     ( TGAHEADER * pTgaHead,       // Pointer to TGA header structure
00122       PLBmp * pBmp,
00123       PLDataSource * pDataSrc
00124     )
00125 {
00126   bool bCompressed=false;
00127 
00128   if (pTgaHead->ImageType == TGA_Mono ||
00129       pTgaHead->ImageType == TGA_RLEMono)
00130     pBmp->SetGrayPalette ();
00131 
00132   switch (pTgaHead->ImageType)
00133   {
00134     case TGA_Map:
00135     case TGA_RGB:
00136     case TGA_Mono:
00137       bCompressed = false;
00138       break;
00139     case TGA_RLEMap:
00140     case TGA_RLERGB:
00141     case TGA_RLEMono:
00142       bCompressed = true;
00143       break;
00144     default:
00145       raiseError (PL_ERRFORMAT_UNKNOWN, "Unknown TGA image type.");
00146   }
00147   readData (pTgaHead, bCompressed, pBmp, pDataSrc);
00148 }
00149 
00150 
00151 void PLTGADecoder::readData
00152     ( TGAHEADER * pTgaHead,       // Pointer to TGA header structure
00153       bool bCompressed,
00154       PLBmp * pBmp,
00155       PLDataSource * pDataSrc
00156     )
00157 {
00158   int Width = pTgaHead->ImageWidth;
00159   int Height = pTgaHead->ImageHeight;
00160   int bpp = pTgaHead->PixelDepth;
00161 
00162   // Bits 4 & 5 of the Image Descriptor byte control the ordering of
00163   // the pixels.
00164   bool bXReversed = ((pTgaHead->ImagDesc & 16) == 16);
00165   bool bYReversed = ((pTgaHead->ImagDesc & 32) == 32);
00166 
00167   PLBYTE * pDest;
00168   pBmp->Lock(false, true);
00169   try
00170   {
00171     PLBYTE ** pLineArray = pBmp->GetLineArray();
00172 
00173     int y;
00174 
00175     for (y=0; y < Height; y++)
00176     {
00177       if (bYReversed)
00178         pDest = pLineArray[y];
00179        else
00180         pDest = pLineArray[Height-y-1];
00181 
00182       if (!bCompressed)
00183         expandUncompressedLine (pDest, Width, bXReversed, bpp, pDataSrc);
00184        else
00185         expandCompressedLine (pDest, Width, bXReversed, bpp, pDataSrc);
00186     }
00187     pBmp->Unlock();
00188   }
00189   catch (...)
00190   {
00191     pBmp->Unlock();
00192     throw;
00193   }
00194 }
00195 
00196 
00197 void PLTGADecoder::expandUncompressedLine
00198     ( PLBYTE * pDest,
00199       int Width,
00200       bool bReversed,
00201       int bpp,
00202       PLDataSource * pDataSrc
00203     )
00204 {
00205   int x;
00206 
00207   for (x=0; x<Width; x++)
00208   {
00209     if (bpp > 8)
00210     {
00211       *((PLPixel32 *)pDest) = readPixel32 (bpp, pDataSrc);
00212       pDest += 4;
00213     }
00214     else
00215     {
00216       *pDest = readPixel8 (bpp, pDataSrc);
00217       pDest ++;
00218     }
00219   }
00220 }
00221 
00222 
00223 void PLTGADecoder::expandCompressedLine
00224     ( PLBYTE * pDest,
00225       int Width,
00226       bool bReversed,
00227       int bpp,
00228       PLDataSource * pDataSrc
00229     )
00230 {
00231   int  x;
00232   int  i;
00233   PLBYTE Count;
00234 
00235   for (x=0; x<Width; )
00236   {
00237     Count = ReadByte (pDataSrc);
00238     if (Count & 128)
00239     { // RLE-Encoded packet
00240       Count -= 127; // Calculate real repeat count.
00241       if (bpp > 8)
00242       {
00243         *((PLPixel32 *)pDest) = readPixel32 (bpp, pDataSrc);
00244         for (i=1; i<Count; i++)
00245           *((PLPixel32 *)(pDest+i*4)) = *(PLPixel32 *)pDest;
00246       }
00247       else
00248       {
00249         *pDest = readPixel8 (bpp, pDataSrc);
00250         for (i=1; i<Count; i++)
00251           *(pDest+i) = *pDest;
00252       }
00253     }
00254     else
00255     { // Raw packet
00256       Count += 1; // Calculate real repeat count.
00257       for (i=0; i<Count; i++)
00258       {
00259         if (bpp > 8)
00260           *((PLPixel32 *)(pDest+i*4)) = readPixel32 (bpp, pDataSrc);
00261         else
00262           *(pDest+i) = readPixel8 (bpp, pDataSrc);
00263       }
00264     }
00265     if (bpp > 8)
00266       pDest += Count*4;
00267     else
00268       pDest += Count;
00269     x += Count;
00270   }
00271 }
00272 
00273 
00274 PLPixel32 PLTGADecoder::readPixel32
00275     ( int bpp,
00276       PLDataSource * pDataSrc
00277     )
00278     // The decoder could be made much faster if the big switch (bpp)
00279     // statement was taken out of the inner loop. On the other hand,
00280     // doing that would cause a lot of code to be repeated half a
00281     // dozen times...
00282 {
00283   PLPixel32 Dest;
00284   PLWORD Src;
00285   PLBYTE * pCurEntry;
00286 
00287   switch (bpp)
00288   {
00289     case 15:
00290     case 16:
00291       Src = ReadIWord(pDataSrc);
00292       if (bpp == 16)
00293         Dest.Set (( Src >> 7 ) & 0x0F8,     // red
00294                   ( Src >> 2 ) & 0x0F8,     // green
00295                   ( Src & 0x1F ) * 8,       // blue
00296                   (PLBYTE)(Src & 32786 >> 8));
00297        else
00298         Dest.Set (( Src >> 7 ) & 0x0F8,     // red
00299                   ( Src >> 2 ) & 0x0F8,     // green
00300                   ( Src & 0x1F ) * 8,       // blue
00301                   0xFF);
00302       break;
00303     case 24:
00304       pCurEntry = pDataSrc->ReadNBytes (3);
00305       Dest.Set (*(pCurEntry+2), *(pCurEntry+1), *(pCurEntry), 0xFF);
00306       break;
00307     case 32:
00308       pCurEntry = pDataSrc->ReadNBytes (4);
00309       Dest.Set (*(pCurEntry+2), *(pCurEntry+1), *(pCurEntry), *(pCurEntry+3));
00310       break;
00311   }
00312   return Dest;
00313 }
00314 
00315 PLBYTE PLTGADecoder::readPixel8
00316     ( int bpp,
00317       PLDataSource * pDataSrc
00318     )
00319 {
00320   PLBYTE Dest;
00321 
00322   PLASSERT (bpp == 8);
00323 
00324   Dest = ReadByte(pDataSrc);
00325 
00326   return Dest;
00327 }
00328 
00329 /*
00330 /--------------------------------------------------------------------
00331 |
00332 |      $Log: pltgadec.cpp,v $
00333 |      Revision 1.1  2004/05/21 21:02:53  maxx
00334 |      Initial Version of vuVolume, moderatly changed to make it compile on my windows and linux machine.
00335 |
00336 |      Revision 1.2  2003/01/07 16:14:59  sbergner
00337 |      *** empty log message ***
00338 |
00339 |      Revision 1.1  2002/11/13 01:58:22  mspindle
00340 |      *** empty log message ***
00341 |
00342 |      Revision 1.3  2001/10/21 17:12:40  uzadow
00343 |      Added PSD decoder beta, removed BPPWanted from all decoders, added PLFilterPixel.
00344 |
00345 |      Revision 1.2  2001/10/06 22:03:26  uzadow
00346 |      Added PL prefix to basic data types.
00347 |
00348 |      Revision 1.1  2001/09/16 19:03:22  uzadow
00349 |      Added global name prefix PL, changed most filenames.
00350 |
00351 |      Revision 1.8  2001/02/04 14:31:52  uzadow
00352 |      Member initialization list cleanup (Erik Hoffmann).
00353 |
00354 |      Revision 1.7  2000/12/18 22:42:52  uzadow
00355 |      Replaced RGBAPIXEL with PLPixel32.
00356 |
00357 |      Revision 1.6  2000/10/24 23:02:28  uzadow
00358 |      Fixed exception handling.
00359 |
00360 |      Revision 1.5  2000/08/13 12:11:43  Administrator
00361 |      Added experimental DirectDraw-Support
00362 |
00363 |      Revision 1.4  2000/01/16 20:43:14  anonymous
00364 |      Removed MFC dependencies
00365 |
00366 |      Revision 1.3  1999/10/03 18:50:52  Ulrich von Zadow
00367 |      Added automatic logging of changes.
00368 |
00369 |
00370 --------------------------------------------------------------------
00371 */

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