]> Creatis software - gdcm.git/blob - src/gdcmjasper/src/libjasper/jpg/jpg_dec.c
a52db73a1aac848424f1c571037b6c65eb26a95f
[gdcm.git] / src / gdcmjasper / src / libjasper / jpg / jpg_dec.c
1 /*
2  * Copyright (c) 2001-2003 Michael David Adams.
3  * All rights reserved.
4  */
5
6 /* __START_OF_JASPER_LICENSE__
7  * 
8  * JasPer License Version 2.0
9  * 
10  * Copyright (c) 1999-2000 Image Power, Inc.
11  * Copyright (c) 1999-2000 The University of British Columbia
12  * Copyright (c) 2001-2003 Michael David Adams
13  * 
14  * All rights reserved.
15  * 
16  * Permission is hereby granted, free of charge, to any person (the
17  * "User") obtaining a copy of this software and associated documentation
18  * files (the "Software"), to deal in the Software without restriction,
19  * including without limitation the rights to use, copy, modify, merge,
20  * publish, distribute, and/or sell copies of the Software, and to permit
21  * persons to whom the Software is furnished to do so, subject to the
22  * following conditions:
23  * 
24  * 1.  The above copyright notices and this permission notice (which
25  * includes the disclaimer below) shall be included in all copies or
26  * substantial portions of the Software.
27  * 
28  * 2.  The name of a copyright holder shall not be used to endorse or
29  * promote products derived from the Software without specific prior
30  * written permission.
31  * 
32  * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
33  * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
34  * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
35  * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
36  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
37  * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
38  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
39  * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
40  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
41  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
42  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
43  * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
44  * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
45  * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
46  * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
47  * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
48  * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
49  * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
50  * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
51  * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
52  * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
53  * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
54  * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
55  * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
56  * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
57  * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
58  * 
59  * __END_OF_JASPER_LICENSE__
60  */
61
62 /******************************************************************************\
63 * Includes.
64 \******************************************************************************/
65
66 #include <stdio.h>
67 #include <assert.h>
68 #include <ctype.h>
69
70 #include "jasper/jas_tvp.h"
71 #include "jasper/jas_stream.h"
72 #include "jasper/jas_image.h"
73 #include "jasper/jas_string.h"
74
75 #include "jpg_jpeglib.h"
76 #include "jpg_cod.h"
77
78 /******************************************************************************\
79 * Types.
80 \******************************************************************************/
81
82 /* JPEG decoder data sink type. */
83
84 typedef struct jpg_dest_s {
85
86   /* Initialize output. */
87   void (*start_output)(j_decompress_ptr cinfo, struct jpg_dest_s *dinfo);
88
89   /* Output rows of decompressed data. */
90   void (*put_pixel_rows)(j_decompress_ptr cinfo, struct jpg_dest_s *dinfo,
91     JDIMENSION rows_supplied);
92
93   /* Cleanup output. */
94   void (*finish_output)(j_decompress_ptr cinfo, struct jpg_dest_s *dinfo);
95
96   /* Output buffer. */
97   JSAMPARRAY buffer;
98
99   /* Height of output buffer. */
100   JDIMENSION buffer_height;
101
102   /* The current row. */
103   JDIMENSION row;
104
105   /* The image used to hold the decompressed sample data. */
106   jas_image_t *image;
107
108   /* The row buffer. */
109   jas_matrix_t *data;
110
111   /* The error indicator.  If this is nonzero, something has gone wrong
112     during decompression. */
113   int error;
114
115 } jpg_dest_t;
116
117 /******************************************************************************\
118 * Local functions.
119 \******************************************************************************/
120
121 static void jpg_start_output(j_decompress_ptr cinfo, jpg_dest_t *dinfo);
122 static void jpg_put_pixel_rows(j_decompress_ptr cinfo, jpg_dest_t *dinfo,
123   JDIMENSION rows_supplied);
124 static void jpg_finish_output(j_decompress_ptr cinfo, jpg_dest_t *dinfo);
125 static int jpg_copystreamtofile(FILE *out, jas_stream_t *in);
126 static jas_image_t *jpg_mkimage(j_decompress_ptr cinfo);
127
128 /******************************************************************************\
129 * Code for load operation.
130 \******************************************************************************/
131
132 /* Load an image from a stream in the JPG format. */
133
134 jas_image_t *jpg_decode(jas_stream_t *in, char *optstr)
135 {
136   struct jpeg_decompress_struct cinfo;
137   struct jpeg_error_mgr jerr;
138   FILE *input_file;
139   jpg_dest_t dest_mgr_buf;
140   jpg_dest_t *dest_mgr = &dest_mgr_buf;
141   int num_scanlines;
142   jas_image_t *image;
143
144   /* Avoid compiler warnings about unused parameters. */
145   optstr = 0;
146
147   image = 0;
148   input_file = 0;
149   if (!(input_file = tmpfile())) {
150     goto error;
151   }
152   if (jpg_copystreamtofile(input_file, in)) {
153     goto error;
154   }
155   rewind(input_file);
156
157   /* Allocate and initialize a JPEG decompression object. */
158   cinfo.err = jpeg_std_error(&jerr);
159   jpeg_create_decompress(&cinfo);
160
161   /* Specify the data source for decompression. */
162   jpeg_stdio_src(&cinfo, input_file);
163
164   /* Read the file header to obtain the image information. */
165   jpeg_read_header(&cinfo, TRUE);
166
167   /* Start the decompressor. */
168   jpeg_start_decompress(&cinfo);
169
170   /* Create an image object to hold the decoded data. */
171   if (!(image = jpg_mkimage(&cinfo))) {
172     goto error;
173   }
174
175   /* Initialize the data sink object. */
176   dest_mgr->image = image;
177   dest_mgr->data = jas_matrix_create(1, cinfo.output_width);
178   dest_mgr->start_output = jpg_start_output;
179   dest_mgr->put_pixel_rows = jpg_put_pixel_rows;
180   dest_mgr->finish_output = jpg_finish_output;
181     dest_mgr->buffer = (*cinfo.mem->alloc_sarray)
182       ((j_common_ptr) &cinfo, JPOOL_IMAGE,
183        cinfo.output_width * cinfo.output_components, (JDIMENSION) 1);
184   dest_mgr->buffer_height = 1;
185   dest_mgr->error = 0;
186
187   /* Process the compressed data. */
188   (*dest_mgr->start_output)(&cinfo, dest_mgr);
189   while (cinfo.output_scanline < cinfo.output_height) {
190     num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
191       dest_mgr->buffer_height);
192     (*dest_mgr->put_pixel_rows)(&cinfo, dest_mgr, num_scanlines);
193   }
194   (*dest_mgr->finish_output)(&cinfo, dest_mgr);
195
196   /* Complete the decompression process. */
197   jpeg_finish_decompress(&cinfo);
198
199   /* Destroy the JPEG decompression object. */
200   jpeg_destroy_decompress(&cinfo);
201
202   jas_matrix_destroy(dest_mgr->data);
203
204   fclose(input_file);
205
206   if (dest_mgr->error) {
207     goto error;
208   }
209
210   return image;
211
212 error:
213   if (image) {
214     jas_image_destroy(image);
215   }
216   if (input_file) {
217     fclose(input_file);
218   }
219   return 0;
220 }
221
222 /******************************************************************************\
223 *
224 \******************************************************************************/
225
226 static jas_image_t *jpg_mkimage(j_decompress_ptr cinfo)
227 {
228   jas_image_t *image;
229   int cmptno;
230   jas_image_cmptparm_t cmptparm;
231   int numcmpts;
232
233   image = 0;
234   numcmpts = cinfo->output_components;
235   if (!(image = jas_image_create0())) {
236     goto error;
237   }
238   for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
239     cmptparm.tlx = 0;
240     cmptparm.tly = 0;
241     cmptparm.hstep = 1;
242     cmptparm.vstep = 1;
243     cmptparm.width = cinfo->image_width;
244     cmptparm.height = cinfo->image_height;
245     cmptparm.prec = 8;
246     cmptparm.sgnd = false;
247     if (jas_image_addcmpt(image, cmptno, &cmptparm)) {
248       goto error;
249     }
250   }
251
252   if (numcmpts == 3) {
253     jas_image_setclrspc(image, JAS_CLRSPC_SRGB);
254     jas_image_setcmpttype(image, 0,
255       JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
256     jas_image_setcmpttype(image, 1,
257       JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
258     jas_image_setcmpttype(image, 2,
259       JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
260   } else {
261     jas_image_setclrspc(image, JAS_CLRSPC_SGRAY);
262     jas_image_setcmpttype(image, 0,
263       JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
264   }
265
266   return image;
267
268 error:
269   if (image) {
270     jas_image_destroy(image);
271   }
272   return 0;
273 }
274
275 /******************************************************************************\
276 * Data source code.
277 \******************************************************************************/
278
279 static int jpg_copystreamtofile(FILE *out, jas_stream_t *in)
280 {
281   int c;
282
283   while ((c = jas_stream_getc(in)) != EOF) {
284     if (fputc(c, out) == EOF) {
285       return -1;
286     }
287   }
288   if (jas_stream_error(in)) {
289     return -1;
290   }
291   return 0;
292 }
293
294 /******************************************************************************\
295 * Data sink code.
296 \******************************************************************************/
297
298 static void jpg_start_output(j_decompress_ptr cinfo, jpg_dest_t *dinfo)
299 {
300   /* Avoid compiler warnings about unused parameters. */
301   cinfo = 0;
302
303   dinfo->row = 0;
304 }
305
306 static void jpg_put_pixel_rows(j_decompress_ptr cinfo, jpg_dest_t *dinfo,
307   JDIMENSION rows_supplied)
308 {
309   JSAMPLE *bufptr;
310   int cmptno;
311   JDIMENSION x;
312   uint_fast32_t width;
313
314   if (dinfo->error) {
315     return;
316   }
317
318   assert(cinfo->output_components == jas_image_numcmpts(dinfo->image));
319
320   for (cmptno = 0; cmptno < cinfo->output_components; ++cmptno) {
321     width = jas_image_cmptwidth(dinfo->image, cmptno);
322     bufptr = (dinfo->buffer[0]) + cmptno;
323     for (x = 0; x < width; ++x) {
324       jas_matrix_set(dinfo->data, 0, x, GETJSAMPLE(*bufptr));
325       bufptr += cinfo->output_components;
326     }
327     if (jas_image_writecmpt(dinfo->image, cmptno, 0, dinfo->row, width, 1,
328       dinfo->data)) {
329       dinfo->error = 1;
330     }
331   }
332   dinfo->row += rows_supplied;
333 }
334
335 static void jpg_finish_output(j_decompress_ptr cinfo, jpg_dest_t *dinfo)
336 {
337   /* Avoid compiler warnings about unused parameters. */
338   cinfo = 0;
339   dinfo = 0;
340 }