blob: 6b2c62320cd982eb9d4b2589ace618e23d5bfd16 [file] [log] [blame]
DRC9b28def2011-05-21 14:37:15 +00001/*
DRC1f79c7c2015-06-01 19:22:41 +00002 * Copyright (C)2009-2015 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>
DRC0713c1b2014-08-22 13:43:33 +000034#include <ctype.h>
DRC296c71b2011-05-25 04:12:52 +000035#include <jinclude.h>
DRCfbb67472010-11-24 04:02:37 +000036#define JPEG_INTERNALS
DRC2e7b76b2009-04-03 12:04:24 +000037#include <jpeglib.h>
38#include <jerror.h>
39#include <setjmp.h>
40#include "./turbojpeg.h"
DRCa29294a2011-05-24 09:17:57 +000041#include "./tjutil.h"
DRC890f1e02011-02-26 22:02:37 +000042#include "transupp.h"
DRC418fe282013-05-07 21:17:35 +000043#include "./jpegcomp.h"
DRC2a2e4512011-01-05 22:33:24 +000044
DRC9b28def2011-05-21 14:37:15 +000045extern void jpeg_mem_dest_tj(j_compress_ptr, unsigned char **,
46 unsigned long *, boolean);
47extern void jpeg_mem_src_tj(j_decompress_ptr, unsigned char *, unsigned long);
48
DRCfbb67472010-11-24 04:02:37 +000049#define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
DRCf610d612013-04-26 10:33:29 +000050#define isPow2(x) (((x)&(x-1))==0)
DRC2e7b76b2009-04-03 12:04:24 +000051
52
DRC9b28def2011-05-21 14:37:15 +000053/* Error handling (based on example in example.c) */
DRC2e7b76b2009-04-03 12:04:24 +000054
DRC9b28def2011-05-21 14:37:15 +000055static char errStr[JMSG_LENGTH_MAX]="No error";
DRC2e7b76b2009-04-03 12:04:24 +000056
DRC9b28def2011-05-21 14:37:15 +000057struct my_error_mgr
DRC2e7b76b2009-04-03 12:04:24 +000058{
59 struct jpeg_error_mgr pub;
DRC9b28def2011-05-21 14:37:15 +000060 jmp_buf setjmp_buffer;
DRC1f79c7c2015-06-01 19:22:41 +000061 void (*emit_message)(j_common_ptr, int);
62 boolean warning;
DRC9b28def2011-05-21 14:37:15 +000063};
64typedef struct my_error_mgr *my_error_ptr;
DRC2e7b76b2009-04-03 12:04:24 +000065
66static void my_error_exit(j_common_ptr cinfo)
67{
DRC9b28def2011-05-21 14:37:15 +000068 my_error_ptr myerr=(my_error_ptr)cinfo->err;
DRC2e7b76b2009-04-03 12:04:24 +000069 (*cinfo->err->output_message)(cinfo);
DRC9b28def2011-05-21 14:37:15 +000070 longjmp(myerr->setjmp_buffer, 1);
DRC2e7b76b2009-04-03 12:04:24 +000071}
72
DRC9b28def2011-05-21 14:37:15 +000073/* Based on output_message() in jerror.c */
74
DRC2e7b76b2009-04-03 12:04:24 +000075static void my_output_message(j_common_ptr cinfo)
76{
DRC9b28def2011-05-21 14:37:15 +000077 (*cinfo->err->format_message)(cinfo, errStr);
DRC2e7b76b2009-04-03 12:04:24 +000078}
79
DRC1f79c7c2015-06-01 19:22:41 +000080static void my_emit_message(j_common_ptr cinfo, int msg_level)
81{
82 my_error_ptr myerr=(my_error_ptr)cinfo->err;
83 myerr->emit_message(cinfo, msg_level);
84 if(msg_level<0) myerr->warning=TRUE;
85}
86
DRC2e7b76b2009-04-03 12:04:24 +000087
DRC9b28def2011-05-21 14:37:15 +000088/* Global structures, macros, etc. */
DRC2e7b76b2009-04-03 12:04:24 +000089
DRC9b28def2011-05-21 14:37:15 +000090enum {COMPRESS=1, DECOMPRESS=2};
91
92typedef struct _tjinstance
DRC2e7b76b2009-04-03 12:04:24 +000093{
94 struct jpeg_compress_struct cinfo;
95 struct jpeg_decompress_struct dinfo;
DRC9b28def2011-05-21 14:37:15 +000096 struct my_error_mgr jerr;
DRCaecea382014-08-11 18:05:41 +000097 int init, headerRead;
DRC9b28def2011-05-21 14:37:15 +000098} tjinstance;
DRC2e7b76b2009-04-03 12:04:24 +000099
DRC1f3635c2013-08-18 10:19:00 +0000100static const int pixelsize[TJ_NUMSAMP]={3, 3, 3, 1, 3, 3};
DRC9b28def2011-05-21 14:37:15 +0000101
DRC007a42c2011-05-22 13:55:56 +0000102static const JXFORM_CODE xformtypes[TJ_NUMXOP]=
103{
DRC890f1e02011-02-26 22:02:37 +0000104 JXFORM_NONE, JXFORM_FLIP_H, JXFORM_FLIP_V, JXFORM_TRANSPOSE,
105 JXFORM_TRANSVERSE, JXFORM_ROT_90, JXFORM_ROT_180, JXFORM_ROT_270
106};
DRC9b28def2011-05-21 14:37:15 +0000107
DRCab2df6e2012-01-28 06:49:56 +0000108#define NUMSF 16
DRC109a5782011-03-01 09:53:07 +0000109static const tjscalingfactor sf[NUMSF]={
DRCab2df6e2012-01-28 06:49:56 +0000110 {2, 1},
111 {15, 8},
112 {7, 4},
113 {13, 8},
114 {3, 2},
115 {11, 8},
116 {5, 4},
117 {9, 8},
DRC109a5782011-03-01 09:53:07 +0000118 {1, 1},
DRCab2df6e2012-01-28 06:49:56 +0000119 {7, 8},
120 {3, 4},
121 {5, 8},
DRC109a5782011-03-01 09:53:07 +0000122 {1, 2},
DRCab2df6e2012-01-28 06:49:56 +0000123 {3, 8},
DRC109a5782011-03-01 09:53:07 +0000124 {1, 4},
125 {1, 8}
126};
DRC2e7b76b2009-04-03 12:04:24 +0000127
DRCa29294a2011-05-24 09:17:57 +0000128#define _throw(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s", m); \
DRCda5220a2011-03-02 02:17:30 +0000129 retval=-1; goto bailout;}
DRC9b28def2011-05-21 14:37:15 +0000130#define getinstance(handle) tjinstance *this=(tjinstance *)handle; \
131 j_compress_ptr cinfo=NULL; j_decompress_ptr dinfo=NULL; \
132 if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
133 return -1;} \
DRC1f79c7c2015-06-01 19:22:41 +0000134 cinfo=&this->cinfo; dinfo=&this->dinfo; \
135 this->jerr.warning=FALSE;
DRC41861622014-04-16 23:38:37 +0000136#define getcinstance(handle) tjinstance *this=(tjinstance *)handle; \
137 j_compress_ptr cinfo=NULL; \
138 if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
139 return -1;} \
DRC1f79c7c2015-06-01 19:22:41 +0000140 cinfo=&this->cinfo; \
141 this->jerr.warning=FALSE;
DRC41861622014-04-16 23:38:37 +0000142#define getdinstance(handle) tjinstance *this=(tjinstance *)handle; \
143 j_decompress_ptr dinfo=NULL; \
144 if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
145 return -1;} \
DRC1f79c7c2015-06-01 19:22:41 +0000146 dinfo=&this->dinfo; \
147 this->jerr.warning=FALSE;
DRC2e7b76b2009-04-03 12:04:24 +0000148
DRC9b28def2011-05-21 14:37:15 +0000149static int getPixelFormat(int pixelSize, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000150{
DRC25b995a2011-05-21 15:34:54 +0000151 if(pixelSize==1) return TJPF_GRAY;
DRC9b28def2011-05-21 14:37:15 +0000152 if(pixelSize==3)
153 {
DRC25b995a2011-05-21 15:34:54 +0000154 if(flags&TJ_BGR) return TJPF_BGR;
155 else return TJPF_RGB;
DRC9b28def2011-05-21 14:37:15 +0000156 }
157 if(pixelSize==4)
158 {
159 if(flags&TJ_ALPHAFIRST)
160 {
DRC25b995a2011-05-21 15:34:54 +0000161 if(flags&TJ_BGR) return TJPF_XBGR;
162 else return TJPF_XRGB;
DRC9b28def2011-05-21 14:37:15 +0000163 }
164 else
165 {
DRC25b995a2011-05-21 15:34:54 +0000166 if(flags&TJ_BGR) return TJPF_BGRX;
167 else return TJPF_RGBX;
DRC9b28def2011-05-21 14:37:15 +0000168 }
169 }
170 return -1;
DRC2e7b76b2009-04-03 12:04:24 +0000171}
172
DRCf12bb302011-09-07 05:03:18 +0000173static int setCompDefaults(struct jpeg_compress_struct *cinfo,
DRC73d74c12012-06-29 23:46:38 +0000174 int pixelFormat, int subsamp, int jpegQual, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000175{
DRCf12bb302011-09-07 05:03:18 +0000176 int retval=0;
DRC0713c1b2014-08-22 13:43:33 +0000177 char *env=NULL;
DRCf12bb302011-09-07 05:03:18 +0000178
DRC9b28def2011-05-21 14:37:15 +0000179 switch(pixelFormat)
180 {
DRC25b995a2011-05-21 15:34:54 +0000181 case TJPF_GRAY:
DRC9b28def2011-05-21 14:37:15 +0000182 cinfo->in_color_space=JCS_GRAYSCALE; break;
183 #if JCS_EXTENSIONS==1
DRC25b995a2011-05-21 15:34:54 +0000184 case TJPF_RGB:
DRC9b28def2011-05-21 14:37:15 +0000185 cinfo->in_color_space=JCS_EXT_RGB; break;
DRC25b995a2011-05-21 15:34:54 +0000186 case TJPF_BGR:
DRC9b28def2011-05-21 14:37:15 +0000187 cinfo->in_color_space=JCS_EXT_BGR; break;
DRC25b995a2011-05-21 15:34:54 +0000188 case TJPF_RGBX:
DRC67ce3b22011-12-19 02:21:03 +0000189 case TJPF_RGBA:
DRC9b28def2011-05-21 14:37:15 +0000190 cinfo->in_color_space=JCS_EXT_RGBX; break;
DRC25b995a2011-05-21 15:34:54 +0000191 case TJPF_BGRX:
DRC67ce3b22011-12-19 02:21:03 +0000192 case TJPF_BGRA:
DRC9b28def2011-05-21 14:37:15 +0000193 cinfo->in_color_space=JCS_EXT_BGRX; break;
DRC25b995a2011-05-21 15:34:54 +0000194 case TJPF_XRGB:
DRC67ce3b22011-12-19 02:21:03 +0000195 case TJPF_ARGB:
DRC9b28def2011-05-21 14:37:15 +0000196 cinfo->in_color_space=JCS_EXT_XRGB; break;
DRC25b995a2011-05-21 15:34:54 +0000197 case TJPF_XBGR:
DRC67ce3b22011-12-19 02:21:03 +0000198 case TJPF_ABGR:
DRC9b28def2011-05-21 14:37:15 +0000199 cinfo->in_color_space=JCS_EXT_XBGR; break;
200 #else
DRC25b995a2011-05-21 15:34:54 +0000201 case TJPF_RGB:
DRCafc06922012-03-23 19:47:57 +0000202 case TJPF_BGR:
203 case TJPF_RGBX:
204 case TJPF_BGRX:
205 case TJPF_XRGB:
206 case TJPF_XBGR:
207 case TJPF_RGBA:
208 case TJPF_BGRA:
209 case TJPF_ARGB:
210 case TJPF_ABGR:
211 cinfo->in_color_space=JCS_RGB; pixelFormat=TJPF_RGB;
212 break;
DRC9b28def2011-05-21 14:37:15 +0000213 #endif
DRCcd7c3e62013-08-23 02:49:25 +0000214 case TJPF_CMYK:
215 cinfo->in_color_space=JCS_CMYK; break;
DRCefa4ddc2010-10-13 19:22:50 +0000216 }
DRC2e7b76b2009-04-03 12:04:24 +0000217
DRC9b28def2011-05-21 14:37:15 +0000218 cinfo->input_components=tjPixelSize[pixelFormat];
219 jpeg_set_defaults(cinfo);
DRC0713c1b2014-08-22 13:43:33 +0000220
DRCfeccdcf2015-02-23 19:19:40 +0000221#ifndef NO_GETENV
DRC0713c1b2014-08-22 13:43:33 +0000222 if((env=getenv("TJ_OPTIMIZE"))!=NULL && strlen(env)>0 && !strcmp(env, "1"))
223 cinfo->optimize_coding=TRUE;
224 if((env=getenv("TJ_ARITHMETIC"))!=NULL && strlen(env)>0 && !strcmp(env, "1"))
225 cinfo->arith_code=TRUE;
226 if((env=getenv("TJ_RESTART"))!=NULL && strlen(env)>0)
227 {
228 int temp=-1; char tempc=0;
229 if(sscanf(env, "%d%c", &temp, &tempc)>=1 && temp>=0 && temp<=65535)
230 {
231 if(toupper(tempc)=='B')
232 {
233 cinfo->restart_interval=temp;
234 cinfo->restart_in_rows=0;
235 }
236 else
237 cinfo->restart_in_rows=temp;
238 }
239 }
DRCfeccdcf2015-02-23 19:19:40 +0000240#endif
DRC0713c1b2014-08-22 13:43:33 +0000241
DRC9b28def2011-05-21 14:37:15 +0000242 if(jpegQual>=0)
243 {
244 jpeg_set_quality(cinfo, jpegQual, TRUE);
DRC73d74c12012-06-29 23:46:38 +0000245 if(jpegQual>=96 || flags&TJFLAG_ACCURATEDCT) cinfo->dct_method=JDCT_ISLOW;
DRC9b28def2011-05-21 14:37:15 +0000246 else cinfo->dct_method=JDCT_FASTEST;
247 }
DRC25b995a2011-05-21 15:34:54 +0000248 if(subsamp==TJSAMP_GRAY)
DRC9b28def2011-05-21 14:37:15 +0000249 jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
DRCcd7c3e62013-08-23 02:49:25 +0000250 else if(pixelFormat==TJPF_CMYK)
251 jpeg_set_colorspace(cinfo, JCS_YCCK);
252 else jpeg_set_colorspace(cinfo, JCS_YCbCr);
DRC2e7b76b2009-04-03 12:04:24 +0000253
DRCfeccdcf2015-02-23 19:19:40 +0000254#ifndef NO_GETENV
DRC0713c1b2014-08-22 13:43:33 +0000255 if((env=getenv("TJ_PROGRESSIVE"))!=NULL && strlen(env)>0
256 && !strcmp(env, "1"))
257 jpeg_simple_progression(cinfo);
DRCfeccdcf2015-02-23 19:19:40 +0000258#endif
DRC0713c1b2014-08-22 13:43:33 +0000259
DRC9b28def2011-05-21 14:37:15 +0000260 cinfo->comp_info[0].h_samp_factor=tjMCUWidth[subsamp]/8;
261 cinfo->comp_info[1].h_samp_factor=1;
262 cinfo->comp_info[2].h_samp_factor=1;
DRCcd7c3e62013-08-23 02:49:25 +0000263 if(cinfo->num_components>3)
264 cinfo->comp_info[3].h_samp_factor=tjMCUWidth[subsamp]/8;
DRC9b28def2011-05-21 14:37:15 +0000265 cinfo->comp_info[0].v_samp_factor=tjMCUHeight[subsamp]/8;
266 cinfo->comp_info[1].v_samp_factor=1;
267 cinfo->comp_info[2].v_samp_factor=1;
DRCcd7c3e62013-08-23 02:49:25 +0000268 if(cinfo->num_components>3)
269 cinfo->comp_info[3].v_samp_factor=tjMCUHeight[subsamp]/8;
DRCf12bb302011-09-07 05:03:18 +0000270
DRCf12bb302011-09-07 05:03:18 +0000271 return retval;
DRC9b28def2011-05-21 14:37:15 +0000272}
273
DRCf12bb302011-09-07 05:03:18 +0000274static int setDecompDefaults(struct jpeg_decompress_struct *dinfo,
DRC73d74c12012-06-29 23:46:38 +0000275 int pixelFormat, int flags)
DRC9b28def2011-05-21 14:37:15 +0000276{
DRCf12bb302011-09-07 05:03:18 +0000277 int retval=0;
278
DRC9b28def2011-05-21 14:37:15 +0000279 switch(pixelFormat)
280 {
DRC25b995a2011-05-21 15:34:54 +0000281 case TJPF_GRAY:
DRC9b28def2011-05-21 14:37:15 +0000282 dinfo->out_color_space=JCS_GRAYSCALE; break;
283 #if JCS_EXTENSIONS==1
DRC25b995a2011-05-21 15:34:54 +0000284 case TJPF_RGB:
DRC9b28def2011-05-21 14:37:15 +0000285 dinfo->out_color_space=JCS_EXT_RGB; break;
DRC25b995a2011-05-21 15:34:54 +0000286 case TJPF_BGR:
DRC9b28def2011-05-21 14:37:15 +0000287 dinfo->out_color_space=JCS_EXT_BGR; break;
DRC25b995a2011-05-21 15:34:54 +0000288 case TJPF_RGBX:
DRC9b28def2011-05-21 14:37:15 +0000289 dinfo->out_color_space=JCS_EXT_RGBX; break;
DRC25b995a2011-05-21 15:34:54 +0000290 case TJPF_BGRX:
DRC9b28def2011-05-21 14:37:15 +0000291 dinfo->out_color_space=JCS_EXT_BGRX; break;
DRC25b995a2011-05-21 15:34:54 +0000292 case TJPF_XRGB:
DRC9b28def2011-05-21 14:37:15 +0000293 dinfo->out_color_space=JCS_EXT_XRGB; break;
DRC25b995a2011-05-21 15:34:54 +0000294 case TJPF_XBGR:
DRC9b28def2011-05-21 14:37:15 +0000295 dinfo->out_color_space=JCS_EXT_XBGR; break;
DRC67ce3b22011-12-19 02:21:03 +0000296 #if JCS_ALPHA_EXTENSIONS==1
297 case TJPF_RGBA:
298 dinfo->out_color_space=JCS_EXT_RGBA; break;
299 case TJPF_BGRA:
300 dinfo->out_color_space=JCS_EXT_BGRA; break;
301 case TJPF_ARGB:
302 dinfo->out_color_space=JCS_EXT_ARGB; break;
303 case TJPF_ABGR:
304 dinfo->out_color_space=JCS_EXT_ABGR; break;
305 #endif
DRC9b28def2011-05-21 14:37:15 +0000306 #else
DRC25b995a2011-05-21 15:34:54 +0000307 case TJPF_RGB:
DRCafc06922012-03-23 19:47:57 +0000308 case TJPF_BGR:
309 case TJPF_RGBX:
310 case TJPF_BGRX:
311 case TJPF_XRGB:
312 case TJPF_XBGR:
313 case TJPF_RGBA:
314 case TJPF_BGRA:
315 case TJPF_ARGB:
316 case TJPF_ABGR:
317 dinfo->out_color_space=JCS_RGB; break;
DRC67ce3b22011-12-19 02:21:03 +0000318 #endif
DRCcd7c3e62013-08-23 02:49:25 +0000319 case TJPF_CMYK:
320 dinfo->out_color_space=JCS_CMYK; break;
DRC9b28def2011-05-21 14:37:15 +0000321 default:
322 _throw("Unsupported pixel format");
DRC9b28def2011-05-21 14:37:15 +0000323 }
DRCf12bb302011-09-07 05:03:18 +0000324
DRC73d74c12012-06-29 23:46:38 +0000325 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
326
DRCf12bb302011-09-07 05:03:18 +0000327 bailout:
DRCf12bb302011-09-07 05:03:18 +0000328 return retval;
DRC9b28def2011-05-21 14:37:15 +0000329}
330
331
DRC9b49f0e2011-07-12 03:17:23 +0000332static int getSubsamp(j_decompress_ptr dinfo)
333{
334 int retval=-1, i, k;
DRCea1eea42014-11-19 00:55:28 +0000335
336 /* The sampling factors actually have no meaning with grayscale JPEG files,
337 and in fact it's possible to generate grayscale JPEGs with sampling
338 factors > 1 (even though those sampling factors are ignored by the
339 decompressor.) Thus, we need to treat grayscale as a special case. */
340 if(dinfo->num_components==1 && dinfo->jpeg_color_space==JCS_GRAYSCALE)
341 return TJSAMP_GRAY;
342
DRC9b49f0e2011-07-12 03:17:23 +0000343 for(i=0; i<NUMSUBOPT; i++)
344 {
DRCcd7c3e62013-08-23 02:49:25 +0000345 if(dinfo->num_components==pixelsize[i]
346 || ((dinfo->jpeg_color_space==JCS_YCCK
347 || dinfo->jpeg_color_space==JCS_CMYK)
348 && pixelsize[i]==3 && dinfo->num_components==4))
DRC9b49f0e2011-07-12 03:17:23 +0000349 {
350 if(dinfo->comp_info[0].h_samp_factor==tjMCUWidth[i]/8
351 && dinfo->comp_info[0].v_samp_factor==tjMCUHeight[i]/8)
352 {
353 int match=0;
354 for(k=1; k<dinfo->num_components; k++)
355 {
DRCcd7c3e62013-08-23 02:49:25 +0000356 int href=1, vref=1;
357 if(dinfo->jpeg_color_space==JCS_YCCK && k==3)
358 {
359 href=tjMCUWidth[i]/8; vref=tjMCUHeight[i]/8;
360 }
361 if(dinfo->comp_info[k].h_samp_factor==href
362 && dinfo->comp_info[k].v_samp_factor==vref)
DRC9b49f0e2011-07-12 03:17:23 +0000363 match++;
364 }
365 if(match==dinfo->num_components-1)
366 {
367 retval=i; break;
368 }
369 }
370 }
371 }
372 return retval;
373}
374
375
DRCafc06922012-03-23 19:47:57 +0000376#ifndef JCS_EXTENSIONS
377
378/* Conversion functions to emulate the colorspace extensions. This allows the
379 TurboJPEG wrapper to be used with libjpeg */
380
381#define TORGB(PS, ROFFSET, GOFFSET, BOFFSET) { \
382 int rowPad=pitch-width*PS; \
383 while(height--) \
384 { \
385 unsigned char *endOfRow=src+width*PS; \
386 while(src<endOfRow) \
387 { \
388 dst[RGB_RED]=src[ROFFSET]; \
389 dst[RGB_GREEN]=src[GOFFSET]; \
390 dst[RGB_BLUE]=src[BOFFSET]; \
391 dst+=RGB_PIXELSIZE; src+=PS; \
392 } \
393 src+=rowPad; \
394 } \
395}
396
397static unsigned char *toRGB(unsigned char *src, int width, int pitch,
398 int height, int pixelFormat, unsigned char *dst)
399{
400 unsigned char *retval=src;
401 switch(pixelFormat)
402 {
403 case TJPF_RGB:
404 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3
405 retval=dst; TORGB(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 retval=dst; TORGB(3, 2, 1, 0);
411 #endif
412 break;
413 case TJPF_RGBX:
414 case TJPF_RGBA:
415 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
416 retval=dst; TORGB(4, 0, 1, 2);
417 #endif
418 break;
419 case TJPF_BGRX:
420 case TJPF_BGRA:
421 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
422 retval=dst; TORGB(4, 2, 1, 0);
423 #endif
424 break;
425 case TJPF_XRGB:
426 case TJPF_ARGB:
427 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
428 retval=dst; TORGB(4, 1, 2, 3);
429 #endif
430 break;
431 case TJPF_XBGR:
432 case TJPF_ABGR:
433 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
434 retval=dst; TORGB(4, 3, 2, 1);
435 #endif
436 break;
437 }
438 return retval;
439}
440
441#define FROMRGB(PS, ROFFSET, GOFFSET, BOFFSET, SETALPHA) { \
442 int rowPad=pitch-width*PS; \
443 while(height--) \
444 { \
445 unsigned char *endOfRow=dst+width*PS; \
446 while(dst<endOfRow) \
447 { \
448 dst[ROFFSET]=src[RGB_RED]; \
449 dst[GOFFSET]=src[RGB_GREEN]; \
450 dst[BOFFSET]=src[RGB_BLUE]; \
451 SETALPHA \
452 dst+=PS; src+=RGB_PIXELSIZE; \
453 } \
454 dst+=rowPad; \
455 } \
456}
457
458static void fromRGB(unsigned char *src, unsigned char *dst, int width,
459 int pitch, int height, int pixelFormat)
460{
461 switch(pixelFormat)
462 {
463 case TJPF_RGB:
464 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3
465 FROMRGB(3, 0, 1, 2,);
466 #endif
467 break;
468 case TJPF_BGR:
469 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3
470 FROMRGB(3, 2, 1, 0,);
471 #endif
472 break;
473 case TJPF_RGBX:
474 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
475 FROMRGB(4, 0, 1, 2,);
476 #endif
477 break;
478 case TJPF_RGBA:
479 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
480 FROMRGB(4, 0, 1, 2, dst[3]=0xFF;);
481 #endif
482 break;
483 case TJPF_BGRX:
484 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
485 FROMRGB(4, 2, 1, 0,);
486 #endif
487 break;
488 case TJPF_BGRA:
489 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
490 FROMRGB(4, 2, 1, 0, dst[3]=0xFF;); return;
491 #endif
492 break;
493 case TJPF_XRGB:
494 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
495 FROMRGB(4, 1, 2, 3,); return;
496 #endif
497 break;
498 case TJPF_ARGB:
499 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
500 FROMRGB(4, 1, 2, 3, dst[0]=0xFF;); return;
501 #endif
502 break;
503 case TJPF_XBGR:
504 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
505 FROMRGB(4, 3, 2, 1,); return;
506 #endif
507 break;
508 case TJPF_ABGR:
509 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
510 FROMRGB(4, 3, 2, 1, dst[0]=0xFF;); return;
511 #endif
512 break;
513 }
514}
515
516#endif
517
518
DRC9b28def2011-05-21 14:37:15 +0000519/* General API functions */
520
521DLLEXPORT char* DLLCALL tjGetErrorStr(void)
522{
523 return errStr;
524}
525
526
527DLLEXPORT int DLLCALL tjDestroy(tjhandle handle)
528{
529 getinstance(handle);
530 if(setjmp(this->jerr.setjmp_buffer)) return -1;
531 if(this->init&COMPRESS) jpeg_destroy_compress(cinfo);
532 if(this->init&DECOMPRESS) jpeg_destroy_decompress(dinfo);
533 free(this);
534 return 0;
535}
536
537
DRC6b76f752011-05-24 16:52:47 +0000538/* These are exposed mainly because Windows can't malloc() and free() across
539 DLL boundaries except when the CRT DLL is used, and we don't use the CRT DLL
540 with turbojpeg.dll for compatibility reasons. However, these functions
541 can potentially be used for other purposes by different implementations. */
542
543DLLEXPORT void DLLCALL tjFree(unsigned char *buf)
544{
545 if(buf) free(buf);
546}
547
548
549DLLEXPORT unsigned char *DLLCALL tjAlloc(int bytes)
550{
551 return (unsigned char *)malloc(bytes);
552}
553
554
DRC9b28def2011-05-21 14:37:15 +0000555/* Compressor */
556
557static tjhandle _tjInitCompress(tjinstance *this)
558{
559 unsigned char buffer[1], *buf=buffer; unsigned long size=1;
560
561 /* This is also straight out of example.c */
562 this->cinfo.err=jpeg_std_error(&this->jerr.pub);
563 this->jerr.pub.error_exit=my_error_exit;
564 this->jerr.pub.output_message=my_output_message;
DRC1f79c7c2015-06-01 19:22:41 +0000565 this->jerr.emit_message=this->jerr.pub.emit_message;
566 this->jerr.pub.emit_message=my_emit_message;
DRC9b28def2011-05-21 14:37:15 +0000567
568 if(setjmp(this->jerr.setjmp_buffer))
569 {
570 /* If we get here, the JPEG code has signaled an error. */
571 if(this) free(this); return NULL;
572 }
573
574 jpeg_create_compress(&this->cinfo);
575 /* Make an initial call so it will create the destination manager */
576 jpeg_mem_dest_tj(&this->cinfo, &buf, &size, 0);
577
DRC007a42c2011-05-22 13:55:56 +0000578 this->init|=COMPRESS;
DRC9b28def2011-05-21 14:37:15 +0000579 return (tjhandle)this;
DRC2e7b76b2009-04-03 12:04:24 +0000580}
581
DRC890f1e02011-02-26 22:02:37 +0000582DLLEXPORT tjhandle DLLCALL tjInitCompress(void)
583{
DRC9b28def2011-05-21 14:37:15 +0000584 tjinstance *this=NULL;
585 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
DRCda5220a2011-03-02 02:17:30 +0000586 {
DRC007a42c2011-05-22 13:55:56 +0000587 snprintf(errStr, JMSG_LENGTH_MAX,
588 "tjInitCompress(): Memory allocation failure");
DRCda5220a2011-03-02 02:17:30 +0000589 return NULL;
590 }
DRC007a42c2011-05-22 13:55:56 +0000591 MEMZERO(this, sizeof(tjinstance));
DRC9b28def2011-05-21 14:37:15 +0000592 return _tjInitCompress(this);
DRC890f1e02011-02-26 22:02:37 +0000593}
594
DRC84241602011-02-25 02:08:23 +0000595
DRC9b49f0e2011-07-12 03:17:23 +0000596DLLEXPORT unsigned long DLLCALL tjBufSize(int width, int height,
597 int jpegSubsamp)
598{
599 unsigned long retval=0; int mcuw, mcuh, chromasf;
600 if(width<1 || height<1 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT)
601 _throw("tjBufSize(): Invalid argument");
602
DRC006bc582014-02-27 21:22:54 +0000603 /* This allows for rare corner cases in which a JPEG image can actually be
604 larger than the uncompressed input (we wouldn't mention it if it hadn't
605 happened before.) */
DRC9b49f0e2011-07-12 03:17:23 +0000606 mcuw=tjMCUWidth[jpegSubsamp];
607 mcuh=tjMCUHeight[jpegSubsamp];
608 chromasf=jpegSubsamp==TJSAMP_GRAY? 0: 4*64/(mcuw*mcuh);
609 retval=PAD(width, mcuw) * PAD(height, mcuh) * (2 + chromasf) + 2048;
610
611 bailout:
612 return retval;
613}
614
DRC2e7b76b2009-04-03 12:04:24 +0000615DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
616{
DRCf3cf9732011-02-22 00:16:14 +0000617 unsigned long retval=0;
618 if(width<1 || height<1)
DRC007a42c2011-05-22 13:55:56 +0000619 _throw("TJBUFSIZE(): Invalid argument");
DRCf3cf9732011-02-22 00:16:14 +0000620
DRC006bc582014-02-27 21:22:54 +0000621 /* This allows for rare corner cases in which a JPEG image can actually be
622 larger than the uncompressed input (we wouldn't mention it if it hadn't
623 happened before.) */
DRC007a42c2011-05-22 13:55:56 +0000624 retval=PAD(width, 16) * PAD(height, 16) * 6 + 2048;
DRCf3cf9732011-02-22 00:16:14 +0000625
626 bailout:
627 return retval;
628}
629
DRC84241602011-02-25 02:08:23 +0000630
DRCf610d612013-04-26 10:33:29 +0000631DLLEXPORT unsigned long DLLCALL tjBufSizeYUV2(int width, int pad, int height,
DRCf3cf9732011-02-22 00:16:14 +0000632 int subsamp)
633{
DRC40dd3142014-08-17 12:23:49 +0000634 int retval=0, nc, i;
635
636 if(subsamp<0 || subsamp>=NUMSUBOPT)
DRCf610d612013-04-26 10:33:29 +0000637 _throw("tjBufSizeYUV2(): Invalid argument");
DRC40dd3142014-08-17 12:23:49 +0000638
639 nc=(subsamp==TJSAMP_GRAY? 1:3);
640 for(i=0; i<nc; i++)
641 {
DRC55620c62014-10-23 19:08:14 +0000642 int pw=tjPlaneWidth(i, width, subsamp);
643 int stride=PAD(pw, pad);
DRC40dd3142014-08-17 12:23:49 +0000644 int ph=tjPlaneHeight(i, height, subsamp);
DRC55620c62014-10-23 19:08:14 +0000645 if(pw<0 || ph<0) return -1;
DRC40dd3142014-08-17 12:23:49 +0000646 else retval+=stride*ph;
647 }
DRCf3cf9732011-02-22 00:16:14 +0000648
649 bailout:
650 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000651}
652
DRCf610d612013-04-26 10:33:29 +0000653DLLEXPORT unsigned long DLLCALL tjBufSizeYUV(int width, int height,
654 int subsamp)
655{
656 return tjBufSizeYUV2(width, 4, height, subsamp);
657}
DRC84241602011-02-25 02:08:23 +0000658
DRC9b49f0e2011-07-12 03:17:23 +0000659DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
660 int subsamp)
661{
662 return tjBufSizeYUV(width, height, subsamp);
663}
664
665
DRC40dd3142014-08-17 12:23:49 +0000666DLLEXPORT int tjPlaneWidth(int componentID, int width, int subsamp)
667{
668 int pw, nc, retval=0;
669
670 if(width<1 || subsamp<0 || subsamp>=TJ_NUMSAMP)
671 _throw("tjPlaneWidth(): Invalid argument");
672 nc=(subsamp==TJSAMP_GRAY? 1:3);
673 if(componentID<0 || componentID>=nc)
674 _throw("tjPlaneWidth(): Invalid argument");
675
676 pw=PAD(width, tjMCUWidth[subsamp]/8);
677 if(componentID==0)
678 retval=pw;
679 else
680 retval=pw*8/tjMCUWidth[subsamp];
681
682 bailout:
683 return retval;
684}
685
686
687DLLEXPORT int tjPlaneHeight(int componentID, int height, int subsamp)
688{
689 int ph, nc, retval=0;
690
691 if(height<1 || subsamp<0 || subsamp>=TJ_NUMSAMP)
692 _throw("tjPlaneHeight(): Invalid argument");
693 nc=(subsamp==TJSAMP_GRAY? 1:3);
694 if(componentID<0 || componentID>=nc)
695 _throw("tjPlaneHeight(): Invalid argument");
696
697 ph=PAD(height, tjMCUHeight[subsamp]/8);
698 if(componentID==0)
699 retval=ph;
700 else
701 retval=ph*8/tjMCUHeight[subsamp];
702
703 bailout:
704 return retval;
705}
706
707
708DLLEXPORT unsigned long DLLCALL tjPlaneSizeYUV(int componentID, int width,
709 int stride, int height, int subsamp)
710{
711 unsigned long retval=0;
712 int pw, ph;
713
714 if(width<1 || height<1 || subsamp<0 || subsamp>=NUMSUBOPT)
715 _throw("tjPlaneSizeYUV(): Invalid argument");
716
717 pw=tjPlaneWidth(componentID, width, subsamp);
718 ph=tjPlaneHeight(componentID, height, subsamp);
DRC22409742014-10-23 18:54:42 +0000719 if(pw<0 || ph<0) return -1;
DRC40dd3142014-08-17 12:23:49 +0000720
721 if(stride==0) stride=pw;
722 else stride=abs(stride);
723
724 retval=stride*(ph-1)+pw;
725
726 bailout:
727 return retval;
728}
729
730
DRC9b28def2011-05-21 14:37:15 +0000731DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf,
732 int width, int pitch, int height, int pixelFormat, unsigned char **jpegBuf,
733 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
734{
DRCff78e372011-05-24 10:17:32 +0000735 int i, retval=0, alloc=1; JSAMPROW *row_pointer=NULL;
DRCafc06922012-03-23 19:47:57 +0000736 #ifndef JCS_EXTENSIONS
737 unsigned char *rgbBuf=NULL;
738 #endif
DRC9b28def2011-05-21 14:37:15 +0000739
DRC41861622014-04-16 23:38:37 +0000740 getcinstance(handle)
DRC9b28def2011-05-21 14:37:15 +0000741 if((this->init&COMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +0000742 _throw("tjCompress2(): Instance has not been initialized for compression");
DRC9b28def2011-05-21 14:37:15 +0000743
744 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
745 || pixelFormat>=TJ_NUMPF || jpegBuf==NULL || jpegSize==NULL
746 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT || jpegQual<0 || jpegQual>100)
DRC007a42c2011-05-22 13:55:56 +0000747 _throw("tjCompress2(): Invalid argument");
DRC9b28def2011-05-21 14:37:15 +0000748
749 if(setjmp(this->jerr.setjmp_buffer))
750 {
751 /* If we get here, the JPEG code has signaled an error. */
752 retval=-1;
753 goto bailout;
754 }
755
756 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
757
DRCafc06922012-03-23 19:47:57 +0000758 #ifndef JCS_EXTENSIONS
DRC230d09d2014-04-20 09:42:49 +0000759 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK)
DRCafc06922012-03-23 19:47:57 +0000760 {
761 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
762 if(!rgbBuf) _throw("tjCompress2(): Memory allocation failure");
763 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
764 pitch=width*RGB_PIXELSIZE;
765 }
766 #endif
767
DRC9b28def2011-05-21 14:37:15 +0000768 cinfo->image_width=width;
769 cinfo->image_height=height;
770
DRCbec45b12015-05-17 15:56:18 +0000771 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
772 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
773 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC9b28def2011-05-21 14:37:15 +0000774
DRCff78e372011-05-24 10:17:32 +0000775 if(flags&TJFLAG_NOREALLOC)
776 {
DRC9b49f0e2011-07-12 03:17:23 +0000777 alloc=0; *jpegSize=tjBufSize(width, height, jpegSubsamp);
DRCff78e372011-05-24 10:17:32 +0000778 }
779 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
DRC73d74c12012-06-29 23:46:38 +0000780 if(setCompDefaults(cinfo, pixelFormat, jpegSubsamp, jpegQual, flags)==-1)
DRCf12bb302011-09-07 05:03:18 +0000781 return -1;
DRC9b28def2011-05-21 14:37:15 +0000782
783 jpeg_start_compress(cinfo, TRUE);
784 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
DRC007a42c2011-05-22 13:55:56 +0000785 _throw("tjCompress2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000786 for(i=0; i<height; i++)
787 {
DRC25b995a2011-05-21 15:34:54 +0000788 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
DRC9b28def2011-05-21 14:37:15 +0000789 else row_pointer[i]=&srcBuf[i*pitch];
790 }
791 while(cinfo->next_scanline<cinfo->image_height)
792 {
793 jpeg_write_scanlines(cinfo, &row_pointer[cinfo->next_scanline],
794 cinfo->image_height-cinfo->next_scanline);
795 }
796 jpeg_finish_compress(cinfo);
797
798 bailout:
799 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
DRCafc06922012-03-23 19:47:57 +0000800 #ifndef JCS_EXTENSIONS
DRCea3396a2012-04-26 03:18:49 +0000801 if(rgbBuf) free(rgbBuf);
DRCafc06922012-03-23 19:47:57 +0000802 #endif
DRC9b28def2011-05-21 14:37:15 +0000803 if(row_pointer) free(row_pointer);
DRC1f79c7c2015-06-01 19:22:41 +0000804 if(this->jerr.warning) retval=-1;
DRC9b28def2011-05-21 14:37:15 +0000805 return retval;
806}
807
808DLLEXPORT int DLLCALL tjCompress(tjhandle handle, unsigned char *srcBuf,
809 int width, int pitch, int height, int pixelSize, unsigned char *jpegBuf,
810 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
811{
812 int retval=0; unsigned long size;
813 if(flags&TJ_YUV)
814 {
DRC9b49f0e2011-07-12 03:17:23 +0000815 size=tjBufSizeYUV(width, height, jpegSubsamp);
DRC9b28def2011-05-21 14:37:15 +0000816 retval=tjEncodeYUV2(handle, srcBuf, width, pitch, height,
817 getPixelFormat(pixelSize, flags), jpegBuf, jpegSubsamp, flags);
818 }
819 else
820 {
DRC9b28def2011-05-21 14:37:15 +0000821 retval=tjCompress2(handle, srcBuf, width, pitch, height,
822 getPixelFormat(pixelSize, flags), &jpegBuf, &size, jpegSubsamp, jpegQual,
DRC25b995a2011-05-21 15:34:54 +0000823 flags|TJFLAG_NOREALLOC);
DRC9b28def2011-05-21 14:37:15 +0000824 }
825 *jpegSize=size;
826 return retval;
827}
828
829
DRCaecea382014-08-11 18:05:41 +0000830DLLEXPORT int DLLCALL tjEncodeYUVPlanes(tjhandle handle, unsigned char *srcBuf,
831 int width, int pitch, int height, int pixelFormat, unsigned char **dstPlanes,
832 int *strides, int subsamp, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000833{
DRC91e86ba2011-02-15 05:24:08 +0000834 int i, retval=0; JSAMPROW *row_pointer=NULL;
DRCfbb67472010-11-24 04:02:37 +0000835 JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS];
836 JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
837 JSAMPROW *outbuf[MAX_COMPONENTS];
DRC40dd3142014-08-17 12:23:49 +0000838 int row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS];
DRCaecea382014-08-11 18:05:41 +0000839 JSAMPLE *ptr;
DRC9b28def2011-05-21 14:37:15 +0000840 jpeg_component_info *compptr;
DRCafc06922012-03-23 19:47:57 +0000841 #ifndef JCS_EXTENSIONS
842 unsigned char *rgbBuf=NULL;
843 #endif
DRC2e7b76b2009-04-03 12:04:24 +0000844
DRC41861622014-04-16 23:38:37 +0000845 getcinstance(handle);
DRCb51ee892013-10-31 05:00:19 +0000846
DRCfbb67472010-11-24 04:02:37 +0000847 for(i=0; i<MAX_COMPONENTS; i++)
848 {
849 tmpbuf[i]=NULL; _tmpbuf[i]=NULL;
850 tmpbuf2[i]=NULL; _tmpbuf2[i]=NULL; outbuf[i]=NULL;
851 }
852
DRCe2f8e692013-10-30 22:21:06 +0000853 if((this->init&COMPRESS)==0)
DRCaecea382014-08-11 18:05:41 +0000854 _throw("tjEncodeYUVPlanes(): Instance has not been initialized for compression");
DRCe2f8e692013-10-30 22:21:06 +0000855
DRC9b28def2011-05-21 14:37:15 +0000856 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
DRCaecea382014-08-11 18:05:41 +0000857 || pixelFormat>=TJ_NUMPF || !dstPlanes || !dstPlanes[0] || subsamp<0
858 || subsamp>=NUMSUBOPT)
859 _throw("tjEncodeYUVPlanes(): Invalid argument");
860 if(subsamp!=TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2]))
861 _throw("tjEncodeYUVPlanes(): Invalid argument");
DRC2e7b76b2009-04-03 12:04:24 +0000862
DRC9b28def2011-05-21 14:37:15 +0000863 if(setjmp(this->jerr.setjmp_buffer))
864 {
865 /* If we get here, the JPEG code has signaled an error. */
866 retval=-1;
867 goto bailout;
868 }
DRC2e7b76b2009-04-03 12:04:24 +0000869
DRCcd7c3e62013-08-23 02:49:25 +0000870 if(pixelFormat==TJPF_CMYK)
DRCaecea382014-08-11 18:05:41 +0000871 _throw("tjEncodeYUVPlanes(): Cannot generate YUV images from CMYK pixels");
DRCcd7c3e62013-08-23 02:49:25 +0000872
DRC9b28def2011-05-21 14:37:15 +0000873 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
DRC2e7b76b2009-04-03 12:04:24 +0000874
DRCafc06922012-03-23 19:47:57 +0000875 #ifndef JCS_EXTENSIONS
DRC230d09d2014-04-20 09:42:49 +0000876 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK)
DRCafc06922012-03-23 19:47:57 +0000877 {
878 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
DRCaecea382014-08-11 18:05:41 +0000879 if(!rgbBuf) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
DRCafc06922012-03-23 19:47:57 +0000880 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
881 pitch=width*RGB_PIXELSIZE;
882 }
883 #endif
884
DRC9b28def2011-05-21 14:37:15 +0000885 cinfo->image_width=width;
886 cinfo->image_height=height;
DRC2e7b76b2009-04-03 12:04:24 +0000887
DRCbec45b12015-05-17 15:56:18 +0000888 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
889 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
890 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC0c6a2712010-02-22 08:34:44 +0000891
DRC73d74c12012-06-29 23:46:38 +0000892 if(setCompDefaults(cinfo, pixelFormat, subsamp, -1, flags)==-1) return -1;
DRC2e7b76b2009-04-03 12:04:24 +0000893
DRC38c99702014-02-11 09:45:18 +0000894 /* Execute only the parts of jpeg_start_compress() that we need. If we
895 were to call the whole jpeg_start_compress() function, then it would try
896 to write the file headers, which could overflow the output buffer if the
897 YUV image were very small. */
898 if(cinfo->global_state!=CSTATE_START)
DRCaecea382014-08-11 18:05:41 +0000899 _throw("tjEncodeYUVPlanes(): libjpeg API is in the wrong state");
DRC38c99702014-02-11 09:45:18 +0000900 (*cinfo->err->reset_error_mgr)((j_common_ptr)cinfo);
DRC38c99702014-02-11 09:45:18 +0000901 jinit_c_master_control(cinfo, FALSE);
902 jinit_color_converter(cinfo);
903 jinit_downsampler(cinfo);
DRC50cfc462014-03-06 20:03:37 +0000904 (*cinfo->cconvert->start_pass)(cinfo);
DRC38c99702014-02-11 09:45:18 +0000905
DRC40dd3142014-08-17 12:23:49 +0000906 pw0=PAD(width, cinfo->max_h_samp_factor);
907 ph0=PAD(height, cinfo->max_v_samp_factor);
DRC2e7b76b2009-04-03 12:04:24 +0000908
DRC40dd3142014-08-17 12:23:49 +0000909 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL)
DRCaecea382014-08-11 18:05:41 +0000910 _throw("tjEncodeYUVPlanes(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000911 for(i=0; i<height; i++)
DRC2e7b76b2009-04-03 12:04:24 +0000912 {
DRC25b995a2011-05-21 15:34:54 +0000913 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
DRC9b28def2011-05-21 14:37:15 +0000914 else row_pointer[i]=&srcBuf[i*pitch];
915 }
DRC40dd3142014-08-17 12:23:49 +0000916 if(height<ph0)
917 for(i=height; i<ph0; i++) row_pointer[i]=row_pointer[height-1];
DRCfbb67472010-11-24 04:02:37 +0000918
DRC9b28def2011-05-21 14:37:15 +0000919 for(i=0; i<cinfo->num_components; i++)
920 {
921 compptr=&cinfo->comp_info[i];
922 _tmpbuf[i]=(JSAMPLE *)malloc(
923 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
924 /compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
DRCaecea382014-08-11 18:05:41 +0000925 if(!_tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000926 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
DRCaecea382014-08-11 18:05:41 +0000927 if(!tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000928 for(row=0; row<cinfo->max_v_samp_factor; row++)
DRCfbb67472010-11-24 04:02:37 +0000929 {
DRC9b28def2011-05-21 14:37:15 +0000930 unsigned char *_tmpbuf_aligned=
931 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
932 tmpbuf[i][row]=&_tmpbuf_aligned[
DRCfbb67472010-11-24 04:02:37 +0000933 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
DRC9b28def2011-05-21 14:37:15 +0000934 /compptr->h_samp_factor, 16) * row];
DRCfbb67472010-11-24 04:02:37 +0000935 }
DRC9b28def2011-05-21 14:37:15 +0000936 _tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
937 * compptr->v_samp_factor + 16);
DRCaecea382014-08-11 18:05:41 +0000938 if(!_tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000939 tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
DRCaecea382014-08-11 18:05:41 +0000940 if(!tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +0000941 for(row=0; row<compptr->v_samp_factor; row++)
942 {
943 unsigned char *_tmpbuf2_aligned=
944 (unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
945 tmpbuf2[i][row]=&_tmpbuf2_aligned[
946 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
947 }
DRC40dd3142014-08-17 12:23:49 +0000948 pw[i]=pw0*compptr->h_samp_factor/cinfo->max_h_samp_factor;
949 ph[i]=ph0*compptr->v_samp_factor/cinfo->max_v_samp_factor;
950 outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]);
DRCaecea382014-08-11 18:05:41 +0000951 if(!outbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
952 ptr=dstPlanes[i];
DRC40dd3142014-08-17 12:23:49 +0000953 for(row=0; row<ph[i]; row++)
DRC9b28def2011-05-21 14:37:15 +0000954 {
955 outbuf[i][row]=ptr;
DRC40dd3142014-08-17 12:23:49 +0000956 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
DRC9b28def2011-05-21 14:37:15 +0000957 }
958 }
DRCfbb67472010-11-24 04:02:37 +0000959
DRC40dd3142014-08-17 12:23:49 +0000960 for(row=0; row<ph0; row+=cinfo->max_v_samp_factor)
DRCfbb67472010-11-24 04:02:37 +0000961 {
DRC9b28def2011-05-21 14:37:15 +0000962 (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0,
963 cinfo->max_v_samp_factor);
964 (cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
965 for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++)
966 jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
967 row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
DRC40dd3142014-08-17 12:23:49 +0000968 compptr->v_samp_factor, pw[i]);
DRC6ee54592011-03-01 08:18:30 +0000969 }
DRC9b28def2011-05-21 14:37:15 +0000970 cinfo->next_scanline+=height;
971 jpeg_abort_compress(cinfo);
DRC2e7b76b2009-04-03 12:04:24 +0000972
DRC91e86ba2011-02-15 05:24:08 +0000973 bailout:
DRC9b28def2011-05-21 14:37:15 +0000974 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
DRCafc06922012-03-23 19:47:57 +0000975 #ifndef JCS_EXTENSIONS
DRCea3396a2012-04-26 03:18:49 +0000976 if(rgbBuf) free(rgbBuf);
DRCafc06922012-03-23 19:47:57 +0000977 #endif
DRC2e7b76b2009-04-03 12:04:24 +0000978 if(row_pointer) free(row_pointer);
DRCfbb67472010-11-24 04:02:37 +0000979 for(i=0; i<MAX_COMPONENTS; i++)
980 {
981 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
DRC57423072011-01-05 23:35:53 +0000982 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
DRCfbb67472010-11-24 04:02:37 +0000983 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
DRC57423072011-01-05 23:35:53 +0000984 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
DRCfbb67472010-11-24 04:02:37 +0000985 if(outbuf[i]!=NULL) free(outbuf[i]);
986 }
DRC1f79c7c2015-06-01 19:22:41 +0000987 if(this->jerr.warning) retval=-1;
DRC91e86ba2011-02-15 05:24:08 +0000988 return retval;
DRC2e7b76b2009-04-03 12:04:24 +0000989}
990
DRCaecea382014-08-11 18:05:41 +0000991DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf,
992 int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
993 int pad, int subsamp, int flags)
994{
995 unsigned char *dstPlanes[3];
DRC40dd3142014-08-17 12:23:49 +0000996 int pw0, ph0, strides[3], retval=-1;
DRCaecea382014-08-11 18:05:41 +0000997
998 if(width<=0 || height<=0 || dstBuf==NULL || pad<0 || !isPow2(pad)
999 || subsamp<0 || subsamp>=NUMSUBOPT)
1000 _throw("tjEncodeYUV3(): Invalid argument");
1001
DRC40dd3142014-08-17 12:23:49 +00001002 pw0=tjPlaneWidth(0, width, subsamp);
1003 ph0=tjPlaneHeight(0, height, subsamp);
DRCaecea382014-08-11 18:05:41 +00001004 dstPlanes[0]=dstBuf;
DRC40dd3142014-08-17 12:23:49 +00001005 strides[0]=PAD(pw0, pad);
1006 if(subsamp==TJSAMP_GRAY)
1007 {
1008 strides[1]=strides[2]=0;
1009 dstPlanes[1]=dstPlanes[2]=NULL;
1010 }
1011 else
1012 {
1013 int pw1=tjPlaneWidth(1, width, subsamp);
1014 int ph1=tjPlaneHeight(1, height, subsamp);
1015 strides[1]=strides[2]=PAD(pw1, pad);
1016 dstPlanes[1]=dstPlanes[0]+strides[0]*ph0;
1017 dstPlanes[2]=dstPlanes[1]+strides[1]*ph1;
1018 }
DRCaecea382014-08-11 18:05:41 +00001019
1020 return tjEncodeYUVPlanes(handle, srcBuf, width, pitch, height, pixelFormat,
1021 dstPlanes, strides, subsamp, flags);
1022
1023 bailout:
1024 return retval;
1025}
1026
DRCf610d612013-04-26 10:33:29 +00001027DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
1028 int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
1029 int subsamp, int flags)
1030{
1031 return tjEncodeYUV3(handle, srcBuf, width, pitch, height, pixelFormat,
1032 dstBuf, 4, subsamp, flags);
1033}
1034
DRC9b28def2011-05-21 14:37:15 +00001035DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf,
1036 int width, int pitch, int height, int pixelSize, unsigned char *dstBuf,
1037 int subsamp, int flags)
DRC84241602011-02-25 02:08:23 +00001038{
DRC9b28def2011-05-21 14:37:15 +00001039 return tjEncodeYUV2(handle, srcBuf, width, pitch, height,
1040 getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags);
DRC84241602011-02-25 02:08:23 +00001041}
1042
1043
DRCaecea382014-08-11 18:05:41 +00001044DLLEXPORT int DLLCALL tjCompressFromYUVPlanes(tjhandle handle,
1045 unsigned char **srcPlanes, int width, int *strides, int height, int subsamp,
1046 unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual, int flags)
DRC910a3572013-10-30 23:02:57 +00001047{
1048 int i, row, retval=0, alloc=1; JSAMPROW *inbuf[MAX_COMPONENTS];
DRC40dd3142014-08-17 12:23:49 +00001049 int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS],
DRC910a3572013-10-30 23:02:57 +00001050 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
DRCaecea382014-08-11 18:05:41 +00001051 JSAMPLE *_tmpbuf=NULL, *ptr; JSAMPROW *tmpbuf[MAX_COMPONENTS];
DRC910a3572013-10-30 23:02:57 +00001052
DRC41861622014-04-16 23:38:37 +00001053 getcinstance(handle)
DRCb51ee892013-10-31 05:00:19 +00001054
DRC910a3572013-10-30 23:02:57 +00001055 for(i=0; i<MAX_COMPONENTS; i++)
1056 {
1057 tmpbuf[i]=NULL; inbuf[i]=NULL;
1058 }
1059
DRC910a3572013-10-30 23:02:57 +00001060 if((this->init&COMPRESS)==0)
DRCaecea382014-08-11 18:05:41 +00001061 _throw("tjCompressFromYUVPlanes(): Instance has not been initialized for compression");
DRC910a3572013-10-30 23:02:57 +00001062
DRCaecea382014-08-11 18:05:41 +00001063 if(!srcPlanes || !srcPlanes[0] || width<=0 || height<=0 || subsamp<0
DRC910a3572013-10-30 23:02:57 +00001064 || subsamp>=NUMSUBOPT || jpegBuf==NULL || jpegSize==NULL || jpegQual<0
1065 || jpegQual>100)
DRCaecea382014-08-11 18:05:41 +00001066 _throw("tjCompressFromYUVPlanes(): Invalid argument");
1067 if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2]))
1068 _throw("tjCompressFromYUVPlanes(): Invalid argument");
DRC910a3572013-10-30 23:02:57 +00001069
1070 if(setjmp(this->jerr.setjmp_buffer))
1071 {
1072 /* If we get here, the JPEG code has signaled an error. */
1073 retval=-1;
1074 goto bailout;
1075 }
1076
1077 cinfo->image_width=width;
1078 cinfo->image_height=height;
1079
DRCbec45b12015-05-17 15:56:18 +00001080 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1081 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1082 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC910a3572013-10-30 23:02:57 +00001083
1084 if(flags&TJFLAG_NOREALLOC)
1085 {
1086 alloc=0; *jpegSize=tjBufSize(width, height, subsamp);
1087 }
1088 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
1089 if(setCompDefaults(cinfo, TJPF_RGB, subsamp, jpegQual, flags)==-1)
1090 return -1;
1091 cinfo->raw_data_in=TRUE;
1092
1093 jpeg_start_compress(cinfo, TRUE);
1094 for(i=0; i<cinfo->num_components; i++)
1095 {
1096 jpeg_component_info *compptr=&cinfo->comp_info[i];
1097 int ih;
1098 iw[i]=compptr->width_in_blocks*DCTSIZE;
1099 ih=compptr->height_in_blocks*DCTSIZE;
DRC40dd3142014-08-17 12:23:49 +00001100 pw[i]=PAD(cinfo->image_width, cinfo->max_h_samp_factor)
DRC910a3572013-10-30 23:02:57 +00001101 *compptr->h_samp_factor/cinfo->max_h_samp_factor;
DRC40dd3142014-08-17 12:23:49 +00001102 ph[i]=PAD(cinfo->image_height, cinfo->max_v_samp_factor)
DRC910a3572013-10-30 23:02:57 +00001103 *compptr->v_samp_factor/cinfo->max_v_samp_factor;
DRC40dd3142014-08-17 12:23:49 +00001104 if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1;
DRC910a3572013-10-30 23:02:57 +00001105 th[i]=compptr->v_samp_factor*DCTSIZE;
1106 tmpbufsize+=iw[i]*th[i];
DRC40dd3142014-08-17 12:23:49 +00001107 if((inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]))==NULL)
DRCaecea382014-08-11 18:05:41 +00001108 _throw("tjCompressFromYUVPlanes(): Memory allocation failure");
1109 ptr=srcPlanes[i];
DRC40dd3142014-08-17 12:23:49 +00001110 for(row=0; row<ph[i]; row++)
DRC910a3572013-10-30 23:02:57 +00001111 {
1112 inbuf[i][row]=ptr;
DRC40dd3142014-08-17 12:23:49 +00001113 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
DRC910a3572013-10-30 23:02:57 +00001114 }
1115 }
1116 if(usetmpbuf)
1117 {
1118 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
DRCaecea382014-08-11 18:05:41 +00001119 _throw("tjCompressFromYUVPlanes(): Memory allocation failure");
DRC910a3572013-10-30 23:02:57 +00001120 ptr=_tmpbuf;
1121 for(i=0; i<cinfo->num_components; i++)
1122 {
1123 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
DRCaecea382014-08-11 18:05:41 +00001124 _throw("tjCompressFromYUVPlanes(): Memory allocation failure");
DRC910a3572013-10-30 23:02:57 +00001125 for(row=0; row<th[i]; row++)
1126 {
1127 tmpbuf[i][row]=ptr;
1128 ptr+=iw[i];
1129 }
1130 }
1131 }
1132
1133 for(row=0; row<(int)cinfo->image_height;
1134 row+=cinfo->max_v_samp_factor*DCTSIZE)
1135 {
1136 JSAMPARRAY yuvptr[MAX_COMPONENTS];
1137 int crow[MAX_COMPONENTS];
1138 for(i=0; i<cinfo->num_components; i++)
1139 {
1140 jpeg_component_info *compptr=&cinfo->comp_info[i];
1141 crow[i]=row*compptr->v_samp_factor/cinfo->max_v_samp_factor;
1142 if(usetmpbuf)
1143 {
1144 int j, k;
DRC40dd3142014-08-17 12:23:49 +00001145 for(j=0; j<min(th[i], ph[i]-crow[i]); j++)
DRC910a3572013-10-30 23:02:57 +00001146 {
DRC40dd3142014-08-17 12:23:49 +00001147 memcpy(tmpbuf[i][j], inbuf[i][crow[i]+j], pw[i]);
DRC006bc582014-02-27 21:22:54 +00001148 /* Duplicate last sample in row to fill out MCU */
DRC40dd3142014-08-17 12:23:49 +00001149 for(k=pw[i]; k<iw[i]; k++) tmpbuf[i][j][k]=tmpbuf[i][j][pw[i]-1];
DRC910a3572013-10-30 23:02:57 +00001150 }
DRC006bc582014-02-27 21:22:54 +00001151 /* Duplicate last row to fill out MCU */
DRC40dd3142014-08-17 12:23:49 +00001152 for(j=ph[i]-crow[i]; j<th[i]; j++)
1153 memcpy(tmpbuf[i][j], tmpbuf[i][ph[i]-crow[i]-1], iw[i]);
DRC910a3572013-10-30 23:02:57 +00001154 yuvptr[i]=tmpbuf[i];
1155 }
1156 else
1157 yuvptr[i]=&inbuf[i][crow[i]];
1158 }
1159 jpeg_write_raw_data(cinfo, yuvptr, cinfo->max_v_samp_factor*DCTSIZE);
1160 }
1161 jpeg_finish_compress(cinfo);
1162
1163 bailout:
1164 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
1165 for(i=0; i<MAX_COMPONENTS; i++)
1166 {
1167 if(tmpbuf[i]) free(tmpbuf[i]);
1168 if(inbuf[i]) free(inbuf[i]);
1169 }
1170 if(_tmpbuf) free(_tmpbuf);
DRC1f79c7c2015-06-01 19:22:41 +00001171 if(this->jerr.warning) retval=-1;
DRC910a3572013-10-30 23:02:57 +00001172 return retval;
1173}
1174
DRCaecea382014-08-11 18:05:41 +00001175DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle, unsigned char *srcBuf,
1176 int width, int pad, int height, int subsamp, unsigned char **jpegBuf,
1177 unsigned long *jpegSize, int jpegQual, int flags)
1178{
1179 unsigned char *srcPlanes[3];
DRC40dd3142014-08-17 12:23:49 +00001180 int pw0, ph0, strides[3], retval=-1;
DRCaecea382014-08-11 18:05:41 +00001181
1182 if(srcBuf==NULL || width<=0 || pad<1 || height<=0 || subsamp<0
1183 || subsamp>=NUMSUBOPT)
1184 _throw("tjCompressFromYUV(): Invalid argument");
1185
DRC40dd3142014-08-17 12:23:49 +00001186 pw0=tjPlaneWidth(0, width, subsamp);
1187 ph0=tjPlaneHeight(0, height, subsamp);
DRCaecea382014-08-11 18:05:41 +00001188 srcPlanes[0]=srcBuf;
DRC40dd3142014-08-17 12:23:49 +00001189 strides[0]=PAD(pw0, pad);
1190 if(subsamp==TJSAMP_GRAY)
1191 {
1192 strides[1]=strides[2]=0;
1193 srcPlanes[1]=srcPlanes[2]=NULL;
1194 }
1195 else
1196 {
1197 int pw1=tjPlaneWidth(1, width, subsamp);
1198 int ph1=tjPlaneHeight(1, height, subsamp);
1199 strides[1]=strides[2]=PAD(pw1, pad);
1200 srcPlanes[1]=srcPlanes[0]+strides[0]*ph0;
1201 srcPlanes[2]=srcPlanes[1]+strides[1]*ph1;
1202 }
DRCaecea382014-08-11 18:05:41 +00001203
1204 return tjCompressFromYUVPlanes(handle, srcPlanes, width, strides, height,
1205 subsamp, jpegBuf, jpegSize, jpegQual, flags);
1206
1207 bailout:
1208 return retval;
1209}
1210
DRC910a3572013-10-30 23:02:57 +00001211
DRC9b28def2011-05-21 14:37:15 +00001212/* Decompressor */
DRC2e7b76b2009-04-03 12:04:24 +00001213
DRC9b28def2011-05-21 14:37:15 +00001214static tjhandle _tjInitDecompress(tjinstance *this)
DRC2e7b76b2009-04-03 12:04:24 +00001215{
DRC9b28def2011-05-21 14:37:15 +00001216 unsigned char buffer[1];
DRC2e7b76b2009-04-03 12:04:24 +00001217
DRC9b28def2011-05-21 14:37:15 +00001218 /* This is also straight out of example.c */
1219 this->dinfo.err=jpeg_std_error(&this->jerr.pub);
1220 this->jerr.pub.error_exit=my_error_exit;
1221 this->jerr.pub.output_message=my_output_message;
DRC1f79c7c2015-06-01 19:22:41 +00001222 this->jerr.emit_message=this->jerr.pub.emit_message;
1223 this->jerr.pub.emit_message=my_emit_message;
DRC2e7b76b2009-04-03 12:04:24 +00001224
DRC9b28def2011-05-21 14:37:15 +00001225 if(setjmp(this->jerr.setjmp_buffer))
1226 {
1227 /* If we get here, the JPEG code has signaled an error. */
1228 if(this) free(this); return NULL;
DRC9e17f7d2010-12-10 04:59:13 +00001229 }
DRC2e7b76b2009-04-03 12:04:24 +00001230
DRC9b28def2011-05-21 14:37:15 +00001231 jpeg_create_decompress(&this->dinfo);
1232 /* Make an initial call so it will create the source manager */
1233 jpeg_mem_src_tj(&this->dinfo, buffer, 1);
DRC2e7b76b2009-04-03 12:04:24 +00001234
DRC007a42c2011-05-22 13:55:56 +00001235 this->init|=DECOMPRESS;
DRC9b28def2011-05-21 14:37:15 +00001236 return (tjhandle)this;
DRC2e7b76b2009-04-03 12:04:24 +00001237}
1238
DRC890f1e02011-02-26 22:02:37 +00001239DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
1240{
DRC9b28def2011-05-21 14:37:15 +00001241 tjinstance *this;
1242 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
DRCda5220a2011-03-02 02:17:30 +00001243 {
DRC007a42c2011-05-22 13:55:56 +00001244 snprintf(errStr, JMSG_LENGTH_MAX,
1245 "tjInitDecompress(): Memory allocation failure");
DRCda5220a2011-03-02 02:17:30 +00001246 return NULL;
1247 }
DRC007a42c2011-05-22 13:55:56 +00001248 MEMZERO(this, sizeof(tjinstance));
DRC9b28def2011-05-21 14:37:15 +00001249 return _tjInitDecompress(this);
DRC890f1e02011-02-26 22:02:37 +00001250}
1251
DRC2e7b76b2009-04-03 12:04:24 +00001252
DRCcd7c3e62013-08-23 02:49:25 +00001253DLLEXPORT int DLLCALL tjDecompressHeader3(tjhandle handle,
DRC9b28def2011-05-21 14:37:15 +00001254 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
DRCcd7c3e62013-08-23 02:49:25 +00001255 int *jpegSubsamp, int *jpegColorspace)
DRC1fe80f82010-12-14 01:21:29 +00001256{
DRC9b49f0e2011-07-12 03:17:23 +00001257 int retval=0;
DRC1fe80f82010-12-14 01:21:29 +00001258
DRC41861622014-04-16 23:38:37 +00001259 getdinstance(handle);
DRC9b28def2011-05-21 14:37:15 +00001260 if((this->init&DECOMPRESS)==0)
DRCcd7c3e62013-08-23 02:49:25 +00001261 _throw("tjDecompressHeader3(): Instance has not been initialized for decompression");
DRC1fe80f82010-12-14 01:21:29 +00001262
DRC9b28def2011-05-21 14:37:15 +00001263 if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL
DRCcd7c3e62013-08-23 02:49:25 +00001264 || jpegSubsamp==NULL || jpegColorspace==NULL)
1265 _throw("tjDecompressHeader3(): Invalid argument");
DRC1fe80f82010-12-14 01:21:29 +00001266
DRC9b28def2011-05-21 14:37:15 +00001267 if(setjmp(this->jerr.setjmp_buffer))
1268 {
1269 /* If we get here, the JPEG code has signaled an error. */
DRC1fe80f82010-12-14 01:21:29 +00001270 return -1;
1271 }
1272
DRC9b28def2011-05-21 14:37:15 +00001273 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1274 jpeg_read_header(dinfo, TRUE);
DRC1fe80f82010-12-14 01:21:29 +00001275
DRC9b28def2011-05-21 14:37:15 +00001276 *width=dinfo->image_width;
1277 *height=dinfo->image_height;
DRC9b49f0e2011-07-12 03:17:23 +00001278 *jpegSubsamp=getSubsamp(dinfo);
DRCcd7c3e62013-08-23 02:49:25 +00001279 switch(dinfo->jpeg_color_space)
1280 {
1281 case JCS_GRAYSCALE: *jpegColorspace=TJCS_GRAY; break;
1282 case JCS_RGB: *jpegColorspace=TJCS_RGB; break;
1283 case JCS_YCbCr: *jpegColorspace=TJCS_YCbCr; break;
1284 case JCS_CMYK: *jpegColorspace=TJCS_CMYK; break;
1285 case JCS_YCCK: *jpegColorspace=TJCS_YCCK; break;
1286 default: *jpegColorspace=-1; break;
1287 }
DRC1fe80f82010-12-14 01:21:29 +00001288
DRC9b28def2011-05-21 14:37:15 +00001289 jpeg_abort_decompress(dinfo);
DRC1fe80f82010-12-14 01:21:29 +00001290
DRC9b28def2011-05-21 14:37:15 +00001291 if(*jpegSubsamp<0)
DRCcd7c3e62013-08-23 02:49:25 +00001292 _throw("tjDecompressHeader3(): Could not determine subsampling type for JPEG image");
1293 if(*jpegColorspace<0)
1294 _throw("tjDecompressHeader3(): Could not determine colorspace of JPEG image");
DRC007a42c2011-05-22 13:55:56 +00001295 if(*width<1 || *height<1)
DRCcd7c3e62013-08-23 02:49:25 +00001296 _throw("tjDecompressHeader3(): Invalid data returned in header");
DRC91e86ba2011-02-15 05:24:08 +00001297
1298 bailout:
DRC1f79c7c2015-06-01 19:22:41 +00001299 if(this->jerr.warning) retval=-1;
DRC91e86ba2011-02-15 05:24:08 +00001300 return retval;
1301}
1302
DRCcd7c3e62013-08-23 02:49:25 +00001303DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle,
1304 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
1305 int *jpegSubsamp)
1306{
1307 int jpegColorspace;
1308 return tjDecompressHeader3(handle, jpegBuf, jpegSize, width, height,
1309 jpegSubsamp, &jpegColorspace);
1310}
1311
DRC9b28def2011-05-21 14:37:15 +00001312DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle,
1313 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height)
DRC91e86ba2011-02-15 05:24:08 +00001314{
DRC9b28def2011-05-21 14:37:15 +00001315 int jpegSubsamp;
1316 return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height,
1317 &jpegSubsamp);
DRC1fe80f82010-12-14 01:21:29 +00001318}
1319
1320
DRC109a5782011-03-01 09:53:07 +00001321DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors)
DRCb28fc572011-02-22 06:41:29 +00001322{
DRC109a5782011-03-01 09:53:07 +00001323 if(numscalingfactors==NULL)
DRCb28fc572011-02-22 06:41:29 +00001324 {
DRC9b28def2011-05-21 14:37:15 +00001325 snprintf(errStr, JMSG_LENGTH_MAX,
DRC007a42c2011-05-22 13:55:56 +00001326 "tjGetScalingFactors(): Invalid argument");
DRC109a5782011-03-01 09:53:07 +00001327 return NULL;
DRCb28fc572011-02-22 06:41:29 +00001328 }
1329
DRC109a5782011-03-01 09:53:07 +00001330 *numscalingfactors=NUMSF;
1331 return (tjscalingfactor *)sf;
DRCb28fc572011-02-22 06:41:29 +00001332}
1333
1334
DRC9b28def2011-05-21 14:37:15 +00001335DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, unsigned char *jpegBuf,
1336 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
1337 int height, int pixelFormat, int flags)
DRC2e7b76b2009-04-03 12:04:24 +00001338{
DRC9b28def2011-05-21 14:37:15 +00001339 int i, retval=0; JSAMPROW *row_pointer=NULL;
DRC109a5782011-03-01 09:53:07 +00001340 int jpegwidth, jpegheight, scaledw, scaledh;
DRCafc06922012-03-23 19:47:57 +00001341 #ifndef JCS_EXTENSIONS
1342 unsigned char *rgbBuf=NULL;
1343 unsigned char *_dstBuf=NULL; int _pitch=0;
1344 #endif
DRC2e7b76b2009-04-03 12:04:24 +00001345
DRC41861622014-04-16 23:38:37 +00001346 getdinstance(handle);
DRC9b28def2011-05-21 14:37:15 +00001347 if((this->init&DECOMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +00001348 _throw("tjDecompress2(): Instance has not been initialized for decompression");
DRC9b28def2011-05-21 14:37:15 +00001349
1350 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0
1351 || height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF)
1352 _throw("tjDecompress2(): Invalid argument");
1353
DRCbec45b12015-05-17 15:56:18 +00001354 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1355 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1356 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC9b28def2011-05-21 14:37:15 +00001357
1358 if(setjmp(this->jerr.setjmp_buffer))
1359 {
1360 /* If we get here, the JPEG code has signaled an error. */
1361 retval=-1;
1362 goto bailout;
1363 }
1364
1365 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1366 jpeg_read_header(dinfo, TRUE);
DRC73d74c12012-06-29 23:46:38 +00001367 if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
DRC2eda8212012-03-23 19:32:38 +00001368 {
1369 retval=-1; goto bailout;
1370 }
DRC9b28def2011-05-21 14:37:15 +00001371
DRC25b995a2011-05-21 15:34:54 +00001372 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
DRC9b28def2011-05-21 14:37:15 +00001373
1374 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
1375 if(width==0) width=jpegwidth;
1376 if(height==0) height=jpegheight;
1377 for(i=0; i<NUMSF; i++)
1378 {
1379 scaledw=TJSCALED(jpegwidth, sf[i]);
1380 scaledh=TJSCALED(jpegheight, sf[i]);
1381 if(scaledw<=width && scaledh<=height)
DRCf610d612013-04-26 10:33:29 +00001382 break;
DRC9b28def2011-05-21 14:37:15 +00001383 }
DRC58ae4012015-08-26 20:29:36 -05001384 if(i>=NUMSF)
DRC007a42c2011-05-22 13:55:56 +00001385 _throw("tjDecompress2(): Could not scale down to desired image dimensions");
DRC9b28def2011-05-21 14:37:15 +00001386 width=scaledw; height=scaledh;
1387 dinfo->scale_num=sf[i].num;
1388 dinfo->scale_denom=sf[i].denom;
1389
1390 jpeg_start_decompress(dinfo);
1391 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
DRCafc06922012-03-23 19:47:57 +00001392
1393 #ifndef JCS_EXTENSIONS
DRC230d09d2014-04-20 09:42:49 +00001394 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK &&
DRCafc06922012-03-23 19:47:57 +00001395 (RGB_RED!=tjRedOffset[pixelFormat] ||
1396 RGB_GREEN!=tjGreenOffset[pixelFormat] ||
1397 RGB_BLUE!=tjBlueOffset[pixelFormat] ||
1398 RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
1399 {
1400 rgbBuf=(unsigned char *)malloc(width*height*3);
1401 if(!rgbBuf) _throw("tjDecompress2(): Memory allocation failure");
1402 _pitch=pitch; pitch=width*3;
1403 _dstBuf=dstBuf; dstBuf=rgbBuf;
1404 }
1405 #endif
1406
DRC9b28def2011-05-21 14:37:15 +00001407 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
1408 *dinfo->output_height))==NULL)
DRC007a42c2011-05-22 13:55:56 +00001409 _throw("tjDecompress2(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +00001410 for(i=0; i<(int)dinfo->output_height; i++)
1411 {
DRC25b995a2011-05-21 15:34:54 +00001412 if(flags&TJFLAG_BOTTOMUP)
DRC9b28def2011-05-21 14:37:15 +00001413 row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*pitch];
1414 else row_pointer[i]=&dstBuf[i*pitch];
1415 }
1416 while(dinfo->output_scanline<dinfo->output_height)
1417 {
1418 jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline],
1419 dinfo->output_height-dinfo->output_scanline);
1420 }
1421 jpeg_finish_decompress(dinfo);
1422
DRCafc06922012-03-23 19:47:57 +00001423 #ifndef JCS_EXTENSIONS
1424 fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
1425 #endif
1426
DRC9b28def2011-05-21 14:37:15 +00001427 bailout:
1428 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
DRCafc06922012-03-23 19:47:57 +00001429 #ifndef JCS_EXTENSIONS
DRCea3396a2012-04-26 03:18:49 +00001430 if(rgbBuf) free(rgbBuf);
DRCafc06922012-03-23 19:47:57 +00001431 #endif
DRC9b28def2011-05-21 14:37:15 +00001432 if(row_pointer) free(row_pointer);
DRC1f79c7c2015-06-01 19:22:41 +00001433 if(this->jerr.warning) retval=-1;
DRC9b28def2011-05-21 14:37:15 +00001434 return retval;
1435}
1436
1437DLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf,
1438 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
1439 int height, int pixelSize, int flags)
1440{
1441 if(flags&TJ_YUV)
1442 return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags);
1443 else
1444 return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch,
1445 height, getPixelFormat(pixelSize, flags), flags);
1446}
1447
1448
DRC34dca052014-02-28 09:17:14 +00001449static int setDecodeDefaults(struct jpeg_decompress_struct *dinfo,
1450 int pixelFormat, int subsamp, int flags)
1451{
DRC895fd6d2014-02-28 09:35:34 +00001452 int i;
1453
DRC34dca052014-02-28 09:17:14 +00001454 dinfo->scale_num=dinfo->scale_denom=1;
1455
1456 if(subsamp==TJSAMP_GRAY)
1457 {
DRCc9014492014-03-10 09:34:04 +00001458 dinfo->num_components=dinfo->comps_in_scan=1;
DRC34dca052014-02-28 09:17:14 +00001459 dinfo->jpeg_color_space=JCS_GRAYSCALE;
1460 }
1461 else
1462 {
DRCc9014492014-03-10 09:34:04 +00001463 dinfo->num_components=dinfo->comps_in_scan=3;
DRC34dca052014-02-28 09:17:14 +00001464 dinfo->jpeg_color_space=JCS_YCbCr;
1465 }
1466
1467 dinfo->comp_info=(jpeg_component_info *)
1468 (*dinfo->mem->alloc_small)((j_common_ptr)dinfo, JPOOL_IMAGE,
DRC5de454b2014-05-18 19:04:03 +00001469 dinfo->num_components*sizeof(jpeg_component_info));
DRC34dca052014-02-28 09:17:14 +00001470
DRC2bdc0422014-03-07 03:52:57 +00001471 for(i=0; i<dinfo->num_components; i++)
DRC34dca052014-02-28 09:17:14 +00001472 {
DRC2bdc0422014-03-07 03:52:57 +00001473 jpeg_component_info *compptr=&dinfo->comp_info[i];
1474 compptr->h_samp_factor=(i==0)? tjMCUWidth[subsamp]/8:1;
1475 compptr->v_samp_factor=(i==0)? tjMCUHeight[subsamp]/8:1;
1476 compptr->component_index=i;
DRC15c08762014-03-10 20:11:56 +00001477 compptr->component_id=i+1;
DRC2bdc0422014-03-07 03:52:57 +00001478 compptr->quant_tbl_no=compptr->dc_tbl_no=compptr->ac_tbl_no=
1479 (i==0)? 0:1;
1480 dinfo->cur_comp_info[i]=compptr;
DRC34dca052014-02-28 09:17:14 +00001481 }
DRCc9014492014-03-10 09:34:04 +00001482 dinfo->data_precision=8;
1483 for(i=0; i<2; i++)
1484 {
1485 if(dinfo->quant_tbl_ptrs[i]==NULL)
1486 dinfo->quant_tbl_ptrs[i]=jpeg_alloc_quant_table((j_common_ptr)dinfo);
1487 }
DRC34dca052014-02-28 09:17:14 +00001488
1489 return 0;
1490}
1491
1492
1493int my_read_markers(j_decompress_ptr dinfo)
1494{
1495 return JPEG_REACHED_SOS;
1496}
1497
1498void my_reset_marker_reader(j_decompress_ptr dinfo)
1499{
1500}
1501
DRCaecea382014-08-11 18:05:41 +00001502DLLEXPORT int DLLCALL tjDecodeYUVPlanes(tjhandle handle,
1503 unsigned char **srcPlanes, int *strides, int subsamp, unsigned char *dstBuf,
1504 int width, int pitch, int height, int pixelFormat, int flags)
DRC34dca052014-02-28 09:17:14 +00001505{
1506 int i, retval=0; JSAMPROW *row_pointer=NULL;
1507 JSAMPLE *_tmpbuf[MAX_COMPONENTS];
1508 JSAMPROW *tmpbuf[MAX_COMPONENTS], *inbuf[MAX_COMPONENTS];
DRC40dd3142014-08-17 12:23:49 +00001509 int row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS];
DRCaecea382014-08-11 18:05:41 +00001510 JSAMPLE *ptr;
DRC34dca052014-02-28 09:17:14 +00001511 jpeg_component_info *compptr;
1512 #ifndef JCS_EXTENSIONS
1513 unsigned char *rgbBuf=NULL;
DRC230d09d2014-04-20 09:42:49 +00001514 unsigned char *_dstBuf=NULL; int _pitch=0;
DRC34dca052014-02-28 09:17:14 +00001515 #endif
DRCbc56b752014-05-16 10:43:44 +00001516 int (*old_read_markers)(j_decompress_ptr);
1517 void (*old_reset_marker_reader)(j_decompress_ptr);
DRC34dca052014-02-28 09:17:14 +00001518
DRC41861622014-04-16 23:38:37 +00001519 getdinstance(handle);
DRC34dca052014-02-28 09:17:14 +00001520
1521 for(i=0; i<MAX_COMPONENTS; i++)
1522 {
1523 tmpbuf[i]=NULL; _tmpbuf[i]=NULL; inbuf[i]=NULL;
1524 }
1525
1526 if((this->init&DECOMPRESS)==0)
DRCaecea382014-08-11 18:05:41 +00001527 _throw("tjDecodeYUVPlanes(): Instance has not been initialized for decompression");
DRC34dca052014-02-28 09:17:14 +00001528
DRCaecea382014-08-11 18:05:41 +00001529 if(!srcPlanes || !srcPlanes[0] || subsamp<0 || subsamp>=NUMSUBOPT
DRC34dca052014-02-28 09:17:14 +00001530 || dstBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
1531 || pixelFormat>=TJ_NUMPF)
DRCaecea382014-08-11 18:05:41 +00001532 _throw("tjDecodeYUVPlanes(): Invalid argument");
1533 if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2]))
1534 _throw("tjDecodeYUVPlanes(): Invalid argument");
DRC34dca052014-02-28 09:17:14 +00001535
1536 if(setjmp(this->jerr.setjmp_buffer))
1537 {
1538 /* If we get here, the JPEG code has signaled an error. */
1539 retval=-1;
1540 goto bailout;
1541 }
1542
1543 if(pixelFormat==TJPF_CMYK)
DRCaecea382014-08-11 18:05:41 +00001544 _throw("tjDecodeYUVPlanes(): Cannot decode YUV images into CMYK pixels.");
DRC34dca052014-02-28 09:17:14 +00001545
1546 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
DRC34dca052014-02-28 09:17:14 +00001547 dinfo->image_width=width;
1548 dinfo->image_height=height;
1549
DRCbec45b12015-05-17 15:56:18 +00001550 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1551 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1552 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC34dca052014-02-28 09:17:14 +00001553
DRC34dca052014-02-28 09:17:14 +00001554 if(setDecodeDefaults(dinfo, pixelFormat, subsamp, flags)==-1)
1555 {
1556 retval=-1; goto bailout;
1557 }
1558 old_read_markers=dinfo->marker->read_markers;
1559 dinfo->marker->read_markers=my_read_markers;
1560 old_reset_marker_reader=dinfo->marker->reset_marker_reader;
1561 dinfo->marker->reset_marker_reader=my_reset_marker_reader;
1562 jpeg_read_header(dinfo, TRUE);
1563 dinfo->marker->read_markers=old_read_markers;
1564 dinfo->marker->reset_marker_reader=old_reset_marker_reader;
1565
1566 if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
1567 {
1568 retval=-1; goto bailout;
1569 }
DRC7d9f7582014-03-10 20:14:53 +00001570 dinfo->do_fancy_upsampling=FALSE;
DRCdb6d8fc2015-06-08 18:31:34 +00001571 dinfo->Se=DCTSIZE2-1;
DRC2bdc0422014-03-07 03:52:57 +00001572 jinit_master_decompress(dinfo);
DRC34dca052014-02-28 09:17:14 +00001573 (*dinfo->upsample->start_pass)(dinfo);
1574
DRC40dd3142014-08-17 12:23:49 +00001575 pw0=PAD(width, dinfo->max_h_samp_factor);
1576 ph0=PAD(height, dinfo->max_v_samp_factor);
DRC34dca052014-02-28 09:17:14 +00001577
1578 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
1579
DRC230d09d2014-04-20 09:42:49 +00001580 #ifndef JCS_EXTENSIONS
1581 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK &&
1582 (RGB_RED!=tjRedOffset[pixelFormat] ||
1583 RGB_GREEN!=tjGreenOffset[pixelFormat] ||
1584 RGB_BLUE!=tjBlueOffset[pixelFormat] ||
1585 RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
1586 {
1587 rgbBuf=(unsigned char *)malloc(width*height*3);
DRCaecea382014-08-11 18:05:41 +00001588 if(!rgbBuf) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
DRC230d09d2014-04-20 09:42:49 +00001589 _pitch=pitch; pitch=width*3;
1590 _dstBuf=dstBuf; dstBuf=rgbBuf;
1591 }
1592 #endif
1593
DRC40dd3142014-08-17 12:23:49 +00001594 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL)
DRCaecea382014-08-11 18:05:41 +00001595 _throw("tjDecodeYUVPlanes(): Memory allocation failure");
DRC34dca052014-02-28 09:17:14 +00001596 for(i=0; i<height; i++)
1597 {
1598 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&dstBuf[(height-i-1)*pitch];
1599 else row_pointer[i]=&dstBuf[i*pitch];
1600 }
DRC40dd3142014-08-17 12:23:49 +00001601 if(height<ph0)
1602 for(i=height; i<ph0; i++) row_pointer[i]=row_pointer[height-1];
DRC34dca052014-02-28 09:17:14 +00001603
1604 for(i=0; i<dinfo->num_components; i++)
1605 {
1606 compptr=&dinfo->comp_info[i];
1607 _tmpbuf[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
1608 * compptr->v_samp_factor + 16);
DRCaecea382014-08-11 18:05:41 +00001609 if(!_tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
DRC34dca052014-02-28 09:17:14 +00001610 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
DRCaecea382014-08-11 18:05:41 +00001611 if(!tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
DRC34dca052014-02-28 09:17:14 +00001612 for(row=0; row<compptr->v_samp_factor; row++)
1613 {
1614 unsigned char *_tmpbuf_aligned=
1615 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
1616 tmpbuf[i][row]=&_tmpbuf_aligned[
1617 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
1618 }
DRC40dd3142014-08-17 12:23:49 +00001619 pw[i]=pw0*compptr->h_samp_factor/dinfo->max_h_samp_factor;
1620 ph[i]=ph0*compptr->v_samp_factor/dinfo->max_v_samp_factor;
1621 inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]);
DRCaecea382014-08-11 18:05:41 +00001622 if(!inbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1623 ptr=srcPlanes[i];
DRC40dd3142014-08-17 12:23:49 +00001624 for(row=0; row<ph[i]; row++)
DRC34dca052014-02-28 09:17:14 +00001625 {
1626 inbuf[i][row]=ptr;
DRC40dd3142014-08-17 12:23:49 +00001627 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
DRC34dca052014-02-28 09:17:14 +00001628 }
1629 }
1630
DRC40dd3142014-08-17 12:23:49 +00001631 for(row=0; row<ph0; row+=dinfo->max_v_samp_factor)
DRC34dca052014-02-28 09:17:14 +00001632 {
1633 JDIMENSION inrow=0, outrow=0;
1634 for(i=0, compptr=dinfo->comp_info; i<dinfo->num_components; i++, compptr++)
1635 jcopy_sample_rows(inbuf[i],
1636 row*compptr->v_samp_factor/dinfo->max_v_samp_factor, tmpbuf[i], 0,
DRC40dd3142014-08-17 12:23:49 +00001637 compptr->v_samp_factor, pw[i]);
DRC34dca052014-02-28 09:17:14 +00001638 (dinfo->upsample->upsample)(dinfo, tmpbuf, &inrow,
1639 dinfo->max_v_samp_factor, &row_pointer[row], &outrow,
1640 dinfo->max_v_samp_factor);
1641 }
1642 jpeg_abort_decompress(dinfo);
1643
DRC230d09d2014-04-20 09:42:49 +00001644 #ifndef JCS_EXTENSIONS
1645 fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
1646 #endif
1647
DRC34dca052014-02-28 09:17:14 +00001648 bailout:
1649 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
1650 #ifndef JCS_EXTENSIONS
1651 if(rgbBuf) free(rgbBuf);
1652 #endif
1653 if(row_pointer) free(row_pointer);
1654 for(i=0; i<MAX_COMPONENTS; i++)
1655 {
1656 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
1657 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
1658 if(inbuf[i]!=NULL) free(inbuf[i]);
1659 }
DRC1f79c7c2015-06-01 19:22:41 +00001660 if(this->jerr.warning) retval=-1;
DRC34dca052014-02-28 09:17:14 +00001661 return retval;
1662}
1663
DRCaecea382014-08-11 18:05:41 +00001664DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, unsigned char *srcBuf,
1665 int pad, int subsamp, unsigned char *dstBuf, int width, int pitch,
1666 int height, int pixelFormat, int flags)
1667{
1668 unsigned char *srcPlanes[3];
DRC40dd3142014-08-17 12:23:49 +00001669 int pw0, ph0, strides[3], retval=-1;
DRC34dca052014-02-28 09:17:14 +00001670
DRCaecea382014-08-11 18:05:41 +00001671 if(srcBuf==NULL || pad<0 || !isPow2(pad) || subsamp<0 || subsamp>=NUMSUBOPT
1672 || width<=0 || height<=0)
1673 _throw("tjDecodeYUV(): Invalid argument");
1674
DRC40dd3142014-08-17 12:23:49 +00001675 pw0=tjPlaneWidth(0, width, subsamp);
1676 ph0=tjPlaneHeight(0, height, subsamp);
DRCaecea382014-08-11 18:05:41 +00001677 srcPlanes[0]=srcBuf;
DRC40dd3142014-08-17 12:23:49 +00001678 strides[0]=PAD(pw0, pad);
1679 if(subsamp==TJSAMP_GRAY)
1680 {
1681 strides[1]=strides[2]=0;
1682 srcPlanes[1]=srcPlanes[2]=NULL;
1683 }
1684 else
1685 {
1686 int pw1=tjPlaneWidth(1, width, subsamp);
1687 int ph1=tjPlaneHeight(1, height, subsamp);
1688 strides[1]=strides[2]=PAD(pw1, pad);
1689 srcPlanes[1]=srcPlanes[0]+strides[0]*ph0;
1690 srcPlanes[2]=srcPlanes[1]+strides[1]*ph1;
1691 }
DRCaecea382014-08-11 18:05:41 +00001692
1693 return tjDecodeYUVPlanes(handle, srcPlanes, strides, subsamp, dstBuf, width,
1694 pitch, height, pixelFormat, flags);
1695
1696 bailout:
1697 return retval;
1698}
1699
1700DLLEXPORT int DLLCALL tjDecompressToYUVPlanes(tjhandle handle,
1701 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char **dstPlanes,
1702 int width, int *strides, int height, int flags)
DRC9b28def2011-05-21 14:37:15 +00001703{
DRCf610d612013-04-26 10:33:29 +00001704 int i, sfi, row, retval=0; JSAMPROW *outbuf[MAX_COMPONENTS];
DRC418fe282013-05-07 21:17:35 +00001705 int jpegwidth, jpegheight, jpegSubsamp, scaledw, scaledh;
DRC40dd3142014-08-17 12:23:49 +00001706 int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS],
DRC9b28def2011-05-21 14:37:15 +00001707 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
DRCaecea382014-08-11 18:05:41 +00001708 JSAMPLE *_tmpbuf=NULL, *ptr; JSAMPROW *tmpbuf[MAX_COMPONENTS];
DRC418fe282013-05-07 21:17:35 +00001709 int dctsize;
DRC9b28def2011-05-21 14:37:15 +00001710
DRC41861622014-04-16 23:38:37 +00001711 getdinstance(handle);
DRCb51ee892013-10-31 05:00:19 +00001712
DRCf9cf5c72010-12-10 10:58:49 +00001713 for(i=0; i<MAX_COMPONENTS; i++)
1714 {
1715 tmpbuf[i]=NULL; outbuf[i]=NULL;
1716 }
DRC9e17f7d2010-12-10 04:59:13 +00001717
DRCe2f8e692013-10-30 22:21:06 +00001718 if((this->init&DECOMPRESS)==0)
DRCaecea382014-08-11 18:05:41 +00001719 _throw("tjDecompressToYUVPlanes(): Instance has not been initialized for decompression");
DRCe2f8e692013-10-30 22:21:06 +00001720
DRCaecea382014-08-11 18:05:41 +00001721 if(jpegBuf==NULL || jpegSize<=0 || !dstPlanes || !dstPlanes[0] || width<0
1722 || height<0)
1723 _throw("tjDecompressToYUVPlanes(): Invalid argument");
DRC2e7b76b2009-04-03 12:04:24 +00001724
DRCbec45b12015-05-17 15:56:18 +00001725 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1726 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1727 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC0c6a2712010-02-22 08:34:44 +00001728
DRC9b28def2011-05-21 14:37:15 +00001729 if(setjmp(this->jerr.setjmp_buffer))
1730 {
1731 /* If we get here, the JPEG code has signaled an error. */
DRC91e86ba2011-02-15 05:24:08 +00001732 retval=-1;
1733 goto bailout;
DRC9e17f7d2010-12-10 04:59:13 +00001734 }
DRC2e7b76b2009-04-03 12:04:24 +00001735
DRCaecea382014-08-11 18:05:41 +00001736 if(!this->headerRead)
1737 {
1738 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1739 jpeg_read_header(dinfo, TRUE);
1740 }
1741 this->headerRead=0;
DRC418fe282013-05-07 21:17:35 +00001742 jpegSubsamp=getSubsamp(dinfo);
1743 if(jpegSubsamp<0)
DRCaecea382014-08-11 18:05:41 +00001744 _throw("tjDecompressToYUVPlanes(): Could not determine subsampling type for JPEG image");
1745
1746 if(jpegSubsamp!=TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2]))
1747 _throw("tjDecompressToYUVPlanes(): Invalid argument");
DRC2e7b76b2009-04-03 12:04:24 +00001748
DRCf610d612013-04-26 10:33:29 +00001749 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
1750 if(width==0) width=jpegwidth;
1751 if(height==0) height=jpegheight;
1752 for(i=0; i<NUMSF; i++)
1753 {
1754 scaledw=TJSCALED(jpegwidth, sf[i]);
1755 scaledh=TJSCALED(jpegheight, sf[i]);
1756 if(scaledw<=width && scaledh<=height)
1757 break;
1758 }
DRC58ae4012015-08-26 20:29:36 -05001759 if(i>=NUMSF)
DRCaecea382014-08-11 18:05:41 +00001760 _throw("tjDecompressToYUVPlanes(): Could not scale down to desired image dimensions");
DRCcd7c3e62013-08-23 02:49:25 +00001761 if(dinfo->num_components>3)
DRCaecea382014-08-11 18:05:41 +00001762 _throw("tjDecompressToYUVPlanes(): JPEG image must have 3 or fewer components");
DRCcd7c3e62013-08-23 02:49:25 +00001763
DRCf610d612013-04-26 10:33:29 +00001764 width=scaledw; height=scaledh;
1765 dinfo->scale_num=sf[i].num;
1766 dinfo->scale_denom=sf[i].denom;
1767 sfi=i;
1768 jpeg_calc_output_dimensions(dinfo);
1769
DRC418fe282013-05-07 21:17:35 +00001770 dctsize=DCTSIZE*sf[sfi].num/sf[sfi].denom;
1771
DRC9b28def2011-05-21 14:37:15 +00001772 for(i=0; i<dinfo->num_components; i++)
DRC2e7b76b2009-04-03 12:04:24 +00001773 {
DRC9b28def2011-05-21 14:37:15 +00001774 jpeg_component_info *compptr=&dinfo->comp_info[i];
1775 int ih;
DRC418fe282013-05-07 21:17:35 +00001776 iw[i]=compptr->width_in_blocks*dctsize;
1777 ih=compptr->height_in_blocks*dctsize;
DRC40dd3142014-08-17 12:23:49 +00001778 pw[i]=PAD(dinfo->output_width, dinfo->max_h_samp_factor)
DRC9b28def2011-05-21 14:37:15 +00001779 *compptr->h_samp_factor/dinfo->max_h_samp_factor;
DRC40dd3142014-08-17 12:23:49 +00001780 ph[i]=PAD(dinfo->output_height, dinfo->max_v_samp_factor)
DRC9b28def2011-05-21 14:37:15 +00001781 *compptr->v_samp_factor/dinfo->max_v_samp_factor;
DRC40dd3142014-08-17 12:23:49 +00001782 if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1;
DRC418fe282013-05-07 21:17:35 +00001783 th[i]=compptr->v_samp_factor*dctsize;
DRC9b28def2011-05-21 14:37:15 +00001784 tmpbufsize+=iw[i]*th[i];
DRC40dd3142014-08-17 12:23:49 +00001785 if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]))==NULL)
DRCaecea382014-08-11 18:05:41 +00001786 _throw("tjDecompressToYUVPlanes(): Memory allocation failure");
1787 ptr=dstPlanes[i];
DRC40dd3142014-08-17 12:23:49 +00001788 for(row=0; row<ph[i]; row++)
DRC9b28def2011-05-21 14:37:15 +00001789 {
1790 outbuf[i][row]=ptr;
DRC40dd3142014-08-17 12:23:49 +00001791 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
DRC9b28def2011-05-21 14:37:15 +00001792 }
1793 }
1794 if(usetmpbuf)
1795 {
1796 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
DRCaecea382014-08-11 18:05:41 +00001797 _throw("tjDecompressToYUVPlanes(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +00001798 ptr=_tmpbuf;
1799 for(i=0; i<dinfo->num_components; i++)
1800 {
1801 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
DRCaecea382014-08-11 18:05:41 +00001802 _throw("tjDecompressToYUVPlanes(): Memory allocation failure");
DRC9b28def2011-05-21 14:37:15 +00001803 for(row=0; row<th[i]; row++)
1804 {
1805 tmpbuf[i][row]=ptr;
1806 ptr+=iw[i];
1807 }
1808 }
1809 }
DRC9e17f7d2010-12-10 04:59:13 +00001810
DRC25b995a2011-05-21 15:34:54 +00001811 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
DRCe0419b52012-07-03 20:01:31 +00001812 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
DRC9b28def2011-05-21 14:37:15 +00001813 dinfo->raw_data_out=TRUE;
1814
1815 jpeg_start_decompress(dinfo);
1816 for(row=0; row<(int)dinfo->output_height;
DRC418fe282013-05-07 21:17:35 +00001817 row+=dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size)
DRC9b28def2011-05-21 14:37:15 +00001818 {
1819 JSAMPARRAY yuvptr[MAX_COMPONENTS];
1820 int crow[MAX_COMPONENTS];
DRC9e17f7d2010-12-10 04:59:13 +00001821 for(i=0; i<dinfo->num_components; i++)
1822 {
1823 jpeg_component_info *compptr=&dinfo->comp_info[i];
DRC418fe282013-05-07 21:17:35 +00001824 if(jpegSubsamp==TJ_420)
1825 {
1826 /* When 4:2:0 subsampling is used with IDCT scaling, libjpeg will try
1827 to be clever and use the IDCT to perform upsampling on the U and V
1828 planes. For instance, if the output image is to be scaled by 1/2
1829 relative to the JPEG image, then the scaling factor and upsampling
1830 effectively cancel each other, so a normal 8x8 IDCT can be used.
1831 However, this is not desirable when using the decompress-to-YUV
1832 functionality in TurboJPEG, since we want to output the U and V
1833 planes in their subsampled form. Thus, we have to override some
1834 internal libjpeg parameters to force it to use the "scaled" IDCT
1835 functions on the U and V planes. */
1836 compptr->_DCT_scaled_size=dctsize;
1837 compptr->MCU_sample_width=tjMCUWidth[jpegSubsamp]*
1838 sf[sfi].num/sf[sfi].denom*
1839 compptr->v_samp_factor/dinfo->max_v_samp_factor;
1840 dinfo->idct->inverse_DCT[i] = dinfo->idct->inverse_DCT[0];
1841 }
DRC9b28def2011-05-21 14:37:15 +00001842 crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
1843 if(usetmpbuf) yuvptr[i]=tmpbuf[i];
1844 else yuvptr[i]=&outbuf[i][crow[i]];
DRCf9cf5c72010-12-10 10:58:49 +00001845 }
DRCf610d612013-04-26 10:33:29 +00001846 jpeg_read_raw_data(dinfo, yuvptr,
DRC418fe282013-05-07 21:17:35 +00001847 dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size);
DRCf9cf5c72010-12-10 10:58:49 +00001848 if(usetmpbuf)
1849 {
DRC9b28def2011-05-21 14:37:15 +00001850 int j;
DRCf9cf5c72010-12-10 10:58:49 +00001851 for(i=0; i<dinfo->num_components; i++)
1852 {
DRC40dd3142014-08-17 12:23:49 +00001853 for(j=0; j<min(th[i], ph[i]-crow[i]); j++)
DRCf9cf5c72010-12-10 10:58:49 +00001854 {
DRC40dd3142014-08-17 12:23:49 +00001855 memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], pw[i]);
DRCf9cf5c72010-12-10 10:58:49 +00001856 }
DRC9e17f7d2010-12-10 04:59:13 +00001857 }
1858 }
1859 }
DRC9b28def2011-05-21 14:37:15 +00001860 jpeg_finish_decompress(dinfo);
DRC2e7b76b2009-04-03 12:04:24 +00001861
DRC91e86ba2011-02-15 05:24:08 +00001862 bailout:
DRC9b28def2011-05-21 14:37:15 +00001863 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
DRC9e17f7d2010-12-10 04:59:13 +00001864 for(i=0; i<MAX_COMPONENTS; i++)
DRCf9cf5c72010-12-10 10:58:49 +00001865 {
1866 if(tmpbuf[i]) free(tmpbuf[i]);
DRC9e17f7d2010-12-10 04:59:13 +00001867 if(outbuf[i]) free(outbuf[i]);
DRCf9cf5c72010-12-10 10:58:49 +00001868 }
1869 if(_tmpbuf) free(_tmpbuf);
DRC1f79c7c2015-06-01 19:22:41 +00001870 if(this->jerr.warning) retval=-1;
DRC91e86ba2011-02-15 05:24:08 +00001871 return retval;
DRC2e7b76b2009-04-03 12:04:24 +00001872}
1873
DRCaecea382014-08-11 18:05:41 +00001874DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle,
1875 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
1876 int width, int pad, int height, int flags)
1877{
1878 unsigned char *dstPlanes[3];
DRC40dd3142014-08-17 12:23:49 +00001879 int pw0, ph0, strides[3], retval=-1, jpegSubsamp=-1;
DRCaecea382014-08-11 18:05:41 +00001880 int i, jpegwidth, jpegheight, scaledw, scaledh;
1881
1882 getdinstance(handle);
1883
1884 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pad<1
1885 || !isPow2(pad) || height<0)
1886 _throw("tjDecompressToYUV2(): Invalid argument");
1887
1888 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1889 jpeg_read_header(dinfo, TRUE);
1890 jpegSubsamp=getSubsamp(dinfo);
1891 if(jpegSubsamp<0)
1892 _throw("tjDecompressToYUV2(): Could not determine subsampling type for JPEG image");
1893
1894 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
1895 if(width==0) width=jpegwidth;
1896 if(height==0) height=jpegheight;
1897
1898 for(i=0; i<NUMSF; i++)
1899 {
1900 scaledw=TJSCALED(jpegwidth, sf[i]);
1901 scaledh=TJSCALED(jpegheight, sf[i]);
1902 if(scaledw<=width && scaledh<=height)
1903 break;
1904 }
DRC58ae4012015-08-26 20:29:36 -05001905 if(i>=NUMSF)
DRCaecea382014-08-11 18:05:41 +00001906 _throw("tjDecompressToYUV2(): Could not scale down to desired image dimensions");
1907
DRC40dd3142014-08-17 12:23:49 +00001908 pw0=tjPlaneWidth(0, width, jpegSubsamp);
1909 ph0=tjPlaneHeight(0, height, jpegSubsamp);
DRCaecea382014-08-11 18:05:41 +00001910 dstPlanes[0]=dstBuf;
DRC40dd3142014-08-17 12:23:49 +00001911 strides[0]=PAD(pw0, pad);
1912 if(jpegSubsamp==TJSAMP_GRAY)
1913 {
1914 strides[1]=strides[2]=0;
1915 dstPlanes[1]=dstPlanes[2]=NULL;
1916 }
1917 else
1918 {
1919 int pw1=tjPlaneWidth(1, width, jpegSubsamp);
1920 int ph1=tjPlaneHeight(1, height, jpegSubsamp);
1921 strides[1]=strides[2]=PAD(pw1, pad);
1922 dstPlanes[1]=dstPlanes[0]+strides[0]*ph0;
1923 dstPlanes[2]=dstPlanes[1]+strides[1]*ph1;
1924 }
DRCaecea382014-08-11 18:05:41 +00001925
1926 this->headerRead=1;
1927 return tjDecompressToYUVPlanes(handle, jpegBuf, jpegSize, dstPlanes, width,
1928 strides, height, flags);
1929
1930 bailout:
1931 return retval;
1932
1933}
1934
DRCf610d612013-04-26 10:33:29 +00001935DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle,
1936 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
1937 int flags)
1938{
1939 return tjDecompressToYUV2(handle, jpegBuf, jpegSize, dstBuf, 0, 4, 0, flags);
1940}
1941
DRC2e7b76b2009-04-03 12:04:24 +00001942
DRC9b28def2011-05-21 14:37:15 +00001943/* Transformer */
DRC890f1e02011-02-26 22:02:37 +00001944
1945DLLEXPORT tjhandle DLLCALL tjInitTransform(void)
1946{
DRC9b28def2011-05-21 14:37:15 +00001947 tjinstance *this=NULL; tjhandle handle=NULL;
1948 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
DRCda5220a2011-03-02 02:17:30 +00001949 {
DRC007a42c2011-05-22 13:55:56 +00001950 snprintf(errStr, JMSG_LENGTH_MAX,
1951 "tjInitTransform(): Memory allocation failure");
DRCda5220a2011-03-02 02:17:30 +00001952 return NULL;
1953 }
DRC007a42c2011-05-22 13:55:56 +00001954 MEMZERO(this, sizeof(tjinstance));
DRC9b28def2011-05-21 14:37:15 +00001955 handle=_tjInitCompress(this);
1956 if(!handle) return NULL;
1957 handle=_tjInitDecompress(this);
1958 return handle;
DRC890f1e02011-02-26 22:02:37 +00001959}
1960
1961
DRC9b28def2011-05-21 14:37:15 +00001962DLLEXPORT int DLLCALL tjTransform(tjhandle handle, unsigned char *jpegBuf,
1963 unsigned long jpegSize, int n, unsigned char **dstBufs,
1964 unsigned long *dstSizes, tjtransform *t, int flags)
DRC890f1e02011-02-26 22:02:37 +00001965{
DRC0a325192011-03-02 09:22:41 +00001966 jpeg_transform_info *xinfo=NULL;
DRC890f1e02011-02-26 22:02:37 +00001967 jvirt_barray_ptr *srccoefs, *dstcoefs;
DRC9b49f0e2011-07-12 03:17:23 +00001968 int retval=0, i, jpegSubsamp;
DRC890f1e02011-02-26 22:02:37 +00001969
DRC9b28def2011-05-21 14:37:15 +00001970 getinstance(handle);
1971 if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0)
DRC007a42c2011-05-22 13:55:56 +00001972 _throw("tjTransform(): Instance has not been initialized for transformation");
DRC890f1e02011-02-26 22:02:37 +00001973
DRC9b28def2011-05-21 14:37:15 +00001974 if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL
1975 || t==NULL || flags<0)
1976 _throw("tjTransform(): Invalid argument");
1977
DRCbec45b12015-05-17 15:56:18 +00001978 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1979 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1980 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
DRC890f1e02011-02-26 22:02:37 +00001981
DRC9b28def2011-05-21 14:37:15 +00001982 if(setjmp(this->jerr.setjmp_buffer))
1983 {
1984 /* If we get here, the JPEG code has signaled an error. */
DRC890f1e02011-02-26 22:02:37 +00001985 retval=-1;
1986 goto bailout;
1987 }
1988
DRC9b28def2011-05-21 14:37:15 +00001989 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
DRC890f1e02011-02-26 22:02:37 +00001990
DRC0a325192011-03-02 09:22:41 +00001991 if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n))
1992 ==NULL)
DRC007a42c2011-05-22 13:55:56 +00001993 _throw("tjTransform(): Memory allocation failure");
1994 MEMZERO(xinfo, sizeof(jpeg_transform_info)*n);
DRC890f1e02011-02-26 22:02:37 +00001995
DRC0a325192011-03-02 09:22:41 +00001996 for(i=0; i<n; i++)
DRC890f1e02011-02-26 22:02:37 +00001997 {
DRC0a325192011-03-02 09:22:41 +00001998 xinfo[i].transform=xformtypes[t[i].op];
DRC25b995a2011-05-21 15:34:54 +00001999 xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0;
2000 xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0;
2001 xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0;
2002 xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0;
2003 if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1;
DRCba5ea512011-03-04 03:20:34 +00002004 else xinfo[i].slow_hflip=0;
DRC0a325192011-03-02 09:22:41 +00002005
2006 if(xinfo[i].crop)
DRC890f1e02011-02-26 22:02:37 +00002007 {
DRC0a325192011-03-02 09:22:41 +00002008 xinfo[i].crop_xoffset=t[i].r.x; xinfo[i].crop_xoffset_set=JCROP_POS;
2009 xinfo[i].crop_yoffset=t[i].r.y; xinfo[i].crop_yoffset_set=JCROP_POS;
2010 if(t[i].r.w!=0)
2011 {
2012 xinfo[i].crop_width=t[i].r.w; xinfo[i].crop_width_set=JCROP_POS;
2013 }
DRCd932e582011-03-15 20:09:47 +00002014 else xinfo[i].crop_width=JCROP_UNSET;
DRC0a325192011-03-02 09:22:41 +00002015 if(t[i].r.h!=0)
2016 {
2017 xinfo[i].crop_height=t[i].r.h; xinfo[i].crop_height_set=JCROP_POS;
2018 }
DRCd932e582011-03-15 20:09:47 +00002019 else xinfo[i].crop_height=JCROP_UNSET;
DRC890f1e02011-02-26 22:02:37 +00002020 }
2021 }
2022
DRC9b28def2011-05-21 14:37:15 +00002023 jcopy_markers_setup(dinfo, JCOPYOPT_ALL);
2024 jpeg_read_header(dinfo, TRUE);
DRC9b49f0e2011-07-12 03:17:23 +00002025 jpegSubsamp=getSubsamp(dinfo);
2026 if(jpegSubsamp<0)
2027 _throw("tjTransform(): Could not determine subsampling type for JPEG image");
DRC890f1e02011-02-26 22:02:37 +00002028
DRC0a325192011-03-02 09:22:41 +00002029 for(i=0; i<n; i++)
DRC890f1e02011-02-26 22:02:37 +00002030 {
DRC9b28def2011-05-21 14:37:15 +00002031 if(!jtransform_request_workspace(dinfo, &xinfo[i]))
DRC007a42c2011-05-22 13:55:56 +00002032 _throw("tjTransform(): Transform is not perfect");
DRC890f1e02011-02-26 22:02:37 +00002033
DRC0a325192011-03-02 09:22:41 +00002034 if(xinfo[i].crop)
DRC890f1e02011-02-26 22:02:37 +00002035 {
DRC0a325192011-03-02 09:22:41 +00002036 if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0
2037 || (t[i].r.y%xinfo[i].iMCU_sample_height)!=0)
2038 {
DRC9b28def2011-05-21 14:37:15 +00002039 snprintf(errStr, JMSG_LENGTH_MAX,
DRC0a325192011-03-02 09:22:41 +00002040 "To crop this JPEG image, x must be a multiple of %d\n"
2041 "and y must be a multiple of %d.\n",
2042 xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height);
2043 retval=-1; goto bailout;
2044 }
DRC890f1e02011-02-26 22:02:37 +00002045 }
2046 }
2047
DRC9b28def2011-05-21 14:37:15 +00002048 srccoefs=jpeg_read_coefficients(dinfo);
DRC890f1e02011-02-26 22:02:37 +00002049
DRC0a325192011-03-02 09:22:41 +00002050 for(i=0; i<n; i++)
2051 {
DRCff78e372011-05-24 10:17:32 +00002052 int w, h, alloc=1;
DRC0a325192011-03-02 09:22:41 +00002053 if(!xinfo[i].crop)
2054 {
DRC9b28def2011-05-21 14:37:15 +00002055 w=dinfo->image_width; h=dinfo->image_height;
DRC0a325192011-03-02 09:22:41 +00002056 }
2057 else
2058 {
2059 w=xinfo[i].crop_width; h=xinfo[i].crop_height;
2060 }
DRCff78e372011-05-24 10:17:32 +00002061 if(flags&TJFLAG_NOREALLOC)
2062 {
DRC9b49f0e2011-07-12 03:17:23 +00002063 alloc=0; dstSizes[i]=tjBufSize(w, h, jpegSubsamp);
DRCff78e372011-05-24 10:17:32 +00002064 }
DRC7bf04d32011-09-17 00:18:31 +00002065 if(!(t[i].options&TJXOPT_NOOUTPUT))
2066 jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc);
DRC9b28def2011-05-21 14:37:15 +00002067 jpeg_copy_critical_parameters(dinfo, cinfo);
2068 dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs,
DRC0a325192011-03-02 09:22:41 +00002069 &xinfo[i]);
DRC7bf04d32011-09-17 00:18:31 +00002070 if(!(t[i].options&TJXOPT_NOOUTPUT))
2071 {
2072 jpeg_write_coefficients(cinfo, dstcoefs);
2073 jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL);
2074 }
2075 else jinit_c_master_control(cinfo, TRUE);
DRC9b28def2011-05-21 14:37:15 +00002076 jtransform_execute_transformation(dinfo, cinfo, srccoefs,
DRC0a325192011-03-02 09:22:41 +00002077 &xinfo[i]);
DRC7bf04d32011-09-17 00:18:31 +00002078 if(t[i].customFilter)
2079 {
DRCefe28ce2012-01-17 11:48:38 +00002080 int ci, y; JDIMENSION by;
DRC7bf04d32011-09-17 00:18:31 +00002081 for(ci=0; ci<cinfo->num_components; ci++)
2082 {
2083 jpeg_component_info *compptr=&cinfo->comp_info[ci];
2084 tjregion arrayRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
2085 DCTSIZE};
2086 tjregion planeRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
2087 compptr->height_in_blocks*DCTSIZE};
2088 for(by=0; by<compptr->height_in_blocks; by+=compptr->v_samp_factor)
2089 {
2090 JBLOCKARRAY barray=(dinfo->mem->access_virt_barray)
2091 ((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor,
2092 TRUE);
2093 for(y=0; y<compptr->v_samp_factor; y++)
2094 {
2095 if(t[i].customFilter(barray[y][0], arrayRegion, planeRegion,
DRCf5467112011-09-20 05:02:19 +00002096 ci, i, &t[i])==-1)
DRC7bf04d32011-09-17 00:18:31 +00002097 _throw("tjTransform(): Error in custom filter");
2098 arrayRegion.y+=DCTSIZE;
2099 }
2100 }
2101 }
2102 }
2103 if(!(t[i].options&TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo);
DRC0a325192011-03-02 09:22:41 +00002104 }
2105
DRC9b28def2011-05-21 14:37:15 +00002106 jpeg_finish_decompress(dinfo);
DRC890f1e02011-02-26 22:02:37 +00002107
DRC890f1e02011-02-26 22:02:37 +00002108 bailout:
DRC9b28def2011-05-21 14:37:15 +00002109 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
2110 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
DRC0a325192011-03-02 09:22:41 +00002111 if(xinfo) free(xinfo);
DRC1f79c7c2015-06-01 19:22:41 +00002112 if(this->jerr.warning) retval=-1;
DRC890f1e02011-02-26 22:02:37 +00002113 return retval;
2114}