Home | History | Annotate | Download | only in libjpeg-turbo
      1 /*
      2  * Copyright (C)2009-2017 D. R. Commander.  All Rights Reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are met:
      6  *
      7  * - 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.
     27  */
     28 
     29 /* TurboJPEG/LJT:  this implements the TurboJPEG API using libjpeg or
     30    libjpeg-turbo */
     31 
     32 #include <stdio.h>
     33 #include <stdlib.h>
     34 #include <ctype.h>
     35 #include <jinclude.h>
     36 #define JPEG_INTERNALS
     37 #include <jpeglib.h>
     38 #include <jerror.h>
     39 #include <setjmp.h>
     40 #include "./turbojpeg.h"
     41 #include "./tjutil.h"
     42 #include "transupp.h"
     43 #include "./jpegcomp.h"
     44 
     45 extern void jpeg_mem_dest_tj(j_compress_ptr, unsigned char **,
     46 	unsigned long *, boolean);
     47 extern void jpeg_mem_src_tj(j_decompress_ptr, const unsigned char *,
     48 	unsigned long);
     49 
     50 #define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
     51 #define isPow2(x) (((x)&(x-1))==0)
     52 
     53 
     54 /* Error handling (based on example in example.c) */
     55 
     56 static char errStr[JMSG_LENGTH_MAX]="No error";
     57 
     58 struct my_error_mgr
     59 {
     60 	struct jpeg_error_mgr pub;
     61 	jmp_buf setjmp_buffer;
     62 	void (*emit_message)(j_common_ptr, int);
     63 	boolean warning;
     64 };
     65 typedef struct my_error_mgr *my_error_ptr;
     66 
     67 static void my_error_exit(j_common_ptr cinfo)
     68 {
     69 	my_error_ptr myerr=(my_error_ptr)cinfo->err;
     70 	(*cinfo->err->output_message)(cinfo);
     71 	longjmp(myerr->setjmp_buffer, 1);
     72 }
     73 
     74 /* Based on output_message() in jerror.c */
     75 
     76 static void my_output_message(j_common_ptr cinfo)
     77 {
     78 	(*cinfo->err->format_message)(cinfo, errStr);
     79 }
     80 
     81 static void my_emit_message(j_common_ptr cinfo, int msg_level)
     82 {
     83 	my_error_ptr myerr=(my_error_ptr)cinfo->err;
     84 	myerr->emit_message(cinfo, msg_level);
     85 	if(msg_level<0) myerr->warning=TRUE;
     86 }
     87 
     88 
     89 /* Global structures, macros, etc. */
     90 
     91 enum {COMPRESS=1, DECOMPRESS=2};
     92 
     93 typedef struct _tjinstance
     94 {
     95 	struct jpeg_compress_struct cinfo;
     96 	struct jpeg_decompress_struct dinfo;
     97 	struct my_error_mgr jerr;
     98 	int init, headerRead;
     99 } tjinstance;
    100 
    101 static const int pixelsize[TJ_NUMSAMP]={3, 3, 3, 1, 3, 3};
    102 
    103 static const JXFORM_CODE xformtypes[TJ_NUMXOP]=
    104 {
    105 	JXFORM_NONE, JXFORM_FLIP_H, JXFORM_FLIP_V, JXFORM_TRANSPOSE,
    106 	JXFORM_TRANSVERSE, JXFORM_ROT_90, JXFORM_ROT_180, JXFORM_ROT_270
    107 };
    108 
    109 #define NUMSF 16
    110 static const tjscalingfactor sf[NUMSF]={
    111 	{2, 1},
    112 	{15, 8},
    113 	{7, 4},
    114 	{13, 8},
    115 	{3, 2},
    116 	{11, 8},
    117 	{5, 4},
    118 	{9, 8},
    119 	{1, 1},
    120 	{7, 8},
    121 	{3, 4},
    122 	{5, 8},
    123 	{1, 2},
    124 	{3, 8},
    125 	{1, 4},
    126 	{1, 8}
    127 };
    128 
    129 #define _throw(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s", m);  \
    130 	retval=-1;  goto bailout;}
    131 #define getinstance(handle) tjinstance *this=(tjinstance *)handle;  \
    132 	j_compress_ptr cinfo=NULL;  j_decompress_ptr dinfo=NULL;  \
    133 	if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle");  \
    134 		return -1;}  \
    135 	cinfo=&this->cinfo;  dinfo=&this->dinfo;  \
    136 	this->jerr.warning=FALSE;
    137 #define getcinstance(handle) tjinstance *this=(tjinstance *)handle;  \
    138 	j_compress_ptr cinfo=NULL;  \
    139 	if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle");  \
    140 		return -1;}  \
    141 	cinfo=&this->cinfo;  \
    142 	this->jerr.warning=FALSE;
    143 #define getdinstance(handle) tjinstance *this=(tjinstance *)handle;  \
    144 	j_decompress_ptr dinfo=NULL;  \
    145 	if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle");  \
    146 		return -1;}  \
    147 	dinfo=&this->dinfo;  \
    148 	this->jerr.warning=FALSE;
    149 
    150 static int getPixelFormat(int pixelSize, int flags)
    151 {
    152 	if(pixelSize==1) return TJPF_GRAY;
    153 	if(pixelSize==3)
    154 	{
    155 		if(flags&TJ_BGR) return TJPF_BGR;
    156 		else return TJPF_RGB;
    157 	}
    158 	if(pixelSize==4)
    159 	{
    160 		if(flags&TJ_ALPHAFIRST)
    161 		{
    162 			if(flags&TJ_BGR) return TJPF_XBGR;
    163 			else return TJPF_XRGB;
    164 		}
    165 		else
    166 		{
    167 			if(flags&TJ_BGR) return TJPF_BGRX;
    168 			else return TJPF_RGBX;
    169 		}
    170 	}
    171 	return -1;
    172 }
    173 
    174 static int setCompDefaults(struct jpeg_compress_struct *cinfo,
    175 	int pixelFormat, int subsamp, int jpegQual, int flags)
    176 {
    177 	int retval=0;
    178 	char *env=NULL;
    179 
    180 	switch(pixelFormat)
    181 	{
    182 		case TJPF_GRAY:
    183 			cinfo->in_color_space=JCS_GRAYSCALE;  break;
    184 		#if JCS_EXTENSIONS==1
    185 		case TJPF_RGB:
    186 			cinfo->in_color_space=JCS_EXT_RGB;  break;
    187 		case TJPF_BGR:
    188 			cinfo->in_color_space=JCS_EXT_BGR;  break;
    189 		case TJPF_RGBX:
    190 		case TJPF_RGBA:
    191 			cinfo->in_color_space=JCS_EXT_RGBX;  break;
    192 		case TJPF_BGRX:
    193 		case TJPF_BGRA:
    194 			cinfo->in_color_space=JCS_EXT_BGRX;  break;
    195 		case TJPF_XRGB:
    196 		case TJPF_ARGB:
    197 			cinfo->in_color_space=JCS_EXT_XRGB;  break;
    198 		case TJPF_XBGR:
    199 		case TJPF_ABGR:
    200 			cinfo->in_color_space=JCS_EXT_XBGR;  break;
    201 		#else
    202 		case TJPF_RGB:
    203 		case TJPF_BGR:
    204 		case TJPF_RGBX:
    205 		case TJPF_BGRX:
    206 		case TJPF_XRGB:
    207 		case TJPF_XBGR:
    208 		case TJPF_RGBA:
    209 		case TJPF_BGRA:
    210 		case TJPF_ARGB:
    211 		case TJPF_ABGR:
    212 			cinfo->in_color_space=JCS_RGB;  pixelFormat=TJPF_RGB;
    213 			break;
    214 		#endif
    215 		case TJPF_CMYK:
    216 			cinfo->in_color_space=JCS_CMYK;  break;
    217 	}
    218 
    219 	cinfo->input_components=tjPixelSize[pixelFormat];
    220 	jpeg_set_defaults(cinfo);
    221 
    222 #ifndef NO_GETENV
    223 	if((env=getenv("TJ_OPTIMIZE"))!=NULL && strlen(env)>0 && !strcmp(env, "1"))
    224 		cinfo->optimize_coding=TRUE;
    225 	if((env=getenv("TJ_ARITHMETIC"))!=NULL && strlen(env)>0 && !strcmp(env, "1"))
    226 		cinfo->arith_code=TRUE;
    227 	if((env=getenv("TJ_RESTART"))!=NULL && strlen(env)>0)
    228 	{
    229 		int temp=-1;  char tempc=0;
    230 		if(sscanf(env, "%d%c", &temp, &tempc)>=1 && temp>=0 && temp<=65535)
    231 		{
    232 			if(toupper(tempc)=='B')
    233 			{
    234 				cinfo->restart_interval=temp;
    235 				cinfo->restart_in_rows=0;
    236 			}
    237 			else
    238 				cinfo->restart_in_rows=temp;
    239 		}
    240 	}
    241 #endif
    242 
    243 	if(jpegQual>=0)
    244 	{
    245 		jpeg_set_quality(cinfo, jpegQual, TRUE);
    246 		if(jpegQual>=96 || flags&TJFLAG_ACCURATEDCT) cinfo->dct_method=JDCT_ISLOW;
    247 		else cinfo->dct_method=JDCT_FASTEST;
    248 	}
    249 	if(subsamp==TJSAMP_GRAY)
    250 		jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
    251 	else if(pixelFormat==TJPF_CMYK)
    252 		jpeg_set_colorspace(cinfo, JCS_YCCK);
    253 	else jpeg_set_colorspace(cinfo, JCS_YCbCr);
    254 
    255 #ifndef NO_GETENV
    256 	if((env=getenv("TJ_PROGRESSIVE"))!=NULL && strlen(env)>0
    257 		&& !strcmp(env, "1"))
    258 		jpeg_simple_progression(cinfo);
    259 #endif
    260 
    261 	cinfo->comp_info[0].h_samp_factor=tjMCUWidth[subsamp]/8;
    262 	cinfo->comp_info[1].h_samp_factor=1;
    263 	cinfo->comp_info[2].h_samp_factor=1;
    264 	if(cinfo->num_components>3)
    265 		cinfo->comp_info[3].h_samp_factor=tjMCUWidth[subsamp]/8;
    266 	cinfo->comp_info[0].v_samp_factor=tjMCUHeight[subsamp]/8;
    267 	cinfo->comp_info[1].v_samp_factor=1;
    268 	cinfo->comp_info[2].v_samp_factor=1;
    269 	if(cinfo->num_components>3)
    270 		cinfo->comp_info[3].v_samp_factor=tjMCUHeight[subsamp]/8;
    271 
    272 	return retval;
    273 }
    274 
    275 static int setDecompDefaults(struct jpeg_decompress_struct *dinfo,
    276 	int pixelFormat, int flags)
    277 {
    278 	int retval=0;
    279 
    280 	switch(pixelFormat)
    281 	{
    282 		case TJPF_GRAY:
    283 			dinfo->out_color_space=JCS_GRAYSCALE;  break;
    284 		#if JCS_EXTENSIONS==1
    285 		case TJPF_RGB:
    286 			dinfo->out_color_space=JCS_EXT_RGB;  break;
    287 		case TJPF_BGR:
    288 			dinfo->out_color_space=JCS_EXT_BGR;  break;
    289 		case TJPF_RGBX:
    290 			dinfo->out_color_space=JCS_EXT_RGBX;  break;
    291 		case TJPF_BGRX:
    292 			dinfo->out_color_space=JCS_EXT_BGRX;  break;
    293 		case TJPF_XRGB:
    294 			dinfo->out_color_space=JCS_EXT_XRGB;  break;
    295 		case TJPF_XBGR:
    296 			dinfo->out_color_space=JCS_EXT_XBGR;  break;
    297 		#if JCS_ALPHA_EXTENSIONS==1
    298 		case TJPF_RGBA:
    299 			dinfo->out_color_space=JCS_EXT_RGBA;  break;
    300 		case TJPF_BGRA:
    301 			dinfo->out_color_space=JCS_EXT_BGRA;  break;
    302 		case TJPF_ARGB:
    303 			dinfo->out_color_space=JCS_EXT_ARGB;  break;
    304 		case TJPF_ABGR:
    305 			dinfo->out_color_space=JCS_EXT_ABGR;  break;
    306 		#endif
    307 		#else
    308 		case TJPF_RGB:
    309 		case TJPF_BGR:
    310 		case TJPF_RGBX:
    311 		case TJPF_BGRX:
    312 		case TJPF_XRGB:
    313 		case TJPF_XBGR:
    314 		case TJPF_RGBA:
    315 		case TJPF_BGRA:
    316 		case TJPF_ARGB:
    317 		case TJPF_ABGR:
    318 			dinfo->out_color_space=JCS_RGB;  break;
    319 		#endif
    320 		case TJPF_CMYK:
    321 			dinfo->out_color_space=JCS_CMYK;  break;
    322 		default:
    323 			_throw("Unsupported pixel format");
    324 	}
    325 
    326 	if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
    327 
    328 	bailout:
    329 	return retval;
    330 }
    331 
    332 
    333 static int getSubsamp(j_decompress_ptr dinfo)
    334 {
    335 	int retval=-1, i, k;
    336 
    337 	/* The sampling factors actually have no meaning with grayscale JPEG files,
    338 	   and in fact it's possible to generate grayscale JPEGs with sampling
    339 	   factors > 1 (even though those sampling factors are ignored by the
    340 	   decompressor.)  Thus, we need to treat grayscale as a special case. */
    341 	if(dinfo->num_components==1 && dinfo->jpeg_color_space==JCS_GRAYSCALE)
    342 		return TJSAMP_GRAY;
    343 
    344 	for(i=0; i<NUMSUBOPT; i++)
    345 	{
    346 		if(dinfo->num_components==pixelsize[i]
    347 			|| ((dinfo->jpeg_color_space==JCS_YCCK
    348 				|| dinfo->jpeg_color_space==JCS_CMYK)
    349 					&& pixelsize[i]==3 && dinfo->num_components==4))
    350 		{
    351 			if(dinfo->comp_info[0].h_samp_factor==tjMCUWidth[i]/8
    352 				&& dinfo->comp_info[0].v_samp_factor==tjMCUHeight[i]/8)
    353 			{
    354 				int match=0;
    355 				for(k=1; k<dinfo->num_components; k++)
    356 				{
    357 					int href=1, vref=1;
    358 					if(dinfo->jpeg_color_space==JCS_YCCK && k==3)
    359 					{
    360 						href=tjMCUWidth[i]/8;  vref=tjMCUHeight[i]/8;
    361 					}
    362 					if(dinfo->comp_info[k].h_samp_factor==href
    363 						&& dinfo->comp_info[k].v_samp_factor==vref)
    364 						match++;
    365 				}
    366 				if(match==dinfo->num_components-1)
    367 				{
    368 					retval=i;  break;
    369 				}
    370 			}
    371 			/* Handle 4:2:2 and 4:4:0 images whose sampling factors are specified
    372 			   in non-standard ways. */
    373 			if(dinfo->comp_info[0].h_samp_factor==2 &&
    374 				dinfo->comp_info[0].v_samp_factor==2 &&
    375 				(i==TJSAMP_422 || i==TJSAMP_440))
    376 			{
    377 				int match=0;
    378 				for(k=1; k<dinfo->num_components; k++)
    379 				{
    380 					int href=tjMCUHeight[i]/8, vref=tjMCUWidth[i]/8;
    381 					if(dinfo->jpeg_color_space==JCS_YCCK && k==3)
    382 					{
    383 						href=vref=2;
    384 					}
    385 					if(dinfo->comp_info[k].h_samp_factor==href
    386 						&& dinfo->comp_info[k].v_samp_factor==vref)
    387 						match++;
    388 				}
    389 				if(match==dinfo->num_components-1)
    390 				{
    391 					retval=i;  break;
    392 				}
    393 			}
    394 		}
    395 	}
    396 	return retval;
    397 }
    398 
    399 
    400 #ifndef JCS_EXTENSIONS
    401 
    402 /* Conversion functions to emulate the colorspace extensions.  This allows the
    403    TurboJPEG wrapper to be used with libjpeg */
    404 
    405 #define TORGB(PS, ROFFSET, GOFFSET, BOFFSET) {  \
    406 	int rowPad=pitch-width*PS;  \
    407 	while(height--)  \
    408 	{  \
    409 		unsigned char *endOfRow=src+width*PS;  \
    410 		while(src<endOfRow)  \
    411 		{  \
    412 			dst[RGB_RED]=src[ROFFSET];  \
    413 			dst[RGB_GREEN]=src[GOFFSET];  \
    414 			dst[RGB_BLUE]=src[BOFFSET];  \
    415 			dst+=RGB_PIXELSIZE;  src+=PS;  \
    416 		}  \
    417 		src+=rowPad;  \
    418 	}  \
    419 }
    420 
    421 static unsigned char *toRGB(unsigned char *src, int width, int pitch,
    422 	int height, int pixelFormat, unsigned char *dst)
    423 {
    424 	unsigned char *retval=src;
    425 	switch(pixelFormat)
    426 	{
    427 		case TJPF_RGB:
    428 			#if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3
    429 			retval=dst;  TORGB(3, 0, 1, 2);
    430 			#endif
    431 			break;
    432 		case TJPF_BGR:
    433 			#if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3
    434 			retval=dst;  TORGB(3, 2, 1, 0);
    435 			#endif
    436 			break;
    437 		case TJPF_RGBX:
    438 		case TJPF_RGBA:
    439 			#if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
    440 			retval=dst;  TORGB(4, 0, 1, 2);
    441 			#endif
    442 			break;
    443 		case TJPF_BGRX:
    444 		case TJPF_BGRA:
    445 			#if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
    446 			retval=dst;  TORGB(4, 2, 1, 0);
    447 			#endif
    448 			break;
    449 		case TJPF_XRGB:
    450 		case TJPF_ARGB:
    451 			#if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
    452 			retval=dst;  TORGB(4, 1, 2, 3);
    453 			#endif
    454 			break;
    455 		case TJPF_XBGR:
    456 		case TJPF_ABGR:
    457 			#if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
    458 			retval=dst;  TORGB(4, 3, 2, 1);
    459 			#endif
    460 			break;
    461 	}
    462 	return retval;
    463 }
    464 
    465 #define FROMRGB(PS, ROFFSET, GOFFSET, BOFFSET, SETALPHA) {  \
    466 	int rowPad=pitch-width*PS;  \
    467 	while(height--)  \
    468 	{  \
    469 		unsigned char *endOfRow=dst+width*PS;  \
    470 		while(dst<endOfRow)  \
    471 		{  \
    472 			dst[ROFFSET]=src[RGB_RED];  \
    473 			dst[GOFFSET]=src[RGB_GREEN];  \
    474 			dst[BOFFSET]=src[RGB_BLUE];  \
    475 			SETALPHA  \
    476 			dst+=PS;  src+=RGB_PIXELSIZE;  \
    477 		}  \
    478 		dst+=rowPad;  \
    479 	}  \
    480 }
    481 
    482 static void fromRGB(unsigned char *src, unsigned char *dst, int width,
    483 	int pitch, int height, int pixelFormat)
    484 {
    485 	switch(pixelFormat)
    486 	{
    487 		case TJPF_RGB:
    488 			#if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3
    489 			FROMRGB(3, 0, 1, 2,);
    490 			#endif
    491 			break;
    492 		case TJPF_BGR:
    493 			#if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3
    494 			FROMRGB(3, 2, 1, 0,);
    495 			#endif
    496 			break;
    497 		case TJPF_RGBX:
    498 			#if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
    499 			FROMRGB(4, 0, 1, 2,);
    500 			#endif
    501 			break;
    502 		case TJPF_RGBA:
    503 			#if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
    504 			FROMRGB(4, 0, 1, 2, dst[3]=0xFF;);
    505 			#endif
    506 			break;
    507 		case TJPF_BGRX:
    508 			#if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
    509 			FROMRGB(4, 2, 1, 0,);
    510 			#endif
    511 			break;
    512 		case TJPF_BGRA:
    513 			#if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
    514 			FROMRGB(4, 2, 1, 0, dst[3]=0xFF;);  return;
    515 			#endif
    516 			break;
    517 		case TJPF_XRGB:
    518 			#if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
    519 			FROMRGB(4, 1, 2, 3,);  return;
    520 			#endif
    521 			break;
    522 		case TJPF_ARGB:
    523 			#if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
    524 			FROMRGB(4, 1, 2, 3, dst[0]=0xFF;);  return;
    525 			#endif
    526 			break;
    527 		case TJPF_XBGR:
    528 			#if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
    529 			FROMRGB(4, 3, 2, 1,);  return;
    530 			#endif
    531 			break;
    532 		case TJPF_ABGR:
    533 			#if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
    534 			FROMRGB(4, 3, 2, 1, dst[0]=0xFF;);  return;
    535 			#endif
    536 			break;
    537 	}
    538 }
    539 
    540 #endif
    541 
    542 
    543 /* General API functions */
    544 
    545 DLLEXPORT char* DLLCALL tjGetErrorStr(void)
    546 {
    547 	return errStr;
    548 }
    549 
    550 
    551 DLLEXPORT int DLLCALL tjDestroy(tjhandle handle)
    552 {
    553 	getinstance(handle);
    554 	if(setjmp(this->jerr.setjmp_buffer)) return -1;
    555 	if(this->init&COMPRESS) jpeg_destroy_compress(cinfo);
    556 	if(this->init&DECOMPRESS) jpeg_destroy_decompress(dinfo);
    557 	free(this);
    558 	return 0;
    559 }
    560 
    561 
    562 /* These are exposed mainly because Windows can't malloc() and free() across
    563    DLL boundaries except when the CRT DLL is used, and we don't use the CRT DLL
    564    with turbojpeg.dll for compatibility reasons.  However, these functions
    565    can potentially be used for other purposes by different implementations. */
    566 
    567 DLLEXPORT void DLLCALL tjFree(unsigned char *buf)
    568 {
    569 	if(buf) free(buf);
    570 }
    571 
    572 
    573 DLLEXPORT unsigned char *DLLCALL tjAlloc(int bytes)
    574 {
    575 	return (unsigned char *)malloc(bytes);
    576 }
    577 
    578 
    579 /* Compressor  */
    580 
    581 static tjhandle _tjInitCompress(tjinstance *this)
    582 {
    583 	static unsigned char buffer[1];
    584 	unsigned char *buf=buffer;  unsigned long size=1;
    585 
    586 	/* This is also straight out of example.c */
    587 	this->cinfo.err=jpeg_std_error(&this->jerr.pub);
    588 	this->jerr.pub.error_exit=my_error_exit;
    589 	this->jerr.pub.output_message=my_output_message;
    590 	this->jerr.emit_message=this->jerr.pub.emit_message;
    591 	this->jerr.pub.emit_message=my_emit_message;
    592 
    593 	if(setjmp(this->jerr.setjmp_buffer))
    594 	{
    595 		/* If we get here, the JPEG code has signaled an error. */
    596 		if(this) free(this);
    597 		return NULL;
    598 	}
    599 
    600 	jpeg_create_compress(&this->cinfo);
    601 	/* Make an initial call so it will create the destination manager */
    602 	jpeg_mem_dest_tj(&this->cinfo, &buf, &size, 0);
    603 
    604 	this->init|=COMPRESS;
    605 	return (tjhandle)this;
    606 }
    607 
    608 DLLEXPORT tjhandle DLLCALL tjInitCompress(void)
    609 {
    610 	tjinstance *this=NULL;
    611 	if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
    612 	{
    613 		snprintf(errStr, JMSG_LENGTH_MAX,
    614 			"tjInitCompress(): Memory allocation failure");
    615 		return NULL;
    616 	}
    617 	MEMZERO(this, sizeof(tjinstance));
    618 	return _tjInitCompress(this);
    619 }
    620 
    621 
    622 DLLEXPORT unsigned long DLLCALL tjBufSize(int width, int height,
    623 	int jpegSubsamp)
    624 {
    625 	unsigned long retval=0;  int mcuw, mcuh, chromasf;
    626 	if(width<1 || height<1 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT)
    627 		_throw("tjBufSize(): Invalid argument");
    628 
    629 	/* This allows for rare corner cases in which a JPEG image can actually be
    630 	   larger than the uncompressed input (we wouldn't mention it if it hadn't
    631 	   happened before.) */
    632 	mcuw=tjMCUWidth[jpegSubsamp];
    633 	mcuh=tjMCUHeight[jpegSubsamp];
    634 	chromasf=jpegSubsamp==TJSAMP_GRAY? 0: 4*64/(mcuw*mcuh);
    635 	retval=PAD(width, mcuw) * PAD(height, mcuh) * (2 + chromasf) + 2048;
    636 
    637 	bailout:
    638 	return retval;
    639 }
    640 
    641 DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
    642 {
    643 	unsigned long retval=0;
    644 	if(width<1 || height<1)
    645 		_throw("TJBUFSIZE(): Invalid argument");
    646 
    647 	/* This allows for rare corner cases in which a JPEG image can actually be
    648 	   larger than the uncompressed input (we wouldn't mention it if it hadn't
    649 	   happened before.) */
    650 	retval=PAD(width, 16) * PAD(height, 16) * 6 + 2048;
    651 
    652 	bailout:
    653 	return retval;
    654 }
    655 
    656 
    657 DLLEXPORT unsigned long DLLCALL tjBufSizeYUV2(int width, int pad, int height,
    658 	int subsamp)
    659 {
    660 	int retval=0, nc, i;
    661 
    662 	if(subsamp<0 || subsamp>=NUMSUBOPT)
    663 		_throw("tjBufSizeYUV2(): Invalid argument");
    664 
    665 	nc=(subsamp==TJSAMP_GRAY? 1:3);
    666 	for(i=0; i<nc; i++)
    667 	{
    668 		int pw=tjPlaneWidth(i, width, subsamp);
    669 		int stride=PAD(pw, pad);
    670 		int ph=tjPlaneHeight(i, height, subsamp);
    671 		if(pw<0 || ph<0) return -1;
    672 		else retval+=stride*ph;
    673 	}
    674 
    675 	bailout:
    676 	return retval;
    677 }
    678 
    679 DLLEXPORT unsigned long DLLCALL tjBufSizeYUV(int width, int height,
    680 	int subsamp)
    681 {
    682 	return tjBufSizeYUV2(width, 4, height, subsamp);
    683 }
    684 
    685 DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
    686 	int subsamp)
    687 {
    688 	return tjBufSizeYUV(width, height, subsamp);
    689 }
    690 
    691 
    692 DLLEXPORT int tjPlaneWidth(int componentID, int width, int subsamp)
    693 {
    694 	int pw, nc, retval=0;
    695 
    696 	if(width<1 || subsamp<0 || subsamp>=TJ_NUMSAMP)
    697 		_throw("tjPlaneWidth(): Invalid argument");
    698 	nc=(subsamp==TJSAMP_GRAY? 1:3);
    699 	if(componentID<0 || componentID>=nc)
    700 		_throw("tjPlaneWidth(): Invalid argument");
    701 
    702 	pw=PAD(width, tjMCUWidth[subsamp]/8);
    703 	if(componentID==0)
    704 		retval=pw;
    705 	else
    706 		retval=pw*8/tjMCUWidth[subsamp];
    707 
    708 	bailout:
    709 	return retval;
    710 }
    711 
    712 
    713 DLLEXPORT int tjPlaneHeight(int componentID, int height, int subsamp)
    714 {
    715 	int ph, nc, retval=0;
    716 
    717 	if(height<1 || subsamp<0 || subsamp>=TJ_NUMSAMP)
    718 		_throw("tjPlaneHeight(): Invalid argument");
    719 	nc=(subsamp==TJSAMP_GRAY? 1:3);
    720 	if(componentID<0 || componentID>=nc)
    721 		_throw("tjPlaneHeight(): Invalid argument");
    722 
    723 	ph=PAD(height, tjMCUHeight[subsamp]/8);
    724 	if(componentID==0)
    725 		retval=ph;
    726 	else
    727 		retval=ph*8/tjMCUHeight[subsamp];
    728 
    729 	bailout:
    730 	return retval;
    731 }
    732 
    733 
    734 DLLEXPORT unsigned long DLLCALL tjPlaneSizeYUV(int componentID, int width,
    735 	int stride, int height, int subsamp)
    736 {
    737 	unsigned long retval=0;
    738 	int pw, ph;
    739 
    740 	if(width<1 || height<1 || subsamp<0 || subsamp>=NUMSUBOPT)
    741 		_throw("tjPlaneSizeYUV(): Invalid argument");
    742 
    743 	pw=tjPlaneWidth(componentID, width, subsamp);
    744 	ph=tjPlaneHeight(componentID, height, subsamp);
    745 	if(pw<0 || ph<0) return -1;
    746 
    747 	if(stride==0) stride=pw;
    748 	else stride=abs(stride);
    749 
    750 	retval=stride*(ph-1)+pw;
    751 
    752 	bailout:
    753 	return retval;
    754 }
    755 
    756 
    757 DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, const unsigned char *srcBuf,
    758 	int width, int pitch, int height, int pixelFormat, unsigned char **jpegBuf,
    759 	unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
    760 {
    761 	int i, retval=0, alloc=1;  JSAMPROW *row_pointer=NULL;
    762 	#ifndef JCS_EXTENSIONS
    763 	unsigned char *rgbBuf=NULL;
    764 	#endif
    765 
    766 	getcinstance(handle)
    767 	if((this->init&COMPRESS)==0)
    768 		_throw("tjCompress2(): Instance has not been initialized for compression");
    769 
    770 	if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
    771 		|| pixelFormat>=TJ_NUMPF || jpegBuf==NULL || jpegSize==NULL
    772 		|| jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT || jpegQual<0 || jpegQual>100)
    773 		_throw("tjCompress2(): Invalid argument");
    774 
    775 	if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
    776 
    777 	#ifndef JCS_EXTENSIONS
    778 	if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK)
    779 	{
    780 		rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
    781 		if(!rgbBuf) _throw("tjCompress2(): Memory allocation failure");
    782 		srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
    783 		pitch=width*RGB_PIXELSIZE;
    784 	}
    785 	#endif
    786 
    787 	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
    788 		_throw("tjCompress2(): Memory allocation failure");
    789 
    790 	if(setjmp(this->jerr.setjmp_buffer))
    791 	{
    792 		/* If we get here, the JPEG code has signaled an error. */
    793 		retval=-1;  goto bailout;
    794 	}
    795 
    796 	cinfo->image_width=width;
    797 	cinfo->image_height=height;
    798 
    799 	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
    800 	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
    801 	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
    802 
    803 	if(flags&TJFLAG_NOREALLOC)
    804 	{
    805 		alloc=0;  *jpegSize=tjBufSize(width, height, jpegSubsamp);
    806 	}
    807 	jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
    808 	if(setCompDefaults(cinfo, pixelFormat, jpegSubsamp, jpegQual, flags)==-1)
    809 		return -1;
    810 
    811 	jpeg_start_compress(cinfo, TRUE);
    812 	for(i=0; i<height; i++)
    813 	{
    814 		if(flags&TJFLAG_BOTTOMUP)
    815 			row_pointer[i]=(JSAMPROW)&srcBuf[(height-i-1)*pitch];
    816 		else row_pointer[i]=(JSAMPROW)&srcBuf[i*pitch];
    817 	}
    818 	while(cinfo->next_scanline<cinfo->image_height)
    819 	{
    820 		jpeg_write_scanlines(cinfo, &row_pointer[cinfo->next_scanline],
    821 			cinfo->image_height-cinfo->next_scanline);
    822 	}
    823 	jpeg_finish_compress(cinfo);
    824 
    825 	bailout:
    826 	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
    827 	#ifndef JCS_EXTENSIONS
    828 	if(rgbBuf) free(rgbBuf);
    829 	#endif
    830 	if(row_pointer) free(row_pointer);
    831 	if(this->jerr.warning) retval=-1;
    832 	return retval;
    833 }
    834 
    835 DLLEXPORT int DLLCALL tjCompress(tjhandle handle, unsigned char *srcBuf,
    836 	int width, int pitch, int height, int pixelSize, unsigned char *jpegBuf,
    837 	unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
    838 {
    839 	int retval=0;  unsigned long size;
    840 	if(flags&TJ_YUV)
    841 	{
    842 		size=tjBufSizeYUV(width, height, jpegSubsamp);
    843 		retval=tjEncodeYUV2(handle, srcBuf, width, pitch, height,
    844 			getPixelFormat(pixelSize, flags), jpegBuf, jpegSubsamp, flags);
    845 	}
    846 	else
    847 	{
    848 		retval=tjCompress2(handle, srcBuf, width, pitch, height,
    849 			getPixelFormat(pixelSize, flags), &jpegBuf, &size, jpegSubsamp, jpegQual,
    850 			flags|TJFLAG_NOREALLOC);
    851 	}
    852 	*jpegSize=size;
    853 	return retval;
    854 }
    855 
    856 
    857 DLLEXPORT int DLLCALL tjEncodeYUVPlanes(tjhandle handle,
    858 	const unsigned char *srcBuf, int width, int pitch, int height,
    859 	int pixelFormat, unsigned char **dstPlanes, int *strides, int subsamp,
    860 	int flags)
    861 {
    862 	int i, retval=0;  JSAMPROW *row_pointer=NULL;
    863 	JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS];
    864 	JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
    865 	JSAMPROW *outbuf[MAX_COMPONENTS];
    866 	int row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS];
    867 	JSAMPLE *ptr;
    868 	jpeg_component_info *compptr;
    869 	#ifndef JCS_EXTENSIONS
    870 	unsigned char *rgbBuf=NULL;
    871 	#endif
    872 
    873 	getcinstance(handle);
    874 
    875 	for(i=0; i<MAX_COMPONENTS; i++)
    876 	{
    877 		tmpbuf[i]=NULL;  _tmpbuf[i]=NULL;
    878 		tmpbuf2[i]=NULL;  _tmpbuf2[i]=NULL;  outbuf[i]=NULL;
    879 	}
    880 
    881 	if((this->init&COMPRESS)==0)
    882 		_throw("tjEncodeYUVPlanes(): Instance has not been initialized for compression");
    883 
    884 	if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
    885 		|| pixelFormat>=TJ_NUMPF || !dstPlanes || !dstPlanes[0] || subsamp<0
    886 		|| subsamp>=NUMSUBOPT)
    887 		_throw("tjEncodeYUVPlanes(): Invalid argument");
    888 	if(subsamp!=TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2]))
    889 		_throw("tjEncodeYUVPlanes(): Invalid argument");
    890 
    891 	if(pixelFormat==TJPF_CMYK)
    892 		_throw("tjEncodeYUVPlanes(): Cannot generate YUV images from CMYK pixels");
    893 
    894 	if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
    895 
    896 	#ifndef JCS_EXTENSIONS
    897 	if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK)
    898 	{
    899 		rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
    900 		if(!rgbBuf) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
    901 		srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
    902 		pitch=width*RGB_PIXELSIZE;
    903 	}
    904 	#endif
    905 
    906 	if(setjmp(this->jerr.setjmp_buffer))
    907 	{
    908 		/* If we get here, the JPEG code has signaled an error. */
    909 		retval=-1;  goto bailout;
    910 	}
    911 
    912 	cinfo->image_width=width;
    913 	cinfo->image_height=height;
    914 
    915 	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
    916 	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
    917 	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
    918 
    919 	if(setCompDefaults(cinfo, pixelFormat, subsamp, -1, flags)==-1) return -1;
    920 
    921 	/* Execute only the parts of jpeg_start_compress() that we need.  If we
    922 	   were to call the whole jpeg_start_compress() function, then it would try
    923 	   to write the file headers, which could overflow the output buffer if the
    924 	   YUV image were very small. */
    925 	if(cinfo->global_state!=CSTATE_START)
    926 		_throw("tjEncodeYUVPlanes(): libjpeg API is in the wrong state");
    927 	(*cinfo->err->reset_error_mgr)((j_common_ptr)cinfo);
    928 	jinit_c_master_control(cinfo, FALSE);
    929 	jinit_color_converter(cinfo);
    930 	jinit_downsampler(cinfo);
    931 	(*cinfo->cconvert->start_pass)(cinfo);
    932 
    933 	pw0=PAD(width, cinfo->max_h_samp_factor);
    934 	ph0=PAD(height, cinfo->max_v_samp_factor);
    935 
    936 	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL)
    937 		_throw("tjEncodeYUVPlanes(): Memory allocation failure");
    938 	for(i=0; i<height; i++)
    939 	{
    940 		if(flags&TJFLAG_BOTTOMUP)
    941 			row_pointer[i]=(JSAMPROW)&srcBuf[(height-i-1)*pitch];
    942 		else row_pointer[i]=(JSAMPROW)&srcBuf[i*pitch];
    943 	}
    944 	if(height<ph0)
    945 		for(i=height; i<ph0; i++) row_pointer[i]=row_pointer[height-1];
    946 
    947 	for(i=0; i<cinfo->num_components; i++)
    948 	{
    949 		compptr=&cinfo->comp_info[i];
    950 		_tmpbuf[i]=(JSAMPLE *)malloc(
    951 			PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
    952 				/compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
    953 		if(!_tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
    954 		tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
    955 		if(!tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
    956 		for(row=0; row<cinfo->max_v_samp_factor; row++)
    957 		{
    958 			unsigned char *_tmpbuf_aligned=
    959 				(unsigned char *)PAD((size_t)_tmpbuf[i], 16);
    960 			tmpbuf[i][row]=&_tmpbuf_aligned[
    961 				PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
    962 					/compptr->h_samp_factor, 16) * row];
    963 		}
    964 		_tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
    965 			* compptr->v_samp_factor + 16);
    966 		if(!_tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
    967 		tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
    968 		if(!tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
    969 		for(row=0; row<compptr->v_samp_factor; row++)
    970 		{
    971 			unsigned char *_tmpbuf2_aligned=
    972 				(unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
    973 			tmpbuf2[i][row]=&_tmpbuf2_aligned[
    974 				PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
    975 		}
    976 		pw[i]=pw0*compptr->h_samp_factor/cinfo->max_h_samp_factor;
    977 		ph[i]=ph0*compptr->v_samp_factor/cinfo->max_v_samp_factor;
    978 		outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]);
    979 		if(!outbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
    980 		ptr=dstPlanes[i];
    981 		for(row=0; row<ph[i]; row++)
    982 		{
    983 			outbuf[i][row]=ptr;
    984 			ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
    985 		}
    986 	}
    987 
    988 	if(setjmp(this->jerr.setjmp_buffer))
    989 	{
    990 		/* If we get here, the JPEG code has signaled an error. */
    991 		retval=-1;  goto bailout;
    992 	}
    993 
    994 	for(row=0; row<ph0; row+=cinfo->max_v_samp_factor)
    995 	{
    996 		(*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0,
    997 			cinfo->max_v_samp_factor);
    998 		(cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
    999 		for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++)
   1000 			jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
   1001 				row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
   1002 				compptr->v_samp_factor, pw[i]);
   1003 	}
   1004 	cinfo->next_scanline+=height;
   1005 	jpeg_abort_compress(cinfo);
   1006 
   1007 	bailout:
   1008 	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
   1009 	#ifndef JCS_EXTENSIONS
   1010 	if(rgbBuf) free(rgbBuf);
   1011 	#endif
   1012 	if(row_pointer) free(row_pointer);
   1013 	for(i=0; i<MAX_COMPONENTS; i++)
   1014 	{
   1015 		if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
   1016 		if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
   1017 		if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
   1018 		if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
   1019 		if(outbuf[i]!=NULL) free(outbuf[i]);
   1020 	}
   1021 	if(this->jerr.warning) retval=-1;
   1022 	return retval;
   1023 }
   1024 
   1025 DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle,
   1026 	const unsigned char *srcBuf, int width, int pitch, int height,
   1027 	int pixelFormat, unsigned char *dstBuf, int pad, int subsamp, int flags)
   1028 {
   1029 	unsigned char *dstPlanes[3];
   1030 	int pw0, ph0, strides[3], retval=-1;
   1031 
   1032 	if(width<=0 || height<=0 || dstBuf==NULL || pad<0 || !isPow2(pad)
   1033 		|| subsamp<0 || subsamp>=NUMSUBOPT)
   1034 		_throw("tjEncodeYUV3(): Invalid argument");
   1035 
   1036 	pw0=tjPlaneWidth(0, width, subsamp);
   1037 	ph0=tjPlaneHeight(0, height, subsamp);
   1038 	dstPlanes[0]=dstBuf;
   1039 	strides[0]=PAD(pw0, pad);
   1040 	if(subsamp==TJSAMP_GRAY)
   1041 	{
   1042 		strides[1]=strides[2]=0;
   1043 		dstPlanes[1]=dstPlanes[2]=NULL;
   1044 	}
   1045 	else
   1046 	{
   1047 		int pw1=tjPlaneWidth(1, width, subsamp);
   1048 		int ph1=tjPlaneHeight(1, height, subsamp);
   1049 		strides[1]=strides[2]=PAD(pw1, pad);
   1050 		dstPlanes[1]=dstPlanes[0]+strides[0]*ph0;
   1051 		dstPlanes[2]=dstPlanes[1]+strides[1]*ph1;
   1052 	}
   1053 
   1054 	return tjEncodeYUVPlanes(handle, srcBuf, width, pitch, height, pixelFormat,
   1055 		dstPlanes, strides, subsamp, flags);
   1056 
   1057 	bailout:
   1058 	return retval;
   1059 }
   1060 
   1061 DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
   1062 	int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
   1063 	int subsamp, int flags)
   1064 {
   1065 	return tjEncodeYUV3(handle, srcBuf, width, pitch, height, pixelFormat,
   1066 		dstBuf, 4, subsamp, flags);
   1067 }
   1068 
   1069 DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf,
   1070 	int width, int pitch, int height, int pixelSize, unsigned char *dstBuf,
   1071 	int subsamp, int flags)
   1072 {
   1073 	return tjEncodeYUV2(handle, srcBuf, width, pitch, height,
   1074 		getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags);
   1075 }
   1076 
   1077 
   1078 DLLEXPORT int DLLCALL tjCompressFromYUVPlanes(tjhandle handle,
   1079 	const unsigned char **srcPlanes, int width, const int *strides, int height,
   1080 	int subsamp, unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual,
   1081 	int flags)
   1082 {
   1083 	int i, row, retval=0, alloc=1;  JSAMPROW *inbuf[MAX_COMPONENTS];
   1084 	int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS],
   1085 		tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
   1086 	JSAMPLE *_tmpbuf=NULL, *ptr;  JSAMPROW *tmpbuf[MAX_COMPONENTS];
   1087 
   1088 	getcinstance(handle)
   1089 
   1090 	for(i=0; i<MAX_COMPONENTS; i++)
   1091 	{
   1092 		tmpbuf[i]=NULL;  inbuf[i]=NULL;
   1093 	}
   1094 
   1095 	if((this->init&COMPRESS)==0)
   1096 		_throw("tjCompressFromYUVPlanes(): Instance has not been initialized for compression");
   1097 
   1098 	if(!srcPlanes || !srcPlanes[0] || width<=0 || height<=0 || subsamp<0
   1099 		|| subsamp>=NUMSUBOPT || jpegBuf==NULL || jpegSize==NULL || jpegQual<0
   1100 		|| jpegQual>100)
   1101 		_throw("tjCompressFromYUVPlanes(): Invalid argument");
   1102 	if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2]))
   1103 		_throw("tjCompressFromYUVPlanes(): Invalid argument");
   1104 
   1105 	if(setjmp(this->jerr.setjmp_buffer))
   1106 	{
   1107 		/* If we get here, the JPEG code has signaled an error. */
   1108 		retval=-1;  goto bailout;
   1109 	}
   1110 
   1111 	cinfo->image_width=width;
   1112 	cinfo->image_height=height;
   1113 
   1114 	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
   1115 	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
   1116 	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
   1117 
   1118 	if(flags&TJFLAG_NOREALLOC)
   1119 	{
   1120 		alloc=0;  *jpegSize=tjBufSize(width, height, subsamp);
   1121 	}
   1122 	jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
   1123 	if(setCompDefaults(cinfo, TJPF_RGB, subsamp, jpegQual, flags)==-1)
   1124 		return -1;
   1125 	cinfo->raw_data_in=TRUE;
   1126 
   1127 	jpeg_start_compress(cinfo, TRUE);
   1128 	for(i=0; i<cinfo->num_components; i++)
   1129 	{
   1130 		jpeg_component_info *compptr=&cinfo->comp_info[i];
   1131 		int ih;
   1132 		iw[i]=compptr->width_in_blocks*DCTSIZE;
   1133 		ih=compptr->height_in_blocks*DCTSIZE;
   1134 		pw[i]=PAD(cinfo->image_width, cinfo->max_h_samp_factor)
   1135 			*compptr->h_samp_factor/cinfo->max_h_samp_factor;
   1136 		ph[i]=PAD(cinfo->image_height, cinfo->max_v_samp_factor)
   1137 			*compptr->v_samp_factor/cinfo->max_v_samp_factor;
   1138 		if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1;
   1139 		th[i]=compptr->v_samp_factor*DCTSIZE;
   1140 		tmpbufsize+=iw[i]*th[i];
   1141 		if((inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]))==NULL)
   1142 			_throw("tjCompressFromYUVPlanes(): Memory allocation failure");
   1143 		ptr=(JSAMPLE *)srcPlanes[i];
   1144 		for(row=0; row<ph[i]; row++)
   1145 		{
   1146 			inbuf[i][row]=ptr;
   1147 			ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
   1148 		}
   1149 	}
   1150 	if(usetmpbuf)
   1151 	{
   1152 		if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
   1153 			_throw("tjCompressFromYUVPlanes(): Memory allocation failure");
   1154 		ptr=_tmpbuf;
   1155 		for(i=0; i<cinfo->num_components; i++)
   1156 		{
   1157 			if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
   1158 				_throw("tjCompressFromYUVPlanes(): Memory allocation failure");
   1159 			for(row=0; row<th[i]; row++)
   1160 			{
   1161 				tmpbuf[i][row]=ptr;
   1162 				ptr+=iw[i];
   1163 			}
   1164 		}
   1165 	}
   1166 
   1167 	if(setjmp(this->jerr.setjmp_buffer))
   1168 	{
   1169 		/* If we get here, the JPEG code has signaled an error. */
   1170 		retval=-1;  goto bailout;
   1171 	}
   1172 
   1173 	for(row=0; row<(int)cinfo->image_height;
   1174 		row+=cinfo->max_v_samp_factor*DCTSIZE)
   1175 	{
   1176 		JSAMPARRAY yuvptr[MAX_COMPONENTS];
   1177 		int crow[MAX_COMPONENTS];
   1178 		for(i=0; i<cinfo->num_components; i++)
   1179 		{
   1180 			jpeg_component_info *compptr=&cinfo->comp_info[i];
   1181 			crow[i]=row*compptr->v_samp_factor/cinfo->max_v_samp_factor;
   1182 			if(usetmpbuf)
   1183 			{
   1184 				int j, k;
   1185 				for(j=0; j<min(th[i], ph[i]-crow[i]); j++)
   1186 				{
   1187 					memcpy(tmpbuf[i][j], inbuf[i][crow[i]+j], pw[i]);
   1188 					/* Duplicate last sample in row to fill out MCU */
   1189 					for(k=pw[i]; k<iw[i]; k++) tmpbuf[i][j][k]=tmpbuf[i][j][pw[i]-1];
   1190 				}
   1191 				/* Duplicate last row to fill out MCU */
   1192 				for(j=ph[i]-crow[i]; j<th[i]; j++)
   1193 					memcpy(tmpbuf[i][j], tmpbuf[i][ph[i]-crow[i]-1], iw[i]);
   1194 				yuvptr[i]=tmpbuf[i];
   1195 			}
   1196 			else
   1197 				yuvptr[i]=&inbuf[i][crow[i]];
   1198 		}
   1199 		jpeg_write_raw_data(cinfo, yuvptr, cinfo->max_v_samp_factor*DCTSIZE);
   1200 	}
   1201 	jpeg_finish_compress(cinfo);
   1202 
   1203 	bailout:
   1204 	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
   1205 	for(i=0; i<MAX_COMPONENTS; i++)
   1206 	{
   1207 		if(tmpbuf[i]) free(tmpbuf[i]);
   1208 		if(inbuf[i]) free(inbuf[i]);
   1209 	}
   1210 	if(_tmpbuf) free(_tmpbuf);
   1211 	if(this->jerr.warning) retval=-1;
   1212 	return retval;
   1213 }
   1214 
   1215 DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle,
   1216 	const unsigned char *srcBuf, int width, int pad, int height, int subsamp,
   1217 	unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual, int flags)
   1218 {
   1219 	const unsigned char *srcPlanes[3];
   1220 	int pw0, ph0, strides[3], retval=-1;
   1221 
   1222 	if(srcBuf==NULL || width<=0 || pad<1 || height<=0 || subsamp<0
   1223 		|| subsamp>=NUMSUBOPT)
   1224 		_throw("tjCompressFromYUV(): Invalid argument");
   1225 
   1226 	pw0=tjPlaneWidth(0, width, subsamp);
   1227 	ph0=tjPlaneHeight(0, height, subsamp);
   1228 	srcPlanes[0]=srcBuf;
   1229 	strides[0]=PAD(pw0, pad);
   1230 	if(subsamp==TJSAMP_GRAY)
   1231 	{
   1232 		strides[1]=strides[2]=0;
   1233 		srcPlanes[1]=srcPlanes[2]=NULL;
   1234 	}
   1235 	else
   1236 	{
   1237 		int pw1=tjPlaneWidth(1, width, subsamp);
   1238 		int ph1=tjPlaneHeight(1, height, subsamp);
   1239 		strides[1]=strides[2]=PAD(pw1, pad);
   1240 		srcPlanes[1]=srcPlanes[0]+strides[0]*ph0;
   1241 		srcPlanes[2]=srcPlanes[1]+strides[1]*ph1;
   1242 	}
   1243 
   1244 	return tjCompressFromYUVPlanes(handle, srcPlanes, width, strides, height,
   1245 		subsamp, jpegBuf, jpegSize, jpegQual, flags);
   1246 
   1247 	bailout:
   1248 	return retval;
   1249 }
   1250 
   1251 
   1252 /* Decompressor */
   1253 
   1254 static tjhandle _tjInitDecompress(tjinstance *this)
   1255 {
   1256 	static unsigned char buffer[1];
   1257 
   1258 	/* This is also straight out of example.c */
   1259 	this->dinfo.err=jpeg_std_error(&this->jerr.pub);
   1260 	this->jerr.pub.error_exit=my_error_exit;
   1261 	this->jerr.pub.output_message=my_output_message;
   1262 	this->jerr.emit_message=this->jerr.pub.emit_message;
   1263 	this->jerr.pub.emit_message=my_emit_message;
   1264 
   1265 	if(setjmp(this->jerr.setjmp_buffer))
   1266 	{
   1267 		/* If we get here, the JPEG code has signaled an error. */
   1268 		if(this) free(this);
   1269 		return NULL;
   1270 	}
   1271 
   1272 	jpeg_create_decompress(&this->dinfo);
   1273 	/* Make an initial call so it will create the source manager */
   1274 	jpeg_mem_src_tj(&this->dinfo, buffer, 1);
   1275 
   1276 	this->init|=DECOMPRESS;
   1277 	return (tjhandle)this;
   1278 }
   1279 
   1280 DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
   1281 {
   1282 	tjinstance *this;
   1283 	if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
   1284 	{
   1285 		snprintf(errStr, JMSG_LENGTH_MAX,
   1286 			"tjInitDecompress(): Memory allocation failure");
   1287 		return NULL;
   1288 	}
   1289 	MEMZERO(this, sizeof(tjinstance));
   1290 	return _tjInitDecompress(this);
   1291 }
   1292 
   1293 
   1294 DLLEXPORT int DLLCALL tjDecompressHeader3(tjhandle handle,
   1295 	const unsigned char *jpegBuf, unsigned long jpegSize, int *width,
   1296 	int *height, int *jpegSubsamp, int *jpegColorspace)
   1297 {
   1298 	int retval=0;
   1299 
   1300 	getdinstance(handle);
   1301 	if((this->init&DECOMPRESS)==0)
   1302 		_throw("tjDecompressHeader3(): Instance has not been initialized for decompression");
   1303 
   1304 	if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL
   1305 		|| jpegSubsamp==NULL || jpegColorspace==NULL)
   1306 		_throw("tjDecompressHeader3(): Invalid argument");
   1307 
   1308 	if(setjmp(this->jerr.setjmp_buffer))
   1309 	{
   1310 		/* If we get here, the JPEG code has signaled an error. */
   1311 		return -1;
   1312 	}
   1313 
   1314 	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
   1315 	jpeg_read_header(dinfo, TRUE);
   1316 
   1317 	*width=dinfo->image_width;
   1318 	*height=dinfo->image_height;
   1319 	*jpegSubsamp=getSubsamp(dinfo);
   1320 	switch(dinfo->jpeg_color_space)
   1321 	{
   1322 		case JCS_GRAYSCALE:  *jpegColorspace=TJCS_GRAY;  break;
   1323 		case JCS_RGB:        *jpegColorspace=TJCS_RGB;  break;
   1324 		case JCS_YCbCr:      *jpegColorspace=TJCS_YCbCr;  break;
   1325 		case JCS_CMYK:       *jpegColorspace=TJCS_CMYK;  break;
   1326 		case JCS_YCCK:       *jpegColorspace=TJCS_YCCK;  break;
   1327 		default:             *jpegColorspace=-1;  break;
   1328 	}
   1329 
   1330 	jpeg_abort_decompress(dinfo);
   1331 
   1332 	if(*jpegSubsamp<0)
   1333 		_throw("tjDecompressHeader3(): Could not determine subsampling type for JPEG image");
   1334 	if(*jpegColorspace<0)
   1335 		_throw("tjDecompressHeader3(): Could not determine colorspace of JPEG image");
   1336 	if(*width<1 || *height<1)
   1337 		_throw("tjDecompressHeader3(): Invalid data returned in header");
   1338 
   1339 	bailout:
   1340 	if(this->jerr.warning) retval=-1;
   1341 	return retval;
   1342 }
   1343 
   1344 DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle,
   1345 	unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
   1346 	int *jpegSubsamp)
   1347 {
   1348 	int jpegColorspace;
   1349 	return tjDecompressHeader3(handle, jpegBuf, jpegSize, width, height,
   1350 		jpegSubsamp, &jpegColorspace);
   1351 }
   1352 
   1353 DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle,
   1354 	unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height)
   1355 {
   1356 	int jpegSubsamp;
   1357 	return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height,
   1358 		&jpegSubsamp);
   1359 }
   1360 
   1361 
   1362 DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors)
   1363 {
   1364 	if(numscalingfactors==NULL)
   1365 	{
   1366 		snprintf(errStr, JMSG_LENGTH_MAX,
   1367 			"tjGetScalingFactors(): Invalid argument");
   1368 		return NULL;
   1369 	}
   1370 
   1371 	*numscalingfactors=NUMSF;
   1372 	return (tjscalingfactor *)sf;
   1373 }
   1374 
   1375 
   1376 DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle,
   1377 	const unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
   1378 	int width, int pitch, int height, int pixelFormat, int flags)
   1379 {
   1380 	int i, retval=0;  JSAMPROW *row_pointer=NULL;
   1381 	int jpegwidth, jpegheight, scaledw, scaledh;
   1382 	#ifndef JCS_EXTENSIONS
   1383 	unsigned char *rgbBuf=NULL;
   1384 	unsigned char *_dstBuf=NULL;  int _pitch=0;
   1385 	#endif
   1386 
   1387 	getdinstance(handle);
   1388 	if((this->init&DECOMPRESS)==0)
   1389 		_throw("tjDecompress2(): Instance has not been initialized for decompression");
   1390 
   1391 	if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0
   1392 		|| height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF)
   1393 		_throw("tjDecompress2(): Invalid argument");
   1394 
   1395 	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
   1396 	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
   1397 	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
   1398 
   1399 	if(setjmp(this->jerr.setjmp_buffer))
   1400 	{
   1401 		/* If we get here, the JPEG code has signaled an error. */
   1402 		retval=-1;  goto bailout;
   1403 	}
   1404 
   1405 	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
   1406 	jpeg_read_header(dinfo, TRUE);
   1407 	if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
   1408 	{
   1409 		retval=-1;  goto bailout;
   1410 	}
   1411 
   1412 	if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
   1413 
   1414 	jpegwidth=dinfo->image_width;  jpegheight=dinfo->image_height;
   1415 	if(width==0) width=jpegwidth;
   1416 	if(height==0) height=jpegheight;
   1417 	for(i=0; i<NUMSF; i++)
   1418 	{
   1419 		scaledw=TJSCALED(jpegwidth, sf[i]);
   1420 		scaledh=TJSCALED(jpegheight, sf[i]);
   1421 		if(scaledw<=width && scaledh<=height)
   1422 			break;
   1423 	}
   1424 	if(i>=NUMSF)
   1425 		_throw("tjDecompress2(): Could not scale down to desired image dimensions");
   1426 	width=scaledw;  height=scaledh;
   1427 	dinfo->scale_num=sf[i].num;
   1428 	dinfo->scale_denom=sf[i].denom;
   1429 
   1430 	jpeg_start_decompress(dinfo);
   1431 	if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
   1432 
   1433 	#ifndef JCS_EXTENSIONS
   1434 	if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK &&
   1435 		(RGB_RED!=tjRedOffset[pixelFormat] ||
   1436 			RGB_GREEN!=tjGreenOffset[pixelFormat] ||
   1437 			RGB_BLUE!=tjBlueOffset[pixelFormat] ||
   1438 			RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
   1439 	{
   1440 		rgbBuf=(unsigned char *)malloc(width*height*3);
   1441 		if(!rgbBuf) _throw("tjDecompress2(): Memory allocation failure");
   1442 		_pitch=pitch;  pitch=width*3;
   1443 		_dstBuf=dstBuf;  dstBuf=rgbBuf;
   1444 	}
   1445 	#endif
   1446 
   1447 	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
   1448 		*dinfo->output_height))==NULL)
   1449 		_throw("tjDecompress2(): Memory allocation failure");
   1450 	if(setjmp(this->jerr.setjmp_buffer))
   1451 	{
   1452 		/* If we get here, the JPEG code has signaled an error. */
   1453 		retval=-1;  goto bailout;
   1454 	}
   1455 	for(i=0; i<(int)dinfo->output_height; i++)
   1456 	{
   1457 		if(flags&TJFLAG_BOTTOMUP)
   1458 			row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*pitch];
   1459 		else row_pointer[i]=&dstBuf[i*pitch];
   1460 	}
   1461 	while(dinfo->output_scanline<dinfo->output_height)
   1462 	{
   1463 		jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline],
   1464 			dinfo->output_height-dinfo->output_scanline);
   1465 	}
   1466 	jpeg_finish_decompress(dinfo);
   1467 
   1468 	#ifndef JCS_EXTENSIONS
   1469 	fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
   1470 	#endif
   1471 
   1472 	bailout:
   1473 	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
   1474 	#ifndef JCS_EXTENSIONS
   1475 	if(rgbBuf) free(rgbBuf);
   1476 	#endif
   1477 	if(row_pointer) free(row_pointer);
   1478 	if(this->jerr.warning) retval=-1;
   1479 	return retval;
   1480 }
   1481 
   1482 DLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf,
   1483 	unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
   1484 	int height, int pixelSize, int flags)
   1485 {
   1486 	if(flags&TJ_YUV)
   1487 		return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags);
   1488 	else
   1489 		return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch,
   1490 			height, getPixelFormat(pixelSize, flags), flags);
   1491 }
   1492 
   1493 
   1494 static int setDecodeDefaults(struct jpeg_decompress_struct *dinfo,
   1495 	int pixelFormat, int subsamp, int flags)
   1496 {
   1497 	int i;
   1498 
   1499 	dinfo->scale_num=dinfo->scale_denom=1;
   1500 
   1501 	if(subsamp==TJSAMP_GRAY)
   1502 	{
   1503 		dinfo->num_components=dinfo->comps_in_scan=1;
   1504 		dinfo->jpeg_color_space=JCS_GRAYSCALE;
   1505 	}
   1506 	else
   1507 	{
   1508 		dinfo->num_components=dinfo->comps_in_scan=3;
   1509 		dinfo->jpeg_color_space=JCS_YCbCr;
   1510 	}
   1511 
   1512 	dinfo->comp_info=(jpeg_component_info *)
   1513 		(*dinfo->mem->alloc_small)((j_common_ptr)dinfo, JPOOL_IMAGE,
   1514 			dinfo->num_components*sizeof(jpeg_component_info));
   1515 
   1516 	for(i=0; i<dinfo->num_components; i++)
   1517 	{
   1518 		jpeg_component_info *compptr=&dinfo->comp_info[i];
   1519 		compptr->h_samp_factor=(i==0)? tjMCUWidth[subsamp]/8:1;
   1520 		compptr->v_samp_factor=(i==0)? tjMCUHeight[subsamp]/8:1;
   1521 		compptr->component_index=i;
   1522 		compptr->component_id=i+1;
   1523 		compptr->quant_tbl_no=compptr->dc_tbl_no=compptr->ac_tbl_no=
   1524 			(i==0)? 0:1;
   1525 		dinfo->cur_comp_info[i]=compptr;
   1526 	}
   1527 	dinfo->data_precision=8;
   1528 	for(i=0; i<2; i++)
   1529 	{
   1530 		if(dinfo->quant_tbl_ptrs[i]==NULL)
   1531 			dinfo->quant_tbl_ptrs[i]=jpeg_alloc_quant_table((j_common_ptr)dinfo);
   1532 	}
   1533 
   1534 	return 0;
   1535 }
   1536 
   1537 
   1538 int my_read_markers(j_decompress_ptr dinfo)
   1539 {
   1540 	return JPEG_REACHED_SOS;
   1541 }
   1542 
   1543 void my_reset_marker_reader(j_decompress_ptr dinfo)
   1544 {
   1545 }
   1546 
   1547 DLLEXPORT int DLLCALL tjDecodeYUVPlanes(tjhandle handle,
   1548 	const unsigned char **srcPlanes, const int *strides, int subsamp,
   1549 	unsigned char *dstBuf, int width, int pitch, int height, int pixelFormat,
   1550 	int flags)
   1551 {
   1552 	int i, retval=0;  JSAMPROW *row_pointer=NULL;
   1553 	JSAMPLE *_tmpbuf[MAX_COMPONENTS];
   1554 	JSAMPROW *tmpbuf[MAX_COMPONENTS], *inbuf[MAX_COMPONENTS];
   1555 	int row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS];
   1556 	JSAMPLE *ptr;
   1557 	jpeg_component_info *compptr;
   1558 	#ifndef JCS_EXTENSIONS
   1559 	unsigned char *rgbBuf=NULL;
   1560 	unsigned char *_dstBuf=NULL;  int _pitch=0;
   1561 	#endif
   1562 	int (*old_read_markers)(j_decompress_ptr);
   1563 	void (*old_reset_marker_reader)(j_decompress_ptr);
   1564 
   1565 	getdinstance(handle);
   1566 
   1567 	for(i=0; i<MAX_COMPONENTS; i++)
   1568 	{
   1569 		tmpbuf[i]=NULL;  _tmpbuf[i]=NULL;  inbuf[i]=NULL;
   1570 	}
   1571 
   1572 	if((this->init&DECOMPRESS)==0)
   1573 		_throw("tjDecodeYUVPlanes(): Instance has not been initialized for decompression");
   1574 
   1575 	if(!srcPlanes || !srcPlanes[0] || subsamp<0 || subsamp>=NUMSUBOPT
   1576 		|| dstBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
   1577 		|| pixelFormat>=TJ_NUMPF)
   1578 		_throw("tjDecodeYUVPlanes(): Invalid argument");
   1579 	if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2]))
   1580 		_throw("tjDecodeYUVPlanes(): Invalid argument");
   1581 
   1582 	if(setjmp(this->jerr.setjmp_buffer))
   1583 	{
   1584 		/* If we get here, the JPEG code has signaled an error. */
   1585 		retval=-1;  goto bailout;
   1586 	}
   1587 
   1588 	if(pixelFormat==TJPF_CMYK)
   1589 		_throw("tjDecodeYUVPlanes(): Cannot decode YUV images into CMYK pixels.");
   1590 
   1591 	if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
   1592 	dinfo->image_width=width;
   1593 	dinfo->image_height=height;
   1594 
   1595 	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
   1596 	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
   1597 	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
   1598 
   1599 	if(setDecodeDefaults(dinfo, pixelFormat, subsamp, flags)==-1)
   1600 	{
   1601 		retval=-1;  goto bailout;
   1602 	}
   1603 	old_read_markers=dinfo->marker->read_markers;
   1604 	dinfo->marker->read_markers=my_read_markers;
   1605 	old_reset_marker_reader=dinfo->marker->reset_marker_reader;
   1606 	dinfo->marker->reset_marker_reader=my_reset_marker_reader;
   1607 	jpeg_read_header(dinfo, TRUE);
   1608 	dinfo->marker->read_markers=old_read_markers;
   1609 	dinfo->marker->reset_marker_reader=old_reset_marker_reader;
   1610 
   1611 	if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
   1612 	{
   1613 		retval=-1;  goto bailout;
   1614 	}
   1615 	dinfo->do_fancy_upsampling=FALSE;
   1616 	dinfo->Se=DCTSIZE2-1;
   1617 	jinit_master_decompress(dinfo);
   1618 	(*dinfo->upsample->start_pass)(dinfo);
   1619 
   1620 	pw0=PAD(width, dinfo->max_h_samp_factor);
   1621 	ph0=PAD(height, dinfo->max_v_samp_factor);
   1622 
   1623 	if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
   1624 
   1625 	#ifndef JCS_EXTENSIONS
   1626 	if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK &&
   1627 		(RGB_RED!=tjRedOffset[pixelFormat] ||
   1628 			RGB_GREEN!=tjGreenOffset[pixelFormat] ||
   1629 			RGB_BLUE!=tjBlueOffset[pixelFormat] ||
   1630 			RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
   1631 	{
   1632 		rgbBuf=(unsigned char *)malloc(width*height*3);
   1633 		if(!rgbBuf) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
   1634 		_pitch=pitch;  pitch=width*3;
   1635 		_dstBuf=dstBuf;  dstBuf=rgbBuf;
   1636 	}
   1637 	#endif
   1638 
   1639 	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL)
   1640 		_throw("tjDecodeYUVPlanes(): Memory allocation failure");
   1641 	for(i=0; i<height; i++)
   1642 	{
   1643 		if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&dstBuf[(height-i-1)*pitch];
   1644 		else row_pointer[i]=&dstBuf[i*pitch];
   1645 	}
   1646 	if(height<ph0)
   1647 		for(i=height; i<ph0; i++) row_pointer[i]=row_pointer[height-1];
   1648 
   1649 	for(i=0; i<dinfo->num_components; i++)
   1650 	{
   1651 		compptr=&dinfo->comp_info[i];
   1652 		_tmpbuf[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
   1653 			* compptr->v_samp_factor + 16);
   1654 		if(!_tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
   1655 		tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
   1656 		if(!tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
   1657 		for(row=0; row<compptr->v_samp_factor; row++)
   1658 		{
   1659 			unsigned char *_tmpbuf_aligned=
   1660 				(unsigned char *)PAD((size_t)_tmpbuf[i], 16);
   1661 			tmpbuf[i][row]=&_tmpbuf_aligned[
   1662 				PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
   1663 		}
   1664 		pw[i]=pw0*compptr->h_samp_factor/dinfo->max_h_samp_factor;
   1665 		ph[i]=ph0*compptr->v_samp_factor/dinfo->max_v_samp_factor;
   1666 		inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]);
   1667 		if(!inbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
   1668 		ptr=(JSAMPLE *)srcPlanes[i];
   1669 		for(row=0; row<ph[i]; row++)
   1670 		{
   1671 			inbuf[i][row]=ptr;
   1672 			ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
   1673 		}
   1674 	}
   1675 
   1676 	if(setjmp(this->jerr.setjmp_buffer))
   1677 	{
   1678 		/* If we get here, the JPEG code has signaled an error. */
   1679 		retval=-1;  goto bailout;
   1680 	}
   1681 
   1682 	for(row=0; row<ph0; row+=dinfo->max_v_samp_factor)
   1683 	{
   1684 		JDIMENSION inrow=0, outrow=0;
   1685 		for(i=0, compptr=dinfo->comp_info; i<dinfo->num_components; i++, compptr++)
   1686 			jcopy_sample_rows(inbuf[i],
   1687 				row*compptr->v_samp_factor/dinfo->max_v_samp_factor, tmpbuf[i], 0,
   1688 				compptr->v_samp_factor, pw[i]);
   1689 		(dinfo->upsample->upsample)(dinfo, tmpbuf, &inrow,
   1690 			dinfo->max_v_samp_factor, &row_pointer[row], &outrow,
   1691 			dinfo->max_v_samp_factor);
   1692 	}
   1693 	jpeg_abort_decompress(dinfo);
   1694 
   1695 	#ifndef JCS_EXTENSIONS
   1696 	fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
   1697 	#endif
   1698 
   1699 	bailout:
   1700 	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
   1701 	#ifndef JCS_EXTENSIONS
   1702 	if(rgbBuf) free(rgbBuf);
   1703 	#endif
   1704 	if(row_pointer) free(row_pointer);
   1705 	for(i=0; i<MAX_COMPONENTS; i++)
   1706 	{
   1707 		if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
   1708 		if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
   1709 		if(inbuf[i]!=NULL) free(inbuf[i]);
   1710 	}
   1711 	if(this->jerr.warning) retval=-1;
   1712 	return retval;
   1713 }
   1714 
   1715 DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, const unsigned char *srcBuf,
   1716 	int pad, int subsamp, unsigned char *dstBuf, int width, int pitch,
   1717 	int height, int pixelFormat, int flags)
   1718 {
   1719 	const unsigned char *srcPlanes[3];
   1720 	int pw0, ph0, strides[3], retval=-1;
   1721 
   1722 	if(srcBuf==NULL || pad<0 || !isPow2(pad) || subsamp<0 || subsamp>=NUMSUBOPT
   1723 		|| width<=0 || height<=0)
   1724 		_throw("tjDecodeYUV(): Invalid argument");
   1725 
   1726 	pw0=tjPlaneWidth(0, width, subsamp);
   1727 	ph0=tjPlaneHeight(0, height, subsamp);
   1728 	srcPlanes[0]=srcBuf;
   1729 	strides[0]=PAD(pw0, pad);
   1730 	if(subsamp==TJSAMP_GRAY)
   1731 	{
   1732 		strides[1]=strides[2]=0;
   1733 		srcPlanes[1]=srcPlanes[2]=NULL;
   1734 	}
   1735 	else
   1736 	{
   1737 		int pw1=tjPlaneWidth(1, width, subsamp);
   1738 		int ph1=tjPlaneHeight(1, height, subsamp);
   1739 		strides[1]=strides[2]=PAD(pw1, pad);
   1740 		srcPlanes[1]=srcPlanes[0]+strides[0]*ph0;
   1741 		srcPlanes[2]=srcPlanes[1]+strides[1]*ph1;
   1742 	}
   1743 
   1744 	return tjDecodeYUVPlanes(handle, srcPlanes, strides, subsamp, dstBuf, width,
   1745 		pitch, height, pixelFormat, flags);
   1746 
   1747 	bailout:
   1748 	return retval;
   1749 }
   1750 
   1751 DLLEXPORT int DLLCALL tjDecompressToYUVPlanes(tjhandle handle,
   1752 	const unsigned char *jpegBuf, unsigned long jpegSize,
   1753 	unsigned char **dstPlanes, int width, int *strides, int height, int flags)
   1754 {
   1755 	int i, sfi, row, retval=0;  JSAMPROW *outbuf[MAX_COMPONENTS];
   1756 	int jpegwidth, jpegheight, jpegSubsamp, scaledw, scaledh;
   1757 	int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS],
   1758 		tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
   1759 	JSAMPLE *_tmpbuf=NULL, *ptr;  JSAMPROW *tmpbuf[MAX_COMPONENTS];
   1760 	int dctsize;
   1761 
   1762 	getdinstance(handle);
   1763 
   1764 	for(i=0; i<MAX_COMPONENTS; i++)
   1765 	{
   1766 		tmpbuf[i]=NULL;  outbuf[i]=NULL;
   1767 	}
   1768 
   1769 	if((this->init&DECOMPRESS)==0)
   1770 		_throw("tjDecompressToYUVPlanes(): Instance has not been initialized for decompression");
   1771 
   1772 	if(jpegBuf==NULL || jpegSize<=0 || !dstPlanes || !dstPlanes[0] || width<0
   1773 		|| height<0)
   1774 		_throw("tjDecompressToYUVPlanes(): Invalid argument");
   1775 
   1776 	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
   1777 	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
   1778 	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
   1779 
   1780 	if(setjmp(this->jerr.setjmp_buffer))
   1781 	{
   1782 		/* If we get here, the JPEG code has signaled an error. */
   1783 		retval=-1;  goto bailout;
   1784 	}
   1785 
   1786 	if(!this->headerRead)
   1787 	{
   1788 		jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
   1789 		jpeg_read_header(dinfo, TRUE);
   1790 	}
   1791 	this->headerRead=0;
   1792 	jpegSubsamp=getSubsamp(dinfo);
   1793 	if(jpegSubsamp<0)
   1794 		_throw("tjDecompressToYUVPlanes(): Could not determine subsampling type for JPEG image");
   1795 
   1796 	if(jpegSubsamp!=TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2]))
   1797 		_throw("tjDecompressToYUVPlanes(): Invalid argument");
   1798 
   1799 	jpegwidth=dinfo->image_width;  jpegheight=dinfo->image_height;
   1800 	if(width==0) width=jpegwidth;
   1801 	if(height==0) height=jpegheight;
   1802 	for(i=0; i<NUMSF; i++)
   1803 	{
   1804 		scaledw=TJSCALED(jpegwidth, sf[i]);
   1805 		scaledh=TJSCALED(jpegheight, sf[i]);
   1806 		if(scaledw<=width && scaledh<=height)
   1807 			break;
   1808 	}
   1809 	if(i>=NUMSF)
   1810 		_throw("tjDecompressToYUVPlanes(): Could not scale down to desired image dimensions");
   1811 	if(dinfo->num_components>3)
   1812 		_throw("tjDecompressToYUVPlanes(): JPEG image must have 3 or fewer components");
   1813 
   1814 	width=scaledw;  height=scaledh;
   1815 	dinfo->scale_num=sf[i].num;
   1816 	dinfo->scale_denom=sf[i].denom;
   1817 	sfi=i;
   1818 	jpeg_calc_output_dimensions(dinfo);
   1819 
   1820 	dctsize=DCTSIZE*sf[sfi].num/sf[sfi].denom;
   1821 
   1822 	for(i=0; i<dinfo->num_components; i++)
   1823 	{
   1824 		jpeg_component_info *compptr=&dinfo->comp_info[i];
   1825 		int ih;
   1826 		iw[i]=compptr->width_in_blocks*dctsize;
   1827 		ih=compptr->height_in_blocks*dctsize;
   1828 		pw[i]=PAD(dinfo->output_width, dinfo->max_h_samp_factor)
   1829 			*compptr->h_samp_factor/dinfo->max_h_samp_factor;
   1830 		ph[i]=PAD(dinfo->output_height, dinfo->max_v_samp_factor)
   1831 			*compptr->v_samp_factor/dinfo->max_v_samp_factor;
   1832 		if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1;
   1833 		th[i]=compptr->v_samp_factor*dctsize;
   1834 		tmpbufsize+=iw[i]*th[i];
   1835 		if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]))==NULL)
   1836 			_throw("tjDecompressToYUVPlanes(): Memory allocation failure");
   1837 		ptr=dstPlanes[i];
   1838 		for(row=0; row<ph[i]; row++)
   1839 		{
   1840 			outbuf[i][row]=ptr;
   1841 			ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
   1842 		}
   1843 	}
   1844 	if(usetmpbuf)
   1845 	{
   1846 		if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
   1847 			_throw("tjDecompressToYUVPlanes(): Memory allocation failure");
   1848 		ptr=_tmpbuf;
   1849 		for(i=0; i<dinfo->num_components; i++)
   1850 		{
   1851 			if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
   1852 				_throw("tjDecompressToYUVPlanes(): Memory allocation failure");
   1853 			for(row=0; row<th[i]; row++)
   1854 			{
   1855 				tmpbuf[i][row]=ptr;
   1856 				ptr+=iw[i];
   1857 			}
   1858 		}
   1859 	}
   1860 
   1861 	if(setjmp(this->jerr.setjmp_buffer))
   1862 	{
   1863 		/* If we get here, the JPEG code has signaled an error. */
   1864 		retval=-1;  goto bailout;
   1865 	}
   1866 
   1867 	if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
   1868 	if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
   1869 	dinfo->raw_data_out=TRUE;
   1870 
   1871 	jpeg_start_decompress(dinfo);
   1872 	for(row=0; row<(int)dinfo->output_height;
   1873 		row+=dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size)
   1874 	{
   1875 		JSAMPARRAY yuvptr[MAX_COMPONENTS];
   1876 		int crow[MAX_COMPONENTS];
   1877 		for(i=0; i<dinfo->num_components; i++)
   1878 		{
   1879 			jpeg_component_info *compptr=&dinfo->comp_info[i];
   1880 			if(jpegSubsamp==TJ_420)
   1881 			{
   1882 				/* When 4:2:0 subsampling is used with IDCT scaling, libjpeg will try
   1883 				   to be clever and use the IDCT to perform upsampling on the U and V
   1884 				   planes.  For instance, if the output image is to be scaled by 1/2
   1885 				   relative to the JPEG image, then the scaling factor and upsampling
   1886 				   effectively cancel each other, so a normal 8x8 IDCT can be used.
   1887 				   However, this is not desirable when using the decompress-to-YUV
   1888 				   functionality in TurboJPEG, since we want to output the U and V
   1889 				   planes in their subsampled form.  Thus, we have to override some
   1890 				   internal libjpeg parameters to force it to use the "scaled" IDCT
   1891 				   functions on the U and V planes. */
   1892 				compptr->_DCT_scaled_size=dctsize;
   1893 				compptr->MCU_sample_width=tjMCUWidth[jpegSubsamp]*
   1894 					sf[sfi].num/sf[sfi].denom*
   1895 					compptr->v_samp_factor/dinfo->max_v_samp_factor;
   1896 				dinfo->idct->inverse_DCT[i] = dinfo->idct->inverse_DCT[0];
   1897 			}
   1898 			crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
   1899 			if(usetmpbuf) yuvptr[i]=tmpbuf[i];
   1900 			else yuvptr[i]=&outbuf[i][crow[i]];
   1901 		}
   1902 		jpeg_read_raw_data(dinfo, yuvptr,
   1903 			dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size);
   1904 		if(usetmpbuf)
   1905 		{
   1906 			int j;
   1907 			for(i=0; i<dinfo->num_components; i++)
   1908 			{
   1909 				for(j=0; j<min(th[i], ph[i]-crow[i]); j++)
   1910 				{
   1911 					memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], pw[i]);
   1912 				}
   1913 			}
   1914 		}
   1915 	}
   1916 	jpeg_finish_decompress(dinfo);
   1917 
   1918 	bailout:
   1919 	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
   1920 	for(i=0; i<MAX_COMPONENTS; i++)
   1921 	{
   1922 		if(tmpbuf[i]) free(tmpbuf[i]);
   1923 		if(outbuf[i]) free(outbuf[i]);
   1924 	}
   1925 	if(_tmpbuf) free(_tmpbuf);
   1926 	if(this->jerr.warning) retval=-1;
   1927 	return retval;
   1928 }
   1929 
   1930 DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle,
   1931 	const unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
   1932 	int width, int pad, int height, int flags)
   1933 {
   1934 	unsigned char *dstPlanes[3];
   1935 	int pw0, ph0, strides[3], retval=-1, jpegSubsamp=-1;
   1936 	int i, jpegwidth, jpegheight, scaledw, scaledh;
   1937 
   1938 	getdinstance(handle);
   1939 
   1940 	if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pad<1
   1941 		|| !isPow2(pad) || height<0)
   1942 		_throw("tjDecompressToYUV2(): Invalid argument");
   1943 
   1944 	if(setjmp(this->jerr.setjmp_buffer))
   1945 	{
   1946 		/* If we get here, the JPEG code has signaled an error. */
   1947 		return -1;
   1948 	}
   1949 
   1950 	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
   1951 	jpeg_read_header(dinfo, TRUE);
   1952 	jpegSubsamp=getSubsamp(dinfo);
   1953 	if(jpegSubsamp<0)
   1954 		_throw("tjDecompressToYUV2(): Could not determine subsampling type for JPEG image");
   1955 
   1956 	jpegwidth=dinfo->image_width;  jpegheight=dinfo->image_height;
   1957 	if(width==0) width=jpegwidth;
   1958 	if(height==0) height=jpegheight;
   1959 
   1960 	for(i=0; i<NUMSF; i++)
   1961 	{
   1962 		scaledw=TJSCALED(jpegwidth, sf[i]);
   1963 		scaledh=TJSCALED(jpegheight, sf[i]);
   1964 		if(scaledw<=width && scaledh<=height)
   1965 			break;
   1966 	}
   1967 	if(i>=NUMSF)
   1968 		_throw("tjDecompressToYUV2(): Could not scale down to desired image dimensions");
   1969 
   1970 	pw0=tjPlaneWidth(0, width, jpegSubsamp);
   1971 	ph0=tjPlaneHeight(0, height, jpegSubsamp);
   1972 	dstPlanes[0]=dstBuf;
   1973 	strides[0]=PAD(pw0, pad);
   1974 	if(jpegSubsamp==TJSAMP_GRAY)
   1975 	{
   1976 		strides[1]=strides[2]=0;
   1977 		dstPlanes[1]=dstPlanes[2]=NULL;
   1978 	}
   1979 	else
   1980 	{
   1981 		int pw1=tjPlaneWidth(1, width, jpegSubsamp);
   1982 		int ph1=tjPlaneHeight(1, height, jpegSubsamp);
   1983 		strides[1]=strides[2]=PAD(pw1, pad);
   1984 		dstPlanes[1]=dstPlanes[0]+strides[0]*ph0;
   1985 		dstPlanes[2]=dstPlanes[1]+strides[1]*ph1;
   1986 	}
   1987 
   1988 	this->headerRead=1;
   1989 	return tjDecompressToYUVPlanes(handle, jpegBuf, jpegSize, dstPlanes, width,
   1990 		strides, height, flags);
   1991 
   1992 	bailout:
   1993 	return retval;
   1994 
   1995 }
   1996 
   1997 DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle,
   1998 	unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
   1999 	int flags)
   2000 {
   2001 	return tjDecompressToYUV2(handle, jpegBuf, jpegSize, dstBuf, 0, 4, 0, flags);
   2002 }
   2003 
   2004 
   2005 /* Transformer */
   2006 
   2007 DLLEXPORT tjhandle DLLCALL tjInitTransform(void)
   2008 {
   2009 	tjinstance *this=NULL;  tjhandle handle=NULL;
   2010 	if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
   2011 	{
   2012 		snprintf(errStr, JMSG_LENGTH_MAX,
   2013 			"tjInitTransform(): Memory allocation failure");
   2014 		return NULL;
   2015 	}
   2016 	MEMZERO(this, sizeof(tjinstance));
   2017 	handle=_tjInitCompress(this);
   2018 	if(!handle) return NULL;
   2019 	handle=_tjInitDecompress(this);
   2020 	return handle;
   2021 }
   2022 
   2023 
   2024 DLLEXPORT int DLLCALL tjTransform(tjhandle handle,
   2025 	const unsigned char *jpegBuf, unsigned long jpegSize, int n,
   2026 	unsigned char **dstBufs, unsigned long *dstSizes, tjtransform *t, int flags)
   2027 {
   2028 	jpeg_transform_info *xinfo=NULL;
   2029 	jvirt_barray_ptr *srccoefs, *dstcoefs;
   2030 	int retval=0, i, jpegSubsamp;
   2031 
   2032 	getinstance(handle);
   2033 	if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0)
   2034 		_throw("tjTransform(): Instance has not been initialized for transformation");
   2035 
   2036 	if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL
   2037 		|| t==NULL || flags<0)
   2038 		_throw("tjTransform(): Invalid argument");
   2039 
   2040 	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
   2041 	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
   2042 	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
   2043 
   2044 	if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n))
   2045 		==NULL)
   2046 		_throw("tjTransform(): Memory allocation failure");
   2047 	MEMZERO(xinfo, sizeof(jpeg_transform_info)*n);
   2048 
   2049 	if(setjmp(this->jerr.setjmp_buffer))
   2050 	{
   2051 		/* If we get here, the JPEG code has signaled an error. */
   2052 		retval=-1;  goto bailout;
   2053 	}
   2054 
   2055 	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
   2056 
   2057 	for(i=0; i<n; i++)
   2058 	{
   2059 		xinfo[i].transform=xformtypes[t[i].op];
   2060 		xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0;
   2061 		xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0;
   2062 		xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0;
   2063 		xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0;
   2064 		if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1;
   2065 		else xinfo[i].slow_hflip=0;
   2066 
   2067 		if(xinfo[i].crop)
   2068 		{
   2069 			xinfo[i].crop_xoffset=t[i].r.x;  xinfo[i].crop_xoffset_set=JCROP_POS;
   2070 			xinfo[i].crop_yoffset=t[i].r.y;  xinfo[i].crop_yoffset_set=JCROP_POS;
   2071 			if(t[i].r.w!=0)
   2072 			{
   2073 				xinfo[i].crop_width=t[i].r.w;  xinfo[i].crop_width_set=JCROP_POS;
   2074 			}
   2075 			else xinfo[i].crop_width=JCROP_UNSET;
   2076 			if(t[i].r.h!=0)
   2077 			{
   2078 				xinfo[i].crop_height=t[i].r.h;  xinfo[i].crop_height_set=JCROP_POS;
   2079 			}
   2080 			else xinfo[i].crop_height=JCROP_UNSET;
   2081 		}
   2082 	}
   2083 
   2084 	jcopy_markers_setup(dinfo, JCOPYOPT_ALL);
   2085 	jpeg_read_header(dinfo, TRUE);
   2086 	jpegSubsamp=getSubsamp(dinfo);
   2087 	if(jpegSubsamp<0)
   2088 		_throw("tjTransform(): Could not determine subsampling type for JPEG image");
   2089 
   2090 	for(i=0; i<n; i++)
   2091 	{
   2092 		if(!jtransform_request_workspace(dinfo, &xinfo[i]))
   2093 			_throw("tjTransform(): Transform is not perfect");
   2094 
   2095 		if(xinfo[i].crop)
   2096 		{
   2097 			if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0
   2098 				|| (t[i].r.y%xinfo[i].iMCU_sample_height)!=0)
   2099 			{
   2100 				snprintf(errStr, JMSG_LENGTH_MAX,
   2101 					"To crop this JPEG image, x must be a multiple of %d\n"
   2102 					"and y must be a multiple of %d.\n",
   2103 					xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height);
   2104 				retval=-1;  goto bailout;
   2105 			}
   2106 		}
   2107 	}
   2108 
   2109 	srccoefs=jpeg_read_coefficients(dinfo);
   2110 
   2111 	for(i=0; i<n; i++)
   2112 	{
   2113 		int w, h, alloc=1;
   2114 		if(!xinfo[i].crop)
   2115 		{
   2116 			w=dinfo->image_width;  h=dinfo->image_height;
   2117 		}
   2118 		else
   2119 		{
   2120 			w=xinfo[i].crop_width;  h=xinfo[i].crop_height;
   2121 		}
   2122 		if(flags&TJFLAG_NOREALLOC)
   2123 		{
   2124 			alloc=0;  dstSizes[i]=tjBufSize(w, h, jpegSubsamp);
   2125 		}
   2126 		if(!(t[i].options&TJXOPT_NOOUTPUT))
   2127 			jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc);
   2128 		jpeg_copy_critical_parameters(dinfo, cinfo);
   2129 		dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs,
   2130 			&xinfo[i]);
   2131 		if(!(t[i].options&TJXOPT_NOOUTPUT))
   2132 		{
   2133 			jpeg_write_coefficients(cinfo, dstcoefs);
   2134 			jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL);
   2135 		}
   2136 		else jinit_c_master_control(cinfo, TRUE);
   2137 		jtransform_execute_transformation(dinfo, cinfo, srccoefs,
   2138 			&xinfo[i]);
   2139 		if(t[i].customFilter)
   2140 		{
   2141 			int ci, y;  JDIMENSION by;
   2142 			for(ci=0; ci<cinfo->num_components; ci++)
   2143 			{
   2144 				jpeg_component_info *compptr=&cinfo->comp_info[ci];
   2145 				tjregion arrayRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
   2146 					DCTSIZE};
   2147 				tjregion planeRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
   2148 					compptr->height_in_blocks*DCTSIZE};
   2149 				for(by=0; by<compptr->height_in_blocks; by+=compptr->v_samp_factor)
   2150 				{
   2151 					JBLOCKARRAY barray=(dinfo->mem->access_virt_barray)
   2152 						((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor,
   2153 						TRUE);
   2154 					for(y=0; y<compptr->v_samp_factor; y++)
   2155 					{
   2156 						if(t[i].customFilter(barray[y][0], arrayRegion, planeRegion,
   2157 							ci, i, &t[i])==-1)
   2158 							_throw("tjTransform(): Error in custom filter");
   2159 						arrayRegion.y+=DCTSIZE;
   2160 					}
   2161 				}
   2162 			}
   2163 		}
   2164 		if(!(t[i].options&TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo);
   2165 	}
   2166 
   2167 	jpeg_finish_decompress(dinfo);
   2168 
   2169 	bailout:
   2170 	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
   2171 	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
   2172 	if(xinfo) free(xinfo);
   2173 	if(this->jerr.warning) retval=-1;
   2174 	return retval;
   2175 }
   2176