]> Pileus Git - ~andy/gtk/blob - gdk-pixbuf/io-jpeg.c
Set the initial ref_count to 1.
[~andy/gtk] / gdk-pixbuf / io-jpeg.c
1 /*
2   io-jpeg.c: GdkPixBuf loader for jpeg files.
3
4   Based on io-jpeg from gdk_imlib, but not much.
5
6   This code is licensed under the Lesser GNU
7   General Public License, version 2.1.
8
9   Author:
10     Michael Zucchi <zucchi@zedzone.mmc.com.au>
11 */
12
13 #include <config.h>
14 #include <stdio.h>
15 #include <glib.h>
16 #include <setjmp.h>
17 #include "gdk-pixbuf.h"
18 /*#include "gdk-pixbuf-io.h"*/
19 #include <jpeglib.h>
20
21 /* error handler data */
22 struct iojpeg_JPEG_error_mgr
23 {
24         struct jpeg_error_mgr pub;
25         sigjmp_buf          setjmp_buffer;
26 };
27
28 static void
29 g_JPEGFatalErrorHandler(j_common_ptr cinfo)
30 {
31         /* FIXME:
32          * We should somehow signal what error occurred to the caller so the
33          * caller can handle the error message */
34         struct iojpeg_JPEG_error_mgr *errmgr;
35
36         errmgr = (struct iojpeg_JPEG_error_mgr *) cinfo->err;
37         cinfo->err->output_message(cinfo);
38         siglongjmp(errmgr->setjmp_buffer, 1);
39         return;
40 }
41
42 GdkPixBuf *image_load(FILE *f)
43 {
44         int w,h,i,j;
45         art_u8 *pixels=NULL, *dptr;
46         unsigned char *lines[4], /* Used to expand rows, via rec_outbuf_height, from
47                                   the header file:
48                                   "* Usually rec_outbuf_height will be 1 or 2, at most 4." */
49                 **lptr;
50         struct jpeg_decompress_struct cinfo;
51         struct iojpeg_JPEG_error_mgr jerr;
52         GdkPixBuf *pixbuf;
53
54         /* setup error handler */
55         cinfo.err = jpeg_std_error(&(jerr.pub));
56         jerr.pub.error_exit = g_JPEGFatalErrorHandler;
57
58         if (sigsetjmp(jerr.setjmp_buffer, 1)) {
59                 /* Whoops there was a jpeg error */
60                 if (pixels != NULL)
61                         art_free(pixels);
62                 jpeg_destroy_decompress(&cinfo);
63                 return NULL;
64         }
65
66         /* load header, setup */
67         jpeg_create_decompress(&cinfo);
68         jpeg_stdio_src(&cinfo, f);
69         jpeg_read_header(&cinfo, TRUE);
70         jpeg_start_decompress(&cinfo);
71         cinfo.do_fancy_upsampling = FALSE;
72         cinfo.do_block_smoothing = FALSE;
73
74         w = cinfo.output_width;
75         h = cinfo.output_height;
76         g_print("w: %d h: %d\n", w, h);
77
78         pixels = art_alloc(h * w * 3);
79         if (pixels == NULL) {
80                 jpeg_destroy_decompress(&cinfo);
81                 return NULL;
82         }
83         dptr = pixels;
84
85         /* decompress all the lines, a few at a time */
86
87         while (cinfo.output_scanline < cinfo.output_height) {
88                 lptr = lines;
89                 for (i=0;i<cinfo.rec_outbuf_height;i++) {
90                         *lptr++=dptr;
91                         dptr+=w*3;
92                 }
93                 jpeg_read_scanlines(&cinfo, lines, cinfo.rec_outbuf_height);
94                 if (cinfo.output_components==1) {
95                         /* expand grey->colour */
96                         /* expand from the end of the memory down, so we can use
97                            the same buffer */
98                         for (i=cinfo.rec_outbuf_height-1;i>=0;i--) {
99                                 unsigned char *from, *to;
100                                 from = lines[i]+w-1;
101                                 to = lines[i]+w*3-3;
102                                 for (j=w-1;j>=0;j--) {
103                                         to[0] = from[0];
104                                         to[1] = from[0];
105                                         to[2] = from[0];
106                                         to-=3;
107                                         from--;
108                                 }
109                         }
110                 }
111         }
112
113         jpeg_finish_decompress(&cinfo);
114         jpeg_destroy_decompress(&cinfo);
115
116         /* finish off, create the pixbuf */
117         pixbuf = g_new(GdkPixBuf, 1);
118         pixbuf->art_pixbuf = art_pixbuf_new_rgb(pixels, w, h, (w * 3));
119         if (!(pixbuf->art_pixbuf)) {
120                 art_free(pixels);
121                 g_free(pixbuf);
122                 return NULL;
123         }
124         pixbuf->ref_count = 1;
125         pixbuf->unref_func = NULL;
126
127         return pixbuf;
128 }
129
130 /*
131  * Local variables:
132  * c-basic-offset: 8
133  * End:
134  */