blob: 1e48234fdc97ced999ccc0e752a30d46bce8989e [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:
DRC2e7b76b2009-04-03 12:04:24 +0000297 if(row_pointer) free(row_pointer);
DRCfbb67472010-11-24 04:02:37 +0000298 for(i=0; i<MAX_COMPONENTS; i++)
299 {
300 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
DRC57423072011-01-05 23:35:53 +0000301 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
DRCfbb67472010-11-24 04:02:37 +0000302 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
DRC57423072011-01-05 23:35:53 +0000303 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
DRCfbb67472010-11-24 04:02:37 +0000304 if(outbuf[i]!=NULL) free(outbuf[i]);
305 }
DRC91e86ba2011-02-15 05:24:08 +0000306 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000307}
308
309
310// DEC
311
312static boolean fill_input_buffer (struct jpeg_decompress_struct *dinfo)
313{
314 ERREXIT(dinfo, JERR_BUFFER_SIZE);
315 return TRUE;
316}
317
318static void skip_input_data (struct jpeg_decompress_struct *dinfo, long num_bytes)
319{
320 dinfo->src->next_input_byte += (size_t) num_bytes;
321 dinfo->src->bytes_in_buffer -= (size_t) num_bytes;
322}
323
324static void source_noop (struct jpeg_decompress_struct *dinfo)
325{
326}
327
328DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
329{
330 jpgstruct *j;
331 if((j=(jpgstruct *)malloc(sizeof(jpgstruct)))==NULL)
332 {sprintf(lasterror, "Memory allocation failure"); return NULL;}
333 memset(j, 0, sizeof(jpgstruct));
334 j->dinfo.err=jpeg_std_error(&j->jerr.pub);
335 j->jerr.pub.error_exit=my_error_exit;
336 j->jerr.pub.output_message=my_output_message;
337
338 if(setjmp(j->jerr.jb))
339 { // this will execute if LIBJPEG has an error
340 free(j); return NULL;
DRC9e17f7d2010-12-10 04:59:13 +0000341 }
DRC2e7b76b2009-04-03 12:04:24 +0000342
343 jpeg_create_decompress(&j->dinfo);
344 j->dinfo.src=&j->jsms;
345 j->jsms.init_source=source_noop;
346 j->jsms.fill_input_buffer = fill_input_buffer;
347 j->jsms.skip_input_data = skip_input_data;
348 j->jsms.resync_to_restart = jpeg_resync_to_restart;
349 j->jsms.term_source = source_noop;
350
351 j->initd=1;
352 return (tjhandle)j;
353}
354
355
DRC1fe80f82010-12-14 01:21:29 +0000356DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle h,
357 unsigned char *srcbuf, unsigned long size,
358 int *width, int *height, int *jpegsub)
359{
DRC91e86ba2011-02-15 05:24:08 +0000360 int i, k, retval=0;
DRC1fe80f82010-12-14 01:21:29 +0000361
362 checkhandle(h);
363
364 if(srcbuf==NULL || size<=0 || width==NULL || height==NULL || jpegsub==NULL)
DRC91e86ba2011-02-15 05:24:08 +0000365 _throw("Invalid argument in tjDecompressHeader2()");
DRC1fe80f82010-12-14 01:21:29 +0000366 if(!j->initd) _throw("Instance has not been initialized for decompression");
367
368 if(setjmp(j->jerr.jb))
369 { // this will execute if LIBJPEG has an error
370 return -1;
371 }
372
373 j->jsms.bytes_in_buffer = size;
374 j->jsms.next_input_byte = srcbuf;
375
376 jpeg_read_header(&j->dinfo, TRUE);
377
378 *width=j->dinfo.image_width; *height=j->dinfo.image_height;
379 *jpegsub=-1;
380 for(i=0; i<NUMSUBOPT; i++)
381 {
382 if(j->dinfo.num_components==pixelsize[i])
383 {
384 if(j->dinfo.comp_info[0].h_samp_factor==hsampfactor[i]
385 && j->dinfo.comp_info[0].v_samp_factor==vsampfactor[i])
386 {
387 int match=0;
388 for(k=1; k<j->dinfo.num_components; k++)
389 {
390 if(j->dinfo.comp_info[k].h_samp_factor==1
391 && j->dinfo.comp_info[k].v_samp_factor==1)
392 match++;
393 }
394 if(match==j->dinfo.num_components-1)
395 {
396 *jpegsub=i; break;
397 }
398 }
399 }
400 }
401
402 jpeg_abort_decompress(&j->dinfo);
403
404 if(*jpegsub<0) _throw("Could not determine subsampling type for JPEG image");
405 if(*width<1 || *height<1) _throw("Invalid data returned in header");
DRC91e86ba2011-02-15 05:24:08 +0000406
407 bailout:
408 return retval;
409}
410
411
412DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle h,
413 unsigned char *srcbuf, unsigned long size,
414 int *width, int *height)
415{
416 int jpegsub;
417 return tjDecompressHeader2(h, srcbuf, size, width, height, &jpegsub);
DRC1fe80f82010-12-14 01:21:29 +0000418}
419
420
DRC8ed7b812011-02-15 08:31:34 +0000421DLLEXPORT int DLLCALL tjDecompress2(tjhandle h,
DRC2e7b76b2009-04-03 12:04:24 +0000422 unsigned char *srcbuf, unsigned long size,
DRC8ed7b812011-02-15 08:31:34 +0000423 unsigned char *dstbuf, int pitch, int ps,
424 int scale_num, int scale_denom, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000425{
DRC91e86ba2011-02-15 05:24:08 +0000426 int i, row, retval=0; JSAMPROW *row_pointer=NULL, *outbuf[MAX_COMPONENTS];
DRCf9cf5c72010-12-10 10:58:49 +0000427 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS],
428 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
429 JSAMPLE *_tmpbuf=NULL; JSAMPROW *tmpbuf[MAX_COMPONENTS];
DRC2e7b76b2009-04-03 12:04:24 +0000430
431 checkhandle(h);
432
DRCf9cf5c72010-12-10 10:58:49 +0000433 for(i=0; i<MAX_COMPONENTS; i++)
434 {
435 tmpbuf[i]=NULL; outbuf[i]=NULL;
436 }
DRC9e17f7d2010-12-10 04:59:13 +0000437
DRC8ed7b812011-02-15 08:31:34 +0000438 if(srcbuf==NULL || size<=0 || dstbuf==NULL || pitch<0)
439 _throw("Invalid argument in tjDecompress2()");
DRC09854f52010-11-04 22:39:59 +0000440 if(ps!=3 && ps!=4 && ps!=1)
441 _throw("This decompressor can only handle 24-bit and 32-bit RGB or 8-bit grayscale output");
DRC2e7b76b2009-04-03 12:04:24 +0000442 if(!j->initd) _throw("Instance has not been initialized for decompression");
443
DRC8ed7b812011-02-15 08:31:34 +0000444 if(scale_num!=1 || scale_denom<1 || scale_denom>8
445 || (scale_denom&(scale_denom-1))!=0)
446 _throw("Unsupported scaling factor");
DRC2e7b76b2009-04-03 12:04:24 +0000447
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;
DRC8ed7b812011-02-15 08:31:34 +0000474 cw[i]=PAD(dinfo->image_width, dinfo->max_h_samp_factor)
475 *compptr->h_samp_factor/dinfo->max_h_samp_factor;
476 ch[i]=PAD(dinfo->image_height, dinfo->max_v_samp_factor)
477 *compptr->v_samp_factor/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 }
DRC2e7b76b2009-04-03 12:04:24 +0000507
DRC09854f52010-11-04 22:39:59 +0000508 if(ps==1) j->dinfo.out_color_space = JCS_GRAYSCALE;
DRC2e7b76b2009-04-03 12:04:24 +0000509 #if JCS_EXTENSIONS==1
DRC09854f52010-11-04 22:39:59 +0000510 else j->dinfo.out_color_space = JCS_EXT_RGB;
DRC2e7b76b2009-04-03 12:04:24 +0000511 if(ps==3 && (flags&TJ_BGR))
512 j->dinfo.out_color_space = JCS_EXT_BGR;
513 else if(ps==4 && !(flags&TJ_BGR) && !(flags&TJ_ALPHAFIRST))
514 j->dinfo.out_color_space = JCS_EXT_RGBX;
515 else if(ps==4 && (flags&TJ_BGR) && !(flags&TJ_ALPHAFIRST))
516 j->dinfo.out_color_space = JCS_EXT_BGRX;
517 else if(ps==4 && (flags&TJ_BGR) && (flags&TJ_ALPHAFIRST))
518 j->dinfo.out_color_space = JCS_EXT_XBGR;
519 else if(ps==4 && !(flags&TJ_BGR) && (flags&TJ_ALPHAFIRST))
520 j->dinfo.out_color_space = JCS_EXT_XRGB;
521 #else
522 #error "TurboJPEG requires JPEG colorspace extensions"
523 #endif
DRCfbb67472010-11-24 04:02:37 +0000524
DRC61e51f92009-04-05 21:53:20 +0000525 if(flags&TJ_FASTUPSAMPLE) j->dinfo.do_fancy_upsampling=FALSE;
DRC9e17f7d2010-12-10 04:59:13 +0000526 if(flags&TJ_YUV) j->dinfo.raw_data_out=TRUE;
DRC8ed7b812011-02-15 08:31:34 +0000527 else
528 {
529 j->dinfo.scale_num=scale_num;
530 j->dinfo.scale_denom=scale_denom;
531 }
DRC2e7b76b2009-04-03 12:04:24 +0000532
533 jpeg_start_decompress(&j->dinfo);
DRC9e17f7d2010-12-10 04:59:13 +0000534 if(flags&TJ_YUV)
DRC2e7b76b2009-04-03 12:04:24 +0000535 {
DRCf9cf5c72010-12-10 10:58:49 +0000536 j_decompress_ptr dinfo=&j->dinfo;
537 for(row=0; row<dinfo->output_height;
538 row+=dinfo->max_v_samp_factor*DCTSIZE)
DRC9e17f7d2010-12-10 04:59:13 +0000539 {
540 JSAMPARRAY yuvptr[MAX_COMPONENTS];
DRCa6f4fca2010-12-11 06:01:11 +0000541 int crow[MAX_COMPONENTS];
DRCf9cf5c72010-12-10 10:58:49 +0000542 for(i=0; i<dinfo->num_components; i++)
DRC9e17f7d2010-12-10 04:59:13 +0000543 {
DRCf9cf5c72010-12-10 10:58:49 +0000544 jpeg_component_info *compptr=&dinfo->comp_info[i];
DRCa6f4fca2010-12-11 06:01:11 +0000545 crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
DRCf9cf5c72010-12-10 10:58:49 +0000546 if(usetmpbuf) yuvptr[i]=tmpbuf[i];
DRCa6f4fca2010-12-11 06:01:11 +0000547 else yuvptr[i]=&outbuf[i][crow[i]];
DRC9e17f7d2010-12-10 04:59:13 +0000548 }
DRCf9cf5c72010-12-10 10:58:49 +0000549 jpeg_read_raw_data(dinfo, yuvptr, dinfo->max_v_samp_factor*DCTSIZE);
550 if(usetmpbuf)
551 {
552 int j;
553 for(i=0; i<dinfo->num_components; i++)
554 {
555 jpeg_component_info *compptr=&dinfo->comp_info[i];
DRCa6f4fca2010-12-11 06:01:11 +0000556 for(j=0; j<min(th[i], ch[i]-crow[i]); j++)
DRCf9cf5c72010-12-10 10:58:49 +0000557 {
DRCa6f4fca2010-12-11 06:01:11 +0000558 memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], cw[i]);
DRCf9cf5c72010-12-10 10:58:49 +0000559 }
560 }
561 }
DRC9e17f7d2010-12-10 04:59:13 +0000562 }
563 }
564 else
565 {
DRC8ed7b812011-02-15 08:31:34 +0000566 if(pitch==0) pitch=j->dinfo.output_width*ps;
567 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
568 *j->dinfo.output_height))==NULL)
569 {
570 jpeg_finish_decompress(&j->dinfo);
571 _throw("Memory allocation failed in tjInitDecompress()");
572 }
573 for(i=0; i<j->dinfo.output_height; i++)
574 {
575 if(flags&TJ_BOTTOMUP)
576 row_pointer[i]= &dstbuf[(j->dinfo.output_height-i-1)*pitch];
577 else row_pointer[i]= &dstbuf[i*pitch];
578 }
DRC9e17f7d2010-12-10 04:59:13 +0000579 while(j->dinfo.output_scanline<j->dinfo.output_height)
580 {
581 jpeg_read_scanlines(&j->dinfo, &row_pointer[j->dinfo.output_scanline],
582 j->dinfo.output_height-j->dinfo.output_scanline);
583 }
DRC2e7b76b2009-04-03 12:04:24 +0000584 }
585 jpeg_finish_decompress(&j->dinfo);
586
DRC91e86ba2011-02-15 05:24:08 +0000587 bailout:
DRC9e17f7d2010-12-10 04:59:13 +0000588 for(i=0; i<MAX_COMPONENTS; i++)
DRCf9cf5c72010-12-10 10:58:49 +0000589 {
590 if(tmpbuf[i]) free(tmpbuf[i]);
DRC9e17f7d2010-12-10 04:59:13 +0000591 if(outbuf[i]) free(outbuf[i]);
DRCf9cf5c72010-12-10 10:58:49 +0000592 }
593 if(_tmpbuf) free(_tmpbuf);
DRC2e7b76b2009-04-03 12:04:24 +0000594 if(row_pointer) free(row_pointer);
DRC91e86ba2011-02-15 05:24:08 +0000595 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000596}
597
598
DRC8ed7b812011-02-15 08:31:34 +0000599DLLEXPORT int DLLCALL tjDecompress(tjhandle h,
600 unsigned char *srcbuf, unsigned long size,
601 unsigned char *dstbuf, int width, int pitch, int height, int ps,
602 int flags)
603{
604 if(width<=0 || height<=0)
605 {
606 sprintf(lasterror, "Invalid argument in tjDecompress()");
607 return -1;
608 }
609 return tjDecompress2(h, srcbuf, size, dstbuf, pitch, ps, 1, 1, flags);
610}
611
DRC2e7b76b2009-04-03 12:04:24 +0000612// General
613
614DLLEXPORT char* DLLCALL tjGetErrorStr(void)
615{
616 return lasterror;
617}
618
619DLLEXPORT int DLLCALL tjDestroy(tjhandle h)
620{
621 checkhandle(h);
622 if(setjmp(j->jerr.jb)) return -1;
623 if(j->initc) jpeg_destroy_compress(&j->cinfo);
624 if(j->initd) jpeg_destroy_decompress(&j->dinfo);
625 free(j);
626 return 0;
627}