blob: 5cc543743f38127faa64c5ce22aa815159392611 [file] [log] [blame]
DRC2e7b76b2009-04-03 12:04:24 +00001/* Copyright (C)2004 Landmark Graphics Corporation
2 * Copyright (C)2005 Sun Microsystems, Inc.
DRC91e86ba2011-02-15 05:24:08 +00003 * Copyright (C)2009-2011 D. R. Commander
DRC2e7b76b2009-04-03 12:04:24 +00004 *
5 * This library is free software and may be redistributed and/or modified under
6 * the terms of the wxWindows Library License, Version 3.1 or (at your option)
7 * any later version. The full license is in the LICENSE.txt file included
8 * with this distribution.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * wxWindows Library License for more details.
14 */
15
16// This implements a JPEG compressor/decompressor using the libjpeg API
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
DRCfbb67472010-11-24 04:02:37 +000021#define JPEG_INTERNALS
DRC2e7b76b2009-04-03 12:04:24 +000022#include <jpeglib.h>
23#include <jerror.h>
24#include <setjmp.h>
25#include "./turbojpeg.h"
DRC2a2e4512011-01-05 22:33:24 +000026
DRCfbb67472010-11-24 04:02:37 +000027#ifndef min
28 #define min(a,b) ((a)<(b)?(a):(b))
29#endif
30
31#define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
DRC2e7b76b2009-04-03 12:04:24 +000032
33
34// Error handling
35
36static char lasterror[JMSG_LENGTH_MAX]="No error";
37
38typedef struct _error_mgr
39{
40 struct jpeg_error_mgr pub;
41 jmp_buf jb;
42} error_mgr;
43
44static void my_error_exit(j_common_ptr cinfo)
45{
46 error_mgr *myerr = (error_mgr *)cinfo->err;
47 (*cinfo->err->output_message)(cinfo);
48 longjmp(myerr->jb, 1);
49}
50
51static void my_output_message(j_common_ptr cinfo)
52{
53 (*cinfo->err->format_message)(cinfo, lasterror);
54}
55
56
57// Global structures, macros, etc.
58
59typedef struct _jpgstruct
60{
61 struct jpeg_compress_struct cinfo;
62 struct jpeg_decompress_struct dinfo;
63 struct jpeg_destination_mgr jdms;
64 struct jpeg_source_mgr jsms;
65 error_mgr jerr;
66 int initc, initd;
67} jpgstruct;
68
69static const int hsampfactor[NUMSUBOPT]={1, 2, 2, 1};
70static const int vsampfactor[NUMSUBOPT]={1, 1, 2, 1};
DRC1fe80f82010-12-14 01:21:29 +000071static const int pixelsize[NUMSUBOPT]={3, 3, 3, 1};
DRC2e7b76b2009-04-03 12:04:24 +000072
DRC91e86ba2011-02-15 05:24:08 +000073#define _throw(c) {sprintf(lasterror, "%s", c); retval=-1; goto bailout;}
DRC2e7b76b2009-04-03 12:04:24 +000074#define checkhandle(h) jpgstruct *j=(jpgstruct *)h; \
DRC91e86ba2011-02-15 05:24:08 +000075 if(!j) {sprintf(lasterror, "Invalid handle"); return -1;}
DRC2e7b76b2009-04-03 12:04:24 +000076
77
78// CO
79
80static boolean empty_output_buffer(struct jpeg_compress_struct *cinfo)
81{
82 ERREXIT(cinfo, JERR_BUFFER_SIZE);
83 return TRUE;
84}
85
86static void destination_noop(struct jpeg_compress_struct *cinfo)
87{
88}
89
90DLLEXPORT tjhandle DLLCALL tjInitCompress(void)
91{
92 jpgstruct *j=NULL;
93 if((j=(jpgstruct *)malloc(sizeof(jpgstruct)))==NULL)
94 {sprintf(lasterror, "Memory allocation failure"); return NULL;}
95 memset(j, 0, sizeof(jpgstruct));
96 j->cinfo.err=jpeg_std_error(&j->jerr.pub);
97 j->jerr.pub.error_exit=my_error_exit;
98 j->jerr.pub.output_message=my_output_message;
99
100 if(setjmp(j->jerr.jb))
101 { // this will execute if LIBJPEG has an error
102 if(j) free(j); return NULL;
DRCefa4ddc2010-10-13 19:22:50 +0000103 }
DRC2e7b76b2009-04-03 12:04:24 +0000104
105 jpeg_create_compress(&j->cinfo);
106 j->cinfo.dest=&j->jdms;
107 j->jdms.init_destination=destination_noop;
108 j->jdms.empty_output_buffer=empty_output_buffer;
109 j->jdms.term_destination=destination_noop;
110
111 j->initc=1;
112 return (tjhandle)j;
113}
114
DRCeeab6952011-02-25 00:02:04 +0000115
DRC2e7b76b2009-04-03 12:04:24 +0000116DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
117{
DRCeeab6952011-02-25 00:02:04 +0000118 unsigned long retval=0;
119 if(width<1 || height<1)
120 _throw("Invalid argument in TJBUFSIZE()");
121
122 // This allows for rare corner cases in which a JPEG image can actually be
123 // larger than the uncompressed input (we wouldn't mention it if it hadn't
124 // happened before.)
125 retval=((width+15)&(~15)) * ((height+15)&(~15)) * 6 + 2048;
126
127 bailout:
128 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000129}
130
DRCeeab6952011-02-25 00:02:04 +0000131
132DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
133 int subsamp)
134{
135 unsigned long retval=0;
136 int pw, ph, cw, ch;
137 if(width<1 || height<1 || subsamp<0 || subsamp>=NUMSUBOPT)
138 _throw("Invalid argument in TJBUFSIZEYUV()");
139 pw=PAD(width, hsampfactor[subsamp]);
140 ph=PAD(height, vsampfactor[subsamp]);
141 cw=pw/hsampfactor[subsamp]; ch=ph/vsampfactor[subsamp];
142 retval=PAD(pw, 4)*ph + (subsamp==TJ_GRAYSCALE? 0:PAD(cw, 4)*ch*2);
143
144 bailout:
145 return retval;
146}
147
148
DRC2e7b76b2009-04-03 12:04:24 +0000149DLLEXPORT int DLLCALL tjCompress(tjhandle h,
150 unsigned char *srcbuf, int width, int pitch, int height, int ps,
151 unsigned char *dstbuf, unsigned long *size,
152 int jpegsub, int qual, int flags)
153{
DRC91e86ba2011-02-15 05:24:08 +0000154 int i, retval=0; JSAMPROW *row_pointer=NULL;
DRCfbb67472010-11-24 04:02:37 +0000155 JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS];
156 JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
157 JSAMPROW *outbuf[MAX_COMPONENTS];
DRC2e7b76b2009-04-03 12:04:24 +0000158
159 checkhandle(h);
160
DRCfbb67472010-11-24 04:02:37 +0000161 for(i=0; i<MAX_COMPONENTS; i++)
162 {
163 tmpbuf[i]=NULL; _tmpbuf[i]=NULL;
164 tmpbuf2[i]=NULL; _tmpbuf2[i]=NULL; outbuf[i]=NULL;
165 }
166
DRC2e7b76b2009-04-03 12:04:24 +0000167 if(srcbuf==NULL || width<=0 || pitch<0 || height<=0
168 || dstbuf==NULL || size==NULL
169 || jpegsub<0 || jpegsub>=NUMSUBOPT || qual<0 || qual>100)
170 _throw("Invalid argument in tjCompress()");
DRC09854f52010-11-04 22:39:59 +0000171 if(ps!=3 && ps!=4 && ps!=1)
172 _throw("This compressor can only handle 24-bit and 32-bit RGB or 8-bit grayscale input");
DRC2e7b76b2009-04-03 12:04:24 +0000173 if(!j->initc) _throw("Instance has not been initialized for compression");
174
175 if(pitch==0) pitch=width*ps;
176
177 j->cinfo.image_width = width;
178 j->cinfo.image_height = height;
179 j->cinfo.input_components = ps;
180
DRC09854f52010-11-04 22:39:59 +0000181 if(ps==1) j->cinfo.in_color_space = JCS_GRAYSCALE;
DRC2e7b76b2009-04-03 12:04:24 +0000182 #if JCS_EXTENSIONS==1
DRC09854f52010-11-04 22:39:59 +0000183 else j->cinfo.in_color_space = JCS_EXT_RGB;
DRC2e7b76b2009-04-03 12:04:24 +0000184 if(ps==3 && (flags&TJ_BGR))
185 j->cinfo.in_color_space = JCS_EXT_BGR;
186 else if(ps==4 && !(flags&TJ_BGR) && !(flags&TJ_ALPHAFIRST))
187 j->cinfo.in_color_space = JCS_EXT_RGBX;
188 else if(ps==4 && (flags&TJ_BGR) && !(flags&TJ_ALPHAFIRST))
189 j->cinfo.in_color_space = JCS_EXT_BGRX;
190 else if(ps==4 && (flags&TJ_BGR) && (flags&TJ_ALPHAFIRST))
191 j->cinfo.in_color_space = JCS_EXT_XBGR;
192 else if(ps==4 && !(flags&TJ_BGR) && (flags&TJ_ALPHAFIRST))
193 j->cinfo.in_color_space = JCS_EXT_XRGB;
194 #else
195 #error "TurboJPEG requires JPEG colorspace extensions"
196 #endif
197
DRC0c6a2712010-02-22 08:34:44 +0000198 if(flags&TJ_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
199 else if(flags&TJ_FORCESSE) putenv("JSIMD_FORCESSE=1");
200 else if(flags&TJ_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
201
DRC2e7b76b2009-04-03 12:04:24 +0000202 if(setjmp(j->jerr.jb))
203 { // this will execute if LIBJPEG has an error
DRC91e86ba2011-02-15 05:24:08 +0000204 retval=-1;
205 goto bailout;
DRCefa4ddc2010-10-13 19:22:50 +0000206 }
DRC2e7b76b2009-04-03 12:04:24 +0000207
208 jpeg_set_defaults(&j->cinfo);
209
210 jpeg_set_quality(&j->cinfo, qual, TRUE);
211 if(jpegsub==TJ_GRAYSCALE)
212 jpeg_set_colorspace(&j->cinfo, JCS_GRAYSCALE);
213 else
214 jpeg_set_colorspace(&j->cinfo, JCS_YCbCr);
DRCe1716b82011-02-18 03:19:43 +0000215 if(qual>=96) j->cinfo.dct_method=JDCT_ISLOW;
216 else j->cinfo.dct_method=JDCT_FASTEST;
DRC2e7b76b2009-04-03 12:04:24 +0000217
218 j->cinfo.comp_info[0].h_samp_factor=hsampfactor[jpegsub];
219 j->cinfo.comp_info[1].h_samp_factor=1;
220 j->cinfo.comp_info[2].h_samp_factor=1;
221 j->cinfo.comp_info[0].v_samp_factor=vsampfactor[jpegsub];
222 j->cinfo.comp_info[1].v_samp_factor=1;
223 j->cinfo.comp_info[2].v_samp_factor=1;
224
225 j->jdms.next_output_byte = dstbuf;
226 j->jdms.free_in_buffer = TJBUFSIZE(j->cinfo.image_width, j->cinfo.image_height);
227
DRC2e7b76b2009-04-03 12:04:24 +0000228 jpeg_start_compress(&j->cinfo, TRUE);
DRCfbb67472010-11-24 04:02:37 +0000229 if(flags&TJ_YUV)
DRC2e7b76b2009-04-03 12:04:24 +0000230 {
DRCfbb67472010-11-24 04:02:37 +0000231 j_compress_ptr cinfo=&j->cinfo;
232 int row;
233 int pw=PAD(width, cinfo->max_h_samp_factor);
234 int ph=PAD(height, cinfo->max_v_samp_factor);
235 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS];
236 jpeg_component_info *compptr;
237 JSAMPLE *ptr=dstbuf; unsigned long yuvsize=0;
238
239 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph))==NULL)
240 _throw("Memory allocation failed in tjCompress()");
241 for(i=0; i<height; i++)
242 {
243 if(flags&TJ_BOTTOMUP) row_pointer[i]= &srcbuf[(height-i-1)*pitch];
244 else row_pointer[i]= &srcbuf[i*pitch];
245 }
246 if(height<ph)
247 for(i=height; i<ph; i++) row_pointer[i]=row_pointer[height-1];
248
249 for(i=0; i<cinfo->num_components; i++)
250 {
251 compptr=&cinfo->comp_info[i];
DRC57423072011-01-05 23:35:53 +0000252 _tmpbuf[i]=(JSAMPLE *)malloc(
DRCfbb67472010-11-24 04:02:37 +0000253 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
DRC57423072011-01-05 23:35:53 +0000254 /compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
DRCfbb67472010-11-24 04:02:37 +0000255 if(!_tmpbuf[i]) _throw("Memory allocation failure");
DRC2a2e4512011-01-05 22:33:24 +0000256 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
DRCfbb67472010-11-24 04:02:37 +0000257 if(!tmpbuf[i]) _throw("Memory allocation failure");
258 for(row=0; row<cinfo->max_v_samp_factor; row++)
DRC57423072011-01-05 23:35:53 +0000259 {
260 unsigned char *_tmpbuf_aligned=
261 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
262 tmpbuf[i][row]=&_tmpbuf_aligned[
DRCfbb67472010-11-24 04:02:37 +0000263 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
264 /compptr->h_samp_factor, 16) * row];
DRC57423072011-01-05 23:35:53 +0000265 }
266 _tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
267 * compptr->v_samp_factor + 16);
DRCfbb67472010-11-24 04:02:37 +0000268 if(!_tmpbuf2[i]) _throw("Memory allocation failure");
DRC2a2e4512011-01-05 22:33:24 +0000269 tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
DRCfbb67472010-11-24 04:02:37 +0000270 if(!tmpbuf2[i]) _throw("Memory allocation failure");
271 for(row=0; row<compptr->v_samp_factor; row++)
DRC57423072011-01-05 23:35:53 +0000272 {
273 unsigned char *_tmpbuf2_aligned=
274 (unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
275 tmpbuf2[i][row]=&_tmpbuf2_aligned[
DRCfbb67472010-11-24 04:02:37 +0000276 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
DRC57423072011-01-05 23:35:53 +0000277 }
DRCfbb67472010-11-24 04:02:37 +0000278 cw[i]=pw*compptr->h_samp_factor/cinfo->max_h_samp_factor;
279 ch[i]=ph*compptr->v_samp_factor/cinfo->max_v_samp_factor;
DRC2a2e4512011-01-05 22:33:24 +0000280 outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]);
DRCfbb67472010-11-24 04:02:37 +0000281 if(!outbuf[i]) _throw("Memory allocation failure");
282 for(row=0; row<ch[i]; row++)
283 {
284 outbuf[i][row]=ptr;
285 ptr+=PAD(cw[i], 4);
286 }
287 }
288 yuvsize=(unsigned long)(ptr-dstbuf);
289
290 for(row=0; row<ph; row+=cinfo->max_v_samp_factor)
291 {
292 (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf,
293 0, cinfo->max_v_samp_factor);
294 (cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
295 for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components;
296 i++, compptr++)
297 jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
298 row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
299 compptr->v_samp_factor, cw[i]);
300 }
301 *size=yuvsize;
302 cinfo->next_scanline+=height;
DRC6ee54592011-03-01 08:18:30 +0000303 jpeg_abort_compress(&j->cinfo);
DRCfbb67472010-11-24 04:02:37 +0000304 }
305 else
306 {
307 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
308 _throw("Memory allocation failed in tjCompress()");
309 for(i=0; i<height; i++)
310 {
311 if(flags&TJ_BOTTOMUP) row_pointer[i]= &srcbuf[(height-i-1)*pitch];
312 else row_pointer[i]= &srcbuf[i*pitch];
313 }
314 while(j->cinfo.next_scanline<j->cinfo.image_height)
315 {
316 jpeg_write_scanlines(&j->cinfo, &row_pointer[j->cinfo.next_scanline],
317 j->cinfo.image_height-j->cinfo.next_scanline);
318 }
DRC6ee54592011-03-01 08:18:30 +0000319 jpeg_finish_compress(&j->cinfo);
DRCfbb67472010-11-24 04:02:37 +0000320 *size=TJBUFSIZE(j->cinfo.image_width, j->cinfo.image_height)
321 -(unsigned long)(j->jdms.free_in_buffer);
DRC6ee54592011-03-01 08:18:30 +0000322 }
DRC2e7b76b2009-04-03 12:04:24 +0000323
DRC91e86ba2011-02-15 05:24:08 +0000324 bailout:
DRC582a46a2011-02-24 21:16:10 +0000325 if(j->cinfo.global_state>CSTATE_START) jpeg_abort_compress(&j->cinfo);
DRC2e7b76b2009-04-03 12:04:24 +0000326 if(row_pointer) free(row_pointer);
DRCfbb67472010-11-24 04:02:37 +0000327 for(i=0; i<MAX_COMPONENTS; i++)
328 {
329 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
DRC57423072011-01-05 23:35:53 +0000330 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
DRCfbb67472010-11-24 04:02:37 +0000331 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
DRC57423072011-01-05 23:35:53 +0000332 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
DRCfbb67472010-11-24 04:02:37 +0000333 if(outbuf[i]!=NULL) free(outbuf[i]);
334 }
DRC91e86ba2011-02-15 05:24:08 +0000335 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000336}
337
338
DRCeeab6952011-02-25 00:02:04 +0000339DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle h,
340 unsigned char *srcbuf, int width, int pitch, int height, int ps,
341 unsigned char *dstbuf, int subsamp, int flags)
342{
343 unsigned long size;
344 return tjCompress(h, srcbuf, width, pitch, height, ps, dstbuf, &size,
345 subsamp, 0, flags|TJ_YUV);
346}
347
348
DRC2e7b76b2009-04-03 12:04:24 +0000349// DEC
350
351static boolean fill_input_buffer (struct jpeg_decompress_struct *dinfo)
352{
353 ERREXIT(dinfo, JERR_BUFFER_SIZE);
354 return TRUE;
355}
356
357static void skip_input_data (struct jpeg_decompress_struct *dinfo, long num_bytes)
358{
359 dinfo->src->next_input_byte += (size_t) num_bytes;
360 dinfo->src->bytes_in_buffer -= (size_t) num_bytes;
361}
362
363static void source_noop (struct jpeg_decompress_struct *dinfo)
364{
365}
366
367DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
368{
369 jpgstruct *j;
370 if((j=(jpgstruct *)malloc(sizeof(jpgstruct)))==NULL)
371 {sprintf(lasterror, "Memory allocation failure"); return NULL;}
372 memset(j, 0, sizeof(jpgstruct));
373 j->dinfo.err=jpeg_std_error(&j->jerr.pub);
374 j->jerr.pub.error_exit=my_error_exit;
375 j->jerr.pub.output_message=my_output_message;
376
377 if(setjmp(j->jerr.jb))
378 { // this will execute if LIBJPEG has an error
379 free(j); return NULL;
DRC9e17f7d2010-12-10 04:59:13 +0000380 }
DRC2e7b76b2009-04-03 12:04:24 +0000381
382 jpeg_create_decompress(&j->dinfo);
383 j->dinfo.src=&j->jsms;
384 j->jsms.init_source=source_noop;
385 j->jsms.fill_input_buffer = fill_input_buffer;
386 j->jsms.skip_input_data = skip_input_data;
387 j->jsms.resync_to_restart = jpeg_resync_to_restart;
388 j->jsms.term_source = source_noop;
389
390 j->initd=1;
391 return (tjhandle)j;
392}
393
394
DRC1fe80f82010-12-14 01:21:29 +0000395DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle h,
396 unsigned char *srcbuf, unsigned long size,
397 int *width, int *height, int *jpegsub)
398{
DRC91e86ba2011-02-15 05:24:08 +0000399 int i, k, retval=0;
DRC1fe80f82010-12-14 01:21:29 +0000400
401 checkhandle(h);
402
403 if(srcbuf==NULL || size<=0 || width==NULL || height==NULL || jpegsub==NULL)
DRC91e86ba2011-02-15 05:24:08 +0000404 _throw("Invalid argument in tjDecompressHeader2()");
DRC1fe80f82010-12-14 01:21:29 +0000405 if(!j->initd) _throw("Instance has not been initialized for decompression");
406
407 if(setjmp(j->jerr.jb))
408 { // this will execute if LIBJPEG has an error
409 return -1;
410 }
411
412 j->jsms.bytes_in_buffer = size;
413 j->jsms.next_input_byte = srcbuf;
414
415 jpeg_read_header(&j->dinfo, TRUE);
416
417 *width=j->dinfo.image_width; *height=j->dinfo.image_height;
418 *jpegsub=-1;
419 for(i=0; i<NUMSUBOPT; i++)
420 {
421 if(j->dinfo.num_components==pixelsize[i])
422 {
423 if(j->dinfo.comp_info[0].h_samp_factor==hsampfactor[i]
424 && j->dinfo.comp_info[0].v_samp_factor==vsampfactor[i])
425 {
426 int match=0;
427 for(k=1; k<j->dinfo.num_components; k++)
428 {
429 if(j->dinfo.comp_info[k].h_samp_factor==1
430 && j->dinfo.comp_info[k].v_samp_factor==1)
431 match++;
432 }
433 if(match==j->dinfo.num_components-1)
434 {
435 *jpegsub=i; break;
436 }
437 }
438 }
439 }
440
441 jpeg_abort_decompress(&j->dinfo);
442
443 if(*jpegsub<0) _throw("Could not determine subsampling type for JPEG image");
444 if(*width<1 || *height<1) _throw("Invalid data returned in header");
DRC91e86ba2011-02-15 05:24:08 +0000445
446 bailout:
447 return retval;
448}
449
450
451DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle h,
452 unsigned char *srcbuf, unsigned long size,
453 int *width, int *height)
454{
455 int jpegsub;
456 return tjDecompressHeader2(h, srcbuf, size, width, height, &jpegsub);
DRC1fe80f82010-12-14 01:21:29 +0000457}
458
459
DRC2e7b76b2009-04-03 12:04:24 +0000460DLLEXPORT int DLLCALL tjDecompress(tjhandle h,
461 unsigned char *srcbuf, unsigned long size,
462 unsigned char *dstbuf, int width, int pitch, int height, int ps,
463 int flags)
464{
DRC91e86ba2011-02-15 05:24:08 +0000465 int i, row, retval=0; JSAMPROW *row_pointer=NULL, *outbuf[MAX_COMPONENTS];
DRCf9cf5c72010-12-10 10:58:49 +0000466 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS],
467 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
468 JSAMPLE *_tmpbuf=NULL; JSAMPROW *tmpbuf[MAX_COMPONENTS];
DRC2e7b76b2009-04-03 12:04:24 +0000469
470 checkhandle(h);
471
DRCf9cf5c72010-12-10 10:58:49 +0000472 for(i=0; i<MAX_COMPONENTS; i++)
473 {
474 tmpbuf[i]=NULL; outbuf[i]=NULL;
475 }
DRC9e17f7d2010-12-10 04:59:13 +0000476
DRC2e7b76b2009-04-03 12:04:24 +0000477 if(srcbuf==NULL || size<=0
478 || dstbuf==NULL || width<=0 || pitch<0 || height<=0)
479 _throw("Invalid argument in tjDecompress()");
DRC09854f52010-11-04 22:39:59 +0000480 if(ps!=3 && ps!=4 && ps!=1)
481 _throw("This decompressor can only handle 24-bit and 32-bit RGB or 8-bit grayscale output");
DRC2e7b76b2009-04-03 12:04:24 +0000482 if(!j->initd) _throw("Instance has not been initialized for decompression");
483
484 if(pitch==0) pitch=width*ps;
485
DRC0c6a2712010-02-22 08:34:44 +0000486 if(flags&TJ_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
487 else if(flags&TJ_FORCESSE) putenv("JSIMD_FORCESSE=1");
488 else if(flags&TJ_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
489
DRC2e7b76b2009-04-03 12:04:24 +0000490 if(setjmp(j->jerr.jb))
491 { // this will execute if LIBJPEG has an error
DRC91e86ba2011-02-15 05:24:08 +0000492 retval=-1;
493 goto bailout;
DRC9e17f7d2010-12-10 04:59:13 +0000494 }
DRC2e7b76b2009-04-03 12:04:24 +0000495
496 j->jsms.bytes_in_buffer = size;
497 j->jsms.next_input_byte = srcbuf;
498
499 jpeg_read_header(&j->dinfo, TRUE);
500
DRC9e17f7d2010-12-10 04:59:13 +0000501 if(flags&TJ_YUV)
DRC2e7b76b2009-04-03 12:04:24 +0000502 {
DRC9e17f7d2010-12-10 04:59:13 +0000503 j_decompress_ptr dinfo=&j->dinfo;
504 JSAMPLE *ptr=dstbuf;
505
506 for(i=0; i<dinfo->num_components; i++)
507 {
508 jpeg_component_info *compptr=&dinfo->comp_info[i];
DRCf9cf5c72010-12-10 10:58:49 +0000509 int ih;
510 iw[i]=compptr->width_in_blocks*DCTSIZE;
511 ih=compptr->height_in_blocks*DCTSIZE;
DRCeeab6952011-02-25 00:02:04 +0000512 cw[i]=PAD(dinfo->image_width, dinfo->max_h_samp_factor)
513 *compptr->h_samp_factor/dinfo->max_h_samp_factor;
514 ch[i]=PAD(dinfo->image_height, dinfo->max_v_samp_factor)
515 *compptr->v_samp_factor/dinfo->max_v_samp_factor;
DRCa6f4fca2010-12-11 06:01:11 +0000516 if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1;
517 th[i]=compptr->v_samp_factor*DCTSIZE;
518 tmpbufsize+=iw[i]*th[i];
DRC9e17f7d2010-12-10 04:59:13 +0000519 if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL)
DRC0745c0f2011-02-25 01:31:13 +0000520 _throw("Memory allocation failed in tjDecompress()");
DRC9e17f7d2010-12-10 04:59:13 +0000521 for(row=0; row<ch[i]; row++)
522 {
523 outbuf[i][row]=ptr;
DRCf9cf5c72010-12-10 10:58:49 +0000524 ptr+=PAD(cw[i], 4);
525 }
526 }
527 if(usetmpbuf)
528 {
529 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
DRC0745c0f2011-02-25 01:31:13 +0000530 _throw("Memory allocation failed in tjDecompress()");
DRCf9cf5c72010-12-10 10:58:49 +0000531 ptr=_tmpbuf;
532 for(i=0; i<dinfo->num_components; i++)
533 {
DRCf9cf5c72010-12-10 10:58:49 +0000534 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
DRC0745c0f2011-02-25 01:31:13 +0000535 _throw("Memory allocation failed in tjDecompress()");
DRCf9cf5c72010-12-10 10:58:49 +0000536 for(row=0; row<th[i]; row++)
537 {
538 tmpbuf[i][row]=ptr;
539 ptr+=iw[i];
540 }
DRC9e17f7d2010-12-10 04:59:13 +0000541 }
542 }
543 }
544 else
545 {
546 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
DRC0745c0f2011-02-25 01:31:13 +0000547 _throw("Memory allocation failed in tjDecompress()");
DRC9e17f7d2010-12-10 04:59:13 +0000548 for(i=0; i<height; i++)
549 {
550 if(flags&TJ_BOTTOMUP) row_pointer[i]= &dstbuf[(height-i-1)*pitch];
551 else row_pointer[i]= &dstbuf[i*pitch];
552 }
DRC2e7b76b2009-04-03 12:04:24 +0000553 }
554
DRC09854f52010-11-04 22:39:59 +0000555 if(ps==1) j->dinfo.out_color_space = JCS_GRAYSCALE;
DRC2e7b76b2009-04-03 12:04:24 +0000556 #if JCS_EXTENSIONS==1
DRC09854f52010-11-04 22:39:59 +0000557 else j->dinfo.out_color_space = JCS_EXT_RGB;
DRC2e7b76b2009-04-03 12:04:24 +0000558 if(ps==3 && (flags&TJ_BGR))
559 j->dinfo.out_color_space = JCS_EXT_BGR;
560 else if(ps==4 && !(flags&TJ_BGR) && !(flags&TJ_ALPHAFIRST))
561 j->dinfo.out_color_space = JCS_EXT_RGBX;
562 else if(ps==4 && (flags&TJ_BGR) && !(flags&TJ_ALPHAFIRST))
563 j->dinfo.out_color_space = JCS_EXT_BGRX;
564 else if(ps==4 && (flags&TJ_BGR) && (flags&TJ_ALPHAFIRST))
565 j->dinfo.out_color_space = JCS_EXT_XBGR;
566 else if(ps==4 && !(flags&TJ_BGR) && (flags&TJ_ALPHAFIRST))
567 j->dinfo.out_color_space = JCS_EXT_XRGB;
568 #else
569 #error "TurboJPEG requires JPEG colorspace extensions"
570 #endif
DRCfbb67472010-11-24 04:02:37 +0000571
DRC61e51f92009-04-05 21:53:20 +0000572 if(flags&TJ_FASTUPSAMPLE) j->dinfo.do_fancy_upsampling=FALSE;
DRC9e17f7d2010-12-10 04:59:13 +0000573 if(flags&TJ_YUV) j->dinfo.raw_data_out=TRUE;
DRC2e7b76b2009-04-03 12:04:24 +0000574
575 jpeg_start_decompress(&j->dinfo);
DRC9e17f7d2010-12-10 04:59:13 +0000576 if(flags&TJ_YUV)
DRC2e7b76b2009-04-03 12:04:24 +0000577 {
DRCf9cf5c72010-12-10 10:58:49 +0000578 j_decompress_ptr dinfo=&j->dinfo;
579 for(row=0; row<dinfo->output_height;
580 row+=dinfo->max_v_samp_factor*DCTSIZE)
DRC9e17f7d2010-12-10 04:59:13 +0000581 {
582 JSAMPARRAY yuvptr[MAX_COMPONENTS];
DRCa6f4fca2010-12-11 06:01:11 +0000583 int crow[MAX_COMPONENTS];
DRCf9cf5c72010-12-10 10:58:49 +0000584 for(i=0; i<dinfo->num_components; i++)
DRC9e17f7d2010-12-10 04:59:13 +0000585 {
DRCf9cf5c72010-12-10 10:58:49 +0000586 jpeg_component_info *compptr=&dinfo->comp_info[i];
DRCa6f4fca2010-12-11 06:01:11 +0000587 crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
DRCf9cf5c72010-12-10 10:58:49 +0000588 if(usetmpbuf) yuvptr[i]=tmpbuf[i];
DRCa6f4fca2010-12-11 06:01:11 +0000589 else yuvptr[i]=&outbuf[i][crow[i]];
DRC9e17f7d2010-12-10 04:59:13 +0000590 }
DRCf9cf5c72010-12-10 10:58:49 +0000591 jpeg_read_raw_data(dinfo, yuvptr, dinfo->max_v_samp_factor*DCTSIZE);
592 if(usetmpbuf)
593 {
594 int j;
595 for(i=0; i<dinfo->num_components; i++)
596 {
DRCa6f4fca2010-12-11 06:01:11 +0000597 for(j=0; j<min(th[i], ch[i]-crow[i]); j++)
DRCf9cf5c72010-12-10 10:58:49 +0000598 {
DRCa6f4fca2010-12-11 06:01:11 +0000599 memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], cw[i]);
DRCf9cf5c72010-12-10 10:58:49 +0000600 }
601 }
602 }
DRC9e17f7d2010-12-10 04:59:13 +0000603 }
604 }
605 else
606 {
607 while(j->dinfo.output_scanline<j->dinfo.output_height)
608 {
609 jpeg_read_scanlines(&j->dinfo, &row_pointer[j->dinfo.output_scanline],
610 j->dinfo.output_height-j->dinfo.output_scanline);
611 }
DRC2e7b76b2009-04-03 12:04:24 +0000612 }
613 jpeg_finish_decompress(&j->dinfo);
614
DRC91e86ba2011-02-15 05:24:08 +0000615 bailout:
DRC582a46a2011-02-24 21:16:10 +0000616 if(j->dinfo.global_state>DSTATE_START) jpeg_abort_decompress(&j->dinfo);
DRC9e17f7d2010-12-10 04:59:13 +0000617 for(i=0; i<MAX_COMPONENTS; i++)
DRCf9cf5c72010-12-10 10:58:49 +0000618 {
619 if(tmpbuf[i]) free(tmpbuf[i]);
DRC9e17f7d2010-12-10 04:59:13 +0000620 if(outbuf[i]) free(outbuf[i]);
DRCf9cf5c72010-12-10 10:58:49 +0000621 }
622 if(_tmpbuf) free(_tmpbuf);
DRC2e7b76b2009-04-03 12:04:24 +0000623 if(row_pointer) free(row_pointer);
DRC91e86ba2011-02-15 05:24:08 +0000624 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000625}
626
627
DRCeeab6952011-02-25 00:02:04 +0000628DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle h,
629 unsigned char *srcbuf, unsigned long size,
630 unsigned char *dstbuf, int flags)
631{
632 return tjDecompress(h, srcbuf, size, dstbuf, 1, 0, 1, 3, flags|TJ_YUV);
633}
634
635
DRC2e7b76b2009-04-03 12:04:24 +0000636// General
637
638DLLEXPORT char* DLLCALL tjGetErrorStr(void)
639{
640 return lasterror;
641}
642
643DLLEXPORT int DLLCALL tjDestroy(tjhandle h)
644{
645 checkhandle(h);
646 if(setjmp(j->jerr.jb)) return -1;
647 if(j->initc) jpeg_destroy_compress(&j->cinfo);
648 if(j->initd) jpeg_destroy_decompress(&j->dinfo);
649 free(j);
650 return 0;
651}