2 * Copyright (c) 2001-2003 Michael David Adams.
6 /* __START_OF_JASPER_LICENSE__
8 * JasPer License Version 2.0
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
14 * All rights reserved.
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:
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.
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
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.
59 * __END_OF_JASPER_LICENSE__
62 /******************************************************************************\
64 \******************************************************************************/
70 #include "jasper/jas_tvp.h"
71 #include "jasper/jas_stream.h"
72 #include "jasper/jas_image.h"
73 #include "jasper/jas_string.h"
75 #include "jpg_jpeglib.h"
78 /******************************************************************************\
80 \******************************************************************************/
82 /* JPEG decoder data sink type. */
84 typedef struct jpg_dest_s {
86 /* Initialize output. */
87 void (*start_output)(j_decompress_ptr cinfo, struct jpg_dest_s *dinfo);
89 /* Output rows of decompressed data. */
90 void (*put_pixel_rows)(j_decompress_ptr cinfo, struct jpg_dest_s *dinfo,
91 JDIMENSION rows_supplied);
94 void (*finish_output)(j_decompress_ptr cinfo, struct jpg_dest_s *dinfo);
99 /* Height of output buffer. */
100 JDIMENSION buffer_height;
102 /* The current row. */
105 /* The image used to hold the decompressed sample data. */
108 /* The row buffer. */
111 /* The error indicator. If this is nonzero, something has gone wrong
112 during decompression. */
117 /******************************************************************************\
119 \******************************************************************************/
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);
128 /******************************************************************************\
129 * Code for load operation.
130 \******************************************************************************/
132 /* Load an image from a stream in the JPG format. */
134 jas_image_t *jpg_decode(jas_stream_t *in, char *optstr)
136 struct jpeg_decompress_struct cinfo;
137 struct jpeg_error_mgr jerr;
139 jpg_dest_t dest_mgr_buf;
140 jpg_dest_t *dest_mgr = &dest_mgr_buf;
144 /* Avoid compiler warnings about unused parameters. */
149 if (!(input_file = tmpfile())) {
152 if (jpg_copystreamtofile(input_file, in)) {
157 /* Allocate and initialize a JPEG decompression object. */
158 cinfo.err = jpeg_std_error(&jerr);
159 jpeg_create_decompress(&cinfo);
161 /* Specify the data source for decompression. */
162 jpeg_stdio_src(&cinfo, input_file);
164 /* Read the file header to obtain the image information. */
165 jpeg_read_header(&cinfo, TRUE);
167 /* Start the decompressor. */
168 jpeg_start_decompress(&cinfo);
170 /* Create an image object to hold the decoded data. */
171 if (!(image = jpg_mkimage(&cinfo))) {
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;
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);
194 (*dest_mgr->finish_output)(&cinfo, dest_mgr);
196 /* Complete the decompression process. */
197 jpeg_finish_decompress(&cinfo);
199 /* Destroy the JPEG decompression object. */
200 jpeg_destroy_decompress(&cinfo);
202 jas_matrix_destroy(dest_mgr->data);
206 if (dest_mgr->error) {
214 jas_image_destroy(image);
222 /******************************************************************************\
224 \******************************************************************************/
226 static jas_image_t *jpg_mkimage(j_decompress_ptr cinfo)
230 jas_image_cmptparm_t cmptparm;
234 numcmpts = cinfo->output_components;
235 if (!(image = jas_image_create0())) {
238 for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
243 cmptparm.width = cinfo->image_width;
244 cmptparm.height = cinfo->image_height;
246 cmptparm.sgnd = false;
247 if (jas_image_addcmpt(image, cmptno, &cmptparm)) {
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));
261 jas_image_setclrspc(image, JAS_CLRSPC_SGRAY);
262 jas_image_setcmpttype(image, 0,
263 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
270 jas_image_destroy(image);
275 /******************************************************************************\
277 \******************************************************************************/
279 static int jpg_copystreamtofile(FILE *out, jas_stream_t *in)
283 while ((c = jas_stream_getc(in)) != EOF) {
284 if (fputc(c, out) == EOF) {
288 if (jas_stream_error(in)) {
294 /******************************************************************************\
296 \******************************************************************************/
298 static void jpg_start_output(j_decompress_ptr cinfo, jpg_dest_t *dinfo)
300 /* Avoid compiler warnings about unused parameters. */
306 static void jpg_put_pixel_rows(j_decompress_ptr cinfo, jpg_dest_t *dinfo,
307 JDIMENSION rows_supplied)
318 assert(cinfo->output_components == jas_image_numcmpts(dinfo->image));
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;
327 if (jas_image_writecmpt(dinfo->image, cmptno, 0, dinfo->row, width, 1,
332 dinfo->row += rows_supplied;
335 static void jpg_finish_output(j_decompress_ptr cinfo, jpg_dest_t *dinfo)
337 /* Avoid compiler warnings about unused parameters. */