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

Last change on this file since 90 was 56, checked in by Sam Hocevar, 12 years ago
  • Add licensing terms to most C / C++ files (Ref #5).
File size: 14.2 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#include "main.hpp"
24#include "macs.hpp"
25#include "image24.hpp"
26
27#define MAXCOLORS 256 
28//#define MC(x) (((x)<3)==0)
29#define MC(x) (x!=0)
30
31// the following table converts rgb to cym.
32int ca[8]={1,1,1,1,0,0,0,0},
33    ma[8]={1,0,1,0,1,0,1,0},
34    ya[8]={1,1,0,0,1,1,0,0};
35// the following defines make a color threshold
36#define RGB2C(r,g,b) (char)(ca[MC(b)|MC(g)<<1|MC(r)<<2])
37#define RGB2Y(r,g,b) (char)(ya[MC(b)|MC(g)<<1|MC(r)<<2])
38#define RGB2M(r,g,b) (char)(ma[MC(b)|MC(g)<<1|MC(r)<<2])
39
40#define LSBFirst        0
41#define MSBFirst        1
42
43#define XYBitmap        0
44#define XYPixmap        1
45#define ZPixmap         2
46
47#define StaticGray      0
48#define GrayScale       1
49#define StaticColor     2
50#define PseudoColor     3
51#define TrueColor       4
52#define DirectColor     5
53
54typedef unsigned long xwdval;
55#define X11WD_FILE_VERSION 7
56typedef struct {
57    xwdval header_size;         /* Size of the entire file header (bytes). */
58    xwdval file_version;        /* X11WD_FILE_VERSION */
59    xwdval pixmap_format;       /* Pixmap format */
60    xwdval pixmap_depth;        /* Pixmap depth */
61    xwdval pixmap_width;        /* Pixmap width */
62    xwdval pixmap_height;       /* Pixmap height */
63    xwdval xoffset;             /* Bitmap x offset */
64    xwdval byte_order;          /* MSBFirst, LSBFirst */
65    xwdval bitmap_unit;         /* Bitmap unit */
66    xwdval bitmap_bit_order;    /* MSBFirst, LSBFirst */
67    xwdval bitmap_pad;          /* Bitmap scanline pad */
68    xwdval bits_per_pixel;      /* Bits per pixel */
69    xwdval bytes_per_line;      /* Bytes per scanline */
70    xwdval visual_class;        /* Class of colormap */
71    xwdval red_mask;            /* Z red mask */
72    xwdval green_mask;          /* Z green mask */
73    xwdval blue_mask;           /* Z blue mask */
74    xwdval bits_per_rgb;        /* Log base 2 of distinct color values */
75    xwdval colormap_entries;    /* Number of entries in colormap */
76    xwdval ncolors;             /* Number of Color structures */
77    xwdval window_width;        /* Window width */
78    xwdval window_height;       /* Window height */
79    long window_x;              /* Window upper left X coordinate */
80    long window_y;              /* Window upper left Y coordinate */
81    xwdval window_bdrwidth;     /* Window border width */
82    } X11WDFileHeader;
83
84typedef struct {
85    unsigned long pixel;
86    unsigned short red, green, blue;
87    char flags;                 /* do_red, do_green, do_blue */
88    char pad;
89    } X11XColor;
90
91image *getinit(FILE *file, palette *&pal, int *padrightP);
92void getimage(FILE *file,image *image, int pad);
93int getpixnum(FILE *file);
94
95
96image *readxwd(char *input_file,palette *&pal)
97//char *hdfpal,int *palsize,int *cols,int *rows)
98{
99  FILE *ifd;
100  int padright;
101  image *im;
102#ifdef __WINDOWS
103   HCURSOR OldCur;
104   OldCur=SetCursor(LoadCursor(0,IDC_WAIT)); // set the cursor to the hour glass
105#endif
106  /* open input file */
107  if (strcmp(input_file,"-") == 0)
108    ifd = stdin;
109  else
110    ifd = fopen(input_file,"rb");
111  /* get X info from file */
112  if (!ifd)
113  {
114#ifndef __WINDOWS   
115    printf("Unable to open %s\n"
116           "Get your story strait and try again.\n",input_file);
117    exit(0);
118#endif
119  }
120  im=getinit( ifd, pal, &padright);
121//cols, rows, &padright, palsize, hdfpal);
122
123  /* alloc image array */
124
125  /* fill image array */
126  getimage(ifd, im, padright);
127#ifdef __WINDOWS
128   SetCursor(OldCur); // set the cursor to the hour glass
129#endif
130
131  return(im);
132}
133
134int bits_per_item, bits_used, bit_shift, bits_per_pixel, pixel_mask;
135int bit_order, byte_swap;
136char buf[4];
137uint8_t *byteP;
138uint16_t *shortP;
139uint32_t *longP;
140
141
142uint32_t bs_uint32(uint32_t s);
143uint16_t bs_uint16(uint16_t s );
144
145
146image *getinit(FILE *file, palette *&pal, int *padrightP)
147{
148  /* Assume X11 headers are larger than X10 ones. */
149  uint8_t header[sizeof(X11WDFileHeader)];
150  image *im;
151  X11WDFileHeader *h11P;
152  char junk[800];
153  unsigned int i;
154  int dummy1, dummy2, dummy3;
155  uint16_t minred, maxred;
156  X11XColor x11col;
157
158  h11P = (X11WDFileHeader *) header;
159
160  if (fread(header,sizeof(*h11P),1,file) != 1 )
161    {
162      fprintf(stderr,"couldn't read X11 XWD file header");
163      exit(-1);
164    }
165  if ( h11P->file_version != X11WD_FILE_VERSION )
166    {
167      byte_swap = 1;
168      h11P->file_version = bltl(h11P->file_version);
169      if (h11P->file_version != X11WD_FILE_VERSION)
170      {
171        set_error(imINCORRECT_FILETYPE);
172        return NULL;
173      }
174
175      h11P->header_size = bltl(h11P->header_size);
176      h11P->file_version = bltl(h11P->file_version);
177      h11P->pixmap_format = bltl(h11P->pixmap_format);
178      h11P->pixmap_depth = bltl(h11P->pixmap_depth);
179      h11P->pixmap_width = bltl(h11P->pixmap_width);
180      h11P->pixmap_height = bltl(h11P->pixmap_height);
181      h11P->xoffset =  bltl(h11P->xoffset);
182      h11P->byte_order =  bltl(h11P->byte_order);
183      h11P->bitmap_unit = bltl(h11P->bitmap_unit);
184      h11P->bitmap_bit_order = bltl(h11P->bitmap_bit_order);
185      h11P->bitmap_pad = bltl(h11P->bitmap_pad);
186      h11P->bits_per_pixel = bltl(h11P->bits_per_pixel);
187      h11P->bytes_per_line = bltl(h11P->bytes_per_line);
188      h11P->visual_class = bltl(h11P->visual_class);
189      h11P->red_mask = bltl(h11P->red_mask);
190      h11P->green_mask = bltl(h11P->green_mask);
191      h11P->blue_mask = bltl(h11P->blue_mask);
192      h11P->bits_per_rgb = bltl(h11P->bits_per_rgb);
193      h11P->colormap_entries = bltl(h11P->colormap_entries);
194      h11P->ncolors = bltl(h11P->ncolors);
195      h11P->window_width = bltl(h11P->window_width);
196      h11P->window_height = bltl(h11P->window_height);
197      h11P->window_x = bltl(h11P->window_x);
198      h11P->window_y = bltl(h11P->window_y);
199      h11P->window_bdrwidth = bltl(h11P->window_bdrwidth);
200    }
201
202  if ( fread( junk, 1, h11P->header_size - sizeof(*h11P), file ) !=
203      h11P->header_size - sizeof(*h11P) )
204    {
205      fclose(file);
206      set_error(imFILE_CORRUPTED);
207      return NULL;
208    }
209
210  /* Check whether we can handle this dump. */
211  if ( h11P->pixmap_depth > 8 )
212    {
213      fclose(file);
214      set_error(imNOT_SUPPORTED);
215      return NULL;
216    }
217  if ( h11P->bits_per_rgb > 8 )
218    {
219      fclose(file);
220      set_error(imNOT_SUPPORTED);
221      return NULL;
222    }
223  if ( h11P->ncolors > MAXCOLORS )
224    {
225      fclose(file);
226      set_error(imNOT_SUPPORTED);
227      return NULL;
228    }
229  if ( h11P->pixmap_format != ZPixmap )
230    {
231      fclose(file);
232      set_error(imNOT_SUPPORTED);
233      return NULL;
234    }
235  if ( h11P->bitmap_unit != 8 && h11P->bitmap_unit != 16 &&
236      h11P->bitmap_unit != 32 )
237    {
238      fclose(file);
239      set_error(imNOT_SUPPORTED);
240      return NULL;
241    }
242  im=new image(h11P->pixmap_width,h11P->pixmap_height);
243  pal=new palette(h11P->colormap_entries);
244  *padrightP = h11P->bytes_per_line * 8 / h11P->bits_per_pixel - im->width();
245
246/*****************************************************************************/
247  /* Read X11 colormap. */
248minred = 65535;
249maxred = 0;
250  for ( i = 0; i < h11P->colormap_entries; i++ )
251    {
252      if ( fread( &x11col, sizeof(X11XColor), 1, file ) != 1 )
253        {
254          fclose(file);
255          set_error(imFILE_CORRUPTED);
256          delete pal;
257          return NULL;
258        }
259        else
260        {
261          x11col.pixel=bltl(x11col.pixel);
262          x11col.red=bstl(x11col.red);
263          x11col.green=bstl(x11col.green);
264          x11col.blue=bstl(x11col.blue);
265        }
266      if (x11col.pixel < 256)
267        {
268          if (minred > x11col.red) minred = x11col.red;
269          if (maxred < x11col.red) maxred = x11col.red;
270          dummy1 = (unsigned) x11col.red>>8;
271          dummy2 = (unsigned) x11col.green>>8;
272          dummy3 = (unsigned) x11col.blue>>8;
273          pal->set(i,dummy1,dummy2,dummy3);
274        }
275      else
276        {
277          fprintf(stderr,"pixel value outside of valid HDF palette\n");
278          exit(-1);
279        }
280    }
281  /* rest of stuff for getpixnum */
282  bits_per_item = h11P->bitmap_unit;
283  bits_used = bits_per_item;
284  bits_per_pixel = h11P->bits_per_pixel;
285  bit_order = h11P->bitmap_bit_order;
286  pixel_mask = ( 1 << bits_per_pixel ) - 1;
287
288  byteP = (uint8_t *) buf;
289  shortP = (uint16_t *) buf;
290  longP = (uint32_t *) buf;
291  return im;
292}
293
294void getimage(FILE *file,image *im,int pad)
295{
296  int i,j;
297  uint8_t *sl;
298#if BYTE_ORDER!=BIG_ENDIAN
299  printf("little guys\n");
300#endif
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 *)jmalloc(bytes,"xwd_read scrap");
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  jfree(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.