00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
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
00056 break;
00057 case 15:
00058 case 24:
00059
00060 DestBPP = 32;
00061 }
00062 pBmp->Create (TgaHead.ImageWidth, TgaHead.ImageHeight,
00063 DestBPP, bAlpha);
00064
00065
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,
00079 PLDataSource * pDataSrc
00080 )
00081 {
00082
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
00097 pDataSrc->Skip (pTgaHead->IdLength);
00098 }
00099
00100
00101 void PLTGADecoder::readPalette
00102 ( int StartIndex,
00103 int Length,
00104 int EntrySize,
00105 PLBmp * pBmp,
00106 PLDataSource * pDataSrc
00107 )
00108
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,
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,
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
00163
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 {
00240 Count -= 127;
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 {
00256 Count += 1;
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
00279
00280
00281
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,
00294 ( Src >> 2 ) & 0x0F8,
00295 ( Src & 0x1F ) * 8,
00296 (PLBYTE)(Src & 32786 >> 8));
00297 else
00298 Dest.Set (( Src >> 7 ) & 0x0F8,
00299 ( Src >> 2 ) & 0x0F8,
00300 ( Src & 0x1F ) * 8,
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
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371