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

plppmdec.cpp

Go to the documentation of this file.
00001 /*
00002 /--------------------------------------------------------------------
00003 |
00004 |      $Id: plppmdec.cpp,v 1.1 2004/05/21 21:02:53 maxx Exp $
00005 |
00006 |      Copyright (c) 2001 Ulrich von Zadow
00007 |
00008 |      Portable Pixmap Decoder Class
00009 |
00010 |      Decodes PPM files, either P3 (ASCII data) or P6 (raw data).
00011 |                  Always decodes to 32 bpp, no alpha channel.
00012 |
00013 |      Originally by Todd Harris - Mar 2001
00014 |      adadapted from pgm.h originally by
00015 |                        Jose Miguel Buenaposada Biencinto. Mar 2000.
00016 |
00017 \--------------------------------------------------------------------
00018 */
00019 
00020 #include "plstdpch.h"
00021 #include "plppmdec.h"
00022 #include "plexcept.h"
00023 
00024 PLPPMDecoder::PLPPMDecoder
00025 ()
00026 // Creates a decoder
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         // Image doesn't have alpha channel
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,       // Pointer to PPM header structure
00055       PLDataSource * pDataSrc
00056     )
00057 {
00058         int current = 0;
00059         bool HeaderComplete = false;
00060         
00061         // Read type
00062         m_LastByte = ReadByte (pDataSrc);
00063         if (m_LastByte!=0x50) // ASCII P
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) // ASCII 3
00069                 pPpmHead->ImageType = PPM_P3;
00070         else if (m_LastByte==0x36) // ASCII 6
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         // Search for the with, height and Max sample value
00079         while (current<3)
00080         {
00081                 if (m_LastByte==0x23) // # Starts a comment
00082                         skipComment(pDataSrc);
00083                 else if ((m_LastByte>=0x30)&&(m_LastByte<=0x39)) // A digit
00084                 switch (current)
00085                   {
00086                     case 0: // looking for the width
00087                             {
00088                                     pPpmHead->ImageWidth = readASCIIDecimal(pDataSrc);
00089                                     current++;
00090                             }
00091                             break;
00092                     case 1: // looking for the height
00093                             {
00094                                     pPpmHead->ImageHeight = readASCIIDecimal(pDataSrc);
00095                                     current++;
00096                             }
00097                             break;
00098                     case 2: // looking for the sample value (max = 255)
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]; // Line should not be larger than 70 bytes
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)|| // Carriege Return
00130                           (byte==0x0A))  // Line Feed
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)) // Is ASCII digit
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)&& // Carriege Return
00161                (m_LastByte!=0x0A))  // New Line
00162         {
00163                 m_LastByte = ReadByte(pDataSrc);
00164         }
00165 }
00166 
00167 void PLPPMDecoder::skipPpmASCIISeparators(PLDataSource * pDataSrc)
00168 {
00169         while ((m_LastByte==0x20)|| // Space
00170                 (m_LastByte==0x0D)|| // Carriege Return
00171                 (m_LastByte==0x0A))  // New Line
00172         {
00173                 m_LastByte = ReadByte(pDataSrc);
00174         }
00175 }
00176 
00177 void PLPPMDecoder::readImage
00178     ( PPMHEADER * pPpmHead,       // Pointer to PPM header structure
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,       // Pointer to PPM header structure
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) // P6
00218                         expandByteLine (pDest, pPpmHead->MaxSampleValue, Width, pDataSrc);
00219                 else // P3
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 |      $Log: plppmdec.cpp,v $
00306 |      Revision 1.1  2004/05/21 21:02:53  maxx
00307 |      Initial Version of vuVolume, moderatly changed to make it compile on my windows and linux machine.
00308 |
00309 |      Revision 1.1  2002/11/13 01:58:22  mspindle
00310 |      *** empty log message ***
00311 |
00312 |      Revision 1.3  2001/10/21 17:12:40  uzadow
00313 |      Added PSD decoder beta, removed BPPWanted from all decoders, added PLFilterPixel.
00314 |
00315 |      Revision 1.2  2001/10/16 18:00:19  uzadow
00316 |      Linux compatibility
00317 |
00318 |      Revision 1.1  2001/10/16 17:51:32  uzadow
00319 |      Added ppm support (Todd Harris)
00320 |
00321 |
00322 \--------------------------------------------------------------------
00323 */

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