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