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

plpcxdec.cpp

Go to the documentation of this file.
00001 /*
00002 /--------------------------------------------------------------------
00003 |
00004 |      $Id: plpcxdec.cpp,v 1.1 2004/05/21 21:02:53 maxx Exp $
00005 |      PCX Decoder Class
00006 |
00007 |      Copyright (c) 1996-2002 Ulrich von Zadow
00008 |
00009 \--------------------------------------------------------------------
00010 */
00011 
00012 #include <iostream>
00013 
00014 #include "plstdpch.h"
00015 #include "plpcxdec.h"
00016 #include "plexcept.h"
00017 
00018 #include "plpcx.h"
00019 
00020 PLPCXDecoder::PLPCXDecoder()
00021   : PLPicDecoder()
00022 // Creates a decoder
00023 {}
00024 
00025 
00026 PLPCXDecoder::~PLPCXDecoder()
00027 {}
00028 
00029 
00030 void PLPCXDecoder::DoDecode (PLBmp * pBmp, PLDataSource * pDataSrc)
00031 {
00032   LPPCXHEADER pcxHeader;
00033   int i, x, y;
00034   PLBYTE ColorMap[PCX_MAXCOLORS][3];
00035   PLBYTE * pcximage = NULL;
00036   PLBYTE * lpHead1 = NULL;
00037   PLBYTE * lpHead2 = NULL;
00038   PLBYTE * pcxplanes;
00039   PLBYTE * pcxpixels;
00040   PLBYTE c;
00041   int nbytes, count;
00042 
00043   int Height, Width;
00044 
00045   // Check if the file is a valid PCX file or not
00046   Trace (2, "Decoding PCX.\n");
00047 
00048   try
00049   {
00050     pcxHeader = (LPPCXHEADER)pDataSrc->ReadNBytes(sizeof(tagPCXHEADER));
00051 
00052     if (pcxHeader->Manufacturer != PCX_MAGIC)
00053     {
00054       raiseError (PL_ERRWRONG_SIGNATURE, "Error decoding pcx: Not a PCX file.");
00055     }
00056     // Check for PCX run length encoding
00057     if (pcxHeader->Encoding != 1)
00058     {
00059       raiseError (PL_ERRWRONG_SIGNATURE, "File has unknown encoding scheme.");
00060     }
00061 
00062     Width = (pcxHeader->Xmax - pcxHeader->Xmin) + 1;
00063     Height = (pcxHeader->Ymax - pcxHeader->Ymin) + 1;
00064     pBmp->Create (Width, Height, 32, false);
00065 
00066     // Check that we can handle this image format
00067     switch (pcxHeader->BitsPerPixel)
00068     {
00069       case 1:
00070         if (pcxHeader->ColorPlanes > 4)
00071         {
00072           raiseError(PL_ERRFORMAT_UNKNOWN, "Can't handle image with more than 4 planes.");
00073         }
00074         break;
00075       case 2:
00076       case 4:
00077       case 8:
00078         if (pcxHeader->ColorPlanes == 1 || pcxHeader->ColorPlanes == 3)
00079           break;
00080       default:
00081         raiseError(PL_ERRFORMAT_UNKNOWN, "Can't handle bits per pixel image with planes.");
00082         break;
00083     }
00084 
00085     nbytes = pcxHeader->BytesPerLine * pcxHeader->ColorPlanes * Height;
00086     lpHead1 = pcximage = (PLBYTE *)malloc(nbytes);
00087     try
00088     {
00089       while (nbytes > 0)
00090       {
00091         c = ReadByte(pDataSrc);
00092         if ((c & 0XC0) != 0XC0) // Repeated group
00093         {
00094           *pcximage++ = c;
00095           --nbytes;
00096           continue;
00097         }
00098         count = c & 0X3F; // extract count
00099         c = ReadByte(pDataSrc);
00100         if (count > nbytes)
00101         {
00102           raiseError(PL_ERRINTERNAL, "repeat count spans end of image.");
00103         }
00104         nbytes -= count;
00105         while (--count >=0)
00106           *pcximage++ = c;
00107       }
00108     }
00109     catch (PLTextException e)
00110     {
00111       // Just in case BytesPerLine is bogus.
00112       // This will fall apart for images that have a palette after the
00113       // image data, however.
00114       if (e.GetCode() != PL_ERREND_OF_FILE)
00115         throw;  
00116     }
00117     pcximage = lpHead1;
00118 
00119     for (i = 0; i < 16; i++)
00120     {
00121       ColorMap[i][0] = pcxHeader->ColorMap[i][0];
00122       ColorMap[i][1] = pcxHeader->ColorMap[i][1];
00123       ColorMap[i][2] = pcxHeader->ColorMap[i][2];
00124     }
00125     if (pcxHeader->BitsPerPixel == 8 && pcxHeader->ColorPlanes == 1)
00126     {
00127       PLBYTE colsig = ReadByte(pDataSrc);
00128 /* It seems like valid PCXs exist with a bad color map signature...
00129       if (colsig != PCX_256_COLORS)
00130       {
00131         raiseError(PL_ERRINTERNAL, "bad color map signature.");
00132       }
00133 */   
00134       for (i = 0; i < PCX_MAXCOLORS; i++)
00135       {
00136         ColorMap[i][0] = ReadByte(pDataSrc);
00137         ColorMap[i][1] = ReadByte(pDataSrc);
00138         ColorMap[i][2] = ReadByte(pDataSrc);
00139       }
00140     }
00141     if (pcxHeader->BitsPerPixel == 1 && pcxHeader->ColorPlanes == 1)
00142     {
00143       ColorMap[0][0] = ColorMap[0][1] = ColorMap[0][2] = 0;
00144       ColorMap[1][0] = ColorMap[1][1] = ColorMap[1][2] = 255;
00145     }
00146 
00147     lpHead2 = pcxpixels = (PLBYTE *)malloc(Width + pcxHeader->BytesPerLine * 8);
00148     // Convert the image
00149     pBmp->Lock(false, true);
00150     PLPixel32 ** pLineArray = pBmp->GetLineArray32();
00151     for (y = 0; y < Height; y++)
00152     {
00153       pcxpixels = lpHead2;
00154       pcxplanes = pcximage + (y * pcxHeader->BytesPerLine * pcxHeader->ColorPlanes);
00155       if (pcxHeader->ColorPlanes == 3 && pcxHeader->BitsPerPixel == 8)
00156       {
00157         // Deal with 24 bit color image
00158         for (x = 0; x < Width; x++)
00159         {
00160           PLPixel32 * pPixel = pLineArray[y];
00161           pPixel[x].Set (pcxplanes[x],
00162                          pcxplanes[pcxHeader->BytesPerLine + x],
00163                          pcxplanes[2*pcxHeader->BytesPerLine + x],
00164                          0xFF);
00165         }
00166         continue;
00167       }
00168       else if (pcxHeader->ColorPlanes == 1)
00169       {
00170         PCX_UnpackPixels(pcxpixels, pcxplanes, pcxHeader->BytesPerLine, pcxHeader->ColorPlanes, pcxHeader->BitsPerPixel);
00171       }
00172       else
00173       {
00174         PCX_PlanesToPixels(pcxpixels, pcxplanes, pcxHeader->BytesPerLine, pcxHeader->ColorPlanes, pcxHeader->BitsPerPixel);
00175       }
00176       for (x = 0; x < Width; x++)
00177       {
00178         i = pcxpixels[x];
00179         PLPixel32 * pPixel = pLineArray[y];
00180         pPixel[x].Set (ColorMap[i][0], ColorMap[i][1],
00181                        ColorMap[i][2], 0xFF);
00182       }
00183     }
00184     pBmp->SetResolution(PLPoint (pcxHeader->Hres, pcxHeader->Vres));
00185     pBmp->Unlock();
00186   }
00187 
00188   catch (PLTextException)
00189   {
00190     if (lpHead1)
00191     {
00192       free(lpHead1);
00193       lpHead1 = NULL;
00194     }
00195     if (lpHead2)
00196     {
00197       free(lpHead2);
00198       lpHead2 = NULL;
00199     }
00200     throw;
00201   }
00202 
00203   if (lpHead1)
00204   {
00205     free(lpHead1);
00206     lpHead1 = NULL;
00207   }
00208   if (lpHead2)
00209   {
00210     free(lpHead2);
00211     lpHead2 = NULL;
00212   }
00213 }
00214 
00215 // Convert multi-plane format into 1 pixel per byte
00216 // from unpacked file data bitplanes[] into pixel row pixels[]
00217 // image Height rows, with each row having planes image planes each
00218 // bytesperline bytes
00219 void PLPCXDecoder::PCX_PlanesToPixels(PLBYTE * pixels, PLBYTE * bitplanes,
00220                                      short bytesperline, short planes, short bitsperpixel)
00221 {
00222   int i, j;
00223   int npixels;
00224   PLBYTE * p;
00225   if (planes > 4)
00226   {
00227     raiseError(PL_ERRINTERNAL, "Can't handle more than 4 planes.");
00228   }
00229   if (bitsperpixel != 1)
00230   {
00231     raiseError(PL_ERRINTERNAL, "Can't handle more than 1 bit per pixel.");
00232   }
00233 
00234   // Clear the pixel buffer
00235   npixels = ((bytesperline-1) * 8) / bitsperpixel;
00236   p = pixels;
00237   while (--npixels >= 0)
00238     *p++ = 0;
00239 
00240   // Do the format conversion
00241   for (i = 0; i < planes; i++)
00242   {
00243     int pixbit, bits, mask;
00244     p = pixels;
00245     pixbit = (1 << i);  // pixel bit for this plane
00246     for (j = 0; j < bytesperline; j++)
00247     {
00248       bits = *bitplanes++;
00249       for (mask = 0X80; mask != 0; mask >>= 1, p++)
00250         if (bits & mask)
00251           *p |= pixbit;
00252     }
00253   }
00254 }
00255 
00256 
00257 // convert packed pixel format into 1 pixel per byte
00258 // from unpacked file data bitplanes[] into pixel row pixels[]
00259 // image Height rows, with each row having planes image planes each
00260 // bytesperline bytes
00261 void PLPCXDecoder::PCX_UnpackPixels(PLBYTE * pixels, PLBYTE * bitplanes,
00262                                    short bytesperline, short planes, short bitsperpixel)
00263 {
00264   register int bits;
00265   if (planes != 1)
00266   {
00267     raiseError(PL_ERRINTERNAL, "Can't handle packed pixels with more than 1 plane.");
00268   }
00269   if (bitsperpixel == 8)  // 8 bits/pixels, no unpacking needed
00270   {
00271     while (bytesperline-- > 0)
00272       *pixels++ = *bitplanes++;
00273   }
00274   else if (bitsperpixel == 4)  // 4 bits/pixel, two pixels per byte
00275   {
00276     while (bytesperline-- > 0)
00277     {
00278       bits = *bitplanes++;
00279       *pixels++ = (PLBYTE)((bits >> 4) & 0X0F);
00280       *pixels++ = (PLBYTE)((bits) & 0X0F);
00281     }
00282   }
00283   else if (bitsperpixel == 2)  // 2 bits/pixel, four pixels per byte
00284   {
00285     while (bytesperline-- > 0)
00286     {
00287       bits = *bitplanes++;
00288       *pixels++ = (PLBYTE)((bits >> 6) & 0X03);
00289       *pixels++ = (PLBYTE)((bits >> 4) & 0X03);
00290       *pixels++ = (PLBYTE)((bits >> 2) & 0X03);
00291       *pixels++ = (PLBYTE)((bits) & 0X03);
00292     }
00293   }
00294   else if (bitsperpixel == 1)  // 1 bits/pixel, 8 pixels per byte
00295   {
00296     while (bytesperline-- > 0)
00297     {
00298       bits = *bitplanes++;
00299       *pixels++ = ((bits & 0X80) != 0);
00300       *pixels++ = ((bits & 0X40) != 0);
00301       *pixels++ = ((bits & 0X20) != 0);
00302       *pixels++ = ((bits & 0X10) != 0);
00303       *pixels++ = ((bits & 0X08) != 0);
00304       *pixels++ = ((bits & 0X04) != 0);
00305       *pixels++ = ((bits & 0X02) != 0);
00306       *pixels++ = ((bits & 0X01) != 0);
00307     }
00308   }
00309 }
00310 
00311 /*
00312 /--------------------------------------------------------------------
00313 |
00314 |      $Log: plpcxdec.cpp,v $
00315 |      Revision 1.1  2004/05/21 21:02:53  maxx
00316 |      Initial Version of vuVolume, moderatly changed to make it compile on my windows and linux machine.
00317 |
00318 |      Revision 1.1  2002/11/13 01:58:21  mspindle
00319 |      *** empty log message ***
00320 |
00321 |      Revision 1.7  2002/01/27 18:20:15  uzadow
00322 |      Updated copyright message; corrected pcx decoder bug.
00323 |
00324 |      Revision 1.6  2001/10/21 17:12:40  uzadow
00325 |      Added PSD decoder beta, removed BPPWanted from all decoders, added PLFilterPixel.
00326 |
00327 |      Revision 1.5  2001/10/16 17:12:26  uzadow
00328 |      Added support for resolution information (Luca Piergentili)
00329 |
00330 |      Revision 1.4  2001/10/06 22:37:08  uzadow
00331 |      Linux compatibility.
00332 |
00333 |      Revision 1.3  2001/10/06 15:32:22  uzadow
00334 |      Removed types LPPLBYTE, DWORD, UCHAR, VOID and INT from the code.
00335 |
00336 |      Revision 1.2  2001/09/30 16:56:29  uzadow
00337 |      Fixed bug decoding wierd pcx files.
00338 |
00339 |      Revision 1.1  2001/09/16 19:03:22  uzadow
00340 |      Added global name prefix PL, changed most filenames.
00341 |
00342 |      Revision 1.12  2001/02/04 14:31:52  uzadow
00343 |      Member initialization list cleanup (Erik Hoffmann).
00344 |
00345 |      Revision 1.11  2000/12/18 22:42:52  uzadow
00346 |      Replaced RGBAPIXEL with PLPixel32.
00347 |
00348 |      Revision 1.10  2000/10/27 11:30:06  uzadow
00349 |      Fixed bug #117544
00350 |
00351 |      Revision 1.9  2000/10/23 22:03:07  uzadow
00352 |      Bugfix for bug #116362 by Marcus J. Hodge
00353 |
00354 |      Revision 1.8  2000/09/21 14:35:13  Administrator
00355 |      Fixed bug in pcx decoder
00356 |
00357 |      Revision 1.7  2000/08/13 12:11:43  Administrator
00358 |      Added experimental DirectDraw-Support
00359 |
00360 |      Revision 1.6  2000/03/30 21:23:43  Ulrich von Zadow
00361 |      no message
00362 |
00363 |      Revision 1.5  2000/03/17 10:51:12  Ulrich von Zadow
00364 |      Bugfix for b/w images.
00365 |
00366 |      Revision 1.4  2000/01/16 20:43:13  anonymous
00367 |      Removed MFC dependencies
00368 |
00369 |
00370 \--------------------------------------------------------------------
00371 */

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