blob: 9dd6eb66a06a0122a3fece080c28ee55552aeadb [file] [log] [blame]
DRC2e7b76b2009-04-03 12:04:24 +00001/* Copyright (C)2004 Landmark Graphics Corporation
2 * Copyright (C)2005 Sun Microsystems, Inc.
DRC09854f52010-11-04 22:39:59 +00003 * Copyright (C)2009-2010 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
73#define _throw(c) {sprintf(lasterror, "%s", c); return -1;}
74#define _catch(f) {if((f)==-1) return -1;}
75#define checkhandle(h) jpgstruct *j=(jpgstruct *)h; \
76 if(!j) _throw("Invalid handle");
77
78
79// CO
80
81static boolean empty_output_buffer(struct jpeg_compress_struct *cinfo)
82{
83 ERREXIT(cinfo, JERR_BUFFER_SIZE);
84 return TRUE;
85}
86
87static void destination_noop(struct jpeg_compress_struct *cinfo)
88{
89}
90
91DLLEXPORT tjhandle DLLCALL tjInitCompress(void)
92{
93 jpgstruct *j=NULL;
94 if((j=(jpgstruct *)malloc(sizeof(jpgstruct)))==NULL)
95 {sprintf(lasterror, "Memory allocation failure"); return NULL;}
96 memset(j, 0, sizeof(jpgstruct));
97 j->cinfo.err=jpeg_std_error(&j->jerr.pub);
98 j->jerr.pub.error_exit=my_error_exit;
99 j->jerr.pub.output_message=my_output_message;
100
101 if(setjmp(j->jerr.jb))
102 { // this will execute if LIBJPEG has an error
103 if(j) free(j); return NULL;
DRCefa4ddc2010-10-13 19:22:50 +0000104 }
DRC2e7b76b2009-04-03 12:04:24 +0000105
106 jpeg_create_compress(&j->cinfo);
107 j->cinfo.dest=&j->jdms;
108 j->jdms.init_destination=destination_noop;
109 j->jdms.empty_output_buffer=empty_output_buffer;
110 j->jdms.term_destination=destination_noop;
111
112 j->initc=1;
113 return (tjhandle)j;
114}
115
116DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
117{
118 // This allows enough room in case the image doesn't compress
119 return ((width+15)&(~15)) * ((height+15)&(~15)) * 6 + 2048;
120}
121
122DLLEXPORT int DLLCALL tjCompress(tjhandle h,
123 unsigned char *srcbuf, int width, int pitch, int height, int ps,
124 unsigned char *dstbuf, unsigned long *size,
125 int jpegsub, int qual, int flags)
126{
127 int i; JSAMPROW *row_pointer=NULL;
DRCfbb67472010-11-24 04:02:37 +0000128 JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS];
129 JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
130 JSAMPROW *outbuf[MAX_COMPONENTS];
DRC2e7b76b2009-04-03 12:04:24 +0000131
132 checkhandle(h);
133
DRCfbb67472010-11-24 04:02:37 +0000134 for(i=0; i<MAX_COMPONENTS; i++)
135 {
136 tmpbuf[i]=NULL; _tmpbuf[i]=NULL;
137 tmpbuf2[i]=NULL; _tmpbuf2[i]=NULL; outbuf[i]=NULL;
138 }
139
DRC2e7b76b2009-04-03 12:04:24 +0000140 if(srcbuf==NULL || width<=0 || pitch<0 || height<=0
141 || dstbuf==NULL || size==NULL
142 || jpegsub<0 || jpegsub>=NUMSUBOPT || qual<0 || qual>100)
143 _throw("Invalid argument in tjCompress()");
DRC09854f52010-11-04 22:39:59 +0000144 if(ps!=3 && ps!=4 && ps!=1)
145 _throw("This compressor can only handle 24-bit and 32-bit RGB or 8-bit grayscale input");
DRC2e7b76b2009-04-03 12:04:24 +0000146 if(!j->initc) _throw("Instance has not been initialized for compression");
147
148 if(pitch==0) pitch=width*ps;
149
150 j->cinfo.image_width = width;
151 j->cinfo.image_height = height;
152 j->cinfo.input_components = ps;
153
DRC09854f52010-11-04 22:39:59 +0000154 if(ps==1) j->cinfo.in_color_space = JCS_GRAYSCALE;
DRC2e7b76b2009-04-03 12:04:24 +0000155 #if JCS_EXTENSIONS==1
DRC09854f52010-11-04 22:39:59 +0000156 else j->cinfo.in_color_space = JCS_EXT_RGB;
DRC2e7b76b2009-04-03 12:04:24 +0000157 if(ps==3 && (flags&TJ_BGR))
158 j->cinfo.in_color_space = JCS_EXT_BGR;
159 else if(ps==4 && !(flags&TJ_BGR) && !(flags&TJ_ALPHAFIRST))
160 j->cinfo.in_color_space = JCS_EXT_RGBX;
161 else if(ps==4 && (flags&TJ_BGR) && !(flags&TJ_ALPHAFIRST))
162 j->cinfo.in_color_space = JCS_EXT_BGRX;
163 else if(ps==4 && (flags&TJ_BGR) && (flags&TJ_ALPHAFIRST))
164 j->cinfo.in_color_space = JCS_EXT_XBGR;
165 else if(ps==4 && !(flags&TJ_BGR) && (flags&TJ_ALPHAFIRST))
166 j->cinfo.in_color_space = JCS_EXT_XRGB;
167 #else
168 #error "TurboJPEG requires JPEG colorspace extensions"
169 #endif
170
DRC0c6a2712010-02-22 08:34:44 +0000171 if(flags&TJ_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
172 else if(flags&TJ_FORCESSE) putenv("JSIMD_FORCESSE=1");
173 else if(flags&TJ_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
174
DRC2e7b76b2009-04-03 12:04:24 +0000175 if(setjmp(j->jerr.jb))
176 { // this will execute if LIBJPEG has an error
177 if(row_pointer) free(row_pointer);
DRCfbb67472010-11-24 04:02:37 +0000178 for(i=0; i<MAX_COMPONENTS; i++)
179 {
180 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
DRC57423072011-01-05 23:35:53 +0000181 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
DRCfbb67472010-11-24 04:02:37 +0000182 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
DRC57423072011-01-05 23:35:53 +0000183 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
DRCfbb67472010-11-24 04:02:37 +0000184 if(outbuf[i]!=NULL) free(outbuf[i]);
185 }
DRC2e7b76b2009-04-03 12:04:24 +0000186 return -1;
DRCefa4ddc2010-10-13 19:22:50 +0000187 }
DRC2e7b76b2009-04-03 12:04:24 +0000188
189 jpeg_set_defaults(&j->cinfo);
190
191 jpeg_set_quality(&j->cinfo, qual, TRUE);
192 if(jpegsub==TJ_GRAYSCALE)
193 jpeg_set_colorspace(&j->cinfo, JCS_GRAYSCALE);
194 else
195 jpeg_set_colorspace(&j->cinfo, JCS_YCbCr);
196 j->cinfo.dct_method = JDCT_FASTEST;
197
198 j->cinfo.comp_info[0].h_samp_factor=hsampfactor[jpegsub];
199 j->cinfo.comp_info[1].h_samp_factor=1;
200 j->cinfo.comp_info[2].h_samp_factor=1;
201 j->cinfo.comp_info[0].v_samp_factor=vsampfactor[jpegsub];
202 j->cinfo.comp_info[1].v_samp_factor=1;
203 j->cinfo.comp_info[2].v_samp_factor=1;
204
205 j->jdms.next_output_byte = dstbuf;
206 j->jdms.free_in_buffer = TJBUFSIZE(j->cinfo.image_width, j->cinfo.image_height);
207
DRC2e7b76b2009-04-03 12:04:24 +0000208 jpeg_start_compress(&j->cinfo, TRUE);
DRCfbb67472010-11-24 04:02:37 +0000209 if(flags&TJ_YUV)
DRC2e7b76b2009-04-03 12:04:24 +0000210 {
DRCfbb67472010-11-24 04:02:37 +0000211 j_compress_ptr cinfo=&j->cinfo;
212 int row;
213 int pw=PAD(width, cinfo->max_h_samp_factor);
214 int ph=PAD(height, cinfo->max_v_samp_factor);
215 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS];
216 jpeg_component_info *compptr;
217 JSAMPLE *ptr=dstbuf; unsigned long yuvsize=0;
218
219 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph))==NULL)
220 _throw("Memory allocation failed in tjCompress()");
221 for(i=0; i<height; i++)
222 {
223 if(flags&TJ_BOTTOMUP) row_pointer[i]= &srcbuf[(height-i-1)*pitch];
224 else row_pointer[i]= &srcbuf[i*pitch];
225 }
226 if(height<ph)
227 for(i=height; i<ph; i++) row_pointer[i]=row_pointer[height-1];
228
229 for(i=0; i<cinfo->num_components; i++)
230 {
231 compptr=&cinfo->comp_info[i];
DRC57423072011-01-05 23:35:53 +0000232 _tmpbuf[i]=(JSAMPLE *)malloc(
DRCfbb67472010-11-24 04:02:37 +0000233 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
DRC57423072011-01-05 23:35:53 +0000234 /compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
DRCfbb67472010-11-24 04:02:37 +0000235 if(!_tmpbuf[i]) _throw("Memory allocation failure");
DRC2a2e4512011-01-05 22:33:24 +0000236 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
DRCfbb67472010-11-24 04:02:37 +0000237 if(!tmpbuf[i]) _throw("Memory allocation failure");
238 for(row=0; row<cinfo->max_v_samp_factor; row++)
DRC57423072011-01-05 23:35:53 +0000239 {
240 unsigned char *_tmpbuf_aligned=
241 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
242 tmpbuf[i][row]=&_tmpbuf_aligned[
DRCfbb67472010-11-24 04:02:37 +0000243 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
244 /compptr->h_samp_factor, 16) * row];
DRC57423072011-01-05 23:35:53 +0000245 }
246 _tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
247 * compptr->v_samp_factor + 16);
DRCfbb67472010-11-24 04:02:37 +0000248 if(!_tmpbuf2[i]) _throw("Memory allocation failure");
DRC2a2e4512011-01-05 22:33:24 +0000249 tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
DRCfbb67472010-11-24 04:02:37 +0000250 if(!tmpbuf2[i]) _throw("Memory allocation failure");
251 for(row=0; row<compptr->v_samp_factor; row++)
DRC57423072011-01-05 23:35:53 +0000252 {
253 unsigned char *_tmpbuf2_aligned=
254 (unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
255 tmpbuf2[i][row]=&_tmpbuf2_aligned[
DRCfbb67472010-11-24 04:02:37 +0000256 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
DRC57423072011-01-05 23:35:53 +0000257 }
DRCfbb67472010-11-24 04:02:37 +0000258 cw[i]=pw*compptr->h_samp_factor/cinfo->max_h_samp_factor;
259 ch[i]=ph*compptr->v_samp_factor/cinfo->max_v_samp_factor;
DRC2a2e4512011-01-05 22:33:24 +0000260 outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]);
DRCfbb67472010-11-24 04:02:37 +0000261 if(!outbuf[i]) _throw("Memory allocation failure");
262 for(row=0; row<ch[i]; row++)
263 {
264 outbuf[i][row]=ptr;
265 ptr+=PAD(cw[i], 4);
266 }
267 }
268 yuvsize=(unsigned long)(ptr-dstbuf);
269
270 for(row=0; row<ph; row+=cinfo->max_v_samp_factor)
271 {
272 (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf,
273 0, cinfo->max_v_samp_factor);
274 (cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
275 for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components;
276 i++, compptr++)
277 jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
278 row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
279 compptr->v_samp_factor, cw[i]);
280 }
281 *size=yuvsize;
282 cinfo->next_scanline+=height;
283 }
284 else
285 {
286 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
287 _throw("Memory allocation failed in tjCompress()");
288 for(i=0; i<height; i++)
289 {
290 if(flags&TJ_BOTTOMUP) row_pointer[i]= &srcbuf[(height-i-1)*pitch];
291 else row_pointer[i]= &srcbuf[i*pitch];
292 }
293 while(j->cinfo.next_scanline<j->cinfo.image_height)
294 {
295 jpeg_write_scanlines(&j->cinfo, &row_pointer[j->cinfo.next_scanline],
296 j->cinfo.image_height-j->cinfo.next_scanline);
297 }
DRC2e7b76b2009-04-03 12:04:24 +0000298 }
299 jpeg_finish_compress(&j->cinfo);
DRCfbb67472010-11-24 04:02:37 +0000300 if(!(flags&TJ_YUV))
301 *size=TJBUFSIZE(j->cinfo.image_width, j->cinfo.image_height)
302 -(unsigned long)(j->jdms.free_in_buffer);
DRC2e7b76b2009-04-03 12:04:24 +0000303
304 if(row_pointer) free(row_pointer);
DRCfbb67472010-11-24 04:02:37 +0000305 for(i=0; i<MAX_COMPONENTS; i++)
306 {
307 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
DRC57423072011-01-05 23:35:53 +0000308 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
DRCfbb67472010-11-24 04:02:37 +0000309 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
DRC57423072011-01-05 23:35:53 +0000310 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
DRCfbb67472010-11-24 04:02:37 +0000311 if(outbuf[i]!=NULL) free(outbuf[i]);
312 }
DRC2e7b76b2009-04-03 12:04:24 +0000313 return 0;
314}
315
316
317// DEC
318
319static boolean fill_input_buffer (struct jpeg_decompress_struct *dinfo)
320{
321 ERREXIT(dinfo, JERR_BUFFER_SIZE);
322 return TRUE;
323}
324
325static void skip_input_data (struct jpeg_decompress_struct *dinfo, long num_bytes)
326{
327 dinfo->src->next_input_byte += (size_t) num_bytes;
328 dinfo->src->bytes_in_buffer -= (size_t) num_bytes;
329}
330
331static void source_noop (struct jpeg_decompress_struct *dinfo)
332{
333}
334
335DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
336{
337 jpgstruct *j;
338 if((j=(jpgstruct *)malloc(sizeof(jpgstruct)))==NULL)
339 {sprintf(lasterror, "Memory allocation failure"); return NULL;}
340 memset(j, 0, sizeof(jpgstruct));
341 j->dinfo.err=jpeg_std_error(&j->jerr.pub);
342 j->jerr.pub.error_exit=my_error_exit;
343 j->jerr.pub.output_message=my_output_message;
344
345 if(setjmp(j->jerr.jb))
346 { // this will execute if LIBJPEG has an error
347 free(j); return NULL;
DRC9e17f7d2010-12-10 04:59:13 +0000348 }
DRC2e7b76b2009-04-03 12:04:24 +0000349
350 jpeg_create_decompress(&j->dinfo);
351 j->dinfo.src=&j->jsms;
352 j->jsms.init_source=source_noop;
353 j->jsms.fill_input_buffer = fill_input_buffer;
354 j->jsms.skip_input_data = skip_input_data;
355 j->jsms.resync_to_restart = jpeg_resync_to_restart;
356 j->jsms.term_source = source_noop;
357
358 j->initd=1;
359 return (tjhandle)j;
360}
361
362
363DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle h,
364 unsigned char *srcbuf, unsigned long size,
365 int *width, int *height)
366{
367 checkhandle(h);
368
369 if(srcbuf==NULL || size<=0 || width==NULL || height==NULL)
370 _throw("Invalid argument in tjDecompressHeader()");
371 if(!j->initd) _throw("Instance has not been initialized for decompression");
372
373 if(setjmp(j->jerr.jb))
374 { // this will execute if LIBJPEG has an error
375 return -1;
376 }
377
378 j->jsms.bytes_in_buffer = size;
379 j->jsms.next_input_byte = srcbuf;
380
381 jpeg_read_header(&j->dinfo, TRUE);
382
383 *width=j->dinfo.image_width; *height=j->dinfo.image_height;
384
385 jpeg_abort_decompress(&j->dinfo);
386
387 if(*width<1 || *height<1) _throw("Invalid data returned in header");
388 return 0;
389}
390
391
DRC1fe80f82010-12-14 01:21:29 +0000392DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle h,
393 unsigned char *srcbuf, unsigned long size,
394 int *width, int *height, int *jpegsub)
395{
396 int i, k;
397
398 checkhandle(h);
399
400 if(srcbuf==NULL || size<=0 || width==NULL || height==NULL || jpegsub==NULL)
401 _throw("Invalid argument in tjDecompressHeader()");
402 if(!j->initd) _throw("Instance has not been initialized for decompression");
403
404 if(setjmp(j->jerr.jb))
405 { // this will execute if LIBJPEG has an error
406 return -1;
407 }
408
409 j->jsms.bytes_in_buffer = size;
410 j->jsms.next_input_byte = srcbuf;
411
412 jpeg_read_header(&j->dinfo, TRUE);
413
414 *width=j->dinfo.image_width; *height=j->dinfo.image_height;
415 *jpegsub=-1;
416 for(i=0; i<NUMSUBOPT; i++)
417 {
418 if(j->dinfo.num_components==pixelsize[i])
419 {
420 if(j->dinfo.comp_info[0].h_samp_factor==hsampfactor[i]
421 && j->dinfo.comp_info[0].v_samp_factor==vsampfactor[i])
422 {
423 int match=0;
424 for(k=1; k<j->dinfo.num_components; k++)
425 {
426 if(j->dinfo.comp_info[k].h_samp_factor==1
427 && j->dinfo.comp_info[k].v_samp_factor==1)
428 match++;
429 }
430 if(match==j->dinfo.num_components-1)
431 {
432 *jpegsub=i; break;
433 }
434 }
435 }
436 }
437
438 jpeg_abort_decompress(&j->dinfo);
439
440 if(*jpegsub<0) _throw("Could not determine subsampling type for JPEG image");
441 if(*width<1 || *height<1) _throw("Invalid data returned in header");
442 return 0;
443}
444
445
DRC2e7b76b2009-04-03 12:04:24 +0000446DLLEXPORT int DLLCALL tjDecompress(tjhandle h,
447 unsigned char *srcbuf, unsigned long size,
448 unsigned char *dstbuf, int width, int pitch, int height, int ps,
449 int flags)
450{
DRC9e17f7d2010-12-10 04:59:13 +0000451 int i, row; JSAMPROW *row_pointer=NULL, *outbuf[MAX_COMPONENTS];
DRCf9cf5c72010-12-10 10:58:49 +0000452 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS],
453 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
454 JSAMPLE *_tmpbuf=NULL; JSAMPROW *tmpbuf[MAX_COMPONENTS];
DRC2e7b76b2009-04-03 12:04:24 +0000455
456 checkhandle(h);
457
DRCf9cf5c72010-12-10 10:58:49 +0000458 for(i=0; i<MAX_COMPONENTS; i++)
459 {
460 tmpbuf[i]=NULL; outbuf[i]=NULL;
461 }
DRC9e17f7d2010-12-10 04:59:13 +0000462
DRC2e7b76b2009-04-03 12:04:24 +0000463 if(srcbuf==NULL || size<=0
464 || dstbuf==NULL || width<=0 || pitch<0 || height<=0)
465 _throw("Invalid argument in tjDecompress()");
DRC09854f52010-11-04 22:39:59 +0000466 if(ps!=3 && ps!=4 && ps!=1)
467 _throw("This decompressor can only handle 24-bit and 32-bit RGB or 8-bit grayscale output");
DRC2e7b76b2009-04-03 12:04:24 +0000468 if(!j->initd) _throw("Instance has not been initialized for decompression");
469
470 if(pitch==0) pitch=width*ps;
471
DRC0c6a2712010-02-22 08:34:44 +0000472 if(flags&TJ_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
473 else if(flags&TJ_FORCESSE) putenv("JSIMD_FORCESSE=1");
474 else if(flags&TJ_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
475
DRC2e7b76b2009-04-03 12:04:24 +0000476 if(setjmp(j->jerr.jb))
477 { // this will execute if LIBJPEG has an error
DRC9e17f7d2010-12-10 04:59:13 +0000478 for(i=0; i<MAX_COMPONENTS; i++)
DRCf9cf5c72010-12-10 10:58:49 +0000479 {
480 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
DRC9e17f7d2010-12-10 04:59:13 +0000481 if(outbuf[i]!=NULL) free(outbuf[i]);
DRCf9cf5c72010-12-10 10:58:49 +0000482 }
483 if(_tmpbuf) free(_tmpbuf);
DRC2e7b76b2009-04-03 12:04:24 +0000484 if(row_pointer) free(row_pointer);
485 return -1;
DRC9e17f7d2010-12-10 04:59:13 +0000486 }
DRC2e7b76b2009-04-03 12:04:24 +0000487
488 j->jsms.bytes_in_buffer = size;
489 j->jsms.next_input_byte = srcbuf;
490
491 jpeg_read_header(&j->dinfo, TRUE);
492
DRC9e17f7d2010-12-10 04:59:13 +0000493 if(flags&TJ_YUV)
DRC2e7b76b2009-04-03 12:04:24 +0000494 {
DRC9e17f7d2010-12-10 04:59:13 +0000495 j_decompress_ptr dinfo=&j->dinfo;
496 JSAMPLE *ptr=dstbuf;
497
498 for(i=0; i<dinfo->num_components; i++)
499 {
500 jpeg_component_info *compptr=&dinfo->comp_info[i];
DRCf9cf5c72010-12-10 10:58:49 +0000501 int ih;
502 iw[i]=compptr->width_in_blocks*DCTSIZE;
503 ih=compptr->height_in_blocks*DCTSIZE;
504 cw[i]=PAD(width, dinfo->max_h_samp_factor)*compptr->h_samp_factor
505 /dinfo->max_h_samp_factor;
506 ch[i]=PAD(height, dinfo->max_v_samp_factor)*compptr->v_samp_factor
507 /dinfo->max_v_samp_factor;
DRCa6f4fca2010-12-11 06:01:11 +0000508 if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1;
509 th[i]=compptr->v_samp_factor*DCTSIZE;
510 tmpbufsize+=iw[i]*th[i];
DRC9e17f7d2010-12-10 04:59:13 +0000511 if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL)
512 _throw("Memory allocation failed in tjInitDecompress()");
513 for(row=0; row<ch[i]; row++)
514 {
515 outbuf[i][row]=ptr;
DRCf9cf5c72010-12-10 10:58:49 +0000516 ptr+=PAD(cw[i], 4);
517 }
518 }
519 if(usetmpbuf)
520 {
521 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
522 _throw("Memory allocation failed in tjInitDecompress()");
523 ptr=_tmpbuf;
524 for(i=0; i<dinfo->num_components; i++)
525 {
526 jpeg_component_info *compptr=&dinfo->comp_info[i];
527 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
528 _throw("Memory allocation failed in tjInitDecompress()");
529 for(row=0; row<th[i]; row++)
530 {
531 tmpbuf[i][row]=ptr;
532 ptr+=iw[i];
533 }
DRC9e17f7d2010-12-10 04:59:13 +0000534 }
535 }
536 }
537 else
538 {
539 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
540 _throw("Memory allocation failed in tjInitDecompress()");
541 for(i=0; i<height; i++)
542 {
543 if(flags&TJ_BOTTOMUP) row_pointer[i]= &dstbuf[(height-i-1)*pitch];
544 else row_pointer[i]= &dstbuf[i*pitch];
545 }
DRC2e7b76b2009-04-03 12:04:24 +0000546 }
547
DRC09854f52010-11-04 22:39:59 +0000548 if(ps==1) j->dinfo.out_color_space = JCS_GRAYSCALE;
DRC2e7b76b2009-04-03 12:04:24 +0000549 #if JCS_EXTENSIONS==1
DRC09854f52010-11-04 22:39:59 +0000550 else j->dinfo.out_color_space = JCS_EXT_RGB;
DRC2e7b76b2009-04-03 12:04:24 +0000551 if(ps==3 && (flags&TJ_BGR))
552 j->dinfo.out_color_space = JCS_EXT_BGR;
553 else if(ps==4 && !(flags&TJ_BGR) && !(flags&TJ_ALPHAFIRST))
554 j->dinfo.out_color_space = JCS_EXT_RGBX;
555 else if(ps==4 && (flags&TJ_BGR) && !(flags&TJ_ALPHAFIRST))
556 j->dinfo.out_color_space = JCS_EXT_BGRX;
557 else if(ps==4 && (flags&TJ_BGR) && (flags&TJ_ALPHAFIRST))
558 j->dinfo.out_color_space = JCS_EXT_XBGR;
559 else if(ps==4 && !(flags&TJ_BGR) && (flags&TJ_ALPHAFIRST))
560 j->dinfo.out_color_space = JCS_EXT_XRGB;
561 #else
562 #error "TurboJPEG requires JPEG colorspace extensions"
563 #endif
DRCfbb67472010-11-24 04:02:37 +0000564
DRC61e51f92009-04-05 21:53:20 +0000565 if(flags&TJ_FASTUPSAMPLE) j->dinfo.do_fancy_upsampling=FALSE;
DRC9e17f7d2010-12-10 04:59:13 +0000566 if(flags&TJ_YUV) j->dinfo.raw_data_out=TRUE;
DRC2e7b76b2009-04-03 12:04:24 +0000567
568 jpeg_start_decompress(&j->dinfo);
DRC9e17f7d2010-12-10 04:59:13 +0000569 if(flags&TJ_YUV)
DRC2e7b76b2009-04-03 12:04:24 +0000570 {
DRCf9cf5c72010-12-10 10:58:49 +0000571 j_decompress_ptr dinfo=&j->dinfo;
572 for(row=0; row<dinfo->output_height;
573 row+=dinfo->max_v_samp_factor*DCTSIZE)
DRC9e17f7d2010-12-10 04:59:13 +0000574 {
575 JSAMPARRAY yuvptr[MAX_COMPONENTS];
DRCa6f4fca2010-12-11 06:01:11 +0000576 int crow[MAX_COMPONENTS];
DRCf9cf5c72010-12-10 10:58:49 +0000577 for(i=0; i<dinfo->num_components; i++)
DRC9e17f7d2010-12-10 04:59:13 +0000578 {
DRCf9cf5c72010-12-10 10:58:49 +0000579 jpeg_component_info *compptr=&dinfo->comp_info[i];
DRCa6f4fca2010-12-11 06:01:11 +0000580 crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
DRCf9cf5c72010-12-10 10:58:49 +0000581 if(usetmpbuf) yuvptr[i]=tmpbuf[i];
DRCa6f4fca2010-12-11 06:01:11 +0000582 else yuvptr[i]=&outbuf[i][crow[i]];
DRC9e17f7d2010-12-10 04:59:13 +0000583 }
DRCf9cf5c72010-12-10 10:58:49 +0000584 jpeg_read_raw_data(dinfo, yuvptr, dinfo->max_v_samp_factor*DCTSIZE);
585 if(usetmpbuf)
586 {
587 int j;
588 for(i=0; i<dinfo->num_components; i++)
589 {
590 jpeg_component_info *compptr=&dinfo->comp_info[i];
DRCa6f4fca2010-12-11 06:01:11 +0000591 for(j=0; j<min(th[i], ch[i]-crow[i]); j++)
DRCf9cf5c72010-12-10 10:58:49 +0000592 {
DRCa6f4fca2010-12-11 06:01:11 +0000593 memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], cw[i]);
DRCf9cf5c72010-12-10 10:58:49 +0000594 }
595 }
596 }
DRC9e17f7d2010-12-10 04:59:13 +0000597 }
598 }
599 else
600 {
601 while(j->dinfo.output_scanline<j->dinfo.output_height)
602 {
603 jpeg_read_scanlines(&j->dinfo, &row_pointer[j->dinfo.output_scanline],
604 j->dinfo.output_height-j->dinfo.output_scanline);
605 }
DRC2e7b76b2009-04-03 12:04:24 +0000606 }
607 jpeg_finish_decompress(&j->dinfo);
608
DRC9e17f7d2010-12-10 04:59:13 +0000609 for(i=0; i<MAX_COMPONENTS; i++)
DRCf9cf5c72010-12-10 10:58:49 +0000610 {
611 if(tmpbuf[i]) free(tmpbuf[i]);
DRC9e17f7d2010-12-10 04:59:13 +0000612 if(outbuf[i]) free(outbuf[i]);
DRCf9cf5c72010-12-10 10:58:49 +0000613 }
614 if(_tmpbuf) free(_tmpbuf);
DRC2e7b76b2009-04-03 12:04:24 +0000615 if(row_pointer) free(row_pointer);
616 return 0;
617}
618
619
620// General
621
622DLLEXPORT char* DLLCALL tjGetErrorStr(void)
623{
624 return lasterror;
625}
626
627DLLEXPORT int DLLCALL tjDestroy(tjhandle h)
628{
629 checkhandle(h);
630 if(setjmp(j->jerr.jb)) return -1;
631 if(j->initc) jpeg_destroy_compress(&j->cinfo);
632 if(j->initd) jpeg_destroy_decompress(&j->dinfo);
633 free(j);
634 return 0;
635}