corona
1.0.2
|
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 }