aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/plugins/image/img_jpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/image/img_jpeg.c')
-rw-r--r--src/others/mimesh/libg3d-0.0.8/plugins/image/img_jpeg.c437
1 files changed, 437 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/image/img_jpeg.c b/src/others/mimesh/libg3d-0.0.8/plugins/image/img_jpeg.c
new file mode 100644
index 0000000..138f26b
--- /dev/null
+++ b/src/others/mimesh/libg3d-0.0.8/plugins/image/img_jpeg.c
@@ -0,0 +1,437 @@
1/* $Id$ */
2
3/*
4 libg3d - 3D object loading library
5
6 Copyright (c) 2011, Dawid Seikel.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; version 2 of the License.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20*/
21
22
23/* This is an ugly collection of styles, I'll fix it up later, just want to get it pushed up now. lol */
24
25#include <stdio.h>
26#include <string.h>
27#include <errno.h>
28
29#include <g3d/types.h>
30#include <g3d/stream.h>
31
32#include <jpeglib.h>
33#include <jerror.h>
34#include <setjmp.h>
35
36#define BUFSIZE 1024
37
38typedef struct
39{
40 struct jpeg_source_mgr pub; /* public fields */
41
42 G3DStream *stream; /* source stream */
43 JOCTET *buffer; /* start of buffer */
44 boolean start_of_file; /* have we gotten any data yet? */
45} my_source_mgr;
46
47typedef my_source_mgr *my_src_ptr;
48
49/* Stuff to stop jpeglib from exit() when things fail. */
50struct my_error_mgr
51{
52 struct jpeg_error_mgr pub; /* "public" fields */
53 jmp_buf setjmp_buffer; /* for return to caller */
54};
55
56typedef struct my_error_mgr *my_error_ptr;
57
58/*
59 * Here's the routine that will replace the standard error_exit method:
60 */
61
62METHODDEF(void)
63my_error_exit (j_common_ptr cinfo)
64{
65 /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
66 my_error_ptr myerr = (my_error_ptr) cinfo->err;
67
68 /* Always display the message. */
69 /* We could postpone this until after returning, if we chose. */
70 (*cinfo->err->output_message) (cinfo);
71
72 /* Return control to the setjmp point */
73 longjmp(myerr->setjmp_buffer, 1);
74}
75
76
77static void init_stream_source (j_decompress_ptr cinfo);
78static boolean fill_stream_input_buffer (j_decompress_ptr cinfo);
79static void skip_input_data (j_decompress_ptr cinfo, long num_bytes);
80/*static void resync_to_restart (j_decompress_ptr cinfo, int desired);*/
81static void term_source (j_decompress_ptr cinfo);
82static void jpeg_stream_src(struct jpeg_decompress_struct *cinfo, G3DStream *stream);
83
84
85EAPI
86gchar *plugin_description(G3DContext *context)
87{
88 return g_strdup("JPEG images.");
89}
90
91EAPI
92gchar **plugin_extensions(G3DContext *context)
93{
94 return g_strsplit("jpg:jpeg:jpe:jfif:jif", ":", 0);
95}
96
97EAPI
98gboolean plugin_load_image_from_stream(G3DContext *context, G3DStream *stream, G3DImage *image, gpointer user_data)
99{
100 gsize n;
101 gboolean retval;
102 guint32 x, y, nchannels;
103
104 /* This struct contains the JPEG decompression parameters and pointers to
105 * working space (which is allocated as needed by the JPEG library).
106 */
107 struct jpeg_decompress_struct cinfo;
108 /* We use our private extension JPEG error handler.
109 * Note that this struct must live as long as the main JPEG parameter
110 * struct, to avoid dangling-pointer problems.
111 */
112 struct my_error_mgr jerr;
113 /* More stuff */
114 JSAMPARRAY buffer; /* Output row buffer */
115 int row_stride; /* physical row width in output buffer */
116
117 /* Step 1: allocate and initialize JPEG decompression object */
118
119 /* We set up the normal JPEG error routines, then override error_exit. */
120 cinfo.err = jpeg_std_error(&jerr.pub);
121 jerr.pub.error_exit = my_error_exit;
122 /* Establish the setjmp return context for my_error_exit to use. */
123 if (setjmp(jerr.setjmp_buffer)) {
124 /* If we get here, the JPEG code has signaled an error.
125 * We need to clean up the JPEG object, close the input file, and return.
126 */
127 jpeg_destroy_decompress(&cinfo);
128 return 0;
129 }
130 /* Now we can initialize the JPEG decompression object. */
131 jpeg_create_decompress(&cinfo);
132
133 /* Step 2: specify data source (eg, a file) */
134
135 jpeg_stream_src(&cinfo, stream);
136
137 /* Step 3: read file parameters with jpeg_read_header() */
138
139 (void) jpeg_read_header(&cinfo, TRUE);
140 /* We can ignore the return value from jpeg_read_header since
141 * (a) suspension is not possible with the stdio data source, and
142 * (b) we passed TRUE to reject a tables-only JPEG file as an error.
143 * See libjpeg.txt for more info.
144 */
145
146 /* Step 4: set parameters for decompression */
147
148 if (cinfo.jpeg_color_space != JCS_RGB)
149 {
150 g_warning("Jpeg plugin: %s: colorspace is not RGB, converting.", stream->uri);
151 cinfo.out_color_space = JCS_RGB;
152 }
153
154
155 /* Step 5: Start decompressor */
156
157 (void) jpeg_start_decompress(&cinfo);
158 /* We can ignore the return value since suspension is not possible
159 * with the stdio data source.
160 */
161
162 /* We may need to do some setup of our own at this point before reading
163 * the data. After jpeg_start_decompress() we have the correct scaled
164 * output image dimensions available, as well as the output colormap
165 * if we asked for color quantization.
166 * In this example, we need to make an output work buffer of the right size.
167 */
168 /* JSAMPLEs per row in output buffer */
169 row_stride = cinfo.output_width * cinfo.output_components;
170 /* Make a one-row-high sample array that will go away when done with image */
171 buffer = (*cinfo.mem->alloc_sarray)
172 ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
173
174/*
175//output_width image width and height, as scaled
176//output_height
177//out_color_components # of color components in out_color_space
178//output_components # of color components returned per pixel
179//colormap the selected colormap, if any
180//actual_number_of_colors number of entries in colormap
181*/
182 nchannels = cinfo.output_components;
183 if(nchannels < 3)
184 {
185 g_warning("Jpeg plugin: %s: has only %d channels", stream->uri, nchannels);
186 jpeg_destroy_decompress(&cinfo);
187 return FALSE;
188 }
189
190 image->width = cinfo.output_width;
191 image->height = cinfo.output_height;
192 image->depth = 32;
193 image->name = g_path_get_basename(stream->uri);
194 image->pixeldata = g_new0(guint8, image->width * image->height * 4);
195
196
197 /* Step 6: while (scan lines remain to be read) */
198 /* jpeg_read_scanlines(...); */
199
200 /* Here we use the library's state variable cinfo.output_scanline as the
201 * loop counter, so that we don't have to keep track ourselves.
202 */
203 y = 0;
204 while (cinfo.output_scanline < cinfo.output_height)
205 {
206 /* jpeg_read_scanlines expects an array of pointers to scanlines.
207 * Here the array is only one element long, but you could ask for
208 * more than one scanline at a time if that's more convenient.
209 */
210 (void) jpeg_read_scanlines(&cinfo, buffer, 1);
211/* for(y = 0; y < image->height; y ++) */
212 for(x = 0; x < image->width; x ++)
213 {
214 JSAMPROW p = buffer[0] + x * nchannels;
215
216 image->pixeldata[(y * image->width + x) * 4 + 0] = GETJSAMPLE(p[0]);
217 image->pixeldata[(y * image->width + x) * 4 + 1] = GETJSAMPLE(p[1]);
218 image->pixeldata[(y * image->width + x) * 4 + 2] = GETJSAMPLE(p[2]);
219 if(nchannels >= 4)
220 image->pixeldata[(y * image->width + x) * 4 + 3] = GETJSAMPLE(p[3]);
221 }
222 y++;
223 }
224
225 /* set alpha to 1.0 */
226 if(nchannels < 4)
227 for(y = 0; y < image->height; y ++)
228 for(x = 0; x < image->width; x ++)
229 image->pixeldata[(y * image->width + x) * 4 + 3] = 0xFF;
230
231 /* Step 7: Finish decompression */
232
233 (void) jpeg_finish_decompress(&cinfo);
234 /* We can ignore the return value since suspension is not possible
235 * with the stdio data source.
236 */
237
238 /* Step 8: Release JPEG decompression object */
239
240 /* This is an important step since it will release a good deal of memory. */
241 jpeg_destroy_decompress(&cinfo);
242
243 /* At this point you may want to check to see whether any corrupt-data
244 * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
245 */
246
247 return TRUE;
248}
249
250/*
251 * SOME FINE POINTS:
252 *
253 * In the above code, we ignored the return value of jpeg_read_scanlines,
254 * which is the number of scanlines actually read. We could get away with
255 * this because we asked for only one line at a time and we weren't using
256 * a suspending data source. See libjpeg.txt for more info.
257 *
258 * We cheated a bit by calling alloc_sarray() after jpeg_start_decompress();
259 * we should have done it beforehand to ensure that the space would be
260 * counted against the JPEG max_memory setting. In some systems the above
261 * code would risk an out-of-memory error. However, in general we don't
262 * know the output image dimensions before jpeg_start_decompress(), unless we
263 * call jpeg_calc_output_dimensions(). See libjpeg.txt for more about this.
264 *
265 * Scanlines are returned in the same order as they appear in the JPEG file,
266 * which is standardly top-to-bottom. If you must emit data bottom-to-top,
267 * you can use one of the virtual arrays provided by the JPEG memory manager
268 * to invert the data. See wrbmp.c for an example.
269 *
270 * As with compression, some operating modes may require temporary files.
271 * On some systems you may need to set up a signal handler to ensure that
272 * temporary files are deleted if the program is interrupted. See libjpeg.txt.
273 */
274
275
276 const JOCTET * next_input_byte; /* => next byte to read from buffer */
277 size_t bytes_in_buffer; /* # of bytes remaining in buffer */
278
279/*
280 Initialize source. This is called by jpeg_read_header() before any
281 data is actually read. Unlike init_destination(), it may leave
282 bytes_in_buffer set to 0 (in which case a fill_input_buffer() call
283 will occur immediately).
284*/
285
286static void init_stream_source (j_decompress_ptr cinfo)
287{
288 my_src_ptr src = (my_src_ptr) cinfo->src;
289
290 /* We reset the empty-input-file flag for each image,
291 * but we don't clear the input buffer.
292 * This is correct behavior for reading a series of images from one source.
293 */
294 src->start_of_file = TRUE;
295}
296
297/*
298 This is called whenever bytes_in_buffer has reached zero and more
299 data is wanted. In typical applications, it should read fresh data
300 into the buffer (ignoring the current state of next_input_byte and
301 bytes_in_buffer), reset the pointer & count to the start of the
302 buffer, and return TRUE indicating that the buffer has been reloaded.
303 It is not necessary to fill the buffer entirely, only to obtain at
304 least one more byte. bytes_in_buffer MUST be set to a positive value
305 if TRUE is returned. A FALSE return should only be used when I/O
306 suspension is desired (this mode is discussed in the next section).
307*/
308static boolean fill_stream_input_buffer (j_decompress_ptr cinfo)
309{
310 my_src_ptr src = (my_src_ptr) cinfo->src;
311 size_t nbytes = 0;
312
313 if (!g3d_stream_eof(src->stream))
314 nbytes = g3d_stream_read(src->stream, src->buffer, BUFSIZE);
315
316 if (nbytes <= 0)
317 {
318 if (src->start_of_file) /* Treat empty input file as fatal error */
319 ERREXIT(cinfo, JERR_INPUT_EMPTY);
320 WARNMS(cinfo, JWRN_JPEG_EOF);
321 /* Insert a fake EOI marker */
322 src->buffer[0] = (JOCTET) 0xFF;
323 src->buffer[1] = (JOCTET) JPEG_EOI;
324 nbytes = 2;
325 }
326
327 src->pub.next_input_byte = src->buffer;
328 src->pub.bytes_in_buffer = nbytes;
329 src->start_of_file = FALSE;
330
331 return TRUE;
332}
333
334/*
335 Skip num_bytes worth of data. The buffer pointer and count should
336 be advanced over num_bytes input bytes, refilling the buffer as
337 needed. This is used to skip over a potentially large amount of
338 uninteresting data (such as an APPn marker). In some applications
339 it may be possible to optimize away the reading of the skipped data,
340 but it's not clear that being smart is worth much trouble; large
341 skips are uncommon. bytes_in_buffer may be zero on return.
342 A zero or negative skip count should be treated as a no-op.
343*/
344static void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
345{
346 struct jpeg_source_mgr * src = cinfo->src;
347
348 /* Just a dumb implementation for now. Could use fseek() except
349 * it doesn't work on pipes. Not clear that being smart is worth
350 * any trouble anyway --- large skips are infrequent.
351 */
352 if (num_bytes > 0)
353 {
354 while (num_bytes > (long) src->bytes_in_buffer)
355 {
356 num_bytes -= (long) src->bytes_in_buffer;
357 (void) (*src->fill_input_buffer) (cinfo);
358 /* note we assume that fill_input_buffer will never return FALSE,
359 * so suspension need not be handled.
360 */
361 }
362 src->next_input_byte += (size_t) num_bytes;
363 src->bytes_in_buffer -= (size_t) num_bytes;
364 }
365}
366
367/*
368 This routine is called only when the decompressor has failed to find
369 a restart (RSTn) marker where one is expected. Its mission is to
370 find a suitable point for resuming decompression. For most
371 applications, we recommend that you just use the default resync
372 procedure, jpeg_resync_to_restart(). However, if you are able to back
373 up in the input data stream, or if you have a-priori knowledge about
374 the likely location of restart markers, you may be able to do better.
375 Read the read_restart_marker() and jpeg_resync_to_restart() routines
376 in jdmarker.c if you think you'd like to implement your own resync
377 procedure.
378*/
379/*
380//static void resync_to_restart (j_decompress_ptr cinfo, int desired)
381//{
382//}
383*/
384
385/*
386 Terminate source --- called by jpeg_finish_decompress() after all
387 data has been read. Often a no-op.
388*/
389static void term_source (j_decompress_ptr cinfo)
390{
391 /* no work necessary here */
392}
393/*
394For both fill_input_buffer() and skip_input_data(), there is no such thing as an EOF return. If the end of the file has been reached, the routine has a choice of exiting via ERREXIT() or inserting fake data into the buffer. In most cases, generating a warning message and inserting a fake EOI marker is the best course of action --- this will allow the decompressor to output however much of the image is there. In pathological cases, the decompressor
395
396may swallow the EOI and again demand data ... just keep feeding it fake EOIs.
397
398jdatasrc.c illustrates the recommended error recovery behavior.
399
400term_source() is NOT called by jpeg_abort() or jpeg_destroy(). If you want the source manager to be cleaned up during an abort, you must do it yourself.
401
402You will also need code to create a jpeg_source_mgr struct, fill in its method pointers, and insert a pointer to the struct into the "src" field of the JPEG decompression object. This can be done in-line in your setup code if you like, but it's probably cleaner to provide a separate routine similar to the jpeg_stdio_src() routine of the supplied source manager.
403
404For more information, consult the stdio source and destination managers in jdatasrc.c and jdatadst.c.
405*/
406
407static void jpeg_stream_src(struct jpeg_decompress_struct *cinfo, G3DStream *stream)
408{
409 my_source_mgr *src;
410
411 if (stream == NULL)
412 ERREXIT(cinfo, JERR_INPUT_EMPTY);
413
414 /* The source object is made permanent so that a series of JPEG images
415 * can be read from the same buffer by calling jpeg_mem_src only before
416 * the first one.
417 */
418 if (cinfo->src == NULL) { /* first time for this JPEG object? */
419 cinfo->src = (struct jpeg_source_mgr *)
420 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(my_source_mgr));
421
422 src = (my_src_ptr) cinfo->src;
423 src->buffer = (JOCTET *)
424 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, BUFSIZE * sizeof(JOCTET));
425 }
426
427 src = (my_src_ptr) cinfo->src;
428 src->pub.init_source = init_stream_source;
429 src->pub.fill_input_buffer = fill_stream_input_buffer;
430 src->pub.skip_input_data = skip_input_data;
431 src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
432 src->pub.term_source = term_source;
433 src->stream = stream;
434 src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
435 src->pub.next_input_byte = NULL; /* until buffer loaded */
436}
437