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
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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
00042 byte data;
00043 if (file->read(&data, 1) != 1) {
00044 return false;
00045 }
00046
00047 if ((data & 0xC0) != 0xC0) {
00048 *out++ = data;
00049 } else {
00050
00051
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
00073 byte pcx_header[128];
00074 int read = file->read(pcx_header, 128);
00075 if (read != 128) {
00076 return 0;
00077 }
00078
00079
00080
00081
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
00093
00094
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
00109 if (bpp != 8) {
00110 COR_LOG("Unsupported bpp");
00111 return 0;
00112 }
00113
00114
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
00122
00123 if (num_planes == 1) {
00124
00125 auto_array<RGB> palette(new RGB[256]);
00126 auto_array<byte> image(new byte[width * height]);
00127
00128
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
00138 if (!file->seek(-769, File::END)) {
00139 COR_LOG("Failure seeking to palette");
00140 return 0;
00141 }
00142
00143
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
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) {
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 }