blob: 7dd6a41a796b73343b2644be4e3a7e7d45d26089 [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
115DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
116{
117 // This allows enough room in case the image doesn't compress
118 return ((width+15)&(~15)) * ((height+15)&(~15)) * 6 + 2048;
119}
120
121DLLEXPORT int DLLCALL tjCompress(tjhandle h,
122 unsigned char *srcbuf, int width, int pitch, int height, int ps,
123 unsigned char *dstbuf, unsigned long *size,
124 int jpegsub, int qual, int flags)
125{
DRC91e86ba2011-02-15 05:24:08 +0000126 int i, retval=0; JSAMPROW *row_pointer=NULL;
DRCfbb67472010-11-24 04:02:37 +0000127 JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS];
128 JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
129 JSAMPROW *outbuf[MAX_COMPONENTS];
DRC2e7b76b2009-04-03 12:04:24 +0000130
131 checkhandle(h);
132
DRCfbb67472010-11-24 04:02:37 +0000133 for(i=0; i<MAX_COMPONENTS; i++)
134 {
135 tmpbuf[i]=NULL; _tmpbuf[i]=NULL;
136 tmpbuf2[i]=NULL; _tmpbuf2[i]=NULL; outbuf[i]=NULL;
137 }
138
DRC2e7b76b2009-04-03 12:04:24 +0000139 if(srcbuf==NULL || width<=0 || pitch<0 || height<=0
140 || dstbuf==NULL || size==NULL
141 || jpegsub<0 || jpegsub>=NUMSUBOPT || qual<0 || qual>100)
142 _throw("Invalid argument in tjCompress()");
DRC09854f52010-11-04 22:39:59 +0000143 if(ps!=3 && ps!=4 && ps!=1)
144 _throw("This compressor can only handle 24-bit and 32-bit RGB or 8-bit grayscale input");
DRC2e7b76b2009-04-03 12:04:24 +0000145 if(!j->initc) _throw("Instance has not been initialized for compression");
146
147 if(pitch==0) pitch=width*ps;
148
149 j->cinfo.image_width = width;
150 j->cinfo.image_height = height;
151 j->cinfo.input_components = ps;
152
DRC09854f52010-11-04 22:39:59 +0000153 if(ps==1) j->cinfo.in_color_space = JCS_GRAYSCALE;
DRC2e7b76b2009-04-03 12:04:24 +0000154 #if JCS_EXTENSIONS==1
DRC09854f52010-11-04 22:39:59 +0000155 else j->cinfo.in_color_space = JCS_EXT_RGB;
DRC2e7b76b2009-04-03 12:04:24 +0000156 if(ps==3 && (flags&TJ_BGR))
157 j->cinfo.in_color_space = JCS_EXT_BGR;
158 else if(ps==4 && !(flags&TJ_BGR) && !(flags&TJ_ALPHAFIRST))
159 j->cinfo.in_color_space = JCS_EXT_RGBX;
160 else if(ps==4 && (flags&TJ_BGR) && !(flags&TJ_ALPHAFIRST))
161 j->cinfo.in_color_space = JCS_EXT_BGRX;
162 else if(ps==4 && (flags&TJ_BGR) && (flags&TJ_ALPHAFIRST))
163 j->cinfo.in_color_space = JCS_EXT_XBGR;
164 else if(ps==4 && !(flags&TJ_BGR) && (flags&TJ_ALPHAFIRST))
165 j->cinfo.in_color_space = JCS_EXT_XRGB;
166 #else
167 #error "TurboJPEG requires JPEG colorspace extensions"
168 #endif
169
DRC0c6a2712010-02-22 08:34:44 +0000170 if(flags&TJ_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
171 else if(flags&TJ_FORCESSE) putenv("JSIMD_FORCESSE=1");
172 else if(flags&TJ_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
173
DRC2e7b76b2009-04-03 12:04:24 +0000174 if(setjmp(j->jerr.jb))
175 { // this will execute if LIBJPEG has an error
DRC91e86ba2011-02-15 05:24:08 +0000176 retval=-1;
177 goto bailout;
DRCefa4ddc2010-10-13 19:22:50 +0000178 }
DRC2e7b76b2009-04-03 12:04:24 +0000179
180 jpeg_set_defaults(&j->cinfo);
181
182 jpeg_set_quality(&j->cinfo, qual, TRUE);
183 if(jpegsub==TJ_GRAYSCALE)
184 jpeg_set_colorspace(&j->cinfo, JCS_GRAYSCALE);
185 else
186 jpeg_set_colorspace(&j->cinfo, JCS_YCbCr);
DRCe1716b82011-02-18 03:19:43 +0000187 if(qual>=96) j->cinfo.dct_method=JDCT_ISLOW;
188 else j->cinfo.dct_method=JDCT_FASTEST;
DRC2e7b76b2009-04-03 12:04:24 +0000189
190 j->cinfo.comp_info[0].h_samp_factor=hsampfactor[jpegsub];
191 j->cinfo.comp_info[1].h_samp_factor=1;
192 j->cinfo.comp_info[2].h_samp_factor=1;
193 j->cinfo.comp_info[0].v_samp_factor=vsampfactor[jpegsub];
194 j->cinfo.comp_info[1].v_samp_factor=1;
195 j->cinfo.comp_info[2].v_samp_factor=1;
196
197 j->jdms.next_output_byte = dstbuf;
198 j->jdms.free_in_buffer = TJBUFSIZE(j->cinfo.image_width, j->cinfo.image_height);
199
DRC2e7b76b2009-04-03 12:04:24 +0000200 jpeg_start_compress(&j->cinfo, TRUE);
DRCfbb67472010-11-24 04:02:37 +0000201 if(flags&TJ_YUV)
DRC2e7b76b2009-04-03 12:04:24 +0000202 {
DRCfbb67472010-11-24 04:02:37 +0000203 j_compress_ptr cinfo=&j->cinfo;
204 int row;
205 int pw=PAD(width, cinfo->max_h_samp_factor);
206 int ph=PAD(height, cinfo->max_v_samp_factor);
207 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS];
208 jpeg_component_info *compptr;
209 JSAMPLE *ptr=dstbuf; unsigned long yuvsize=0;
210
211 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph))==NULL)
212 _throw("Memory allocation failed in tjCompress()");
213 for(i=0; i<height; i++)
214 {
215 if(flags&TJ_BOTTOMUP) row_pointer[i]= &srcbuf[(height-i-1)*pitch];
216 else row_pointer[i]= &srcbuf[i*pitch];
217 }
218 if(height<ph)
219 for(i=height; i<ph; i++) row_pointer[i]=row_pointer[height-1];
220
221 for(i=0; i<cinfo->num_components; i++)
222 {
223 compptr=&cinfo->comp_info[i];
DRC57423072011-01-05 23:35:53 +0000224 _tmpbuf[i]=(JSAMPLE *)malloc(
DRCfbb67472010-11-24 04:02:37 +0000225 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
DRC57423072011-01-05 23:35:53 +0000226 /compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
DRCfbb67472010-11-24 04:02:37 +0000227 if(!_tmpbuf[i]) _throw("Memory allocation failure");
DRC2a2e4512011-01-05 22:33:24 +0000228 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
DRCfbb67472010-11-24 04:02:37 +0000229 if(!tmpbuf[i]) _throw("Memory allocation failure");
230 for(row=0; row<cinfo->max_v_samp_factor; row++)
DRC57423072011-01-05 23:35:53 +0000231 {
232 unsigned char *_tmpbuf_aligned=
233 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
234 tmpbuf[i][row]=&_tmpbuf_aligned[
DRCfbb67472010-11-24 04:02:37 +0000235 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
236 /compptr->h_samp_factor, 16) * row];
DRC57423072011-01-05 23:35:53 +0000237 }
238 _tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
239 * compptr->v_samp_factor + 16);
DRCfbb67472010-11-24 04:02:37 +0000240 if(!_tmpbuf2[i]) _throw("Memory allocation failure");
DRC2a2e4512011-01-05 22:33:24 +0000241 tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
DRCfbb67472010-11-24 04:02:37 +0000242 if(!tmpbuf2[i]) _throw("Memory allocation failure");
243 for(row=0; row<compptr->v_samp_factor; row++)
DRC57423072011-01-05 23:35:53 +0000244 {
245 unsigned char *_tmpbuf2_aligned=
246 (unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
247 tmpbuf2[i][row]=&_tmpbuf2_aligned[
DRCfbb67472010-11-24 04:02:37 +0000248 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
DRC57423072011-01-05 23:35:53 +0000249 }
DRCfbb67472010-11-24 04:02:37 +0000250 cw[i]=pw*compptr->h_samp_factor/cinfo->max_h_samp_factor;
251 ch[i]=ph*compptr->v_samp_factor/cinfo->max_v_samp_factor;
DRC2a2e4512011-01-05 22:33:24 +0000252 outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]);
DRCfbb67472010-11-24 04:02:37 +0000253 if(!outbuf[i]) _throw("Memory allocation failure");
254 for(row=0; row<ch[i]; row++)
255 {
256 outbuf[i][row]=ptr;
257 ptr+=PAD(cw[i], 4);
258 }
259 }
260 yuvsize=(unsigned long)(ptr-dstbuf);
261
262 for(row=0; row<ph; row+=cinfo->max_v_samp_factor)
263 {
264 (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf,
265 0, cinfo->max_v_samp_factor);
266 (cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
267 for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components;
268 i++, compptr++)
269 jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
270 row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
271 compptr->v_samp_factor, cw[i]);
272 }
273 *size=yuvsize;
274 cinfo->next_scanline+=height;
275 }
276 else
277 {
278 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
279 _throw("Memory allocation failed in tjCompress()");
280 for(i=0; i<height; i++)
281 {
282 if(flags&TJ_BOTTOMUP) row_pointer[i]= &srcbuf[(height-i-1)*pitch];
283 else row_pointer[i]= &srcbuf[i*pitch];
284 }
285 while(j->cinfo.next_scanline<j->cinfo.image_height)
286 {
287 jpeg_write_scanlines(&j->cinfo, &row_pointer[j->cinfo.next_scanline],
288 j->cinfo.image_height-j->cinfo.next_scanline);
289 }
DRC2e7b76b2009-04-03 12:04:24 +0000290 }
291 jpeg_finish_compress(&j->cinfo);
DRCfbb67472010-11-24 04:02:37 +0000292 if(!(flags&TJ_YUV))
293 *size=TJBUFSIZE(j->cinfo.image_width, j->cinfo.image_height)
294 -(unsigned long)(j->jdms.free_in_buffer);
DRC2e7b76b2009-04-03 12:04:24 +0000295
DRC91e86ba2011-02-15 05:24:08 +0000296 bailout:
DRC582a46a2011-02-24 21:16:10 +0000297 if(j->cinfo.global_state>CSTATE_START) jpeg_abort_compress(&j->cinfo);
DRC2e7b76b2009-04-03 12:04:24 +0000298 if(row_pointer) free(row_pointer);
DRCfbb67472010-11-24 04:02:37 +0000299 for(i=0; i<MAX_COMPONENTS; i++)
300 {
301 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
DRC57423072011-01-05 23:35:53 +0000302 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
DRCfbb67472010-11-24 04:02:37 +0000303 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
DRC57423072011-01-05 23:35:53 +0000304 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
DRCfbb67472010-11-24 04:02:37 +0000305 if(outbuf[i]!=NULL) free(outbuf[i]);
306 }
DRC91e86ba2011-02-15 05:24:08 +0000307 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000308}
309
310
311// DEC
312
313static boolean fill_input_buffer (struct jpeg_decompress_struct *dinfo)
314{
315 ERREXIT(dinfo, JERR_BUFFER_SIZE);
316 return TRUE;
317}
318
319static void skip_input_data (struct jpeg_decompress_struct *dinfo, long num_bytes)
320{
321 dinfo->src->next_input_byte += (size_t) num_bytes;
322 dinfo->src->bytes_in_buffer -= (size_t) num_bytes;
323}
324
325static void source_noop (struct jpeg_decompress_struct *dinfo)
326{
327}
328
329DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
330{
331 jpgstruct *j;
332 if((j=(jpgstruct *)malloc(sizeof(jpgstruct)))==NULL)
333 {sprintf(lasterror, "Memory allocation failure"); return NULL;}
334 memset(j, 0, sizeof(jpgstruct));
335 j->dinfo.err=jpeg_std_error(&j->jerr.pub);
336 j->jerr.pub.error_exit=my_error_exit;
337 j->jerr.pub.output_message=my_output_message;
338
339 if(setjmp(j->jerr.jb))
340 { // this will execute if LIBJPEG has an error
341 free(j); return NULL;
DRC9e17f7d2010-12-10 04:59:13 +0000342 }
DRC2e7b76b2009-04-03 12:04:24 +0000343
344 jpeg_create_decompress(&j->dinfo);
345 j->dinfo.src=&j->jsms;
346 j->jsms.init_source=source_noop;
347 j->jsms.fill_input_buffer = fill_input_buffer;
348 j->jsms.skip_input_data = skip_input_data;
349 j->jsms.resync_to_restart = jpeg_resync_to_restart;
350 j->jsms.term_source = source_noop;
351
352 j->initd=1;
353 return (tjhandle)j;
354}
355
356
DRC1fe80f82010-12-14 01:21:29 +0000357DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle h,
358 unsigned char *srcbuf, unsigned long size,
359 int *width, int *height, int *jpegsub)
360{
DRC91e86ba2011-02-15 05:24:08 +0000361 int i, k, retval=0;
DRC1fe80f82010-12-14 01:21:29 +0000362
363 checkhandle(h);
364
365 if(srcbuf==NULL || size<=0 || width==NULL || height==NULL || jpegsub==NULL)
DRC91e86ba2011-02-15 05:24:08 +0000366 _throw("Invalid argument in tjDecompressHeader2()");
DRC1fe80f82010-12-14 01:21:29 +0000367 if(!j->initd) _throw("Instance has not been initialized for decompression");
368
369 if(setjmp(j->jerr.jb))
370 { // this will execute if LIBJPEG has an error
371 return -1;
372 }
373
374 j->jsms.bytes_in_buffer = size;
375 j->jsms.next_input_byte = srcbuf;
376
377 jpeg_read_header(&j->dinfo, TRUE);
378
379 *width=j->dinfo.image_width; *height=j->dinfo.image_height;
380 *jpegsub=-1;
381 for(i=0; i<NUMSUBOPT; i++)
382 {
383 if(j->dinfo.num_components==pixelsize[i])
384 {
385 if(j->dinfo.comp_info[0].h_samp_factor==hsampfactor[i]
386 && j->dinfo.comp_info[0].v_samp_factor==vsampfactor[i])
387 {
388 int match=0;
389 for(k=1; k<j->dinfo.num_components; k++)
390 {
391 if(j->dinfo.comp_info[k].h_samp_factor==1
392 && j->dinfo.comp_info[k].v_samp_factor==1)
393 match++;
394 }
395 if(match==j->dinfo.num_components-1)
396 {
397 *jpegsub=i; break;
398 }
399 }
400 }
401 }
402
403 jpeg_abort_decompress(&j->dinfo);
404
405 if(*jpegsub<0) _throw("Could not determine subsampling type for JPEG image");
406 if(*width<1 || *height<1) _throw("Invalid data returned in header");
DRC91e86ba2011-02-15 05:24:08 +0000407
408 bailout:
409 return retval;
410}
411
412
413DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle h,
414 unsigned char *srcbuf, unsigned long size,
415 int *width, int *height)
416{
417 int jpegsub;
418 return tjDecompressHeader2(h, srcbuf, size, width, height, &jpegsub);
DRC1fe80f82010-12-14 01:21:29 +0000419}
420
421
DRC2e7b76b2009-04-03 12:04:24 +0000422DLLEXPORT int DLLCALL tjDecompress(tjhandle h,
423 unsigned char *srcbuf, unsigned long size,
424 unsigned char *dstbuf, int width, int pitch, int height, int ps,
425 int flags)
426{
DRC91e86ba2011-02-15 05:24:08 +0000427 int i, row, retval=0; JSAMPROW *row_pointer=NULL, *outbuf[MAX_COMPONENTS];
DRCf9cf5c72010-12-10 10:58:49 +0000428 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS],
429 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
430 JSAMPLE *_tmpbuf=NULL; JSAMPROW *tmpbuf[MAX_COMPONENTS];
DRC2e7b76b2009-04-03 12:04:24 +0000431
432 checkhandle(h);
433
DRCf9cf5c72010-12-10 10:58:49 +0000434 for(i=0; i<MAX_COMPONENTS; i++)
435 {
436 tmpbuf[i]=NULL; outbuf[i]=NULL;
437 }
DRC9e17f7d2010-12-10 04:59:13 +0000438
DRC2e7b76b2009-04-03 12:04:24 +0000439 if(srcbuf==NULL || size<=0
440 || dstbuf==NULL || width<=0 || pitch<0 || height<=0)
441 _throw("Invalid argument in tjDecompress()");
DRC09854f52010-11-04 22:39:59 +0000442 if(ps!=3 && ps!=4 && ps!=1)
443 _throw("This decompressor can only handle 24-bit and 32-bit RGB or 8-bit grayscale output");
DRC2e7b76b2009-04-03 12:04:24 +0000444 if(!j->initd) _throw("Instance has not been initialized for decompression");
445
446 if(pitch==0) pitch=width*ps;
447
DRC0c6a2712010-02-22 08:34:44 +0000448 if(flags&TJ_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
449 else if(flags&TJ_FORCESSE) putenv("JSIMD_FORCESSE=1");
450 else if(flags&TJ_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
451
DRC2e7b76b2009-04-03 12:04:24 +0000452 if(setjmp(j->jerr.jb))
453 { // this will execute if LIBJPEG has an error
DRC91e86ba2011-02-15 05:24:08 +0000454 retval=-1;
455 goto bailout;
DRC9e17f7d2010-12-10 04:59:13 +0000456 }
DRC2e7b76b2009-04-03 12:04:24 +0000457
458 j->jsms.bytes_in_buffer = size;
459 j->jsms.next_input_byte = srcbuf;
460
461 jpeg_read_header(&j->dinfo, TRUE);
462
DRC9e17f7d2010-12-10 04:59:13 +0000463 if(flags&TJ_YUV)
DRC2e7b76b2009-04-03 12:04:24 +0000464 {
DRC9e17f7d2010-12-10 04:59:13 +0000465 j_decompress_ptr dinfo=&j->dinfo;
466 JSAMPLE *ptr=dstbuf;
467
468 for(i=0; i<dinfo->num_components; i++)
469 {
470 jpeg_component_info *compptr=&dinfo->comp_info[i];
DRCf9cf5c72010-12-10 10:58:49 +0000471 int ih;
472 iw[i]=compptr->width_in_blocks*DCTSIZE;
473 ih=compptr->height_in_blocks*DCTSIZE;
474 cw[i]=PAD(width, dinfo->max_h_samp_factor)*compptr->h_samp_factor
475 /dinfo->max_h_samp_factor;
476 ch[i]=PAD(height, dinfo->max_v_samp_factor)*compptr->v_samp_factor
477 /dinfo->max_v_samp_factor;
DRCa6f4fca2010-12-11 06:01:11 +0000478 if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1;
479 th[i]=compptr->v_samp_factor*DCTSIZE;
480 tmpbufsize+=iw[i]*th[i];
DRC9e17f7d2010-12-10 04:59:13 +0000481 if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL)
482 _throw("Memory allocation failed in tjInitDecompress()");
483 for(row=0; row<ch[i]; row++)
484 {
485 outbuf[i][row]=ptr;
DRCf9cf5c72010-12-10 10:58:49 +0000486 ptr+=PAD(cw[i], 4);
487 }
488 }
489 if(usetmpbuf)
490 {
491 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
492 _throw("Memory allocation failed in tjInitDecompress()");
493 ptr=_tmpbuf;
494 for(i=0; i<dinfo->num_components; i++)
495 {
496 jpeg_component_info *compptr=&dinfo->comp_info[i];
497 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
498 _throw("Memory allocation failed in tjInitDecompress()");
499 for(row=0; row<th[i]; row++)
500 {
501 tmpbuf[i][row]=ptr;
502 ptr+=iw[i];
503 }
DRC9e17f7d2010-12-10 04:59:13 +0000504 }
505 }
506 }
507 else
508 {
509 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
510 _throw("Memory allocation failed in tjInitDecompress()");
511 for(i=0; i<height; i++)
512 {
513 if(flags&TJ_BOTTOMUP) row_pointer[i]= &dstbuf[(height-i-1)*pitch];
514 else row_pointer[i]= &dstbuf[i*pitch];
515 }
DRC2e7b76b2009-04-03 12:04:24 +0000516 }
517
DRC09854f52010-11-04 22:39:59 +0000518 if(ps==1) j->dinfo.out_color_space = JCS_GRAYSCALE;
DRC2e7b76b2009-04-03 12:04:24 +0000519 #if JCS_EXTENSIONS==1
DRC09854f52010-11-04 22:39:59 +0000520 else j->dinfo.out_color_space = JCS_EXT_RGB;
DRC2e7b76b2009-04-03 12:04:24 +0000521 if(ps==3 && (flags&TJ_BGR))
522 j->dinfo.out_color_space = JCS_EXT_BGR;
523 else if(ps==4 && !(flags&TJ_BGR) && !(flags&TJ_ALPHAFIRST))
524 j->dinfo.out_color_space = JCS_EXT_RGBX;
525 else if(ps==4 && (flags&TJ_BGR) && !(flags&TJ_ALPHAFIRST))
526 j->dinfo.out_color_space = JCS_EXT_BGRX;
527 else if(ps==4 && (flags&TJ_BGR) && (flags&TJ_ALPHAFIRST))
528 j->dinfo.out_color_space = JCS_EXT_XBGR;
529 else if(ps==4 && !(flags&TJ_BGR) && (flags&TJ_ALPHAFIRST))
530 j->dinfo.out_color_space = JCS_EXT_XRGB;
531 #else
532 #error "TurboJPEG requires JPEG colorspace extensions"
533 #endif
DRCfbb67472010-11-24 04:02:37 +0000534
DRC61e51f92009-04-05 21:53:20 +0000535 if(flags&TJ_FASTUPSAMPLE) j->dinfo.do_fancy_upsampling=FALSE;
DRC9e17f7d2010-12-10 04:59:13 +0000536 if(flags&TJ_YUV) j->dinfo.raw_data_out=TRUE;
DRC2e7b76b2009-04-03 12:04:24 +0000537
538 jpeg_start_decompress(&j->dinfo);
DRC9e17f7d2010-12-10 04:59:13 +0000539 if(flags&TJ_YUV)
DRC2e7b76b2009-04-03 12:04:24 +0000540 {
DRCf9cf5c72010-12-10 10:58:49 +0000541 j_decompress_ptr dinfo=&j->dinfo;
542 for(row=0; row<dinfo->output_height;
543 row+=dinfo->max_v_samp_factor*DCTSIZE)
DRC9e17f7d2010-12-10 04:59:13 +0000544 {
545 JSAMPARRAY yuvptr[MAX_COMPONENTS];
DRCa6f4fca2010-12-11 06:01:11 +0000546 int crow[MAX_COMPONENTS];
DRCf9cf5c72010-12-10 10:58:49 +0000547 for(i=0; i<dinfo->num_components; i++)
DRC9e17f7d2010-12-10 04:59:13 +0000548 {
DRCf9cf5c72010-12-10 10:58:49 +0000549 jpeg_component_info *compptr=&dinfo->comp_info[i];
DRCa6f4fca2010-12-11 06:01:11 +0000550 crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
DRCf9cf5c72010-12-10 10:58:49 +0000551 if(usetmpbuf) yuvptr[i]=tmpbuf[i];
DRCa6f4fca2010-12-11 06:01:11 +0000552 else yuvptr[i]=&outbuf[i][crow[i]];
DRC9e17f7d2010-12-10 04:59:13 +0000553 }
DRCf9cf5c72010-12-10 10:58:49 +0000554 jpeg_read_raw_data(dinfo, yuvptr, dinfo->max_v_samp_factor*DCTSIZE);
555 if(usetmpbuf)
556 {
557 int j;
558 for(i=0; i<dinfo->num_components; i++)
559 {
560 jpeg_component_info *compptr=&dinfo->comp_info[i];
DRCa6f4fca2010-12-11 06:01:11 +0000561 for(j=0; j<min(th[i], ch[i]-crow[i]); j++)
DRCf9cf5c72010-12-10 10:58:49 +0000562 {
DRCa6f4fca2010-12-11 06:01:11 +0000563 memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], cw[i]);
DRCf9cf5c72010-12-10 10:58:49 +0000564 }
565 }
566 }
DRC9e17f7d2010-12-10 04:59:13 +0000567 }
568 }
569 else
570 {
571 while(j->dinfo.output_scanline<j->dinfo.output_height)
572 {
573 jpeg_read_scanlines(&j->dinfo, &row_pointer[j->dinfo.output_scanline],
574 j->dinfo.output_height-j->dinfo.output_scanline);
575 }
DRC2e7b76b2009-04-03 12:04:24 +0000576 }
577 jpeg_finish_decompress(&j->dinfo);
578
DRC91e86ba2011-02-15 05:24:08 +0000579 bailout:
DRC582a46a2011-02-24 21:16:10 +0000580 if(j->dinfo.global_state>DSTATE_START) jpeg_abort_decompress(&j->dinfo);
DRC9e17f7d2010-12-10 04:59:13 +0000581 for(i=0; i<MAX_COMPONENTS; i++)
DRCf9cf5c72010-12-10 10:58:49 +0000582 {
583 if(tmpbuf[i]) free(tmpbuf[i]);
DRC9e17f7d2010-12-10 04:59:13 +0000584 if(outbuf[i]) free(outbuf[i]);
DRCf9cf5c72010-12-10 10:58:49 +0000585 }
586 if(_tmpbuf) free(_tmpbuf);
DRC2e7b76b2009-04-03 12:04:24 +0000587 if(row_pointer) free(row_pointer);
DRC91e86ba2011-02-15 05:24:08 +0000588 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000589}
590
591
592// General
593
594DLLEXPORT char* DLLCALL tjGetErrorStr(void)
595{
596 return lasterror;
597}
598
599DLLEXPORT int DLLCALL tjDestroy(tjhandle h)
600{
601 checkhandle(h);
602 if(setjmp(j->jerr.jb)) return -1;
603 if(j->initc) jpeg_destroy_compress(&j->cinfo);
604 if(j->initd) jpeg_destroy_decompress(&j->dinfo);
605 free(j);
606 return 0;
607}