blob: 2f7cbf9a645a8bf14e8aafe3b59f7c8fda6d22e5 [file] [log] [blame]
DRC9b28def2011-05-21 14:37:15 +00001/*
2 * Copyright (C)2009-2011 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
DRCab2df6e2012-01-28 06:49:56 +000095#define NUMSF 16
DRC109a5782011-03-01 09:53:07 +000096static const tjscalingfactor sf[NUMSF]={
DRCab2df6e2012-01-28 06:49:56 +000097 {2, 1},
98 {15, 8},
99 {7, 4},
100 {13, 8},
101 {3, 2},
102 {11, 8},
103 {5, 4},
104 {9, 8},
DRC109a5782011-03-01 09:53:07 +0000105 {1, 1},
DRCab2df6e2012-01-28 06:49:56 +0000106 {7, 8},
107 {3, 4},
108 {5, 8},
DRC109a5782011-03-01 09:53:07 +0000109 {1, 2},
DRCab2df6e2012-01-28 06:49:56 +0000110 {3, 8},
DRC109a5782011-03-01 09:53:07 +0000111 {1, 4},
112 {1, 8}
113};
DRC2e7b76b2009-04-03 12:04:24 +0000114
DRCa29294a2011-05-24 09:17:57 +0000115#define _throw(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s", m); \
DRCda5220a2011-03-02 02:17:30 +0000116 retval=-1; goto bailout;}
DRC9b28def2011-05-21 14:37:15 +0000117#define getinstance(handle) tjinstance *this=(tjinstance *)handle; \
118 j_compress_ptr cinfo=NULL; j_decompress_ptr dinfo=NULL; \
119 if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
120 return -1;} \
121 cinfo=&this->cinfo; dinfo=&this->dinfo;
DRC2e7b76b2009-04-03 12:04:24 +0000122
DRC9b28def2011-05-21 14:37:15 +0000123static int getPixelFormat(int pixelSize, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000124{
DRC25b995a2011-05-21 15:34:54 +0000125 if(pixelSize==1) return TJPF_GRAY;
DRC9b28def2011-05-21 14:37:15 +0000126 if(pixelSize==3)
127 {
DRC25b995a2011-05-21 15:34:54 +0000128 if(flags&TJ_BGR) return TJPF_BGR;
129 else return TJPF_RGB;
DRC9b28def2011-05-21 14:37:15 +0000130 }
131 if(pixelSize==4)
132 {
133 if(flags&TJ_ALPHAFIRST)
134 {
DRC25b995a2011-05-21 15:34:54 +0000135 if(flags&TJ_BGR) return TJPF_XBGR;
136 else return TJPF_XRGB;
DRC9b28def2011-05-21 14:37:15 +0000137 }
138 else
139 {
DRC25b995a2011-05-21 15:34:54 +0000140 if(flags&TJ_BGR) return TJPF_BGRX;
141 else return TJPF_RGBX;
DRC9b28def2011-05-21 14:37:15 +0000142 }
143 }
144 return -1;
DRC2e7b76b2009-04-03 12:04:24 +0000145}
146
DRCf12bb302011-09-07 05:03:18 +0000147static int setCompDefaults(struct jpeg_compress_struct *cinfo,
DRC9b28def2011-05-21 14:37:15 +0000148 int pixelFormat, int subsamp, int jpegQual)
DRC2e7b76b2009-04-03 12:04:24 +0000149{
DRCf12bb302011-09-07 05:03:18 +0000150 int retval=0;
151
DRC9b28def2011-05-21 14:37:15 +0000152 switch(pixelFormat)
153 {
DRC25b995a2011-05-21 15:34:54 +0000154 case TJPF_GRAY:
DRC9b28def2011-05-21 14:37:15 +0000155 cinfo->in_color_space=JCS_GRAYSCALE; break;
156 #if JCS_EXTENSIONS==1
DRC25b995a2011-05-21 15:34:54 +0000157 case TJPF_RGB:
DRC9b28def2011-05-21 14:37:15 +0000158 cinfo->in_color_space=JCS_EXT_RGB; break;
DRC25b995a2011-05-21 15:34:54 +0000159 case TJPF_BGR:
DRC9b28def2011-05-21 14:37:15 +0000160 cinfo->in_color_space=JCS_EXT_BGR; break;
DRC25b995a2011-05-21 15:34:54 +0000161 case TJPF_RGBX:
DRC67ce3b22011-12-19 02:21:03 +0000162 case TJPF_RGBA:
DRC9b28def2011-05-21 14:37:15 +0000163 cinfo->in_color_space=JCS_EXT_RGBX; break;
DRC25b995a2011-05-21 15:34:54 +0000164 case TJPF_BGRX:
DRC67ce3b22011-12-19 02:21:03 +0000165 case TJPF_BGRA:
DRC9b28def2011-05-21 14:37:15 +0000166 cinfo->in_color_space=JCS_EXT_BGRX; break;
DRC25b995a2011-05-21 15:34:54 +0000167 case TJPF_XRGB:
DRC67ce3b22011-12-19 02:21:03 +0000168 case TJPF_ARGB:
DRC9b28def2011-05-21 14:37:15 +0000169 cinfo->in_color_space=JCS_EXT_XRGB; break;
DRC25b995a2011-05-21 15:34:54 +0000170 case TJPF_XBGR:
DRC67ce3b22011-12-19 02:21:03 +0000171 case TJPF_ABGR:
DRC9b28def2011-05-21 14:37:15 +0000172 cinfo->in_color_space=JCS_EXT_XBGR; break;
173 #else
DRC25b995a2011-05-21 15:34:54 +0000174 case TJPF_RGB:
DRC9b28def2011-05-21 14:37:15 +0000175 if(RGB_RED==0 && RGB_GREEN==1 && RGB_BLUE==2 && RGB_PIXELSIZE==3)
176 {
177 cinfo->in_color_space=JCS_RGB; break;
178 }
179 default:
180 _throw("Unsupported pixel format");
181 #endif
DRCefa4ddc2010-10-13 19:22:50 +0000182 }
DRC2e7b76b2009-04-03 12:04:24 +0000183
DRC9b28def2011-05-21 14:37:15 +0000184 cinfo->input_components=tjPixelSize[pixelFormat];
185 jpeg_set_defaults(cinfo);
186 if(jpegQual>=0)
187 {
188 jpeg_set_quality(cinfo, jpegQual, TRUE);
189 if(jpegQual>=96) cinfo->dct_method=JDCT_ISLOW;
190 else cinfo->dct_method=JDCT_FASTEST;
191 }
DRC25b995a2011-05-21 15:34:54 +0000192 if(subsamp==TJSAMP_GRAY)
DRC9b28def2011-05-21 14:37:15 +0000193 jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
194 else
195 jpeg_set_colorspace(cinfo, JCS_YCbCr);
DRC2e7b76b2009-04-03 12:04:24 +0000196
DRC9b28def2011-05-21 14:37:15 +0000197 cinfo->comp_info[0].h_samp_factor=tjMCUWidth[subsamp]/8;
198 cinfo->comp_info[1].h_samp_factor=1;
199 cinfo->comp_info[2].h_samp_factor=1;
200 cinfo->comp_info[0].v_samp_factor=tjMCUHeight[subsamp]/8;
201 cinfo->comp_info[1].v_samp_factor=1;
202 cinfo->comp_info[2].v_samp_factor=1;
DRCf12bb302011-09-07 05:03:18 +0000203
204 #if JCS_EXTENSIONS!=1
205 bailout:
206 #endif
207 return retval;
DRC9b28def2011-05-21 14:37:15 +0000208}
209
DRCf12bb302011-09-07 05:03:18 +0000210static int setDecompDefaults(struct jpeg_decompress_struct *dinfo,
DRC9b28def2011-05-21 14:37:15 +0000211 int pixelFormat)
212{
DRCf12bb302011-09-07 05:03:18 +0000213 int retval=0;
214
DRC9b28def2011-05-21 14:37:15 +0000215 switch(pixelFormat)
216 {
DRC25b995a2011-05-21 15:34:54 +0000217 case TJPF_GRAY:
DRC9b28def2011-05-21 14:37:15 +0000218 dinfo->out_color_space=JCS_GRAYSCALE; break;
219 #if JCS_EXTENSIONS==1
DRC25b995a2011-05-21 15:34:54 +0000220 case TJPF_RGB:
DRC9b28def2011-05-21 14:37:15 +0000221 dinfo->out_color_space=JCS_EXT_RGB; break;
DRC25b995a2011-05-21 15:34:54 +0000222 case TJPF_BGR:
DRC9b28def2011-05-21 14:37:15 +0000223 dinfo->out_color_space=JCS_EXT_BGR; break;
DRC25b995a2011-05-21 15:34:54 +0000224 case TJPF_RGBX:
DRC9b28def2011-05-21 14:37:15 +0000225 dinfo->out_color_space=JCS_EXT_RGBX; break;
DRC25b995a2011-05-21 15:34:54 +0000226 case TJPF_BGRX:
DRC9b28def2011-05-21 14:37:15 +0000227 dinfo->out_color_space=JCS_EXT_BGRX; break;
DRC25b995a2011-05-21 15:34:54 +0000228 case TJPF_XRGB:
DRC9b28def2011-05-21 14:37:15 +0000229 dinfo->out_color_space=JCS_EXT_XRGB; break;
DRC25b995a2011-05-21 15:34:54 +0000230 case TJPF_XBGR:
DRC9b28def2011-05-21 14:37:15 +0000231 dinfo->out_color_space=JCS_EXT_XBGR; break;
DRC67ce3b22011-12-19 02:21:03 +0000232 #if JCS_ALPHA_EXTENSIONS==1
233 case TJPF_RGBA:
234 dinfo->out_color_space=JCS_EXT_RGBA; break;
235 case TJPF_BGRA:
236 dinfo->out_color_space=JCS_EXT_BGRA; break;
237 case TJPF_ARGB:
238 dinfo->out_color_space=JCS_EXT_ARGB; break;
239 case TJPF_ABGR:
240 dinfo->out_color_space=JCS_EXT_ABGR; break;
241 #endif
DRC9b28def2011-05-21 14:37:15 +0000242 #else
DRC25b995a2011-05-21 15:34:54 +0000243 case TJPF_RGB:
DRC9b28def2011-05-21 14:37:15 +0000244 if(RGB_RED==0 && RGB_GREEN==1 && RGB_BLUE==2 && RGB_PIXELSIZE==3)
245 {
246 dinfo->out_color_space=JCS_RGB; break;
247 }
DRC67ce3b22011-12-19 02:21:03 +0000248 #endif
DRC9b28def2011-05-21 14:37:15 +0000249 default:
250 _throw("Unsupported pixel format");
DRC9b28def2011-05-21 14:37:15 +0000251 }
DRCf12bb302011-09-07 05:03:18 +0000252
DRCf12bb302011-09-07 05:03:18 +0000253 bailout:
DRCf12bb302011-09-07 05:03:18 +0000254 return retval;
DRC9b28def2011-05-21 14:37:15 +0000255}
256
257
DRC9b49f0e2011-07-12 03:17:23 +0000258static int getSubsamp(j_decompress_ptr dinfo)
259{
260 int retval=-1, i, k;
261 for(i=0; i<NUMSUBOPT; i++)
262 {
263 if(dinfo->num_components==pixelsize[i])
264 {
265 if(dinfo->comp_info[0].h_samp_factor==tjMCUWidth[i]/8
266 && dinfo->comp_info[0].v_samp_factor==tjMCUHeight[i]/8)
267 {
268 int match=0;
269 for(k=1; k<dinfo->num_components; k++)
270 {
271 if(dinfo->comp_info[k].h_samp_factor==1
272 && dinfo->comp_info[k].v_samp_factor==1)
273 match++;
274 }
275 if(match==dinfo->num_components-1)
276 {
277 retval=i; break;
278 }
279 }
280 }
281 }
282 return retval;
283}
284
285
DRC9b28def2011-05-21 14:37:15 +0000286/* General API functions */
287
288DLLEXPORT char* DLLCALL tjGetErrorStr(void)
289{
290 return errStr;
291}
292
293
294DLLEXPORT int DLLCALL tjDestroy(tjhandle handle)
295{
296 getinstance(handle);
297 if(setjmp(this->jerr.setjmp_buffer)) return -1;
298 if(this->init&COMPRESS) jpeg_destroy_compress(cinfo);
299 if(this->init&DECOMPRESS) jpeg_destroy_decompress(dinfo);
300 free(this);
301 return 0;
302}
303
304
DRC6b76f752011-05-24 16:52:47 +0000305/* These are exposed mainly because Windows can't malloc() and free() across
306 DLL boundaries except when the CRT DLL is used, and we don't use the CRT DLL
307 with turbojpeg.dll for compatibility reasons. However, these functions
308 can potentially be used for other purposes by different implementations. */
309
310DLLEXPORT void DLLCALL tjFree(unsigned char *buf)
311{
312 if(buf) free(buf);
313}
314
315
316DLLEXPORT unsigned char *DLLCALL tjAlloc(int bytes)
317{
318 return (unsigned char *)malloc(bytes);
319}
320
321
DRC9b28def2011-05-21 14:37:15 +0000322/* Compressor */
323
324static tjhandle _tjInitCompress(tjinstance *this)
325{
326 unsigned char buffer[1], *buf=buffer; unsigned long size=1;
327
328 /* This is also straight out of example.c */
329 this->cinfo.err=jpeg_std_error(&this->jerr.pub);
330 this->jerr.pub.error_exit=my_error_exit;
331 this->jerr.pub.output_message=my_output_message;
332
333 if(setjmp(this->jerr.setjmp_buffer))
334 {
335 /* If we get here, the JPEG code has signaled an error. */
336 if(this) free(this); return NULL;
337 }
338
339 jpeg_create_compress(&this->cinfo);
340 /* Make an initial call so it will create the destination manager */
341 jpeg_mem_dest_tj(&this->cinfo, &buf, &size, 0);
342
DRC007a42c2011-05-22 13:55:56 +0000343 this->init|=COMPRESS;
DRC9b28def2011-05-21 14:37:15 +0000344 return (tjhandle)this;
DRC2e7b76b2009-04-03 12:04:24 +0000345}
346
DRC890f1e02011-02-26 22:02:37 +0000347DLLEXPORT tjhandle DLLCALL tjInitCompress(void)
348{
DRC9b28def2011-05-21 14:37:15 +0000349 tjinstance *this=NULL;
350 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
DRCda5220a2011-03-02 02:17:30 +0000351 {
DRC007a42c2011-05-22 13:55:56 +0000352 snprintf(errStr, JMSG_LENGTH_MAX,
353 "tjInitCompress(): Memory allocation failure");
DRCda5220a2011-03-02 02:17:30 +0000354 return NULL;
355 }
DRC007a42c2011-05-22 13:55:56 +0000356 MEMZERO(this, sizeof(tjinstance));
DRC9b28def2011-05-21 14:37:15 +0000357 return _tjInitCompress(this);
DRC890f1e02011-02-26 22:02:37 +0000358}
359
DRC84241602011-02-25 02:08:23 +0000360
DRC9b49f0e2011-07-12 03:17:23 +0000361DLLEXPORT unsigned long DLLCALL tjBufSize(int width, int height,
362 int jpegSubsamp)
363{
364 unsigned long retval=0; int mcuw, mcuh, chromasf;
365 if(width<1 || height<1 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT)
366 _throw("tjBufSize(): Invalid argument");
367
368 // This allows for rare corner cases in which a JPEG image can actually be
369 // larger than the uncompressed input (we wouldn't mention it if it hadn't
370 // happened before.)
371 mcuw=tjMCUWidth[jpegSubsamp];
372 mcuh=tjMCUHeight[jpegSubsamp];
373 chromasf=jpegSubsamp==TJSAMP_GRAY? 0: 4*64/(mcuw*mcuh);
374 retval=PAD(width, mcuw) * PAD(height, mcuh) * (2 + chromasf) + 2048;
375
376 bailout:
377 return retval;
378}
379
380
DRC2e7b76b2009-04-03 12:04:24 +0000381DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
382{
DRCf3cf9732011-02-22 00:16:14 +0000383 unsigned long retval=0;
384 if(width<1 || height<1)
DRC007a42c2011-05-22 13:55:56 +0000385 _throw("TJBUFSIZE(): Invalid argument");
DRCf3cf9732011-02-22 00:16:14 +0000386
387 // This allows for rare corner cases in which a JPEG image can actually be
388 // larger than the uncompressed input (we wouldn't mention it if it hadn't
DRCb28fc572011-02-22 06:41:29 +0000389 // happened before.)
DRC007a42c2011-05-22 13:55:56 +0000390 retval=PAD(width, 16) * PAD(height, 16) * 6 + 2048;
DRCf3cf9732011-02-22 00:16:14 +0000391
392 bailout:
393 return retval;
394}
395
DRC84241602011-02-25 02:08:23 +0000396
DRC9b49f0e2011-07-12 03:17:23 +0000397DLLEXPORT unsigned long DLLCALL tjBufSizeYUV(int width, int height,
DRCf3cf9732011-02-22 00:16:14 +0000398 int subsamp)
399{
400 unsigned long retval=0;
401 int pw, ph, cw, ch;
402 if(width<1 || height<1 || subsamp<0 || subsamp>=NUMSUBOPT)
DRC9b49f0e2011-07-12 03:17:23 +0000403 _throw("tjBufSizeYUV(): Invalid argument");
DRC9b28def2011-05-21 14:37:15 +0000404 pw=PAD(width, tjMCUWidth[subsamp]/8);
405 ph=PAD(height, tjMCUHeight[subsamp]/8);
406 cw=pw*8/tjMCUWidth[subsamp]; ch=ph*8/tjMCUHeight[subsamp];
DRC25b995a2011-05-21 15:34:54 +0000407 retval=PAD(pw, 4)*ph + (subsamp==TJSAMP_GRAY? 0:PAD(cw, 4)*ch*2);
DRCf3cf9732011-02-22 00:16:14 +0000408
409 bailout:
410 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000411}
412
DRC84241602011-02-25 02:08:23 +0000413
DRC9b49f0e2011-07-12 03:17:23 +0000414DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
415 int subsamp)
416{
417 return tjBufSizeYUV(width, height, subsamp);
418}
419
420
DRC9b28def2011-05-21 14:37:15 +0000421DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf,
422 int width, int pitch, int height, int pixelFormat, unsigned char **jpegBuf,
423 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
424{
DRCff78e372011-05-24 10:17:32 +0000425 int i, retval=0, alloc=1; JSAMPROW *row_pointer=NULL;
DRC9b28def2011-05-21 14:37:15 +0000426
427 getinstance(handle)
428 if((this->init&COMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +0000429 _throw("tjCompress2(): Instance has not been initialized for compression");
DRC9b28def2011-05-21 14:37:15 +0000430
431 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
432 || pixelFormat>=TJ_NUMPF || jpegBuf==NULL || jpegSize==NULL
433 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT || jpegQual<0 || jpegQual>100)
DRC007a42c2011-05-22 13:55:56 +0000434 _throw("tjCompress2(): Invalid argument");
DRC9b28def2011-05-21 14:37:15 +0000435
436 if(setjmp(this->jerr.setjmp_buffer))
437 {
438 /* If we get here, the JPEG code has signaled an error. */
439 retval=-1;
440 goto bailout;
441 }
442
443 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
444
445 cinfo->image_width=width;
446 cinfo->image_height=height;
447
DRC25b995a2011-05-21 15:34:54 +0000448 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
449 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
450 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC9b28def2011-05-21 14:37:15 +0000451
DRCff78e372011-05-24 10:17:32 +0000452 if(flags&TJFLAG_NOREALLOC)
453 {
DRC9b49f0e2011-07-12 03:17:23 +0000454 alloc=0; *jpegSize=tjBufSize(width, height, jpegSubsamp);
DRCff78e372011-05-24 10:17:32 +0000455 }
456 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
DRCf12bb302011-09-07 05:03:18 +0000457 if(setCompDefaults(cinfo, pixelFormat, jpegSubsamp, jpegQual)==-1)
458 return -1;
DRC9b28def2011-05-21 14:37:15 +0000459
460 jpeg_start_compress(cinfo, TRUE);
461 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
DRC007a42c2011-05-22 13:55:56 +0000462 _throw("tjCompress2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000463 for(i=0; i<height; i++)
464 {
DRC25b995a2011-05-21 15:34:54 +0000465 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
DRC9b28def2011-05-21 14:37:15 +0000466 else row_pointer[i]=&srcBuf[i*pitch];
467 }
468 while(cinfo->next_scanline<cinfo->image_height)
469 {
470 jpeg_write_scanlines(cinfo, &row_pointer[cinfo->next_scanline],
471 cinfo->image_height-cinfo->next_scanline);
472 }
473 jpeg_finish_compress(cinfo);
474
475 bailout:
476 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
477 if(row_pointer) free(row_pointer);
478 return retval;
479}
480
481DLLEXPORT int DLLCALL tjCompress(tjhandle handle, unsigned char *srcBuf,
482 int width, int pitch, int height, int pixelSize, unsigned char *jpegBuf,
483 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
484{
485 int retval=0; unsigned long size;
486 if(flags&TJ_YUV)
487 {
DRC9b49f0e2011-07-12 03:17:23 +0000488 size=tjBufSizeYUV(width, height, jpegSubsamp);
DRC9b28def2011-05-21 14:37:15 +0000489 retval=tjEncodeYUV2(handle, srcBuf, width, pitch, height,
490 getPixelFormat(pixelSize, flags), jpegBuf, jpegSubsamp, flags);
491 }
492 else
493 {
DRC9b28def2011-05-21 14:37:15 +0000494 retval=tjCompress2(handle, srcBuf, width, pitch, height,
495 getPixelFormat(pixelSize, flags), &jpegBuf, &size, jpegSubsamp, jpegQual,
DRC25b995a2011-05-21 15:34:54 +0000496 flags|TJFLAG_NOREALLOC);
DRC9b28def2011-05-21 14:37:15 +0000497 }
498 *jpegSize=size;
499 return retval;
500}
501
502
503DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
504 int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
505 int subsamp, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000506{
DRC91e86ba2011-02-15 05:24:08 +0000507 int i, retval=0; JSAMPROW *row_pointer=NULL;
DRCfbb67472010-11-24 04:02:37 +0000508 JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS];
509 JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
510 JSAMPROW *outbuf[MAX_COMPONENTS];
DRC9b28def2011-05-21 14:37:15 +0000511 int row, pw, ph, cw[MAX_COMPONENTS], ch[MAX_COMPONENTS];
512 JSAMPLE *ptr=dstBuf;
513 unsigned long yuvsize=0;
514 jpeg_component_info *compptr;
DRC2e7b76b2009-04-03 12:04:24 +0000515
DRC9b28def2011-05-21 14:37:15 +0000516 getinstance(handle);
517 if((this->init&COMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +0000518 _throw("tjEncodeYUV2(): Instance has not been initialized for compression");
DRC2e7b76b2009-04-03 12:04:24 +0000519
DRCfbb67472010-11-24 04:02:37 +0000520 for(i=0; i<MAX_COMPONENTS; i++)
521 {
522 tmpbuf[i]=NULL; _tmpbuf[i]=NULL;
523 tmpbuf2[i]=NULL; _tmpbuf2[i]=NULL; outbuf[i]=NULL;
524 }
525
DRC9b28def2011-05-21 14:37:15 +0000526 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
527 || pixelFormat>=TJ_NUMPF || dstBuf==NULL || subsamp<0
528 || subsamp>=NUMSUBOPT)
529 _throw("tjEncodeYUV2(): Invalid argument");
DRC2e7b76b2009-04-03 12:04:24 +0000530
DRC9b28def2011-05-21 14:37:15 +0000531 if(setjmp(this->jerr.setjmp_buffer))
532 {
533 /* If we get here, the JPEG code has signaled an error. */
534 retval=-1;
535 goto bailout;
536 }
DRC2e7b76b2009-04-03 12:04:24 +0000537
DRC9b28def2011-05-21 14:37:15 +0000538 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
DRC2e7b76b2009-04-03 12:04:24 +0000539
DRC9b28def2011-05-21 14:37:15 +0000540 cinfo->image_width=width;
541 cinfo->image_height=height;
DRC2e7b76b2009-04-03 12:04:24 +0000542
DRC25b995a2011-05-21 15:34:54 +0000543 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
544 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
545 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC0c6a2712010-02-22 08:34:44 +0000546
DRC9b49f0e2011-07-12 03:17:23 +0000547 yuvsize=tjBufSizeYUV(width, height, subsamp);
DRC9b28def2011-05-21 14:37:15 +0000548 jpeg_mem_dest_tj(cinfo, &dstBuf, &yuvsize, 0);
DRCf12bb302011-09-07 05:03:18 +0000549 if(setCompDefaults(cinfo, pixelFormat, subsamp, -1)==-1) return -1;
DRC2e7b76b2009-04-03 12:04:24 +0000550
DRC9b28def2011-05-21 14:37:15 +0000551 jpeg_start_compress(cinfo, TRUE);
552 pw=PAD(width, cinfo->max_h_samp_factor);
553 ph=PAD(height, cinfo->max_v_samp_factor);
DRC2e7b76b2009-04-03 12:04:24 +0000554
DRC9b28def2011-05-21 14:37:15 +0000555 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph))==NULL)
DRC007a42c2011-05-22 13:55:56 +0000556 _throw("tjEncodeYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000557 for(i=0; i<height; i++)
DRC2e7b76b2009-04-03 12:04:24 +0000558 {
DRC25b995a2011-05-21 15:34:54 +0000559 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
DRC9b28def2011-05-21 14:37:15 +0000560 else row_pointer[i]=&srcBuf[i*pitch];
561 }
562 if(height<ph)
563 for(i=height; i<ph; i++) row_pointer[i]=row_pointer[height-1];
DRCfbb67472010-11-24 04:02:37 +0000564
DRC9b28def2011-05-21 14:37:15 +0000565 for(i=0; i<cinfo->num_components; i++)
566 {
567 compptr=&cinfo->comp_info[i];
568 _tmpbuf[i]=(JSAMPLE *)malloc(
569 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
570 /compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
DRC007a42c2011-05-22 13:55:56 +0000571 if(!_tmpbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000572 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
DRC007a42c2011-05-22 13:55:56 +0000573 if(!tmpbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000574 for(row=0; row<cinfo->max_v_samp_factor; row++)
DRCfbb67472010-11-24 04:02:37 +0000575 {
DRC9b28def2011-05-21 14:37:15 +0000576 unsigned char *_tmpbuf_aligned=
577 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
578 tmpbuf[i][row]=&_tmpbuf_aligned[
DRCfbb67472010-11-24 04:02:37 +0000579 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
DRC9b28def2011-05-21 14:37:15 +0000580 /compptr->h_samp_factor, 16) * row];
DRCfbb67472010-11-24 04:02:37 +0000581 }
DRC9b28def2011-05-21 14:37:15 +0000582 _tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
583 * compptr->v_samp_factor + 16);
DRC007a42c2011-05-22 13:55:56 +0000584 if(!_tmpbuf2[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000585 tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
DRC007a42c2011-05-22 13:55:56 +0000586 if(!tmpbuf2[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000587 for(row=0; row<compptr->v_samp_factor; row++)
588 {
589 unsigned char *_tmpbuf2_aligned=
590 (unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
591 tmpbuf2[i][row]=&_tmpbuf2_aligned[
592 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
593 }
594 cw[i]=pw*compptr->h_samp_factor/cinfo->max_h_samp_factor;
595 ch[i]=ph*compptr->v_samp_factor/cinfo->max_v_samp_factor;
596 outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]);
DRC007a42c2011-05-22 13:55:56 +0000597 if(!outbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000598 for(row=0; row<ch[i]; row++)
599 {
600 outbuf[i][row]=ptr;
601 ptr+=PAD(cw[i], 4);
602 }
603 }
604 if(yuvsize!=(unsigned long)(ptr-dstBuf))
605 _throw("tjEncodeYUV2(): Generated image is not the correct size");
DRCfbb67472010-11-24 04:02:37 +0000606
DRC9b28def2011-05-21 14:37:15 +0000607 for(row=0; row<ph; row+=cinfo->max_v_samp_factor)
DRCfbb67472010-11-24 04:02:37 +0000608 {
DRC9b28def2011-05-21 14:37:15 +0000609 (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0,
610 cinfo->max_v_samp_factor);
611 (cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
612 for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++)
613 jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
614 row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
615 compptr->v_samp_factor, cw[i]);
DRC6ee54592011-03-01 08:18:30 +0000616 }
DRC9b28def2011-05-21 14:37:15 +0000617 cinfo->next_scanline+=height;
618 jpeg_abort_compress(cinfo);
DRC2e7b76b2009-04-03 12:04:24 +0000619
DRC91e86ba2011-02-15 05:24:08 +0000620 bailout:
DRC9b28def2011-05-21 14:37:15 +0000621 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
DRC2e7b76b2009-04-03 12:04:24 +0000622 if(row_pointer) free(row_pointer);
DRCfbb67472010-11-24 04:02:37 +0000623 for(i=0; i<MAX_COMPONENTS; i++)
624 {
625 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
DRC57423072011-01-05 23:35:53 +0000626 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
DRCfbb67472010-11-24 04:02:37 +0000627 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
DRC57423072011-01-05 23:35:53 +0000628 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
DRCfbb67472010-11-24 04:02:37 +0000629 if(outbuf[i]!=NULL) free(outbuf[i]);
630 }
DRC91e86ba2011-02-15 05:24:08 +0000631 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000632}
633
DRC9b28def2011-05-21 14:37:15 +0000634DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf,
635 int width, int pitch, int height, int pixelSize, unsigned char *dstBuf,
636 int subsamp, int flags)
DRC84241602011-02-25 02:08:23 +0000637{
DRC9b28def2011-05-21 14:37:15 +0000638 return tjEncodeYUV2(handle, srcBuf, width, pitch, height,
639 getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags);
DRC84241602011-02-25 02:08:23 +0000640}
641
642
DRC9b28def2011-05-21 14:37:15 +0000643/* Decompressor */
DRC2e7b76b2009-04-03 12:04:24 +0000644
DRC9b28def2011-05-21 14:37:15 +0000645static tjhandle _tjInitDecompress(tjinstance *this)
DRC2e7b76b2009-04-03 12:04:24 +0000646{
DRC9b28def2011-05-21 14:37:15 +0000647 unsigned char buffer[1];
DRC2e7b76b2009-04-03 12:04:24 +0000648
DRC9b28def2011-05-21 14:37:15 +0000649 /* This is also straight out of example.c */
650 this->dinfo.err=jpeg_std_error(&this->jerr.pub);
651 this->jerr.pub.error_exit=my_error_exit;
652 this->jerr.pub.output_message=my_output_message;
DRC2e7b76b2009-04-03 12:04:24 +0000653
DRC9b28def2011-05-21 14:37:15 +0000654 if(setjmp(this->jerr.setjmp_buffer))
655 {
656 /* If we get here, the JPEG code has signaled an error. */
657 if(this) free(this); return NULL;
DRC9e17f7d2010-12-10 04:59:13 +0000658 }
DRC2e7b76b2009-04-03 12:04:24 +0000659
DRC9b28def2011-05-21 14:37:15 +0000660 jpeg_create_decompress(&this->dinfo);
661 /* Make an initial call so it will create the source manager */
662 jpeg_mem_src_tj(&this->dinfo, buffer, 1);
DRC2e7b76b2009-04-03 12:04:24 +0000663
DRC007a42c2011-05-22 13:55:56 +0000664 this->init|=DECOMPRESS;
DRC9b28def2011-05-21 14:37:15 +0000665 return (tjhandle)this;
DRC2e7b76b2009-04-03 12:04:24 +0000666}
667
DRC890f1e02011-02-26 22:02:37 +0000668DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
669{
DRC9b28def2011-05-21 14:37:15 +0000670 tjinstance *this;
671 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
DRCda5220a2011-03-02 02:17:30 +0000672 {
DRC007a42c2011-05-22 13:55:56 +0000673 snprintf(errStr, JMSG_LENGTH_MAX,
674 "tjInitDecompress(): Memory allocation failure");
DRCda5220a2011-03-02 02:17:30 +0000675 return NULL;
676 }
DRC007a42c2011-05-22 13:55:56 +0000677 MEMZERO(this, sizeof(tjinstance));
DRC9b28def2011-05-21 14:37:15 +0000678 return _tjInitDecompress(this);
DRC890f1e02011-02-26 22:02:37 +0000679}
680
DRC2e7b76b2009-04-03 12:04:24 +0000681
DRC9b28def2011-05-21 14:37:15 +0000682DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle,
683 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
684 int *jpegSubsamp)
DRC1fe80f82010-12-14 01:21:29 +0000685{
DRC9b49f0e2011-07-12 03:17:23 +0000686 int retval=0;
DRC1fe80f82010-12-14 01:21:29 +0000687
DRC9b28def2011-05-21 14:37:15 +0000688 getinstance(handle);
689 if((this->init&DECOMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +0000690 _throw("tjDecompressHeader2(): Instance has not been initialized for decompression");
DRC1fe80f82010-12-14 01:21:29 +0000691
DRC9b28def2011-05-21 14:37:15 +0000692 if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL
693 || jpegSubsamp==NULL)
694 _throw("tjDecompressHeader2(): Invalid argument");
DRC1fe80f82010-12-14 01:21:29 +0000695
DRC9b28def2011-05-21 14:37:15 +0000696 if(setjmp(this->jerr.setjmp_buffer))
697 {
698 /* If we get here, the JPEG code has signaled an error. */
DRC1fe80f82010-12-14 01:21:29 +0000699 return -1;
700 }
701
DRC9b28def2011-05-21 14:37:15 +0000702 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
703 jpeg_read_header(dinfo, TRUE);
DRC1fe80f82010-12-14 01:21:29 +0000704
DRC9b28def2011-05-21 14:37:15 +0000705 *width=dinfo->image_width;
706 *height=dinfo->image_height;
DRC9b49f0e2011-07-12 03:17:23 +0000707 *jpegSubsamp=getSubsamp(dinfo);
DRC1fe80f82010-12-14 01:21:29 +0000708
DRC9b28def2011-05-21 14:37:15 +0000709 jpeg_abort_decompress(dinfo);
DRC1fe80f82010-12-14 01:21:29 +0000710
DRC9b28def2011-05-21 14:37:15 +0000711 if(*jpegSubsamp<0)
DRC007a42c2011-05-22 13:55:56 +0000712 _throw("tjDecompressHeader2(): Could not determine subsampling type for JPEG image");
713 if(*width<1 || *height<1)
714 _throw("tjDecompressHeader2(): Invalid data returned in header");
DRC91e86ba2011-02-15 05:24:08 +0000715
716 bailout:
717 return retval;
718}
719
DRC9b28def2011-05-21 14:37:15 +0000720DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle,
721 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height)
DRC91e86ba2011-02-15 05:24:08 +0000722{
DRC9b28def2011-05-21 14:37:15 +0000723 int jpegSubsamp;
724 return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height,
725 &jpegSubsamp);
DRC1fe80f82010-12-14 01:21:29 +0000726}
727
728
DRC109a5782011-03-01 09:53:07 +0000729DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors)
DRCb28fc572011-02-22 06:41:29 +0000730{
DRC109a5782011-03-01 09:53:07 +0000731 if(numscalingfactors==NULL)
DRCb28fc572011-02-22 06:41:29 +0000732 {
DRC9b28def2011-05-21 14:37:15 +0000733 snprintf(errStr, JMSG_LENGTH_MAX,
DRC007a42c2011-05-22 13:55:56 +0000734 "tjGetScalingFactors(): Invalid argument");
DRC109a5782011-03-01 09:53:07 +0000735 return NULL;
DRCb28fc572011-02-22 06:41:29 +0000736 }
737
DRC109a5782011-03-01 09:53:07 +0000738 *numscalingfactors=NUMSF;
739 return (tjscalingfactor *)sf;
DRCb28fc572011-02-22 06:41:29 +0000740}
741
742
DRC9b28def2011-05-21 14:37:15 +0000743DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, unsigned char *jpegBuf,
744 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
745 int height, int pixelFormat, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000746{
DRC9b28def2011-05-21 14:37:15 +0000747 int i, retval=0; JSAMPROW *row_pointer=NULL;
DRC109a5782011-03-01 09:53:07 +0000748 int jpegwidth, jpegheight, scaledw, scaledh;
DRC2e7b76b2009-04-03 12:04:24 +0000749
DRC9b28def2011-05-21 14:37:15 +0000750 getinstance(handle);
751 if((this->init&DECOMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +0000752 _throw("tjDecompress2(): Instance has not been initialized for decompression");
DRC9b28def2011-05-21 14:37:15 +0000753
754 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0
755 || height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF)
756 _throw("tjDecompress2(): Invalid argument");
757
DRC25b995a2011-05-21 15:34:54 +0000758 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
759 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
760 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC9b28def2011-05-21 14:37:15 +0000761
762 if(setjmp(this->jerr.setjmp_buffer))
763 {
764 /* If we get here, the JPEG code has signaled an error. */
765 retval=-1;
766 goto bailout;
767 }
768
769 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
770 jpeg_read_header(dinfo, TRUE);
DRCf12bb302011-09-07 05:03:18 +0000771 if(setDecompDefaults(dinfo, pixelFormat)==-1) return -1;
DRC9b28def2011-05-21 14:37:15 +0000772
DRC25b995a2011-05-21 15:34:54 +0000773 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
DRC9b28def2011-05-21 14:37:15 +0000774
775 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
776 if(width==0) width=jpegwidth;
777 if(height==0) height=jpegheight;
778 for(i=0; i<NUMSF; i++)
779 {
780 scaledw=TJSCALED(jpegwidth, sf[i]);
781 scaledh=TJSCALED(jpegheight, sf[i]);
782 if(scaledw<=width && scaledh<=height)
783 break;
784 }
785 if(scaledw>width || scaledh>height)
DRC007a42c2011-05-22 13:55:56 +0000786 _throw("tjDecompress2(): Could not scale down to desired image dimensions");
DRC9b28def2011-05-21 14:37:15 +0000787 width=scaledw; height=scaledh;
788 dinfo->scale_num=sf[i].num;
789 dinfo->scale_denom=sf[i].denom;
790
791 jpeg_start_decompress(dinfo);
792 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
793 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
794 *dinfo->output_height))==NULL)
DRC007a42c2011-05-22 13:55:56 +0000795 _throw("tjDecompress2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000796 for(i=0; i<(int)dinfo->output_height; i++)
797 {
DRC25b995a2011-05-21 15:34:54 +0000798 if(flags&TJFLAG_BOTTOMUP)
DRC9b28def2011-05-21 14:37:15 +0000799 row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*pitch];
800 else row_pointer[i]=&dstBuf[i*pitch];
801 }
802 while(dinfo->output_scanline<dinfo->output_height)
803 {
804 jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline],
805 dinfo->output_height-dinfo->output_scanline);
806 }
807 jpeg_finish_decompress(dinfo);
808
809 bailout:
810 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
811 if(row_pointer) free(row_pointer);
812 return retval;
813}
814
815DLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf,
816 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
817 int height, int pixelSize, int flags)
818{
819 if(flags&TJ_YUV)
820 return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags);
821 else
822 return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch,
823 height, getPixelFormat(pixelSize, flags), flags);
824}
825
826
827DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle,
828 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
829 int flags)
830{
831 int i, row, retval=0; JSAMPROW *outbuf[MAX_COMPONENTS];
832 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS],
833 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
834 JSAMPLE *_tmpbuf=NULL, *ptr=dstBuf; JSAMPROW *tmpbuf[MAX_COMPONENTS];
835
836 getinstance(handle);
837 if((this->init&DECOMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +0000838 _throw("tjDecompressToYUV(): Instance has not been initialized for decompression");
DRC2e7b76b2009-04-03 12:04:24 +0000839
DRCf9cf5c72010-12-10 10:58:49 +0000840 for(i=0; i<MAX_COMPONENTS; i++)
841 {
842 tmpbuf[i]=NULL; outbuf[i]=NULL;
843 }
DRC9e17f7d2010-12-10 04:59:13 +0000844
DRC9b28def2011-05-21 14:37:15 +0000845 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL)
846 _throw("tjDecompressToYUV(): Invalid argument");
DRC2e7b76b2009-04-03 12:04:24 +0000847
DRC25b995a2011-05-21 15:34:54 +0000848 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
849 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
850 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC0c6a2712010-02-22 08:34:44 +0000851
DRC9b28def2011-05-21 14:37:15 +0000852 if(setjmp(this->jerr.setjmp_buffer))
853 {
854 /* If we get here, the JPEG code has signaled an error. */
DRC91e86ba2011-02-15 05:24:08 +0000855 retval=-1;
856 goto bailout;
DRC9e17f7d2010-12-10 04:59:13 +0000857 }
DRC2e7b76b2009-04-03 12:04:24 +0000858
DRC9b28def2011-05-21 14:37:15 +0000859 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
860 jpeg_read_header(dinfo, TRUE);
DRC2e7b76b2009-04-03 12:04:24 +0000861
DRC9b28def2011-05-21 14:37:15 +0000862 for(i=0; i<dinfo->num_components; i++)
DRC2e7b76b2009-04-03 12:04:24 +0000863 {
DRC9b28def2011-05-21 14:37:15 +0000864 jpeg_component_info *compptr=&dinfo->comp_info[i];
865 int ih;
866 iw[i]=compptr->width_in_blocks*DCTSIZE;
867 ih=compptr->height_in_blocks*DCTSIZE;
868 cw[i]=PAD(dinfo->image_width, dinfo->max_h_samp_factor)
869 *compptr->h_samp_factor/dinfo->max_h_samp_factor;
870 ch[i]=PAD(dinfo->image_height, dinfo->max_v_samp_factor)
871 *compptr->v_samp_factor/dinfo->max_v_samp_factor;
872 if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1;
873 th[i]=compptr->v_samp_factor*DCTSIZE;
874 tmpbufsize+=iw[i]*th[i];
875 if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL)
DRC007a42c2011-05-22 13:55:56 +0000876 _throw("tjDecompressToYUV(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000877 for(row=0; row<ch[i]; row++)
878 {
879 outbuf[i][row]=ptr;
880 ptr+=PAD(cw[i], 4);
881 }
882 }
883 if(usetmpbuf)
884 {
885 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
DRC007a42c2011-05-22 13:55:56 +0000886 _throw("tjDecompressToYUV(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000887 ptr=_tmpbuf;
888 for(i=0; i<dinfo->num_components; i++)
889 {
890 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
DRC007a42c2011-05-22 13:55:56 +0000891 _throw("tjDecompressToYUV(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000892 for(row=0; row<th[i]; row++)
893 {
894 tmpbuf[i][row]=ptr;
895 ptr+=iw[i];
896 }
897 }
898 }
DRC9e17f7d2010-12-10 04:59:13 +0000899
DRC25b995a2011-05-21 15:34:54 +0000900 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
DRC9b28def2011-05-21 14:37:15 +0000901 dinfo->raw_data_out=TRUE;
902
903 jpeg_start_decompress(dinfo);
904 for(row=0; row<(int)dinfo->output_height;
905 row+=dinfo->max_v_samp_factor*DCTSIZE)
906 {
907 JSAMPARRAY yuvptr[MAX_COMPONENTS];
908 int crow[MAX_COMPONENTS];
DRC9e17f7d2010-12-10 04:59:13 +0000909 for(i=0; i<dinfo->num_components; i++)
910 {
911 jpeg_component_info *compptr=&dinfo->comp_info[i];
DRC9b28def2011-05-21 14:37:15 +0000912 crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
913 if(usetmpbuf) yuvptr[i]=tmpbuf[i];
914 else yuvptr[i]=&outbuf[i][crow[i]];
DRCf9cf5c72010-12-10 10:58:49 +0000915 }
DRC9b28def2011-05-21 14:37:15 +0000916 jpeg_read_raw_data(dinfo, yuvptr, dinfo->max_v_samp_factor*DCTSIZE);
DRCf9cf5c72010-12-10 10:58:49 +0000917 if(usetmpbuf)
918 {
DRC9b28def2011-05-21 14:37:15 +0000919 int j;
DRCf9cf5c72010-12-10 10:58:49 +0000920 for(i=0; i<dinfo->num_components; i++)
921 {
DRC9b28def2011-05-21 14:37:15 +0000922 for(j=0; j<min(th[i], ch[i]-crow[i]); j++)
DRCf9cf5c72010-12-10 10:58:49 +0000923 {
DRC9b28def2011-05-21 14:37:15 +0000924 memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], cw[i]);
DRCf9cf5c72010-12-10 10:58:49 +0000925 }
DRC9e17f7d2010-12-10 04:59:13 +0000926 }
927 }
928 }
DRC9b28def2011-05-21 14:37:15 +0000929 jpeg_finish_decompress(dinfo);
DRC2e7b76b2009-04-03 12:04:24 +0000930
DRC91e86ba2011-02-15 05:24:08 +0000931 bailout:
DRC9b28def2011-05-21 14:37:15 +0000932 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
DRC9e17f7d2010-12-10 04:59:13 +0000933 for(i=0; i<MAX_COMPONENTS; i++)
DRCf9cf5c72010-12-10 10:58:49 +0000934 {
935 if(tmpbuf[i]) free(tmpbuf[i]);
DRC9e17f7d2010-12-10 04:59:13 +0000936 if(outbuf[i]) free(outbuf[i]);
DRCf9cf5c72010-12-10 10:58:49 +0000937 }
938 if(_tmpbuf) free(_tmpbuf);
DRC91e86ba2011-02-15 05:24:08 +0000939 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000940}
941
942
DRC9b28def2011-05-21 14:37:15 +0000943/* Transformer */
DRC890f1e02011-02-26 22:02:37 +0000944
945DLLEXPORT tjhandle DLLCALL tjInitTransform(void)
946{
DRC9b28def2011-05-21 14:37:15 +0000947 tjinstance *this=NULL; tjhandle handle=NULL;
948 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
DRCda5220a2011-03-02 02:17:30 +0000949 {
DRC007a42c2011-05-22 13:55:56 +0000950 snprintf(errStr, JMSG_LENGTH_MAX,
951 "tjInitTransform(): Memory allocation failure");
DRCda5220a2011-03-02 02:17:30 +0000952 return NULL;
953 }
DRC007a42c2011-05-22 13:55:56 +0000954 MEMZERO(this, sizeof(tjinstance));
DRC9b28def2011-05-21 14:37:15 +0000955 handle=_tjInitCompress(this);
956 if(!handle) return NULL;
957 handle=_tjInitDecompress(this);
958 return handle;
DRC890f1e02011-02-26 22:02:37 +0000959}
960
961
DRC9b28def2011-05-21 14:37:15 +0000962DLLEXPORT int DLLCALL tjTransform(tjhandle handle, unsigned char *jpegBuf,
963 unsigned long jpegSize, int n, unsigned char **dstBufs,
964 unsigned long *dstSizes, tjtransform *t, int flags)
DRC890f1e02011-02-26 22:02:37 +0000965{
DRC0a325192011-03-02 09:22:41 +0000966 jpeg_transform_info *xinfo=NULL;
DRC890f1e02011-02-26 22:02:37 +0000967 jvirt_barray_ptr *srccoefs, *dstcoefs;
DRC9b49f0e2011-07-12 03:17:23 +0000968 int retval=0, i, jpegSubsamp;
DRC890f1e02011-02-26 22:02:37 +0000969
DRC9b28def2011-05-21 14:37:15 +0000970 getinstance(handle);
971 if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +0000972 _throw("tjTransform(): Instance has not been initialized for transformation");
DRC890f1e02011-02-26 22:02:37 +0000973
DRC9b28def2011-05-21 14:37:15 +0000974 if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL
975 || t==NULL || flags<0)
976 _throw("tjTransform(): Invalid argument");
977
DRC25b995a2011-05-21 15:34:54 +0000978 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
979 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
980 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC890f1e02011-02-26 22:02:37 +0000981
DRC9b28def2011-05-21 14:37:15 +0000982 if(setjmp(this->jerr.setjmp_buffer))
983 {
984 /* If we get here, the JPEG code has signaled an error. */
DRC890f1e02011-02-26 22:02:37 +0000985 retval=-1;
986 goto bailout;
987 }
988
DRC9b28def2011-05-21 14:37:15 +0000989 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
DRC890f1e02011-02-26 22:02:37 +0000990
DRC0a325192011-03-02 09:22:41 +0000991 if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n))
992 ==NULL)
DRC007a42c2011-05-22 13:55:56 +0000993 _throw("tjTransform(): Memory allocation failure");
994 MEMZERO(xinfo, sizeof(jpeg_transform_info)*n);
DRC890f1e02011-02-26 22:02:37 +0000995
DRC0a325192011-03-02 09:22:41 +0000996 for(i=0; i<n; i++)
DRC890f1e02011-02-26 22:02:37 +0000997 {
DRC0a325192011-03-02 09:22:41 +0000998 xinfo[i].transform=xformtypes[t[i].op];
DRC25b995a2011-05-21 15:34:54 +0000999 xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0;
1000 xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0;
1001 xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0;
1002 xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0;
1003 if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1;
DRCba5ea512011-03-04 03:20:34 +00001004 else xinfo[i].slow_hflip=0;
DRC0a325192011-03-02 09:22:41 +00001005
1006 if(xinfo[i].crop)
DRC890f1e02011-02-26 22:02:37 +00001007 {
DRC0a325192011-03-02 09:22:41 +00001008 xinfo[i].crop_xoffset=t[i].r.x; xinfo[i].crop_xoffset_set=JCROP_POS;
1009 xinfo[i].crop_yoffset=t[i].r.y; xinfo[i].crop_yoffset_set=JCROP_POS;
1010 if(t[i].r.w!=0)
1011 {
1012 xinfo[i].crop_width=t[i].r.w; xinfo[i].crop_width_set=JCROP_POS;
1013 }
DRCd932e582011-03-15 20:09:47 +00001014 else xinfo[i].crop_width=JCROP_UNSET;
DRC0a325192011-03-02 09:22:41 +00001015 if(t[i].r.h!=0)
1016 {
1017 xinfo[i].crop_height=t[i].r.h; xinfo[i].crop_height_set=JCROP_POS;
1018 }
DRCd932e582011-03-15 20:09:47 +00001019 else xinfo[i].crop_height=JCROP_UNSET;
DRC890f1e02011-02-26 22:02:37 +00001020 }
1021 }
1022
DRC9b28def2011-05-21 14:37:15 +00001023 jcopy_markers_setup(dinfo, JCOPYOPT_ALL);
1024 jpeg_read_header(dinfo, TRUE);
DRC9b49f0e2011-07-12 03:17:23 +00001025 jpegSubsamp=getSubsamp(dinfo);
1026 if(jpegSubsamp<0)
1027 _throw("tjTransform(): Could not determine subsampling type for JPEG image");
DRC890f1e02011-02-26 22:02:37 +00001028
DRC0a325192011-03-02 09:22:41 +00001029 for(i=0; i<n; i++)
DRC890f1e02011-02-26 22:02:37 +00001030 {
DRC9b28def2011-05-21 14:37:15 +00001031 if(!jtransform_request_workspace(dinfo, &xinfo[i]))
DRC007a42c2011-05-22 13:55:56 +00001032 _throw("tjTransform(): Transform is not perfect");
DRC890f1e02011-02-26 22:02:37 +00001033
DRC0a325192011-03-02 09:22:41 +00001034 if(xinfo[i].crop)
DRC890f1e02011-02-26 22:02:37 +00001035 {
DRC0a325192011-03-02 09:22:41 +00001036 if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0
1037 || (t[i].r.y%xinfo[i].iMCU_sample_height)!=0)
1038 {
DRC9b28def2011-05-21 14:37:15 +00001039 snprintf(errStr, JMSG_LENGTH_MAX,
DRC0a325192011-03-02 09:22:41 +00001040 "To crop this JPEG image, x must be a multiple of %d\n"
1041 "and y must be a multiple of %d.\n",
1042 xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height);
1043 retval=-1; goto bailout;
1044 }
DRC890f1e02011-02-26 22:02:37 +00001045 }
1046 }
1047
DRC9b28def2011-05-21 14:37:15 +00001048 srccoefs=jpeg_read_coefficients(dinfo);
DRC890f1e02011-02-26 22:02:37 +00001049
DRC0a325192011-03-02 09:22:41 +00001050 for(i=0; i<n; i++)
1051 {
DRCff78e372011-05-24 10:17:32 +00001052 int w, h, alloc=1;
DRC0a325192011-03-02 09:22:41 +00001053 if(!xinfo[i].crop)
1054 {
DRC9b28def2011-05-21 14:37:15 +00001055 w=dinfo->image_width; h=dinfo->image_height;
DRC0a325192011-03-02 09:22:41 +00001056 }
1057 else
1058 {
1059 w=xinfo[i].crop_width; h=xinfo[i].crop_height;
1060 }
DRCff78e372011-05-24 10:17:32 +00001061 if(flags&TJFLAG_NOREALLOC)
1062 {
DRC9b49f0e2011-07-12 03:17:23 +00001063 alloc=0; dstSizes[i]=tjBufSize(w, h, jpegSubsamp);
DRCff78e372011-05-24 10:17:32 +00001064 }
DRC7bf04d32011-09-17 00:18:31 +00001065 if(!(t[i].options&TJXOPT_NOOUTPUT))
1066 jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc);
DRC9b28def2011-05-21 14:37:15 +00001067 jpeg_copy_critical_parameters(dinfo, cinfo);
1068 dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs,
DRC0a325192011-03-02 09:22:41 +00001069 &xinfo[i]);
DRC7bf04d32011-09-17 00:18:31 +00001070 if(!(t[i].options&TJXOPT_NOOUTPUT))
1071 {
1072 jpeg_write_coefficients(cinfo, dstcoefs);
1073 jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL);
1074 }
1075 else jinit_c_master_control(cinfo, TRUE);
DRC9b28def2011-05-21 14:37:15 +00001076 jtransform_execute_transformation(dinfo, cinfo, srccoefs,
DRC0a325192011-03-02 09:22:41 +00001077 &xinfo[i]);
DRC7bf04d32011-09-17 00:18:31 +00001078 if(t[i].customFilter)
1079 {
DRCefe28ce2012-01-17 11:48:38 +00001080 int ci, y; JDIMENSION by;
DRC7bf04d32011-09-17 00:18:31 +00001081 for(ci=0; ci<cinfo->num_components; ci++)
1082 {
1083 jpeg_component_info *compptr=&cinfo->comp_info[ci];
1084 tjregion arrayRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
1085 DCTSIZE};
1086 tjregion planeRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
1087 compptr->height_in_blocks*DCTSIZE};
1088 for(by=0; by<compptr->height_in_blocks; by+=compptr->v_samp_factor)
1089 {
1090 JBLOCKARRAY barray=(dinfo->mem->access_virt_barray)
1091 ((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor,
1092 TRUE);
1093 for(y=0; y<compptr->v_samp_factor; y++)
1094 {
1095 if(t[i].customFilter(barray[y][0], arrayRegion, planeRegion,
DRCf5467112011-09-20 05:02:19 +00001096 ci, i, &t[i])==-1)
DRC7bf04d32011-09-17 00:18:31 +00001097 _throw("tjTransform(): Error in custom filter");
1098 arrayRegion.y+=DCTSIZE;
1099 }
1100 }
1101 }
1102 }
1103 if(!(t[i].options&TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo);
DRC0a325192011-03-02 09:22:41 +00001104 }
1105
DRC9b28def2011-05-21 14:37:15 +00001106 jpeg_finish_decompress(dinfo);
DRC890f1e02011-02-26 22:02:37 +00001107
DRC890f1e02011-02-26 22:02:37 +00001108 bailout:
DRC9b28def2011-05-21 14:37:15 +00001109 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
1110 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
DRC0a325192011-03-02 09:22:41 +00001111 if(xinfo) free(xinfo);
DRC890f1e02011-02-26 22:02:37 +00001112 return retval;
1113}