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

Last change on this file since 39 was 17, checked in by Sam Hocevar, 18 years ago
  • absolute shitloads of 64 bit fixes.
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];
125uint8_t *byteP;
126uint16_t *shortP;
127uint32_t *longP;
128
129
130uint32_t bs_uint32(uint32_t s);
131uint16_t bs_uint16(uint16_t s );
132
133
134image *getinit(FILE *file, palette *&pal, int *padrightP)
135{
136  /* Assume X11 headers are larger than X10 ones. */
137  uint8_t header[sizeof(X11WDFileHeader)];
138  image *im;
139  X11WDFileHeader *h11P;
140  char junk[800];
141  unsigned int i;
142  int dummy1, dummy2, dummy3;
143  uint16_t 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 = (uint8_t *) buf;
277  shortP = (uint16_t *) buf;
278  longP = (uint32_t *) buf;
279  return im;
280}
281
282void getimage(FILE *file,image *im,int pad)
283{
284  int i,j;
285  uint8_t *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=0;
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=uint16_swap(*shortP); break;
316
317          case 32: *longP=uint32_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
358uint16_t bs_uint16(uint16_t s )
359{
360  uint16_t ss;
361  uint8_t *bp, t;
362
363  ss = s;
364  bp = (uint8_t *) &ss;
365  t = bp[0];
366  bp[0] = bp[1];
367  bp[1] = t;
368  return ss;
369}
370
371uint32_t bs_uint32(uint32_t l )
372{
373  uint32_t ii;
374  uint8_t *bp, t;
375
376  ii = l;
377  bp = (uint8_t *) &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
387struct BMP_header
388{
389  char id[2];
390  long filesize;
391  int16_t reserved[2];
392  long headersize,infosize,width,height;
393  int16_t biplanes,bits;
394  long bicompression, bisizeimage, bixpelspermeter, biypelspermeter,
395       biclrused,biclrimportant;
396} bmp;
397
398int read_BMP_header(FILE *fp)
399{
400  if (!fread(&bmp.id,1,2,fp)) return 0;         // 2 0
401  bmp.filesize=read_uint32(fp);                   // 4 4
402  if (!fread(bmp.reserved,1,4,fp)) return 0;    // 4 8
403  bmp.headersize=read_uint32(fp);                 // 4 12
404  bmp.infosize=read_uint32(fp);                   // 4 16
405  bmp.width=read_uint32(fp);                      // 4 20
406  bmp.height=read_uint32(fp);                     // 4 24
407  bmp.biplanes=read_uint16(fp);                  // 2 26
408  bmp.bits=read_uint16(fp);                      // 2 28
409  bmp.bicompression=read_uint32(fp);              // 4 32
410  bmp.bisizeimage=read_uint32(fp);                // 4 36
411  bmp.bixpelspermeter=read_uint32(fp);            // 4 40
412  bmp.biypelspermeter=read_uint32(fp);            // 4 44
413  bmp.biclrused=read_uint32(fp);                  // 4 48
414  bmp.biclrimportant=read_uint32(fp);             // 4 52
415  return 1;
416 
417}
418
419
420
421
422int bmp_bits(char *filename)
423{
424  FILE *fp;
425  fp=fopen(filename,"rb");
426  if (!fp) return 0;
427  if (!read_BMP_header(fp)) return 0;
428  fclose(fp);
429
430  if (bmp.id[0]!='B' || bmp.id[1]!='M') 
431    return 0;
432  else return bmp.bits;
433}
434
435image24 *read_bmp24(char *filename)
436{
437  image24 *im;
438  FILE *fp;
439  int i,j;
440  fp=fopen(filename,"rb");
441  if (!fp)
442    return NULL;
443  if (!read_BMP_header(fp)) return NULL;
444 
445  if (bmp.id[0]!='B' || bmp.id[1]!='M') 
446    return NULL;
447
448  if (bmp.bits!=24)
449    return NULL;
450 
451  im=new image24((bmp.width+3)&(0xffffffff-3),
452                 (bmp.height+3)&0xffffffff-3);
453  if (!im)
454    return NULL;
455 
456  uint8_t *sl;
457  int trailer=im->width()%4;
458  if (trailer==1) trailer=3;
459  else if (trailer==3) trailer=1;
460  uint8_t buf[9];
461  for (i=im->height();i;i--)
462  {
463    sl=im->scan_line(i-1);
464    for (j=0;j<im->width();j++)   
465    {
466      fread(sl+2,1,1,fp);
467      fread(sl+1,1,1,fp);     
468      fread(sl,1,1,fp);
469      sl+=3; 
470    }   
471    if (trailer)
472      fread(buf,trailer*3,1,fp);
473  }
474  fclose(fp);
475
476  return im;
477}
478
479image *read_bmp(palette *&pal, char *filename)
480{
481  image *im;
482  FILE *fp;
483  uint8_t pal_quad[4];
484  char *scrap;
485  int bytes,i;
486  fp=fopen(filename,"rb");
487  if (!fp)
488    return NULL;
489
490  if (!read_BMP_header(fp)) return NULL;
491 
492  if (bmp.id[0]!='B' || bmp.id[1]!='M') 
493    return NULL;
494
495  if (bmp.bits!=8)
496    return NULL;
497 
498  im=new image((bmp.width+3)&(0xffffffff-3),
499                 (bmp.height+3)&0xffffffff-3);
500
501  if (!im)
502    return NULL;
503
504  pal=new palette(256);
505  for (i=0;i<256;i++)
506  {
507    fread(pal_quad,1,4,fp);
508    pal->set(i,pal_quad[2],pal_quad[1],pal_quad[0]);
509  }
510  bytes=(im->width()+3)/4;
511  bytes*=4;
512  scrap=(char *)jmalloc(bytes,"xwd_read scrap");
513  for (i=im->height();i;i--)
514  {
515    fread(scrap,1,bytes,fp);
516    memcpy(im->scan_line(i-1),scrap,im->width());
517  }
518  jfree(scrap);
519  fclose(fp);
520  return im;
521}
522
523int write_BMP_header(FILE *fp)
524{
525  if (!fwrite(&bmp.id,1,2,fp)) return 0; 
526  write_uint32(fp,bmp.filesize); 
527  if (!fwrite(bmp.reserved,1,4,fp)) return 0;   
528  write_uint32(fp,bmp.headersize);
529  write_uint32(fp,bmp.infosize); 
530  write_uint32(fp,bmp.width);
531  write_uint32(fp,bmp.height);
532  write_uint16(fp,bmp.biplanes);
533  write_uint16(fp,bmp.bits);
534  write_uint32(fp,bmp.bicompression);
535  write_uint32(fp,bmp.bisizeimage);
536  write_uint32(fp,bmp.bixpelspermeter);
537  write_uint32(fp,bmp.biypelspermeter);
538  write_uint32(fp,bmp.biclrused);
539  write_uint32(fp,bmp.biclrimportant);   
540  return 1;
541 
542}
543
544void write_bmp(image *im, palette *pal, char *filename)
545{
546  FILE *fp;
547  int i,bytes;
548  uint8_t pal_quad[4];
549  fp=fopen(filename,"wb");
550  if (!fp)
551  { printf("Error : unable to open %s for writing!\n",filename);
552    exit(0);
553  }
554  bytes=(im->width()+3)/4;
555  memset((char *)&bmp,0,sizeof(bmp));
556  memcpy(bmp.id,"BM",2);
557  bmp.width=im->width();
558  bmp.height=im->height();
559  bmp.bits=8;
560  bmp.infosize=0x28L;
561  bmp.biplanes=1;
562  bmp.headersize=1078;
563  bmp.filesize=bmp.headersize+bytes*im->height()*4;
564  bmp.bisizeimage=im->width()*im->height();
565  bmp.biclrused=256;
566  bmp.biclrimportant=256;
567  write_BMP_header(fp);
568 
569  pal_quad[3]=0;
570  for (i=0;i<256;i++)
571  {
572    pal->get(i,pal_quad[2],pal_quad[1],pal_quad[0]);
573    fwrite(pal_quad,1,4,fp);
574  }
575  for (i=im->height();i;i--)
576    fwrite(im->scan_line(i-1),1,bytes*4,fp);
577  fclose(fp);
578}
579
580
Note: See TracBrowser for help on using the repository browser.