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