blob: 5aee2e816c0784a36943e5826682407de546cd1a [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;
DRC2e7b76b2009-04-03 12:04:24 +0000125
DRC9b28def2011-05-21 14:37:15 +0000126static int getPixelFormat(int pixelSize, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000127{
DRC25b995a2011-05-21 15:34:54 +0000128 if(pixelSize==1) return TJPF_GRAY;
DRC9b28def2011-05-21 14:37:15 +0000129 if(pixelSize==3)
130 {
DRC25b995a2011-05-21 15:34:54 +0000131 if(flags&TJ_BGR) return TJPF_BGR;
132 else return TJPF_RGB;
DRC9b28def2011-05-21 14:37:15 +0000133 }
134 if(pixelSize==4)
135 {
136 if(flags&TJ_ALPHAFIRST)
137 {
DRC25b995a2011-05-21 15:34:54 +0000138 if(flags&TJ_BGR) return TJPF_XBGR;
139 else return TJPF_XRGB;
DRC9b28def2011-05-21 14:37:15 +0000140 }
141 else
142 {
DRC25b995a2011-05-21 15:34:54 +0000143 if(flags&TJ_BGR) return TJPF_BGRX;
144 else return TJPF_RGBX;
DRC9b28def2011-05-21 14:37:15 +0000145 }
146 }
147 return -1;
DRC2e7b76b2009-04-03 12:04:24 +0000148}
149
DRCf12bb302011-09-07 05:03:18 +0000150static int setCompDefaults(struct jpeg_compress_struct *cinfo,
DRC73d74c12012-06-29 23:46:38 +0000151 int pixelFormat, int subsamp, int jpegQual, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000152{
DRCf12bb302011-09-07 05:03:18 +0000153 int retval=0;
154
DRC9b28def2011-05-21 14:37:15 +0000155 switch(pixelFormat)
156 {
DRC25b995a2011-05-21 15:34:54 +0000157 case TJPF_GRAY:
DRC9b28def2011-05-21 14:37:15 +0000158 cinfo->in_color_space=JCS_GRAYSCALE; break;
159 #if JCS_EXTENSIONS==1
DRC25b995a2011-05-21 15:34:54 +0000160 case TJPF_RGB:
DRC9b28def2011-05-21 14:37:15 +0000161 cinfo->in_color_space=JCS_EXT_RGB; break;
DRC25b995a2011-05-21 15:34:54 +0000162 case TJPF_BGR:
DRC9b28def2011-05-21 14:37:15 +0000163 cinfo->in_color_space=JCS_EXT_BGR; break;
DRC25b995a2011-05-21 15:34:54 +0000164 case TJPF_RGBX:
DRC67ce3b22011-12-19 02:21:03 +0000165 case TJPF_RGBA:
DRC9b28def2011-05-21 14:37:15 +0000166 cinfo->in_color_space=JCS_EXT_RGBX; break;
DRC25b995a2011-05-21 15:34:54 +0000167 case TJPF_BGRX:
DRC67ce3b22011-12-19 02:21:03 +0000168 case TJPF_BGRA:
DRC9b28def2011-05-21 14:37:15 +0000169 cinfo->in_color_space=JCS_EXT_BGRX; break;
DRC25b995a2011-05-21 15:34:54 +0000170 case TJPF_XRGB:
DRC67ce3b22011-12-19 02:21:03 +0000171 case TJPF_ARGB:
DRC9b28def2011-05-21 14:37:15 +0000172 cinfo->in_color_space=JCS_EXT_XRGB; break;
DRC25b995a2011-05-21 15:34:54 +0000173 case TJPF_XBGR:
DRC67ce3b22011-12-19 02:21:03 +0000174 case TJPF_ABGR:
DRC9b28def2011-05-21 14:37:15 +0000175 cinfo->in_color_space=JCS_EXT_XBGR; break;
176 #else
DRC25b995a2011-05-21 15:34:54 +0000177 case TJPF_RGB:
DRCafc06922012-03-23 19:47:57 +0000178 case TJPF_BGR:
179 case TJPF_RGBX:
180 case TJPF_BGRX:
181 case TJPF_XRGB:
182 case TJPF_XBGR:
183 case TJPF_RGBA:
184 case TJPF_BGRA:
185 case TJPF_ARGB:
186 case TJPF_ABGR:
187 cinfo->in_color_space=JCS_RGB; pixelFormat=TJPF_RGB;
188 break;
DRC9b28def2011-05-21 14:37:15 +0000189 #endif
DRCcd7c3e62013-08-23 02:49:25 +0000190 case TJPF_CMYK:
191 cinfo->in_color_space=JCS_CMYK; break;
DRCefa4ddc2010-10-13 19:22:50 +0000192 }
DRC2e7b76b2009-04-03 12:04:24 +0000193
DRC9b28def2011-05-21 14:37:15 +0000194 cinfo->input_components=tjPixelSize[pixelFormat];
195 jpeg_set_defaults(cinfo);
196 if(jpegQual>=0)
197 {
198 jpeg_set_quality(cinfo, jpegQual, TRUE);
DRC73d74c12012-06-29 23:46:38 +0000199 if(jpegQual>=96 || flags&TJFLAG_ACCURATEDCT) cinfo->dct_method=JDCT_ISLOW;
DRC9b28def2011-05-21 14:37:15 +0000200 else cinfo->dct_method=JDCT_FASTEST;
201 }
DRC25b995a2011-05-21 15:34:54 +0000202 if(subsamp==TJSAMP_GRAY)
DRC9b28def2011-05-21 14:37:15 +0000203 jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
DRCcd7c3e62013-08-23 02:49:25 +0000204 else if(pixelFormat==TJPF_CMYK)
205 jpeg_set_colorspace(cinfo, JCS_YCCK);
206 else jpeg_set_colorspace(cinfo, JCS_YCbCr);
DRC2e7b76b2009-04-03 12:04:24 +0000207
DRC9b28def2011-05-21 14:37:15 +0000208 cinfo->comp_info[0].h_samp_factor=tjMCUWidth[subsamp]/8;
209 cinfo->comp_info[1].h_samp_factor=1;
210 cinfo->comp_info[2].h_samp_factor=1;
DRCcd7c3e62013-08-23 02:49:25 +0000211 if(cinfo->num_components>3)
212 cinfo->comp_info[3].h_samp_factor=tjMCUWidth[subsamp]/8;
DRC9b28def2011-05-21 14:37:15 +0000213 cinfo->comp_info[0].v_samp_factor=tjMCUHeight[subsamp]/8;
214 cinfo->comp_info[1].v_samp_factor=1;
215 cinfo->comp_info[2].v_samp_factor=1;
DRCcd7c3e62013-08-23 02:49:25 +0000216 if(cinfo->num_components>3)
217 cinfo->comp_info[3].v_samp_factor=tjMCUHeight[subsamp]/8;
DRCf12bb302011-09-07 05:03:18 +0000218
DRCf12bb302011-09-07 05:03:18 +0000219 return retval;
DRC9b28def2011-05-21 14:37:15 +0000220}
221
DRCf12bb302011-09-07 05:03:18 +0000222static int setDecompDefaults(struct jpeg_decompress_struct *dinfo,
DRC73d74c12012-06-29 23:46:38 +0000223 int pixelFormat, int flags)
DRC9b28def2011-05-21 14:37:15 +0000224{
DRCf12bb302011-09-07 05:03:18 +0000225 int retval=0;
226
DRC9b28def2011-05-21 14:37:15 +0000227 switch(pixelFormat)
228 {
DRC25b995a2011-05-21 15:34:54 +0000229 case TJPF_GRAY:
DRC9b28def2011-05-21 14:37:15 +0000230 dinfo->out_color_space=JCS_GRAYSCALE; break;
231 #if JCS_EXTENSIONS==1
DRC25b995a2011-05-21 15:34:54 +0000232 case TJPF_RGB:
DRC9b28def2011-05-21 14:37:15 +0000233 dinfo->out_color_space=JCS_EXT_RGB; break;
DRC25b995a2011-05-21 15:34:54 +0000234 case TJPF_BGR:
DRC9b28def2011-05-21 14:37:15 +0000235 dinfo->out_color_space=JCS_EXT_BGR; break;
DRC25b995a2011-05-21 15:34:54 +0000236 case TJPF_RGBX:
DRC9b28def2011-05-21 14:37:15 +0000237 dinfo->out_color_space=JCS_EXT_RGBX; break;
DRC25b995a2011-05-21 15:34:54 +0000238 case TJPF_BGRX:
DRC9b28def2011-05-21 14:37:15 +0000239 dinfo->out_color_space=JCS_EXT_BGRX; break;
DRC25b995a2011-05-21 15:34:54 +0000240 case TJPF_XRGB:
DRC9b28def2011-05-21 14:37:15 +0000241 dinfo->out_color_space=JCS_EXT_XRGB; break;
DRC25b995a2011-05-21 15:34:54 +0000242 case TJPF_XBGR:
DRC9b28def2011-05-21 14:37:15 +0000243 dinfo->out_color_space=JCS_EXT_XBGR; break;
DRC67ce3b22011-12-19 02:21:03 +0000244 #if JCS_ALPHA_EXTENSIONS==1
245 case TJPF_RGBA:
246 dinfo->out_color_space=JCS_EXT_RGBA; break;
247 case TJPF_BGRA:
248 dinfo->out_color_space=JCS_EXT_BGRA; break;
249 case TJPF_ARGB:
250 dinfo->out_color_space=JCS_EXT_ARGB; break;
251 case TJPF_ABGR:
252 dinfo->out_color_space=JCS_EXT_ABGR; break;
253 #endif
DRC9b28def2011-05-21 14:37:15 +0000254 #else
DRC25b995a2011-05-21 15:34:54 +0000255 case TJPF_RGB:
DRCafc06922012-03-23 19:47:57 +0000256 case TJPF_BGR:
257 case TJPF_RGBX:
258 case TJPF_BGRX:
259 case TJPF_XRGB:
260 case TJPF_XBGR:
261 case TJPF_RGBA:
262 case TJPF_BGRA:
263 case TJPF_ARGB:
264 case TJPF_ABGR:
265 dinfo->out_color_space=JCS_RGB; break;
DRC67ce3b22011-12-19 02:21:03 +0000266 #endif
DRCcd7c3e62013-08-23 02:49:25 +0000267 case TJPF_CMYK:
268 dinfo->out_color_space=JCS_CMYK; break;
DRC9b28def2011-05-21 14:37:15 +0000269 default:
270 _throw("Unsupported pixel format");
DRC9b28def2011-05-21 14:37:15 +0000271 }
DRCf12bb302011-09-07 05:03:18 +0000272
DRC73d74c12012-06-29 23:46:38 +0000273 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
274
DRCf12bb302011-09-07 05:03:18 +0000275 bailout:
DRCf12bb302011-09-07 05:03:18 +0000276 return retval;
DRC9b28def2011-05-21 14:37:15 +0000277}
278
279
DRC9b49f0e2011-07-12 03:17:23 +0000280static int getSubsamp(j_decompress_ptr dinfo)
281{
282 int retval=-1, i, k;
283 for(i=0; i<NUMSUBOPT; i++)
284 {
DRCcd7c3e62013-08-23 02:49:25 +0000285 if(dinfo->num_components==pixelsize[i]
286 || ((dinfo->jpeg_color_space==JCS_YCCK
287 || dinfo->jpeg_color_space==JCS_CMYK)
288 && pixelsize[i]==3 && dinfo->num_components==4))
DRC9b49f0e2011-07-12 03:17:23 +0000289 {
290 if(dinfo->comp_info[0].h_samp_factor==tjMCUWidth[i]/8
291 && dinfo->comp_info[0].v_samp_factor==tjMCUHeight[i]/8)
292 {
293 int match=0;
294 for(k=1; k<dinfo->num_components; k++)
295 {
DRCcd7c3e62013-08-23 02:49:25 +0000296 int href=1, vref=1;
297 if(dinfo->jpeg_color_space==JCS_YCCK && k==3)
298 {
299 href=tjMCUWidth[i]/8; vref=tjMCUHeight[i]/8;
300 }
301 if(dinfo->comp_info[k].h_samp_factor==href
302 && dinfo->comp_info[k].v_samp_factor==vref)
DRC9b49f0e2011-07-12 03:17:23 +0000303 match++;
304 }
305 if(match==dinfo->num_components-1)
306 {
307 retval=i; break;
308 }
309 }
310 }
311 }
312 return retval;
313}
314
315
DRCafc06922012-03-23 19:47:57 +0000316#ifndef JCS_EXTENSIONS
317
318/* Conversion functions to emulate the colorspace extensions. This allows the
319 TurboJPEG wrapper to be used with libjpeg */
320
321#define TORGB(PS, ROFFSET, GOFFSET, BOFFSET) { \
322 int rowPad=pitch-width*PS; \
323 while(height--) \
324 { \
325 unsigned char *endOfRow=src+width*PS; \
326 while(src<endOfRow) \
327 { \
328 dst[RGB_RED]=src[ROFFSET]; \
329 dst[RGB_GREEN]=src[GOFFSET]; \
330 dst[RGB_BLUE]=src[BOFFSET]; \
331 dst+=RGB_PIXELSIZE; src+=PS; \
332 } \
333 src+=rowPad; \
334 } \
335}
336
337static unsigned char *toRGB(unsigned char *src, int width, int pitch,
338 int height, int pixelFormat, unsigned char *dst)
339{
340 unsigned char *retval=src;
341 switch(pixelFormat)
342 {
343 case TJPF_RGB:
344 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3
345 retval=dst; TORGB(3, 0, 1, 2);
346 #endif
347 break;
348 case TJPF_BGR:
349 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3
350 retval=dst; TORGB(3, 2, 1, 0);
351 #endif
352 break;
353 case TJPF_RGBX:
354 case TJPF_RGBA:
355 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
356 retval=dst; TORGB(4, 0, 1, 2);
357 #endif
358 break;
359 case TJPF_BGRX:
360 case TJPF_BGRA:
361 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
362 retval=dst; TORGB(4, 2, 1, 0);
363 #endif
364 break;
365 case TJPF_XRGB:
366 case TJPF_ARGB:
367 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
368 retval=dst; TORGB(4, 1, 2, 3);
369 #endif
370 break;
371 case TJPF_XBGR:
372 case TJPF_ABGR:
373 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
374 retval=dst; TORGB(4, 3, 2, 1);
375 #endif
376 break;
377 }
378 return retval;
379}
380
381#define FROMRGB(PS, ROFFSET, GOFFSET, BOFFSET, SETALPHA) { \
382 int rowPad=pitch-width*PS; \
383 while(height--) \
384 { \
385 unsigned char *endOfRow=dst+width*PS; \
386 while(dst<endOfRow) \
387 { \
388 dst[ROFFSET]=src[RGB_RED]; \
389 dst[GOFFSET]=src[RGB_GREEN]; \
390 dst[BOFFSET]=src[RGB_BLUE]; \
391 SETALPHA \
392 dst+=PS; src+=RGB_PIXELSIZE; \
393 } \
394 dst+=rowPad; \
395 } \
396}
397
398static void fromRGB(unsigned char *src, unsigned char *dst, int width,
399 int pitch, int height, int pixelFormat)
400{
401 switch(pixelFormat)
402 {
403 case TJPF_RGB:
404 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3
405 FROMRGB(3, 0, 1, 2,);
406 #endif
407 break;
408 case TJPF_BGR:
409 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3
410 FROMRGB(3, 2, 1, 0,);
411 #endif
412 break;
413 case TJPF_RGBX:
414 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
415 FROMRGB(4, 0, 1, 2,);
416 #endif
417 break;
418 case TJPF_RGBA:
419 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
420 FROMRGB(4, 0, 1, 2, dst[3]=0xFF;);
421 #endif
422 break;
423 case TJPF_BGRX:
424 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
425 FROMRGB(4, 2, 1, 0,);
426 #endif
427 break;
428 case TJPF_BGRA:
429 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
430 FROMRGB(4, 2, 1, 0, dst[3]=0xFF;); return;
431 #endif
432 break;
433 case TJPF_XRGB:
434 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
435 FROMRGB(4, 1, 2, 3,); return;
436 #endif
437 break;
438 case TJPF_ARGB:
439 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
440 FROMRGB(4, 1, 2, 3, dst[0]=0xFF;); return;
441 #endif
442 break;
443 case TJPF_XBGR:
444 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
445 FROMRGB(4, 3, 2, 1,); return;
446 #endif
447 break;
448 case TJPF_ABGR:
449 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
450 FROMRGB(4, 3, 2, 1, dst[0]=0xFF;); return;
451 #endif
452 break;
453 }
454}
455
456#endif
457
458
DRC9b28def2011-05-21 14:37:15 +0000459/* General API functions */
460
461DLLEXPORT char* DLLCALL tjGetErrorStr(void)
462{
463 return errStr;
464}
465
466
467DLLEXPORT int DLLCALL tjDestroy(tjhandle handle)
468{
469 getinstance(handle);
470 if(setjmp(this->jerr.setjmp_buffer)) return -1;
471 if(this->init&COMPRESS) jpeg_destroy_compress(cinfo);
472 if(this->init&DECOMPRESS) jpeg_destroy_decompress(dinfo);
473 free(this);
474 return 0;
475}
476
477
DRC6b76f752011-05-24 16:52:47 +0000478/* These are exposed mainly because Windows can't malloc() and free() across
479 DLL boundaries except when the CRT DLL is used, and we don't use the CRT DLL
480 with turbojpeg.dll for compatibility reasons. However, these functions
481 can potentially be used for other purposes by different implementations. */
482
483DLLEXPORT void DLLCALL tjFree(unsigned char *buf)
484{
485 if(buf) free(buf);
486}
487
488
489DLLEXPORT unsigned char *DLLCALL tjAlloc(int bytes)
490{
491 return (unsigned char *)malloc(bytes);
492}
493
494
DRC9b28def2011-05-21 14:37:15 +0000495/* Compressor */
496
497static tjhandle _tjInitCompress(tjinstance *this)
498{
499 unsigned char buffer[1], *buf=buffer; unsigned long size=1;
500
501 /* This is also straight out of example.c */
502 this->cinfo.err=jpeg_std_error(&this->jerr.pub);
503 this->jerr.pub.error_exit=my_error_exit;
504 this->jerr.pub.output_message=my_output_message;
505
506 if(setjmp(this->jerr.setjmp_buffer))
507 {
508 /* If we get here, the JPEG code has signaled an error. */
509 if(this) free(this); return NULL;
510 }
511
512 jpeg_create_compress(&this->cinfo);
513 /* Make an initial call so it will create the destination manager */
514 jpeg_mem_dest_tj(&this->cinfo, &buf, &size, 0);
515
DRC007a42c2011-05-22 13:55:56 +0000516 this->init|=COMPRESS;
DRC9b28def2011-05-21 14:37:15 +0000517 return (tjhandle)this;
DRC2e7b76b2009-04-03 12:04:24 +0000518}
519
DRC890f1e02011-02-26 22:02:37 +0000520DLLEXPORT tjhandle DLLCALL tjInitCompress(void)
521{
DRC9b28def2011-05-21 14:37:15 +0000522 tjinstance *this=NULL;
523 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
DRCda5220a2011-03-02 02:17:30 +0000524 {
DRC007a42c2011-05-22 13:55:56 +0000525 snprintf(errStr, JMSG_LENGTH_MAX,
526 "tjInitCompress(): Memory allocation failure");
DRCda5220a2011-03-02 02:17:30 +0000527 return NULL;
528 }
DRC007a42c2011-05-22 13:55:56 +0000529 MEMZERO(this, sizeof(tjinstance));
DRC9b28def2011-05-21 14:37:15 +0000530 return _tjInitCompress(this);
DRC890f1e02011-02-26 22:02:37 +0000531}
532
DRC84241602011-02-25 02:08:23 +0000533
DRC9b49f0e2011-07-12 03:17:23 +0000534DLLEXPORT unsigned long DLLCALL tjBufSize(int width, int height,
535 int jpegSubsamp)
536{
537 unsigned long retval=0; int mcuw, mcuh, chromasf;
538 if(width<1 || height<1 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT)
539 _throw("tjBufSize(): Invalid argument");
540
DRC006bc582014-02-27 21:22:54 +0000541 /* This allows for rare corner cases in which a JPEG image can actually be
542 larger than the uncompressed input (we wouldn't mention it if it hadn't
543 happened before.) */
DRC9b49f0e2011-07-12 03:17:23 +0000544 mcuw=tjMCUWidth[jpegSubsamp];
545 mcuh=tjMCUHeight[jpegSubsamp];
546 chromasf=jpegSubsamp==TJSAMP_GRAY? 0: 4*64/(mcuw*mcuh);
547 retval=PAD(width, mcuw) * PAD(height, mcuh) * (2 + chromasf) + 2048;
548
549 bailout:
550 return retval;
551}
552
DRC2e7b76b2009-04-03 12:04:24 +0000553DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
554{
DRCf3cf9732011-02-22 00:16:14 +0000555 unsigned long retval=0;
556 if(width<1 || height<1)
DRC007a42c2011-05-22 13:55:56 +0000557 _throw("TJBUFSIZE(): Invalid argument");
DRCf3cf9732011-02-22 00:16:14 +0000558
DRC006bc582014-02-27 21:22:54 +0000559 /* This allows for rare corner cases in which a JPEG image can actually be
560 larger than the uncompressed input (we wouldn't mention it if it hadn't
561 happened before.) */
DRC007a42c2011-05-22 13:55:56 +0000562 retval=PAD(width, 16) * PAD(height, 16) * 6 + 2048;
DRCf3cf9732011-02-22 00:16:14 +0000563
564 bailout:
565 return retval;
566}
567
DRC84241602011-02-25 02:08:23 +0000568
DRCf610d612013-04-26 10:33:29 +0000569DLLEXPORT unsigned long DLLCALL tjBufSizeYUV2(int width, int pad, int height,
DRCf3cf9732011-02-22 00:16:14 +0000570 int subsamp)
571{
572 unsigned long retval=0;
573 int pw, ph, cw, ch;
DRCf610d612013-04-26 10:33:29 +0000574 if(width<1 || height<1 || pad<1 || !isPow2(pad) || subsamp<0
575 || subsamp>=NUMSUBOPT)
576 _throw("tjBufSizeYUV2(): Invalid argument");
DRC9b28def2011-05-21 14:37:15 +0000577 pw=PAD(width, tjMCUWidth[subsamp]/8);
578 ph=PAD(height, tjMCUHeight[subsamp]/8);
579 cw=pw*8/tjMCUWidth[subsamp]; ch=ph*8/tjMCUHeight[subsamp];
DRCf610d612013-04-26 10:33:29 +0000580 retval=PAD(pw, pad)*ph + (subsamp==TJSAMP_GRAY? 0:PAD(cw, pad)*ch*2);
DRCf3cf9732011-02-22 00:16:14 +0000581
582 bailout:
583 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000584}
585
DRCf610d612013-04-26 10:33:29 +0000586DLLEXPORT unsigned long DLLCALL tjBufSizeYUV(int width, int height,
587 int subsamp)
588{
589 return tjBufSizeYUV2(width, 4, height, subsamp);
590}
DRC84241602011-02-25 02:08:23 +0000591
DRC9b49f0e2011-07-12 03:17:23 +0000592DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
593 int subsamp)
594{
595 return tjBufSizeYUV(width, height, subsamp);
596}
597
598
DRC9b28def2011-05-21 14:37:15 +0000599DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf,
600 int width, int pitch, int height, int pixelFormat, unsigned char **jpegBuf,
601 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
602{
DRCff78e372011-05-24 10:17:32 +0000603 int i, retval=0, alloc=1; JSAMPROW *row_pointer=NULL;
DRCafc06922012-03-23 19:47:57 +0000604 #ifndef JCS_EXTENSIONS
605 unsigned char *rgbBuf=NULL;
606 #endif
DRC9b28def2011-05-21 14:37:15 +0000607
608 getinstance(handle)
609 if((this->init&COMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +0000610 _throw("tjCompress2(): Instance has not been initialized for compression");
DRC9b28def2011-05-21 14:37:15 +0000611
612 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
613 || pixelFormat>=TJ_NUMPF || jpegBuf==NULL || jpegSize==NULL
614 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT || jpegQual<0 || jpegQual>100)
DRC007a42c2011-05-22 13:55:56 +0000615 _throw("tjCompress2(): Invalid argument");
DRC9b28def2011-05-21 14:37:15 +0000616
617 if(setjmp(this->jerr.setjmp_buffer))
618 {
619 /* If we get here, the JPEG code has signaled an error. */
620 retval=-1;
621 goto bailout;
622 }
623
624 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
625
DRCafc06922012-03-23 19:47:57 +0000626 #ifndef JCS_EXTENSIONS
627 if(pixelFormat!=TJPF_GRAY)
628 {
629 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
630 if(!rgbBuf) _throw("tjCompress2(): Memory allocation failure");
631 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
632 pitch=width*RGB_PIXELSIZE;
633 }
634 #endif
635
DRC9b28def2011-05-21 14:37:15 +0000636 cinfo->image_width=width;
637 cinfo->image_height=height;
638
DRC25b995a2011-05-21 15:34:54 +0000639 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
640 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
641 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC9b28def2011-05-21 14:37:15 +0000642
DRCff78e372011-05-24 10:17:32 +0000643 if(flags&TJFLAG_NOREALLOC)
644 {
DRC9b49f0e2011-07-12 03:17:23 +0000645 alloc=0; *jpegSize=tjBufSize(width, height, jpegSubsamp);
DRCff78e372011-05-24 10:17:32 +0000646 }
647 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
DRC73d74c12012-06-29 23:46:38 +0000648 if(setCompDefaults(cinfo, pixelFormat, jpegSubsamp, jpegQual, flags)==-1)
DRCf12bb302011-09-07 05:03:18 +0000649 return -1;
DRC9b28def2011-05-21 14:37:15 +0000650
651 jpeg_start_compress(cinfo, TRUE);
652 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
DRC007a42c2011-05-22 13:55:56 +0000653 _throw("tjCompress2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000654 for(i=0; i<height; i++)
655 {
DRC25b995a2011-05-21 15:34:54 +0000656 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
DRC9b28def2011-05-21 14:37:15 +0000657 else row_pointer[i]=&srcBuf[i*pitch];
658 }
659 while(cinfo->next_scanline<cinfo->image_height)
660 {
661 jpeg_write_scanlines(cinfo, &row_pointer[cinfo->next_scanline],
662 cinfo->image_height-cinfo->next_scanline);
663 }
664 jpeg_finish_compress(cinfo);
665
666 bailout:
667 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
DRCafc06922012-03-23 19:47:57 +0000668 #ifndef JCS_EXTENSIONS
DRCea3396a2012-04-26 03:18:49 +0000669 if(rgbBuf) free(rgbBuf);
DRCafc06922012-03-23 19:47:57 +0000670 #endif
DRC9b28def2011-05-21 14:37:15 +0000671 if(row_pointer) free(row_pointer);
672 return retval;
673}
674
675DLLEXPORT int DLLCALL tjCompress(tjhandle handle, unsigned char *srcBuf,
676 int width, int pitch, int height, int pixelSize, unsigned char *jpegBuf,
677 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
678{
679 int retval=0; unsigned long size;
680 if(flags&TJ_YUV)
681 {
DRC9b49f0e2011-07-12 03:17:23 +0000682 size=tjBufSizeYUV(width, height, jpegSubsamp);
DRC9b28def2011-05-21 14:37:15 +0000683 retval=tjEncodeYUV2(handle, srcBuf, width, pitch, height,
684 getPixelFormat(pixelSize, flags), jpegBuf, jpegSubsamp, flags);
685 }
686 else
687 {
DRC9b28def2011-05-21 14:37:15 +0000688 retval=tjCompress2(handle, srcBuf, width, pitch, height,
689 getPixelFormat(pixelSize, flags), &jpegBuf, &size, jpegSubsamp, jpegQual,
DRC25b995a2011-05-21 15:34:54 +0000690 flags|TJFLAG_NOREALLOC);
DRC9b28def2011-05-21 14:37:15 +0000691 }
692 *jpegSize=size;
693 return retval;
694}
695
696
DRCf610d612013-04-26 10:33:29 +0000697DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf,
DRC9b28def2011-05-21 14:37:15 +0000698 int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
DRCf610d612013-04-26 10:33:29 +0000699 int pad, int subsamp, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000700{
DRC91e86ba2011-02-15 05:24:08 +0000701 int i, retval=0; JSAMPROW *row_pointer=NULL;
DRCfbb67472010-11-24 04:02:37 +0000702 JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS];
703 JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
704 JSAMPROW *outbuf[MAX_COMPONENTS];
DRC9b28def2011-05-21 14:37:15 +0000705 int row, pw, ph, cw[MAX_COMPONENTS], ch[MAX_COMPONENTS];
706 JSAMPLE *ptr=dstBuf;
DRCafc06922012-03-23 19:47:57 +0000707 unsigned long yuvsize=0;
DRC9b28def2011-05-21 14:37:15 +0000708 jpeg_component_info *compptr;
DRCafc06922012-03-23 19:47:57 +0000709 #ifndef JCS_EXTENSIONS
710 unsigned char *rgbBuf=NULL;
711 #endif
DRC2e7b76b2009-04-03 12:04:24 +0000712
DRCb51ee892013-10-31 05:00:19 +0000713 getinstance(handle);
714
DRCfbb67472010-11-24 04:02:37 +0000715 for(i=0; i<MAX_COMPONENTS; i++)
716 {
717 tmpbuf[i]=NULL; _tmpbuf[i]=NULL;
718 tmpbuf2[i]=NULL; _tmpbuf2[i]=NULL; outbuf[i]=NULL;
719 }
720
DRCe2f8e692013-10-30 22:21:06 +0000721 if((this->init&COMPRESS)==0)
722 _throw("tjEncodeYUV3(): Instance has not been initialized for compression");
723
DRC9b28def2011-05-21 14:37:15 +0000724 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
DRCf610d612013-04-26 10:33:29 +0000725 || pixelFormat>=TJ_NUMPF || dstBuf==NULL || pad<0 || !isPow2(pad)
726 || subsamp<0 || subsamp>=NUMSUBOPT)
727 _throw("tjEncodeYUV3(): Invalid argument");
DRC2e7b76b2009-04-03 12:04:24 +0000728
DRC9b28def2011-05-21 14:37:15 +0000729 if(setjmp(this->jerr.setjmp_buffer))
730 {
731 /* If we get here, the JPEG code has signaled an error. */
732 retval=-1;
733 goto bailout;
734 }
DRC2e7b76b2009-04-03 12:04:24 +0000735
DRCcd7c3e62013-08-23 02:49:25 +0000736 if(pixelFormat==TJPF_CMYK)
737 _throw("tjEncodeYUV3(): Cannot generate YUV images from CMYK pixels");
738
DRC9b28def2011-05-21 14:37:15 +0000739 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
DRC2e7b76b2009-04-03 12:04:24 +0000740
DRCafc06922012-03-23 19:47:57 +0000741 #ifndef JCS_EXTENSIONS
742 if(pixelFormat!=TJPF_GRAY)
743 {
744 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
DRCf610d612013-04-26 10:33:29 +0000745 if(!rgbBuf) _throw("tjEncodeYUV3(): Memory allocation failure");
DRCafc06922012-03-23 19:47:57 +0000746 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
747 pitch=width*RGB_PIXELSIZE;
748 }
749 #endif
750
DRC9b28def2011-05-21 14:37:15 +0000751 cinfo->image_width=width;
752 cinfo->image_height=height;
DRC2e7b76b2009-04-03 12:04:24 +0000753
DRC25b995a2011-05-21 15:34:54 +0000754 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
755 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
756 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC0c6a2712010-02-22 08:34:44 +0000757
DRCf610d612013-04-26 10:33:29 +0000758 yuvsize=tjBufSizeYUV2(width, pad, height, subsamp);
DRC73d74c12012-06-29 23:46:38 +0000759 if(setCompDefaults(cinfo, pixelFormat, subsamp, -1, flags)==-1) return -1;
DRC2e7b76b2009-04-03 12:04:24 +0000760
DRC38c99702014-02-11 09:45:18 +0000761 /* Execute only the parts of jpeg_start_compress() that we need. If we
762 were to call the whole jpeg_start_compress() function, then it would try
763 to write the file headers, which could overflow the output buffer if the
764 YUV image were very small. */
765 if(cinfo->global_state!=CSTATE_START)
766 _throw("tjEncodeYUV3(): libjpeg API is in the wrong state");
767 (*cinfo->err->reset_error_mgr)((j_common_ptr)cinfo);
DRC38c99702014-02-11 09:45:18 +0000768 jinit_c_master_control(cinfo, FALSE);
769 jinit_color_converter(cinfo);
770 jinit_downsampler(cinfo);
DRC50cfc462014-03-06 20:03:37 +0000771 (*cinfo->cconvert->start_pass)(cinfo);
DRC38c99702014-02-11 09:45:18 +0000772
DRC9b28def2011-05-21 14:37:15 +0000773 pw=PAD(width, cinfo->max_h_samp_factor);
774 ph=PAD(height, cinfo->max_v_samp_factor);
DRC2e7b76b2009-04-03 12:04:24 +0000775
DRC9b28def2011-05-21 14:37:15 +0000776 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph))==NULL)
DRCf610d612013-04-26 10:33:29 +0000777 _throw("tjEncodeYUV3(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000778 for(i=0; i<height; i++)
DRC2e7b76b2009-04-03 12:04:24 +0000779 {
DRC25b995a2011-05-21 15:34:54 +0000780 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
DRC9b28def2011-05-21 14:37:15 +0000781 else row_pointer[i]=&srcBuf[i*pitch];
782 }
783 if(height<ph)
784 for(i=height; i<ph; i++) row_pointer[i]=row_pointer[height-1];
DRCfbb67472010-11-24 04:02:37 +0000785
DRC9b28def2011-05-21 14:37:15 +0000786 for(i=0; i<cinfo->num_components; i++)
787 {
788 compptr=&cinfo->comp_info[i];
789 _tmpbuf[i]=(JSAMPLE *)malloc(
790 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
791 /compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
DRCf610d612013-04-26 10:33:29 +0000792 if(!_tmpbuf[i]) _throw("tjEncodeYUV3(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000793 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
DRCf610d612013-04-26 10:33:29 +0000794 if(!tmpbuf[i]) _throw("tjEncodeYUV3(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000795 for(row=0; row<cinfo->max_v_samp_factor; row++)
DRCfbb67472010-11-24 04:02:37 +0000796 {
DRC9b28def2011-05-21 14:37:15 +0000797 unsigned char *_tmpbuf_aligned=
798 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
799 tmpbuf[i][row]=&_tmpbuf_aligned[
DRCfbb67472010-11-24 04:02:37 +0000800 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
DRC9b28def2011-05-21 14:37:15 +0000801 /compptr->h_samp_factor, 16) * row];
DRCfbb67472010-11-24 04:02:37 +0000802 }
DRC9b28def2011-05-21 14:37:15 +0000803 _tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
804 * compptr->v_samp_factor + 16);
DRCf610d612013-04-26 10:33:29 +0000805 if(!_tmpbuf2[i]) _throw("tjEncodeYUV3(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000806 tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
DRCf610d612013-04-26 10:33:29 +0000807 if(!tmpbuf2[i]) _throw("tjEncodeYUV3(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000808 for(row=0; row<compptr->v_samp_factor; row++)
809 {
810 unsigned char *_tmpbuf2_aligned=
811 (unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
812 tmpbuf2[i][row]=&_tmpbuf2_aligned[
813 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
814 }
815 cw[i]=pw*compptr->h_samp_factor/cinfo->max_h_samp_factor;
816 ch[i]=ph*compptr->v_samp_factor/cinfo->max_v_samp_factor;
817 outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]);
DRCf610d612013-04-26 10:33:29 +0000818 if(!outbuf[i]) _throw("tjEncodeYUV3(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000819 for(row=0; row<ch[i]; row++)
820 {
821 outbuf[i][row]=ptr;
DRCf610d612013-04-26 10:33:29 +0000822 ptr+=PAD(cw[i], pad);
DRC9b28def2011-05-21 14:37:15 +0000823 }
824 }
825 if(yuvsize!=(unsigned long)(ptr-dstBuf))
DRCf610d612013-04-26 10:33:29 +0000826 _throw("tjEncodeYUV3(): Generated image is not the correct size");
DRCfbb67472010-11-24 04:02:37 +0000827
DRC9b28def2011-05-21 14:37:15 +0000828 for(row=0; row<ph; row+=cinfo->max_v_samp_factor)
DRCfbb67472010-11-24 04:02:37 +0000829 {
DRC9b28def2011-05-21 14:37:15 +0000830 (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0,
831 cinfo->max_v_samp_factor);
832 (cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
833 for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++)
834 jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
835 row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
836 compptr->v_samp_factor, cw[i]);
DRC6ee54592011-03-01 08:18:30 +0000837 }
DRC9b28def2011-05-21 14:37:15 +0000838 cinfo->next_scanline+=height;
839 jpeg_abort_compress(cinfo);
DRC2e7b76b2009-04-03 12:04:24 +0000840
DRC91e86ba2011-02-15 05:24:08 +0000841 bailout:
DRC9b28def2011-05-21 14:37:15 +0000842 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
DRCafc06922012-03-23 19:47:57 +0000843 #ifndef JCS_EXTENSIONS
DRCea3396a2012-04-26 03:18:49 +0000844 if(rgbBuf) free(rgbBuf);
DRCafc06922012-03-23 19:47:57 +0000845 #endif
DRC2e7b76b2009-04-03 12:04:24 +0000846 if(row_pointer) free(row_pointer);
DRCfbb67472010-11-24 04:02:37 +0000847 for(i=0; i<MAX_COMPONENTS; i++)
848 {
849 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
DRC57423072011-01-05 23:35:53 +0000850 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
DRCfbb67472010-11-24 04:02:37 +0000851 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
DRC57423072011-01-05 23:35:53 +0000852 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
DRCfbb67472010-11-24 04:02:37 +0000853 if(outbuf[i]!=NULL) free(outbuf[i]);
854 }
DRC91e86ba2011-02-15 05:24:08 +0000855 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000856}
857
DRCf610d612013-04-26 10:33:29 +0000858DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
859 int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
860 int subsamp, int flags)
861{
862 return tjEncodeYUV3(handle, srcBuf, width, pitch, height, pixelFormat,
863 dstBuf, 4, subsamp, flags);
864}
865
DRC9b28def2011-05-21 14:37:15 +0000866DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf,
867 int width, int pitch, int height, int pixelSize, unsigned char *dstBuf,
868 int subsamp, int flags)
DRC84241602011-02-25 02:08:23 +0000869{
DRC9b28def2011-05-21 14:37:15 +0000870 return tjEncodeYUV2(handle, srcBuf, width, pitch, height,
871 getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags);
DRC84241602011-02-25 02:08:23 +0000872}
873
874
DRC910a3572013-10-30 23:02:57 +0000875DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle, unsigned char *srcBuf,
876 int width, int pad, int height, int subsamp, unsigned char **jpegBuf,
877 unsigned long *jpegSize, int jpegQual, int flags)
878{
879 int i, row, retval=0, alloc=1; JSAMPROW *inbuf[MAX_COMPONENTS];
880 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS],
881 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
882 JSAMPLE *_tmpbuf=NULL, *ptr=srcBuf; JSAMPROW *tmpbuf[MAX_COMPONENTS];
883
DRCb51ee892013-10-31 05:00:19 +0000884 getinstance(handle)
885
DRC910a3572013-10-30 23:02:57 +0000886 for(i=0; i<MAX_COMPONENTS; i++)
887 {
888 tmpbuf[i]=NULL; inbuf[i]=NULL;
889 }
890
DRC910a3572013-10-30 23:02:57 +0000891 if((this->init&COMPRESS)==0)
892 _throw("tjCompressFromYUV(): Instance has not been initialized for compression");
893
894 if(srcBuf==NULL || width<=0 || pad<1 || height<=0 || subsamp<0
895 || subsamp>=NUMSUBOPT || jpegBuf==NULL || jpegSize==NULL || jpegQual<0
896 || jpegQual>100)
897 _throw("tjCompressFromYUV(): Invalid argument");
898
899 if(setjmp(this->jerr.setjmp_buffer))
900 {
901 /* If we get here, the JPEG code has signaled an error. */
902 retval=-1;
903 goto bailout;
904 }
905
906 cinfo->image_width=width;
907 cinfo->image_height=height;
908
909 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
910 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
911 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
912
913 if(flags&TJFLAG_NOREALLOC)
914 {
915 alloc=0; *jpegSize=tjBufSize(width, height, subsamp);
916 }
917 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
918 if(setCompDefaults(cinfo, TJPF_RGB, subsamp, jpegQual, flags)==-1)
919 return -1;
920 cinfo->raw_data_in=TRUE;
921
922 jpeg_start_compress(cinfo, TRUE);
923 for(i=0; i<cinfo->num_components; i++)
924 {
925 jpeg_component_info *compptr=&cinfo->comp_info[i];
926 int ih;
927 iw[i]=compptr->width_in_blocks*DCTSIZE;
928 ih=compptr->height_in_blocks*DCTSIZE;
929 cw[i]=PAD(cinfo->image_width, cinfo->max_h_samp_factor)
930 *compptr->h_samp_factor/cinfo->max_h_samp_factor;
931 ch[i]=PAD(cinfo->image_height, cinfo->max_v_samp_factor)
932 *compptr->v_samp_factor/cinfo->max_v_samp_factor;
933 if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1;
934 th[i]=compptr->v_samp_factor*DCTSIZE;
935 tmpbufsize+=iw[i]*th[i];
936 if((inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL)
937 _throw("tjCompressFromYUV(): Memory allocation failure");
938 for(row=0; row<ch[i]; row++)
939 {
940 inbuf[i][row]=ptr;
941 ptr+=PAD(cw[i], pad);
942 }
943 }
944 if(usetmpbuf)
945 {
946 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
947 _throw("tjCompressFromYUV(): Memory allocation failure");
948 ptr=_tmpbuf;
949 for(i=0; i<cinfo->num_components; i++)
950 {
951 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
952 _throw("tjCompressFromYUV(): Memory allocation failure");
953 for(row=0; row<th[i]; row++)
954 {
955 tmpbuf[i][row]=ptr;
956 ptr+=iw[i];
957 }
958 }
959 }
960
961 for(row=0; row<(int)cinfo->image_height;
962 row+=cinfo->max_v_samp_factor*DCTSIZE)
963 {
964 JSAMPARRAY yuvptr[MAX_COMPONENTS];
965 int crow[MAX_COMPONENTS];
966 for(i=0; i<cinfo->num_components; i++)
967 {
968 jpeg_component_info *compptr=&cinfo->comp_info[i];
969 crow[i]=row*compptr->v_samp_factor/cinfo->max_v_samp_factor;
970 if(usetmpbuf)
971 {
972 int j, k;
973 for(j=0; j<min(th[i], ch[i]-crow[i]); j++)
974 {
975 memcpy(tmpbuf[i][j], inbuf[i][crow[i]+j], cw[i]);
DRC006bc582014-02-27 21:22:54 +0000976 /* Duplicate last sample in row to fill out MCU */
DRC910a3572013-10-30 23:02:57 +0000977 for(k=cw[i]; k<iw[i]; k++) tmpbuf[i][j][k]=tmpbuf[i][j][cw[i]-1];
978 }
DRC006bc582014-02-27 21:22:54 +0000979 /* Duplicate last row to fill out MCU */
DRC910a3572013-10-30 23:02:57 +0000980 for(j=ch[i]-crow[i]; j<th[i]; j++)
981 memcpy(tmpbuf[i][j], tmpbuf[i][ch[i]-crow[i]-1], iw[i]);
982 yuvptr[i]=tmpbuf[i];
983 }
984 else
985 yuvptr[i]=&inbuf[i][crow[i]];
986 }
987 jpeg_write_raw_data(cinfo, yuvptr, cinfo->max_v_samp_factor*DCTSIZE);
988 }
989 jpeg_finish_compress(cinfo);
990
991 bailout:
992 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
993 for(i=0; i<MAX_COMPONENTS; i++)
994 {
995 if(tmpbuf[i]) free(tmpbuf[i]);
996 if(inbuf[i]) free(inbuf[i]);
997 }
998 if(_tmpbuf) free(_tmpbuf);
999 return retval;
1000}
1001
1002
DRC9b28def2011-05-21 14:37:15 +00001003/* Decompressor */
DRC2e7b76b2009-04-03 12:04:24 +00001004
DRC9b28def2011-05-21 14:37:15 +00001005static tjhandle _tjInitDecompress(tjinstance *this)
DRC2e7b76b2009-04-03 12:04:24 +00001006{
DRC9b28def2011-05-21 14:37:15 +00001007 unsigned char buffer[1];
DRC2e7b76b2009-04-03 12:04:24 +00001008
DRC9b28def2011-05-21 14:37:15 +00001009 /* This is also straight out of example.c */
1010 this->dinfo.err=jpeg_std_error(&this->jerr.pub);
1011 this->jerr.pub.error_exit=my_error_exit;
1012 this->jerr.pub.output_message=my_output_message;
DRC2e7b76b2009-04-03 12:04:24 +00001013
DRC9b28def2011-05-21 14:37:15 +00001014 if(setjmp(this->jerr.setjmp_buffer))
1015 {
1016 /* If we get here, the JPEG code has signaled an error. */
1017 if(this) free(this); return NULL;
DRC9e17f7d2010-12-10 04:59:13 +00001018 }
DRC2e7b76b2009-04-03 12:04:24 +00001019
DRC9b28def2011-05-21 14:37:15 +00001020 jpeg_create_decompress(&this->dinfo);
1021 /* Make an initial call so it will create the source manager */
1022 jpeg_mem_src_tj(&this->dinfo, buffer, 1);
DRC2e7b76b2009-04-03 12:04:24 +00001023
DRC007a42c2011-05-22 13:55:56 +00001024 this->init|=DECOMPRESS;
DRC9b28def2011-05-21 14:37:15 +00001025 return (tjhandle)this;
DRC2e7b76b2009-04-03 12:04:24 +00001026}
1027
DRC890f1e02011-02-26 22:02:37 +00001028DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
1029{
DRC9b28def2011-05-21 14:37:15 +00001030 tjinstance *this;
1031 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
DRCda5220a2011-03-02 02:17:30 +00001032 {
DRC007a42c2011-05-22 13:55:56 +00001033 snprintf(errStr, JMSG_LENGTH_MAX,
1034 "tjInitDecompress(): Memory allocation failure");
DRCda5220a2011-03-02 02:17:30 +00001035 return NULL;
1036 }
DRC007a42c2011-05-22 13:55:56 +00001037 MEMZERO(this, sizeof(tjinstance));
DRC9b28def2011-05-21 14:37:15 +00001038 return _tjInitDecompress(this);
DRC890f1e02011-02-26 22:02:37 +00001039}
1040
DRC2e7b76b2009-04-03 12:04:24 +00001041
DRCcd7c3e62013-08-23 02:49:25 +00001042DLLEXPORT int DLLCALL tjDecompressHeader3(tjhandle handle,
DRC9b28def2011-05-21 14:37:15 +00001043 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
DRCcd7c3e62013-08-23 02:49:25 +00001044 int *jpegSubsamp, int *jpegColorspace)
DRC1fe80f82010-12-14 01:21:29 +00001045{
DRC9b49f0e2011-07-12 03:17:23 +00001046 int retval=0;
DRC1fe80f82010-12-14 01:21:29 +00001047
DRC9b28def2011-05-21 14:37:15 +00001048 getinstance(handle);
1049 if((this->init&DECOMPRESS)==0)
DRCcd7c3e62013-08-23 02:49:25 +00001050 _throw("tjDecompressHeader3(): Instance has not been initialized for decompression");
DRC1fe80f82010-12-14 01:21:29 +00001051
DRC9b28def2011-05-21 14:37:15 +00001052 if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL
DRCcd7c3e62013-08-23 02:49:25 +00001053 || jpegSubsamp==NULL || jpegColorspace==NULL)
1054 _throw("tjDecompressHeader3(): Invalid argument");
DRC1fe80f82010-12-14 01:21:29 +00001055
DRC9b28def2011-05-21 14:37:15 +00001056 if(setjmp(this->jerr.setjmp_buffer))
1057 {
1058 /* If we get here, the JPEG code has signaled an error. */
DRC1fe80f82010-12-14 01:21:29 +00001059 return -1;
1060 }
1061
DRC9b28def2011-05-21 14:37:15 +00001062 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1063 jpeg_read_header(dinfo, TRUE);
DRC1fe80f82010-12-14 01:21:29 +00001064
DRC9b28def2011-05-21 14:37:15 +00001065 *width=dinfo->image_width;
1066 *height=dinfo->image_height;
DRC9b49f0e2011-07-12 03:17:23 +00001067 *jpegSubsamp=getSubsamp(dinfo);
DRCcd7c3e62013-08-23 02:49:25 +00001068 switch(dinfo->jpeg_color_space)
1069 {
1070 case JCS_GRAYSCALE: *jpegColorspace=TJCS_GRAY; break;
1071 case JCS_RGB: *jpegColorspace=TJCS_RGB; break;
1072 case JCS_YCbCr: *jpegColorspace=TJCS_YCbCr; break;
1073 case JCS_CMYK: *jpegColorspace=TJCS_CMYK; break;
1074 case JCS_YCCK: *jpegColorspace=TJCS_YCCK; break;
1075 default: *jpegColorspace=-1; break;
1076 }
DRC1fe80f82010-12-14 01:21:29 +00001077
DRC9b28def2011-05-21 14:37:15 +00001078 jpeg_abort_decompress(dinfo);
DRC1fe80f82010-12-14 01:21:29 +00001079
DRC9b28def2011-05-21 14:37:15 +00001080 if(*jpegSubsamp<0)
DRCcd7c3e62013-08-23 02:49:25 +00001081 _throw("tjDecompressHeader3(): Could not determine subsampling type for JPEG image");
1082 if(*jpegColorspace<0)
1083 _throw("tjDecompressHeader3(): Could not determine colorspace of JPEG image");
DRC007a42c2011-05-22 13:55:56 +00001084 if(*width<1 || *height<1)
DRCcd7c3e62013-08-23 02:49:25 +00001085 _throw("tjDecompressHeader3(): Invalid data returned in header");
DRC91e86ba2011-02-15 05:24:08 +00001086
1087 bailout:
1088 return retval;
1089}
1090
DRCcd7c3e62013-08-23 02:49:25 +00001091DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle,
1092 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
1093 int *jpegSubsamp)
1094{
1095 int jpegColorspace;
1096 return tjDecompressHeader3(handle, jpegBuf, jpegSize, width, height,
1097 jpegSubsamp, &jpegColorspace);
1098}
1099
DRC9b28def2011-05-21 14:37:15 +00001100DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle,
1101 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height)
DRC91e86ba2011-02-15 05:24:08 +00001102{
DRC9b28def2011-05-21 14:37:15 +00001103 int jpegSubsamp;
1104 return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height,
1105 &jpegSubsamp);
DRC1fe80f82010-12-14 01:21:29 +00001106}
1107
1108
DRC109a5782011-03-01 09:53:07 +00001109DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors)
DRCb28fc572011-02-22 06:41:29 +00001110{
DRC109a5782011-03-01 09:53:07 +00001111 if(numscalingfactors==NULL)
DRCb28fc572011-02-22 06:41:29 +00001112 {
DRC9b28def2011-05-21 14:37:15 +00001113 snprintf(errStr, JMSG_LENGTH_MAX,
DRC007a42c2011-05-22 13:55:56 +00001114 "tjGetScalingFactors(): Invalid argument");
DRC109a5782011-03-01 09:53:07 +00001115 return NULL;
DRCb28fc572011-02-22 06:41:29 +00001116 }
1117
DRC109a5782011-03-01 09:53:07 +00001118 *numscalingfactors=NUMSF;
1119 return (tjscalingfactor *)sf;
DRCb28fc572011-02-22 06:41:29 +00001120}
1121
1122
DRC9b28def2011-05-21 14:37:15 +00001123DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, unsigned char *jpegBuf,
1124 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
1125 int height, int pixelFormat, int flags)
DRC2e7b76b2009-04-03 12:04:24 +00001126{
DRC9b28def2011-05-21 14:37:15 +00001127 int i, retval=0; JSAMPROW *row_pointer=NULL;
DRC109a5782011-03-01 09:53:07 +00001128 int jpegwidth, jpegheight, scaledw, scaledh;
DRCafc06922012-03-23 19:47:57 +00001129 #ifndef JCS_EXTENSIONS
1130 unsigned char *rgbBuf=NULL;
1131 unsigned char *_dstBuf=NULL; int _pitch=0;
1132 #endif
DRC2e7b76b2009-04-03 12:04:24 +00001133
DRC9b28def2011-05-21 14:37:15 +00001134 getinstance(handle);
1135 if((this->init&DECOMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +00001136 _throw("tjDecompress2(): Instance has not been initialized for decompression");
DRC9b28def2011-05-21 14:37:15 +00001137
1138 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0
1139 || height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF)
1140 _throw("tjDecompress2(): Invalid argument");
1141
DRC25b995a2011-05-21 15:34:54 +00001142 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1143 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1144 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC9b28def2011-05-21 14:37:15 +00001145
1146 if(setjmp(this->jerr.setjmp_buffer))
1147 {
1148 /* If we get here, the JPEG code has signaled an error. */
1149 retval=-1;
1150 goto bailout;
1151 }
1152
1153 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1154 jpeg_read_header(dinfo, TRUE);
DRC73d74c12012-06-29 23:46:38 +00001155 if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
DRC2eda8212012-03-23 19:32:38 +00001156 {
1157 retval=-1; goto bailout;
1158 }
DRC9b28def2011-05-21 14:37:15 +00001159
DRC25b995a2011-05-21 15:34:54 +00001160 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
DRC9b28def2011-05-21 14:37:15 +00001161
1162 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
1163 if(width==0) width=jpegwidth;
1164 if(height==0) height=jpegheight;
1165 for(i=0; i<NUMSF; i++)
1166 {
1167 scaledw=TJSCALED(jpegwidth, sf[i]);
1168 scaledh=TJSCALED(jpegheight, sf[i]);
1169 if(scaledw<=width && scaledh<=height)
DRCf610d612013-04-26 10:33:29 +00001170 break;
DRC9b28def2011-05-21 14:37:15 +00001171 }
1172 if(scaledw>width || scaledh>height)
DRC007a42c2011-05-22 13:55:56 +00001173 _throw("tjDecompress2(): Could not scale down to desired image dimensions");
DRC9b28def2011-05-21 14:37:15 +00001174 width=scaledw; height=scaledh;
1175 dinfo->scale_num=sf[i].num;
1176 dinfo->scale_denom=sf[i].denom;
1177
1178 jpeg_start_decompress(dinfo);
1179 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
DRCafc06922012-03-23 19:47:57 +00001180
1181 #ifndef JCS_EXTENSIONS
1182 if(pixelFormat!=TJPF_GRAY &&
1183 (RGB_RED!=tjRedOffset[pixelFormat] ||
1184 RGB_GREEN!=tjGreenOffset[pixelFormat] ||
1185 RGB_BLUE!=tjBlueOffset[pixelFormat] ||
1186 RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
1187 {
1188 rgbBuf=(unsigned char *)malloc(width*height*3);
1189 if(!rgbBuf) _throw("tjDecompress2(): Memory allocation failure");
1190 _pitch=pitch; pitch=width*3;
1191 _dstBuf=dstBuf; dstBuf=rgbBuf;
1192 }
1193 #endif
1194
DRC9b28def2011-05-21 14:37:15 +00001195 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
1196 *dinfo->output_height))==NULL)
DRC007a42c2011-05-22 13:55:56 +00001197 _throw("tjDecompress2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +00001198 for(i=0; i<(int)dinfo->output_height; i++)
1199 {
DRC25b995a2011-05-21 15:34:54 +00001200 if(flags&TJFLAG_BOTTOMUP)
DRC9b28def2011-05-21 14:37:15 +00001201 row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*pitch];
1202 else row_pointer[i]=&dstBuf[i*pitch];
1203 }
1204 while(dinfo->output_scanline<dinfo->output_height)
1205 {
1206 jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline],
1207 dinfo->output_height-dinfo->output_scanline);
1208 }
1209 jpeg_finish_decompress(dinfo);
1210
DRCafc06922012-03-23 19:47:57 +00001211 #ifndef JCS_EXTENSIONS
1212 fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
1213 #endif
1214
DRC9b28def2011-05-21 14:37:15 +00001215 bailout:
1216 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
DRCafc06922012-03-23 19:47:57 +00001217 #ifndef JCS_EXTENSIONS
DRCea3396a2012-04-26 03:18:49 +00001218 if(rgbBuf) free(rgbBuf);
DRCafc06922012-03-23 19:47:57 +00001219 #endif
DRC9b28def2011-05-21 14:37:15 +00001220 if(row_pointer) free(row_pointer);
1221 return retval;
1222}
1223
1224DLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf,
1225 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
1226 int height, int pixelSize, int flags)
1227{
1228 if(flags&TJ_YUV)
1229 return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags);
1230 else
1231 return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch,
1232 height, getPixelFormat(pixelSize, flags), flags);
1233}
1234
1235
DRC34dca052014-02-28 09:17:14 +00001236static int setDecodeDefaults(struct jpeg_decompress_struct *dinfo,
1237 int pixelFormat, int subsamp, int flags)
1238{
DRC895fd6d2014-02-28 09:35:34 +00001239 int i;
1240
DRC34dca052014-02-28 09:17:14 +00001241 dinfo->scale_num=dinfo->scale_denom=1;
1242
1243 if(subsamp==TJSAMP_GRAY)
1244 {
DRCc9014492014-03-10 09:34:04 +00001245 dinfo->num_components=dinfo->comps_in_scan=1;
DRC34dca052014-02-28 09:17:14 +00001246 dinfo->jpeg_color_space=JCS_GRAYSCALE;
1247 }
1248 else
1249 {
DRCc9014492014-03-10 09:34:04 +00001250 dinfo->num_components=dinfo->comps_in_scan=3;
DRC34dca052014-02-28 09:17:14 +00001251 dinfo->jpeg_color_space=JCS_YCbCr;
1252 }
1253
1254 dinfo->comp_info=(jpeg_component_info *)
1255 (*dinfo->mem->alloc_small)((j_common_ptr)dinfo, JPOOL_IMAGE,
1256 dinfo->num_components*SIZEOF(jpeg_component_info));
1257
DRC2bdc0422014-03-07 03:52:57 +00001258 for(i=0; i<dinfo->num_components; i++)
DRC34dca052014-02-28 09:17:14 +00001259 {
DRC2bdc0422014-03-07 03:52:57 +00001260 jpeg_component_info *compptr=&dinfo->comp_info[i];
1261 compptr->h_samp_factor=(i==0)? tjMCUWidth[subsamp]/8:1;
1262 compptr->v_samp_factor=(i==0)? tjMCUHeight[subsamp]/8:1;
1263 compptr->component_index=i;
DRC15c08762014-03-10 20:11:56 +00001264 compptr->component_id=i+1;
DRC2bdc0422014-03-07 03:52:57 +00001265 compptr->quant_tbl_no=compptr->dc_tbl_no=compptr->ac_tbl_no=
1266 (i==0)? 0:1;
1267 dinfo->cur_comp_info[i]=compptr;
DRC34dca052014-02-28 09:17:14 +00001268 }
DRCc9014492014-03-10 09:34:04 +00001269 dinfo->data_precision=8;
1270 for(i=0; i<2; i++)
1271 {
1272 if(dinfo->quant_tbl_ptrs[i]==NULL)
1273 dinfo->quant_tbl_ptrs[i]=jpeg_alloc_quant_table((j_common_ptr)dinfo);
1274 }
DRC34dca052014-02-28 09:17:14 +00001275
1276 return 0;
1277}
1278
1279
1280int my_read_markers(j_decompress_ptr dinfo)
1281{
1282 return JPEG_REACHED_SOS;
1283}
1284
1285void my_reset_marker_reader(j_decompress_ptr dinfo)
1286{
1287}
1288
1289DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, unsigned char *srcBuf,
1290 int pad, int subsamp, unsigned char *dstBuf, int width, int pitch,
1291 int height, int pixelFormat, int flags)
1292{
1293 int i, retval=0; JSAMPROW *row_pointer=NULL;
1294 JSAMPLE *_tmpbuf[MAX_COMPONENTS];
1295 JSAMPROW *tmpbuf[MAX_COMPONENTS], *inbuf[MAX_COMPONENTS];
DRC7d9f7582014-03-10 20:14:53 +00001296 int row, pw, ph, cw[MAX_COMPONENTS], ch[MAX_COMPONENTS];
DRC34dca052014-02-28 09:17:14 +00001297 JSAMPLE *ptr=srcBuf;
1298 unsigned long yuvsize=0;
1299 jpeg_component_info *compptr;
1300 #ifndef JCS_EXTENSIONS
1301 unsigned char *rgbBuf=NULL;
1302 #endif
1303 JMETHOD(int, old_read_markers, (j_decompress_ptr));
1304 JMETHOD(void, old_reset_marker_reader, (j_decompress_ptr));
1305
1306 getinstance(handle);
1307
1308 for(i=0; i<MAX_COMPONENTS; i++)
1309 {
1310 tmpbuf[i]=NULL; _tmpbuf[i]=NULL; inbuf[i]=NULL;
1311 }
1312
1313 if((this->init&DECOMPRESS)==0)
1314 _throw("tjDecodeYUV(): Instance has not been initialized for compression");
1315
1316 if(srcBuf==NULL || pad<0 || !isPow2(pad) || subsamp<0 || subsamp>=NUMSUBOPT
1317 || dstBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
1318 || pixelFormat>=TJ_NUMPF)
1319 _throw("tjDecodeYUV(): Invalid argument");
1320
1321 if(setjmp(this->jerr.setjmp_buffer))
1322 {
1323 /* If we get here, the JPEG code has signaled an error. */
1324 retval=-1;
1325 goto bailout;
1326 }
1327
1328 if(pixelFormat==TJPF_CMYK)
1329 _throw("tjDecodeYUV(): Cannot decode YUV images into CMYK pixels.");
1330
1331 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
1332
1333 #ifndef JCS_EXTENSIONS
1334 if(pixelFormat!=TJPF_GRAY)
1335 {
1336 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
1337 if(!rgbBuf) _throw("tjDecodeYUV(): Memory allocation failure");
1338 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
1339 pitch=width*RGB_PIXELSIZE;
1340 }
1341 #endif
1342
1343 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
1376 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph))==NULL)
1377 _throw("tjDecodeYUV(): Memory allocation failure");
1378 for(i=0; i<height; i++)
1379 {
1380 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&dstBuf[(height-i-1)*pitch];
1381 else row_pointer[i]=&dstBuf[i*pitch];
1382 }
1383 if(height<ph)
1384 for(i=height; i<ph; i++) row_pointer[i]=row_pointer[height-1];
1385
1386 for(i=0; i<dinfo->num_components; i++)
1387 {
1388 compptr=&dinfo->comp_info[i];
1389 _tmpbuf[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
1390 * compptr->v_samp_factor + 16);
1391 if(!_tmpbuf[i]) _throw("tjDecodeYUV(): Memory allocation failure");
1392 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
1393 if(!tmpbuf[i]) _throw("tjDecodeYUV(): Memory allocation failure");
1394 for(row=0; row<compptr->v_samp_factor; row++)
1395 {
1396 unsigned char *_tmpbuf_aligned=
1397 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
1398 tmpbuf[i][row]=&_tmpbuf_aligned[
1399 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
1400 }
1401 cw[i]=pw*compptr->h_samp_factor/dinfo->max_h_samp_factor;
1402 ch[i]=ph*compptr->v_samp_factor/dinfo->max_v_samp_factor;
1403 inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]);
1404 if(!inbuf[i]) _throw("tjDecodeYUV(): Memory allocation failure");
1405 for(row=0; row<ch[i]; row++)
1406 {
1407 inbuf[i][row]=ptr;
1408 ptr+=PAD(cw[i], pad);
1409 }
1410 }
1411
1412 if(yuvsize!=(unsigned long)(ptr-srcBuf))
1413 _throw("tjDecodeYUV(): YUV image is not the correct size");
1414
1415 for(row=0; row<ph; row+=dinfo->max_v_samp_factor)
1416 {
1417 JDIMENSION inrow=0, outrow=0;
1418 for(i=0, compptr=dinfo->comp_info; i<dinfo->num_components; i++, compptr++)
1419 jcopy_sample_rows(inbuf[i],
1420 row*compptr->v_samp_factor/dinfo->max_v_samp_factor, tmpbuf[i], 0,
1421 compptr->v_samp_factor, cw[i]);
1422 (dinfo->upsample->upsample)(dinfo, tmpbuf, &inrow,
1423 dinfo->max_v_samp_factor, &row_pointer[row], &outrow,
1424 dinfo->max_v_samp_factor);
1425 }
1426 jpeg_abort_decompress(dinfo);
1427
1428 bailout:
1429 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
1430 #ifndef JCS_EXTENSIONS
1431 if(rgbBuf) free(rgbBuf);
1432 #endif
1433 if(row_pointer) free(row_pointer);
1434 for(i=0; i<MAX_COMPONENTS; i++)
1435 {
1436 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
1437 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
1438 if(inbuf[i]!=NULL) free(inbuf[i]);
1439 }
1440 return retval;
1441}
1442
1443
DRCf610d612013-04-26 10:33:29 +00001444DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle,
DRC9b28def2011-05-21 14:37:15 +00001445 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
DRCf610d612013-04-26 10:33:29 +00001446 int width, int pad, int height, int flags)
DRC9b28def2011-05-21 14:37:15 +00001447{
DRCf610d612013-04-26 10:33:29 +00001448 int i, sfi, row, retval=0; JSAMPROW *outbuf[MAX_COMPONENTS];
DRC418fe282013-05-07 21:17:35 +00001449 int jpegwidth, jpegheight, jpegSubsamp, scaledw, scaledh;
DRC9b28def2011-05-21 14:37:15 +00001450 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS],
1451 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
1452 JSAMPLE *_tmpbuf=NULL, *ptr=dstBuf; JSAMPROW *tmpbuf[MAX_COMPONENTS];
DRC418fe282013-05-07 21:17:35 +00001453 int dctsize;
DRC9b28def2011-05-21 14:37:15 +00001454
DRCb51ee892013-10-31 05:00:19 +00001455 getinstance(handle);
1456
DRCf9cf5c72010-12-10 10:58:49 +00001457 for(i=0; i<MAX_COMPONENTS; i++)
1458 {
1459 tmpbuf[i]=NULL; outbuf[i]=NULL;
1460 }
DRC9e17f7d2010-12-10 04:59:13 +00001461
DRCe2f8e692013-10-30 22:21:06 +00001462 if((this->init&DECOMPRESS)==0)
1463 _throw("tjDecompressToYUV2(): Instance has not been initialized for decompression");
1464
DRCf610d612013-04-26 10:33:29 +00001465 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pad<1
1466 || !isPow2(pad) || height<0)
1467 _throw("tjDecompressToYUV2(): Invalid argument");
DRC2e7b76b2009-04-03 12:04:24 +00001468
DRC25b995a2011-05-21 15:34:54 +00001469 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1470 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1471 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC0c6a2712010-02-22 08:34:44 +00001472
DRC9b28def2011-05-21 14:37:15 +00001473 if(setjmp(this->jerr.setjmp_buffer))
1474 {
1475 /* If we get here, the JPEG code has signaled an error. */
DRC91e86ba2011-02-15 05:24:08 +00001476 retval=-1;
1477 goto bailout;
DRC9e17f7d2010-12-10 04:59:13 +00001478 }
DRC2e7b76b2009-04-03 12:04:24 +00001479
DRC9b28def2011-05-21 14:37:15 +00001480 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1481 jpeg_read_header(dinfo, TRUE);
DRC418fe282013-05-07 21:17:35 +00001482 jpegSubsamp=getSubsamp(dinfo);
1483 if(jpegSubsamp<0)
DRC910a3572013-10-30 23:02:57 +00001484 _throw("tjDecompressToYUV2(): Could not determine subsampling type for JPEG image");
DRC2e7b76b2009-04-03 12:04:24 +00001485
DRCf610d612013-04-26 10:33:29 +00001486 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
1487 if(width==0) width=jpegwidth;
1488 if(height==0) height=jpegheight;
1489 for(i=0; i<NUMSF; i++)
1490 {
1491 scaledw=TJSCALED(jpegwidth, sf[i]);
1492 scaledh=TJSCALED(jpegheight, sf[i]);
1493 if(scaledw<=width && scaledh<=height)
1494 break;
1495 }
1496 if(scaledw>width || scaledh>height)
1497 _throw("tjDecompressToYUV2(): Could not scale down to desired image dimensions");
DRCcd7c3e62013-08-23 02:49:25 +00001498 if(dinfo->num_components>3)
1499 _throw("tjDecompressToYUV2(): JPEG image must have 3 or fewer components");
1500
DRCf610d612013-04-26 10:33:29 +00001501 width=scaledw; height=scaledh;
1502 dinfo->scale_num=sf[i].num;
1503 dinfo->scale_denom=sf[i].denom;
1504 sfi=i;
1505 jpeg_calc_output_dimensions(dinfo);
1506
DRC418fe282013-05-07 21:17:35 +00001507 dctsize=DCTSIZE*sf[sfi].num/sf[sfi].denom;
1508
DRC9b28def2011-05-21 14:37:15 +00001509 for(i=0; i<dinfo->num_components; i++)
DRC2e7b76b2009-04-03 12:04:24 +00001510 {
DRC9b28def2011-05-21 14:37:15 +00001511 jpeg_component_info *compptr=&dinfo->comp_info[i];
1512 int ih;
DRC418fe282013-05-07 21:17:35 +00001513 iw[i]=compptr->width_in_blocks*dctsize;
1514 ih=compptr->height_in_blocks*dctsize;
DRCf610d612013-04-26 10:33:29 +00001515 cw[i]=PAD(dinfo->output_width, dinfo->max_h_samp_factor)
DRC9b28def2011-05-21 14:37:15 +00001516 *compptr->h_samp_factor/dinfo->max_h_samp_factor;
DRCf610d612013-04-26 10:33:29 +00001517 ch[i]=PAD(dinfo->output_height, dinfo->max_v_samp_factor)
DRC9b28def2011-05-21 14:37:15 +00001518 *compptr->v_samp_factor/dinfo->max_v_samp_factor;
1519 if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1;
DRC418fe282013-05-07 21:17:35 +00001520 th[i]=compptr->v_samp_factor*dctsize;
DRC9b28def2011-05-21 14:37:15 +00001521 tmpbufsize+=iw[i]*th[i];
1522 if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL)
DRCf610d612013-04-26 10:33:29 +00001523 _throw("tjDecompressToYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +00001524 for(row=0; row<ch[i]; row++)
1525 {
1526 outbuf[i][row]=ptr;
DRCf610d612013-04-26 10:33:29 +00001527 ptr+=PAD(cw[i], pad);
DRC9b28def2011-05-21 14:37:15 +00001528 }
1529 }
1530 if(usetmpbuf)
1531 {
1532 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
DRCf610d612013-04-26 10:33:29 +00001533 _throw("tjDecompressToYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +00001534 ptr=_tmpbuf;
1535 for(i=0; i<dinfo->num_components; i++)
1536 {
1537 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
DRCf610d612013-04-26 10:33:29 +00001538 _throw("tjDecompressToYUV2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +00001539 for(row=0; row<th[i]; row++)
1540 {
1541 tmpbuf[i][row]=ptr;
1542 ptr+=iw[i];
1543 }
1544 }
1545 }
DRC9e17f7d2010-12-10 04:59:13 +00001546
DRC25b995a2011-05-21 15:34:54 +00001547 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
DRCe0419b52012-07-03 20:01:31 +00001548 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
DRC9b28def2011-05-21 14:37:15 +00001549 dinfo->raw_data_out=TRUE;
1550
1551 jpeg_start_decompress(dinfo);
1552 for(row=0; row<(int)dinfo->output_height;
DRC418fe282013-05-07 21:17:35 +00001553 row+=dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size)
DRC9b28def2011-05-21 14:37:15 +00001554 {
1555 JSAMPARRAY yuvptr[MAX_COMPONENTS];
1556 int crow[MAX_COMPONENTS];
DRC9e17f7d2010-12-10 04:59:13 +00001557 for(i=0; i<dinfo->num_components; i++)
1558 {
1559 jpeg_component_info *compptr=&dinfo->comp_info[i];
DRC418fe282013-05-07 21:17:35 +00001560 if(jpegSubsamp==TJ_420)
1561 {
1562 /* When 4:2:0 subsampling is used with IDCT scaling, libjpeg will try
1563 to be clever and use the IDCT to perform upsampling on the U and V
1564 planes. For instance, if the output image is to be scaled by 1/2
1565 relative to the JPEG image, then the scaling factor and upsampling
1566 effectively cancel each other, so a normal 8x8 IDCT can be used.
1567 However, this is not desirable when using the decompress-to-YUV
1568 functionality in TurboJPEG, since we want to output the U and V
1569 planes in their subsampled form. Thus, we have to override some
1570 internal libjpeg parameters to force it to use the "scaled" IDCT
1571 functions on the U and V planes. */
1572 compptr->_DCT_scaled_size=dctsize;
1573 compptr->MCU_sample_width=tjMCUWidth[jpegSubsamp]*
1574 sf[sfi].num/sf[sfi].denom*
1575 compptr->v_samp_factor/dinfo->max_v_samp_factor;
1576 dinfo->idct->inverse_DCT[i] = dinfo->idct->inverse_DCT[0];
1577 }
DRC9b28def2011-05-21 14:37:15 +00001578 crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
1579 if(usetmpbuf) yuvptr[i]=tmpbuf[i];
1580 else yuvptr[i]=&outbuf[i][crow[i]];
DRCf9cf5c72010-12-10 10:58:49 +00001581 }
DRCf610d612013-04-26 10:33:29 +00001582 jpeg_read_raw_data(dinfo, yuvptr,
DRC418fe282013-05-07 21:17:35 +00001583 dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size);
DRCf9cf5c72010-12-10 10:58:49 +00001584 if(usetmpbuf)
1585 {
DRC9b28def2011-05-21 14:37:15 +00001586 int j;
DRCf9cf5c72010-12-10 10:58:49 +00001587 for(i=0; i<dinfo->num_components; i++)
1588 {
DRC9b28def2011-05-21 14:37:15 +00001589 for(j=0; j<min(th[i], ch[i]-crow[i]); j++)
DRCf9cf5c72010-12-10 10:58:49 +00001590 {
DRC9b28def2011-05-21 14:37:15 +00001591 memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], cw[i]);
DRCf9cf5c72010-12-10 10:58:49 +00001592 }
DRC9e17f7d2010-12-10 04:59:13 +00001593 }
1594 }
1595 }
DRC9b28def2011-05-21 14:37:15 +00001596 jpeg_finish_decompress(dinfo);
DRC2e7b76b2009-04-03 12:04:24 +00001597
DRC91e86ba2011-02-15 05:24:08 +00001598 bailout:
DRC9b28def2011-05-21 14:37:15 +00001599 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
DRC9e17f7d2010-12-10 04:59:13 +00001600 for(i=0; i<MAX_COMPONENTS; i++)
DRCf9cf5c72010-12-10 10:58:49 +00001601 {
1602 if(tmpbuf[i]) free(tmpbuf[i]);
DRC9e17f7d2010-12-10 04:59:13 +00001603 if(outbuf[i]) free(outbuf[i]);
DRCf9cf5c72010-12-10 10:58:49 +00001604 }
1605 if(_tmpbuf) free(_tmpbuf);
DRC91e86ba2011-02-15 05:24:08 +00001606 return retval;
DRC2e7b76b2009-04-03 12:04:24 +00001607}
1608
DRCf610d612013-04-26 10:33:29 +00001609DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle,
1610 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
1611 int flags)
1612{
1613 return tjDecompressToYUV2(handle, jpegBuf, jpegSize, dstBuf, 0, 4, 0, flags);
1614}
1615
DRC2e7b76b2009-04-03 12:04:24 +00001616
DRC9b28def2011-05-21 14:37:15 +00001617/* Transformer */
DRC890f1e02011-02-26 22:02:37 +00001618
1619DLLEXPORT tjhandle DLLCALL tjInitTransform(void)
1620{
DRC9b28def2011-05-21 14:37:15 +00001621 tjinstance *this=NULL; tjhandle handle=NULL;
1622 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
DRCda5220a2011-03-02 02:17:30 +00001623 {
DRC007a42c2011-05-22 13:55:56 +00001624 snprintf(errStr, JMSG_LENGTH_MAX,
1625 "tjInitTransform(): Memory allocation failure");
DRCda5220a2011-03-02 02:17:30 +00001626 return NULL;
1627 }
DRC007a42c2011-05-22 13:55:56 +00001628 MEMZERO(this, sizeof(tjinstance));
DRC9b28def2011-05-21 14:37:15 +00001629 handle=_tjInitCompress(this);
1630 if(!handle) return NULL;
1631 handle=_tjInitDecompress(this);
1632 return handle;
DRC890f1e02011-02-26 22:02:37 +00001633}
1634
1635
DRC9b28def2011-05-21 14:37:15 +00001636DLLEXPORT int DLLCALL tjTransform(tjhandle handle, unsigned char *jpegBuf,
1637 unsigned long jpegSize, int n, unsigned char **dstBufs,
1638 unsigned long *dstSizes, tjtransform *t, int flags)
DRC890f1e02011-02-26 22:02:37 +00001639{
DRC0a325192011-03-02 09:22:41 +00001640 jpeg_transform_info *xinfo=NULL;
DRC890f1e02011-02-26 22:02:37 +00001641 jvirt_barray_ptr *srccoefs, *dstcoefs;
DRC9b49f0e2011-07-12 03:17:23 +00001642 int retval=0, i, jpegSubsamp;
DRC890f1e02011-02-26 22:02:37 +00001643
DRC9b28def2011-05-21 14:37:15 +00001644 getinstance(handle);
1645 if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +00001646 _throw("tjTransform(): Instance has not been initialized for transformation");
DRC890f1e02011-02-26 22:02:37 +00001647
DRC9b28def2011-05-21 14:37:15 +00001648 if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL
1649 || t==NULL || flags<0)
1650 _throw("tjTransform(): Invalid argument");
1651
DRC25b995a2011-05-21 15:34:54 +00001652 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1653 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1654 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC890f1e02011-02-26 22:02:37 +00001655
DRC9b28def2011-05-21 14:37:15 +00001656 if(setjmp(this->jerr.setjmp_buffer))
1657 {
1658 /* If we get here, the JPEG code has signaled an error. */
DRC890f1e02011-02-26 22:02:37 +00001659 retval=-1;
1660 goto bailout;
1661 }
1662
DRC9b28def2011-05-21 14:37:15 +00001663 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
DRC890f1e02011-02-26 22:02:37 +00001664
DRC0a325192011-03-02 09:22:41 +00001665 if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n))
1666 ==NULL)
DRC007a42c2011-05-22 13:55:56 +00001667 _throw("tjTransform(): Memory allocation failure");
1668 MEMZERO(xinfo, sizeof(jpeg_transform_info)*n);
DRC890f1e02011-02-26 22:02:37 +00001669
DRC0a325192011-03-02 09:22:41 +00001670 for(i=0; i<n; i++)
DRC890f1e02011-02-26 22:02:37 +00001671 {
DRC0a325192011-03-02 09:22:41 +00001672 xinfo[i].transform=xformtypes[t[i].op];
DRC25b995a2011-05-21 15:34:54 +00001673 xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0;
1674 xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0;
1675 xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0;
1676 xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0;
1677 if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1;
DRCba5ea512011-03-04 03:20:34 +00001678 else xinfo[i].slow_hflip=0;
DRC0a325192011-03-02 09:22:41 +00001679
1680 if(xinfo[i].crop)
DRC890f1e02011-02-26 22:02:37 +00001681 {
DRC0a325192011-03-02 09:22:41 +00001682 xinfo[i].crop_xoffset=t[i].r.x; xinfo[i].crop_xoffset_set=JCROP_POS;
1683 xinfo[i].crop_yoffset=t[i].r.y; xinfo[i].crop_yoffset_set=JCROP_POS;
1684 if(t[i].r.w!=0)
1685 {
1686 xinfo[i].crop_width=t[i].r.w; xinfo[i].crop_width_set=JCROP_POS;
1687 }
DRCd932e582011-03-15 20:09:47 +00001688 else xinfo[i].crop_width=JCROP_UNSET;
DRC0a325192011-03-02 09:22:41 +00001689 if(t[i].r.h!=0)
1690 {
1691 xinfo[i].crop_height=t[i].r.h; xinfo[i].crop_height_set=JCROP_POS;
1692 }
DRCd932e582011-03-15 20:09:47 +00001693 else xinfo[i].crop_height=JCROP_UNSET;
DRC890f1e02011-02-26 22:02:37 +00001694 }
1695 }
1696
DRC9b28def2011-05-21 14:37:15 +00001697 jcopy_markers_setup(dinfo, JCOPYOPT_ALL);
1698 jpeg_read_header(dinfo, TRUE);
DRC9b49f0e2011-07-12 03:17:23 +00001699 jpegSubsamp=getSubsamp(dinfo);
1700 if(jpegSubsamp<0)
1701 _throw("tjTransform(): Could not determine subsampling type for JPEG image");
DRC890f1e02011-02-26 22:02:37 +00001702
DRC0a325192011-03-02 09:22:41 +00001703 for(i=0; i<n; i++)
DRC890f1e02011-02-26 22:02:37 +00001704 {
DRC9b28def2011-05-21 14:37:15 +00001705 if(!jtransform_request_workspace(dinfo, &xinfo[i]))
DRC007a42c2011-05-22 13:55:56 +00001706 _throw("tjTransform(): Transform is not perfect");
DRC890f1e02011-02-26 22:02:37 +00001707
DRC0a325192011-03-02 09:22:41 +00001708 if(xinfo[i].crop)
DRC890f1e02011-02-26 22:02:37 +00001709 {
DRC0a325192011-03-02 09:22:41 +00001710 if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0
1711 || (t[i].r.y%xinfo[i].iMCU_sample_height)!=0)
1712 {
DRC9b28def2011-05-21 14:37:15 +00001713 snprintf(errStr, JMSG_LENGTH_MAX,
DRC0a325192011-03-02 09:22:41 +00001714 "To crop this JPEG image, x must be a multiple of %d\n"
1715 "and y must be a multiple of %d.\n",
1716 xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height);
1717 retval=-1; goto bailout;
1718 }
DRC890f1e02011-02-26 22:02:37 +00001719 }
1720 }
1721
DRC9b28def2011-05-21 14:37:15 +00001722 srccoefs=jpeg_read_coefficients(dinfo);
DRC890f1e02011-02-26 22:02:37 +00001723
DRC0a325192011-03-02 09:22:41 +00001724 for(i=0; i<n; i++)
1725 {
DRCff78e372011-05-24 10:17:32 +00001726 int w, h, alloc=1;
DRC0a325192011-03-02 09:22:41 +00001727 if(!xinfo[i].crop)
1728 {
DRC9b28def2011-05-21 14:37:15 +00001729 w=dinfo->image_width; h=dinfo->image_height;
DRC0a325192011-03-02 09:22:41 +00001730 }
1731 else
1732 {
1733 w=xinfo[i].crop_width; h=xinfo[i].crop_height;
1734 }
DRCff78e372011-05-24 10:17:32 +00001735 if(flags&TJFLAG_NOREALLOC)
1736 {
DRC9b49f0e2011-07-12 03:17:23 +00001737 alloc=0; dstSizes[i]=tjBufSize(w, h, jpegSubsamp);
DRCff78e372011-05-24 10:17:32 +00001738 }
DRC7bf04d32011-09-17 00:18:31 +00001739 if(!(t[i].options&TJXOPT_NOOUTPUT))
1740 jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc);
DRC9b28def2011-05-21 14:37:15 +00001741 jpeg_copy_critical_parameters(dinfo, cinfo);
1742 dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs,
DRC0a325192011-03-02 09:22:41 +00001743 &xinfo[i]);
DRC7bf04d32011-09-17 00:18:31 +00001744 if(!(t[i].options&TJXOPT_NOOUTPUT))
1745 {
1746 jpeg_write_coefficients(cinfo, dstcoefs);
1747 jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL);
1748 }
1749 else jinit_c_master_control(cinfo, TRUE);
DRC9b28def2011-05-21 14:37:15 +00001750 jtransform_execute_transformation(dinfo, cinfo, srccoefs,
DRC0a325192011-03-02 09:22:41 +00001751 &xinfo[i]);
DRC7bf04d32011-09-17 00:18:31 +00001752 if(t[i].customFilter)
1753 {
DRCefe28ce2012-01-17 11:48:38 +00001754 int ci, y; JDIMENSION by;
DRC7bf04d32011-09-17 00:18:31 +00001755 for(ci=0; ci<cinfo->num_components; ci++)
1756 {
1757 jpeg_component_info *compptr=&cinfo->comp_info[ci];
1758 tjregion arrayRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
1759 DCTSIZE};
1760 tjregion planeRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
1761 compptr->height_in_blocks*DCTSIZE};
1762 for(by=0; by<compptr->height_in_blocks; by+=compptr->v_samp_factor)
1763 {
1764 JBLOCKARRAY barray=(dinfo->mem->access_virt_barray)
1765 ((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor,
1766 TRUE);
1767 for(y=0; y<compptr->v_samp_factor; y++)
1768 {
1769 if(t[i].customFilter(barray[y][0], arrayRegion, planeRegion,
DRCf5467112011-09-20 05:02:19 +00001770 ci, i, &t[i])==-1)
DRC7bf04d32011-09-17 00:18:31 +00001771 _throw("tjTransform(): Error in custom filter");
1772 arrayRegion.y+=DCTSIZE;
1773 }
1774 }
1775 }
1776 }
1777 if(!(t[i].options&TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo);
DRC0a325192011-03-02 09:22:41 +00001778 }
1779
DRC9b28def2011-05-21 14:37:15 +00001780 jpeg_finish_decompress(dinfo);
DRC890f1e02011-02-26 22:02:37 +00001781
DRC890f1e02011-02-26 22:02:37 +00001782 bailout:
DRC9b28def2011-05-21 14:37:15 +00001783 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
1784 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
DRC0a325192011-03-02 09:22:41 +00001785 if(xinfo) free(xinfo);
DRC890f1e02011-02-26 22:02:37 +00001786 return retval;
1787}