Advanced Strategic Command
loadpcxc.cpp
Go to the documentation of this file.
1 
8 /*
9  This file is part of Advanced Strategic Command; http://www.asc-hq.de
10  Copyright (C) 1994-2010 Martin Bickel and Marc Schellenberger
11 
12  This program is free software; you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation; either version 2 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; see the file COPYING. If not, write to the
24  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
25  Boston, MA 02111-1307 USA
26 */
27 
28 #include <stdio.h>
29 #include <cstring>
30 
31 #include "basestrm.h"
32 // #include "basegfx.h"
33 #include "misc.h"
34 #include "loadpcx.h"
35 
36 #pragma pack(1)
37 
38 struct tpcxheader{
39  Uint8 manufacturer;
40  Uint8 version ;
41  Uint8 encoding ;
42  Uint8 bitsperpixel;
43  Uint16 xmin,ymin ;
44  Uint16 xmax,ymax ;
45  Uint16 hdpi,vdpi ;
46  Uint8 colormap[48];
47  Uint8 reserved ;
48  Uint8 nplanes ;
49  Uint16 bytesperline;
50  Uint16 paletteinfo ;
51  Uint16 hscreensize ;
52  Uint16 vscreensize ;
53  Uint8 dummy[50] ;
54  int size; // patch to be able to read pcx files without seeking
55 
56  void read ( tnstream* stream );
57  void write ( tnstream* stream );
58  };
59 
60 void tpcxheader::read ( tnstream* stream )
61 {
62  manufacturer = stream->readUint8();
63  version = stream->readUint8();
64  encoding = stream->readUint8();
65  bitsperpixel = stream->readUint8();
66  xmin = stream->readWord();
67  ymin = stream->readWord();
68  xmax = stream->readWord();
69  ymax = stream->readWord();
70  hdpi = stream->readWord();
71  vdpi = stream->readWord();
72  stream->readdata ( colormap, 48);
73  reserved = stream->readUint8();
74  nplanes = stream->readUint8();
75  bytesperline= stream->readWord();
76  paletteinfo = stream->readWord();
77  hscreensize = stream->readWord();
78  vscreensize = stream->readWord();
79  stream->readdata ( dummy, 50 ) ;
80  size = stream->readInt(); // patch to be able to read pcx files without seeking
81 }
82 
83 void tpcxheader::write ( tnstream* stream )
84 {
85  stream->writeUint8( manufacturer );
86  stream->writeUint8( version );
87  stream->writeUint8( encoding );
88  stream->writeUint8( bitsperpixel );
89  stream->writeWord( xmin );
90  stream->writeWord( ymin );
91  stream->writeWord( xmax );
92  stream->writeWord( ymax );
93  stream->writeWord( hdpi );
94  stream->writeWord( vdpi );
95  stream->writedata ( colormap, 48);
96  stream->writeUint8( reserved );
97  stream->writeUint8( nplanes );
98  stream->writeWord( bytesperline);
99  stream->writeWord( paletteinfo );
100  stream->writeWord( hscreensize );
101  stream->writeWord( vscreensize );
102  stream->writedata ( dummy, 50 ) ;
103  stream->writeInt( size ); // patch to be able to read pcx files without seeking
104 }
105 
106 #pragma pack()
107 
108 #if 0
109 int pcxGetColorDepth ( const ASCString& filename, int* width, int* height )
110 {
111  tnfilestream stream ( filename.c_str(), tnstream::reading );
112 
113  tpcxheader header;
114  header.read ( &stream );
115 
116  if ( width )
117  *width = header.xmax - header.xmin + 1 ;
118 
119  if ( height )
120  *height = header.ymax - header.ymin + 1;
121 
122 
123  return header.nplanes * header.bitsperpixel;
124 }
125 
126 
127 Uint8 loadpcxxy( pnstream stream, int x, int y, bool setpalette, int* xsize, int* ysize )
128 {
129  int read = 0;
130 
131  // int m = y * agmp-> scanlinelength * agmp->byteperpix + x;
132 
133  tpcxheader header;
134 
135  header.read( stream );
136 
137  read += sizeof(header);
138 
139  if ( !header.size ) {
140  if ( stream->getSize() < 0 )
141  return 12;
142  else
143  header.size = stream->getSize();
144  }
145 
146  int width = header.xmax - header.xmin + 1 ;
147  int height = header.ymax - header.ymin + 1;
148  int pixels = width * height * header.nplanes;
149 
150  if ( xsize )
151  *xsize = width;
152 
153  if ( ysize )
154  *ysize = height;
155 
156  if ( header.manufacturer != 10 ||
157  header.bitsperpixel != 8 ||
158  header.xmax-header.xmin > agmp-> scanlinelength )
159  return 11;
160 
161  int colors = header.nplanes * header.bitsperpixel;
162 
163  int scanlineret[4];
164 
165  if (agmp->byteperpix > 1) {
166 
167  scanlineret[0] = agmp-> redfieldposition / 8;
168  scanlineret[1] = header.bytesperline * agmp->byteperpix - agmp->greenfieldposition / 8 + agmp-> redfieldposition / 8;
169  scanlineret[2] = header.bytesperline * agmp->byteperpix - agmp->bluefieldposition / 8 + agmp-> greenfieldposition / 8;
170  scanlineret[3] = -(agmp-> scanlinelength -
172 
173  } else {
174  scanlineret[0]=0;
175  scanlineret[1]= -(agmp->scanlinelength - header.bytesperline * agmp->byteperpix);
176  }
177 
178  // int totalbytes = header.nplanes * header.bytesperline;
179 
180 
181  int ttlbytes = 0;
182  int xpos = 0;
183  int planenum = 0;
184 
185  int byteperpix = agmp->byteperpix;
186 
187 
188  // some simple buffering
189  Uint8* buf = new Uint8[header.size];
190  // int bufdata =
191  stream->readdata ( buf, header.size - sizeof( header ));
192  int actpos = 0;
193 
194 
195  Uint8* dest = (Uint8*) (agmp->linearaddress + x * agmp->byteperpix + y * agmp->bytesperscanline + scanlineret[0]);
196  while ( pixels ) {
197  Uint8 a;
198 
199  a = buf[actpos++];
200 
201  read++;
202 
203  int count;
204  if ( a >= 192 ) {
205  count = a ^192;
206 
207  a = buf[actpos++];
208 
209  read++;
210  } else
211  count = 1;
212 
213  while ( count ) {
214  if ( xpos >= header.bytesperline ) {
215  planenum++;
216  dest -= scanlineret[planenum];
217  if ( planenum >= header.nplanes ) {
218  planenum = 0;
219  ttlbytes = 0;
220  }
221  xpos = 0;
222  }
223  if ( xpos < width ) {
224  *dest = a;
225  pixels--;
226  }
227  dest+= byteperpix;
228  xpos++;
229  ttlbytes++;
230  count--;
231  } /* endwhile */
232 
233  } /* endwhile */
234 
235  if ( setpalette && colors == 8 ) {
236  if ( header.size ) {
237  int dataend = header.size - sizeof ( dacpalette256 ) - 1 - sizeof ( header );
238  actpos = dataend;
239  /*
240  while ( read < dataend ) {
241  Uint8 scratch[100];
242  int datalength;
243  if ( 100 > dataend - read )
244  datalength = dataend - read;
245  else
246  datalength = 100;
247  stream->readdata ( scratch, datalength );
248  read+= datalength;;
249  }
250  */
251  }
252 
253  Uint8 c = buf[actpos++];
254  if ( c == 12 ) {
256  memcpy ( pal, &buf[actpos], sizeof ( pal ));
257  // stream->readdata ( pal, sizeof ( pal ) );
258  for ( int i = 0; i < 3; i++ )
259  for ( int j = 0; j < 256; j++ )
260  pal[j][i] >>= 2;
261  // setvgapalette256 ( pal );
262  }
263  }
264 
265  delete[] buf;
266  return 0;
267 }
268 
269 
270 Uint8 loadpcxxy ( const ASCString& name, bool setpal, int xpos, int ypos, int* xsize, int* ysize )
271 {
272  tnfilestream s ( name, tnstream::reading );
273  return loadpcxxy ( &s, xpos, ypos, setpal, xsize, ysize );
274 }
275 #endif
276 
277 void writepcx ( const ASCString& name, int x1, int y1, int x2, int y2, dacpalette256 pal )
278 {
279  tpcxheader header;
280  memset ( &header, 0, sizeof (header ));
281  header.manufacturer = 10;
282  header.version = 5;
283  header.encoding = 1;
284  header.bitsperpixel = 8;
285  header.xmin = 0;
286  header.xmax = x2 - x1 ;
287  header.ymin = 0;
288  header.ymax = y2 - y1 ;
289  header.hdpi = 0;
290  header.vdpi = 0;
291  if ( agmp->byteperpix == 1 )
292  header.nplanes = 1;
293  else
294  header.nplanes = 3;
295 
296 // header.bytesperline = ((header.xmax - header.xmin) + 1) & 0xFFFE;
297  header.bytesperline = x2 - x1 + 1 ;
298  if ( header.bytesperline & 1 )
299  header.bytesperline++;
300  header.paletteinfo = 1;
301 
302  int fsize = 0;
303 
304  tn_file_buf_stream stream ( name, tnstream::writing );
305 
306  header.write ( &stream );
307 
308  fsize += sizeof ( header );
309 
310  for ( int y = y1; y <= y2; y++ )
311  for ( int plane = 0; plane < header.nplanes; plane++ ) {
312  int lastbyte = -1;
313  int count = 0;
314  for ( int x = x1; x < x1 + header.bytesperline; x++ ) {
315  Uint8 c = (getpixel( x, y ) >> ( plane * 8 )) & 0xff;
316 
317  if ( (lastbyte == c && count < 63) || lastbyte == -1 ) {
318  count ++;
319  lastbyte = c;
320  }
321  else {
322  if ( count > 1 || lastbyte >= 192 ) {
323  Uint8 d = 192 + count;
324  stream.writeUint8 ( d );
325  fsize += sizeof ( d );
326  }
327  Uint8 lstbyte = lastbyte;
328  stream.writeUint8 ( lstbyte );
329  fsize += sizeof ( lstbyte );
330  count = 1;
331  lastbyte = c;
332  }
333 
334  }
335  if ( count > 1 || lastbyte >= 192 ) {
336  Uint8 d = 192 + count;
337  stream.writeUint8 ( d );
338  fsize += sizeof ( d );
339  }
340  Uint8 lstbyte = lastbyte;
341  stream.writeUint8 ( lstbyte );
342  fsize += sizeof ( lstbyte );
343 
344  }
345 
346  if ( header.nplanes == 1 ) {
347  Uint8 d = 12;
348  stream.writeUint8 ( d );
349  fsize += sizeof ( d );
350 
351  dacpalette256 pal2;
352 
353  for ( int i = 0; i < 3; i++ )
354  for ( int j = 0; j < 256; j++ )
355  pal2[j][i] = pal[j][i] << 2;
356 
357  stream.writedata ( &pal2, 768 ); // endian ok !!!
358  fsize += 768 ;
359  }
360  stream.seek ( 0 );
361  header.size = fsize;
362  header.write ( &stream );
363 }
364 
365 
366 void writepcx ( const ASCString& name, const Surface& s )
367 {
368  writepcx( name, s, SDLmm::SRect( SPoint(0,0), s.w(), s.h() ));
369 }
370 
371 void writepcx ( const ASCString& name, const Surface& s, const SDLmm::SRect& rect )
372 {
373  int x1 = rect.x;
374  int y1 = rect.y;
375  int x2 = rect.x + rect.w - 1;
376  int y2 = rect.y + rect.h - 1;
377  tpcxheader header;
378  memset ( &header, 0, sizeof (header ));
379  header.manufacturer = 10;
380  header.version = 5;
381  header.encoding = 1;
382  header.bitsperpixel = 8;
383  header.xmin = 0;
384  header.xmax = x2 - y1 ;
385  header.ymin = 0 ;
386  header.ymax = y2 - y1;
387  header.hdpi = 0;
388  header.vdpi = 0;
389  if ( s.GetPixelFormat().BitsPerPixel() == 8 )
390  header.nplanes = 1;
391  else
392  header.nplanes = 3;
393 
394 // header.bytesperline = ((header.xmax - header.xmin) + 1) & 0xFFFE;
395  header.bytesperline = x2 - x1 + 1 ;
396  if ( header.bytesperline & 1 )
397  header.bytesperline++;
398  header.paletteinfo = 1;
399 
400  int fsize = 0;
401 
402  tn_file_buf_stream stream ( name, tnstream::writing );
403 
404  header.write ( &stream );
405 
406  fsize += sizeof ( header );
407 
408  int shift[3] = { 0, 0, };
409  if ( header.nplanes > 1 ) {
410  shift[0] = s.GetPixelFormat().Rshift();
411  shift[1] = s.GetPixelFormat().Gshift();
412  shift[2] = s.GetPixelFormat().Bshift();
413  }
414 
415  for ( int y = y1; y <= y2; y++ )
416  for ( int plane = 0; plane < header.nplanes; plane++ ) {
417  int lastbyte = -1;
418  int count = 0;
419  for ( int x = x1; x < x1 + header.bytesperline; x++ ) {
420  Uint8 c = (s.GetPixel( x, y ) >> shift[plane]) & 0xff;
421 
422  if ( (lastbyte == c && count < 63) || lastbyte == -1 ) {
423  count ++;
424  lastbyte = c;
425  }
426  else {
427  if ( count > 1 || lastbyte >= 192 ) {
428  Uint8 d = 192 + count;
429  stream.writeUint8 ( d );
430  fsize += sizeof ( d );
431  }
432  Uint8 lstbyte = lastbyte;
433  stream.writeUint8 ( lstbyte );
434  fsize += sizeof ( lstbyte );
435  count = 1;
436  lastbyte = c;
437  }
438 
439  }
440  if ( count > 1 || lastbyte >= 192 ) {
441  Uint8 d = 192 + count;
442  stream.writeUint8 ( d );
443  fsize += sizeof ( d );
444  }
445  Uint8 lstbyte = lastbyte;
446  stream.writeUint8 ( lstbyte );
447  fsize += sizeof ( lstbyte );
448  }
449 
450  if ( header.nplanes == 1 ) {
451  Uint8 d = 12;
452  stream.writeUint8 ( d );
453  fsize += sizeof ( d );
454 
455  dacpalette256 pal2;
456 
457  for ( int i = 0; i < 3; i++ )
458  for ( int j = 0; j < 256; j++ )
459  pal2[j][i] = pal[j][i] << 2;
460 
461  stream.writedata ( &pal2, 768 ); // endian ok !!!
462  fsize += 768 ;
463  }
464  stream.seek ( 0 );
465  header.size = fsize;
466  header.write ( &stream );
467 }
void writepcx(const ASCString &name, int x1, int y1, int x2, int y2, dacpalette256 pal)
Definition: loadpcxc.cpp:277
Interface for loading and writing of PCX images.
virtual void writeInt(int i)
Writes a 32 bit signed Integer. In the stream little-endian byte order is used and a translation is p...
Definition: basestrm.cpp:363
miscellaneous functions which are used by ASC and all its tools
Uint16 paletteinfo
Definition: loadpcxc.cpp:50
Uint8 encoding
Definition: loadpcxc.cpp:41
void write(tnstream *stream)
Definition: loadpcxc.cpp:83
virtual int readInt(void)
Reads a 32 bit signed Integer. In the stream little-endian byte order is used and a translation is pe...
Definition: basestrm.cpp:284
Uint8 reserved
Definition: loadpcxc.cpp:47
Uint8 bluefieldposition
RGB only: the position of the first blue bit relative to the start of the pixel.
Definition: basegfx.h:70
virtual void writedata(const void *buf, int size)
writes data to the stream
virtual int readWord(void)
Reads a 16 bit unsigned Integer. In the stream little-endian byte order is used and a translation is ...
Definition: basestrm.cpp:291
The interface for all kinds of IO stream.
tgraphmodeparameters * agmp
Definition: basegfx.cpp:39
if(!yyg->yy_init)
Definition: scanner.cpp:695
virtual Uint8 readUint8(void)
Reads a 8 bit unsigned Integer.
Definition: basestrm.cpp:305
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
int getpixel(int x1, int y1)
gets the color of a single pixel from the screen. This is one of the few functions that work in truec...
Definition: basegfx.cpp:760
Uint16 xmax
Definition: loadpcxc.cpp:44
Uint8 greenfieldposition
RGB only: the position of the first green bit relative to the start of the pixel. ...
Definition: basegfx.h:68
Uint8 bitsperpixel
Definition: loadpcxc.cpp:42
Uint16 ymin
Definition: loadpcxc.cpp:43
Uint16 vdpi
Definition: loadpcxc.cpp:45
Uint8 manufacturer
Definition: loadpcxc.cpp:39
virtual void writeUint8(Uint8 c)
Writes a 8 bit unsigned Integer.
Definition: basestrm.cpp:380
PointerSizedInt linearaddress
the pointer to the actual memory (typecast to char* )
Definition: basegfx.h:63
virtual int readdata(void *buf, int size, bool excpt=true)=0
Reads data from the stream.
The interface for the various streams that ASC offers, like file and memory streams.
Uint8 version
Definition: loadpcxc.cpp:40
int byteperpix
the distance between two pixel
Definition: basegfx.h:62
SDLmm::SPoint SPoint
Definition: surface.h:27
virtual void seek(int newpos)
Sets the stream pointer to a new location. An exception is thrown if the stream does not support seek...
dacpalette256 pal
Definition: palette.cpp:33
void read(tnstream *stream)
Definition: loadpcxc.cpp:60
Uint16 vscreensize
Definition: loadpcxc.cpp:52
virtual void writeWord(int w)
Writes a 16 bit unsigned Integer. In the stream little-endian byte order is used and a translation is...
Definition: basestrm.cpp:369
Uint8 redfieldposition
RGB only: the position of the first red bit relative to the start of the pixel.
Definition: basegfx.h:66
Uint16 bytesperline
Definition: loadpcxc.cpp:49
Uint16 hdpi
Definition: loadpcxc.cpp:45
Uint8 nplanes
Definition: loadpcxc.cpp:48
int scanlinelength
the size of a line in byte (may be larger than resolutionx due to offscreen memory) ...
Definition: basegfx.h:57
Uint8 colormap[48]
Definition: loadpcxc.cpp:46
Uint8 dacpalette256[256][3]
Definition: palette.h:76
Uint16 ymax
Definition: loadpcxc.cpp:44
Uint16 xmin
Definition: loadpcxc.cpp:43
Uint16 hscreensize
Definition: loadpcxc.cpp:51
Uint8 dummy[50]
Definition: loadpcxc.cpp:53
int bytesperscanline
the size of a line in byte
Definition: basegfx.h:59
virtual void writedata(const void *buf, int size)=0
writes data to the stream