source: abuse/trunk/src/imlib/xwdread.cpp @ 129

Last change on this file since 129 was 129, checked in by Sam Hocevar, 14 years ago
  • Get rid of jmalloc and replace it with standard malloc. Modern operating systems certainly perform a lot better than this custom implementation, and we have superior tools (eg. valgrind) to debug and profile memory usage without interfering with the code itself.
File size: 14.4 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *
5 *  This software was released into the Public Domain. As with most public
6 *  domain software, no warranty is made or implied by Crack dot Com or
7 *  Jonathan Clark.
8 */
9
10#include "config.h"
11
12#include <stdio.h>
13
14/* readxwd.c */
15/* This program is limited to X11 format XWD files */
16#include "filter.hpp"
17#include "system.h"
18#include "image.hpp"
19#include "palette.hpp"
20#include "event.hpp"
21#include "video.hpp"
22#include "dos.h"
23#ifndef __APPLE__
24#include "main.hpp"
25#endif
26#include "macs.hpp"
27#include "image24.hpp"
28
29#define MAXCOLORS 256
30//#define MC(x) (((x)<3)==0)
31#define MC(x) (x!=0)
32
33// the following table converts rgb to cym.
34int ca[8]={1,1,1,1,0,0,0,0},
35    ma[8]={1,0,1,0,1,0,1,0},
36    ya[8]={1,1,0,0,1,1,0,0};
37// the following defines make a color threshold
38#define RGB2C(r,g,b) (char)(ca[MC(b)|MC(g)<<1|MC(r)<<2])
39#define RGB2Y(r,g,b) (char)(ya[MC(b)|MC(g)<<1|MC(r)<<2])
40#define RGB2M(r,g,b) (char)(ma[MC(b)|MC(g)<<1|MC(r)<<2])
41
42#define LSBFirst    0
43#define MSBFirst    1
44
45#define XYBitmap    0
46#define XYPixmap    1
47#define ZPixmap        2
48
49#define StaticGray    0
50#define GrayScale    1
51#define StaticColor    2
52#define PseudoColor    3
53#define TrueColor    4
54#define DirectColor    5
55
56typedef unsigned long xwdval;
57#define X11WD_FILE_VERSION 7
58typedef struct {
59    xwdval header_size;        /* Size of the entire file header (bytes). */
60    xwdval file_version;    /* X11WD_FILE_VERSION */
61    xwdval pixmap_format;    /* Pixmap format */
62    xwdval pixmap_depth;    /* Pixmap depth */
63    xwdval pixmap_width;    /* Pixmap width */
64    xwdval pixmap_height;    /* Pixmap height */
65    xwdval xoffset;        /* Bitmap x offset */
66    xwdval byte_order;        /* MSBFirst, LSBFirst */
67    xwdval bitmap_unit;        /* Bitmap unit */
68    xwdval bitmap_bit_order;    /* MSBFirst, LSBFirst */
69    xwdval bitmap_pad;        /* Bitmap scanline pad */
70    xwdval bits_per_pixel;    /* Bits per pixel */
71    xwdval bytes_per_line;    /* Bytes per scanline */
72    xwdval visual_class;    /* Class of colormap */
73    xwdval red_mask;        /* Z red mask */
74    xwdval green_mask;        /* Z green mask */
75    xwdval blue_mask;        /* Z blue mask */
76    xwdval bits_per_rgb;    /* Log base 2 of distinct color values */
77    xwdval colormap_entries;    /* Number of entries in colormap */
78    xwdval ncolors;        /* Number of Color structures */
79    xwdval window_width;    /* Window width */
80    xwdval window_height;    /* Window height */
81    long window_x;        /* Window upper left X coordinate */
82    long window_y;        /* Window upper left Y coordinate */
83    xwdval window_bdrwidth;    /* Window border width */
84    } X11WDFileHeader;
85
86typedef struct {
87    unsigned long pixel;
88    unsigned short red, green, blue;
89    char flags;            /* do_red, do_green, do_blue */
90    char pad;
91    } X11XColor;
92
93image *getinit(FILE *file, palette *&pal, int *padrightP);
94void getimage(FILE *file,image *image, int pad);
95int getpixnum(FILE *file);
96
97
98image *readxwd(char *input_file,palette *&pal)
99//char *hdfpal,int *palsize,int *cols,int *rows)
100{
101  FILE *ifd;
102  int padright;
103  image *im;
104#ifdef __WINDOWS
105   HCURSOR OldCur;
106   OldCur=SetCursor(LoadCursor(0,IDC_WAIT)); // set the cursor to the hour glass
107#endif
108  /* open input file */
109  if (strcmp(input_file,"-") == 0)
110    ifd = stdin;
111  else
112    ifd = fopen(input_file,"rb");
113  /* get X info from file */
114  if (!ifd)
115  {
116#ifndef __WINDOWS
117    printf("Unable to open %s\n"
118       "Get your story strait and try again.\n",input_file);
119    exit(0);
120#endif
121  }
122  im=getinit( ifd, pal, &padright);
123//cols, rows, &padright, palsize, hdfpal);
124
125  /* alloc image array */
126
127  /* fill image array */
128  getimage(ifd, im, padright);
129#ifdef __WINDOWS
130   SetCursor(OldCur); // set the cursor to the hour glass
131#endif
132
133  return(im);
134}
135
136int bits_per_item, bits_used, bit_shift, bits_per_pixel, pixel_mask;
137int bit_order, byte_swap;
138char buf[4];
139uint8_t *byteP;
140uint16_t *shortP;
141uint32_t *longP;
142
143
144uint32_t bs_uint32(uint32_t s);
145uint16_t bs_uint16(uint16_t s );
146
147
148image *getinit(FILE *file, palette *&pal, int *padrightP)
149{
150  /* Assume X11 headers are larger than X10 ones. */
151  uint8_t header[sizeof(X11WDFileHeader)];
152  image *im;
153  X11WDFileHeader *h11P;
154  char junk[800];
155  unsigned int i;
156  int dummy1, dummy2, dummy3;
157  uint16_t minred, maxred;
158  X11XColor x11col;
159
160  h11P = (X11WDFileHeader *) header;
161
162  if (fread(header,sizeof(*h11P),1,file) != 1 )
163    {
164      fprintf(stderr,"couldn't read X11 XWD file header");
165      exit(-1);
166    }
167  if ( h11P->file_version != X11WD_FILE_VERSION )
168    {
169      byte_swap = 1;
170      h11P->file_version = bltl(h11P->file_version);
171      if (h11P->file_version != X11WD_FILE_VERSION)
172      {
173        set_error(imINCORRECT_FILETYPE);
174        return NULL;
175      }
176
177      h11P->header_size = bltl(h11P->header_size);
178      h11P->file_version = bltl(h11P->file_version);
179      h11P->pixmap_format = bltl(h11P->pixmap_format);
180      h11P->pixmap_depth = bltl(h11P->pixmap_depth);
181      h11P->pixmap_width = bltl(h11P->pixmap_width);
182      h11P->pixmap_height = bltl(h11P->pixmap_height);
183      h11P->xoffset =  bltl(h11P->xoffset);
184      h11P->byte_order =  bltl(h11P->byte_order);
185      h11P->bitmap_unit = bltl(h11P->bitmap_unit);
186      h11P->bitmap_bit_order = bltl(h11P->bitmap_bit_order);
187      h11P->bitmap_pad = bltl(h11P->bitmap_pad);
188      h11P->bits_per_pixel = bltl(h11P->bits_per_pixel);
189      h11P->bytes_per_line = bltl(h11P->bytes_per_line);
190      h11P->visual_class = bltl(h11P->visual_class);
191      h11P->red_mask = bltl(h11P->red_mask);
192      h11P->green_mask = bltl(h11P->green_mask);
193      h11P->blue_mask = bltl(h11P->blue_mask);
194      h11P->bits_per_rgb = bltl(h11P->bits_per_rgb);
195      h11P->colormap_entries = bltl(h11P->colormap_entries);
196      h11P->ncolors = bltl(h11P->ncolors);
197      h11P->window_width = bltl(h11P->window_width);
198      h11P->window_height = bltl(h11P->window_height);
199      h11P->window_x = bltl(h11P->window_x);
200      h11P->window_y = bltl(h11P->window_y);
201      h11P->window_bdrwidth = bltl(h11P->window_bdrwidth);
202    }
203
204  if ( fread( junk, 1, h11P->header_size - sizeof(*h11P), file ) !=
205      h11P->header_size - sizeof(*h11P) )
206    {
207      fclose(file);
208      set_error(imFILE_CORRUPTED);
209      return NULL;
210    }
211
212  /* Check whether we can handle this dump. */
213  if ( h11P->pixmap_depth > 8 )
214    {
215      fclose(file);
216      set_error(imNOT_SUPPORTED);
217      return NULL;
218    }
219  if ( h11P->bits_per_rgb > 8 )
220    {
221      fclose(file);
222      set_error(imNOT_SUPPORTED);
223      return NULL;
224    }
225  if ( h11P->ncolors > MAXCOLORS )
226    {
227      fclose(file);
228      set_error(imNOT_SUPPORTED);
229      return NULL;
230    }
231  if ( h11P->pixmap_format != ZPixmap )
232    {
233      fclose(file);
234      set_error(imNOT_SUPPORTED);
235      return NULL;
236    }
237  if ( h11P->bitmap_unit != 8 && h11P->bitmap_unit != 16 &&
238      h11P->bitmap_unit != 32 )
239    {
240      fclose(file);
241      set_error(imNOT_SUPPORTED);
242      return NULL;
243    }
244  im=new image(h11P->pixmap_width,h11P->pixmap_height);
245  pal=new palette(h11P->colormap_entries);
246  *padrightP = h11P->bytes_per_line * 8 / h11P->bits_per_pixel - im->width();
247
248/*****************************************************************************/
249  /* Read X11 colormap. */
250minred = 65535;
251maxred = 0;
252  for ( i = 0; i < h11P->colormap_entries; i++ )
253    {
254      if ( fread( &x11col, sizeof(X11XColor), 1, file ) != 1 )
255    {
256          fclose(file);
257          set_error(imFILE_CORRUPTED);
258          delete pal;
259          return NULL;
260    }
261    else
262    {
263      x11col.pixel=bltl(x11col.pixel);
264      x11col.red=bstl(x11col.red);
265      x11col.green=bstl(x11col.green);
266      x11col.blue=bstl(x11col.blue);
267    }
268      if (x11col.pixel < 256)
269    {
270      if (minred > x11col.red) minred = x11col.red;
271      if (maxred < x11col.red) maxred = x11col.red;
272      dummy1 = (unsigned) x11col.red>>8;
273      dummy2 = (unsigned) x11col.green>>8;
274      dummy3 = (unsigned) x11col.blue>>8;
275      pal->set(i,dummy1,dummy2,dummy3);
276    }
277      else
278    {
279      fprintf(stderr,"pixel value outside of valid HDF palette\n");
280      exit(-1);
281    }
282    }
283  /* rest of stuff for getpixnum */
284  bits_per_item = h11P->bitmap_unit;
285  bits_used = bits_per_item;
286  bits_per_pixel = h11P->bits_per_pixel;
287  bit_order = h11P->bitmap_bit_order;
288  pixel_mask = ( 1 << bits_per_pixel ) - 1;
289
290  byteP = (uint8_t *) buf;
291  shortP = (uint16_t *) buf;
292  longP = (uint32_t *) buf;
293  return im;
294}
295
296void getimage(FILE *file,image *im,int pad)
297{
298  int i,j;
299  uint8_t *sl;
300
301  printf("getting image, bits_per_item = %d %d %d\n",bits_per_item,bits_used,bit_order==MSBFirst);
302  for (i=0; i<im->height(); i++)
303    {
304      sl=im->scan_line(i);
305      for (j=0; j<im->width(); j++)
306    sl[j]= getpixnum(file);
307
308      for ( j = 0; j < pad; j++ )
309    getpixnum( file );
310    }
311}
312
313
314int getpixnum(FILE *file)
315{
316  int p=0;
317  if ( bits_used == bits_per_item )
318    {
319      if ( fread( buf, bits_per_item / 8, 1, file ) != 1 )
320    fprintf(stderr, "couldn't read bits" );
321      if ( byte_swap )
322    switch ( bits_per_item )
323      {
324      case 8:
325        break;
326
327      case 16: *shortP=uint16_swap(*shortP); break;
328
329      case 32: *longP=uint32_swap(*longP); break;
330
331      default:
332        fprintf(stderr, "can't happen" );
333      }
334      bits_used = 0;
335
336//      if ( bit_order == MSBFirst )
337    bit_shift = bits_per_item - bits_per_pixel;
338//      else
339//    bit_shift = 0;
340    }
341
342  switch ( bits_per_item )
343    {
344    case 8:
345      p = ( *byteP >> bit_shift) & pixel_mask;
346      break;
347
348    case 16:
349      p = ( *shortP >> bit_shift) & pixel_mask;
350      break;
351
352    case 32:
353      p = ( *longP >> bit_shift) & pixel_mask;
354      break;
355
356    default:
357      fprintf(stderr, "can't happen" );
358    }
359
360//  if ( bit_order == MSBFirst )
361    bit_shift -= bits_per_pixel;
362//  else
363//    bit_shift += bits_per_pixel;
364  bits_used += bits_per_pixel;
365
366  return p;
367}
368
369
370uint16_t bs_uint16(uint16_t s )
371{
372  uint16_t ss;
373  uint8_t *bp, t;
374
375  ss = s;
376  bp = (uint8_t *) &ss;
377  t = bp[0];
378  bp[0] = bp[1];
379  bp[1] = t;
380  return ss;
381}
382
383uint32_t bs_uint32(uint32_t l )
384{
385  uint32_t ii;
386  uint8_t *bp, t;
387
388  ii = l;
389  bp = (uint8_t *) &ii;
390  t = bp[0];
391  bp[0] = bp[3];
392  bp[3] = t;
393  t = bp[1];
394  bp[1] = bp[2];
395  bp[2] = t;
396  return ii;
397}
398
399struct BMP_header
400{
401  char id[2];
402  long filesize;
403  int16_t reserved[2];
404  long headersize,infosize,width,height;
405  int16_t biplanes,bits;
406  long bicompression, bisizeimage, bixpelspermeter, biypelspermeter,
407       biclrused,biclrimportant;
408} bmp;
409
410int read_BMP_header(FILE *fp)
411{
412  if (!fread(&bmp.id,1,2,fp)) return 0;         // 2 0
413  bmp.filesize=read_uint32(fp);                   // 4 4
414  if (!fread(bmp.reserved,1,4,fp)) return 0;    // 4 8
415  bmp.headersize=read_uint32(fp);                 // 4 12
416  bmp.infosize=read_uint32(fp);                   // 4 16
417  bmp.width=read_uint32(fp);                      // 4 20
418  bmp.height=read_uint32(fp);                     // 4 24
419  bmp.biplanes=read_uint16(fp);                  // 2 26
420  bmp.bits=read_uint16(fp);                      // 2 28
421  bmp.bicompression=read_uint32(fp);              // 4 32
422  bmp.bisizeimage=read_uint32(fp);                // 4 36
423  bmp.bixpelspermeter=read_uint32(fp);            // 4 40
424  bmp.biypelspermeter=read_uint32(fp);            // 4 44
425  bmp.biclrused=read_uint32(fp);                  // 4 48
426  bmp.biclrimportant=read_uint32(fp);             // 4 52
427  return 1;
428
429}
430
431
432
433
434int bmp_bits(char *filename)
435{
436  FILE *fp;
437  fp=fopen(filename,"rb");
438  if (!fp) return 0;
439  if (!read_BMP_header(fp)) return 0;
440  fclose(fp);
441
442  if (bmp.id[0]!='B' || bmp.id[1]!='M')
443    return 0;
444  else return bmp.bits;
445}
446
447image24 *read_bmp24(char *filename)
448{
449  image24 *im;
450  FILE *fp;
451  int i,j;
452  fp=fopen(filename,"rb");
453  if (!fp)
454    return NULL;
455  if (!read_BMP_header(fp)) return NULL;
456
457  if (bmp.id[0]!='B' || bmp.id[1]!='M')
458    return NULL;
459
460  if (bmp.bits!=24)
461    return NULL;
462
463  im=new image24((bmp.width+3)&(0xffffffff-3),
464         (bmp.height+3)&0xffffffff-3);
465  if (!im)
466    return NULL;
467
468  uint8_t *sl;
469  int trailer=im->width()%4;
470  if (trailer==1) trailer=3;
471  else if (trailer==3) trailer=1;
472  uint8_t buf[9];
473  for (i=im->height();i;i--)
474  {
475    sl=im->scan_line(i-1);
476    for (j=0;j<im->width();j++)
477    {
478      fread(sl+2,1,1,fp);
479      fread(sl+1,1,1,fp);
480      fread(sl,1,1,fp);
481      sl+=3;
482    }
483    if (trailer)
484      fread(buf,trailer*3,1,fp);
485  }
486  fclose(fp);
487
488  return im;
489}
490
491image *read_bmp(palette *&pal, char *filename)
492{
493  image *im;
494  FILE *fp;
495  uint8_t pal_quad[4];
496  char *scrap;
497  int bytes,i;
498  fp=fopen(filename,"rb");
499  if (!fp)
500    return NULL;
501
502  if (!read_BMP_header(fp)) return NULL;
503
504  if (bmp.id[0]!='B' || bmp.id[1]!='M')
505    return NULL;
506
507  if (bmp.bits!=8)
508    return NULL;
509
510  im=new image((bmp.width+3)&(0xffffffff-3),
511         (bmp.height+3)&0xffffffff-3);
512
513  if (!im)
514    return NULL;
515
516  pal=new palette(256);
517  for (i=0;i<256;i++)
518  {
519    fread(pal_quad,1,4,fp);
520    pal->set(i,pal_quad[2],pal_quad[1],pal_quad[0]);
521  }
522  bytes=(im->width()+3)/4;
523  bytes*=4;
524  scrap=(char *)malloc(bytes);
525  for (i=im->height();i;i--)
526  {
527    fread(scrap,1,bytes,fp);
528    memcpy(im->scan_line(i-1),scrap,im->width());
529  }
530  free(scrap);
531  fclose(fp);
532  return im;
533}
534
535int write_BMP_header(FILE *fp)
536{
537  if (!fwrite(&bmp.id,1,2,fp)) return 0;
538  write_uint32(fp,bmp.filesize);
539  if (!fwrite(bmp.reserved,1,4,fp)) return 0;
540  write_uint32(fp,bmp.headersize);
541  write_uint32(fp,bmp.infosize);
542  write_uint32(fp,bmp.width);
543  write_uint32(fp,bmp.height);
544  write_uint16(fp,bmp.biplanes);
545  write_uint16(fp,bmp.bits);
546  write_uint32(fp,bmp.bicompression);
547  write_uint32(fp,bmp.bisizeimage);
548  write_uint32(fp,bmp.bixpelspermeter);
549  write_uint32(fp,bmp.biypelspermeter);
550  write_uint32(fp,bmp.biclrused);
551  write_uint32(fp,bmp.biclrimportant);
552  return 1;
553
554}
555
556void write_bmp(image *im, palette *pal, char *filename)
557{
558  FILE *fp;
559  int i,bytes;
560  uint8_t pal_quad[4];
561  fp=fopen(filename,"wb");
562  if (!fp)
563  { printf("Error : unable to open %s for writing!\n",filename);
564    exit(0);
565  }
566  bytes=(im->width()+3)/4;
567  memset((char *)&bmp,0,sizeof(bmp));
568  memcpy(bmp.id,"BM",2);
569  bmp.width=im->width();
570  bmp.height=im->height();
571  bmp.bits=8;
572  bmp.infosize=0x28L;
573  bmp.biplanes=1;
574  bmp.headersize=1078;
575  bmp.filesize=bmp.headersize+bytes*im->height()*4;
576  bmp.bisizeimage=im->width()*im->height();
577  bmp.biclrused=256;
578  bmp.biclrimportant=256;
579  write_BMP_header(fp);
580
581  pal_quad[3]=0;
582  for (i=0;i<256;i++)
583  {
584    pal->get(i,pal_quad[2],pal_quad[1],pal_quad[0]);
585    fwrite(pal_quad,1,4,fp);
586  }
587  for (i=im->height();i;i--)
588    fwrite(im->scan_line(i-1),1,bytes*4,fp);
589  fclose(fp);
590}
591
592
Note: See TracBrowser for help on using the repository browser.