Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

loadpcxc.cpp

Go to the documentation of this file.
00001 
00008 /*
00009     This file is part of Advanced Strategic Command; http://www.asc-hq.de
00010     Copyright (C) 1994-2005  Martin Bickel  and  Marc Schellenberger
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; see the file COPYING. If not, write to the
00024     Free Software Foundation, Inc., 59 Temple Place, Suite 330,
00025     Boston, MA  02111-1307  USA
00026 */
00027 
00028 #include <stdio.h>
00029 #include <cstring>
00030 
00031 #include "basestrm.h"
00032 // #include "basegfx.h"
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;            // patch to be able to read pcx files without seeking
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();            // patch to be able to read pcx files without seeking
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 );            // patch to be able to read pcx files without seeking
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    // int m = y * agmp-> scanlinelength * agmp->byteperpix + x;
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    // int totalbytes = header.nplanes * header.bytesperline;
00179 
00180 
00181    int ttlbytes = 0;
00182    int xpos = 0;
00183    int planenum = 0;
00184 
00185    int byteperpix = agmp->byteperpix;
00186 
00187 
00188    // some simple buffering
00189    char* buf = new char[header.size];
00190    // int bufdata =
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       } /* endwhile */
00232 
00233    } /* endwhile */
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          while ( read < dataend ) {
00241             char scratch[100];
00242             int datalength;
00243             if ( 100 > dataend - read )
00244                datalength = dataend - read;
00245             else
00246                datalength = 100;
00247             stream->readdata ( scratch, datalength );
00248             read+= datalength;;
00249          }
00250          */
00251       }    
00252 
00253       char c = buf[actpos++];
00254       if ( c == 12 ) {
00255          dacpalette256 pal;
00256          memcpy ( pal, &buf[actpos], sizeof ( pal ));
00257          // stream->readdata ( pal, sizeof ( pal ) );
00258          for ( int i = 0; i < 3; i++ )
00259             for ( int j = 0; j < 256; j++ )
00260                pal[j][i] >>= 2;
00261          // setvgapalette256 ( pal );
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 //   header.bytesperline = ((header.xmax - header.xmin) + 1) & 0xFFFE;
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 ); // endian ok !!!
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 //   header.bytesperline = ((header.xmax - header.xmin) + 1) & 0xFFFE;
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 ); // endian ok !!!
00463          fsize += 768 ;
00464       }
00465       stream.seek ( 0 );
00466       header.size = fsize;
00467       header.write ( &stream );
00468 }

Generated on Tue Jun 24 01:27:44 2008 for Advanced Strategic Command by  doxygen 1.4.2