/* /-------------------------------------------------------------------- | | $Id: plpgmdec.cpp,v 1.10 2004/09/11 12:41:35 uzadow Exp $ | portable graymap Decoder Class | | Original author: Jose Miguel Buenaposada Biencinto. | | Copyright (c) 1996-2002 Ulrich von Zadow | \-------------------------------------------------------------------- */ #include "plpgmdec.h" #include "plexcept.h" PLPGMDecoder::PLPGMDecoder () : PLPicDecoder(), m_LastByte(0), m_UseLastByte(false) // Creates a decoder { } PLPGMDecoder::~PLPGMDecoder () { } void PLPGMDecoder::Open (PLDataSource * pDataSrc) { Trace (2, "Decoding PGM.\n"); readPgmHeader(&m_PGMHeader, pDataSrc); SetBmpInfo (PLPoint(m_PGMHeader.ImageWidth, m_PGMHeader.ImageHeight), PLPoint (0,0), PLPixelFormat::L8); } void PLPGMDecoder::GetImage (PLBmpBase & Bmp) { readImage (&Bmp, m_pDataSrc); } void PLPGMDecoder::readPgmHeader ( PGMHEADER * pPgmHead, // Pointer to PGM header structure PLDataSource * pDataSrc ) { int current = 0; bool HeaderComplete = false; // Read type m_LastByte = ReadByte (pDataSrc); if (m_LastByte!=0x50) // ASCII P raiseError (PL_ERRFORMAT_UNKNOWN, "PGM decoder: Is not the correct identifier P5 or P2."); m_LastByte = ReadByte (pDataSrc); if (m_LastByte==0x32) // ASCII 2 pPgmHead->ImageType = PGM_P2; else if (m_LastByte==0x35) // ASCII 5 pPgmHead->ImageType = PGM_P5; else raiseError (PL_ERRFORMAT_UNKNOWN, "PGM decoder: Is not the correct identifier P5 or P2."); m_LastByte = ReadByte (pDataSrc); // Search for the with, height and Max gray value while (current<3) { if (m_LastByte==0x23) // # Starts a comment skipComment(pDataSrc); else if ((m_LastByte>=0x30)&&(m_LastByte<=0x39)) // A digit switch (current) { case 0: // looking for the width { pPgmHead->ImageWidth = readASCIIDecimal(pDataSrc); current++; } break; case 1: // looking for the height { pPgmHead->ImageHeight = readASCIIDecimal(pDataSrc); current++; } break; case 2: // looking for the max gray value { pPgmHead->MaxGrayValue = readASCIIDecimal(pDataSrc); if ((pPgmHead->MaxGrayValue>255)||(pPgmHead->MaxGrayValue<=0)) pPgmHead->MaxGrayValue=255; current++; } break; default: continue; } else skipPgmASCIISeparators(pDataSrc); } } PLBYTE *PLPGMDecoder::readASCIILine(PLDataSource *pDataSrc) { int i = 0; bool HaveLine = false; PLBYTE byte; PLBYTE* pLine = new PLBYTE[PGM_MAXLINESIZE]; // Line should not be larger than 70 bytes do { if (i==80) raiseError (PL_ERRFORMAT_UNKNOWN, "PGM decoder: File Line to long."); byte =ReadByte(pDataSrc); pLine[i]=byte; if ((byte==0x0D)|| // Carriege Return (byte==0x0A)) // Line Feed { HaveLine=true; pLine[i]=0x00; } i++; } while (!HaveLine); return pLine; } int PLPGMDecoder::readASCIIDecimal(PLDataSource * pDataSrc) { int Value = 0; int digit; while ((m_LastByte>=0x30)&&(m_LastByte<=0x39)) // Is ASCII digit { digit = m_LastByte - 0x30; Value = Value*10+digit; m_LastByte = ReadByte(pDataSrc); } return Value; } void PLPGMDecoder::skipComment(PLDataSource * pDataSrc) { while ((m_LastByte!=0x0D)&& // Carriege Return (m_LastByte!=0x0A)) // New Line { m_LastByte = ReadByte(pDataSrc); } } void PLPGMDecoder::skipPgmASCIISeparators(PLDataSource * pDataSrc) { while ((m_LastByte==0x20)|| // Space (m_LastByte==0x0D)|| // Carriege Return // (m_LastByte<=0x10)|| // Tab (m_LastByte==0x0A)) // New Line { m_LastByte = ReadByte(pDataSrc); } } void PLPGMDecoder::readImage ( PLBmpBase * pBmp, PLDataSource * pDataSrc ) { switch (m_PGMHeader.ImageType) { case PGM_P5: case PGM_P2: readData(pBmp, pDataSrc); break; default: raiseError (PL_ERRFORMAT_UNKNOWN, "Unknown PGM image type."); } } void PLPGMDecoder::readData ( PLBmpBase * pBmp, PLDataSource * pDataSrc ) { int Width = m_PGMHeader.ImageWidth; int Height = m_PGMHeader.ImageHeight; PLBYTE * pDest; PLBYTE ** pLineArray = pBmp->GetLineArray(); int y; if (m_PGMHeader.ImageType == PGM_P2) { skipPgmASCIISeparators(pDataSrc); m_UseLastByte = true; } for (y=0; y < Height; y++) { pDest = pLineArray[y]; if (m_PGMHeader.ImageType==PGM_P5) // P5 expandByteLine (pDest, m_PGMHeader.MaxGrayValue, Width, pDataSrc); else // P2 expandASCIILine (pDest, m_PGMHeader.MaxGrayValue, Width, pDataSrc); } } void PLPGMDecoder::expandASCIILine ( PLBYTE * pDest, int MaxGrayValue, int Width, PLDataSource * pDataSrc ) { int x; for (x=0; xReadNBytes(Width); if (pLine==NULL) return; for (x=0; x