#include "JpegI.h" #include #include #include void _XmJpegErrorExit(j_common_ptr cinfo) { int rc; XmJpegErrorMgr err = (XmJpegErrorMgr) cinfo->err; switch (cinfo->err->msg_code) { case JERR_NO_SOI: rc = 1; break; case JERR_OUT_OF_MEMORY: rc = 4; break; default: rc = 2; break; } longjmp(err->setjmp_buffer, rc); } int load_jpeg(FILE * infile, unsigned long *pWidth, unsigned long *pHeight, CTable ** image_data) { CTable *buf; struct jpeg_decompress_struct cinfo; XmJpegErrorMgrRec jerr; JSAMPROW row_pointer[1]; int x, y; int rc; *image_data = NULL; cinfo.err = jpeg_std_error((struct jpeg_error_mgr *) &jerr); jerr.pub.error_exit = _XmJpegErrorExit; if ((rc = setjmp(jerr.setjmp_buffer))) { jpeg_destroy_decompress(&cinfo); return rc; } jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, infile); jpeg_read_header(&cinfo, TRUE); jpeg_calc_output_dimensions(&cinfo); jpeg_start_decompress(&cinfo); *pWidth = cinfo.output_width; *pHeight = cinfo.output_height; *image_data = malloc(cinfo.output_width * cinfo.output_height * sizeof(CTable)); for (buf = *image_data; cinfo.output_scanline < cinfo.output_height; buf += cinfo.output_width) jpeg_read_scanlines(&cinfo, (JSAMPARRAY) (&buf), 1); if (cinfo.out_color_space == JCS_GRAYSCALE) { for (y = 0, buf = *image_data; y < cinfo.output_height; y++, buf += cinfo.output_width) for (x = cinfo.output_width - 1; x >= 0; x--) buf[x].red = buf[x].green = buf[x].blue = ((JSAMPLE *) buf)[x]; } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); return 0; } Pixel get_cval(unsigned char c, unsigned long mask) { Pixel value = c, x; int i; for (i = 0, x = 1; i < 32; i++, x <<= 1) if (mask & x) break; for (; i < 32; i++, x <<= 1) if (!(mask & x)) break; if (i < 8) value >>= 8 - i; else if (i > 8) value <<= i - 8; return (value & mask); } void store_pixel(Screen * screen, CTable * p, int x, char *cdata) { Pixel px = get_cval(p->red, screen->root_visual->red_mask) | get_cval(p->green, screen->root_visual->green_mask) | get_cval(p->blue, screen->root_visual->blue_mask); if (screen->root_depth <= 16) { if (ImageByteOrder(screen->display) == MSBFirst) { cdata[x * 2] = (px >> 8); cdata[x * 2 + 1] = (px & 0xff); } else { cdata[x * 2] = (px & 0xff); cdata[x * 2 + 1] = (px >> 8); } } else { if (ImageByteOrder(screen->display) == MSBFirst) { cdata[x * 4] = (px >> 24); cdata[x * 4 + 1] = (px >> 16); cdata[x * 4 + 2] = (px >> 8); cdata[x * 4 + 3] = (px & 0xff); } else { cdata[x * 4 + 3] = (px >> 24); cdata[x * 4 + 2] = (px >> 16); cdata[x * 4 + 1] = (px >> 8); cdata[x * 4] = (px & 0xff); } } } int _XmJpegGetImage(Screen * screen, FILE * infile, XImage ** ximage) { unsigned long image_width, image_height; unsigned char *xdata; int pad; CTable *image_data; int rc; if ((rc = load_jpeg(infile, &image_width, &image_height, &image_data))) return rc; if (screen->root_depth == 24 || screen->root_depth == 32) { xdata = (unsigned char *) malloc(4 * image_width * image_height); pad = 32; } else if (screen->root_depth == 16) { xdata = (unsigned char *) malloc(2 * image_width * image_height); pad = 16; } else { /* depth == 8 */ xdata = (unsigned char *) malloc(image_width * image_height); pad = 8; } if (!xdata) return 4; *ximage = XCreateImage(screen->display, screen->root_visual, screen->root_depth, ZPixmap, 0, (char *) xdata, image_width, image_height, pad, 0); if (!*ximage) { free(xdata); return 4; } { int xx, yy; CTable *p; for (yy = 0; yy < (*ximage)->height; yy++) { p = image_data + yy * (*ximage)->width; for (xx = 0; xx < (*ximage)->width; xx++, p++) store_pixel(screen, p, xx + yy * (*ximage)->width, (*ximage)->data); } } if (image_data) { free(image_data); image_data = NULL; } return 0; }