source: abuse/branches/pd/macabuse/imlib/xwdread.c @ 161

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