/* readxwd.c */ /* This program is limited to X11 format XWD files */ #include "filter.hpp" #include "system.h" #include "image.hpp" #include "palette.hpp" #include "event.hpp" #include "video.hpp" #include "dos.h" #include "main.hpp" #include #include "macs.hpp" #include "image24.hpp" #define MAXCOLORS 256 //#define MC(x) (((x)<3)==0) #define MC(x) (x!=0) // the following table converts rgb to cym. int ca[8]={1,1,1,1,0,0,0,0}, ma[8]={1,0,1,0,1,0,1,0}, ya[8]={1,1,0,0,1,1,0,0}; // the following defines make a color threshold #define RGB2C(r,g,b) (char)(ca[MC(b)|MC(g)<<1|MC(r)<<2]) #define RGB2Y(r,g,b) (char)(ya[MC(b)|MC(g)<<1|MC(r)<<2]) #define RGB2M(r,g,b) (char)(ma[MC(b)|MC(g)<<1|MC(r)<<2]) #define LSBFirst 0 #define MSBFirst 1 #define XYBitmap 0 #define XYPixmap 1 #define ZPixmap 2 #define StaticGray 0 #define GrayScale 1 #define StaticColor 2 #define PseudoColor 3 #define TrueColor 4 #define DirectColor 5 typedef unsigned long xwdval; #define X11WD_FILE_VERSION 7 typedef struct { xwdval header_size; /* Size of the entire file header (bytes). */ xwdval file_version; /* X11WD_FILE_VERSION */ xwdval pixmap_format; /* Pixmap format */ xwdval pixmap_depth; /* Pixmap depth */ xwdval pixmap_width; /* Pixmap width */ xwdval pixmap_height; /* Pixmap height */ xwdval xoffset; /* Bitmap x offset */ xwdval byte_order; /* MSBFirst, LSBFirst */ xwdval bitmap_unit; /* Bitmap unit */ xwdval bitmap_bit_order; /* MSBFirst, LSBFirst */ xwdval bitmap_pad; /* Bitmap scanline pad */ xwdval bits_per_pixel; /* Bits per pixel */ xwdval bytes_per_line; /* Bytes per scanline */ xwdval visual_class; /* Class of colormap */ xwdval red_mask; /* Z red mask */ xwdval green_mask; /* Z green mask */ xwdval blue_mask; /* Z blue mask */ xwdval bits_per_rgb; /* Log base 2 of distinct color values */ xwdval colormap_entries; /* Number of entries in colormap */ xwdval ncolors; /* Number of Color structures */ xwdval window_width; /* Window width */ xwdval window_height; /* Window height */ long window_x; /* Window upper left X coordinate */ long window_y; /* Window upper left Y coordinate */ xwdval window_bdrwidth; /* Window border width */ } X11WDFileHeader; typedef struct { unsigned long pixel; unsigned short red, green, blue; char flags; /* do_red, do_green, do_blue */ char pad; } X11XColor; image *getinit(FILE *file, palette *&pal, int *padrightP); void getimage(FILE *file,image *image, int pad); int getpixnum(FILE *file); image *readxwd(char *input_file,palette *&pal) //char *hdfpal,int *palsize,int *cols,int *rows) { FILE *ifd; int padright; image *im; #ifdef __WINDOWS HCURSOR OldCur; OldCur=SetCursor(LoadCursor(0,IDC_WAIT)); // set the cursor to the hour glass #endif /* open input file */ if (strcmp(input_file,"-") == 0) ifd = stdin; else ifd = fopen(input_file,"rb"); /* get X info from file */ if (!ifd) { #ifndef __WINDOWS printf("Unable to open %s\n" "Get your story strait and try again.\n",input_file); exit(0); #endif } im=getinit( ifd, pal, &padright); //cols, rows, &padright, palsize, hdfpal); /* alloc image array */ /* fill image array */ getimage(ifd, im, padright); #ifdef __WINDOWS SetCursor(OldCur); // set the cursor to the hour glass #endif return(im); } int bits_per_item, bits_used, bit_shift, bits_per_pixel, pixel_mask; int bit_order, byte_swap; char buf[4]; unsigned char *byteP; unsigned short *shortP; unsigned long *longP; int bs_int(int s); long bs_long(long s); short bs_short(short s ); image *getinit(FILE *file, palette *&pal, int *padrightP) { /* Assume X11 headers are larger than X10 ones. */ unsigned char header[sizeof(X11WDFileHeader)]; image *im; X11WDFileHeader *h11P; char junk[800]; int i, dummy1, dummy2, dummy3; unsigned short minred, maxred; X11XColor x11col; h11P = (X11WDFileHeader *) header; if (fread(header,sizeof(*h11P),1,file) != 1 ) { fprintf(stderr,"couldn't read X11 XWD file header"); exit(-1); } if ( h11P->file_version != X11WD_FILE_VERSION ) { byte_swap = 1; h11P->file_version = bltl(h11P->file_version); if (h11P->file_version != X11WD_FILE_VERSION) { set_error(imINCORRECT_FILETYPE); return NULL; } h11P->header_size = bltl(h11P->header_size); h11P->file_version = bltl(h11P->file_version); h11P->pixmap_format = bltl(h11P->pixmap_format); h11P->pixmap_depth = bltl(h11P->pixmap_depth); h11P->pixmap_width = bltl(h11P->pixmap_width); h11P->pixmap_height = bltl(h11P->pixmap_height); h11P->xoffset = bltl(h11P->xoffset); h11P->byte_order = bltl(h11P->byte_order); h11P->bitmap_unit = bltl(h11P->bitmap_unit); h11P->bitmap_bit_order = bltl(h11P->bitmap_bit_order); h11P->bitmap_pad = bltl(h11P->bitmap_pad); h11P->bits_per_pixel = bltl(h11P->bits_per_pixel); h11P->bytes_per_line = bltl(h11P->bytes_per_line); h11P->visual_class = bltl(h11P->visual_class); h11P->red_mask = bltl(h11P->red_mask); h11P->green_mask = bltl(h11P->green_mask); h11P->blue_mask = bltl(h11P->blue_mask); h11P->bits_per_rgb = bltl(h11P->bits_per_rgb); h11P->colormap_entries = bltl(h11P->colormap_entries); h11P->ncolors = bltl(h11P->ncolors); h11P->window_width = bltl(h11P->window_width); h11P->window_height = bltl(h11P->window_height); h11P->window_x = bltl(h11P->window_x); h11P->window_y = bltl(h11P->window_y); h11P->window_bdrwidth = bltl(h11P->window_bdrwidth); } if ( fread( junk, 1, h11P->header_size - sizeof(*h11P), file ) != h11P->header_size - sizeof(*h11P) ) { fclose(file); set_error(imFILE_CORRUPTED); return NULL; } /* Check whether we can handle this dump. */ if ( h11P->pixmap_depth > 8 ) { fclose(file); set_error(imNOT_SUPPORTED); return NULL; } if ( h11P->bits_per_rgb > 8 ) { fclose(file); set_error(imNOT_SUPPORTED); return NULL; } if ( h11P->ncolors > MAXCOLORS ) { fclose(file); set_error(imNOT_SUPPORTED); return NULL; } if ( h11P->pixmap_format != ZPixmap ) { fclose(file); set_error(imNOT_SUPPORTED); return NULL; } if ( h11P->bitmap_unit != 8 && h11P->bitmap_unit != 16 && h11P->bitmap_unit != 32 ) { fclose(file); set_error(imNOT_SUPPORTED); return NULL; } im=new image(h11P->pixmap_width,h11P->pixmap_height); pal=new palette(h11P->colormap_entries); *padrightP = h11P->bytes_per_line * 8 / h11P->bits_per_pixel - im->width(); /*****************************************************************************/ /* Read X11 colormap. */ minred = 65535; maxred = 0; for ( i = 0; i < h11P->colormap_entries; i++ ) { if ( fread( &x11col, sizeof(X11XColor), 1, file ) != 1 ) { fclose(file); set_error(imFILE_CORRUPTED); delete pal; return NULL; } else { x11col.pixel=bltl(x11col.pixel); x11col.red=bstl(x11col.red); x11col.green=bstl(x11col.green); x11col.blue=bstl(x11col.blue); } if (x11col.pixel < 256) { if (minred > x11col.red) minred = x11col.red; if (maxred < x11col.red) maxred = x11col.red; dummy1 = (unsigned) x11col.red>>8; dummy2 = (unsigned) x11col.green>>8; dummy3 = (unsigned) x11col.blue>>8; pal->set(i,dummy1,dummy2,dummy3); } else { fprintf(stderr,"pixel value outside of valid HDF palette\n"); exit(-1); } } /* rest of stuff for getpixnum */ bits_per_item = h11P->bitmap_unit; bits_used = bits_per_item; bits_per_pixel = h11P->bits_per_pixel; bit_order = h11P->bitmap_bit_order; pixel_mask = ( 1 << bits_per_pixel ) - 1; byteP = (unsigned char *) buf; shortP = (unsigned short *) buf; longP = (unsigned long *) buf; return im; } void getimage(FILE *file,image *im,int pad) { int i,j; unsigned char *sl; #if BYTE_ORDER!=BIG_ENDIAN printf("little guys\n"); #endif printf("getting image, bits_per_item = %d %d %d\n",bits_per_item,bits_used,bit_order==MSBFirst); for (i=0; iheight(); i++) { sl=im->scan_line(i); for (j=0; jwidth(); j++) sl[j]= getpixnum(file); for ( j = 0; j < pad; j++ ) getpixnum( file ); } } int getpixnum(FILE *file) { int p; if ( bits_used == bits_per_item ) { if ( fread( buf, bits_per_item / 8, 1, file ) != 1 ) fprintf(stderr, "couldn't read bits" ); if ( byte_swap ) switch ( bits_per_item ) { case 8: break; case 16: *shortP=short_swap(*shortP); break; case 32: *longP=long_swap(*longP); break; default: fprintf(stderr, "can't happen" ); } bits_used = 0; // if ( bit_order == MSBFirst ) bit_shift = bits_per_item - bits_per_pixel; // else // bit_shift = 0; } switch ( bits_per_item ) { case 8: p = ( *byteP >> bit_shift) & pixel_mask; break; case 16: p = ( *shortP >> bit_shift) & pixel_mask; break; case 32: p = ( *longP >> bit_shift) & pixel_mask; break; default: fprintf(stderr, "can't happen" ); } // if ( bit_order == MSBFirst ) bit_shift -= bits_per_pixel; // else // bit_shift += bits_per_pixel; bits_used += bits_per_pixel; return p; } short bs_short(short s ) { short ss; unsigned char *bp, t; ss = s; bp = (unsigned char *) &ss; t = bp[0]; bp[0] = bp[1]; bp[1] = t; return ss; } int bs_int(int i ) { int ii; unsigned char *bp, t; ii = i; bp = (unsigned char *) ⅈ t = bp[0]; bp[0] = bp[3]; bp[3] = t; t = bp[1]; bp[1] = bp[2]; bp[2] = t; return ii; } long bs_long(long l ) { return bs_int( l ); } struct BMP_header { char id[2]; long filesize; short reserved[2]; long headersize,infosize,width,height; short biplanes,bits; long bicompression, bisizeimage, bixpelspermeter, biypelspermeter, biclrused,biclrimportant; } bmp; int read_BMP_header(FILE *fp) { if (!fread(&bmp.id,1,2,fp)) return 0; // 2 0 bmp.filesize=read_long(fp); // 4 4 if (!fread(bmp.reserved,1,4,fp)) return 0; // 4 8 bmp.headersize=read_long(fp); // 4 12 bmp.infosize=read_long(fp); // 4 16 bmp.width=read_long(fp); // 4 20 bmp.height=read_long(fp); // 4 24 bmp.biplanes=read_short(fp); // 2 26 bmp.bits=read_short(fp); // 2 28 bmp.bicompression=read_long(fp); // 4 32 bmp.bisizeimage=read_long(fp); // 4 36 bmp.bixpelspermeter=read_long(fp); // 4 40 bmp.biypelspermeter=read_long(fp); // 4 44 bmp.biclrused=read_long(fp); // 4 48 bmp.biclrimportant=read_long(fp); // 4 52 return 1; } int bmp_bits(char *filename) { FILE *fp; fp=fopen(filename,"rb"); if (!fp) return 0; if (!read_BMP_header(fp)) return 0; fclose(fp); if (bmp.id[0]!='B' || bmp.id[1]!='M') return 0; else return bmp.bits; } image24 *read_bmp24(char *filename) { image24 *im; FILE *fp; int i,j; fp=fopen(filename,"rb"); if (!fp) return NULL; if (!read_BMP_header(fp)) return NULL; if (bmp.id[0]!='B' || bmp.id[1]!='M') return NULL; if (bmp.bits!=24) return NULL; im=new image24((bmp.width+3)&(0xffffffff-3), (bmp.height+3)&0xffffffff-3); if (!im) return NULL; unsigned char *sl; int trailer=im->width()%4; if (trailer==1) trailer=3; else if (trailer==3) trailer=1; uchar buf[9]; for (i=im->height();i;i--) { sl=im->scan_line(i-1); for (j=0;jwidth();j++) { fread(sl+2,1,1,fp); fread(sl+1,1,1,fp); fread(sl,1,1,fp); sl+=3; } if (trailer) fread(buf,trailer*3,1,fp); } fclose(fp); return im; } image *read_bmp(palette *&pal, char *filename) { image *im; FILE *fp; unsigned char pal_quad[4]; char *scrap; int bytes,i; fp=fopen(filename,"rb"); if (!fp) return NULL; if (!read_BMP_header(fp)) return NULL; if (bmp.id[0]!='B' || bmp.id[1]!='M') return NULL; if (bmp.bits!=8) return NULL; im=new image((bmp.width+3)&(0xffffffff-3), (bmp.height+3)&0xffffffff-3); if (!im) return NULL; pal=new palette(256); for (i=0;i<256;i++) { fread(pal_quad,1,4,fp); pal->set(i,pal_quad[2],pal_quad[1],pal_quad[0]); } bytes=(im->width()+3)/4; bytes*=4; scrap=(char *)jmalloc(bytes,"xwd_read scrap"); for (i=im->height();i;i--) { fread(scrap,1,bytes,fp); memcpy(im->scan_line(i-1),scrap,im->width()); } jfree(scrap); fclose(fp); return im; } int write_BMP_header(FILE *fp) { if (!fwrite(&bmp.id,1,2,fp)) return 0; write_long(fp,bmp.filesize); if (!fwrite(bmp.reserved,1,4,fp)) return 0; write_long(fp,bmp.headersize); write_long(fp,bmp.infosize); write_long(fp,bmp.width); write_long(fp,bmp.height); write_short(fp,bmp.biplanes); write_short(fp,bmp.bits); write_long(fp,bmp.bicompression); write_long(fp,bmp.bisizeimage); write_long(fp,bmp.bixpelspermeter); write_long(fp,bmp.biypelspermeter); write_long(fp,bmp.biclrused); write_long(fp,bmp.biclrimportant); return 1; } void write_bmp(image *im, palette *pal, char *filename) { FILE *fp; int i,bytes; unsigned char pal_quad[4]; fp=fopen(filename,"wb"); if (!fp) { printf("Error : unable to open %s for writing!\n"); exit(0); } bytes=(im->width()+3)/4; memset((char *)&bmp,0,sizeof(bmp)); memcpy(bmp.id,"BM",2); bmp.width=im->width(); bmp.height=im->height(); bmp.bits=8; bmp.infosize=0x28L; bmp.biplanes=1; bmp.headersize=1078; bmp.filesize=bmp.headersize+bytes*im->height()*4; bmp.bisizeimage=im->width()*im->height(); bmp.biclrused=256; bmp.biclrimportant=256; write_BMP_header(fp); pal_quad[3]=0; for (i=0;i<256;i++) { pal->get(i,pal_quad[2],pal_quad[1],pal_quad[0]); fwrite(pal_quad,1,4,fp); } for (i=im->height();i;i--) fwrite(im->scan_line(i-1),1,bytes*4,fp); fclose(fp); }