diff options
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.c | 437 |
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 | |||
38 | typedef 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 | |||
47 | typedef my_source_mgr *my_src_ptr; | ||
48 | |||
49 | /* Stuff to stop jpeglib from exit() when things fail. */ | ||
50 | struct my_error_mgr | ||
51 | { | ||
52 | struct jpeg_error_mgr pub; /* "public" fields */ | ||
53 | jmp_buf setjmp_buffer; /* for return to caller */ | ||
54 | }; | ||
55 | |||
56 | typedef struct my_error_mgr *my_error_ptr; | ||
57 | |||
58 | /* | ||
59 | * Here's the routine that will replace the standard error_exit method: | ||
60 | */ | ||
61 | |||
62 | METHODDEF(void) | ||
63 | my_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 | |||
77 | static void init_stream_source (j_decompress_ptr cinfo); | ||
78 | static boolean fill_stream_input_buffer (j_decompress_ptr cinfo); | ||
79 | static void skip_input_data (j_decompress_ptr cinfo, long num_bytes); | ||
80 | /*static void resync_to_restart (j_decompress_ptr cinfo, int desired);*/ | ||
81 | static void term_source (j_decompress_ptr cinfo); | ||
82 | static void jpeg_stream_src(struct jpeg_decompress_struct *cinfo, G3DStream *stream); | ||
83 | |||
84 | |||
85 | EAPI | ||
86 | gchar *plugin_description(G3DContext *context) | ||
87 | { | ||
88 | return g_strdup("JPEG images."); | ||
89 | } | ||
90 | |||
91 | EAPI | ||
92 | gchar **plugin_extensions(G3DContext *context) | ||
93 | { | ||
94 | return g_strsplit("jpg:jpeg:jpe:jfif:jif", ":", 0); | ||
95 | } | ||
96 | |||
97 | EAPI | ||
98 | gboolean 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 | |||
286 | static 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 | */ | ||
308 | static 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 | */ | ||
344 | static 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 | */ | ||
389 | static void term_source (j_decompress_ptr cinfo) | ||
390 | { | ||
391 | /* no work necessary here */ | ||
392 | } | ||
393 | /* | ||
394 | For 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 | |||
396 | may swallow the EOI and again demand data ... just keep feeding it fake EOIs. | ||
397 | |||
398 | jdatasrc.c illustrates the recommended error recovery behavior. | ||
399 | |||
400 | term_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 | |||
402 | You 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 | |||
404 | For more information, consult the stdio source and destination managers in jdatasrc.c and jdatadst.c. | ||
405 | */ | ||
406 | |||
407 | static 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 | |||