source: abuse/branches/pd/imlib/xwdread.c @ 608

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