00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 # include <config.h>
00021 #endif
00022
00023 #include "SDL_byteorder.h"
00024 #include <iostream>
00025
00026 #ifndef ALPHA_LINUX_CXX
00027 # include <cstdio>
00028 # include <cstring>
00029 # include <string>
00030 #endif
00031
00032 #include "exult_types.h"
00033
00034 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
00035 #define qtohl(x) (x)
00036 #define qtohs(x) (x)
00037 #else
00038 #define qtohl(x) \
00039 ((uint32)((((uint32)(x) & 0x000000ffU) << 24) | \
00040 (((uint32)(x) & 0x0000ff00U) << 8) | \
00041 (((uint32)(x) & 0x00ff0000U) >> 8) | \
00042 (((uint32)(x) & 0xff000000U) >> 24)))
00043 #define qtohs(x) \
00044 ((uint16)((((uint16)(x) & 0x00ff) << 8) | \
00045 (((uint16)(x) & 0xff00) >> 8)))
00046 #endif
00047 #define htoql(x) qtohl(x)
00048 #define htoqs(x) qtohs(x)
00049
00050
00051 using std::cout;
00052 using std::endl;
00053 using std::cerr;
00054 using std::string;
00055 using std::strlen;
00056 using std::memset;
00057 using std::memcpy;
00058
00059 typedef struct PCX_Header {
00060 uint8 manufacturer;
00061 uint8 version;
00062 uint8 compression;
00063 uint8 bpp;
00064 sint16 x1, y1;
00065 sint16 x2, y2;
00066 sint16 hdpi;
00067 sint16 vdpi;
00068 uint8 colormap[48];
00069 uint8 reserved;
00070 uint8 planes;
00071 sint16 bytesperline;
00072 sint16 color;
00073 uint8 filler[58];
00074 } PCX_Header;
00075
00076 struct u7frame {
00077 sint16 leftX;
00078 sint16 leftY;
00079 sint16 rightX;
00080 sint16 rightY;
00081 uint16 width;
00082 uint16 height;
00083 uint32 datalen;
00084 uint8 *pixels;
00085 };
00086
00087 struct u7shape {
00088 int num_frames;
00089 struct u7frame *frames;
00090 int width, height;
00091 };
00092
00093 unsigned int read1(FILE *f)
00094 {
00095 unsigned char b0;
00096 b0 = fgetc(f);
00097 return b0;
00098 }
00099
00100 unsigned int read2(FILE *f)
00101 {
00102 unsigned char b0, b1;
00103 b0 = fgetc(f);
00104 b1 = fgetc(f);
00105 return (b0 + (b1<<8));
00106 }
00107
00108
00109 signed int read2signed(FILE *f)
00110 {
00111 unsigned char b0, b1;
00112 signed int i0;
00113 b0 = fgetc(f);
00114 b1 = fgetc(f);
00115 i0 = b0 + (b1<<8);
00116 if (i0 >= 32768) { i0 = i0 - 65536; }
00117 return (i0);
00118 }
00119
00120 unsigned int read4(FILE *f)
00121 {
00122 unsigned char b0, b1, b2, b3;
00123 b0 = fgetc(f);
00124 b1 = fgetc(f);
00125 b2 = fgetc(f);
00126 b3 = fgetc(f);
00127 return (b0 + (b1<<8) + (b2<<16) + (b3<<24));
00128 }
00129
00130
00131 u7shape* load_shape(char* filename)
00132 {
00133 FILE *fp;
00134 int file_size, shape_size, hdr_size;
00135 uint8 *pixptr, *eod;
00136 int frame_offset;
00137 int slice;
00138 int image_ID = -1, layer_ID = -1;
00139 int slice_type, slice_length;
00140 int block_type, block_length;
00141 int max_leftX = -1, max_rightX = -1;
00142 int max_leftY = -1, max_rightY = -1;
00143 int offsetX, offsetY;
00144 char *framename;
00145 uint8 block;
00146 uint8 pix;
00147 int i, j;
00148
00149 int temp_int;
00150
00151 u7shape *shape = new u7shape;
00152 u7frame *frame;
00153
00154 fp = fopen (filename, "rb");
00155 if (!fp) {
00156 cerr << "Can't open " << filename << endl;
00157 return 0;
00158 }
00159 fseek(fp, 0, SEEK_END);
00160 file_size = ftell(fp);
00161 fseek(fp, 0, SEEK_SET);
00162
00163 shape_size = read4(fp);
00164
00165 if(file_size!=shape_size) {
00166 shape->num_frames = file_size/64;
00167 fseek(fp, 0, SEEK_SET);
00168 cout << "num_frames = " << shape->num_frames << endl;
00169 shape->frames = new u7frame[shape->num_frames];
00170 max_leftX = 0; max_leftY = 0; max_rightX = 7; max_rightY = 7;
00171
00172 for(i=0; i<shape->num_frames; i++) {
00173 frame = &shape->frames[i];
00174 frame->width = 8;
00175 frame->height = 8;
00176 frame->leftX = 0;
00177 frame->leftY = 0;
00178 frame->pixels = new uint8[64];
00179 fread(frame->pixels, 1, 64, fp);
00180 }
00181 } else {
00182 hdr_size = read4(fp);
00183 shape->num_frames = (hdr_size-4)/4;
00184
00185 cout << "num_frames = "<< shape->num_frames << endl;
00186 shape->frames = new u7frame[shape->num_frames];
00187
00188 for(i=0; i<shape->num_frames; i++) {
00189 frame = &shape->frames[i];
00190
00191
00192 fseek(fp, (i+1)*4, SEEK_SET);
00193 frame_offset = read4(fp);
00194 fseek(fp, frame_offset, SEEK_SET);
00195 frame->rightX = read2(fp);
00196 frame->leftX = read2(fp);
00197 frame->leftY = read2(fp);
00198 frame->rightY = read2(fp);
00199
00200 if (frame->leftX > max_leftX)
00201 max_leftX = frame->leftX;
00202 if (frame->rightX > max_rightX)
00203 max_rightX = frame->rightX;
00204 if (frame->leftY > max_leftY)
00205 max_leftY = frame->leftY;
00206 if (frame->rightY > max_rightY)
00207 max_rightY = frame->rightY;
00208
00209 frame->width = frame->leftX+frame->rightX+1;
00210 frame->height = frame->leftY+frame->rightY+1;
00211
00212 pixptr = new uint8[frame->width*frame->height];
00213 frame->pixels = pixptr;
00214 memset(pixptr, 0, frame->width*frame->height);
00215
00216 eod = frame->pixels+frame->width*frame->height;
00217 while((slice=read2(fp))!=0) {
00218 slice_type = slice & 0x1;
00219 slice_length = slice >> 1;
00220
00221 offsetX = read2signed(fp);
00222 offsetY = read2signed(fp);
00223
00224 temp_int = (frame->leftY + offsetY)*frame->width +
00225 (frame->leftX + offsetX);
00226
00227 pixptr = frame->pixels;
00228 pixptr = pixptr + temp_int;
00229
00230 if(pixptr<frame->pixels)
00231 pixptr = frame->pixels;
00232 if(slice_type) {
00233 while(slice_length>0) {
00234 block = read1(fp);
00235 block_type = block & 0x1;
00236 block_length = block >> 1;
00237 if(block_type) {
00238 pix = read1(fp);
00239 for(j=0;j<block_length;j++) {
00240 *pixptr++ = pix;
00241 }
00242 } else {
00243 for(j=0;j<block_length;j++) {
00244 pix = read1(fp);
00245 *pixptr++ = pix;
00246 }
00247 }
00248 slice_length -= block_length;
00249 }
00250 } else {
00251
00252 for(j=0;j<slice_length;j++) {
00253 pix = read1(fp);
00254 *pixptr++ = pix;
00255 }
00256 }
00257 }
00258 }
00259 }
00260
00261 cout << "origin: x = " << max_leftX << ", y = " << max_leftY << endl;
00262
00263 int width = max_leftX + max_rightX + 1;
00264 int height = max_leftY + max_rightY + 1;
00265
00266 shape->width = width; shape->height = height;
00267
00268 int srcx, srcy, dstx, dsty;
00269
00270 for (i=0; i<shape->num_frames; i++) {
00271 frame = &shape->frames[i];
00272 pixptr = frame->pixels;
00273
00274 frame->pixels = new uint8[width*height];
00275 memset(frame->pixels, 0, width*height);
00276
00277 dsty = max_leftY - frame->leftY;
00278
00279 for (srcy = 0; srcy < frame->height; srcy++, dsty++) {
00280 dstx = max_leftX - frame->leftX;
00281 srcx = 0;
00282 memcpy(frame->pixels + dsty*width + dstx, pixptr + srcy*frame->width + srcx, frame->width);
00283 }
00284
00285 delete [] pixptr;
00286 }
00287
00288 return shape;
00289 }
00290
00291 uint8* load_palette (char *filename)
00292 {
00293 FILE *fp;
00294 long len;
00295 int i;
00296
00297 fp = fopen (filename, "rb");
00298 if (!fp) {
00299 cerr << "Can't open " << filename << endl;
00300 return 0;
00301 }
00302
00303 uint8* palette = new uint8[768];
00304
00305 fseek(fp, 0, SEEK_END);
00306 len = ftell(fp);
00307 fseek(fp, 0, SEEK_SET);
00308 if(len==768) {
00309 for(i=0;i<256;i++) {
00310 palette[i*3]=read1(fp) << 2;
00311 palette[i*3+1]=read1(fp) << 2;
00312 palette[i*3+2]=read1(fp) << 2;
00313 }
00314 } else if(len==1536) {
00315 for(i=0;i<256;i++) {
00316 palette[i*3]=read1(fp) << 2;
00317 read1(fp);
00318 palette[i*3+1]=read1(fp) << 2;
00319 read1(fp);
00320 palette[i*3+2]=read1(fp) << 2;
00321 read1(fp);
00322 }
00323 } else {
00324 cerr << "Not a valid palette file: " << filename << endl;
00325 delete [] palette;
00326 return 0;
00327 }
00328 fclose(fp);
00329
00330 return palette;
00331 }
00332
00333 static void writeline (FILE *dst, uint8* buffer, int bytes) {
00334 uint8 value, count, tmp;
00335 uint8 *finish = buffer + bytes;
00336
00337 while (buffer < finish) {
00338
00339 value = *(buffer++);
00340 count = 1;
00341
00342 while (buffer < finish && count < 63 && *buffer == value) {
00343 count++; buffer++;
00344 }
00345
00346 if (value < 0xc0 && count == 1) {
00347 fputc(value, dst);
00348 } else {
00349 tmp = count + 0xc0;
00350 fputc(tmp, dst);
00351 fputc(value, dst);
00352 }
00353 }
00354 }
00355
00356 void save_8 (FILE *dst, int width, int height,
00357 int pitch, uint8* buffer)
00358 {
00359 int row;
00360
00361 for (row = 0; row < height; ++row)
00362 {
00363 writeline (dst, buffer, width);
00364 buffer += pitch;
00365 }
00366 }
00367
00368
00369 void save_image(uint8* pixels, uint8* palette, int width, int height, char *filename)
00370 {
00371 uint8 tmp;
00372 int pitch;
00373 int i;
00374 PCX_Header header;
00375
00376 FILE *fp = fopen (filename, "wb");
00377 if (!fp) {
00378 cerr << "Can't open " << filename << endl;
00379 return;
00380 }
00381
00382 pitch = width;
00383
00384 header.manufacturer = 0x0a;
00385 header.version = 5;
00386 header.compression = 1;
00387
00388 header.bpp = 8;
00389 header.bytesperline = htoqs (width);
00390 header.planes = 1;
00391 header.color = htoqs (1);
00392
00393 header.x1 = 0;
00394 header.y1 = 0;
00395 header.x2 = htoqs (width - 1);
00396 header.y2 = htoqs (height - 1);
00397
00398 header.hdpi = htoqs (300);
00399 header.vdpi = htoqs (300);
00400 header.reserved = 0;
00401
00402
00403 fwrite(&header, sizeof(PCX_Header), 1, fp);
00404
00405 save_8 (fp, width, height, pitch, pixels);
00406
00407 fputc(0x0c, fp);
00408 fwrite(palette, 3, 256, fp);
00409 }
00410
00411 int main(int argc, char *argv[])
00412 {
00413 char* palfilename ;
00414 char* infilename;
00415 char* outprefix, outfilename[255];
00416 u7shape* sh;
00417 uint8* palette;
00418
00419 if (argc < 4) {
00420 cout << "Usage: shp2pcx [input file] [output file prefix] [palette file]" << endl;
00421 return 0;
00422 }
00423
00424 infilename = argv[1];
00425 outprefix = argv[2];
00426 palfilename = argv[3];
00427
00428 if (strlen(outprefix) > 128) {
00429 cerr << "Output file prefix too long!" << endl;
00430 return -1;
00431 }
00432
00433 sh = load_shape(infilename);
00434 if (!sh) return 1;
00435 palette = load_palette(palfilename);
00436 if (!palette) return 1;
00437
00438 for (int i = 0; i < sh->num_frames; i++) {
00439 sprintf(outfilename, "%s%02i.pcx", outprefix, i);
00440 cout << "Writing frame " << i << " to " << outfilename << "..." << endl;
00441 save_image(sh->frames[i].pixels, palette, sh->width, sh->height, outfilename);
00442 }
00443
00444 return 0;
00445 }