00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "plstdpch.h"
00021 #include "plppmdec.h"
00022 #include "plexcept.h"
00023
00024 PLPPMDecoder::PLPPMDecoder
00025 ()
00026
00027 {
00028 }
00029
00030 PLPPMDecoder::~PLPPMDecoder
00031 ()
00032 {
00033 }
00034
00035 void PLPPMDecoder::DoDecode
00036 ( PLBmp * pBmp,
00037 PLDataSource * pDataSrc
00038 )
00039 {
00040 PPMHEADER PpmHead;
00041 Trace (2, "Decoding PPM.\n");
00042
00043 readPpmHeader(&PpmHead, pDataSrc);
00044
00045
00046 pBmp->Create (PpmHead.ImageWidth, PpmHead.ImageHeight,
00047 32, false);
00048
00049 readImage (&PpmHead, pBmp, pDataSrc);
00050 }
00051
00052
00053 void PLPPMDecoder::readPpmHeader
00054 ( PPMHEADER * pPpmHead,
00055 PLDataSource * pDataSrc
00056 )
00057 {
00058 int current = 0;
00059 bool HeaderComplete = false;
00060
00061
00062 m_LastByte = ReadByte (pDataSrc);
00063 if (m_LastByte!=0x50)
00064 raiseError (PL_ERRFORMAT_UNKNOWN,
00065 "PPM decoder: Is not the correct identifier P3 or P6.");
00066
00067 m_LastByte = ReadByte (pDataSrc);
00068 if (m_LastByte==0x33)
00069 pPpmHead->ImageType = PPM_P3;
00070 else if (m_LastByte==0x36)
00071 pPpmHead->ImageType = PPM_P6;
00072 else
00073 raiseError (PL_ERRFORMAT_UNKNOWN,
00074 "PPM decoder: Is not the correct identifier P3 or P6.");
00075
00076 m_LastByte = ReadByte (pDataSrc);
00077
00078
00079 while (current<3)
00080 {
00081 if (m_LastByte==0x23)
00082 skipComment(pDataSrc);
00083 else if ((m_LastByte>=0x30)&&(m_LastByte<=0x39))
00084 switch (current)
00085 {
00086 case 0:
00087 {
00088 pPpmHead->ImageWidth = readASCIIDecimal(pDataSrc);
00089 current++;
00090 }
00091 break;
00092 case 1:
00093 {
00094 pPpmHead->ImageHeight = readASCIIDecimal(pDataSrc);
00095 current++;
00096 }
00097 break;
00098 case 2:
00099 {
00100 pPpmHead->MaxSampleValue = readASCIIDecimal(pDataSrc);
00101 if ((pPpmHead->MaxSampleValue>255)||(pPpmHead->MaxSampleValue<=0))
00102 pPpmHead->MaxSampleValue=255;
00103 current++;
00104 }
00105 break;
00106 default:
00107 continue;
00108 }
00109 else
00110 skipPpmASCIISeparators(pDataSrc);
00111 }
00112 }
00113
00114 PLBYTE *PLPPMDecoder::readASCIILine(PLDataSource *pDataSrc)
00115 {
00116 int i = 0;
00117 bool HaveLine = false;
00118 PLBYTE byte;
00119 PLBYTE* pLine = new PLBYTE[PPM_MAXLINESIZE];
00120
00121 do
00122 {
00123 if (i==80)
00124 raiseError (PL_ERRFORMAT_UNKNOWN,
00125 "PPM decoder: File Line to long.");
00126
00127 byte = ReadByte(pDataSrc);
00128 pLine[i] = byte;
00129 if ((byte==0x0D)||
00130 (byte==0x0A))
00131 {
00132 HaveLine=true;
00133 pLine[i]=0x00;
00134 }
00135 i++;
00136 }
00137 while (!HaveLine);
00138
00139 return pLine;
00140 }
00141
00142
00143 int PLPPMDecoder::readASCIIDecimal(PLDataSource * pDataSrc)
00144 {
00145 int Value = 0;
00146 int digit;
00147
00148 while ((m_LastByte>=0x30)&&(m_LastByte<=0x39))
00149 {
00150 digit = m_LastByte - 0x30;
00151 Value = Value*10+digit;
00152 m_LastByte = ReadByte(pDataSrc);
00153 }
00154
00155 return Value;
00156 }
00157
00158 void PLPPMDecoder::skipComment(PLDataSource * pDataSrc)
00159 {
00160 while ((m_LastByte!=0x0D)&&
00161 (m_LastByte!=0x0A))
00162 {
00163 m_LastByte = ReadByte(pDataSrc);
00164 }
00165 }
00166
00167 void PLPPMDecoder::skipPpmASCIISeparators(PLDataSource * pDataSrc)
00168 {
00169 while ((m_LastByte==0x20)||
00170 (m_LastByte==0x0D)||
00171 (m_LastByte==0x0A))
00172 {
00173 m_LastByte = ReadByte(pDataSrc);
00174 }
00175 }
00176
00177 void PLPPMDecoder::readImage
00178 ( PPMHEADER * pPpmHead,
00179 PLBmp * pBmp,
00180 PLDataSource * pDataSrc
00181 )
00182 {
00183 switch (pPpmHead->ImageType)
00184 {
00185 case PPM_P6:
00186 case PPM_P3:
00187 readData (pPpmHead, pBmp, pDataSrc);
00188 break;
00189 default:
00190 raiseError (PL_ERRFORMAT_UNKNOWN, "Unknown PPM image type.");
00191 }
00192 }
00193
00194 void PLPPMDecoder::readData
00195 ( PPMHEADER * pPpmHead,
00196 PLBmp * pBmp,
00197 PLDataSource * pDataSrc
00198 )
00199 {
00200 int Width = pPpmHead->ImageWidth;
00201 int Height = pPpmHead->ImageHeight;
00202
00203 PLPixel32 * pDest;
00204 PLPixel32 ** pLineArray = pBmp->GetLineArray32();
00205
00206 int y;
00207
00208 if (pPpmHead->ImageType == PPM_P3)
00209 {
00210 skipPpmASCIISeparators(pDataSrc);
00211 m_UseLastByte = true;
00212 }
00213
00214 for (y=0; y < Height; y++)
00215 {
00216 pDest = pLineArray[y];
00217 if (pPpmHead->ImageType==PPM_P6)
00218 expandByteLine (pDest, pPpmHead->MaxSampleValue, Width, pDataSrc);
00219 else
00220 expandASCIILine (pDest, pPpmHead->MaxSampleValue, Width, pDataSrc);
00221 }
00222 }
00223
00224 void PLPPMDecoder::expandASCIILine
00225 ( PLPixel32 * pDest,
00226 int MaxSampleValue,
00227 int Width,
00228 PLDataSource * pDataSrc
00229 )
00230 {
00231 int x;
00232
00233 for (x=0; x<Width; x++)
00234 {
00235 *pDest = readASCIIPixel32 (MaxSampleValue, pDataSrc);
00236 pDest ++;
00237 }
00238 }
00239
00240 void PLPPMDecoder::expandByteLine
00241 ( PLPixel32 * pDest,
00242 int MaxSampleValue,
00243 int Width,
00244 PLDataSource * pDataSrc
00245 )
00246 {
00247 int x;
00248 PLBYTE *pLine;
00249 PLBYTE r,g,b;
00250 int bWidth = Width * 3;
00251
00252 pLine = pDataSrc->ReadNBytes(bWidth);
00253 if (pLine==NULL)
00254 return;
00255
00256 for (x=0; x<bWidth; x+=3)
00257 {
00258 if (MaxSampleValue != 255)
00259 {
00260 r = ((int)pLine[x] * 255) / MaxSampleValue;
00261 g = ((int)pLine[x+1] * 255) / MaxSampleValue;
00262 b = ((int)pLine[x+2] * 255) / MaxSampleValue;
00263 pDest->Set(r, g, b, 255);
00264 }
00265 else
00266 pDest->Set(pLine[x], pLine[x+1], pLine[x+2], 0);
00267 pDest ++;
00268 }
00269 }
00270
00271
00272 PLPixel32 PLPPMDecoder::readASCIIPixel32
00273 ( int MaxSampleValue,
00274 PLDataSource * pDataSrc
00275 )
00276 {
00277 PLPixel32 Dest;
00278 PLBYTE r, g, b;
00279
00280 skipPpmASCIISeparators(pDataSrc);
00281 r = readASCIIDecimal(pDataSrc);
00282
00283 skipPpmASCIISeparators(pDataSrc);
00284 g = readASCIIDecimal(pDataSrc);
00285
00286 skipPpmASCIISeparators(pDataSrc);
00287 b = readASCIIDecimal(pDataSrc);
00288
00289 if (MaxSampleValue != 255)
00290 {
00291 r = (r * 255) / MaxSampleValue;
00292 g = (g * 255) / MaxSampleValue;
00293 b = (b * 255) / MaxSampleValue;
00294 }
00295
00296 Dest.Set(r, g, b, 0);
00297
00298 return Dest;
00299 }
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323