blob: 2089cbed85632a7101f8efa6cd63defdcdc0ff4c [file] [log] [blame]
DRC9b28def2011-05-21 14:37:15 +00001/*
DRC2eda8212012-03-23 19:32:38 +00002 * Copyright (C)2009-2012 D. R. Commander. All Rights Reserved.
DRC2e7b76b2009-04-03 12:04:24 +00003 *
DRC9b28def2011-05-21 14:37:15 +00004 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
DRC2e7b76b2009-04-03 12:04:24 +00006 *
DRC9b28def2011-05-21 14:37:15 +00007 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * - Neither the name of the libjpeg-turbo Project nor the names of its
13 * contributors may be used to endorse or promote products derived from this
14 * software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
DRC2e7b76b2009-04-03 12:04:24 +000027 */
28
DRC9b28def2011-05-21 14:37:15 +000029/* TurboJPEG/OSS: this implements the TurboJPEG API using libjpeg-turbo */
DRC2e7b76b2009-04-03 12:04:24 +000030
31#include <stdio.h>
32#include <stdlib.h>
DRC296c71b2011-05-25 04:12:52 +000033#include <jinclude.h>
DRCfbb67472010-11-24 04:02:37 +000034#define JPEG_INTERNALS
DRC2e7b76b2009-04-03 12:04:24 +000035#include <jpeglib.h>
36#include <jerror.h>
37#include <setjmp.h>
38#include "./turbojpeg.h"
DRCa29294a2011-05-24 09:17:57 +000039#include "./tjutil.h"
DRC890f1e02011-02-26 22:02:37 +000040#include "transupp.h"
DRC2a2e4512011-01-05 22:33:24 +000041
DRC9b28def2011-05-21 14:37:15 +000042extern void jpeg_mem_dest_tj(j_compress_ptr, unsigned char **,
43 unsigned long *, boolean);
44extern void jpeg_mem_src_tj(j_decompress_ptr, unsigned char *, unsigned long);
45
DRCfbb67472010-11-24 04:02:37 +000046#define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
DRC2e7b76b2009-04-03 12:04:24 +000047
48
DRC9b28def2011-05-21 14:37:15 +000049/* Error handling (based on example in example.c) */
DRC2e7b76b2009-04-03 12:04:24 +000050
DRC9b28def2011-05-21 14:37:15 +000051static char errStr[JMSG_LENGTH_MAX]="No error";
DRC2e7b76b2009-04-03 12:04:24 +000052
DRC9b28def2011-05-21 14:37:15 +000053struct my_error_mgr
DRC2e7b76b2009-04-03 12:04:24 +000054{
55 struct jpeg_error_mgr pub;
DRC9b28def2011-05-21 14:37:15 +000056 jmp_buf setjmp_buffer;
57};
58typedef struct my_error_mgr *my_error_ptr;
DRC2e7b76b2009-04-03 12:04:24 +000059
60static void my_error_exit(j_common_ptr cinfo)
61{
DRC9b28def2011-05-21 14:37:15 +000062 my_error_ptr myerr=(my_error_ptr)cinfo->err;
DRC2e7b76b2009-04-03 12:04:24 +000063 (*cinfo->err->output_message)(cinfo);
DRC9b28def2011-05-21 14:37:15 +000064 longjmp(myerr->setjmp_buffer, 1);
DRC2e7b76b2009-04-03 12:04:24 +000065}
66
DRC9b28def2011-05-21 14:37:15 +000067/* Based on output_message() in jerror.c */
68
DRC2e7b76b2009-04-03 12:04:24 +000069static void my_output_message(j_common_ptr cinfo)
70{
DRC9b28def2011-05-21 14:37:15 +000071 (*cinfo->err->format_message)(cinfo, errStr);
DRC2e7b76b2009-04-03 12:04:24 +000072}
73
74
DRC9b28def2011-05-21 14:37:15 +000075/* Global structures, macros, etc. */
DRC2e7b76b2009-04-03 12:04:24 +000076
DRC9b28def2011-05-21 14:37:15 +000077enum {COMPRESS=1, DECOMPRESS=2};
78
79typedef struct _tjinstance
DRC2e7b76b2009-04-03 12:04:24 +000080{
81 struct jpeg_compress_struct cinfo;
82 struct jpeg_decompress_struct dinfo;
DRC9b28def2011-05-21 14:37:15 +000083 struct my_error_mgr jerr;
84 int init;
85} tjinstance;
DRC2e7b76b2009-04-03 12:04:24 +000086
DRC007a42c2011-05-22 13:55:56 +000087static const int pixelsize[TJ_NUMSAMP]={3, 3, 3, 1, 3};
DRC9b28def2011-05-21 14:37:15 +000088
DRC007a42c2011-05-22 13:55:56 +000089static const JXFORM_CODE xformtypes[TJ_NUMXOP]=
90{
DRC890f1e02011-02-26 22:02:37 +000091 JXFORM_NONE, JXFORM_FLIP_H, JXFORM_FLIP_V, JXFORM_TRANSPOSE,
92 JXFORM_TRANSVERSE, JXFORM_ROT_90, JXFORM_ROT_180, JXFORM_ROT_270
93};
DRC9b28def2011-05-21 14:37:15 +000094
DRC109a5782011-03-01 09:53:07 +000095#define NUMSF 4
96static const tjscalingfactor sf[NUMSF]={
97 {1, 1},
98 {1, 2},
99 {1, 4},
100 {1, 8}
101};
DRC2e7b76b2009-04-03 12:04:24 +0000102
DRCa29294a2011-05-24 09:17:57 +0000103#define _throw(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s", m); \
DRCda5220a2011-03-02 02:17:30 +0000104 retval=-1; goto bailout;}
DRC9b28def2011-05-21 14:37:15 +0000105#define getinstance(handle) tjinstance *this=(tjinstance *)handle; \
106 j_compress_ptr cinfo=NULL; j_decompress_ptr dinfo=NULL; \
107 if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
108 return -1;} \
109 cinfo=&this->cinfo; dinfo=&this->dinfo;
DRC2e7b76b2009-04-03 12:04:24 +0000110
DRC9b28def2011-05-21 14:37:15 +0000111static int getPixelFormat(int pixelSize, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000112{
DRC25b995a2011-05-21 15:34:54 +0000113 if(pixelSize==1) return TJPF_GRAY;
DRC9b28def2011-05-21 14:37:15 +0000114 if(pixelSize==3)
115 {
DRC25b995a2011-05-21 15:34:54 +0000116 if(flags&TJ_BGR) return TJPF_BGR;
117 else return TJPF_RGB;
DRC9b28def2011-05-21 14:37:15 +0000118 }
119 if(pixelSize==4)
120 {
121 if(flags&TJ_ALPHAFIRST)
122 {
DRC25b995a2011-05-21 15:34:54 +0000123 if(flags&TJ_BGR) return TJPF_XBGR;
124 else return TJPF_XRGB;
DRC9b28def2011-05-21 14:37:15 +0000125 }
126 else
127 {
DRC25b995a2011-05-21 15:34:54 +0000128 if(flags&TJ_BGR) return TJPF_BGRX;
129 else return TJPF_RGBX;
DRC9b28def2011-05-21 14:37:15 +0000130 }
131 }
132 return -1;
DRC2e7b76b2009-04-03 12:04:24 +0000133}
134
DRCf12bb302011-09-07 05:03:18 +0000135static int setCompDefaults(struct jpeg_compress_struct *cinfo,
DRCfd3aba32012-06-29 23:14:48 +0000136 int pixelFormat, int subsamp, int jpegQual, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000137{
DRCf12bb302011-09-07 05:03:18 +0000138 int retval=0;
139
DRC9b28def2011-05-21 14:37:15 +0000140 switch(pixelFormat)
141 {
DRC25b995a2011-05-21 15:34:54 +0000142 case TJPF_GRAY:
DRC9b28def2011-05-21 14:37:15 +0000143 cinfo->in_color_space=JCS_GRAYSCALE; break;
144 #if JCS_EXTENSIONS==1
DRC25b995a2011-05-21 15:34:54 +0000145 case TJPF_RGB:
DRC9b28def2011-05-21 14:37:15 +0000146 cinfo->in_color_space=JCS_EXT_RGB; break;
DRC25b995a2011-05-21 15:34:54 +0000147 case TJPF_BGR:
DRC9b28def2011-05-21 14:37:15 +0000148 cinfo->in_color_space=JCS_EXT_BGR; break;
DRC25b995a2011-05-21 15:34:54 +0000149 case TJPF_RGBX:
DRC67ce3b22011-12-19 02:21:03 +0000150 case TJPF_RGBA:
DRC9b28def2011-05-21 14:37:15 +0000151 cinfo->in_color_space=JCS_EXT_RGBX; break;
DRC25b995a2011-05-21 15:34:54 +0000152 case TJPF_BGRX:
DRC67ce3b22011-12-19 02:21:03 +0000153 case TJPF_BGRA:
DRC9b28def2011-05-21 14:37:15 +0000154 cinfo->in_color_space=JCS_EXT_BGRX; break;
DRC25b995a2011-05-21 15:34:54 +0000155 case TJPF_XRGB:
DRC67ce3b22011-12-19 02:21:03 +0000156 case TJPF_ARGB:
DRC9b28def2011-05-21 14:37:15 +0000157 cinfo->in_color_space=JCS_EXT_XRGB; break;
DRC25b995a2011-05-21 15:34:54 +0000158 case TJPF_XBGR:
DRC67ce3b22011-12-19 02:21:03 +0000159 case TJPF_ABGR:
DRC9b28def2011-05-21 14:37:15 +0000160 cinfo->in_color_space=JCS_EXT_XBGR; break;
161 #else
DRC25b995a2011-05-21 15:34:54 +0000162 case TJPF_RGB:
DRC9b28def2011-05-21 14:37:15 +0000163 if(RGB_RED==0 && RGB_GREEN==1 && RGB_BLUE==2 && RGB_PIXELSIZE==3)
164 {
165 cinfo->in_color_space=JCS_RGB; break;
166 }
167 default:
168 _throw("Unsupported pixel format");
169 #endif
DRCefa4ddc2010-10-13 19:22:50 +0000170 }
DRC2e7b76b2009-04-03 12:04:24 +0000171
DRC9b28def2011-05-21 14:37:15 +0000172 cinfo->input_components=tjPixelSize[pixelFormat];
173 jpeg_set_defaults(cinfo);
174 if(jpegQual>=0)
175 {
176 jpeg_set_quality(cinfo, jpegQual, TRUE);
DRCfd3aba32012-06-29 23:14:48 +0000177 if(jpegQual>=96 || flags&TJFLAG_ACCURATEDCT) cinfo->dct_method=JDCT_ISLOW;
DRC9b28def2011-05-21 14:37:15 +0000178 else cinfo->dct_method=JDCT_FASTEST;
179 }
DRC25b995a2011-05-21 15:34:54 +0000180 if(subsamp==TJSAMP_GRAY)
DRC9b28def2011-05-21 14:37:15 +0000181 jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
182 else
183 jpeg_set_colorspace(cinfo, JCS_YCbCr);
DRC2e7b76b2009-04-03 12:04:24 +0000184
DRC9b28def2011-05-21 14:37:15 +0000185 cinfo->comp_info[0].h_samp_factor=tjMCUWidth[subsamp]/8;
186 cinfo->comp_info[1].h_samp_factor=1;
187 cinfo->comp_info[2].h_samp_factor=1;
188 cinfo->comp_info[0].v_samp_factor=tjMCUHeight[subsamp]/8;
189 cinfo->comp_info[1].v_samp_factor=1;
190 cinfo->comp_info[2].v_samp_factor=1;
DRCf12bb302011-09-07 05:03:18 +0000191
192 #if JCS_EXTENSIONS!=1
193 bailout:
194 #endif
195 return retval;
DRC9b28def2011-05-21 14:37:15 +0000196}
197
DRCf12bb302011-09-07 05:03:18 +0000198static int setDecompDefaults(struct jpeg_decompress_struct *dinfo,
DRCfd3aba32012-06-29 23:14:48 +0000199 int pixelFormat, int flags)
DRC9b28def2011-05-21 14:37:15 +0000200{
DRCf12bb302011-09-07 05:03:18 +0000201 int retval=0;
202
DRC9b28def2011-05-21 14:37:15 +0000203 switch(pixelFormat)
204 {
DRC25b995a2011-05-21 15:34:54 +0000205 case TJPF_GRAY:
DRC9b28def2011-05-21 14:37:15 +0000206 dinfo->out_color_space=JCS_GRAYSCALE; break;
207 #if JCS_EXTENSIONS==1
DRC25b995a2011-05-21 15:34:54 +0000208 case TJPF_RGB:
DRC9b28def2011-05-21 14:37:15 +0000209 dinfo->out_color_space=JCS_EXT_RGB; break;
DRC25b995a2011-05-21 15:34:54 +0000210 case TJPF_BGR:
DRC9b28def2011-05-21 14:37:15 +0000211 dinfo->out_color_space=JCS_EXT_BGR; break;
DRC25b995a2011-05-21 15:34:54 +0000212 case TJPF_RGBX:
DRC9b28def2011-05-21 14:37:15 +0000213 dinfo->out_color_space=JCS_EXT_RGBX; break;
DRC25b995a2011-05-21 15:34:54 +0000214 case TJPF_BGRX:
DRC9b28def2011-05-21 14:37:15 +0000215 dinfo->out_color_space=JCS_EXT_BGRX; break;
DRC25b995a2011-05-21 15:34:54 +0000216 case TJPF_XRGB:
DRC9b28def2011-05-21 14:37:15 +0000217 dinfo->out_color_space=JCS_EXT_XRGB; break;
DRC25b995a2011-05-21 15:34:54 +0000218 case TJPF_XBGR:
DRC9b28def2011-05-21 14:37:15 +0000219 dinfo->out_color_space=JCS_EXT_XBGR; break;
DRC67ce3b22011-12-19 02:21:03 +0000220 #if JCS_ALPHA_EXTENSIONS==1
221 case TJPF_RGBA:
222 dinfo->out_color_space=JCS_EXT_RGBA; break;
223 case TJPF_BGRA:
224 dinfo->out_color_space=JCS_EXT_BGRA; break;
225 case TJPF_ARGB:
226 dinfo->out_color_space=JCS_EXT_ARGB; break;
227 case TJPF_ABGR:
228 dinfo->out_color_space=JCS_EXT_ABGR; break;
229 #endif
DRC9b28def2011-05-21 14:37:15 +0000230 #else
DRC25b995a2011-05-21 15:34:54 +0000231 case TJPF_RGB:
DRC9b28def2011-05-21 14:37:15 +0000232 if(RGB_RED==0 && RGB_GREEN==1 && RGB_BLUE==2 && RGB_PIXELSIZE==3)
233 {
234 dinfo->out_color_space=JCS_RGB; break;
235 }
DRC67ce3b22011-12-19 02:21:03 +0000236 #endif
DRC9b28def2011-05-21 14:37:15 +0000237 default:
238 _throw("Unsupported pixel format");
DRC9b28def2011-05-21 14:37:15 +0000239 }
DRCf12bb302011-09-07 05:03:18 +0000240
DRCfd3aba32012-06-29 23:14:48 +0000241 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
242
DRCf12bb302011-09-07 05:03:18 +0000243 bailout:
DRCf12bb302011-09-07 05:03:18 +0000244 return retval;
DRC9b28def2011-05-21 14:37:15 +0000245}
246
247
DRC9b49f0e2011-07-12 03:17:23 +0000248static int getSubsamp(j_decompress_ptr dinfo)
249{
250 int retval=-1, i, k;
251 for(i=0; i<NUMSUBOPT; i++)
252 {
253 if(dinfo->num_components==pixelsize[i])
254 {
255 if(dinfo->comp_info[0].h_samp_factor==tjMCUWidth[i]/8
256 && dinfo->comp_info[0].v_samp_factor==tjMCUHeight[i]/8)
257 {
258 int match=0;
259 for(k=1; k<dinfo->num_components; k++)
260 {
261 if(dinfo->comp_info[k].h_samp_factor==1
262 && dinfo->comp_info[k].v_samp_factor==1)
263 match++;
264 }
265 if(match==dinfo->num_components-1)
266 {
267 retval=i; break;
268 }
269 }
270 }
271 }
272 return retval;
273}
274
275
DRC9b28def2011-05-21 14:37:15 +0000276/* General API functions */
277
278DLLEXPORT char* DLLCALL tjGetErrorStr(void)
279{
280 return errStr;
281}
282
283
284DLLEXPORT int DLLCALL tjDestroy(tjhandle handle)
285{
286 getinstance(handle);
287 if(setjmp(this->jerr.setjmp_buffer)) return -1;
288 if(this->init&COMPRESS) jpeg_destroy_compress(cinfo);
289 if(this->init&DECOMPRESS) jpeg_destroy_decompress(dinfo);
290 free(this);
291 return 0;
292}
293
294
DRC6b76f752011-05-24 16:52:47 +0000295/* These are exposed mainly because Windows can't malloc() and free() across
296 DLL boundaries except when the CRT DLL is used, and we don't use the CRT DLL
297 with turbojpeg.dll for compatibility reasons. However, these functions
298 can potentially be used for other purposes by different implementations. */
299
300DLLEXPORT void DLLCALL tjFree(unsigned char *buf)
301{
302 if(buf) free(buf);
303}
304
305
306DLLEXPORT unsigned char *DLLCALL tjAlloc(int bytes)
307{
308 return (unsigned char *)malloc(bytes);
309}
310
311
DRC9b28def2011-05-21 14:37:15 +0000312/* Compressor */
313
314static tjhandle _tjInitCompress(tjinstance *this)
315{
316 unsigned char buffer[1], *buf=buffer; unsigned long size=1;
317
318 /* This is also straight out of example.c */
319 this->cinfo.err=jpeg_std_error(&this->jerr.pub);
320 this->jerr.pub.error_exit=my_error_exit;
321 this->jerr.pub.output_message=my_output_message;
322
323 if(setjmp(this->jerr.setjmp_buffer))
324 {
325 /* If we get here, the JPEG code has signaled an error. */
326 if(this) free(this); return NULL;
327 }
328
329 jpeg_create_compress(&this->cinfo);
330 /* Make an initial call so it will create the destination manager */
331 jpeg_mem_dest_tj(&this->cinfo, &buf, &size, 0);
332
DRC007a42c2011-05-22 13:55:56 +0000333 this->init|=COMPRESS;
DRC9b28def2011-05-21 14:37:15 +0000334 return (tjhandle)this;
DRC2e7b76b2009-04-03 12:04:24 +0000335}
336
DRC890f1e02011-02-26 22:02:37 +0000337DLLEXPORT tjhandle DLLCALL tjInitCompress(void)
338{
DRC9b28def2011-05-21 14:37:15 +0000339 tjinstance *this=NULL;
340 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
DRCda5220a2011-03-02 02:17:30 +0000341 {
DRC007a42c2011-05-22 13:55:56 +0000342 snprintf(errStr, JMSG_LENGTH_MAX,
343 "tjInitCompress(): Memory allocation failure");
DRCda5220a2011-03-02 02:17:30 +0000344 return NULL;
345 }
DRC007a42c2011-05-22 13:55:56 +0000346 MEMZERO(this, sizeof(tjinstance));
DRC9b28def2011-05-21 14:37:15 +0000347 return _tjInitCompress(this);
DRC890f1e02011-02-26 22:02:37 +0000348}
349
DRC84241602011-02-25 02:08:23 +0000350
DRC9b49f0e2011-07-12 03:17:23 +0000351DLLEXPORT unsigned long DLLCALL tjBufSize(int width, int height,
352 int jpegSubsamp)
353{
354 unsigned long retval=0; int mcuw, mcuh, chromasf;
355 if(width<1 || height<1 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT)
356 _throw("tjBufSize(): Invalid argument");
357
358 // This allows for rare corner cases in which a JPEG image can actually be
359 // larger than the uncompressed input (we wouldn't mention it if it hadn't
360 // happened before.)
361 mcuw=tjMCUWidth[jpegSubsamp];
362 mcuh=tjMCUHeight[jpegSubsamp];
363 chromasf=jpegSubsamp==TJSAMP_GRAY? 0: 4*64/(mcuw*mcuh);
364 retval=PAD(width, mcuw) * PAD(height, mcuh) * (2 + chromasf) + 2048;
365
366 bailout:
367 return retval;
368}
369
370
DRC2e7b76b2009-04-03 12:04:24 +0000371DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
372{
DRCf3cf9732011-02-22 00:16:14 +0000373 unsigned long retval=0;
374 if(width<1 || height<1)
DRC007a42c2011-05-22 13:55:56 +0000375 _throw("TJBUFSIZE(): Invalid argument");
DRCf3cf9732011-02-22 00:16:14 +0000376
377 // This allows for rare corner cases in which a JPEG image can actually be
378 // larger than the uncompressed input (we wouldn't mention it if it hadn't
DRCb28fc572011-02-22 06:41:29 +0000379 // happened before.)
DRC007a42c2011-05-22 13:55:56 +0000380 retval=PAD(width, 16) * PAD(height, 16) * 6 + 2048;
DRCf3cf9732011-02-22 00:16:14 +0000381
382 bailout:
383 return retval;
384}
385
DRC84241602011-02-25 02:08:23 +0000386
DRC9b49f0e2011-07-12 03:17:23 +0000387DLLEXPORT unsigned long DLLCALL tjBufSizeYUV(int width, int height,
DRCf3cf9732011-02-22 00:16:14 +0000388 int subsamp)
389{
390 unsigned long retval=0;
391 int pw, ph, cw, ch;
392 if(width<1 || height<1 || subsamp<0 || subsamp>=NUMSUBOPT)
DRC9b49f0e2011-07-12 03:17:23 +0000393 _throw("tjBufSizeYUV(): Invalid argument");
DRC9b28def2011-05-21 14:37:15 +0000394 pw=PAD(width, tjMCUWidth[subsamp]/8);
395 ph=PAD(height, tjMCUHeight[subsamp]/8);
396 cw=pw*8/tjMCUWidth[subsamp]; ch=ph*8/tjMCUHeight[subsamp];
DRC25b995a2011-05-21 15:34:54 +0000397 retval=PAD(pw, 4)*ph + (subsamp==TJSAMP_GRAY? 0:PAD(cw, 4)*ch*2);
DRCf3cf9732011-02-22 00:16:14 +0000398
399 bailout:
400 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000401}
402
DRC84241602011-02-25 02:08:23 +0000403
DRC9b49f0e2011-07-12 03:17:23 +0000404DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
405 int subsamp)
406{
407 return tjBufSizeYUV(width, height, subsamp);
408}
409
410
DRC9b28def2011-05-21 14:37:15 +0000411DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf,
412 int width, int pitch, int height, int pixelFormat, unsigned char **jpegBuf,
413 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
414{
DRCff78e372011-05-24 10:17:32 +0000415 int i, retval=0, alloc=1; JSAMPROW *row_pointer=NULL;
DRC9b28def2011-05-21 14:37:15 +0000416
417 getinstance(handle)
418 if((this->init&COMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +0000419 _throw("tjCompress2(): Instance has not been initialized for compression");
DRC9b28def2011-05-21 14:37:15 +0000420
421 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
422 || pixelFormat>=TJ_NUMPF || jpegBuf==NULL || jpegSize==NULL
423 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT || jpegQual<0 || jpegQual>100)
DRC007a42c2011-05-22 13:55:56 +0000424 _throw("tjCompress2(): Invalid argument");
DRC9b28def2011-05-21 14:37:15 +0000425
426 if(setjmp(this->jerr.setjmp_buffer))
427 {
428 /* If we get here, the JPEG code has signaled an error. */
429 retval=-1;
430 goto bailout;
431 }
432
433 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
434
435 cinfo->image_width=width;
436 cinfo->image_height=height;
437
DRC25b995a2011-05-21 15:34:54 +0000438 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
439 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
440 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC9b28def2011-05-21 14:37:15 +0000441
DRCff78e372011-05-24 10:17:32 +0000442 if(flags&TJFLAG_NOREALLOC)
443 {
DRC9b49f0e2011-07-12 03:17:23 +0000444 alloc=0; *jpegSize=tjBufSize(width, height, jpegSubsamp);
DRCff78e372011-05-24 10:17:32 +0000445 }
446 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
DRCfd3aba32012-06-29 23:14:48 +0000447 if(setCompDefaults(cinfo, pixelFormat, jpegSubsamp, jpegQual, flags)==-1)
DRCf12bb302011-09-07 05:03:18 +0000448 return -1;
DRC9b28def2011-05-21 14:37:15 +0000449
450 jpeg_start_compress(cinfo, TRUE);
451 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
DRC007a42c2011-05-22 13:55:56 +0000452 _throw("tjCompress2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000453 for(i=0; i<height; i++)
454 {
DRC25b995a2011-05-21 15:34:54 +0000455 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
DRC9b28def2011-05-21 14:37:15 +0000456 else row_pointer[i]=&srcBuf[i*pitch];
457 }
458 while(cinfo->next_scanline<cinfo->image_height)
459 {
460 jpeg_write_scanlines(cinfo, &row_pointer[cinfo->next_scanline],
461 cinfo->image_height-cinfo->next_scanline);
462 }
463 jpeg_finish_compress(cinfo);
464
465 bailout:
466 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
467 if(row_pointer) free(row_pointer);
468 return retval;
469}
470
471DLLEXPORT int DLLCALL tjCompress(tjhandle handle, unsigned char *srcBuf,
472 int width, int pitch, int height, int pixelSize, unsigned char *jpegBuf,
473 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
474{
475 int retval=0; unsigned long size;
476 if(flags&TJ_YUV)
477 {
DRC9b49f0e2011-07-12 03:17:23 +0000478 size=tjBufSizeYUV(width, height, jpegSubsamp);
DRC9b28def2011-05-21 14:37:15 +0000479 retval=tjEncodeYUV2(handle, srcBuf, width, pitch, height,
480 getPixelFormat(pixelSize, flags), jpegBuf, jpegSubsamp, flags);
481 }
482 else
483 {
DRC9b28def2011-05-21 14:37:15 +0000484 retval=tjCompress2(handle, srcBuf, width, pitch, height,
485 getPixelFormat(pixelSize, flags), &jpegBuf, &size, jpegSubsamp, jpegQual,
DRC25b995a2011-05-21 15:34:54 +0000486 flags|TJFLAG_NOREALLOC);
DRC9b28def2011-05-21 14:37:15 +0000487 }
488 *jpegSize=size;
489 return retval;
490}
491
492
493DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
494 int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
495 int subsamp, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000496{
DRC91e86ba2011-02-15 05:24:08 +0000497 int i, retval=0; JSAMPROW *row_pointer=NULL;
DRCfbb67472010-11-24 04:02:37 +0000498 JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS];
499 JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
500 JSAMPROW *outbuf[MAX_COMPONENTS];
DRC9b28def2011-05-21 14:37:15 +0000501 int row, pw, ph, cw[MAX_COMPONENTS], ch[MAX_COMPONENTS];
502 JSAMPLE *ptr=dstBuf;
DRCd4c15e12012-03-23 19:39:14 +0000503 unsigned long yuvsize=0;
DRC9b28def2011-05-21 14:37:15 +0000504 jpeg_component_info *compptr;
DRC2e7b76b2009-04-03 12:04:24 +0000505
DRC9b28def2011-05-21 14:37:15 +0000506 getinstance(handle);
507 if((this->init&COMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +0000508 _throw("tjEncodeYUV2(): Instance has not been initialized for compression");
DRC2e7b76b2009-04-03 12:04:24 +0000509
DRCfbb67472010-11-24 04:02:37 +0000510 for(i=0; i<MAX_COMPONENTS; i++)
511 {
512 tmpbuf[i]=NULL; _tmpbuf[i]=NULL;
513 tmpbuf2[i]=NULL; _tmpbuf2[i]=NULL; outbuf[i]=NULL;
514 }
515
DRC9b28def2011-05-21 14:37:15 +0000516 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
517 || pixelFormat>=TJ_NUMPF || dstBuf==NULL || subsamp<0
518 || subsamp>=NUMSUBOPT)
519 _throw("tjEncodeYUV2(): Invalid argument");
DRC2e7b76b2009-04-03 12:04:24 +0000520
DRC9b28def2011-05-21 14:37:15 +0000521 if(setjmp(this->jerr.setjmp_buffer))
522 {
523 /* If we get here, the JPEG code has signaled an error. */
524 retval=-1;
525 goto bailout;
526 }
DRC2e7b76b2009-04-03 12:04:24 +0000527
DRC9b28def2011-05-21 14:37:15 +0000528 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
DRC2e7b76b2009-04-03 12:04:24 +0000529
DRC9b28def2011-05-21 14:37:15 +0000530 cinfo->image_width=width;
531 cinfo->image_height=height;
DRC2e7b76b2009-04-03 12:04:24 +0000532
DRC25b995a2011-05-21 15:34:54 +0000533 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
534 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
535 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC0c6a2712010-02-22 08:34:44 +0000536
DRC9b49f0e2011-07-12 03:17:23 +0000537 yuvsize=tjBufSizeYUV(width, height, subsamp);
DRC9b28def2011-05-21 14:37:15 +0000538 jpeg_mem_dest_tj(cinfo, &dstBuf, &yuvsize, 0);
DRCfd3aba32012-06-29 23:14:48 +0000539 if(setCompDefaults(cinfo, pixelFormat, subsamp, -1, flags)==-1) return -1;
DRC2e7b76b2009-04-03 12:04:24 +0000540
DRC9b28def2011-05-21 14:37:15 +0000541 jpeg_start_compress(cinfo, TRUE);
542 pw=PAD(width, cinfo->max_h_samp_factor);
543 ph=PAD(height, cinfo->max_v_samp_factor);
DRC2e7b76b2009-04-03 12:04:24 +0000544
DRC9b28def2011-05-21 14:37:15 +0000545 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph))==NULL)
DRC007a42c2011-05-22 13:55:56 +0000546 _throw("tjEncodeYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000547 for(i=0; i<height; i++)
DRC2e7b76b2009-04-03 12:04:24 +0000548 {
DRC25b995a2011-05-21 15:34:54 +0000549 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
DRC9b28def2011-05-21 14:37:15 +0000550 else row_pointer[i]=&srcBuf[i*pitch];
551 }
552 if(height<ph)
553 for(i=height; i<ph; i++) row_pointer[i]=row_pointer[height-1];
DRCfbb67472010-11-24 04:02:37 +0000554
DRC9b28def2011-05-21 14:37:15 +0000555 for(i=0; i<cinfo->num_components; i++)
556 {
557 compptr=&cinfo->comp_info[i];
558 _tmpbuf[i]=(JSAMPLE *)malloc(
559 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
560 /compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
DRC007a42c2011-05-22 13:55:56 +0000561 if(!_tmpbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000562 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
DRC007a42c2011-05-22 13:55:56 +0000563 if(!tmpbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000564 for(row=0; row<cinfo->max_v_samp_factor; row++)
DRCfbb67472010-11-24 04:02:37 +0000565 {
DRC9b28def2011-05-21 14:37:15 +0000566 unsigned char *_tmpbuf_aligned=
567 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
568 tmpbuf[i][row]=&_tmpbuf_aligned[
DRCfbb67472010-11-24 04:02:37 +0000569 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
DRC9b28def2011-05-21 14:37:15 +0000570 /compptr->h_samp_factor, 16) * row];
DRCfbb67472010-11-24 04:02:37 +0000571 }
DRC9b28def2011-05-21 14:37:15 +0000572 _tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
573 * compptr->v_samp_factor + 16);
DRC007a42c2011-05-22 13:55:56 +0000574 if(!_tmpbuf2[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000575 tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
DRC007a42c2011-05-22 13:55:56 +0000576 if(!tmpbuf2[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000577 for(row=0; row<compptr->v_samp_factor; row++)
578 {
579 unsigned char *_tmpbuf2_aligned=
580 (unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
581 tmpbuf2[i][row]=&_tmpbuf2_aligned[
582 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
583 }
584 cw[i]=pw*compptr->h_samp_factor/cinfo->max_h_samp_factor;
585 ch[i]=ph*compptr->v_samp_factor/cinfo->max_v_samp_factor;
586 outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]);
DRC007a42c2011-05-22 13:55:56 +0000587 if(!outbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000588 for(row=0; row<ch[i]; row++)
589 {
590 outbuf[i][row]=ptr;
591 ptr+=PAD(cw[i], 4);
592 }
593 }
594 if(yuvsize!=(unsigned long)(ptr-dstBuf))
595 _throw("tjEncodeYUV2(): Generated image is not the correct size");
DRCfbb67472010-11-24 04:02:37 +0000596
DRC9b28def2011-05-21 14:37:15 +0000597 for(row=0; row<ph; row+=cinfo->max_v_samp_factor)
DRCfbb67472010-11-24 04:02:37 +0000598 {
DRC9b28def2011-05-21 14:37:15 +0000599 (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0,
600 cinfo->max_v_samp_factor);
601 (cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
602 for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++)
603 jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
604 row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
605 compptr->v_samp_factor, cw[i]);
DRC6ee54592011-03-01 08:18:30 +0000606 }
DRC9b28def2011-05-21 14:37:15 +0000607 cinfo->next_scanline+=height;
608 jpeg_abort_compress(cinfo);
DRC2e7b76b2009-04-03 12:04:24 +0000609
DRC91e86ba2011-02-15 05:24:08 +0000610 bailout:
DRC9b28def2011-05-21 14:37:15 +0000611 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
DRC2e7b76b2009-04-03 12:04:24 +0000612 if(row_pointer) free(row_pointer);
DRCfbb67472010-11-24 04:02:37 +0000613 for(i=0; i<MAX_COMPONENTS; i++)
614 {
615 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
DRC57423072011-01-05 23:35:53 +0000616 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
DRCfbb67472010-11-24 04:02:37 +0000617 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
DRC57423072011-01-05 23:35:53 +0000618 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
DRCfbb67472010-11-24 04:02:37 +0000619 if(outbuf[i]!=NULL) free(outbuf[i]);
620 }
DRC91e86ba2011-02-15 05:24:08 +0000621 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000622}
623
DRC9b28def2011-05-21 14:37:15 +0000624DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf,
625 int width, int pitch, int height, int pixelSize, unsigned char *dstBuf,
626 int subsamp, int flags)
DRC84241602011-02-25 02:08:23 +0000627{
DRC9b28def2011-05-21 14:37:15 +0000628 return tjEncodeYUV2(handle, srcBuf, width, pitch, height,
629 getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags);
DRC84241602011-02-25 02:08:23 +0000630}
631
632
DRC9b28def2011-05-21 14:37:15 +0000633/* Decompressor */
DRC2e7b76b2009-04-03 12:04:24 +0000634
DRC9b28def2011-05-21 14:37:15 +0000635static tjhandle _tjInitDecompress(tjinstance *this)
DRC2e7b76b2009-04-03 12:04:24 +0000636{
DRC9b28def2011-05-21 14:37:15 +0000637 unsigned char buffer[1];
DRC2e7b76b2009-04-03 12:04:24 +0000638
DRC9b28def2011-05-21 14:37:15 +0000639 /* This is also straight out of example.c */
640 this->dinfo.err=jpeg_std_error(&this->jerr.pub);
641 this->jerr.pub.error_exit=my_error_exit;
642 this->jerr.pub.output_message=my_output_message;
DRC2e7b76b2009-04-03 12:04:24 +0000643
DRC9b28def2011-05-21 14:37:15 +0000644 if(setjmp(this->jerr.setjmp_buffer))
645 {
646 /* If we get here, the JPEG code has signaled an error. */
647 if(this) free(this); return NULL;
DRC9e17f7d2010-12-10 04:59:13 +0000648 }
DRC2e7b76b2009-04-03 12:04:24 +0000649
DRC9b28def2011-05-21 14:37:15 +0000650 jpeg_create_decompress(&this->dinfo);
651 /* Make an initial call so it will create the source manager */
652 jpeg_mem_src_tj(&this->dinfo, buffer, 1);
DRC2e7b76b2009-04-03 12:04:24 +0000653
DRC007a42c2011-05-22 13:55:56 +0000654 this->init|=DECOMPRESS;
DRC9b28def2011-05-21 14:37:15 +0000655 return (tjhandle)this;
DRC2e7b76b2009-04-03 12:04:24 +0000656}
657
DRC890f1e02011-02-26 22:02:37 +0000658DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
659{
DRC9b28def2011-05-21 14:37:15 +0000660 tjinstance *this;
661 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
DRCda5220a2011-03-02 02:17:30 +0000662 {
DRC007a42c2011-05-22 13:55:56 +0000663 snprintf(errStr, JMSG_LENGTH_MAX,
664 "tjInitDecompress(): Memory allocation failure");
DRCda5220a2011-03-02 02:17:30 +0000665 return NULL;
666 }
DRC007a42c2011-05-22 13:55:56 +0000667 MEMZERO(this, sizeof(tjinstance));
DRC9b28def2011-05-21 14:37:15 +0000668 return _tjInitDecompress(this);
DRC890f1e02011-02-26 22:02:37 +0000669}
670
DRC2e7b76b2009-04-03 12:04:24 +0000671
DRC9b28def2011-05-21 14:37:15 +0000672DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle,
673 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
674 int *jpegSubsamp)
DRC1fe80f82010-12-14 01:21:29 +0000675{
DRC9b49f0e2011-07-12 03:17:23 +0000676 int retval=0;
DRC1fe80f82010-12-14 01:21:29 +0000677
DRC9b28def2011-05-21 14:37:15 +0000678 getinstance(handle);
679 if((this->init&DECOMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +0000680 _throw("tjDecompressHeader2(): Instance has not been initialized for decompression");
DRC1fe80f82010-12-14 01:21:29 +0000681
DRC9b28def2011-05-21 14:37:15 +0000682 if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL
683 || jpegSubsamp==NULL)
684 _throw("tjDecompressHeader2(): Invalid argument");
DRC1fe80f82010-12-14 01:21:29 +0000685
DRC9b28def2011-05-21 14:37:15 +0000686 if(setjmp(this->jerr.setjmp_buffer))
687 {
688 /* If we get here, the JPEG code has signaled an error. */
DRC1fe80f82010-12-14 01:21:29 +0000689 return -1;
690 }
691
DRC9b28def2011-05-21 14:37:15 +0000692 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
693 jpeg_read_header(dinfo, TRUE);
DRC1fe80f82010-12-14 01:21:29 +0000694
DRC9b28def2011-05-21 14:37:15 +0000695 *width=dinfo->image_width;
696 *height=dinfo->image_height;
DRC9b49f0e2011-07-12 03:17:23 +0000697 *jpegSubsamp=getSubsamp(dinfo);
DRC1fe80f82010-12-14 01:21:29 +0000698
DRC9b28def2011-05-21 14:37:15 +0000699 jpeg_abort_decompress(dinfo);
DRC1fe80f82010-12-14 01:21:29 +0000700
DRC9b28def2011-05-21 14:37:15 +0000701 if(*jpegSubsamp<0)
DRC007a42c2011-05-22 13:55:56 +0000702 _throw("tjDecompressHeader2(): Could not determine subsampling type for JPEG image");
703 if(*width<1 || *height<1)
704 _throw("tjDecompressHeader2(): Invalid data returned in header");
DRC91e86ba2011-02-15 05:24:08 +0000705
706 bailout:
707 return retval;
708}
709
DRC9b28def2011-05-21 14:37:15 +0000710DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle,
711 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height)
DRC91e86ba2011-02-15 05:24:08 +0000712{
DRC9b28def2011-05-21 14:37:15 +0000713 int jpegSubsamp;
714 return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height,
715 &jpegSubsamp);
DRC1fe80f82010-12-14 01:21:29 +0000716}
717
718
DRC109a5782011-03-01 09:53:07 +0000719DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors)
DRCb28fc572011-02-22 06:41:29 +0000720{
DRC109a5782011-03-01 09:53:07 +0000721 if(numscalingfactors==NULL)
DRCb28fc572011-02-22 06:41:29 +0000722 {
DRC9b28def2011-05-21 14:37:15 +0000723 snprintf(errStr, JMSG_LENGTH_MAX,
DRC007a42c2011-05-22 13:55:56 +0000724 "tjGetScalingFactors(): Invalid argument");
DRC109a5782011-03-01 09:53:07 +0000725 return NULL;
DRCb28fc572011-02-22 06:41:29 +0000726 }
727
DRC109a5782011-03-01 09:53:07 +0000728 *numscalingfactors=NUMSF;
729 return (tjscalingfactor *)sf;
DRCb28fc572011-02-22 06:41:29 +0000730}
731
732
DRC9b28def2011-05-21 14:37:15 +0000733DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, unsigned char *jpegBuf,
734 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
735 int height, int pixelFormat, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000736{
DRC9b28def2011-05-21 14:37:15 +0000737 int i, retval=0; JSAMPROW *row_pointer=NULL;
DRC109a5782011-03-01 09:53:07 +0000738 int jpegwidth, jpegheight, scaledw, scaledh;
DRC2e7b76b2009-04-03 12:04:24 +0000739
DRC9b28def2011-05-21 14:37:15 +0000740 getinstance(handle);
741 if((this->init&DECOMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +0000742 _throw("tjDecompress2(): Instance has not been initialized for decompression");
DRC9b28def2011-05-21 14:37:15 +0000743
744 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0
745 || height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF)
746 _throw("tjDecompress2(): Invalid argument");
747
DRC25b995a2011-05-21 15:34:54 +0000748 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
749 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
750 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC9b28def2011-05-21 14:37:15 +0000751
752 if(setjmp(this->jerr.setjmp_buffer))
753 {
754 /* If we get here, the JPEG code has signaled an error. */
755 retval=-1;
756 goto bailout;
757 }
758
759 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
760 jpeg_read_header(dinfo, TRUE);
DRCfd3aba32012-06-29 23:14:48 +0000761 if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
DRC2eda8212012-03-23 19:32:38 +0000762 {
763 retval=-1; goto bailout;
764 }
DRC9b28def2011-05-21 14:37:15 +0000765
DRC25b995a2011-05-21 15:34:54 +0000766 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
DRC9b28def2011-05-21 14:37:15 +0000767
768 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
769 if(width==0) width=jpegwidth;
770 if(height==0) height=jpegheight;
771 for(i=0; i<NUMSF; i++)
772 {
773 scaledw=TJSCALED(jpegwidth, sf[i]);
774 scaledh=TJSCALED(jpegheight, sf[i]);
775 if(scaledw<=width && scaledh<=height)
776 break;
777 }
778 if(scaledw>width || scaledh>height)
DRC007a42c2011-05-22 13:55:56 +0000779 _throw("tjDecompress2(): Could not scale down to desired image dimensions");
DRC9b28def2011-05-21 14:37:15 +0000780 width=scaledw; height=scaledh;
781 dinfo->scale_num=sf[i].num;
782 dinfo->scale_denom=sf[i].denom;
783
784 jpeg_start_decompress(dinfo);
785 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
786 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
787 *dinfo->output_height))==NULL)
DRC007a42c2011-05-22 13:55:56 +0000788 _throw("tjDecompress2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000789 for(i=0; i<(int)dinfo->output_height; i++)
790 {
DRC25b995a2011-05-21 15:34:54 +0000791 if(flags&TJFLAG_BOTTOMUP)
DRC9b28def2011-05-21 14:37:15 +0000792 row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*pitch];
793 else row_pointer[i]=&dstBuf[i*pitch];
794 }
795 while(dinfo->output_scanline<dinfo->output_height)
796 {
797 jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline],
798 dinfo->output_height-dinfo->output_scanline);
799 }
800 jpeg_finish_decompress(dinfo);
801
802 bailout:
803 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
804 if(row_pointer) free(row_pointer);
805 return retval;
806}
807
808DLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf,
809 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
810 int height, int pixelSize, int flags)
811{
812 if(flags&TJ_YUV)
813 return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags);
814 else
815 return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch,
816 height, getPixelFormat(pixelSize, flags), flags);
817}
818
819
820DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle,
821 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
822 int flags)
823{
824 int i, row, retval=0; JSAMPROW *outbuf[MAX_COMPONENTS];
825 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS],
826 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
827 JSAMPLE *_tmpbuf=NULL, *ptr=dstBuf; JSAMPROW *tmpbuf[MAX_COMPONENTS];
828
829 getinstance(handle);
830 if((this->init&DECOMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +0000831 _throw("tjDecompressToYUV(): Instance has not been initialized for decompression");
DRC2e7b76b2009-04-03 12:04:24 +0000832
DRCf9cf5c72010-12-10 10:58:49 +0000833 for(i=0; i<MAX_COMPONENTS; i++)
834 {
835 tmpbuf[i]=NULL; outbuf[i]=NULL;
836 }
DRC9e17f7d2010-12-10 04:59:13 +0000837
DRC9b28def2011-05-21 14:37:15 +0000838 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL)
839 _throw("tjDecompressToYUV(): Invalid argument");
DRC2e7b76b2009-04-03 12:04:24 +0000840
DRC25b995a2011-05-21 15:34:54 +0000841 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
842 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
843 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC0c6a2712010-02-22 08:34:44 +0000844
DRC9b28def2011-05-21 14:37:15 +0000845 if(setjmp(this->jerr.setjmp_buffer))
846 {
847 /* If we get here, the JPEG code has signaled an error. */
DRC91e86ba2011-02-15 05:24:08 +0000848 retval=-1;
849 goto bailout;
DRC9e17f7d2010-12-10 04:59:13 +0000850 }
DRC2e7b76b2009-04-03 12:04:24 +0000851
DRC9b28def2011-05-21 14:37:15 +0000852 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
853 jpeg_read_header(dinfo, TRUE);
DRC2e7b76b2009-04-03 12:04:24 +0000854
DRC9b28def2011-05-21 14:37:15 +0000855 for(i=0; i<dinfo->num_components; i++)
DRC2e7b76b2009-04-03 12:04:24 +0000856 {
DRC9b28def2011-05-21 14:37:15 +0000857 jpeg_component_info *compptr=&dinfo->comp_info[i];
858 int ih;
859 iw[i]=compptr->width_in_blocks*DCTSIZE;
860 ih=compptr->height_in_blocks*DCTSIZE;
861 cw[i]=PAD(dinfo->image_width, dinfo->max_h_samp_factor)
862 *compptr->h_samp_factor/dinfo->max_h_samp_factor;
863 ch[i]=PAD(dinfo->image_height, dinfo->max_v_samp_factor)
864 *compptr->v_samp_factor/dinfo->max_v_samp_factor;
865 if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1;
866 th[i]=compptr->v_samp_factor*DCTSIZE;
867 tmpbufsize+=iw[i]*th[i];
868 if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL)
DRC007a42c2011-05-22 13:55:56 +0000869 _throw("tjDecompressToYUV(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000870 for(row=0; row<ch[i]; row++)
871 {
872 outbuf[i][row]=ptr;
873 ptr+=PAD(cw[i], 4);
874 }
875 }
876 if(usetmpbuf)
877 {
878 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
DRC007a42c2011-05-22 13:55:56 +0000879 _throw("tjDecompressToYUV(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000880 ptr=_tmpbuf;
881 for(i=0; i<dinfo->num_components; i++)
882 {
883 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
DRC007a42c2011-05-22 13:55:56 +0000884 _throw("tjDecompressToYUV(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000885 for(row=0; row<th[i]; row++)
886 {
887 tmpbuf[i][row]=ptr;
888 ptr+=iw[i];
889 }
890 }
891 }
DRC9e17f7d2010-12-10 04:59:13 +0000892
DRC25b995a2011-05-21 15:34:54 +0000893 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
DRCe0419b52012-07-03 20:01:31 +0000894 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
DRC9b28def2011-05-21 14:37:15 +0000895 dinfo->raw_data_out=TRUE;
896
897 jpeg_start_decompress(dinfo);
898 for(row=0; row<(int)dinfo->output_height;
899 row+=dinfo->max_v_samp_factor*DCTSIZE)
900 {
901 JSAMPARRAY yuvptr[MAX_COMPONENTS];
902 int crow[MAX_COMPONENTS];
DRC9e17f7d2010-12-10 04:59:13 +0000903 for(i=0; i<dinfo->num_components; i++)
904 {
905 jpeg_component_info *compptr=&dinfo->comp_info[i];
DRC9b28def2011-05-21 14:37:15 +0000906 crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
907 if(usetmpbuf) yuvptr[i]=tmpbuf[i];
908 else yuvptr[i]=&outbuf[i][crow[i]];
DRCf9cf5c72010-12-10 10:58:49 +0000909 }
DRC9b28def2011-05-21 14:37:15 +0000910 jpeg_read_raw_data(dinfo, yuvptr, dinfo->max_v_samp_factor*DCTSIZE);
DRCf9cf5c72010-12-10 10:58:49 +0000911 if(usetmpbuf)
912 {
DRC9b28def2011-05-21 14:37:15 +0000913 int j;
DRCf9cf5c72010-12-10 10:58:49 +0000914 for(i=0; i<dinfo->num_components; i++)
915 {
DRC9b28def2011-05-21 14:37:15 +0000916 for(j=0; j<min(th[i], ch[i]-crow[i]); j++)
DRCf9cf5c72010-12-10 10:58:49 +0000917 {
DRC9b28def2011-05-21 14:37:15 +0000918 memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], cw[i]);
DRCf9cf5c72010-12-10 10:58:49 +0000919 }
DRC9e17f7d2010-12-10 04:59:13 +0000920 }
921 }
922 }
DRC9b28def2011-05-21 14:37:15 +0000923 jpeg_finish_decompress(dinfo);
DRC2e7b76b2009-04-03 12:04:24 +0000924
DRC91e86ba2011-02-15 05:24:08 +0000925 bailout:
DRC9b28def2011-05-21 14:37:15 +0000926 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
DRC9e17f7d2010-12-10 04:59:13 +0000927 for(i=0; i<MAX_COMPONENTS; i++)
DRCf9cf5c72010-12-10 10:58:49 +0000928 {
929 if(tmpbuf[i]) free(tmpbuf[i]);
DRC9e17f7d2010-12-10 04:59:13 +0000930 if(outbuf[i]) free(outbuf[i]);
DRCf9cf5c72010-12-10 10:58:49 +0000931 }
932 if(_tmpbuf) free(_tmpbuf);
DRC91e86ba2011-02-15 05:24:08 +0000933 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000934}
935
936
DRC9b28def2011-05-21 14:37:15 +0000937/* Transformer */
DRC890f1e02011-02-26 22:02:37 +0000938
939DLLEXPORT tjhandle DLLCALL tjInitTransform(void)
940{
DRC9b28def2011-05-21 14:37:15 +0000941 tjinstance *this=NULL; tjhandle handle=NULL;
942 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
DRCda5220a2011-03-02 02:17:30 +0000943 {
DRC007a42c2011-05-22 13:55:56 +0000944 snprintf(errStr, JMSG_LENGTH_MAX,
945 "tjInitTransform(): Memory allocation failure");
DRCda5220a2011-03-02 02:17:30 +0000946 return NULL;
947 }
DRC007a42c2011-05-22 13:55:56 +0000948 MEMZERO(this, sizeof(tjinstance));
DRC9b28def2011-05-21 14:37:15 +0000949 handle=_tjInitCompress(this);
950 if(!handle) return NULL;
951 handle=_tjInitDecompress(this);
952 return handle;
DRC890f1e02011-02-26 22:02:37 +0000953}
954
955
DRC9b28def2011-05-21 14:37:15 +0000956DLLEXPORT int DLLCALL tjTransform(tjhandle handle, unsigned char *jpegBuf,
957 unsigned long jpegSize, int n, unsigned char **dstBufs,
958 unsigned long *dstSizes, tjtransform *t, int flags)
DRC890f1e02011-02-26 22:02:37 +0000959{
DRC0a325192011-03-02 09:22:41 +0000960 jpeg_transform_info *xinfo=NULL;
DRC890f1e02011-02-26 22:02:37 +0000961 jvirt_barray_ptr *srccoefs, *dstcoefs;
DRC9b49f0e2011-07-12 03:17:23 +0000962 int retval=0, i, jpegSubsamp;
DRC890f1e02011-02-26 22:02:37 +0000963
DRC9b28def2011-05-21 14:37:15 +0000964 getinstance(handle);
965 if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +0000966 _throw("tjTransform(): Instance has not been initialized for transformation");
DRC890f1e02011-02-26 22:02:37 +0000967
DRC9b28def2011-05-21 14:37:15 +0000968 if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL
969 || t==NULL || flags<0)
970 _throw("tjTransform(): Invalid argument");
971
DRC25b995a2011-05-21 15:34:54 +0000972 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
973 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
974 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC890f1e02011-02-26 22:02:37 +0000975
DRC9b28def2011-05-21 14:37:15 +0000976 if(setjmp(this->jerr.setjmp_buffer))
977 {
978 /* If we get here, the JPEG code has signaled an error. */
DRC890f1e02011-02-26 22:02:37 +0000979 retval=-1;
980 goto bailout;
981 }
982
DRC9b28def2011-05-21 14:37:15 +0000983 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
DRC890f1e02011-02-26 22:02:37 +0000984
DRC0a325192011-03-02 09:22:41 +0000985 if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n))
986 ==NULL)
DRC007a42c2011-05-22 13:55:56 +0000987 _throw("tjTransform(): Memory allocation failure");
988 MEMZERO(xinfo, sizeof(jpeg_transform_info)*n);
DRC890f1e02011-02-26 22:02:37 +0000989
DRC0a325192011-03-02 09:22:41 +0000990 for(i=0; i<n; i++)
DRC890f1e02011-02-26 22:02:37 +0000991 {
DRC0a325192011-03-02 09:22:41 +0000992 xinfo[i].transform=xformtypes[t[i].op];
DRC25b995a2011-05-21 15:34:54 +0000993 xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0;
994 xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0;
995 xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0;
996 xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0;
997 if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1;
DRCba5ea512011-03-04 03:20:34 +0000998 else xinfo[i].slow_hflip=0;
DRC0a325192011-03-02 09:22:41 +0000999
1000 if(xinfo[i].crop)
DRC890f1e02011-02-26 22:02:37 +00001001 {
DRC0a325192011-03-02 09:22:41 +00001002 xinfo[i].crop_xoffset=t[i].r.x; xinfo[i].crop_xoffset_set=JCROP_POS;
1003 xinfo[i].crop_yoffset=t[i].r.y; xinfo[i].crop_yoffset_set=JCROP_POS;
1004 if(t[i].r.w!=0)
1005 {
1006 xinfo[i].crop_width=t[i].r.w; xinfo[i].crop_width_set=JCROP_POS;
1007 }
DRCd932e582011-03-15 20:09:47 +00001008 else xinfo[i].crop_width=JCROP_UNSET;
DRC0a325192011-03-02 09:22:41 +00001009 if(t[i].r.h!=0)
1010 {
1011 xinfo[i].crop_height=t[i].r.h; xinfo[i].crop_height_set=JCROP_POS;
1012 }
DRCd932e582011-03-15 20:09:47 +00001013 else xinfo[i].crop_height=JCROP_UNSET;
DRC890f1e02011-02-26 22:02:37 +00001014 }
1015 }
1016
DRC9b28def2011-05-21 14:37:15 +00001017 jcopy_markers_setup(dinfo, JCOPYOPT_ALL);
1018 jpeg_read_header(dinfo, TRUE);
DRC9b49f0e2011-07-12 03:17:23 +00001019 jpegSubsamp=getSubsamp(dinfo);
1020 if(jpegSubsamp<0)
1021 _throw("tjTransform(): Could not determine subsampling type for JPEG image");
DRC890f1e02011-02-26 22:02:37 +00001022
DRC0a325192011-03-02 09:22:41 +00001023 for(i=0; i<n; i++)
DRC890f1e02011-02-26 22:02:37 +00001024 {
DRC9b28def2011-05-21 14:37:15 +00001025 if(!jtransform_request_workspace(dinfo, &xinfo[i]))
DRC007a42c2011-05-22 13:55:56 +00001026 _throw("tjTransform(): Transform is not perfect");
DRC890f1e02011-02-26 22:02:37 +00001027
DRC0a325192011-03-02 09:22:41 +00001028 if(xinfo[i].crop)
DRC890f1e02011-02-26 22:02:37 +00001029 {
DRC0a325192011-03-02 09:22:41 +00001030 if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0
1031 || (t[i].r.y%xinfo[i].iMCU_sample_height)!=0)
1032 {
DRC9b28def2011-05-21 14:37:15 +00001033 snprintf(errStr, JMSG_LENGTH_MAX,
DRC0a325192011-03-02 09:22:41 +00001034 "To crop this JPEG image, x must be a multiple of %d\n"
1035 "and y must be a multiple of %d.\n",
1036 xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height);
1037 retval=-1; goto bailout;
1038 }
DRC890f1e02011-02-26 22:02:37 +00001039 }
1040 }
1041
DRC9b28def2011-05-21 14:37:15 +00001042 srccoefs=jpeg_read_coefficients(dinfo);
DRC890f1e02011-02-26 22:02:37 +00001043
DRC0a325192011-03-02 09:22:41 +00001044 for(i=0; i<n; i++)
1045 {
DRCff78e372011-05-24 10:17:32 +00001046 int w, h, alloc=1;
DRC0a325192011-03-02 09:22:41 +00001047 if(!xinfo[i].crop)
1048 {
DRC9b28def2011-05-21 14:37:15 +00001049 w=dinfo->image_width; h=dinfo->image_height;
DRC0a325192011-03-02 09:22:41 +00001050 }
1051 else
1052 {
1053 w=xinfo[i].crop_width; h=xinfo[i].crop_height;
1054 }
DRCff78e372011-05-24 10:17:32 +00001055 if(flags&TJFLAG_NOREALLOC)
1056 {
DRC9b49f0e2011-07-12 03:17:23 +00001057 alloc=0; dstSizes[i]=tjBufSize(w, h, jpegSubsamp);
DRCff78e372011-05-24 10:17:32 +00001058 }
DRC7bf04d32011-09-17 00:18:31 +00001059 if(!(t[i].options&TJXOPT_NOOUTPUT))
1060 jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc);
DRC9b28def2011-05-21 14:37:15 +00001061 jpeg_copy_critical_parameters(dinfo, cinfo);
1062 dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs,
DRC0a325192011-03-02 09:22:41 +00001063 &xinfo[i]);
DRC7bf04d32011-09-17 00:18:31 +00001064 if(!(t[i].options&TJXOPT_NOOUTPUT))
1065 {
1066 jpeg_write_coefficients(cinfo, dstcoefs);
1067 jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL);
1068 }
1069 else jinit_c_master_control(cinfo, TRUE);
DRC9b28def2011-05-21 14:37:15 +00001070 jtransform_execute_transformation(dinfo, cinfo, srccoefs,
DRC0a325192011-03-02 09:22:41 +00001071 &xinfo[i]);
DRC7bf04d32011-09-17 00:18:31 +00001072 if(t[i].customFilter)
1073 {
DRCefe28ce2012-01-17 11:48:38 +00001074 int ci, y; JDIMENSION by;
DRC7bf04d32011-09-17 00:18:31 +00001075 for(ci=0; ci<cinfo->num_components; ci++)
1076 {
1077 jpeg_component_info *compptr=&cinfo->comp_info[ci];
1078 tjregion arrayRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
1079 DCTSIZE};
1080 tjregion planeRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
1081 compptr->height_in_blocks*DCTSIZE};
1082 for(by=0; by<compptr->height_in_blocks; by+=compptr->v_samp_factor)
1083 {
1084 JBLOCKARRAY barray=(dinfo->mem->access_virt_barray)
1085 ((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor,
1086 TRUE);
1087 for(y=0; y<compptr->v_samp_factor; y++)
1088 {
1089 if(t[i].customFilter(barray[y][0], arrayRegion, planeRegion,
DRCf5467112011-09-20 05:02:19 +00001090 ci, i, &t[i])==-1)
DRC7bf04d32011-09-17 00:18:31 +00001091 _throw("tjTransform(): Error in custom filter");
1092 arrayRegion.y+=DCTSIZE;
1093 }
1094 }
1095 }
1096 }
1097 if(!(t[i].options&TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo);
DRC0a325192011-03-02 09:22:41 +00001098 }
1099
DRC9b28def2011-05-21 14:37:15 +00001100 jpeg_finish_decompress(dinfo);
DRC890f1e02011-02-26 22:02:37 +00001101
DRC890f1e02011-02-26 22:02:37 +00001102 bailout:
DRC9b28def2011-05-21 14:37:15 +00001103 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
1104 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
DRC0a325192011-03-02 09:22:41 +00001105 if(xinfo) free(xinfo);
DRC890f1e02011-02-26 22:02:37 +00001106 return retval;
1107}