/* io-jpeg.c: GdkPixBuf loader for jpeg files. Based on io-jpeg from gdk_imlib, but not much. This code is licensed under the Lesser GNU General Public License, version 2.1. Author: Michael Zucchi */ #include #include #include #include #include "gdk-pixbuf.h" /*#include "gdk-pixbuf-io.h"*/ #include /* error handler data */ struct iojpeg_JPEG_error_mgr { struct jpeg_error_mgr pub; sigjmp_buf setjmp_buffer; }; static void g_JPEGFatalErrorHandler(j_common_ptr cinfo) { /* FIXME: * We should somehow signal what error occurred to the caller so the * caller can handle the error message */ struct iojpeg_JPEG_error_mgr *errmgr; errmgr = (struct iojpeg_JPEG_error_mgr *) cinfo->err; cinfo->err->output_message(cinfo); siglongjmp(errmgr->setjmp_buffer, 1); return; } GdkPixBuf *image_load(FILE *f) { int w,h,i,j; art_u8 *pixels=NULL, *dptr, *fptr, *pptr; unsigned char *lines[4], /* Used to expand rows, via rec_outbuf_height, from the header file: "* Usually rec_outbuf_height will be 1 or 2, at most 4." */ **lptr; struct jpeg_decompress_struct cinfo; struct iojpeg_JPEG_error_mgr jerr; GdkPixBuf *pixbuf; /* setup error handler */ cinfo.err = jpeg_std_error(&(jerr.pub)); jerr.pub.error_exit = g_JPEGFatalErrorHandler; if (sigsetjmp(jerr.setjmp_buffer, 1)) { /* Whoops there was a jpeg error */ if (pixels != NULL) art_free(pixels); jpeg_destroy_decompress(&cinfo); return NULL; } /* load header, setup */ jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, f); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); cinfo.do_fancy_upsampling = FALSE; cinfo.do_block_smoothing = FALSE; w = cinfo.output_width; h = cinfo.output_height; g_print("w: %d h: %d\n", w, h); pixels = art_alloc(h * w * 3); if (pixels == NULL) { jpeg_destroy_decompress(&cinfo); return NULL; } dptr = pixels; /* decompress all the lines, a few at a time */ while (cinfo.output_scanline < cinfo.output_height) { lptr = lines; for (i=0;icolour */ /* expand from the end of the memory down, so we can use the same buffer */ for (i=cinfo.rec_outbuf_height-1;i>=0;i--) { unsigned char *from, *to; from = lines[i]+w-1; to = lines[i]+w*3-3; for (j=w-1;j>=0;j++) { to[0] = from[0]; to[1] = from[0]; to[2] = from[0]; to-=3; from--; } } } } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); /* finish off, create the pixbuf */ pixbuf = g_new(GdkPixBuf, 1); pixbuf->art_pixbuf = art_pixbuf_new_rgb(pixels, w, h, (w * 3)); if (!(pixbuf->art_pixbuf)) return NULL; pixbuf->ref_count = 0; pixbuf->unref_func = NULL; return pixbuf; } /* * Local variables: * c-basic-offset: 8 * End: */