/* +-------------------------------------------------------------------+ */ /* | This file is derived from | */ /* | Xpaint's read/write routines, copyrighted | */ /* | by David Koblas (koblas@netcom.com), | */ /* | Torsten Martinsen ( | */ /* | Greg Roelofs (newt@pobox.com) | */ /* | | */ /* | Permission to use, copy, modify, and to distribute this software | */ /* | and its documentation for any purpose is hereby granted without | */ /* | fee, provided that the above copyright notice appear in all | */ /* | copies and that both that copyright notice and this permission | */ /* | notice appear in supporting documentation. There is no | */ /* | representations about the suitability of this software for | */ /* | any purpose. this software is provided "as is" without express | */ /* | or implied warranty. | */ /* | | */ /* +-------------------------------------------------------------------+ */ #include #include #include #include #include #include #include #include #include "xrmap.h" #include "numdefs.h" extern Display * dpy; extern Visual * visual; extern Colormap cmap; extern GC gc; extern int scr; extern int bigendian; extern int color_depth; extern int color_pad; extern int runlevel; extern int num_flag_types; extern int brief_menu; extern char *color_table; extern int cmdwin_on; extern Window mainwin, datawin, cmdwin; extern char *error_msg; extern char **msg; extern char *flag_formats[]; extern char *flag_ordering; extern char **flag_type; extern char **flag_dir; extern int flag_size; extern int num_flag_dirs; extern int num_flag_types; int bytes_per_pixel; /* Make a temporary file */ char * mk_tmp(char *suff) { static char template[256]; int fd; sprintf(template, "%s/xrmapXXXXXX", P_tmpdir); fd = mkstemp(template); if (fd == -1) return NULL; close(fd); unlink(template); strcat(template, suff); return template; } XImage * ximage_rescale(XImage * image, int height) { XImage * ximage; int i, ip, j, jp, k, b, bp, width; width = (int) (((double)image->width * (double) height / (double) image->height)+0.5); ximage = XCreateImage(dpy, visual, DefaultDepth(dpy, scr), ZPixmap,0, NULL, width, height, color_pad,0); XFlush(dpy); if (!ximage) return NULL; ximage->data = (char *) malloc(ximage->bytes_per_line * ximage->height); if (!ximage->data) return NULL; for (j=0; jheight)/height; for (i=0; iwidth)/width; b = i*bytes_per_pixel + j * ximage->bytes_per_line; bp = ip*bytes_per_pixel + jp*image->bytes_per_line; for (k=0; kdata[b+k] = image->data[bp+k]; } } XDestroyImage(image); return ximage; } /* PNG routines */ typedef struct _jmpbuf_wrapper { jmp_buf jmpbuf; } jmpbuf_wrapper; /* this can be shared between reading/writing code since they never overlap: */ static jmpbuf_wrapper jmpbuf_struct; static void png_error_handler (png_structp png_ptr, png_const_charp msg) { jmpbuf_wrapper *jmpbuf_ptr; /* this function, aside from the extra step of retrieving the "error * pointer" (below) and the fact that it exists within the application * rather than within libpng, is essentially identical to libpng's * default error handler. The second point is critical: since both * setjmp() and longjmp() are called from the same code, they are * guaranteed to have compatible notions of how big a jmp_buf is, * regardless of whether _BSD_SOURCE or anything else has (or has not) * been defined. */ fprintf(stderr, "Fatal libpng error !!\n"); fflush(stderr); jmpbuf_ptr = png_get_error_ptr(png_ptr); if (jmpbuf_ptr == NULL) { /* we are completely hosed now */ exit(99); } longjmp(jmpbuf_ptr->jmpbuf, 1); } void fill_line(char *scan, char* c, int w, int wp) { unsigned char r, g, b; int i, j, k; k = 0; if (color_depth>16) { if (bigendian) k = bytes_per_pixel - 3; for (i = 0; i < wp; i++) { if (i==0) j = 0 ; else j = 3 * ((i* (w-1))/(wp-1)); if (bigendian) { c[k] = scan[j]; c[k+1] = scan[j+1]; c[k+2] = scan[j+2]; } else { c[k] = scan[j+2]; c[k+1] = scan[j+1]; c[k+2] = scan[j]; } k += bytes_per_pixel; } } else if (color_depth==16) for (i = 0; i < wp; i++) { if (i==0) j = 0 ; else j = 3 * ((i* (w-1))/(wp-1)); r = scan[j]; g = scan[j+1]; b = scan[j+2]; /* blue c[k] = 31; c[k+1] = 0; green c[k] = 224 (low weight) c[k+1] = 7 (high weight) red c[k] = 0; c[k+1] = 248; */ if (bigendian) { c[k+1] = (((b&248)>>3) | ((g&28)<<3)); c[k] = (((g&224)>>5) | (r&248)); } else { c[k] = (((b&248)>>3) | ((g&28)<<3)); c[k+1] = (((g&224)>>5) | (r&248)); } k += 2; } else if (color_depth==15) for (i = 0; i < wp; i++) { if (i==0) j = 0 ; else j = 3 * ((i* (w-1))/(wp-1)); r = scan[j]; g = scan[j+1]; b = scan[j+2]; /* blue c[k] = 31; c[k+1] = 0; green c[k] = 224 (low weight) c[k+1] = 7 (high weight) red c[k] = 0; c[k+1] = 248; */ if (bigendian) { c[k+1] = (b&248)>>3 | (g&56)<<2; c[k] = (g&192)>>6 | (r&248)>>1; } else { c[k] = (b&248)>>3 | (g&56)<<2; c[k+1] = (g&192)>>6 | (r&248)>>1; } k += 2; } else { for (i = 0; i < wp; i++) { if (i==0) j = 0 ; else j = 3 * ((i* (w-1))/(wp-1)); r = scan[j]; g = scan[j+1]; b = scan[j+2]; c[k] = color_table[(((6*g)>>8)*36)+(((6*r)>>8)*6)+((6*b)>>8)]; k++; } } } XImage * readPNG(char *file, int height, Colordata *color) { XImage *ximage; FILE *fp; png_structp png_ptr; png_infop info_ptr; png_uint_32 width0, height0; png_colorp palette; png_bytep *row_pointers, png_data, png; int bit_depth, color_type, interlace_type, num_palette, rowbytes; int i, i1, i2, x, y, yp, size, width = 0; int * ys; unsigned char * scan, *scanp, *out; unsigned char c; unsigned char bg[4]; if ((fp = fopen(file, "rb")) == (FILE *)NULL) { return NULL; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, &jmpbuf_struct, png_error_handler, NULL); if (!png_ptr) { fclose(fp); return NULL; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); fclose(fp); return NULL; } if (setjmp(jmpbuf_struct.jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); return NULL; } png_init_io(png_ptr, fp); png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ png_get_IHDR(png_ptr, info_ptr, &width0, &height0, &bit_depth, &color_type, &interlace_type, NULL, NULL); switch (color_type) { case PNG_COLOR_TYPE_PALETTE: if (!png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); return NULL; } break; case PNG_COLOR_TYPE_RGB: if (bit_depth == 16) { png_set_strip_16(png_ptr); } break; case PNG_COLOR_TYPE_GRAY: /* treat grayscale as special colormap */ if (bit_depth == 16) { png_set_strip_16(png_ptr); bit_depth = 8; } break; case PNG_COLOR_TYPE_RGB_ALPHA: if (bit_depth == 16) { png_set_strip_16(png_ptr); } break; case PNG_COLOR_TYPE_GRAY_ALPHA: if (bit_depth == 16) { png_set_strip_16(png_ptr); } break; default: png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); return NULL; } if (height == 0) height = height0; if (height == height0) width = width0; else width = (int) (((double)width0 * (double) height / (double) height0)+0.5); ximage = XCreateImage(dpy, visual, DefaultDepth(dpy, scr), ZPixmap, 0, NULL, width, height, color_pad, 0); XFlush(dpy); if (!ximage) return NULL; bytes_per_pixel = ximage->bits_per_pixel/8; size = ximage->bytes_per_line * height; ximage->data = (char *) malloc(size); if (!ximage->data) { XDestroyImage(ximage); return NULL; } if (bit_depth < 8) png_set_packing(png_ptr); if (interlace_type) /* npasses = */ png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); rowbytes = png_get_rowbytes(png_ptr, info_ptr); png_data = (png_bytep) malloc(height0*rowbytes); row_pointers = (png_bytep *)malloc(height0 * sizeof(png_bytep)); scan = (char *)malloc(3*width0); ys = (int *)malloc((height0+1)*sizeof(int)); if (!png_data || !row_pointers || !scan || !ys) { if (png_data) free(png_data); png_data = NULL; if (row_pointers) free(row_pointers); row_pointers = NULL; if (scan) free(scan); if (ys) free(ys); XDestroyImage(ximage); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); return NULL; } for (y=0; yb>>8; bg[2] = color->g>>8; bg[3] = color->r>>8; for (y=0; ydata + yp * ximage->bytes_per_line; png = png_data + y*rowbytes; scanp = scan; if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) { for (x=0; x>8; } } else if (color_type == PNG_COLOR_TYPE_RGB) { for (x=0; x>8; } } fill_line(scan, out, width0, width); } /* fill intermediate lines in output, if necessary*/ if (height>height0) { ys[height0] = height; for(y=0; y=0 || ys[y+1]data + ys[y+1] * ximage->bytes_per_line; i1 = 0; i2 = ys[y+1]; } else { out = ximage->data + ys[y]*ximage->bytes_per_line; i1 = ys[y]+1; i2 = ys[y+1]; if (i2>height) i2=height; } for (i=i1; idata+i*ximage->bytes_per_line, out, ximage->bytes_per_line); } } } /* Close everything */ png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); free(png_data); free(row_pointers); free(scan); free(ys); fclose(fp); return ximage; } /* end function ReadPNG() */ /* GIF routines */ #define MAXCOLORMAPSIZE 256 #define TRUE 1 #define FALSE 0 #define CM_RED 0 #define CM_GREEN 1 #define CM_BLUE 2 #define MAX_LWZ_BITS 12 #define INTERLACE 0x40 #define LOCALCOLORMAP 0x80 #define BitSet(byte, bit) (((byte) & (bit)) == (bit)) #define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0) #define LM_to_uint(a,b) (((b)<<8)|(a)) struct { unsigned int Width; unsigned int Height; unsigned char ColorMap[3][MAXCOLORMAPSIZE]; unsigned int BitPixel; unsigned int ColorResolution; unsigned int Background; unsigned int AspectRatio; int Grayscale; } GifScreen; static struct { int transparent; int delayTime; int inputFlag; int disposal; } Gif89 = { -1, -1, -1, 0 }; static int ReadColorMap(FILE * fd, int number, unsigned char buffer[3][MAXCOLORMAPSIZE], int *flag); static int DoExtension(FILE * fd, int label); static int GetDataBlock(FILE * fd, unsigned char *buf); static int GetCode(FILE * fd, int code_size, int flag); static int LWZReadByte(FILE * fd, int flag, int input_code_size); static int ReadImage(FILE * fd, XImage *ximage, int width, int height, int bitPixel, unsigned char cmap[3][MAXCOLORMAPSIZE], int gray, int interlace); XImage * readGIF(char *file, int height, Colordata *color) { XImage *image; unsigned char buf[16]; unsigned char c; unsigned char localColorMap[3][MAXCOLORMAPSIZE]; int output = 0, size; int grayScale; int useGlobalColormap; int bitPixel; char version[4]; FILE *fd; fd = fopen(file, "r"); if (fd == NULL) return NULL; if (!ReadOK(fd, buf, 6)) { fclose(fd); return NULL; } if (strncmp((char *) buf, "GIF", 3) != 0) { fclose(fd); return NULL; } strncpy(version, (char *) buf + 3, 3); version[3] = '\0'; if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) { fclose(fd); return NULL; } if (!ReadOK(fd, buf, 7)) { fclose(fd); return NULL; } GifScreen.Width = LM_to_uint(buf[0], buf[1]); GifScreen.Height = LM_to_uint(buf[2], buf[3]); GifScreen.BitPixel = 2 << (buf[4] & 0x07); GifScreen.ColorResolution = (((buf[4] & 0x70) >> 3) + 1); GifScreen.Background = buf[5]; GifScreen.AspectRatio = buf[6]; if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */ if (ReadColorMap(fd, GifScreen.BitPixel, GifScreen.ColorMap, &GifScreen.Grayscale)) { fclose(fd); return NULL; } } repeat: if (!ReadOK(fd, &c, 1)) { fclose(fd); return NULL; } if (c == '!') { /* Extension */ if (!ReadOK(fd, &c, 1)) { fclose(fd); return NULL; } DoExtension(fd, c); goto repeat; } if (c != ',') { /* Not a valid start character */ goto repeat; } if (!ReadOK(fd, buf, 9)) { fclose(fd); return NULL; } useGlobalColormap = !BitSet(buf[8], LOCALCOLORMAP); bitPixel = 1 << ((buf[8] & 0x07) + 1); image = XCreateImage(dpy, visual, DefaultDepth(dpy, scr), ZPixmap, 0, NULL, GifScreen.Width, GifScreen.Height, color_pad, 0); XFlush(dpy); if (!image) return NULL; bytes_per_pixel = (image->bits_per_pixel/8); size = image->bytes_per_line * GifScreen.Height; image->data = (char *) malloc(size); if (!image->data) { XDestroyImage(image); return NULL; } if (!useGlobalColormap) { if (ReadColorMap(fd, bitPixel, localColorMap, &grayScale)) { XDestroyImage(image); return NULL; } output = ReadImage(fd, image, LM_to_uint(buf[4], buf[5]), LM_to_uint(buf[6], buf[7]), bitPixel, localColorMap, grayScale, BitSet(buf[8], INTERLACE)); } else { output = ReadImage(fd, image, LM_to_uint(buf[4], buf[5]), LM_to_uint(buf[6], buf[7]), GifScreen.BitPixel, GifScreen.ColorMap, GifScreen.Grayscale, BitSet(buf[8], INTERLACE)); } if (output) { XDestroyImage(image); return NULL; } if (height == 0 || height == image->height) { return image; } return ximage_rescale(image, height); } static int ReadColorMap(FILE *fd, int number, unsigned char buffer[3][MAXCOLORMAPSIZE], int *gray) { int i; unsigned char rgb[3]; int flag; flag = TRUE; for (i = 0; i < number; ++i) { if (!ReadOK(fd, rgb, sizeof(rgb))) { return 1; } buffer[CM_RED][i] = rgb[0]; buffer[CM_GREEN][i] = rgb[1]; buffer[CM_BLUE][i] = rgb[2]; flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]); } #if 0 if (flag) *gray = (number == 2) ? PBM_TYPE : PGM_TYPE; else *gray = PPM_TYPE; #else *gray = 0; #endif return FALSE; } static int DoExtension(FILE *fd, int label) { static char buf[256]; char *str; switch (label) { case 0x01: /* Plain Text Extension */ str = "Plain Text Extension"; break; case 0xff: /* Application Extension */ str = "Application Extension"; break; case 0xfe: /* Comment Extension */ str = "Comment Extension"; while (GetDataBlock(fd, (unsigned char *) buf) != 0); return FALSE; case 0xf9: /* Graphic Control Extension */ str = "Graphic Control Extension"; (void) GetDataBlock(fd, (unsigned char *) buf); Gif89.disposal = (buf[0] >> 2) & 0x7; Gif89.inputFlag = (buf[0] >> 1) & 0x1; Gif89.delayTime = LM_to_uint(buf[1], buf[2]); if ((buf[0] & 0x1) != 0) Gif89.transparent = buf[3]; while (GetDataBlock(fd, (unsigned char *) buf) != 0); return FALSE; default: str = buf; sprintf(buf, "UNKNOWN (0x%02x)", label); break; } while (GetDataBlock(fd, (unsigned char *) buf) != 0); return FALSE; } static int ZeroDataBlock = FALSE; static int GetDataBlock(FILE *fd, unsigned char *buf) { unsigned char count; if (!ReadOK(fd, &count, 1)) { /* pm_message("error in getting DataBlock size" ); */ return -1; } ZeroDataBlock = count == 0; if ((count != 0) && (!ReadOK(fd, buf, count))) { /* pm_message("error in reading DataBlock" ); */ return -1; } return count; } static int GetCode(FILE *fd, int code_size, int flag) { static unsigned char buf[280]; static int curbit, lastbit, done, last_byte; int i, j, ret; unsigned char count; if (flag) { curbit = 0; lastbit = 0; done = FALSE; return 0; } if ((curbit + code_size) >= lastbit) { if (done) { if (curbit >= lastbit) fprintf(stderr, "ran off the end of my bits...\n"); return -1; } buf[0] = buf[last_byte - 2]; buf[1] = buf[last_byte - 1]; if ((count = GetDataBlock(fd, &buf[2])) == 0) done = TRUE; last_byte = 2 + count; curbit = (curbit - lastbit) + 16; lastbit = (2 + count) * 8; } ret = 0; for (i = curbit, j = 0; j < code_size; ++i, ++j) ret |= ((buf[i / 8] & (1 << (i % 8))) != 0) << j; curbit += code_size; return ret; } static int LWZReadByte(FILE *fd, int flag, int input_code_size) { static int fresh = FALSE; int code, incode; static int code_size, set_code_size; static int max_code, max_code_size; static int firstcode, oldcode; static int clear_code, end_code; static int table[2][(1 << MAX_LWZ_BITS)]; static int stack[(1 << (MAX_LWZ_BITS)) * 2], *sp; register int i; if (flag) { set_code_size = input_code_size; code_size = set_code_size + 1; clear_code = 1 << set_code_size; end_code = clear_code + 1; max_code_size = 2 * clear_code; max_code = clear_code + 2; GetCode(fd, 0, TRUE); fresh = TRUE; for (i = 0; i < clear_code; ++i) { table[0][i] = 0; table[1][i] = i; } for (; i < (1 << MAX_LWZ_BITS); ++i) table[0][i] = table[1][0] = 0; sp = stack; return 0; } else if (fresh) { fresh = FALSE; do { firstcode = oldcode = GetCode(fd, code_size, FALSE); } while (firstcode == clear_code); return firstcode; } if (sp > stack) return *--sp; while ((code = GetCode(fd, code_size, FALSE)) >= 0) { if (code == clear_code) { for (i = 0; i < clear_code; ++i) { table[0][i] = 0; table[1][i] = i; } for (; i < (1 << MAX_LWZ_BITS); ++i) table[0][i] = table[1][i] = 0; code_size = set_code_size + 1; max_code_size = 2 * clear_code; max_code = clear_code + 2; sp = stack; firstcode = oldcode = GetCode(fd, code_size, FALSE); return firstcode; } else if (code == end_code) { int count; unsigned char buf[260]; if (ZeroDataBlock) return -2; while ((count = GetDataBlock(fd, buf)) > 0); if (count != 0) { /* * pm_message("missing EOD in data stream (common occurence)"); */ } return -2; } incode = code; if (code >= max_code) { *sp++ = firstcode; code = oldcode; } while (code >= clear_code) { *sp++ = table[1][code]; if (code == table[0][code]) fprintf(stderr, "circular table entry BIG ERROR...\n"); code = table[0][code]; } *sp++ = firstcode = table[1][code]; if ((code = max_code) < (1 << MAX_LWZ_BITS)) { table[0][code] = oldcode; table[1][code] = firstcode; ++max_code; if ((max_code >= max_code_size) && (max_code_size < (1 << MAX_LWZ_BITS))) { max_code_size *= 2; ++code_size; } } oldcode = incode; if (sp > stack) return *--sp; } return code; } static int ReadImage(FILE * fd, XImage *ximage, int width, int height, int cmapSize, unsigned char cmap[3][MAXCOLORMAPSIZE], int gray, int interlace) { unsigned char c; char *out; int v, ind; int xpos = 0, ypos = 0, pass = 0; unsigned char *scan; /* ** Initialize the compression routines */ scan = (unsigned char *)malloc(3*width); if (!scan) return 4; if (!ReadOK(fd, &c, 1)) { return 2; } if (LWZReadByte(fd, TRUE, c) < 0) { return 2; } while ((v = LWZReadByte(fd, FALSE, c)) >= 0) { ind = 3*xpos; scan[ind] = cmap[CM_RED][v]; scan[ind+1] = cmap[CM_GREEN][v]; scan[ind+2] = cmap[CM_BLUE][v]; out = ximage->data + ypos * ximage->bytes_per_line; ++xpos; if (xpos == width) { xpos = 0; if (interlace) { switch (pass) { case 0: case 1: ypos += 8; break; case 2: ypos += 4; break; case 3: ypos += 2; break; } if (ypos >= height) { ++pass; switch (pass) { case 1: ypos = 4; break; case 2: ypos = 2; break; case 3: ypos = 1; break; default: goto fini; } } } else { ++ypos; } fill_line(scan, out, width, width); } if (ypos >= height) break; } fini: free(scan); return 0; } /* JPEG routines */ struct error_mgr { struct jpeg_error_mgr pub; /* "public" fields */ jmp_buf setjmp_buffer; /* for return to caller */ }; typedef struct error_mgr * error_ptr; void error_exit (j_common_ptr cinfo) { /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ error_ptr err = (error_ptr) cinfo->err; /* Always display the message. */ /* We could postpone this until after returning, if we chose. */ (*cinfo->err->output_message) (cinfo); /* Return control to the setjmp point */ longjmp(err->setjmp_buffer, 1); } XImage * readJPG(char * file, int height, Colordata *color) { FILE *input_file; XImage *ximage; struct jpeg_decompress_struct cinfo; struct error_mgr jerr; double ratio; int l, prev, next=0, size, width; JSAMPROW scanline[1]; char *scan, *c; if ((input_file = fopen(file, "r")) == NULL) return NULL; cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = error_exit; if (setjmp(jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, * and return. */ jpeg_destroy_decompress(&cinfo); fclose(input_file); return NULL; } jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, input_file); jpeg_read_header(&cinfo, TRUE); if (cinfo.jpeg_color_space == JCS_GRAYSCALE) return NULL; if (height == 0) { width = cinfo.image_width; height = cinfo.image_height; ratio = 1.0; cinfo.scale_denom = 1; } else { width = (int)((double) cinfo.image_width * (double) height / (double) cinfo.image_height + 0.5); ratio = ((double) cinfo.image_width/(double) width + (double) cinfo.image_height/(double) height )/1.8; if (ratio>=8.0) cinfo.scale_denom = 8; else if (ratio>=4.0) cinfo.scale_denom = 4; else if (ratio>=2.0) cinfo.scale_denom = 2; else cinfo.scale_denom = 1; } jpeg_start_decompress(&cinfo); ximage = XCreateImage(dpy, visual, DefaultDepth(dpy, scr), ZPixmap, 0, NULL, width, height, color_pad, 0); XFlush(dpy); if (!ximage) return NULL; bytes_per_pixel = (ximage->bits_per_pixel/8); size = ximage->bytes_per_line * height; ximage->data = (char *) malloc(size); scan = (char *) malloc(3 * cinfo.output_width * sizeof(char)); #if 0 /* verbose */ fprintf(stderr, "Loading %s\n" "Rescaling JPEG data by 1/%d, " "%d %d --> %d %d, %d bytes per pixel\n", file, cinfo.scale_denom, cinfo.image_width, cinfo.image_height, width, height, bytes_per_pixel); #endif prev = -1; scanline[0] = (JSAMPROW) scan; while (cinfo.output_scanline < cinfo.output_height) { (void) jpeg_read_scanlines(&cinfo, scanline, (JDIMENSION) 1); next = ((2*cinfo.output_scanline - 1) * height)/ (2*(int)cinfo.output_height); if (next>=0) { if (next>=height) { next = height - 1; /* get loop to stop at next iteration ! */ cinfo.output_scanline = cinfo.output_height; } for (l = prev+1; l<= next; l++) { c = ximage->data + l * ximage->bytes_per_line; fill_line(scan, c, cinfo.output_width, width); } prev = next; } } free(scan); jpeg_destroy_decompress(&cinfo); fclose(input_file); if (jerr.pub.num_warnings > 0) { longjmp(jerr.setjmp_buffer, 1); } return ximage; } /* XPM routines */ XImage * readXPM(char *file, int height, Colordata *color) { XImage *image; XpmAttributes attrib; XpmColorSymbol flagbg; XColor xc; #ifdef XPMBUG char *buffer; gzFile fd; #endif int j, k; if (color_depth<=8) { attrib.valuemask = XpmColormap; attrib.valuemask = XpmColormap | XpmReturnPixels | XpmColorSymbols; attrib.colormap = XCreateColormap(dpy, mainwin, visual, AllocNone); attrib.numsymbols = 1; attrib.colorsymbols = &flagbg; flagbg.name = NULL; flagbg.value = "None"; flagbg.pixel = 255; } else { attrib.valuemask = XpmColormap | XpmReturnPixels | XpmColorSymbols; attrib.colormap = cmap; attrib.numsymbols = 1; attrib.colorsymbols = &flagbg; flagbg.pixel = color->pix; flagbg.name = NULL; flagbg.value = "None"; } if (!file || !*file) return NULL; image = NULL; #ifdef XPMBUG fd = gzopen(file, "r"); buffer = NULL; j = 0; k = -1; while (!gzeof(fd)) { ++k; if (k>=j) { j += 4096; buffer = realloc(buffer, j); } buffer[k] = gzgetc(fd); } gzclose(fd); if (XpmCreateImageFromBuffer(dpy, buffer, &image, NULL, &attrib) != XpmSuccess) { free(buffer); return NULL; } free(buffer); #else if (XpmReadFileToImage(dpy, file, &image, NULL, &attrib) != XpmSuccess) return NULL; #endif if (image) bytes_per_pixel = image->bits_per_pixel/8; else return NULL; if (color_depth<=8) { unsigned char * cvs_table; unsigned char r, g, b, *c; cvs_table = (unsigned char*) malloc(256); for (j=0; j<256; j++) { xc.pixel = j; XQueryColor(dpy, attrib.colormap, &xc); r = xc.red>>8; g = xc.green>>8; b = xc.blue>>8; cvs_table[j]=color_table[(((6*g)>>8)*36)+(((6*r)>>8)*6)+((6*b)>>8)]; } cvs_table[255] = color->pix; c = image->data; k = image->bytes_per_line * image->height; for (j=0; jheight) { return image; } return ximage_rescale(image, height); } XImage * readEPS(char *file, int height, Colordata *color) { XImage *ximage; char scan[80], buf[512]; double x1, x2, y1, y2, res; int l, width, zip; char *tmp; #ifdef ZLIB gzFile fd; #else FILE * fd; #endif zip = 0; tmp = mk_tmp(".png"); if (!tmp) return NULL; #ifdef ZLIB strcpy(buf, file); l = strlen(file); if (l>=3 && !strcmp(file+l-3, ".gz")) zip = -1; fd = gzopen(buf, "r"); if (!fd && zip==0) { strcat(buf, ".gz"); fd = gzopen(buf, "r"); if (!fd) return NULL; zip = 1; } width = 0; while (!gzeof(fd)) { gzgets(fd, buf, 256); if (!strncasecmp(buf, "%%HiResBoundingBox:", 19)) { sscanf(buf, "%s %lf %lf %lf %lf", scan, &x1, &y1, &x2, &y2); width = -1; break; } } gzclose(fd); #else fd = fopen(file, "r"); width = 0; while (!feof(fd)) { fgets(buf, 256, fd); if (!strncasecmp(buf, "%%HiResBoundingBox:", 19)) { sscanf(buf, "%s %lf %lf %lf %lf", scan, &x1, &y1, &x2, &y2); width = 1; break; } } fclose(fd); #endif if (!width) { return NULL; } res = (72.0 * height) / y2; width = (int) (0.999 + height * x2 / y2); if (zip) sprintf(buf, "zcat %s%s | gs -r%f -sDEVICE=pngalpha -dNOPAUSE -dQUIET " "-g%dx%d -sOutputFile=%s - -c quit", file, (zip==1)?".gz":"", res, width, height, tmp); else sprintf(buf, "gs -r%f -sDEVICE=pngalpha -dNOPAUSE -dQUIET -g%dx%d " "-sOutputFile=%s %s -c quit", res, width, height, tmp, file); system(buf); ximage = readPNG(tmp, 0, color); unlink(tmp); return ximage; } XImage * readSVG(char *file, int height, Colordata *color) { XImage * ximage; char buf[512]; char *tmp; int l, zip; #ifdef ZLIB gzFile fd; #else FILE * fd; #endif zip = 0; tmp = mk_tmp(".png"); if (!tmp) return NULL; #ifdef ZLIB strcpy(buf, file); fd = gzopen(buf, "r"); l = strlen(file); if (l>=3 && !strcmp(file+l-3, ".gz")) zip = -1; if (!fd && zip==0) { strcat(buf, ".gz"); fd = gzopen(buf, "r"); if (!fd) return NULL; zip = 1; } gzclose(fd); #endif sprintf(buf, "inkscape %s%s --export-height=%d --export-png=%s", file, (zip==1)?".gz":"", height, tmp); system(buf); ximage = readPNG(tmp, 0, color); unlink(tmp); return ximage; } int image_type(char *name) { int k, l, ret; char *ptr; ret = -1; if ((k=strlen(name))>=4 && name[k-4] == '.') { ptr = name + k-3; for (l=0; l=7 && name[k-7] == '.' && !strcmp(name+k-3, ".gz")) { ptr = name + k-6; for (l=0; l=0) { /* image extension specified */ if (default_dir && *default_dir) sprintf(name, "%s/%s", default_dir, file); else strcpy(name, file); } else { /* image extension not specified - try to find ... */ s = flag_size * (num_flag_dirs+1); *name = '\0'; for (l=0; l9) k = flag_ordering[l+s] - 'a' + 9; if (k<0 || k>=num_flag_dirs) continue; sprintf(name, "%s/%s/%s.%s", FLAGPATH, flag_dir[k], file, flag_type[k]); if (!stat(name, &buf) && S_ISREG(buf.st_mode)) break; strcat(name, ".gz"); if (!stat(name, &buf) && S_ISREG(buf.st_mode)) break; } } } if (!*name) { strcpy(name, file); image = NULL; goto error; } l = strlen(name); if (l<=2 || strcmp(name+l-3, ".gz")) { if (stat(name, &buf) || !S_ISREG(buf.st_mode)) strcat(name, ".gz"); } if (stat(name, &buf) || !S_ISREG(buf.st_mode)) { image = NULL; goto error; } k = image_type(name); switch(k) { case 0: image = readXPM(name, height, color); break; case 1: image = readGIF(name, height, color); break; case 2: image = readPNG(name, height, color); break; case 3: image = readJPG(name, height, color); break; case 4: image = readEPS(name, height, color); break; case 5: image = readSVG(name, height, color); break; default: image = NULL; break; } error: if (!image) { sprintf(errstr, msg[COULDNT_READ_IMAGE_FILE], name); if (runlevel) { if (error_msg) free(error_msg); error_msg = strdup(errstr); brief_menu = 4; show_brief_menu(scene); } else fprintf(stderr, "%s\n", errstr); } return image; } Pixmap xim2pix(XImage *ximage) { GC gc; XGCValues values; Pixmap pixmap; if (!ximage) return None; pixmap = XCreatePixmap(dpy, datawin, ximage->width, ximage->height, ximage->depth); if (!pixmap) return pixmap; /* set fg and bg in case we have an XYBitmap */ values.foreground = 1; values.background = 0; gc = XCreateGC(dpy, pixmap, GCForeground | GCBackground, &values); if (!gc) { XFreePixmap(dpy, pixmap); return None; } XPutImage(dpy, pixmap, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height); XFreeGC(dpy, gc); return pixmap; }