00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <stdio.h>
00029 #include <cstring>
00030
00031 #include "basestrm.h"
00032
00033 #include "misc.h"
00034 #include "loadpcx.h"
00035
00036 #pragma pack(1)
00037
00038 struct tpcxheader{
00039 char manufacturer;
00040 char version ;
00041 char encoding ;
00042 char bitsperpixel;
00043 Uint16 xmin,ymin ;
00044 Uint16 xmax,ymax ;
00045 Uint16 hdpi,vdpi ;
00046 char colormap[48];
00047 char reserved ;
00048 char nplanes ;
00049 Uint16 bytesperline;
00050 Uint16 paletteinfo ;
00051 Uint16 hscreensize ;
00052 Uint16 vscreensize ;
00053 char dummy[50] ;
00054 int size;
00055
00056 void read ( tnstream* stream );
00057 void write ( tnstream* stream );
00058 };
00059
00060 void tpcxheader::read ( tnstream* stream )
00061 {
00062 manufacturer = stream->readChar();
00063 version = stream->readChar();
00064 encoding = stream->readChar();
00065 bitsperpixel = stream->readChar();
00066 xmin = stream->readWord();
00067 ymin = stream->readWord();
00068 xmax = stream->readWord();
00069 ymax = stream->readWord();
00070 hdpi = stream->readWord();
00071 vdpi = stream->readWord();
00072 stream->readdata ( colormap, 48);
00073 reserved = stream->readChar();
00074 nplanes = stream->readChar();
00075 bytesperline= stream->readWord();
00076 paletteinfo = stream->readWord();
00077 hscreensize = stream->readWord();
00078 vscreensize = stream->readWord();
00079 stream->readdata ( dummy, 50 ) ;
00080 size = stream->readInt();
00081 }
00082
00083 void tpcxheader::write ( tnstream* stream )
00084 {
00085 stream->writeChar( manufacturer );
00086 stream->writeChar( version );
00087 stream->writeChar( encoding );
00088 stream->writeChar( bitsperpixel );
00089 stream->writeWord( xmin );
00090 stream->writeWord( ymin );
00091 stream->writeWord( xmax );
00092 stream->writeWord( ymax );
00093 stream->writeWord( hdpi );
00094 stream->writeWord( vdpi );
00095 stream->writedata ( colormap, 48);
00096 stream->writeChar( reserved );
00097 stream->writeChar( nplanes );
00098 stream->writeWord( bytesperline);
00099 stream->writeWord( paletteinfo );
00100 stream->writeWord( hscreensize );
00101 stream->writeWord( vscreensize );
00102 stream->writedata ( dummy, 50 ) ;
00103 stream->writeInt( size );
00104 }
00105
00106 #pragma pack()
00107
00108 #if 0
00109 int pcxGetColorDepth ( const ASCString& filename, int* width, int* height )
00110 {
00111 tnfilestream stream ( filename.c_str(), tnstream::reading );
00112
00113 tpcxheader header;
00114 header.read ( &stream );
00115
00116 if ( width )
00117 *width = header.xmax - header.xmin + 1 ;
00118
00119 if ( height )
00120 *height = header.ymax - header.ymin + 1;
00121
00122
00123 return header.nplanes * header.bitsperpixel;
00124 }
00125
00126
00127 char loadpcxxy( pnstream stream, int x, int y, bool setpalette, int* xsize, int* ysize )
00128 {
00129 int read = 0;
00130
00131
00132
00133 tpcxheader header;
00134
00135 header.read( stream );
00136
00137 read += sizeof(header);
00138
00139 if ( !header.size ) {
00140 if ( stream->getSize() < 0 )
00141 return 12;
00142 else
00143 header.size = stream->getSize();
00144 }
00145
00146 int width = header.xmax - header.xmin + 1 ;
00147 int height = header.ymax - header.ymin + 1;
00148 int pixels = width * height * header.nplanes;
00149
00150 if ( xsize )
00151 *xsize = width;
00152
00153 if ( ysize )
00154 *ysize = height;
00155
00156 if ( header.manufacturer != 10 ||
00157 header.bitsperpixel != 8 ||
00158 header.xmax-header.xmin > agmp-> scanlinelength )
00159 return 11;
00160
00161 int colors = header.nplanes * header.bitsperpixel;
00162
00163 int scanlineret[4];
00164
00165 if (agmp->byteperpix > 1) {
00166
00167 scanlineret[0] = agmp-> redfieldposition / 8;
00168 scanlineret[1] = header.bytesperline * agmp->byteperpix - agmp->greenfieldposition / 8 + agmp-> redfieldposition / 8;
00169 scanlineret[2] = header.bytesperline * agmp->byteperpix - agmp->bluefieldposition / 8 + agmp-> greenfieldposition / 8;
00170 scanlineret[3] = -(agmp-> scanlinelength -
00171 header.bytesperline* agmp->byteperpix + agmp->redfieldposition / 8 - agmp->bluefieldposition / 8);
00172
00173 } else {
00174 scanlineret[0]=0;
00175 scanlineret[1]= -(agmp->scanlinelength - header.bytesperline * agmp->byteperpix);
00176 }
00177
00178
00179
00180
00181 int ttlbytes = 0;
00182 int xpos = 0;
00183 int planenum = 0;
00184
00185 int byteperpix = agmp->byteperpix;
00186
00187
00188
00189 char* buf = new char[header.size];
00190
00191 stream->readdata ( buf, header.size - sizeof( header ));
00192 int actpos = 0;
00193
00194
00195 char* dest = (char*) (agmp->linearaddress + x * agmp->byteperpix + y * agmp->bytesperscanline + scanlineret[0]);
00196 while ( pixels ) {
00197 char a;
00198
00199 a = buf[actpos++];
00200
00201 read++;
00202
00203 int count;
00204 if ( a >= 192 ) {
00205 count = a ^192;
00206
00207 a = buf[actpos++];
00208
00209 read++;
00210 } else
00211 count = 1;
00212
00213 while ( count ) {
00214 if ( xpos >= header.bytesperline ) {
00215 planenum++;
00216 dest -= scanlineret[planenum];
00217 if ( planenum >= header.nplanes ) {
00218 planenum = 0;
00219 ttlbytes = 0;
00220 }
00221 xpos = 0;
00222 }
00223 if ( xpos < width ) {
00224 *dest = a;
00225 pixels--;
00226 }
00227 dest+= byteperpix;
00228 xpos++;
00229 ttlbytes++;
00230 count--;
00231 }
00232
00233 }
00234
00235 if ( setpalette && colors == 8 ) {
00236 if ( header.size ) {
00237 int dataend = header.size - sizeof ( dacpalette256 ) - 1 - sizeof ( header );
00238 actpos = dataend;
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 }
00252
00253 char c = buf[actpos++];
00254 if ( c == 12 ) {
00255 dacpalette256 pal;
00256 memcpy ( pal, &buf[actpos], sizeof ( pal ));
00257
00258 for ( int i = 0; i < 3; i++ )
00259 for ( int j = 0; j < 256; j++ )
00260 pal[j][i] >>= 2;
00261
00262 }
00263 }
00264
00265 delete[] buf;
00266 return 0;
00267 }
00268
00269
00270 char loadpcxxy ( const ASCString& name, bool setpal, int xpos, int ypos, int* xsize, int* ysize )
00271 {
00272 tnfilestream s ( name, tnstream::reading );
00273 return loadpcxxy ( &s, xpos, ypos, setpal, xsize, ysize );
00274 }
00275 #endif
00276
00277 void writepcx ( const ASCString& name, int x1, int y1, int x2, int y2, dacpalette256 pal )
00278 {
00279 tpcxheader header;
00280 memset ( &header, 0, sizeof (header ));
00281 header.manufacturer = 10;
00282 header.version = 5;
00283 header.encoding = 1;
00284 header.bitsperpixel = 8;
00285 header.xmin = 0;
00286 header.xmax = x2 - x1 ;
00287 header.ymin = 0;
00288 header.ymax = y2 - y1 ;
00289 header.hdpi = 0;
00290 header.vdpi = 0;
00291 if ( agmp->byteperpix == 1 )
00292 header.nplanes = 1;
00293 else
00294 header.nplanes = 3;
00295
00296
00297 header.bytesperline = x2 - x1 + 1 ;
00298 if ( header.bytesperline & 1 )
00299 header.bytesperline++;
00300 header.paletteinfo = 1;
00301
00302 int fsize = 0;
00303
00304 tn_file_buf_stream stream ( name, tnstream::writing );
00305
00306 header.write ( &stream );
00307
00308 fsize += sizeof ( header );
00309
00310 for ( int y = y1; y <= y2; y++ )
00311 for ( int plane = 0; plane < header.nplanes; plane++ ) {
00312 int lastbyte = -1;
00313 int count = 0;
00314 for ( int x = x1; x < x1 + header.bytesperline; x++ ) {
00315 char c = (getpixel( x, y ) >> ( plane * 8 )) & 0xff;
00316
00317 if ( (lastbyte == c && count < 63) || lastbyte == -1 ) {
00318 count ++;
00319 lastbyte = c;
00320 }
00321 else {
00322 if ( count > 1 || lastbyte >= 192 ) {
00323 char d = 192 + count;
00324 stream.writeChar ( d );
00325 fsize += sizeof ( d );
00326 }
00327 char lstbyte = lastbyte;
00328 stream.writeChar ( lstbyte );
00329 fsize += sizeof ( lstbyte );
00330 count = 1;
00331 lastbyte = c;
00332 }
00333
00334 }
00335 if ( count > 1 || lastbyte >= 192 ) {
00336 char d = 192 + count;
00337 stream.writeChar ( d );
00338 fsize += sizeof ( d );
00339 }
00340 char lstbyte = lastbyte;
00341 stream.writeChar ( lstbyte );
00342 fsize += sizeof ( lstbyte );
00343
00344 }
00345
00346 if ( header.nplanes == 1 ) {
00347 char d = 12;
00348 stream.writeChar ( d );
00349 fsize += sizeof ( d );
00350
00351 dacpalette256 pal2;
00352
00353 for ( int i = 0; i < 3; i++ )
00354 for ( int j = 0; j < 256; j++ )
00355 pal2[j][i] = pal[j][i] << 2;
00356
00357 stream.writedata ( &pal2, 768 );
00358 fsize += 768 ;
00359 }
00360 stream.seek ( 0 );
00361 header.size = fsize;
00362 header.write ( &stream );
00363 }
00364
00365
00366 void writepcx ( const ASCString& name, const Surface& s )
00367 {
00368 writepcx( name, s, SDLmm::SRect( SPoint(0,0), s.w(), s.h() ));
00369 }
00370
00371 void writepcx ( const ASCString& name, const Surface& s, const SDLmm::SRect& rect )
00372 {
00373 int x1 = rect.x;
00374 int y1 = rect.y;
00375 int x2 = rect.x + rect.w - 1;
00376 int y2 = rect.y + rect.h - 1;
00377 tpcxheader header;
00378 memset ( &header, 0, sizeof (header ));
00379 header.manufacturer = 10;
00380 header.version = 5;
00381 header.encoding = 1;
00382 header.bitsperpixel = 8;
00383 header.xmin = 0;
00384 header.xmax = x2 - y1 ;
00385 header.ymin = 0 ;
00386 header.ymax = y2 - y1;
00387 header.hdpi = 0;
00388 header.vdpi = 0;
00389 if ( s.GetPixelFormat().BitsPerPixel() == 8 )
00390 header.nplanes = 1;
00391 else
00392 header.nplanes = 3;
00393
00394
00395 header.bytesperline = x2 - x1 + 1 ;
00396 if ( header.bytesperline & 1 )
00397 header.bytesperline++;
00398 header.paletteinfo = 1;
00399
00400 int fsize = 0;
00401
00402 tn_file_buf_stream stream ( name, tnstream::writing );
00403
00404 header.write ( &stream );
00405
00406 fsize += sizeof ( header );
00407
00408 int shift[3] = { 0, 0, };
00409 if ( header.nplanes > 1 ) {
00410 shift[0] = s.GetPixelFormat().Rshift();
00411 shift[1] = s.GetPixelFormat().Gshift();
00412 shift[2] = s.GetPixelFormat().Bshift();
00413 }
00414
00415 for ( int y = y1; y <= y2; y++ )
00416 for ( int plane = 0; plane < header.nplanes; plane++ ) {
00417 int lastbyte = -1;
00418 int count = 0;
00419 for ( int x = x1; x < x1 + header.bytesperline; x++ ) {
00420 char c = (s.GetPixel( x, y ) >> shift[plane]) & 0xff;
00421
00422 if ( (lastbyte == c && count < 63) || lastbyte == -1 ) {
00423 count ++;
00424 lastbyte = c;
00425 }
00426 else {
00427 if ( count > 1 || lastbyte >= 192 ) {
00428 char d = 192 + count;
00429 stream.writeChar ( d );
00430 fsize += sizeof ( d );
00431 }
00432 char lstbyte = lastbyte;
00433 stream.writeChar ( lstbyte );
00434 fsize += sizeof ( lstbyte );
00435 count = 1;
00436 lastbyte = c;
00437 }
00438
00439 }
00440 if ( count > 1 || lastbyte >= 192 ) {
00441 char d = 192 + count;
00442 stream.writeChar ( d );
00443 fsize += sizeof ( d );
00444 }
00445 char lstbyte = lastbyte;
00446 stream.writeChar ( lstbyte );
00447 fsize += sizeof ( lstbyte );
00448
00449 }
00450
00451 if ( header.nplanes == 1 ) {
00452 char d = 12;
00453 stream.writeChar ( d );
00454 fsize += sizeof ( d );
00455
00456 dacpalette256 pal2;
00457
00458 for ( int i = 0; i < 3; i++ )
00459 for ( int j = 0; j < 256; j++ )
00460 pal2[j][i] = pal[j][i] << 2;
00461
00462 stream.writedata ( &pal2, 768 );
00463 fsize += 768 ;
00464 }
00465 stream.seek ( 0 );
00466 header.size = fsize;
00467 header.write ( &stream );
00468 }