blob: 2490836b2600eed2a9ad018383f815e161c7424b [file] [log] [blame]
DRC9b28def2011-05-21 14:37:15 +00001/*
DRC38c99702014-02-11 09:45:18 +00002 * Copyright (C)2009-2014 D. R. Commander. All Rights Reserved.
DRC2e7b76b2009-04-03 12:04:24 +00003 *
DRC9b28def2011-05-21 14:37:15 +00004 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
DRC2e7b76b2009-04-03 12:04:24 +00006 *
DRC9b28def2011-05-21 14:37:15 +00007 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * - Neither the name of the libjpeg-turbo Project nor the names of its
13 * contributors may be used to endorse or promote products derived from this
14 * software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
DRC2e7b76b2009-04-03 12:04:24 +000027 */
28
DRCbdfcb742013-01-22 13:56:34 +000029/* TurboJPEG/LJT: this implements the TurboJPEG API using libjpeg or
30 libjpeg-turbo */
DRC2e7b76b2009-04-03 12:04:24 +000031
32#include <stdio.h>
33#include <stdlib.h>
DRC296c71b2011-05-25 04:12:52 +000034#include <jinclude.h>
DRCfbb67472010-11-24 04:02:37 +000035#define JPEG_INTERNALS
DRC2e7b76b2009-04-03 12:04:24 +000036#include <jpeglib.h>
37#include <jerror.h>
38#include <setjmp.h>
39#include "./turbojpeg.h"
DRCa29294a2011-05-24 09:17:57 +000040#include "./tjutil.h"
DRC890f1e02011-02-26 22:02:37 +000041#include "transupp.h"
DRC418fe282013-05-07 21:17:35 +000042#include "./jpegcomp.h"
DRC2a2e4512011-01-05 22:33:24 +000043
DRC9b28def2011-05-21 14:37:15 +000044extern void jpeg_mem_dest_tj(j_compress_ptr, unsigned char **,
45 unsigned long *, boolean);
46extern void jpeg_mem_src_tj(j_decompress_ptr, unsigned char *, unsigned long);
47
DRCfbb67472010-11-24 04:02:37 +000048#define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
DRCf610d612013-04-26 10:33:29 +000049#define isPow2(x) (((x)&(x-1))==0)
DRC2e7b76b2009-04-03 12:04:24 +000050
51
DRC9b28def2011-05-21 14:37:15 +000052/* Error handling (based on example in example.c) */
DRC2e7b76b2009-04-03 12:04:24 +000053
DRC9b28def2011-05-21 14:37:15 +000054static char errStr[JMSG_LENGTH_MAX]="No error";
DRC2e7b76b2009-04-03 12:04:24 +000055
DRC9b28def2011-05-21 14:37:15 +000056struct my_error_mgr
DRC2e7b76b2009-04-03 12:04:24 +000057{
58 struct jpeg_error_mgr pub;
DRC9b28def2011-05-21 14:37:15 +000059 jmp_buf setjmp_buffer;
60};
61typedef struct my_error_mgr *my_error_ptr;
DRC2e7b76b2009-04-03 12:04:24 +000062
63static void my_error_exit(j_common_ptr cinfo)
64{
DRC9b28def2011-05-21 14:37:15 +000065 my_error_ptr myerr=(my_error_ptr)cinfo->err;
DRC2e7b76b2009-04-03 12:04:24 +000066 (*cinfo->err->output_message)(cinfo);
DRC9b28def2011-05-21 14:37:15 +000067 longjmp(myerr->setjmp_buffer, 1);
DRC2e7b76b2009-04-03 12:04:24 +000068}
69
DRC9b28def2011-05-21 14:37:15 +000070/* Based on output_message() in jerror.c */
71
DRC2e7b76b2009-04-03 12:04:24 +000072static void my_output_message(j_common_ptr cinfo)
73{
DRC9b28def2011-05-21 14:37:15 +000074 (*cinfo->err->format_message)(cinfo, errStr);
DRC2e7b76b2009-04-03 12:04:24 +000075}
76
77
DRC9b28def2011-05-21 14:37:15 +000078/* Global structures, macros, etc. */
DRC2e7b76b2009-04-03 12:04:24 +000079
DRC9b28def2011-05-21 14:37:15 +000080enum {COMPRESS=1, DECOMPRESS=2};
81
82typedef struct _tjinstance
DRC2e7b76b2009-04-03 12:04:24 +000083{
84 struct jpeg_compress_struct cinfo;
85 struct jpeg_decompress_struct dinfo;
DRC9b28def2011-05-21 14:37:15 +000086 struct my_error_mgr jerr;
87 int init;
88} tjinstance;
DRC2e7b76b2009-04-03 12:04:24 +000089
DRC1f3635c2013-08-18 10:19:00 +000090static const int pixelsize[TJ_NUMSAMP]={3, 3, 3, 1, 3, 3};
DRC9b28def2011-05-21 14:37:15 +000091
DRC007a42c2011-05-22 13:55:56 +000092static const JXFORM_CODE xformtypes[TJ_NUMXOP]=
93{
DRC890f1e02011-02-26 22:02:37 +000094 JXFORM_NONE, JXFORM_FLIP_H, JXFORM_FLIP_V, JXFORM_TRANSPOSE,
95 JXFORM_TRANSVERSE, JXFORM_ROT_90, JXFORM_ROT_180, JXFORM_ROT_270
96};
DRC9b28def2011-05-21 14:37:15 +000097
DRCab2df6e2012-01-28 06:49:56 +000098#define NUMSF 16
DRC109a5782011-03-01 09:53:07 +000099static const tjscalingfactor sf[NUMSF]={
DRCab2df6e2012-01-28 06:49:56 +0000100 {2, 1},
101 {15, 8},
102 {7, 4},
103 {13, 8},
104 {3, 2},
105 {11, 8},
106 {5, 4},
107 {9, 8},
DRC109a5782011-03-01 09:53:07 +0000108 {1, 1},
DRCab2df6e2012-01-28 06:49:56 +0000109 {7, 8},
110 {3, 4},
111 {5, 8},
DRC109a5782011-03-01 09:53:07 +0000112 {1, 2},
DRCab2df6e2012-01-28 06:49:56 +0000113 {3, 8},
DRC109a5782011-03-01 09:53:07 +0000114 {1, 4},
115 {1, 8}
116};
DRC2e7b76b2009-04-03 12:04:24 +0000117
DRCa29294a2011-05-24 09:17:57 +0000118#define _throw(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s", m); \
DRCda5220a2011-03-02 02:17:30 +0000119 retval=-1; goto bailout;}
DRC9b28def2011-05-21 14:37:15 +0000120#define getinstance(handle) tjinstance *this=(tjinstance *)handle; \
121 j_compress_ptr cinfo=NULL; j_decompress_ptr dinfo=NULL; \
122 if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
123 return -1;} \
124 cinfo=&this->cinfo; dinfo=&this->dinfo;
DRC41861622014-04-16 23:38:37 +0000125#define getcinstance(handle) tjinstance *this=(tjinstance *)handle; \
126 j_compress_ptr cinfo=NULL; \
127 if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
128 return -1;} \
129 cinfo=&this->cinfo;
130#define getdinstance(handle) tjinstance *this=(tjinstance *)handle; \
131 j_decompress_ptr dinfo=NULL; \
132 if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
133 return -1;} \
134 dinfo=&this->dinfo;
DRC2e7b76b2009-04-03 12:04:24 +0000135
DRC9b28def2011-05-21 14:37:15 +0000136static int getPixelFormat(int pixelSize, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000137{
DRC25b995a2011-05-21 15:34:54 +0000138 if(pixelSize==1) return TJPF_GRAY;
DRC9b28def2011-05-21 14:37:15 +0000139 if(pixelSize==3)
140 {
DRC25b995a2011-05-21 15:34:54 +0000141 if(flags&TJ_BGR) return TJPF_BGR;
142 else return TJPF_RGB;
DRC9b28def2011-05-21 14:37:15 +0000143 }
144 if(pixelSize==4)
145 {
146 if(flags&TJ_ALPHAFIRST)
147 {
DRC25b995a2011-05-21 15:34:54 +0000148 if(flags&TJ_BGR) return TJPF_XBGR;
149 else return TJPF_XRGB;
DRC9b28def2011-05-21 14:37:15 +0000150 }
151 else
152 {
DRC25b995a2011-05-21 15:34:54 +0000153 if(flags&TJ_BGR) return TJPF_BGRX;
154 else return TJPF_RGBX;
DRC9b28def2011-05-21 14:37:15 +0000155 }
156 }
157 return -1;
DRC2e7b76b2009-04-03 12:04:24 +0000158}
159
DRCf12bb302011-09-07 05:03:18 +0000160static int setCompDefaults(struct jpeg_compress_struct *cinfo,
DRC73d74c12012-06-29 23:46:38 +0000161 int pixelFormat, int subsamp, int jpegQual, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000162{
DRCf12bb302011-09-07 05:03:18 +0000163 int retval=0;
164
DRC9b28def2011-05-21 14:37:15 +0000165 switch(pixelFormat)
166 {
DRC25b995a2011-05-21 15:34:54 +0000167 case TJPF_GRAY:
DRC9b28def2011-05-21 14:37:15 +0000168 cinfo->in_color_space=JCS_GRAYSCALE; break;
169 #if JCS_EXTENSIONS==1
DRC25b995a2011-05-21 15:34:54 +0000170 case TJPF_RGB:
DRC9b28def2011-05-21 14:37:15 +0000171 cinfo->in_color_space=JCS_EXT_RGB; break;
DRC25b995a2011-05-21 15:34:54 +0000172 case TJPF_BGR:
DRC9b28def2011-05-21 14:37:15 +0000173 cinfo->in_color_space=JCS_EXT_BGR; break;
DRC25b995a2011-05-21 15:34:54 +0000174 case TJPF_RGBX:
DRC67ce3b22011-12-19 02:21:03 +0000175 case TJPF_RGBA:
DRC9b28def2011-05-21 14:37:15 +0000176 cinfo->in_color_space=JCS_EXT_RGBX; break;
DRC25b995a2011-05-21 15:34:54 +0000177 case TJPF_BGRX:
DRC67ce3b22011-12-19 02:21:03 +0000178 case TJPF_BGRA:
DRC9b28def2011-05-21 14:37:15 +0000179 cinfo->in_color_space=JCS_EXT_BGRX; break;
DRC25b995a2011-05-21 15:34:54 +0000180 case TJPF_XRGB:
DRC67ce3b22011-12-19 02:21:03 +0000181 case TJPF_ARGB:
DRC9b28def2011-05-21 14:37:15 +0000182 cinfo->in_color_space=JCS_EXT_XRGB; break;
DRC25b995a2011-05-21 15:34:54 +0000183 case TJPF_XBGR:
DRC67ce3b22011-12-19 02:21:03 +0000184 case TJPF_ABGR:
DRC9b28def2011-05-21 14:37:15 +0000185 cinfo->in_color_space=JCS_EXT_XBGR; break;
186 #else
DRC25b995a2011-05-21 15:34:54 +0000187 case TJPF_RGB:
DRCafc06922012-03-23 19:47:57 +0000188 case TJPF_BGR:
189 case TJPF_RGBX:
190 case TJPF_BGRX:
191 case TJPF_XRGB:
192 case TJPF_XBGR:
193 case TJPF_RGBA:
194 case TJPF_BGRA:
195 case TJPF_ARGB:
196 case TJPF_ABGR:
197 cinfo->in_color_space=JCS_RGB; pixelFormat=TJPF_RGB;
198 break;
DRC9b28def2011-05-21 14:37:15 +0000199 #endif
DRCcd7c3e62013-08-23 02:49:25 +0000200 case TJPF_CMYK:
201 cinfo->in_color_space=JCS_CMYK; break;
DRCefa4ddc2010-10-13 19:22:50 +0000202 }
DRC2e7b76b2009-04-03 12:04:24 +0000203
DRC9b28def2011-05-21 14:37:15 +0000204 cinfo->input_components=tjPixelSize[pixelFormat];
205 jpeg_set_defaults(cinfo);
206 if(jpegQual>=0)
207 {
208 jpeg_set_quality(cinfo, jpegQual, TRUE);
DRC73d74c12012-06-29 23:46:38 +0000209 if(jpegQual>=96 || flags&TJFLAG_ACCURATEDCT) cinfo->dct_method=JDCT_ISLOW;
DRC9b28def2011-05-21 14:37:15 +0000210 else cinfo->dct_method=JDCT_FASTEST;
211 }
DRC25b995a2011-05-21 15:34:54 +0000212 if(subsamp==TJSAMP_GRAY)
DRC9b28def2011-05-21 14:37:15 +0000213 jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
DRCcd7c3e62013-08-23 02:49:25 +0000214 else if(pixelFormat==TJPF_CMYK)
215 jpeg_set_colorspace(cinfo, JCS_YCCK);
216 else jpeg_set_colorspace(cinfo, JCS_YCbCr);
DRC2e7b76b2009-04-03 12:04:24 +0000217
DRC9b28def2011-05-21 14:37:15 +0000218 cinfo->comp_info[0].h_samp_factor=tjMCUWidth[subsamp]/8;
219 cinfo->comp_info[1].h_samp_factor=1;
220 cinfo->comp_info[2].h_samp_factor=1;
DRCcd7c3e62013-08-23 02:49:25 +0000221 if(cinfo->num_components>3)
222 cinfo->comp_info[3].h_samp_factor=tjMCUWidth[subsamp]/8;
DRC9b28def2011-05-21 14:37:15 +0000223 cinfo->comp_info[0].v_samp_factor=tjMCUHeight[subsamp]/8;
224 cinfo->comp_info[1].v_samp_factor=1;
225 cinfo->comp_info[2].v_samp_factor=1;
DRCcd7c3e62013-08-23 02:49:25 +0000226 if(cinfo->num_components>3)
227 cinfo->comp_info[3].v_samp_factor=tjMCUHeight[subsamp]/8;
DRCf12bb302011-09-07 05:03:18 +0000228
DRCf12bb302011-09-07 05:03:18 +0000229 return retval;
DRC9b28def2011-05-21 14:37:15 +0000230}
231
DRCf12bb302011-09-07 05:03:18 +0000232static int setDecompDefaults(struct jpeg_decompress_struct *dinfo,
DRC73d74c12012-06-29 23:46:38 +0000233 int pixelFormat, int flags)
DRC9b28def2011-05-21 14:37:15 +0000234{
DRCf12bb302011-09-07 05:03:18 +0000235 int retval=0;
236
DRC9b28def2011-05-21 14:37:15 +0000237 switch(pixelFormat)
238 {
DRC25b995a2011-05-21 15:34:54 +0000239 case TJPF_GRAY:
DRC9b28def2011-05-21 14:37:15 +0000240 dinfo->out_color_space=JCS_GRAYSCALE; break;
241 #if JCS_EXTENSIONS==1
DRC25b995a2011-05-21 15:34:54 +0000242 case TJPF_RGB:
DRC9b28def2011-05-21 14:37:15 +0000243 dinfo->out_color_space=JCS_EXT_RGB; break;
DRC25b995a2011-05-21 15:34:54 +0000244 case TJPF_BGR:
DRC9b28def2011-05-21 14:37:15 +0000245 dinfo->out_color_space=JCS_EXT_BGR; break;
DRC25b995a2011-05-21 15:34:54 +0000246 case TJPF_RGBX:
DRC9b28def2011-05-21 14:37:15 +0000247 dinfo->out_color_space=JCS_EXT_RGBX; break;
DRC25b995a2011-05-21 15:34:54 +0000248 case TJPF_BGRX:
DRC9b28def2011-05-21 14:37:15 +0000249 dinfo->out_color_space=JCS_EXT_BGRX; break;
DRC25b995a2011-05-21 15:34:54 +0000250 case TJPF_XRGB:
DRC9b28def2011-05-21 14:37:15 +0000251 dinfo->out_color_space=JCS_EXT_XRGB; break;
DRC25b995a2011-05-21 15:34:54 +0000252 case TJPF_XBGR:
DRC9b28def2011-05-21 14:37:15 +0000253 dinfo->out_color_space=JCS_EXT_XBGR; break;
DRC67ce3b22011-12-19 02:21:03 +0000254 #if JCS_ALPHA_EXTENSIONS==1
255 case TJPF_RGBA:
256 dinfo->out_color_space=JCS_EXT_RGBA; break;
257 case TJPF_BGRA:
258 dinfo->out_color_space=JCS_EXT_BGRA; break;
259 case TJPF_ARGB:
260 dinfo->out_color_space=JCS_EXT_ARGB; break;
261 case TJPF_ABGR:
262 dinfo->out_color_space=JCS_EXT_ABGR; break;
263 #endif
DRC9b28def2011-05-21 14:37:15 +0000264 #else
DRC25b995a2011-05-21 15:34:54 +0000265 case TJPF_RGB:
DRCafc06922012-03-23 19:47:57 +0000266 case TJPF_BGR:
267 case TJPF_RGBX:
268 case TJPF_BGRX:
269 case TJPF_XRGB:
270 case TJPF_XBGR:
271 case TJPF_RGBA:
272 case TJPF_BGRA:
273 case TJPF_ARGB:
274 case TJPF_ABGR:
275 dinfo->out_color_space=JCS_RGB; break;
DRC67ce3b22011-12-19 02:21:03 +0000276 #endif
DRCcd7c3e62013-08-23 02:49:25 +0000277 case TJPF_CMYK:
278 dinfo->out_color_space=JCS_CMYK; break;
DRC9b28def2011-05-21 14:37:15 +0000279 default:
280 _throw("Unsupported pixel format");
DRC9b28def2011-05-21 14:37:15 +0000281 }
DRCf12bb302011-09-07 05:03:18 +0000282
DRC73d74c12012-06-29 23:46:38 +0000283 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
284
DRCf12bb302011-09-07 05:03:18 +0000285 bailout:
DRCf12bb302011-09-07 05:03:18 +0000286 return retval;
DRC9b28def2011-05-21 14:37:15 +0000287}
288
289
DRC9b49f0e2011-07-12 03:17:23 +0000290static int getSubsamp(j_decompress_ptr dinfo)
291{
292 int retval=-1, i, k;
293 for(i=0; i<NUMSUBOPT; i++)
294 {
DRCcd7c3e62013-08-23 02:49:25 +0000295 if(dinfo->num_components==pixelsize[i]
296 || ((dinfo->jpeg_color_space==JCS_YCCK
297 || dinfo->jpeg_color_space==JCS_CMYK)
298 && pixelsize[i]==3 && dinfo->num_components==4))
DRC9b49f0e2011-07-12 03:17:23 +0000299 {
300 if(dinfo->comp_info[0].h_samp_factor==tjMCUWidth[i]/8
301 && dinfo->comp_info[0].v_samp_factor==tjMCUHeight[i]/8)
302 {
303 int match=0;
304 for(k=1; k<dinfo->num_components; k++)
305 {
DRCcd7c3e62013-08-23 02:49:25 +0000306 int href=1, vref=1;
307 if(dinfo->jpeg_color_space==JCS_YCCK && k==3)
308 {
309 href=tjMCUWidth[i]/8; vref=tjMCUHeight[i]/8;
310 }
311 if(dinfo->comp_info[k].h_samp_factor==href
312 && dinfo->comp_info[k].v_samp_factor==vref)
DRC9b49f0e2011-07-12 03:17:23 +0000313 match++;
314 }
315 if(match==dinfo->num_components-1)
316 {
317 retval=i; break;
318 }
319 }
320 }
321 }
322 return retval;
323}
324
325
DRCafc06922012-03-23 19:47:57 +0000326#ifndef JCS_EXTENSIONS
327
328/* Conversion functions to emulate the colorspace extensions. This allows the
329 TurboJPEG wrapper to be used with libjpeg */
330
331#define TORGB(PS, ROFFSET, GOFFSET, BOFFSET) { \
332 int rowPad=pitch-width*PS; \
333 while(height--) \
334 { \
335 unsigned char *endOfRow=src+width*PS; \
336 while(src<endOfRow) \
337 { \
338 dst[RGB_RED]=src[ROFFSET]; \
339 dst[RGB_GREEN]=src[GOFFSET]; \
340 dst[RGB_BLUE]=src[BOFFSET]; \
341 dst+=RGB_PIXELSIZE; src+=PS; \
342 } \
343 src+=rowPad; \
344 } \
345}
346
347static unsigned char *toRGB(unsigned char *src, int width, int pitch,
348 int height, int pixelFormat, unsigned char *dst)
349{
350 unsigned char *retval=src;
351 switch(pixelFormat)
352 {
353 case TJPF_RGB:
354 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3
355 retval=dst; TORGB(3, 0, 1, 2);
356 #endif
357 break;
358 case TJPF_BGR:
359 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3
360 retval=dst; TORGB(3, 2, 1, 0);
361 #endif
362 break;
363 case TJPF_RGBX:
364 case TJPF_RGBA:
365 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
366 retval=dst; TORGB(4, 0, 1, 2);
367 #endif
368 break;
369 case TJPF_BGRX:
370 case TJPF_BGRA:
371 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
372 retval=dst; TORGB(4, 2, 1, 0);
373 #endif
374 break;
375 case TJPF_XRGB:
376 case TJPF_ARGB:
377 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
378 retval=dst; TORGB(4, 1, 2, 3);
379 #endif
380 break;
381 case TJPF_XBGR:
382 case TJPF_ABGR:
383 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
384 retval=dst; TORGB(4, 3, 2, 1);
385 #endif
386 break;
387 }
388 return retval;
389}
390
391#define FROMRGB(PS, ROFFSET, GOFFSET, BOFFSET, SETALPHA) { \
392 int rowPad=pitch-width*PS; \
393 while(height--) \
394 { \
395 unsigned char *endOfRow=dst+width*PS; \
396 while(dst<endOfRow) \
397 { \
398 dst[ROFFSET]=src[RGB_RED]; \
399 dst[GOFFSET]=src[RGB_GREEN]; \
400 dst[BOFFSET]=src[RGB_BLUE]; \
401 SETALPHA \
402 dst+=PS; src+=RGB_PIXELSIZE; \
403 } \
404 dst+=rowPad; \
405 } \
406}
407
408static void fromRGB(unsigned char *src, unsigned char *dst, int width,
409 int pitch, int height, int pixelFormat)
410{
411 switch(pixelFormat)
412 {
413 case TJPF_RGB:
414 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3
415 FROMRGB(3, 0, 1, 2,);
416 #endif
417 break;
418 case TJPF_BGR:
419 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3
420 FROMRGB(3, 2, 1, 0,);
421 #endif
422 break;
423 case TJPF_RGBX:
424 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
425 FROMRGB(4, 0, 1, 2,);
426 #endif
427 break;
428 case TJPF_RGBA:
429 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
430 FROMRGB(4, 0, 1, 2, dst[3]=0xFF;);
431 #endif
432 break;
433 case TJPF_BGRX:
434 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
435 FROMRGB(4, 2, 1, 0,);
436 #endif
437 break;
438 case TJPF_BGRA:
439 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
440 FROMRGB(4, 2, 1, 0, dst[3]=0xFF;); return;
441 #endif
442 break;
443 case TJPF_XRGB:
444 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
445 FROMRGB(4, 1, 2, 3,); return;
446 #endif
447 break;
448 case TJPF_ARGB:
449 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
450 FROMRGB(4, 1, 2, 3, dst[0]=0xFF;); return;
451 #endif
452 break;
453 case TJPF_XBGR:
454 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
455 FROMRGB(4, 3, 2, 1,); return;
456 #endif
457 break;
458 case TJPF_ABGR:
459 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
460 FROMRGB(4, 3, 2, 1, dst[0]=0xFF;); return;
461 #endif
462 break;
463 }
464}
465
466#endif
467
468
DRC9b28def2011-05-21 14:37:15 +0000469/* General API functions */
470
471DLLEXPORT char* DLLCALL tjGetErrorStr(void)
472{
473 return errStr;
474}
475
476
477DLLEXPORT int DLLCALL tjDestroy(tjhandle handle)
478{
479 getinstance(handle);
480 if(setjmp(this->jerr.setjmp_buffer)) return -1;
481 if(this->init&COMPRESS) jpeg_destroy_compress(cinfo);
482 if(this->init&DECOMPRESS) jpeg_destroy_decompress(dinfo);
483 free(this);
484 return 0;
485}
486
487
DRC6b76f752011-05-24 16:52:47 +0000488/* These are exposed mainly because Windows can't malloc() and free() across
489 DLL boundaries except when the CRT DLL is used, and we don't use the CRT DLL
490 with turbojpeg.dll for compatibility reasons. However, these functions
491 can potentially be used for other purposes by different implementations. */
492
493DLLEXPORT void DLLCALL tjFree(unsigned char *buf)
494{
495 if(buf) free(buf);
496}
497
498
499DLLEXPORT unsigned char *DLLCALL tjAlloc(int bytes)
500{
501 return (unsigned char *)malloc(bytes);
502}
503
504
DRC9b28def2011-05-21 14:37:15 +0000505/* Compressor */
506
507static tjhandle _tjInitCompress(tjinstance *this)
508{
509 unsigned char buffer[1], *buf=buffer; unsigned long size=1;
510
511 /* This is also straight out of example.c */
512 this->cinfo.err=jpeg_std_error(&this->jerr.pub);
513 this->jerr.pub.error_exit=my_error_exit;
514 this->jerr.pub.output_message=my_output_message;
515
516 if(setjmp(this->jerr.setjmp_buffer))
517 {
518 /* If we get here, the JPEG code has signaled an error. */
519 if(this) free(this); return NULL;
520 }
521
522 jpeg_create_compress(&this->cinfo);
523 /* Make an initial call so it will create the destination manager */
524 jpeg_mem_dest_tj(&this->cinfo, &buf, &size, 0);
525
DRC007a42c2011-05-22 13:55:56 +0000526 this->init|=COMPRESS;
DRC9b28def2011-05-21 14:37:15 +0000527 return (tjhandle)this;
DRC2e7b76b2009-04-03 12:04:24 +0000528}
529
DRC890f1e02011-02-26 22:02:37 +0000530DLLEXPORT tjhandle DLLCALL tjInitCompress(void)
531{
DRC9b28def2011-05-21 14:37:15 +0000532 tjinstance *this=NULL;
533 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
DRCda5220a2011-03-02 02:17:30 +0000534 {
DRC007a42c2011-05-22 13:55:56 +0000535 snprintf(errStr, JMSG_LENGTH_MAX,
536 "tjInitCompress(): Memory allocation failure");
DRCda5220a2011-03-02 02:17:30 +0000537 return NULL;
538 }
DRC007a42c2011-05-22 13:55:56 +0000539 MEMZERO(this, sizeof(tjinstance));
DRC9b28def2011-05-21 14:37:15 +0000540 return _tjInitCompress(this);
DRC890f1e02011-02-26 22:02:37 +0000541}
542
DRC84241602011-02-25 02:08:23 +0000543
DRC9b49f0e2011-07-12 03:17:23 +0000544DLLEXPORT unsigned long DLLCALL tjBufSize(int width, int height,
545 int jpegSubsamp)
546{
547 unsigned long retval=0; int mcuw, mcuh, chromasf;
548 if(width<1 || height<1 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT)
549 _throw("tjBufSize(): Invalid argument");
550
DRC006bc582014-02-27 21:22:54 +0000551 /* This allows for rare corner cases in which a JPEG image can actually be
552 larger than the uncompressed input (we wouldn't mention it if it hadn't
553 happened before.) */
DRC9b49f0e2011-07-12 03:17:23 +0000554 mcuw=tjMCUWidth[jpegSubsamp];
555 mcuh=tjMCUHeight[jpegSubsamp];
556 chromasf=jpegSubsamp==TJSAMP_GRAY? 0: 4*64/(mcuw*mcuh);
557 retval=PAD(width, mcuw) * PAD(height, mcuh) * (2 + chromasf) + 2048;
558
559 bailout:
560 return retval;
561}
562
DRC2e7b76b2009-04-03 12:04:24 +0000563DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
564{
DRCf3cf9732011-02-22 00:16:14 +0000565 unsigned long retval=0;
566 if(width<1 || height<1)
DRC007a42c2011-05-22 13:55:56 +0000567 _throw("TJBUFSIZE(): Invalid argument");
DRCf3cf9732011-02-22 00:16:14 +0000568
DRC006bc582014-02-27 21:22:54 +0000569 /* This allows for rare corner cases in which a JPEG image can actually be
570 larger than the uncompressed input (we wouldn't mention it if it hadn't
571 happened before.) */
DRC007a42c2011-05-22 13:55:56 +0000572 retval=PAD(width, 16) * PAD(height, 16) * 6 + 2048;
DRCf3cf9732011-02-22 00:16:14 +0000573
574 bailout:
575 return retval;
576}
577
DRC84241602011-02-25 02:08:23 +0000578
DRCf610d612013-04-26 10:33:29 +0000579DLLEXPORT unsigned long DLLCALL tjBufSizeYUV2(int width, int pad, int height,
DRCf3cf9732011-02-22 00:16:14 +0000580 int subsamp)
581{
582 unsigned long retval=0;
583 int pw, ph, cw, ch;
DRCf610d612013-04-26 10:33:29 +0000584 if(width<1 || height<1 || pad<1 || !isPow2(pad) || subsamp<0
585 || subsamp>=NUMSUBOPT)
586 _throw("tjBufSizeYUV2(): Invalid argument");
DRC9b28def2011-05-21 14:37:15 +0000587 pw=PAD(width, tjMCUWidth[subsamp]/8);
588 ph=PAD(height, tjMCUHeight[subsamp]/8);
589 cw=pw*8/tjMCUWidth[subsamp]; ch=ph*8/tjMCUHeight[subsamp];
DRCf610d612013-04-26 10:33:29 +0000590 retval=PAD(pw, pad)*ph + (subsamp==TJSAMP_GRAY? 0:PAD(cw, pad)*ch*2);
DRCf3cf9732011-02-22 00:16:14 +0000591
592 bailout:
593 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000594}
595
DRCf610d612013-04-26 10:33:29 +0000596DLLEXPORT unsigned long DLLCALL tjBufSizeYUV(int width, int height,
597 int subsamp)
598{
599 return tjBufSizeYUV2(width, 4, height, subsamp);
600}
DRC84241602011-02-25 02:08:23 +0000601
DRC9b49f0e2011-07-12 03:17:23 +0000602DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
603 int subsamp)
604{
605 return tjBufSizeYUV(width, height, subsamp);
606}
607
608
DRC9b28def2011-05-21 14:37:15 +0000609DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf,
610 int width, int pitch, int height, int pixelFormat, unsigned char **jpegBuf,
611 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
612{
DRCff78e372011-05-24 10:17:32 +0000613 int i, retval=0, alloc=1; JSAMPROW *row_pointer=NULL;
DRCafc06922012-03-23 19:47:57 +0000614 #ifndef JCS_EXTENSIONS
615 unsigned char *rgbBuf=NULL;
616 #endif
DRC9b28def2011-05-21 14:37:15 +0000617
DRC41861622014-04-16 23:38:37 +0000618 getcinstance(handle)
DRC9b28def2011-05-21 14:37:15 +0000619 if((this->init&COMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +0000620 _throw("tjCompress2(): Instance has not been initialized for compression");
DRC9b28def2011-05-21 14:37:15 +0000621
622 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
623 || pixelFormat>=TJ_NUMPF || jpegBuf==NULL || jpegSize==NULL
624 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT || jpegQual<0 || jpegQual>100)
DRC007a42c2011-05-22 13:55:56 +0000625 _throw("tjCompress2(): Invalid argument");
DRC9b28def2011-05-21 14:37:15 +0000626
627 if(setjmp(this->jerr.setjmp_buffer))
628 {
629 /* If we get here, the JPEG code has signaled an error. */
630 retval=-1;
631 goto bailout;
632 }
633
634 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
635
DRCafc06922012-03-23 19:47:57 +0000636 #ifndef JCS_EXTENSIONS
DRC230d09d2014-04-20 09:42:49 +0000637 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK)
DRCafc06922012-03-23 19:47:57 +0000638 {
639 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
640 if(!rgbBuf) _throw("tjCompress2(): Memory allocation failure");
641 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
642 pitch=width*RGB_PIXELSIZE;
643 }
644 #endif
645
DRC9b28def2011-05-21 14:37:15 +0000646 cinfo->image_width=width;
647 cinfo->image_height=height;
648
DRC25b995a2011-05-21 15:34:54 +0000649 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
650 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
651 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC9b28def2011-05-21 14:37:15 +0000652
DRCff78e372011-05-24 10:17:32 +0000653 if(flags&TJFLAG_NOREALLOC)
654 {
DRC9b49f0e2011-07-12 03:17:23 +0000655 alloc=0; *jpegSize=tjBufSize(width, height, jpegSubsamp);
DRCff78e372011-05-24 10:17:32 +0000656 }
657 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
DRC73d74c12012-06-29 23:46:38 +0000658 if(setCompDefaults(cinfo, pixelFormat, jpegSubsamp, jpegQual, flags)==-1)
DRCf12bb302011-09-07 05:03:18 +0000659 return -1;
DRC9b28def2011-05-21 14:37:15 +0000660
661 jpeg_start_compress(cinfo, TRUE);
662 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
DRC007a42c2011-05-22 13:55:56 +0000663 _throw("tjCompress2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000664 for(i=0; i<height; i++)
665 {
DRC25b995a2011-05-21 15:34:54 +0000666 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
DRC9b28def2011-05-21 14:37:15 +0000667 else row_pointer[i]=&srcBuf[i*pitch];
668 }
669 while(cinfo->next_scanline<cinfo->image_height)
670 {
671 jpeg_write_scanlines(cinfo, &row_pointer[cinfo->next_scanline],
672 cinfo->image_height-cinfo->next_scanline);
673 }
674 jpeg_finish_compress(cinfo);
675
676 bailout:
677 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
DRCafc06922012-03-23 19:47:57 +0000678 #ifndef JCS_EXTENSIONS
DRCea3396a2012-04-26 03:18:49 +0000679 if(rgbBuf) free(rgbBuf);
DRCafc06922012-03-23 19:47:57 +0000680 #endif
DRC9b28def2011-05-21 14:37:15 +0000681 if(row_pointer) free(row_pointer);
682 return retval;
683}
684
685DLLEXPORT int DLLCALL tjCompress(tjhandle handle, unsigned char *srcBuf,
686 int width, int pitch, int height, int pixelSize, unsigned char *jpegBuf,
687 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
688{
689 int retval=0; unsigned long size;
690 if(flags&TJ_YUV)
691 {
DRC9b49f0e2011-07-12 03:17:23 +0000692 size=tjBufSizeYUV(width, height, jpegSubsamp);
DRC9b28def2011-05-21 14:37:15 +0000693 retval=tjEncodeYUV2(handle, srcBuf, width, pitch, height,
694 getPixelFormat(pixelSize, flags), jpegBuf, jpegSubsamp, flags);
695 }
696 else
697 {
DRC9b28def2011-05-21 14:37:15 +0000698 retval=tjCompress2(handle, srcBuf, width, pitch, height,
699 getPixelFormat(pixelSize, flags), &jpegBuf, &size, jpegSubsamp, jpegQual,
DRC25b995a2011-05-21 15:34:54 +0000700 flags|TJFLAG_NOREALLOC);
DRC9b28def2011-05-21 14:37:15 +0000701 }
702 *jpegSize=size;
703 return retval;
704}
705
706
DRCf610d612013-04-26 10:33:29 +0000707DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf,
DRC9b28def2011-05-21 14:37:15 +0000708 int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
DRCf610d612013-04-26 10:33:29 +0000709 int pad, int subsamp, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000710{
DRC91e86ba2011-02-15 05:24:08 +0000711 int i, retval=0; JSAMPROW *row_pointer=NULL;
DRCfbb67472010-11-24 04:02:37 +0000712 JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS];
713 JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
714 JSAMPROW *outbuf[MAX_COMPONENTS];
DRC9b28def2011-05-21 14:37:15 +0000715 int row, pw, ph, cw[MAX_COMPONENTS], ch[MAX_COMPONENTS];
716 JSAMPLE *ptr=dstBuf;
DRCafc06922012-03-23 19:47:57 +0000717 unsigned long yuvsize=0;
DRC9b28def2011-05-21 14:37:15 +0000718 jpeg_component_info *compptr;
DRCafc06922012-03-23 19:47:57 +0000719 #ifndef JCS_EXTENSIONS
720 unsigned char *rgbBuf=NULL;
721 #endif
DRC2e7b76b2009-04-03 12:04:24 +0000722
DRC41861622014-04-16 23:38:37 +0000723 getcinstance(handle);
DRCb51ee892013-10-31 05:00:19 +0000724
DRCfbb67472010-11-24 04:02:37 +0000725 for(i=0; i<MAX_COMPONENTS; i++)
726 {
727 tmpbuf[i]=NULL; _tmpbuf[i]=NULL;
728 tmpbuf2[i]=NULL; _tmpbuf2[i]=NULL; outbuf[i]=NULL;
729 }
730
DRCe2f8e692013-10-30 22:21:06 +0000731 if((this->init&COMPRESS)==0)
732 _throw("tjEncodeYUV3(): Instance has not been initialized for compression");
733
DRC9b28def2011-05-21 14:37:15 +0000734 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
DRCf610d612013-04-26 10:33:29 +0000735 || pixelFormat>=TJ_NUMPF || dstBuf==NULL || pad<0 || !isPow2(pad)
736 || subsamp<0 || subsamp>=NUMSUBOPT)
737 _throw("tjEncodeYUV3(): Invalid argument");
DRC2e7b76b2009-04-03 12:04:24 +0000738
DRC9b28def2011-05-21 14:37:15 +0000739 if(setjmp(this->jerr.setjmp_buffer))
740 {
741 /* If we get here, the JPEG code has signaled an error. */
742 retval=-1;
743 goto bailout;
744 }
DRC2e7b76b2009-04-03 12:04:24 +0000745
DRCcd7c3e62013-08-23 02:49:25 +0000746 if(pixelFormat==TJPF_CMYK)
747 _throw("tjEncodeYUV3(): Cannot generate YUV images from CMYK pixels");
748
DRC9b28def2011-05-21 14:37:15 +0000749 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
DRC2e7b76b2009-04-03 12:04:24 +0000750
DRCafc06922012-03-23 19:47:57 +0000751 #ifndef JCS_EXTENSIONS
DRC230d09d2014-04-20 09:42:49 +0000752 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK)
DRCafc06922012-03-23 19:47:57 +0000753 {
754 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
DRCf610d612013-04-26 10:33:29 +0000755 if(!rgbBuf) _throw("tjEncodeYUV3(): Memory allocation failure");
DRCafc06922012-03-23 19:47:57 +0000756 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
757 pitch=width*RGB_PIXELSIZE;
758 }
759 #endif
760
DRC9b28def2011-05-21 14:37:15 +0000761 cinfo->image_width=width;
762 cinfo->image_height=height;
DRC2e7b76b2009-04-03 12:04:24 +0000763
DRC25b995a2011-05-21 15:34:54 +0000764 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
765 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
766 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC0c6a2712010-02-22 08:34:44 +0000767
DRCf610d612013-04-26 10:33:29 +0000768 yuvsize=tjBufSizeYUV2(width, pad, height, subsamp);
DRC73d74c12012-06-29 23:46:38 +0000769 if(setCompDefaults(cinfo, pixelFormat, subsamp, -1, flags)==-1) return -1;
DRC2e7b76b2009-04-03 12:04:24 +0000770
DRC38c99702014-02-11 09:45:18 +0000771 /* Execute only the parts of jpeg_start_compress() that we need. If we
772 were to call the whole jpeg_start_compress() function, then it would try
773 to write the file headers, which could overflow the output buffer if the
774 YUV image were very small. */
775 if(cinfo->global_state!=CSTATE_START)
776 _throw("tjEncodeYUV3(): libjpeg API is in the wrong state");
777 (*cinfo->err->reset_error_mgr)((j_common_ptr)cinfo);
DRC38c99702014-02-11 09:45:18 +0000778 jinit_c_master_control(cinfo, FALSE);
779 jinit_color_converter(cinfo);
780 jinit_downsampler(cinfo);
DRC50cfc462014-03-06 20:03:37 +0000781 (*cinfo->cconvert->start_pass)(cinfo);
DRC38c99702014-02-11 09:45:18 +0000782
DRC9b28def2011-05-21 14:37:15 +0000783 pw=PAD(width, cinfo->max_h_samp_factor);
784 ph=PAD(height, cinfo->max_v_samp_factor);
DRC2e7b76b2009-04-03 12:04:24 +0000785
DRC9b28def2011-05-21 14:37:15 +0000786 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph))==NULL)
DRCf610d612013-04-26 10:33:29 +0000787 _throw("tjEncodeYUV3(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000788 for(i=0; i<height; i++)
DRC2e7b76b2009-04-03 12:04:24 +0000789 {
DRC25b995a2011-05-21 15:34:54 +0000790 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
DRC9b28def2011-05-21 14:37:15 +0000791 else row_pointer[i]=&srcBuf[i*pitch];
792 }
793 if(height<ph)
794 for(i=height; i<ph; i++) row_pointer[i]=row_pointer[height-1];
DRCfbb67472010-11-24 04:02:37 +0000795
DRC9b28def2011-05-21 14:37:15 +0000796 for(i=0; i<cinfo->num_components; i++)
797 {
798 compptr=&cinfo->comp_info[i];
799 _tmpbuf[i]=(JSAMPLE *)malloc(
800 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
801 /compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
DRCf610d612013-04-26 10:33:29 +0000802 if(!_tmpbuf[i]) _throw("tjEncodeYUV3(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000803 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
DRCf610d612013-04-26 10:33:29 +0000804 if(!tmpbuf[i]) _throw("tjEncodeYUV3(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000805 for(row=0; row<cinfo->max_v_samp_factor; row++)
DRCfbb67472010-11-24 04:02:37 +0000806 {
DRC9b28def2011-05-21 14:37:15 +0000807 unsigned char *_tmpbuf_aligned=
808 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
809 tmpbuf[i][row]=&_tmpbuf_aligned[
DRCfbb67472010-11-24 04:02:37 +0000810 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
DRC9b28def2011-05-21 14:37:15 +0000811 /compptr->h_samp_factor, 16) * row];
DRCfbb67472010-11-24 04:02:37 +0000812 }
DRC9b28def2011-05-21 14:37:15 +0000813 _tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
814 * compptr->v_samp_factor + 16);
DRCf610d612013-04-26 10:33:29 +0000815 if(!_tmpbuf2[i]) _throw("tjEncodeYUV3(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000816 tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
DRCf610d612013-04-26 10:33:29 +0000817 if(!tmpbuf2[i]) _throw("tjEncodeYUV3(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000818 for(row=0; row<compptr->v_samp_factor; row++)
819 {
820 unsigned char *_tmpbuf2_aligned=
821 (unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
822 tmpbuf2[i][row]=&_tmpbuf2_aligned[
823 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
824 }
825 cw[i]=pw*compptr->h_samp_factor/cinfo->max_h_samp_factor;
826 ch[i]=ph*compptr->v_samp_factor/cinfo->max_v_samp_factor;
827 outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]);
DRCf610d612013-04-26 10:33:29 +0000828 if(!outbuf[i]) _throw("tjEncodeYUV3(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000829 for(row=0; row<ch[i]; row++)
830 {
831 outbuf[i][row]=ptr;
DRCf610d612013-04-26 10:33:29 +0000832 ptr+=PAD(cw[i], pad);
DRC9b28def2011-05-21 14:37:15 +0000833 }
834 }
835 if(yuvsize!=(unsigned long)(ptr-dstBuf))
DRCf610d612013-04-26 10:33:29 +0000836 _throw("tjEncodeYUV3(): Generated image is not the correct size");
DRCfbb67472010-11-24 04:02:37 +0000837
DRC9b28def2011-05-21 14:37:15 +0000838 for(row=0; row<ph; row+=cinfo->max_v_samp_factor)
DRCfbb67472010-11-24 04:02:37 +0000839 {
DRC9b28def2011-05-21 14:37:15 +0000840 (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0,
841 cinfo->max_v_samp_factor);
842 (cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
843 for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++)
844 jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
845 row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
846 compptr->v_samp_factor, cw[i]);
DRC6ee54592011-03-01 08:18:30 +0000847 }
DRC9b28def2011-05-21 14:37:15 +0000848 cinfo->next_scanline+=height;
849 jpeg_abort_compress(cinfo);
DRC2e7b76b2009-04-03 12:04:24 +0000850
DRC91e86ba2011-02-15 05:24:08 +0000851 bailout:
DRC9b28def2011-05-21 14:37:15 +0000852 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
DRCafc06922012-03-23 19:47:57 +0000853 #ifndef JCS_EXTENSIONS
DRCea3396a2012-04-26 03:18:49 +0000854 if(rgbBuf) free(rgbBuf);
DRCafc06922012-03-23 19:47:57 +0000855 #endif
DRC2e7b76b2009-04-03 12:04:24 +0000856 if(row_pointer) free(row_pointer);
DRCfbb67472010-11-24 04:02:37 +0000857 for(i=0; i<MAX_COMPONENTS; i++)
858 {
859 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
DRC57423072011-01-05 23:35:53 +0000860 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
DRCfbb67472010-11-24 04:02:37 +0000861 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
DRC57423072011-01-05 23:35:53 +0000862 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
DRCfbb67472010-11-24 04:02:37 +0000863 if(outbuf[i]!=NULL) free(outbuf[i]);
864 }
DRC91e86ba2011-02-15 05:24:08 +0000865 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000866}
867
DRCf610d612013-04-26 10:33:29 +0000868DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
869 int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
870 int subsamp, int flags)
871{
872 return tjEncodeYUV3(handle, srcBuf, width, pitch, height, pixelFormat,
873 dstBuf, 4, subsamp, flags);
874}
875
DRC9b28def2011-05-21 14:37:15 +0000876DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf,
877 int width, int pitch, int height, int pixelSize, unsigned char *dstBuf,
878 int subsamp, int flags)
DRC84241602011-02-25 02:08:23 +0000879{
DRC9b28def2011-05-21 14:37:15 +0000880 return tjEncodeYUV2(handle, srcBuf, width, pitch, height,
881 getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags);
DRC84241602011-02-25 02:08:23 +0000882}
883
884
DRC910a3572013-10-30 23:02:57 +0000885DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle, unsigned char *srcBuf,
886 int width, int pad, int height, int subsamp, unsigned char **jpegBuf,
887 unsigned long *jpegSize, int jpegQual, int flags)
888{
889 int i, row, retval=0, alloc=1; JSAMPROW *inbuf[MAX_COMPONENTS];
890 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS],
891 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
892 JSAMPLE *_tmpbuf=NULL, *ptr=srcBuf; JSAMPROW *tmpbuf[MAX_COMPONENTS];
893
DRC41861622014-04-16 23:38:37 +0000894 getcinstance(handle)
DRCb51ee892013-10-31 05:00:19 +0000895
DRC910a3572013-10-30 23:02:57 +0000896 for(i=0; i<MAX_COMPONENTS; i++)
897 {
898 tmpbuf[i]=NULL; inbuf[i]=NULL;
899 }
900
DRC910a3572013-10-30 23:02:57 +0000901 if((this->init&COMPRESS)==0)
902 _throw("tjCompressFromYUV(): Instance has not been initialized for compression");
903
904 if(srcBuf==NULL || width<=0 || pad<1 || height<=0 || subsamp<0
905 || subsamp>=NUMSUBOPT || jpegBuf==NULL || jpegSize==NULL || jpegQual<0
906 || jpegQual>100)
907 _throw("tjCompressFromYUV(): Invalid argument");
908
909 if(setjmp(this->jerr.setjmp_buffer))
910 {
911 /* If we get here, the JPEG code has signaled an error. */
912 retval=-1;
913 goto bailout;
914 }
915
916 cinfo->image_width=width;
917 cinfo->image_height=height;
918
919 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
920 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
921 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
922
923 if(flags&TJFLAG_NOREALLOC)
924 {
925 alloc=0; *jpegSize=tjBufSize(width, height, subsamp);
926 }
927 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
928 if(setCompDefaults(cinfo, TJPF_RGB, subsamp, jpegQual, flags)==-1)
929 return -1;
930 cinfo->raw_data_in=TRUE;
931
932 jpeg_start_compress(cinfo, TRUE);
933 for(i=0; i<cinfo->num_components; i++)
934 {
935 jpeg_component_info *compptr=&cinfo->comp_info[i];
936 int ih;
937 iw[i]=compptr->width_in_blocks*DCTSIZE;
938 ih=compptr->height_in_blocks*DCTSIZE;
939 cw[i]=PAD(cinfo->image_width, cinfo->max_h_samp_factor)
940 *compptr->h_samp_factor/cinfo->max_h_samp_factor;
941 ch[i]=PAD(cinfo->image_height, cinfo->max_v_samp_factor)
942 *compptr->v_samp_factor/cinfo->max_v_samp_factor;
943 if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1;
944 th[i]=compptr->v_samp_factor*DCTSIZE;
945 tmpbufsize+=iw[i]*th[i];
946 if((inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL)
947 _throw("tjCompressFromYUV(): Memory allocation failure");
948 for(row=0; row<ch[i]; row++)
949 {
950 inbuf[i][row]=ptr;
951 ptr+=PAD(cw[i], pad);
952 }
953 }
954 if(usetmpbuf)
955 {
956 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
957 _throw("tjCompressFromYUV(): Memory allocation failure");
958 ptr=_tmpbuf;
959 for(i=0; i<cinfo->num_components; i++)
960 {
961 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
962 _throw("tjCompressFromYUV(): Memory allocation failure");
963 for(row=0; row<th[i]; row++)
964 {
965 tmpbuf[i][row]=ptr;
966 ptr+=iw[i];
967 }
968 }
969 }
970
971 for(row=0; row<(int)cinfo->image_height;
972 row+=cinfo->max_v_samp_factor*DCTSIZE)
973 {
974 JSAMPARRAY yuvptr[MAX_COMPONENTS];
975 int crow[MAX_COMPONENTS];
976 for(i=0; i<cinfo->num_components; i++)
977 {
978 jpeg_component_info *compptr=&cinfo->comp_info[i];
979 crow[i]=row*compptr->v_samp_factor/cinfo->max_v_samp_factor;
980 if(usetmpbuf)
981 {
982 int j, k;
983 for(j=0; j<min(th[i], ch[i]-crow[i]); j++)
984 {
985 memcpy(tmpbuf[i][j], inbuf[i][crow[i]+j], cw[i]);
DRC006bc582014-02-27 21:22:54 +0000986 /* Duplicate last sample in row to fill out MCU */
DRC910a3572013-10-30 23:02:57 +0000987 for(k=cw[i]; k<iw[i]; k++) tmpbuf[i][j][k]=tmpbuf[i][j][cw[i]-1];
988 }
DRC006bc582014-02-27 21:22:54 +0000989 /* Duplicate last row to fill out MCU */
DRC910a3572013-10-30 23:02:57 +0000990 for(j=ch[i]-crow[i]; j<th[i]; j++)
991 memcpy(tmpbuf[i][j], tmpbuf[i][ch[i]-crow[i]-1], iw[i]);
992 yuvptr[i]=tmpbuf[i];
993 }
994 else
995 yuvptr[i]=&inbuf[i][crow[i]];
996 }
997 jpeg_write_raw_data(cinfo, yuvptr, cinfo->max_v_samp_factor*DCTSIZE);
998 }
999 jpeg_finish_compress(cinfo);
1000
1001 bailout:
1002 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
1003 for(i=0; i<MAX_COMPONENTS; i++)
1004 {
1005 if(tmpbuf[i]) free(tmpbuf[i]);
1006 if(inbuf[i]) free(inbuf[i]);
1007 }
1008 if(_tmpbuf) free(_tmpbuf);
1009 return retval;
1010}
1011
1012
DRC9b28def2011-05-21 14:37:15 +00001013/* Decompressor */
DRC2e7b76b2009-04-03 12:04:24 +00001014
DRC9b28def2011-05-21 14:37:15 +00001015static tjhandle _tjInitDecompress(tjinstance *this)
DRC2e7b76b2009-04-03 12:04:24 +00001016{
DRC9b28def2011-05-21 14:37:15 +00001017 unsigned char buffer[1];
DRC2e7b76b2009-04-03 12:04:24 +00001018
DRC9b28def2011-05-21 14:37:15 +00001019 /* This is also straight out of example.c */
1020 this->dinfo.err=jpeg_std_error(&this->jerr.pub);
1021 this->jerr.pub.error_exit=my_error_exit;
1022 this->jerr.pub.output_message=my_output_message;
DRC2e7b76b2009-04-03 12:04:24 +00001023
DRC9b28def2011-05-21 14:37:15 +00001024 if(setjmp(this->jerr.setjmp_buffer))
1025 {
1026 /* If we get here, the JPEG code has signaled an error. */
1027 if(this) free(this); return NULL;
DRC9e17f7d2010-12-10 04:59:13 +00001028 }
DRC2e7b76b2009-04-03 12:04:24 +00001029
DRC9b28def2011-05-21 14:37:15 +00001030 jpeg_create_decompress(&this->dinfo);
1031 /* Make an initial call so it will create the source manager */
1032 jpeg_mem_src_tj(&this->dinfo, buffer, 1);
DRC2e7b76b2009-04-03 12:04:24 +00001033
DRC007a42c2011-05-22 13:55:56 +00001034 this->init|=DECOMPRESS;
DRC9b28def2011-05-21 14:37:15 +00001035 return (tjhandle)this;
DRC2e7b76b2009-04-03 12:04:24 +00001036}
1037
DRC890f1e02011-02-26 22:02:37 +00001038DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
1039{
DRC9b28def2011-05-21 14:37:15 +00001040 tjinstance *this;
1041 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
DRCda5220a2011-03-02 02:17:30 +00001042 {
DRC007a42c2011-05-22 13:55:56 +00001043 snprintf(errStr, JMSG_LENGTH_MAX,
1044 "tjInitDecompress(): Memory allocation failure");
DRCda5220a2011-03-02 02:17:30 +00001045 return NULL;
1046 }
DRC007a42c2011-05-22 13:55:56 +00001047 MEMZERO(this, sizeof(tjinstance));
DRC9b28def2011-05-21 14:37:15 +00001048 return _tjInitDecompress(this);
DRC890f1e02011-02-26 22:02:37 +00001049}
1050
DRC2e7b76b2009-04-03 12:04:24 +00001051
DRCcd7c3e62013-08-23 02:49:25 +00001052DLLEXPORT int DLLCALL tjDecompressHeader3(tjhandle handle,
DRC9b28def2011-05-21 14:37:15 +00001053 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
DRCcd7c3e62013-08-23 02:49:25 +00001054 int *jpegSubsamp, int *jpegColorspace)
DRC1fe80f82010-12-14 01:21:29 +00001055{
DRC9b49f0e2011-07-12 03:17:23 +00001056 int retval=0;
DRC1fe80f82010-12-14 01:21:29 +00001057
DRC41861622014-04-16 23:38:37 +00001058 getdinstance(handle);
DRC9b28def2011-05-21 14:37:15 +00001059 if((this->init&DECOMPRESS)==0)
DRCcd7c3e62013-08-23 02:49:25 +00001060 _throw("tjDecompressHeader3(): Instance has not been initialized for decompression");
DRC1fe80f82010-12-14 01:21:29 +00001061
DRC9b28def2011-05-21 14:37:15 +00001062 if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL
DRCcd7c3e62013-08-23 02:49:25 +00001063 || jpegSubsamp==NULL || jpegColorspace==NULL)
1064 _throw("tjDecompressHeader3(): Invalid argument");
DRC1fe80f82010-12-14 01:21:29 +00001065
DRC9b28def2011-05-21 14:37:15 +00001066 if(setjmp(this->jerr.setjmp_buffer))
1067 {
1068 /* If we get here, the JPEG code has signaled an error. */
DRC1fe80f82010-12-14 01:21:29 +00001069 return -1;
1070 }
1071
DRC9b28def2011-05-21 14:37:15 +00001072 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1073 jpeg_read_header(dinfo, TRUE);
DRC1fe80f82010-12-14 01:21:29 +00001074
DRC9b28def2011-05-21 14:37:15 +00001075 *width=dinfo->image_width;
1076 *height=dinfo->image_height;
DRC9b49f0e2011-07-12 03:17:23 +00001077 *jpegSubsamp=getSubsamp(dinfo);
DRCcd7c3e62013-08-23 02:49:25 +00001078 switch(dinfo->jpeg_color_space)
1079 {
1080 case JCS_GRAYSCALE: *jpegColorspace=TJCS_GRAY; break;
1081 case JCS_RGB: *jpegColorspace=TJCS_RGB; break;
1082 case JCS_YCbCr: *jpegColorspace=TJCS_YCbCr; break;
1083 case JCS_CMYK: *jpegColorspace=TJCS_CMYK; break;
1084 case JCS_YCCK: *jpegColorspace=TJCS_YCCK; break;
1085 default: *jpegColorspace=-1; break;
1086 }
DRC1fe80f82010-12-14 01:21:29 +00001087
DRC9b28def2011-05-21 14:37:15 +00001088 jpeg_abort_decompress(dinfo);
DRC1fe80f82010-12-14 01:21:29 +00001089
DRC9b28def2011-05-21 14:37:15 +00001090 if(*jpegSubsamp<0)
DRCcd7c3e62013-08-23 02:49:25 +00001091 _throw("tjDecompressHeader3(): Could not determine subsampling type for JPEG image");
1092 if(*jpegColorspace<0)
1093 _throw("tjDecompressHeader3(): Could not determine colorspace of JPEG image");
DRC007a42c2011-05-22 13:55:56 +00001094 if(*width<1 || *height<1)
DRCcd7c3e62013-08-23 02:49:25 +00001095 _throw("tjDecompressHeader3(): Invalid data returned in header");
DRC91e86ba2011-02-15 05:24:08 +00001096
1097 bailout:
1098 return retval;
1099}
1100
DRCcd7c3e62013-08-23 02:49:25 +00001101DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle,
1102 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
1103 int *jpegSubsamp)
1104{
1105 int jpegColorspace;
1106 return tjDecompressHeader3(handle, jpegBuf, jpegSize, width, height,
1107 jpegSubsamp, &jpegColorspace);
1108}
1109
DRC9b28def2011-05-21 14:37:15 +00001110DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle,
1111 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height)
DRC91e86ba2011-02-15 05:24:08 +00001112{
DRC9b28def2011-05-21 14:37:15 +00001113 int jpegSubsamp;
1114 return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height,
1115 &jpegSubsamp);
DRC1fe80f82010-12-14 01:21:29 +00001116}
1117
1118
DRC109a5782011-03-01 09:53:07 +00001119DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors)
DRCb28fc572011-02-22 06:41:29 +00001120{
DRC109a5782011-03-01 09:53:07 +00001121 if(numscalingfactors==NULL)
DRCb28fc572011-02-22 06:41:29 +00001122 {
DRC9b28def2011-05-21 14:37:15 +00001123 snprintf(errStr, JMSG_LENGTH_MAX,
DRC007a42c2011-05-22 13:55:56 +00001124 "tjGetScalingFactors(): Invalid argument");
DRC109a5782011-03-01 09:53:07 +00001125 return NULL;
DRCb28fc572011-02-22 06:41:29 +00001126 }
1127
DRC109a5782011-03-01 09:53:07 +00001128 *numscalingfactors=NUMSF;
1129 return (tjscalingfactor *)sf;
DRCb28fc572011-02-22 06:41:29 +00001130}
1131
1132
DRC9b28def2011-05-21 14:37:15 +00001133DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, unsigned char *jpegBuf,
1134 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
1135 int height, int pixelFormat, int flags)
DRC2e7b76b2009-04-03 12:04:24 +00001136{
DRC9b28def2011-05-21 14:37:15 +00001137 int i, retval=0; JSAMPROW *row_pointer=NULL;
DRC109a5782011-03-01 09:53:07 +00001138 int jpegwidth, jpegheight, scaledw, scaledh;
DRCafc06922012-03-23 19:47:57 +00001139 #ifndef JCS_EXTENSIONS
1140 unsigned char *rgbBuf=NULL;
1141 unsigned char *_dstBuf=NULL; int _pitch=0;
1142 #endif
DRC2e7b76b2009-04-03 12:04:24 +00001143
DRC41861622014-04-16 23:38:37 +00001144 getdinstance(handle);
DRC9b28def2011-05-21 14:37:15 +00001145 if((this->init&DECOMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +00001146 _throw("tjDecompress2(): Instance has not been initialized for decompression");
DRC9b28def2011-05-21 14:37:15 +00001147
1148 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0
1149 || height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF)
1150 _throw("tjDecompress2(): Invalid argument");
1151
DRC25b995a2011-05-21 15:34:54 +00001152 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1153 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1154 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC9b28def2011-05-21 14:37:15 +00001155
1156 if(setjmp(this->jerr.setjmp_buffer))
1157 {
1158 /* If we get here, the JPEG code has signaled an error. */
1159 retval=-1;
1160 goto bailout;
1161 }
1162
1163 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1164 jpeg_read_header(dinfo, TRUE);
DRC73d74c12012-06-29 23:46:38 +00001165 if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
DRC2eda8212012-03-23 19:32:38 +00001166 {
1167 retval=-1; goto bailout;
1168 }
DRC9b28def2011-05-21 14:37:15 +00001169
DRC25b995a2011-05-21 15:34:54 +00001170 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
DRC9b28def2011-05-21 14:37:15 +00001171
1172 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
1173 if(width==0) width=jpegwidth;
1174 if(height==0) height=jpegheight;
1175 for(i=0; i<NUMSF; i++)
1176 {
1177 scaledw=TJSCALED(jpegwidth, sf[i]);
1178 scaledh=TJSCALED(jpegheight, sf[i]);
1179 if(scaledw<=width && scaledh<=height)
DRCf610d612013-04-26 10:33:29 +00001180 break;
DRC9b28def2011-05-21 14:37:15 +00001181 }
1182 if(scaledw>width || scaledh>height)
DRC007a42c2011-05-22 13:55:56 +00001183 _throw("tjDecompress2(): Could not scale down to desired image dimensions");
DRC9b28def2011-05-21 14:37:15 +00001184 width=scaledw; height=scaledh;
1185 dinfo->scale_num=sf[i].num;
1186 dinfo->scale_denom=sf[i].denom;
1187
1188 jpeg_start_decompress(dinfo);
1189 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
DRCafc06922012-03-23 19:47:57 +00001190
1191 #ifndef JCS_EXTENSIONS
DRC230d09d2014-04-20 09:42:49 +00001192 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK &&
DRCafc06922012-03-23 19:47:57 +00001193 (RGB_RED!=tjRedOffset[pixelFormat] ||
1194 RGB_GREEN!=tjGreenOffset[pixelFormat] ||
1195 RGB_BLUE!=tjBlueOffset[pixelFormat] ||
1196 RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
1197 {
1198 rgbBuf=(unsigned char *)malloc(width*height*3);
1199 if(!rgbBuf) _throw("tjDecompress2(): Memory allocation failure");
1200 _pitch=pitch; pitch=width*3;
1201 _dstBuf=dstBuf; dstBuf=rgbBuf;
1202 }
1203 #endif
1204
DRC9b28def2011-05-21 14:37:15 +00001205 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
1206 *dinfo->output_height))==NULL)
DRC007a42c2011-05-22 13:55:56 +00001207 _throw("tjDecompress2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +00001208 for(i=0; i<(int)dinfo->output_height; i++)
1209 {
DRC25b995a2011-05-21 15:34:54 +00001210 if(flags&TJFLAG_BOTTOMUP)
DRC9b28def2011-05-21 14:37:15 +00001211 row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*pitch];
1212 else row_pointer[i]=&dstBuf[i*pitch];
1213 }
1214 while(dinfo->output_scanline<dinfo->output_height)
1215 {
1216 jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline],
1217 dinfo->output_height-dinfo->output_scanline);
1218 }
1219 jpeg_finish_decompress(dinfo);
1220
DRCafc06922012-03-23 19:47:57 +00001221 #ifndef JCS_EXTENSIONS
1222 fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
1223 #endif
1224
DRC9b28def2011-05-21 14:37:15 +00001225 bailout:
1226 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
DRCafc06922012-03-23 19:47:57 +00001227 #ifndef JCS_EXTENSIONS
DRCea3396a2012-04-26 03:18:49 +00001228 if(rgbBuf) free(rgbBuf);
DRCafc06922012-03-23 19:47:57 +00001229 #endif
DRC9b28def2011-05-21 14:37:15 +00001230 if(row_pointer) free(row_pointer);
1231 return retval;
1232}
1233
1234DLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf,
1235 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
1236 int height, int pixelSize, int flags)
1237{
1238 if(flags&TJ_YUV)
1239 return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags);
1240 else
1241 return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch,
1242 height, getPixelFormat(pixelSize, flags), flags);
1243}
1244
1245
DRC34dca052014-02-28 09:17:14 +00001246static int setDecodeDefaults(struct jpeg_decompress_struct *dinfo,
1247 int pixelFormat, int subsamp, int flags)
1248{
DRC895fd6d2014-02-28 09:35:34 +00001249 int i;
1250
DRC34dca052014-02-28 09:17:14 +00001251 dinfo->scale_num=dinfo->scale_denom=1;
1252
1253 if(subsamp==TJSAMP_GRAY)
1254 {
DRCc9014492014-03-10 09:34:04 +00001255 dinfo->num_components=dinfo->comps_in_scan=1;
DRC34dca052014-02-28 09:17:14 +00001256 dinfo->jpeg_color_space=JCS_GRAYSCALE;
1257 }
1258 else
1259 {
DRCc9014492014-03-10 09:34:04 +00001260 dinfo->num_components=dinfo->comps_in_scan=3;
DRC34dca052014-02-28 09:17:14 +00001261 dinfo->jpeg_color_space=JCS_YCbCr;
1262 }
1263
1264 dinfo->comp_info=(jpeg_component_info *)
1265 (*dinfo->mem->alloc_small)((j_common_ptr)dinfo, JPOOL_IMAGE,
DRC5de454b2014-05-18 19:04:03 +00001266 dinfo->num_components*sizeof(jpeg_component_info));
DRC34dca052014-02-28 09:17:14 +00001267
DRC2bdc0422014-03-07 03:52:57 +00001268 for(i=0; i<dinfo->num_components; i++)
DRC34dca052014-02-28 09:17:14 +00001269 {
DRC2bdc0422014-03-07 03:52:57 +00001270 jpeg_component_info *compptr=&dinfo->comp_info[i];
1271 compptr->h_samp_factor=(i==0)? tjMCUWidth[subsamp]/8:1;
1272 compptr->v_samp_factor=(i==0)? tjMCUHeight[subsamp]/8:1;
1273 compptr->component_index=i;
DRC15c08762014-03-10 20:11:56 +00001274 compptr->component_id=i+1;
DRC2bdc0422014-03-07 03:52:57 +00001275 compptr->quant_tbl_no=compptr->dc_tbl_no=compptr->ac_tbl_no=
1276 (i==0)? 0:1;
1277 dinfo->cur_comp_info[i]=compptr;
DRC34dca052014-02-28 09:17:14 +00001278 }
DRCc9014492014-03-10 09:34:04 +00001279 dinfo->data_precision=8;
1280 for(i=0; i<2; i++)
1281 {
1282 if(dinfo->quant_tbl_ptrs[i]==NULL)
1283 dinfo->quant_tbl_ptrs[i]=jpeg_alloc_quant_table((j_common_ptr)dinfo);
1284 }
DRC34dca052014-02-28 09:17:14 +00001285
1286 return 0;
1287}
1288
1289
1290int my_read_markers(j_decompress_ptr dinfo)
1291{
1292 return JPEG_REACHED_SOS;
1293}
1294
1295void my_reset_marker_reader(j_decompress_ptr dinfo)
1296{
1297}
1298
1299DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, unsigned char *srcBuf,
1300 int pad, int subsamp, unsigned char *dstBuf, int width, int pitch,
1301 int height, int pixelFormat, int flags)
1302{
1303 int i, retval=0; JSAMPROW *row_pointer=NULL;
1304 JSAMPLE *_tmpbuf[MAX_COMPONENTS];
1305 JSAMPROW *tmpbuf[MAX_COMPONENTS], *inbuf[MAX_COMPONENTS];
DRC7d9f7582014-03-10 20:14:53 +00001306 int row, pw, ph, cw[MAX_COMPONENTS], ch[MAX_COMPONENTS];
DRC34dca052014-02-28 09:17:14 +00001307 JSAMPLE *ptr=srcBuf;
1308 unsigned long yuvsize=0;
1309 jpeg_component_info *compptr;
1310 #ifndef JCS_EXTENSIONS
1311 unsigned char *rgbBuf=NULL;
DRC230d09d2014-04-20 09:42:49 +00001312 unsigned char *_dstBuf=NULL; int _pitch=0;
DRC34dca052014-02-28 09:17:14 +00001313 #endif
DRCbc56b752014-05-16 10:43:44 +00001314 int (*old_read_markers)(j_decompress_ptr);
1315 void (*old_reset_marker_reader)(j_decompress_ptr);
DRC34dca052014-02-28 09:17:14 +00001316
DRC41861622014-04-16 23:38:37 +00001317 getdinstance(handle);
DRC34dca052014-02-28 09:17:14 +00001318
1319 for(i=0; i<MAX_COMPONENTS; i++)
1320 {
1321 tmpbuf[i]=NULL; _tmpbuf[i]=NULL; inbuf[i]=NULL;
1322 }
1323
1324 if((this->init&DECOMPRESS)==0)
DRCf57b8a62014-05-06 09:41:08 +00001325 _throw("tjDecodeYUV(): Instance has not been initialized for decompression");
DRC34dca052014-02-28 09:17:14 +00001326
1327 if(srcBuf==NULL || pad<0 || !isPow2(pad) || subsamp<0 || subsamp>=NUMSUBOPT
1328 || dstBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
1329 || pixelFormat>=TJ_NUMPF)
1330 _throw("tjDecodeYUV(): Invalid argument");
1331
1332 if(setjmp(this->jerr.setjmp_buffer))
1333 {
1334 /* If we get here, the JPEG code has signaled an error. */
1335 retval=-1;
1336 goto bailout;
1337 }
1338
1339 if(pixelFormat==TJPF_CMYK)
1340 _throw("tjDecodeYUV(): Cannot decode YUV images into CMYK pixels.");
1341
1342 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
DRC34dca052014-02-28 09:17:14 +00001343 dinfo->image_width=width;
1344 dinfo->image_height=height;
1345
1346 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1347 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1348 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
1349
1350 yuvsize=tjBufSizeYUV2(width, pad, height, subsamp);
1351 if(setDecodeDefaults(dinfo, pixelFormat, subsamp, flags)==-1)
1352 {
1353 retval=-1; goto bailout;
1354 }
1355 old_read_markers=dinfo->marker->read_markers;
1356 dinfo->marker->read_markers=my_read_markers;
1357 old_reset_marker_reader=dinfo->marker->reset_marker_reader;
1358 dinfo->marker->reset_marker_reader=my_reset_marker_reader;
1359 jpeg_read_header(dinfo, TRUE);
1360 dinfo->marker->read_markers=old_read_markers;
1361 dinfo->marker->reset_marker_reader=old_reset_marker_reader;
1362
1363 if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
1364 {
1365 retval=-1; goto bailout;
1366 }
DRC7d9f7582014-03-10 20:14:53 +00001367 dinfo->do_fancy_upsampling=FALSE;
DRC2bdc0422014-03-07 03:52:57 +00001368 jinit_master_decompress(dinfo);
DRC34dca052014-02-28 09:17:14 +00001369 (*dinfo->upsample->start_pass)(dinfo);
1370
1371 pw=PAD(width, dinfo->max_h_samp_factor);
1372 ph=PAD(height, dinfo->max_v_samp_factor);
1373
1374 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
1375
DRC230d09d2014-04-20 09:42:49 +00001376 #ifndef JCS_EXTENSIONS
1377 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK &&
1378 (RGB_RED!=tjRedOffset[pixelFormat] ||
1379 RGB_GREEN!=tjGreenOffset[pixelFormat] ||
1380 RGB_BLUE!=tjBlueOffset[pixelFormat] ||
1381 RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
1382 {
1383 rgbBuf=(unsigned char *)malloc(width*height*3);
1384 if(!rgbBuf) _throw("tjDecodeYUV(): Memory allocation failure");
1385 _pitch=pitch; pitch=width*3;
1386 _dstBuf=dstBuf; dstBuf=rgbBuf;
1387 }
1388 #endif
1389
DRC34dca052014-02-28 09:17:14 +00001390 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph))==NULL)
1391 _throw("tjDecodeYUV(): Memory allocation failure");
1392 for(i=0; i<height; i++)
1393 {
1394 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&dstBuf[(height-i-1)*pitch];
1395 else row_pointer[i]=&dstBuf[i*pitch];
1396 }
1397 if(height<ph)
1398 for(i=height; i<ph; i++) row_pointer[i]=row_pointer[height-1];
1399
1400 for(i=0; i<dinfo->num_components; i++)
1401 {
1402 compptr=&dinfo->comp_info[i];
1403 _tmpbuf[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
1404 * compptr->v_samp_factor + 16);
1405 if(!_tmpbuf[i]) _throw("tjDecodeYUV(): Memory allocation failure");
1406 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
1407 if(!tmpbuf[i]) _throw("tjDecodeYUV(): Memory allocation failure");
1408 for(row=0; row<compptr->v_samp_factor; row++)
1409 {
1410 unsigned char *_tmpbuf_aligned=
1411 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
1412 tmpbuf[i][row]=&_tmpbuf_aligned[
1413 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
1414 }
1415 cw[i]=pw*compptr->h_samp_factor/dinfo->max_h_samp_factor;
1416 ch[i]=ph*compptr->v_samp_factor/dinfo->max_v_samp_factor;
1417 inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]);
1418 if(!inbuf[i]) _throw("tjDecodeYUV(): Memory allocation failure");
1419 for(row=0; row<ch[i]; row++)
1420 {
1421 inbuf[i][row]=ptr;
1422 ptr+=PAD(cw[i], pad);
1423 }
1424 }
1425
1426 if(yuvsize!=(unsigned long)(ptr-srcBuf))
1427 _throw("tjDecodeYUV(): YUV image is not the correct size");
1428
1429 for(row=0; row<ph; row+=dinfo->max_v_samp_factor)
1430 {
1431 JDIMENSION inrow=0, outrow=0;
1432 for(i=0, compptr=dinfo->comp_info; i<dinfo->num_components; i++, compptr++)
1433 jcopy_sample_rows(inbuf[i],
1434 row*compptr->v_samp_factor/dinfo->max_v_samp_factor, tmpbuf[i], 0,
1435 compptr->v_samp_factor, cw[i]);
1436 (dinfo->upsample->upsample)(dinfo, tmpbuf, &inrow,
1437 dinfo->max_v_samp_factor, &row_pointer[row], &outrow,
1438 dinfo->max_v_samp_factor);
1439 }
1440 jpeg_abort_decompress(dinfo);
1441
DRC230d09d2014-04-20 09:42:49 +00001442 #ifndef JCS_EXTENSIONS
1443 fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
1444 #endif
1445
DRC34dca052014-02-28 09:17:14 +00001446 bailout:
1447 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
1448 #ifndef JCS_EXTENSIONS
1449 if(rgbBuf) free(rgbBuf);
1450 #endif
1451 if(row_pointer) free(row_pointer);
1452 for(i=0; i<MAX_COMPONENTS; i++)
1453 {
1454 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
1455 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
1456 if(inbuf[i]!=NULL) free(inbuf[i]);
1457 }
1458 return retval;
1459}
1460
1461
DRCf610d612013-04-26 10:33:29 +00001462DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle,
DRC9b28def2011-05-21 14:37:15 +00001463 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
DRCf610d612013-04-26 10:33:29 +00001464 int width, int pad, int height, int flags)
DRC9b28def2011-05-21 14:37:15 +00001465{
DRCf610d612013-04-26 10:33:29 +00001466 int i, sfi, row, retval=0; JSAMPROW *outbuf[MAX_COMPONENTS];
DRC418fe282013-05-07 21:17:35 +00001467 int jpegwidth, jpegheight, jpegSubsamp, scaledw, scaledh;
DRC9b28def2011-05-21 14:37:15 +00001468 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS],
1469 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
1470 JSAMPLE *_tmpbuf=NULL, *ptr=dstBuf; JSAMPROW *tmpbuf[MAX_COMPONENTS];
DRC418fe282013-05-07 21:17:35 +00001471 int dctsize;
DRC9b28def2011-05-21 14:37:15 +00001472
DRC41861622014-04-16 23:38:37 +00001473 getdinstance(handle);
DRCb51ee892013-10-31 05:00:19 +00001474
DRCf9cf5c72010-12-10 10:58:49 +00001475 for(i=0; i<MAX_COMPONENTS; i++)
1476 {
1477 tmpbuf[i]=NULL; outbuf[i]=NULL;
1478 }
DRC9e17f7d2010-12-10 04:59:13 +00001479
DRCe2f8e692013-10-30 22:21:06 +00001480 if((this->init&DECOMPRESS)==0)
1481 _throw("tjDecompressToYUV2(): Instance has not been initialized for decompression");
1482
DRCf610d612013-04-26 10:33:29 +00001483 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pad<1
1484 || !isPow2(pad) || height<0)
1485 _throw("tjDecompressToYUV2(): Invalid argument");
DRC2e7b76b2009-04-03 12:04:24 +00001486
DRC25b995a2011-05-21 15:34:54 +00001487 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1488 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1489 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC0c6a2712010-02-22 08:34:44 +00001490
DRC9b28def2011-05-21 14:37:15 +00001491 if(setjmp(this->jerr.setjmp_buffer))
1492 {
1493 /* If we get here, the JPEG code has signaled an error. */
DRC91e86ba2011-02-15 05:24:08 +00001494 retval=-1;
1495 goto bailout;
DRC9e17f7d2010-12-10 04:59:13 +00001496 }
DRC2e7b76b2009-04-03 12:04:24 +00001497
DRC9b28def2011-05-21 14:37:15 +00001498 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1499 jpeg_read_header(dinfo, TRUE);
DRC418fe282013-05-07 21:17:35 +00001500 jpegSubsamp=getSubsamp(dinfo);
1501 if(jpegSubsamp<0)
DRC910a3572013-10-30 23:02:57 +00001502 _throw("tjDecompressToYUV2(): Could not determine subsampling type for JPEG image");
DRC2e7b76b2009-04-03 12:04:24 +00001503
DRCf610d612013-04-26 10:33:29 +00001504 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
1505 if(width==0) width=jpegwidth;
1506 if(height==0) height=jpegheight;
1507 for(i=0; i<NUMSF; i++)
1508 {
1509 scaledw=TJSCALED(jpegwidth, sf[i]);
1510 scaledh=TJSCALED(jpegheight, sf[i]);
1511 if(scaledw<=width && scaledh<=height)
1512 break;
1513 }
1514 if(scaledw>width || scaledh>height)
1515 _throw("tjDecompressToYUV2(): Could not scale down to desired image dimensions");
DRCcd7c3e62013-08-23 02:49:25 +00001516 if(dinfo->num_components>3)
1517 _throw("tjDecompressToYUV2(): JPEG image must have 3 or fewer components");
1518
DRCf610d612013-04-26 10:33:29 +00001519 width=scaledw; height=scaledh;
1520 dinfo->scale_num=sf[i].num;
1521 dinfo->scale_denom=sf[i].denom;
1522 sfi=i;
1523 jpeg_calc_output_dimensions(dinfo);
1524
DRC418fe282013-05-07 21:17:35 +00001525 dctsize=DCTSIZE*sf[sfi].num/sf[sfi].denom;
1526
DRC9b28def2011-05-21 14:37:15 +00001527 for(i=0; i<dinfo->num_components; i++)
DRC2e7b76b2009-04-03 12:04:24 +00001528 {
DRC9b28def2011-05-21 14:37:15 +00001529 jpeg_component_info *compptr=&dinfo->comp_info[i];
1530 int ih;
DRC418fe282013-05-07 21:17:35 +00001531 iw[i]=compptr->width_in_blocks*dctsize;
1532 ih=compptr->height_in_blocks*dctsize;
DRCf610d612013-04-26 10:33:29 +00001533 cw[i]=PAD(dinfo->output_width, dinfo->max_h_samp_factor)
DRC9b28def2011-05-21 14:37:15 +00001534 *compptr->h_samp_factor/dinfo->max_h_samp_factor;
DRCf610d612013-04-26 10:33:29 +00001535 ch[i]=PAD(dinfo->output_height, dinfo->max_v_samp_factor)
DRC9b28def2011-05-21 14:37:15 +00001536 *compptr->v_samp_factor/dinfo->max_v_samp_factor;
1537 if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1;
DRC418fe282013-05-07 21:17:35 +00001538 th[i]=compptr->v_samp_factor*dctsize;
DRC9b28def2011-05-21 14:37:15 +00001539 tmpbufsize+=iw[i]*th[i];
1540 if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL)
DRCf610d612013-04-26 10:33:29 +00001541 _throw("tjDecompressToYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +00001542 for(row=0; row<ch[i]; row++)
1543 {
1544 outbuf[i][row]=ptr;
DRCf610d612013-04-26 10:33:29 +00001545 ptr+=PAD(cw[i], pad);
DRC9b28def2011-05-21 14:37:15 +00001546 }
1547 }
1548 if(usetmpbuf)
1549 {
1550 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
DRCf610d612013-04-26 10:33:29 +00001551 _throw("tjDecompressToYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +00001552 ptr=_tmpbuf;
1553 for(i=0; i<dinfo->num_components; i++)
1554 {
1555 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
DRCf610d612013-04-26 10:33:29 +00001556 _throw("tjDecompressToYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +00001557 for(row=0; row<th[i]; row++)
1558 {
1559 tmpbuf[i][row]=ptr;
1560 ptr+=iw[i];
1561 }
1562 }
1563 }
DRC9e17f7d2010-12-10 04:59:13 +00001564
DRC25b995a2011-05-21 15:34:54 +00001565 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
DRCe0419b52012-07-03 20:01:31 +00001566 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
DRC9b28def2011-05-21 14:37:15 +00001567 dinfo->raw_data_out=TRUE;
1568
1569 jpeg_start_decompress(dinfo);
1570 for(row=0; row<(int)dinfo->output_height;
DRC418fe282013-05-07 21:17:35 +00001571 row+=dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size)
DRC9b28def2011-05-21 14:37:15 +00001572 {
1573 JSAMPARRAY yuvptr[MAX_COMPONENTS];
1574 int crow[MAX_COMPONENTS];
DRC9e17f7d2010-12-10 04:59:13 +00001575 for(i=0; i<dinfo->num_components; i++)
1576 {
1577 jpeg_component_info *compptr=&dinfo->comp_info[i];
DRC418fe282013-05-07 21:17:35 +00001578 if(jpegSubsamp==TJ_420)
1579 {
1580 /* When 4:2:0 subsampling is used with IDCT scaling, libjpeg will try
1581 to be clever and use the IDCT to perform upsampling on the U and V
1582 planes. For instance, if the output image is to be scaled by 1/2
1583 relative to the JPEG image, then the scaling factor and upsampling
1584 effectively cancel each other, so a normal 8x8 IDCT can be used.
1585 However, this is not desirable when using the decompress-to-YUV
1586 functionality in TurboJPEG, since we want to output the U and V
1587 planes in their subsampled form. Thus, we have to override some
1588 internal libjpeg parameters to force it to use the "scaled" IDCT
1589 functions on the U and V planes. */
1590 compptr->_DCT_scaled_size=dctsize;
1591 compptr->MCU_sample_width=tjMCUWidth[jpegSubsamp]*
1592 sf[sfi].num/sf[sfi].denom*
1593 compptr->v_samp_factor/dinfo->max_v_samp_factor;
1594 dinfo->idct->inverse_DCT[i] = dinfo->idct->inverse_DCT[0];
1595 }
DRC9b28def2011-05-21 14:37:15 +00001596 crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
1597 if(usetmpbuf) yuvptr[i]=tmpbuf[i];
1598 else yuvptr[i]=&outbuf[i][crow[i]];
DRCf9cf5c72010-12-10 10:58:49 +00001599 }
DRCf610d612013-04-26 10:33:29 +00001600 jpeg_read_raw_data(dinfo, yuvptr,
DRC418fe282013-05-07 21:17:35 +00001601 dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size);
DRCf9cf5c72010-12-10 10:58:49 +00001602 if(usetmpbuf)
1603 {
DRC9b28def2011-05-21 14:37:15 +00001604 int j;
DRCf9cf5c72010-12-10 10:58:49 +00001605 for(i=0; i<dinfo->num_components; i++)
1606 {
DRC9b28def2011-05-21 14:37:15 +00001607 for(j=0; j<min(th[i], ch[i]-crow[i]); j++)
DRCf9cf5c72010-12-10 10:58:49 +00001608 {
DRC9b28def2011-05-21 14:37:15 +00001609 memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], cw[i]);
DRCf9cf5c72010-12-10 10:58:49 +00001610 }
DRC9e17f7d2010-12-10 04:59:13 +00001611 }
1612 }
1613 }
DRC9b28def2011-05-21 14:37:15 +00001614 jpeg_finish_decompress(dinfo);
DRC2e7b76b2009-04-03 12:04:24 +00001615
DRC91e86ba2011-02-15 05:24:08 +00001616 bailout:
DRC9b28def2011-05-21 14:37:15 +00001617 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
DRC9e17f7d2010-12-10 04:59:13 +00001618 for(i=0; i<MAX_COMPONENTS; i++)
DRCf9cf5c72010-12-10 10:58:49 +00001619 {
1620 if(tmpbuf[i]) free(tmpbuf[i]);
DRC9e17f7d2010-12-10 04:59:13 +00001621 if(outbuf[i]) free(outbuf[i]);
DRCf9cf5c72010-12-10 10:58:49 +00001622 }
1623 if(_tmpbuf) free(_tmpbuf);
DRC91e86ba2011-02-15 05:24:08 +00001624 return retval;
DRC2e7b76b2009-04-03 12:04:24 +00001625}
1626
DRCf610d612013-04-26 10:33:29 +00001627DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle,
1628 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
1629 int flags)
1630{
1631 return tjDecompressToYUV2(handle, jpegBuf, jpegSize, dstBuf, 0, 4, 0, flags);
1632}
1633
DRC2e7b76b2009-04-03 12:04:24 +00001634
DRC9b28def2011-05-21 14:37:15 +00001635/* Transformer */
DRC890f1e02011-02-26 22:02:37 +00001636
1637DLLEXPORT tjhandle DLLCALL tjInitTransform(void)
1638{
DRC9b28def2011-05-21 14:37:15 +00001639 tjinstance *this=NULL; tjhandle handle=NULL;
1640 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
DRCda5220a2011-03-02 02:17:30 +00001641 {
DRC007a42c2011-05-22 13:55:56 +00001642 snprintf(errStr, JMSG_LENGTH_MAX,
1643 "tjInitTransform(): Memory allocation failure");
DRCda5220a2011-03-02 02:17:30 +00001644 return NULL;
1645 }
DRC007a42c2011-05-22 13:55:56 +00001646 MEMZERO(this, sizeof(tjinstance));
DRC9b28def2011-05-21 14:37:15 +00001647 handle=_tjInitCompress(this);
1648 if(!handle) return NULL;
1649 handle=_tjInitDecompress(this);
1650 return handle;
DRC890f1e02011-02-26 22:02:37 +00001651}
1652
1653
DRC9b28def2011-05-21 14:37:15 +00001654DLLEXPORT int DLLCALL tjTransform(tjhandle handle, unsigned char *jpegBuf,
1655 unsigned long jpegSize, int n, unsigned char **dstBufs,
1656 unsigned long *dstSizes, tjtransform *t, int flags)
DRC890f1e02011-02-26 22:02:37 +00001657{
DRC0a325192011-03-02 09:22:41 +00001658 jpeg_transform_info *xinfo=NULL;
DRC890f1e02011-02-26 22:02:37 +00001659 jvirt_barray_ptr *srccoefs, *dstcoefs;
DRC9b49f0e2011-07-12 03:17:23 +00001660 int retval=0, i, jpegSubsamp;
DRC890f1e02011-02-26 22:02:37 +00001661
DRC9b28def2011-05-21 14:37:15 +00001662 getinstance(handle);
1663 if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +00001664 _throw("tjTransform(): Instance has not been initialized for transformation");
DRC890f1e02011-02-26 22:02:37 +00001665
DRC9b28def2011-05-21 14:37:15 +00001666 if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL
1667 || t==NULL || flags<0)
1668 _throw("tjTransform(): Invalid argument");
1669
DRC25b995a2011-05-21 15:34:54 +00001670 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1671 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1672 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC890f1e02011-02-26 22:02:37 +00001673
DRC9b28def2011-05-21 14:37:15 +00001674 if(setjmp(this->jerr.setjmp_buffer))
1675 {
1676 /* If we get here, the JPEG code has signaled an error. */
DRC890f1e02011-02-26 22:02:37 +00001677 retval=-1;
1678 goto bailout;
1679 }
1680
DRC9b28def2011-05-21 14:37:15 +00001681 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
DRC890f1e02011-02-26 22:02:37 +00001682
DRC0a325192011-03-02 09:22:41 +00001683 if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n))
1684 ==NULL)
DRC007a42c2011-05-22 13:55:56 +00001685 _throw("tjTransform(): Memory allocation failure");
1686 MEMZERO(xinfo, sizeof(jpeg_transform_info)*n);
DRC890f1e02011-02-26 22:02:37 +00001687
DRC0a325192011-03-02 09:22:41 +00001688 for(i=0; i<n; i++)
DRC890f1e02011-02-26 22:02:37 +00001689 {
DRC0a325192011-03-02 09:22:41 +00001690 xinfo[i].transform=xformtypes[t[i].op];
DRC25b995a2011-05-21 15:34:54 +00001691 xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0;
1692 xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0;
1693 xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0;
1694 xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0;
1695 if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1;
DRCba5ea512011-03-04 03:20:34 +00001696 else xinfo[i].slow_hflip=0;
DRC0a325192011-03-02 09:22:41 +00001697
1698 if(xinfo[i].crop)
DRC890f1e02011-02-26 22:02:37 +00001699 {
DRC0a325192011-03-02 09:22:41 +00001700 xinfo[i].crop_xoffset=t[i].r.x; xinfo[i].crop_xoffset_set=JCROP_POS;
1701 xinfo[i].crop_yoffset=t[i].r.y; xinfo[i].crop_yoffset_set=JCROP_POS;
1702 if(t[i].r.w!=0)
1703 {
1704 xinfo[i].crop_width=t[i].r.w; xinfo[i].crop_width_set=JCROP_POS;
1705 }
DRCd932e582011-03-15 20:09:47 +00001706 else xinfo[i].crop_width=JCROP_UNSET;
DRC0a325192011-03-02 09:22:41 +00001707 if(t[i].r.h!=0)
1708 {
1709 xinfo[i].crop_height=t[i].r.h; xinfo[i].crop_height_set=JCROP_POS;
1710 }
DRCd932e582011-03-15 20:09:47 +00001711 else xinfo[i].crop_height=JCROP_UNSET;
DRC890f1e02011-02-26 22:02:37 +00001712 }
1713 }
1714
DRC9b28def2011-05-21 14:37:15 +00001715 jcopy_markers_setup(dinfo, JCOPYOPT_ALL);
1716 jpeg_read_header(dinfo, TRUE);
DRC9b49f0e2011-07-12 03:17:23 +00001717 jpegSubsamp=getSubsamp(dinfo);
1718 if(jpegSubsamp<0)
1719 _throw("tjTransform(): Could not determine subsampling type for JPEG image");
DRC890f1e02011-02-26 22:02:37 +00001720
DRC0a325192011-03-02 09:22:41 +00001721 for(i=0; i<n; i++)
DRC890f1e02011-02-26 22:02:37 +00001722 {
DRC9b28def2011-05-21 14:37:15 +00001723 if(!jtransform_request_workspace(dinfo, &xinfo[i]))
DRC007a42c2011-05-22 13:55:56 +00001724 _throw("tjTransform(): Transform is not perfect");
DRC890f1e02011-02-26 22:02:37 +00001725
DRC0a325192011-03-02 09:22:41 +00001726 if(xinfo[i].crop)
DRC890f1e02011-02-26 22:02:37 +00001727 {
DRC0a325192011-03-02 09:22:41 +00001728 if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0
1729 || (t[i].r.y%xinfo[i].iMCU_sample_height)!=0)
1730 {
DRC9b28def2011-05-21 14:37:15 +00001731 snprintf(errStr, JMSG_LENGTH_MAX,
DRC0a325192011-03-02 09:22:41 +00001732 "To crop this JPEG image, x must be a multiple of %d\n"
1733 "and y must be a multiple of %d.\n",
1734 xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height);
1735 retval=-1; goto bailout;
1736 }
DRC890f1e02011-02-26 22:02:37 +00001737 }
1738 }
1739
DRC9b28def2011-05-21 14:37:15 +00001740 srccoefs=jpeg_read_coefficients(dinfo);
DRC890f1e02011-02-26 22:02:37 +00001741
DRC0a325192011-03-02 09:22:41 +00001742 for(i=0; i<n; i++)
1743 {
DRCff78e372011-05-24 10:17:32 +00001744 int w, h, alloc=1;
DRC0a325192011-03-02 09:22:41 +00001745 if(!xinfo[i].crop)
1746 {
DRC9b28def2011-05-21 14:37:15 +00001747 w=dinfo->image_width; h=dinfo->image_height;
DRC0a325192011-03-02 09:22:41 +00001748 }
1749 else
1750 {
1751 w=xinfo[i].crop_width; h=xinfo[i].crop_height;
1752 }
DRCff78e372011-05-24 10:17:32 +00001753 if(flags&TJFLAG_NOREALLOC)
1754 {
DRC9b49f0e2011-07-12 03:17:23 +00001755 alloc=0; dstSizes[i]=tjBufSize(w, h, jpegSubsamp);
DRCff78e372011-05-24 10:17:32 +00001756 }
DRC7bf04d32011-09-17 00:18:31 +00001757 if(!(t[i].options&TJXOPT_NOOUTPUT))
1758 jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc);
DRC9b28def2011-05-21 14:37:15 +00001759 jpeg_copy_critical_parameters(dinfo, cinfo);
1760 dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs,
DRC0a325192011-03-02 09:22:41 +00001761 &xinfo[i]);
DRC7bf04d32011-09-17 00:18:31 +00001762 if(!(t[i].options&TJXOPT_NOOUTPUT))
1763 {
1764 jpeg_write_coefficients(cinfo, dstcoefs);
1765 jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL);
1766 }
1767 else jinit_c_master_control(cinfo, TRUE);
DRC9b28def2011-05-21 14:37:15 +00001768 jtransform_execute_transformation(dinfo, cinfo, srccoefs,
DRC0a325192011-03-02 09:22:41 +00001769 &xinfo[i]);
DRC7bf04d32011-09-17 00:18:31 +00001770 if(t[i].customFilter)
1771 {
DRCefe28ce2012-01-17 11:48:38 +00001772 int ci, y; JDIMENSION by;
DRC7bf04d32011-09-17 00:18:31 +00001773 for(ci=0; ci<cinfo->num_components; ci++)
1774 {
1775 jpeg_component_info *compptr=&cinfo->comp_info[ci];
1776 tjregion arrayRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
1777 DCTSIZE};
1778 tjregion planeRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
1779 compptr->height_in_blocks*DCTSIZE};
1780 for(by=0; by<compptr->height_in_blocks; by+=compptr->v_samp_factor)
1781 {
1782 JBLOCKARRAY barray=(dinfo->mem->access_virt_barray)
1783 ((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor,
1784 TRUE);
1785 for(y=0; y<compptr->v_samp_factor; y++)
1786 {
1787 if(t[i].customFilter(barray[y][0], arrayRegion, planeRegion,
DRCf5467112011-09-20 05:02:19 +00001788 ci, i, &t[i])==-1)
DRC7bf04d32011-09-17 00:18:31 +00001789 _throw("tjTransform(): Error in custom filter");
1790 arrayRegion.y+=DCTSIZE;
1791 }
1792 }
1793 }
1794 }
1795 if(!(t[i].options&TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo);
DRC0a325192011-03-02 09:22:41 +00001796 }
1797
DRC9b28def2011-05-21 14:37:15 +00001798 jpeg_finish_decompress(dinfo);
DRC890f1e02011-02-26 22:02:37 +00001799
DRC890f1e02011-02-26 22:02:37 +00001800 bailout:
DRC9b28def2011-05-21 14:37:15 +00001801 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
1802 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
DRC0a325192011-03-02 09:22:41 +00001803 if(xinfo) free(xinfo);
DRC890f1e02011-02-26 22:02:37 +00001804 return retval;
1805}