Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OpenPCX.cpp

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <string.h>
00003 #include "Debug.h"
00004 #include "Open.h"
00005 #include "SimpleImage.h"
00006 #include "Utility.h"
00007 
00008 
00009 namespace corona {
00010 
00011   /*
00012   struct PCX_HEADER {
00013     byte manufacturer;
00014     byte version;
00015     byte encoding;
00016     byte bits_per_pixel;
00017     word xmin;
00018     word ymin;
00019     word xmax;
00020     word ymax;
00021     word hdpi;
00022     word vdpi;
00023     byte colormap[48];
00024     byte reserved;
00025     byte num_planes;
00026     word bytes_per_line;
00027     word palette_info;
00028     word h_screen_size;
00029     word v_screen_size;
00030     byte filler[54];
00031   };
00032   */
00033 
00034 
00036 
00037   bool ReadScanline(File* file, int scansize, byte* scanline) {
00038     byte* out = scanline;
00039     while (out - scanline < scansize) {
00040 
00041       // read a byte!
00042       byte data;
00043       if (file->read(&data, 1) != 1) {
00044         return false;
00045       }
00046 
00047       if ((data & 0xC0) != 0xC0) {  // non RLE
00048         *out++ = data;
00049       } else {                      // RLE
00050 
00051         // read the repeated byte
00052         int numbytes = data & 0x3F;
00053         if (file->read(&data, 1) != 1) {
00054           return false;
00055         }
00056 
00057         while (numbytes-- && out - scanline < scansize) {
00058           *out++ = data;
00059         }
00060 
00061       }
00062     }
00063 
00064     return true;
00065   }
00066 
00068 
00069   Image* OpenPCX(File* file) {
00070     COR_GUARD("OpenPCX");
00071 
00072     // read the header block
00073     byte pcx_header[128];
00074     int read = file->read(pcx_header, 128);
00075     if (read != 128) {
00076       return 0;
00077     }
00078 
00079     // parse the header...
00080     //int manufacturer   = pcx_header[0];
00081     //int version        = pcx_header[1];
00082     int encoding       = pcx_header[2];
00083     int bpp            = pcx_header[3];
00084     int xmin           = read16_le(pcx_header + 4);
00085     int ymin           = read16_le(pcx_header + 6);
00086     int xmax           = read16_le(pcx_header + 8);
00087     int ymax           = read16_le(pcx_header + 10);
00088     int num_planes     = pcx_header[65];
00089     int bytes_per_line = read16_le(pcx_header + 66);
00090 
00091 
00092     // verify the header
00093 
00094     // we only support RLE encoding
00095     if (encoding != 1) {
00096       COR_LOG("Unsupported encoding");
00097       return 0;
00098     }
00099 
00100     COR_IF_DEBUG {
00101       char str[100];
00102       sprintf(str, "bits per pixel - %d", bpp);
00103       COR_LOG(str);
00104       sprintf(str, "bytes per line - %d", bytes_per_line);
00105       COR_LOG(str);
00106     }
00107 
00108     // we only support 8 bits per pixel
00109     if (bpp != 8) {
00110       COR_LOG("Unsupported bpp");
00111       return 0;
00112     }
00113 
00114     // create the image structure
00115     int width  = xmax - xmin + 1;
00116     int height = ymax - ymin + 1;
00117 
00118     auto_array<byte> scanline(new byte[bytes_per_line]);
00119     auto_array<byte> pixels(new byte[width * height * 3]);
00120 
00121     // decode the pixel data
00122 
00123     if (num_planes == 1) {               // 256 colors
00124 
00125       auto_array<RGB> palette(new RGB[256]);
00126       auto_array<byte> image(new byte[width * height]);
00127 
00128       // read all of the scanlines
00129       for (int iy = 0; iy < height; ++iy) {
00130         if (!ReadScanline(file, bytes_per_line, scanline)) {
00131           COR_LOG("Failure reading scanline");
00132           return 0;
00133         }
00134         memcpy((byte*)image + iy * width, scanline, width);
00135       }
00136 
00137       // seek back from the end 769 bytes
00138       if (!file->seek(-769, File::END)) {
00139         COR_LOG("Failure seeking to palette");
00140         return 0;
00141       }
00142 
00143       // do we have a palette?
00144       byte has_palette;
00145       if (file->read(&has_palette, 1) != 1 || has_palette != 12) {
00146         COR_LOG("Failure testing for existence of palette");
00147         return 0;
00148       }
00149 
00150       // read palette
00151       if (file->read(palette, 3 * 256) != 3 * 256) {
00152         COR_LOG("Failure reading palette");
00153         return 0;
00154       }
00155 
00156       return new SimpleImage(width, height, PF_I8, image.release(),
00157                              (byte*)palette.release(), 256, PF_R8G8B8);
00158 
00159     } else if (num_planes == 3) { // 24-bit color
00160 
00161       auto_array<byte> scanline(new byte[3 * bytes_per_line]);
00162 
00163       byte* out = pixels;
00164       for (int iy = 0; iy < height; ++iy) {
00165         if (!ReadScanline(file, 3 * bytes_per_line, scanline)) {
00166           COR_LOG("Failure reading scanline");
00167           return 0;
00168         }
00169 
00170         byte* r = scanline;
00171         byte* g = scanline + bytes_per_line;
00172         byte* b = scanline + bytes_per_line * 2;
00173         for (int ix = 0; ix < width; ++ix) {
00174           *out++ = *r++;
00175           *out++ = *g++;
00176           *out++ = *b++;
00177         }
00178       }
00179 
00180       return new SimpleImage(width, height, PF_R8G8B8, pixels.release());
00181 
00182     } else {
00183       COR_LOG("Unknown number of planes");
00184       return 0;
00185     }
00186   }
00187 
00189 
00190 }

Generated on Thu Oct 2 12:59:31 2003 for corona by doxygen1.3-rc1