shp2pcx.cc

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2001  The Exult Team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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 /* Flauschepelz */
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) { /* 8x8 tile */
00166     shape->num_frames = file_size/64;
00167     fseek(fp, 0, SEEK_SET);   /* Return to start of file */
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       // Go to where frame offset is stored
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) {  // Compressed
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 {    // Uncompressed
00251     // Just read the pixels
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   /* write header */
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 }

Generated on Mon Jul 9 14:42:50 2007 for ExultEngine by  doxygen 1.5.1