Home | History | Annotate | Download | only in libjpeg-turbo
      1 /*
      2  * Copyright (C)2009-2016 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(setjmp(this->jerr.setjmp_buffer))
    776 	{
    777 		/* If we get here, the JPEG code has signaled an error. */
    778 		retval=-1;
    779 		goto bailout;
    780 	}
    781 
    782 	if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
    783 
    784 	#ifndef JCS_EXTENSIONS
    785 	if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK)
    786 	{
    787 		rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
    788 		if(!rgbBuf) _throw("tjCompress2(): Memory allocation failure");
    789 		srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
    790 		pitch=width*RGB_PIXELSIZE;
    791 	}
    792 	#endif
    793 
    794 	cinfo->image_width=width;
    795 	cinfo->image_height=height;
    796 
    797 	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
    798 	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
    799 	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
    800 
    801 	if(flags&TJFLAG_NOREALLOC)
    802 	{
    803 		alloc=0;  *jpegSize=tjBufSize(width, height, jpegSubsamp);
    804 	}
    805 	jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
    806 	if(setCompDefaults(cinfo, pixelFormat, jpegSubsamp, jpegQual, flags)==-1)
    807 		return -1;
    808 
    809 	jpeg_start_compress(cinfo, TRUE);
    810 	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
    811 		_throw("tjCompress2(): Memory allocation failure");
    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(setjmp(this->jerr.setjmp_buffer))
    892 	{
    893 		/* If we get here, the JPEG code has signaled an error. */
    894 		retval=-1;
    895 		goto bailout;
    896 	}
    897 
    898 	if(pixelFormat==TJPF_CMYK)
    899 		_throw("tjEncodeYUVPlanes(): Cannot generate YUV images from CMYK pixels");
    900 
    901 	if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
    902 
    903 	#ifndef JCS_EXTENSIONS
    904 	if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK)
    905 	{
    906 		rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
    907 		if(!rgbBuf) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
    908 		srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
    909 		pitch=width*RGB_PIXELSIZE;
    910 	}
    911 	#endif
    912 
    913 	cinfo->image_width=width;
    914 	cinfo->image_height=height;
    915 
    916 	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
    917 	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
    918 	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
    919 
    920 	if(setCompDefaults(cinfo, pixelFormat, subsamp, -1, flags)==-1) return -1;
    921 
    922 	/* Execute only the parts of jpeg_start_compress() that we need.  If we
    923 	   were to call the whole jpeg_start_compress() function, then it would try
    924 	   to write the file headers, which could overflow the output buffer if the
    925 	   YUV image were very small. */
    926 	if(cinfo->global_state!=CSTATE_START)
    927 		_throw("tjEncodeYUVPlanes(): libjpeg API is in the wrong state");
    928 	(*cinfo->err->reset_error_mgr)((j_common_ptr)cinfo);
    929 	jinit_c_master_control(cinfo, FALSE);
    930 	jinit_color_converter(cinfo);
    931 	jinit_downsampler(cinfo);
    932 	(*cinfo->cconvert->start_pass)(cinfo);
    933 
    934 	pw0=PAD(width, cinfo->max_h_samp_factor);
    935 	ph0=PAD(height, cinfo->max_v_samp_factor);
    936 
    937 	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL)
    938 		_throw("tjEncodeYUVPlanes(): Memory allocation failure");
    939 	for(i=0; i<height; i++)
    940 	{
    941 		if(flags&TJFLAG_BOTTOMUP)
    942 			row_pointer[i]=(JSAMPROW)&srcBuf[(height-i-1)*pitch];
    943 		else row_pointer[i]=(JSAMPROW)&srcBuf[i*pitch];
    944 	}
    945 	if(height<ph0)
    946 		for(i=height; i<ph0; i++) row_pointer[i]=row_pointer[height-1];
    947 
    948 	for(i=0; i<cinfo->num_components; i++)
    949 	{
    950 		compptr=&cinfo->comp_info[i];
    951 		_tmpbuf[i]=(JSAMPLE *)malloc(
    952 			PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
    953 				/compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
    954 		if(!_tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
    955 		tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
    956 		if(!tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
    957 		for(row=0; row<cinfo->max_v_samp_factor; row++)
    958 		{
    959 			unsigned char *_tmpbuf_aligned=
    960 				(unsigned char *)PAD((size_t)_tmpbuf[i], 16);
    961 			tmpbuf[i][row]=&_tmpbuf_aligned[
    962 				PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
    963 					/compptr->h_samp_factor, 16) * row];
    964 		}
    965 		_tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
    966 			* compptr->v_samp_factor + 16);
    967 		if(!_tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
    968 		tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
    969 		if(!tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
    970 		for(row=0; row<compptr->v_samp_factor; row++)
    971 		{
    972 			unsigned char *_tmpbuf2_aligned=
    973 				(unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
    974 			tmpbuf2[i][row]=&_tmpbuf2_aligned[
    975 				PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
    976 		}
    977 		pw[i]=pw0*compptr->h_samp_factor/cinfo->max_h_samp_factor;
    978 		ph[i]=ph0*compptr->v_samp_factor/cinfo->max_v_samp_factor;
    979 		outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]);
    980 		if(!outbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
    981 		ptr=dstPlanes[i];
    982 		for(row=0; row<ph[i]; row++)
    983 		{
    984 			outbuf[i][row]=ptr;
    985 			ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
    986 		}
    987 	}
    988 
    989 	for(row=0; row<ph0; row+=cinfo->max_v_samp_factor)
    990 	{
    991 		(*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0,
    992 			cinfo->max_v_samp_factor);
    993 		(cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
    994 		for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++)
    995 			jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
    996 				row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
    997 				compptr->v_samp_factor, pw[i]);
    998 	}
    999 	cinfo->next_scanline+=height;
   1000 	jpeg_abort_compress(cinfo);
   1001 
   1002 	bailout:
   1003 	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
   1004 	#ifndef JCS_EXTENSIONS
   1005 	if(rgbBuf) free(rgbBuf);
   1006 	#endif
   1007 	if(row_pointer) free(row_pointer);
   1008 	for(i=0; i<MAX_COMPONENTS; i++)
   1009 	{
   1010 		if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
   1011 		if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
   1012 		if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
   1013 		if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
   1014 		if(outbuf[i]!=NULL) free(outbuf[i]);
   1015 	}
   1016 	if(this->jerr.warning) retval=-1;
   1017 	return retval;
   1018 }
   1019 
   1020 DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle,
   1021 	const unsigned char *srcBuf, int width, int pitch, int height,
   1022 	int pixelFormat, unsigned char *dstBuf, int pad, int subsamp, int flags)
   1023 {
   1024 	unsigned char *dstPlanes[3];
   1025 	int pw0, ph0, strides[3], retval=-1;
   1026 
   1027 	if(width<=0 || height<=0 || dstBuf==NULL || pad<0 || !isPow2(pad)
   1028 		|| subsamp<0 || subsamp>=NUMSUBOPT)
   1029 		_throw("tjEncodeYUV3(): Invalid argument");
   1030 
   1031 	pw0=tjPlaneWidth(0, width, subsamp);
   1032 	ph0=tjPlaneHeight(0, height, subsamp);
   1033 	dstPlanes[0]=dstBuf;
   1034 	strides[0]=PAD(pw0, pad);
   1035 	if(subsamp==TJSAMP_GRAY)
   1036 	{
   1037 		strides[1]=strides[2]=0;
   1038 		dstPlanes[1]=dstPlanes[2]=NULL;
   1039 	}
   1040 	else
   1041 	{
   1042 		int pw1=tjPlaneWidth(1, width, subsamp);
   1043 		int ph1=tjPlaneHeight(1, height, subsamp);
   1044 		strides[1]=strides[2]=PAD(pw1, pad);
   1045 		dstPlanes[1]=dstPlanes[0]+strides[0]*ph0;
   1046 		dstPlanes[2]=dstPlanes[1]+strides[1]*ph1;
   1047 	}
   1048 
   1049 	return tjEncodeYUVPlanes(handle, srcBuf, width, pitch, height, pixelFormat,
   1050 		dstPlanes, strides, subsamp, flags);
   1051 
   1052 	bailout:
   1053 	return retval;
   1054 }
   1055 
   1056 DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
   1057 	int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
   1058 	int subsamp, int flags)
   1059 {
   1060 	return tjEncodeYUV3(handle, srcBuf, width, pitch, height, pixelFormat,
   1061 		dstBuf, 4, subsamp, flags);
   1062 }
   1063 
   1064 DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf,
   1065 	int width, int pitch, int height, int pixelSize, unsigned char *dstBuf,
   1066 	int subsamp, int flags)
   1067 {
   1068 	return tjEncodeYUV2(handle, srcBuf, width, pitch, height,
   1069 		getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags);
   1070 }
   1071 
   1072 
   1073 DLLEXPORT int DLLCALL tjCompressFromYUVPlanes(tjhandle handle,
   1074 	const unsigned char **srcPlanes, int width, const int *strides, int height,
   1075 	int subsamp, unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual,
   1076 	int flags)
   1077 {
   1078 	int i, row, retval=0, alloc=1;  JSAMPROW *inbuf[MAX_COMPONENTS];
   1079 	int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS],
   1080 		tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
   1081 	JSAMPLE *_tmpbuf=NULL, *ptr;  JSAMPROW *tmpbuf[MAX_COMPONENTS];
   1082 
   1083 	getcinstance(handle)
   1084 
   1085 	for(i=0; i<MAX_COMPONENTS; i++)
   1086 	{
   1087 		tmpbuf[i]=NULL;  inbuf[i]=NULL;
   1088 	}
   1089 
   1090 	if((this->init&COMPRESS)==0)
   1091 		_throw("tjCompressFromYUVPlanes(): Instance has not been initialized for compression");
   1092 
   1093 	if(!srcPlanes || !srcPlanes[0] || width<=0 || height<=0 || subsamp<0
   1094 		|| subsamp>=NUMSUBOPT || jpegBuf==NULL || jpegSize==NULL || jpegQual<0
   1095 		|| jpegQual>100)
   1096 		_throw("tjCompressFromYUVPlanes(): Invalid argument");
   1097 	if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2]))
   1098 		_throw("tjCompressFromYUVPlanes(): Invalid argument");
   1099 
   1100 	if(setjmp(this->jerr.setjmp_buffer))
   1101 	{
   1102 		/* If we get here, the JPEG code has signaled an error. */
   1103 		retval=-1;
   1104 		goto bailout;
   1105 	}
   1106 
   1107 	cinfo->image_width=width;
   1108 	cinfo->image_height=height;
   1109 
   1110 	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
   1111 	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
   1112 	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
   1113 
   1114 	if(flags&TJFLAG_NOREALLOC)
   1115 	{
   1116 		alloc=0;  *jpegSize=tjBufSize(width, height, subsamp);
   1117 	}
   1118 	jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
   1119 	if(setCompDefaults(cinfo, TJPF_RGB, subsamp, jpegQual, flags)==-1)
   1120 		return -1;
   1121 	cinfo->raw_data_in=TRUE;
   1122 
   1123 	jpeg_start_compress(cinfo, TRUE);
   1124 	for(i=0; i<cinfo->num_components; i++)
   1125 	{
   1126 		jpeg_component_info *compptr=&cinfo->comp_info[i];
   1127 		int ih;
   1128 		iw[i]=compptr->width_in_blocks*DCTSIZE;
   1129 		ih=compptr->height_in_blocks*DCTSIZE;
   1130 		pw[i]=PAD(cinfo->image_width, cinfo->max_h_samp_factor)
   1131 			*compptr->h_samp_factor/cinfo->max_h_samp_factor;
   1132 		ph[i]=PAD(cinfo->image_height, cinfo->max_v_samp_factor)
   1133 			*compptr->v_samp_factor/cinfo->max_v_samp_factor;
   1134 		if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1;
   1135 		th[i]=compptr->v_samp_factor*DCTSIZE;
   1136 		tmpbufsize+=iw[i]*th[i];
   1137 		if((inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]))==NULL)
   1138 			_throw("tjCompressFromYUVPlanes(): Memory allocation failure");
   1139 		ptr=(JSAMPLE *)srcPlanes[i];
   1140 		for(row=0; row<ph[i]; row++)
   1141 		{
   1142 			inbuf[i][row]=ptr;
   1143 			ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
   1144 		}
   1145 	}
   1146 	if(usetmpbuf)
   1147 	{
   1148 		if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
   1149 			_throw("tjCompressFromYUVPlanes(): Memory allocation failure");
   1150 		ptr=_tmpbuf;
   1151 		for(i=0; i<cinfo->num_components; i++)
   1152 		{
   1153 			if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
   1154 				_throw("tjCompressFromYUVPlanes(): Memory allocation failure");
   1155 			for(row=0; row<th[i]; row++)
   1156 			{
   1157 				tmpbuf[i][row]=ptr;
   1158 				ptr+=iw[i];
   1159 			}
   1160 		}
   1161 	}
   1162 
   1163 	for(row=0; row<(int)cinfo->image_height;
   1164 		row+=cinfo->max_v_samp_factor*DCTSIZE)
   1165 	{
   1166 		JSAMPARRAY yuvptr[MAX_COMPONENTS];
   1167 		int crow[MAX_COMPONENTS];
   1168 		for(i=0; i<cinfo->num_components; i++)
   1169 		{
   1170 			jpeg_component_info *compptr=&cinfo->comp_info[i];
   1171 			crow[i]=row*compptr->v_samp_factor/cinfo->max_v_samp_factor;
   1172 			if(usetmpbuf)
   1173 			{
   1174 				int j, k;
   1175 				for(j=0; j<min(th[i], ph[i]-crow[i]); j++)
   1176 				{
   1177 					memcpy(tmpbuf[i][j], inbuf[i][crow[i]+j], pw[i]);
   1178 					/* Duplicate last sample in row to fill out MCU */
   1179 					for(k=pw[i]; k<iw[i]; k++) tmpbuf[i][j][k]=tmpbuf[i][j][pw[i]-1];
   1180 				}
   1181 				/* Duplicate last row to fill out MCU */
   1182 				for(j=ph[i]-crow[i]; j<th[i]; j++)
   1183 					memcpy(tmpbuf[i][j], tmpbuf[i][ph[i]-crow[i]-1], iw[i]);
   1184 				yuvptr[i]=tmpbuf[i];
   1185 			}
   1186 			else
   1187 				yuvptr[i]=&inbuf[i][crow[i]];
   1188 		}
   1189 		jpeg_write_raw_data(cinfo, yuvptr, cinfo->max_v_samp_factor*DCTSIZE);
   1190 	}
   1191 	jpeg_finish_compress(cinfo);
   1192 
   1193 	bailout:
   1194 	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
   1195 	for(i=0; i<MAX_COMPONENTS; i++)
   1196 	{
   1197 		if(tmpbuf[i]) free(tmpbuf[i]);
   1198 		if(inbuf[i]) free(inbuf[i]);
   1199 	}
   1200 	if(_tmpbuf) free(_tmpbuf);
   1201 	if(this->jerr.warning) retval=-1;
   1202 	return retval;
   1203 }
   1204 
   1205 DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle,
   1206 	const unsigned char *srcBuf, int width, int pad, int height, int subsamp,
   1207 	unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual, int flags)
   1208 {
   1209 	const unsigned char *srcPlanes[3];
   1210 	int pw0, ph0, strides[3], retval=-1;
   1211 
   1212 	if(srcBuf==NULL || width<=0 || pad<1 || height<=0 || subsamp<0
   1213 		|| subsamp>=NUMSUBOPT)
   1214 		_throw("tjCompressFromYUV(): Invalid argument");
   1215 
   1216 	pw0=tjPlaneWidth(0, width, subsamp);
   1217 	ph0=tjPlaneHeight(0, height, subsamp);
   1218 	srcPlanes[0]=srcBuf;
   1219 	strides[0]=PAD(pw0, pad);
   1220 	if(subsamp==TJSAMP_GRAY)
   1221 	{
   1222 		strides[1]=strides[2]=0;
   1223 		srcPlanes[1]=srcPlanes[2]=NULL;
   1224 	}
   1225 	else
   1226 	{
   1227 		int pw1=tjPlaneWidth(1, width, subsamp);
   1228 		int ph1=tjPlaneHeight(1, height, subsamp);
   1229 		strides[1]=strides[2]=PAD(pw1, pad);
   1230 		srcPlanes[1]=srcPlanes[0]+strides[0]*ph0;
   1231 		srcPlanes[2]=srcPlanes[1]+strides[1]*ph1;
   1232 	}
   1233 
   1234 	return tjCompressFromYUVPlanes(handle, srcPlanes, width, strides, height,
   1235 		subsamp, jpegBuf, jpegSize, jpegQual, flags);
   1236 
   1237 	bailout:
   1238 	return retval;
   1239 }
   1240 
   1241 
   1242 /* Decompressor */
   1243 
   1244 static tjhandle _tjInitDecompress(tjinstance *this)
   1245 {
   1246 	static unsigned char buffer[1];
   1247 
   1248 	/* This is also straight out of example.c */
   1249 	this->dinfo.err=jpeg_std_error(&this->jerr.pub);
   1250 	this->jerr.pub.error_exit=my_error_exit;
   1251 	this->jerr.pub.output_message=my_output_message;
   1252 	this->jerr.emit_message=this->jerr.pub.emit_message;
   1253 	this->jerr.pub.emit_message=my_emit_message;
   1254 
   1255 	if(setjmp(this->jerr.setjmp_buffer))
   1256 	{
   1257 		/* If we get here, the JPEG code has signaled an error. */
   1258 		if(this) free(this);
   1259 		return NULL;
   1260 	}
   1261 
   1262 	jpeg_create_decompress(&this->dinfo);
   1263 	/* Make an initial call so it will create the source manager */
   1264 	jpeg_mem_src_tj(&this->dinfo, buffer, 1);
   1265 
   1266 	this->init|=DECOMPRESS;
   1267 	return (tjhandle)this;
   1268 }
   1269 
   1270 DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
   1271 {
   1272 	tjinstance *this;
   1273 	if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
   1274 	{
   1275 		snprintf(errStr, JMSG_LENGTH_MAX,
   1276 			"tjInitDecompress(): Memory allocation failure");
   1277 		return NULL;
   1278 	}
   1279 	MEMZERO(this, sizeof(tjinstance));
   1280 	return _tjInitDecompress(this);
   1281 }
   1282 
   1283 
   1284 DLLEXPORT int DLLCALL tjDecompressHeader3(tjhandle handle,
   1285 	const unsigned char *jpegBuf, unsigned long jpegSize, int *width,
   1286 	int *height, int *jpegSubsamp, int *jpegColorspace)
   1287 {
   1288 	int retval=0;
   1289 
   1290 	getdinstance(handle);
   1291 	if((this->init&DECOMPRESS)==0)
   1292 		_throw("tjDecompressHeader3(): Instance has not been initialized for decompression");
   1293 
   1294 	if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL
   1295 		|| jpegSubsamp==NULL || jpegColorspace==NULL)
   1296 		_throw("tjDecompressHeader3(): Invalid argument");
   1297 
   1298 	if(setjmp(this->jerr.setjmp_buffer))
   1299 	{
   1300 		/* If we get here, the JPEG code has signaled an error. */
   1301 		return -1;
   1302 	}
   1303 
   1304 	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
   1305 	jpeg_read_header(dinfo, TRUE);
   1306 
   1307 	*width=dinfo->image_width;
   1308 	*height=dinfo->image_height;
   1309 	*jpegSubsamp=getSubsamp(dinfo);
   1310 	switch(dinfo->jpeg_color_space)
   1311 	{
   1312 		case JCS_GRAYSCALE:  *jpegColorspace=TJCS_GRAY;  break;
   1313 		case JCS_RGB:        *jpegColorspace=TJCS_RGB;  break;
   1314 		case JCS_YCbCr:      *jpegColorspace=TJCS_YCbCr;  break;
   1315 		case JCS_CMYK:       *jpegColorspace=TJCS_CMYK;  break;
   1316 		case JCS_YCCK:       *jpegColorspace=TJCS_YCCK;  break;
   1317 		default:             *jpegColorspace=-1;  break;
   1318 	}
   1319 
   1320 	jpeg_abort_decompress(dinfo);
   1321 
   1322 	if(*jpegSubsamp<0)
   1323 		_throw("tjDecompressHeader3(): Could not determine subsampling type for JPEG image");
   1324 	if(*jpegColorspace<0)
   1325 		_throw("tjDecompressHeader3(): Could not determine colorspace of JPEG image");
   1326 	if(*width<1 || *height<1)
   1327 		_throw("tjDecompressHeader3(): Invalid data returned in header");
   1328 
   1329 	bailout:
   1330 	if(this->jerr.warning) retval=-1;
   1331 	return retval;
   1332 }
   1333 
   1334 DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle,
   1335 	unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
   1336 	int *jpegSubsamp)
   1337 {
   1338 	int jpegColorspace;
   1339 	return tjDecompressHeader3(handle, jpegBuf, jpegSize, width, height,
   1340 		jpegSubsamp, &jpegColorspace);
   1341 }
   1342 
   1343 DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle,
   1344 	unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height)
   1345 {
   1346 	int jpegSubsamp;
   1347 	return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height,
   1348 		&jpegSubsamp);
   1349 }
   1350 
   1351 
   1352 DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors)
   1353 {
   1354 	if(numscalingfactors==NULL)
   1355 	{
   1356 		snprintf(errStr, JMSG_LENGTH_MAX,
   1357 			"tjGetScalingFactors(): Invalid argument");
   1358 		return NULL;
   1359 	}
   1360 
   1361 	*numscalingfactors=NUMSF;
   1362 	return (tjscalingfactor *)sf;
   1363 }
   1364 
   1365 
   1366 DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle,
   1367 	const unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
   1368 	int width, int pitch, int height, int pixelFormat, int flags)
   1369 {
   1370 	int i, retval=0;  JSAMPROW *row_pointer=NULL;
   1371 	int jpegwidth, jpegheight, scaledw, scaledh;
   1372 	#ifndef JCS_EXTENSIONS
   1373 	unsigned char *rgbBuf=NULL;
   1374 	unsigned char *_dstBuf=NULL;  int _pitch=0;
   1375 	#endif
   1376 
   1377 	getdinstance(handle);
   1378 	if((this->init&DECOMPRESS)==0)
   1379 		_throw("tjDecompress2(): Instance has not been initialized for decompression");
   1380 
   1381 	if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0
   1382 		|| height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF)
   1383 		_throw("tjDecompress2(): Invalid argument");
   1384 
   1385 	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
   1386 	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
   1387 	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
   1388 
   1389 	if(setjmp(this->jerr.setjmp_buffer))
   1390 	{
   1391 		/* If we get here, the JPEG code has signaled an error. */
   1392 		retval=-1;
   1393 		goto bailout;
   1394 	}
   1395 
   1396 	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
   1397 	jpeg_read_header(dinfo, TRUE);
   1398 	if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
   1399 	{
   1400 		retval=-1;  goto bailout;
   1401 	}
   1402 
   1403 	if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
   1404 
   1405 	jpegwidth=dinfo->image_width;  jpegheight=dinfo->image_height;
   1406 	if(width==0) width=jpegwidth;
   1407 	if(height==0) height=jpegheight;
   1408 	for(i=0; i<NUMSF; i++)
   1409 	{
   1410 		scaledw=TJSCALED(jpegwidth, sf[i]);
   1411 		scaledh=TJSCALED(jpegheight, sf[i]);
   1412 		if(scaledw<=width && scaledh<=height)
   1413 			break;
   1414 	}
   1415 	if(i>=NUMSF)
   1416 		_throw("tjDecompress2(): Could not scale down to desired image dimensions");
   1417 	width=scaledw;  height=scaledh;
   1418 	dinfo->scale_num=sf[i].num;
   1419 	dinfo->scale_denom=sf[i].denom;
   1420 
   1421 	jpeg_start_decompress(dinfo);
   1422 	if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
   1423 
   1424 	#ifndef JCS_EXTENSIONS
   1425 	if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK &&
   1426 		(RGB_RED!=tjRedOffset[pixelFormat] ||
   1427 			RGB_GREEN!=tjGreenOffset[pixelFormat] ||
   1428 			RGB_BLUE!=tjBlueOffset[pixelFormat] ||
   1429 			RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
   1430 	{
   1431 		rgbBuf=(unsigned char *)malloc(width*height*3);
   1432 		if(!rgbBuf) _throw("tjDecompress2(): Memory allocation failure");
   1433 		_pitch=pitch;  pitch=width*3;
   1434 		_dstBuf=dstBuf;  dstBuf=rgbBuf;
   1435 	}
   1436 	#endif
   1437 
   1438 	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
   1439 		*dinfo->output_height))==NULL)
   1440 		_throw("tjDecompress2(): Memory allocation failure");
   1441 	for(i=0; i<(int)dinfo->output_height; i++)
   1442 	{
   1443 		if(flags&TJFLAG_BOTTOMUP)
   1444 			row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*pitch];
   1445 		else row_pointer[i]=&dstBuf[i*pitch];
   1446 	}
   1447 	while(dinfo->output_scanline<dinfo->output_height)
   1448 	{
   1449 		jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline],
   1450 			dinfo->output_height-dinfo->output_scanline);
   1451 	}
   1452 	jpeg_finish_decompress(dinfo);
   1453 
   1454 	#ifndef JCS_EXTENSIONS
   1455 	fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
   1456 	#endif
   1457 
   1458 	bailout:
   1459 	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
   1460 	#ifndef JCS_EXTENSIONS
   1461 	if(rgbBuf) free(rgbBuf);
   1462 	#endif
   1463 	if(row_pointer) free(row_pointer);
   1464 	if(this->jerr.warning) retval=-1;
   1465 	return retval;
   1466 }
   1467 
   1468 DLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf,
   1469 	unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
   1470 	int height, int pixelSize, int flags)
   1471 {
   1472 	if(flags&TJ_YUV)
   1473 		return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags);
   1474 	else
   1475 		return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch,
   1476 			height, getPixelFormat(pixelSize, flags), flags);
   1477 }
   1478 
   1479 
   1480 static int setDecodeDefaults(struct jpeg_decompress_struct *dinfo,
   1481 	int pixelFormat, int subsamp, int flags)
   1482 {
   1483 	int i;
   1484 
   1485 	dinfo->scale_num=dinfo->scale_denom=1;
   1486 
   1487 	if(subsamp==TJSAMP_GRAY)
   1488 	{
   1489 		dinfo->num_components=dinfo->comps_in_scan=1;
   1490 		dinfo->jpeg_color_space=JCS_GRAYSCALE;
   1491 	}
   1492 	else
   1493 	{
   1494 		dinfo->num_components=dinfo->comps_in_scan=3;
   1495 		dinfo->jpeg_color_space=JCS_YCbCr;
   1496 	}
   1497 
   1498 	dinfo->comp_info=(jpeg_component_info *)
   1499 		(*dinfo->mem->alloc_small)((j_common_ptr)dinfo, JPOOL_IMAGE,
   1500 			dinfo->num_components*sizeof(jpeg_component_info));
   1501 
   1502 	for(i=0; i<dinfo->num_components; i++)
   1503 	{
   1504 		jpeg_component_info *compptr=&dinfo->comp_info[i];
   1505 		compptr->h_samp_factor=(i==0)? tjMCUWidth[subsamp]/8:1;
   1506 		compptr->v_samp_factor=(i==0)? tjMCUHeight[subsamp]/8:1;
   1507 		compptr->component_index=i;
   1508 		compptr->component_id=i+1;
   1509 		compptr->quant_tbl_no=compptr->dc_tbl_no=compptr->ac_tbl_no=
   1510 			(i==0)? 0:1;
   1511 		dinfo->cur_comp_info[i]=compptr;
   1512 	}
   1513 	dinfo->data_precision=8;
   1514 	for(i=0; i<2; i++)
   1515 	{
   1516 		if(dinfo->quant_tbl_ptrs[i]==NULL)
   1517 			dinfo->quant_tbl_ptrs[i]=jpeg_alloc_quant_table((j_common_ptr)dinfo);
   1518 	}
   1519 
   1520 	return 0;
   1521 }
   1522 
   1523 
   1524 int my_read_markers(j_decompress_ptr dinfo)
   1525 {
   1526 	return JPEG_REACHED_SOS;
   1527 }
   1528 
   1529 void my_reset_marker_reader(j_decompress_ptr dinfo)
   1530 {
   1531 }
   1532 
   1533 DLLEXPORT int DLLCALL tjDecodeYUVPlanes(tjhandle handle,
   1534 	const unsigned char **srcPlanes, const int *strides, int subsamp,
   1535 	unsigned char *dstBuf, int width, int pitch, int height, int pixelFormat,
   1536 	int flags)
   1537 {
   1538 	int i, retval=0;  JSAMPROW *row_pointer=NULL;
   1539 	JSAMPLE *_tmpbuf[MAX_COMPONENTS];
   1540 	JSAMPROW *tmpbuf[MAX_COMPONENTS], *inbuf[MAX_COMPONENTS];
   1541 	int row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS];
   1542 	JSAMPLE *ptr;
   1543 	jpeg_component_info *compptr;
   1544 	#ifndef JCS_EXTENSIONS
   1545 	unsigned char *rgbBuf=NULL;
   1546 	unsigned char *_dstBuf=NULL;  int _pitch=0;
   1547 	#endif
   1548 	int (*old_read_markers)(j_decompress_ptr);
   1549 	void (*old_reset_marker_reader)(j_decompress_ptr);
   1550 
   1551 	getdinstance(handle);
   1552 
   1553 	for(i=0; i<MAX_COMPONENTS; i++)
   1554 	{
   1555 		tmpbuf[i]=NULL;  _tmpbuf[i]=NULL;  inbuf[i]=NULL;
   1556 	}
   1557 
   1558 	if((this->init&DECOMPRESS)==0)
   1559 		_throw("tjDecodeYUVPlanes(): Instance has not been initialized for decompression");
   1560 
   1561 	if(!srcPlanes || !srcPlanes[0] || subsamp<0 || subsamp>=NUMSUBOPT
   1562 		|| dstBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
   1563 		|| pixelFormat>=TJ_NUMPF)
   1564 		_throw("tjDecodeYUVPlanes(): Invalid argument");
   1565 	if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2]))
   1566 		_throw("tjDecodeYUVPlanes(): Invalid argument");
   1567 
   1568 	if(setjmp(this->jerr.setjmp_buffer))
   1569 	{
   1570 		/* If we get here, the JPEG code has signaled an error. */
   1571 		retval=-1;
   1572 		goto bailout;
   1573 	}
   1574 
   1575 	if(pixelFormat==TJPF_CMYK)
   1576 		_throw("tjDecodeYUVPlanes(): Cannot decode YUV images into CMYK pixels.");
   1577 
   1578 	if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
   1579 	dinfo->image_width=width;
   1580 	dinfo->image_height=height;
   1581 
   1582 	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
   1583 	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
   1584 	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
   1585 
   1586 	if(setDecodeDefaults(dinfo, pixelFormat, subsamp, flags)==-1)
   1587 	{
   1588 		retval=-1;  goto bailout;
   1589 	}
   1590 	old_read_markers=dinfo->marker->read_markers;
   1591 	dinfo->marker->read_markers=my_read_markers;
   1592 	old_reset_marker_reader=dinfo->marker->reset_marker_reader;
   1593 	dinfo->marker->reset_marker_reader=my_reset_marker_reader;
   1594 	jpeg_read_header(dinfo, TRUE);
   1595 	dinfo->marker->read_markers=old_read_markers;
   1596 	dinfo->marker->reset_marker_reader=old_reset_marker_reader;
   1597 
   1598 	if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
   1599 	{
   1600 		retval=-1;  goto bailout;
   1601 	}
   1602 	dinfo->do_fancy_upsampling=FALSE;
   1603 	dinfo->Se=DCTSIZE2-1;
   1604 	jinit_master_decompress(dinfo);
   1605 	(*dinfo->upsample->start_pass)(dinfo);
   1606 
   1607 	pw0=PAD(width, dinfo->max_h_samp_factor);
   1608 	ph0=PAD(height, dinfo->max_v_samp_factor);
   1609 
   1610 	if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
   1611 
   1612 	#ifndef JCS_EXTENSIONS
   1613 	if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK &&
   1614 		(RGB_RED!=tjRedOffset[pixelFormat] ||
   1615 			RGB_GREEN!=tjGreenOffset[pixelFormat] ||
   1616 			RGB_BLUE!=tjBlueOffset[pixelFormat] ||
   1617 			RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
   1618 	{
   1619 		rgbBuf=(unsigned char *)malloc(width*height*3);
   1620 		if(!rgbBuf) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
   1621 		_pitch=pitch;  pitch=width*3;
   1622 		_dstBuf=dstBuf;  dstBuf=rgbBuf;
   1623 	}
   1624 	#endif
   1625 
   1626 	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL)
   1627 		_throw("tjDecodeYUVPlanes(): Memory allocation failure");
   1628 	for(i=0; i<height; i++)
   1629 	{
   1630 		if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&dstBuf[(height-i-1)*pitch];
   1631 		else row_pointer[i]=&dstBuf[i*pitch];
   1632 	}
   1633 	if(height<ph0)
   1634 		for(i=height; i<ph0; i++) row_pointer[i]=row_pointer[height-1];
   1635 
   1636 	for(i=0; i<dinfo->num_components; i++)
   1637 	{
   1638 		compptr=&dinfo->comp_info[i];
   1639 		_tmpbuf[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
   1640 			* compptr->v_samp_factor + 16);
   1641 		if(!_tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
   1642 		tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
   1643 		if(!tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
   1644 		for(row=0; row<compptr->v_samp_factor; row++)
   1645 		{
   1646 			unsigned char *_tmpbuf_aligned=
   1647 				(unsigned char *)PAD((size_t)_tmpbuf[i], 16);
   1648 			tmpbuf[i][row]=&_tmpbuf_aligned[
   1649 				PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
   1650 		}
   1651 		pw[i]=pw0*compptr->h_samp_factor/dinfo->max_h_samp_factor;
   1652 		ph[i]=ph0*compptr->v_samp_factor/dinfo->max_v_samp_factor;
   1653 		inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]);
   1654 		if(!inbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
   1655 		ptr=(JSAMPLE *)srcPlanes[i];
   1656 		for(row=0; row<ph[i]; row++)
   1657 		{
   1658 			inbuf[i][row]=ptr;
   1659 			ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
   1660 		}
   1661 	}
   1662 
   1663 	for(row=0; row<ph0; row+=dinfo->max_v_samp_factor)
   1664 	{
   1665 		JDIMENSION inrow=0, outrow=0;
   1666 		for(i=0, compptr=dinfo->comp_info; i<dinfo->num_components; i++, compptr++)
   1667 			jcopy_sample_rows(inbuf[i],
   1668 				row*compptr->v_samp_factor/dinfo->max_v_samp_factor, tmpbuf[i], 0,
   1669 				compptr->v_samp_factor, pw[i]);
   1670 		(dinfo->upsample->upsample)(dinfo, tmpbuf, &inrow,
   1671 			dinfo->max_v_samp_factor, &row_pointer[row], &outrow,
   1672 			dinfo->max_v_samp_factor);
   1673 	}
   1674 	jpeg_abort_decompress(dinfo);
   1675 
   1676 	#ifndef JCS_EXTENSIONS
   1677 	fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
   1678 	#endif
   1679 
   1680 	bailout:
   1681 	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
   1682 	#ifndef JCS_EXTENSIONS
   1683 	if(rgbBuf) free(rgbBuf);
   1684 	#endif
   1685 	if(row_pointer) free(row_pointer);
   1686 	for(i=0; i<MAX_COMPONENTS; i++)
   1687 	{
   1688 		if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
   1689 		if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
   1690 		if(inbuf[i]!=NULL) free(inbuf[i]);
   1691 	}
   1692 	if(this->jerr.warning) retval=-1;
   1693 	return retval;
   1694 }
   1695 
   1696 DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, const unsigned char *srcBuf,
   1697 	int pad, int subsamp, unsigned char *dstBuf, int width, int pitch,
   1698 	int height, int pixelFormat, int flags)
   1699 {
   1700 	const unsigned char *srcPlanes[3];
   1701 	int pw0, ph0, strides[3], retval=-1;
   1702 
   1703 	if(srcBuf==NULL || pad<0 || !isPow2(pad) || subsamp<0 || subsamp>=NUMSUBOPT
   1704 		|| width<=0 || height<=0)
   1705 		_throw("tjDecodeYUV(): Invalid argument");
   1706 
   1707 	pw0=tjPlaneWidth(0, width, subsamp);
   1708 	ph0=tjPlaneHeight(0, height, subsamp);
   1709 	srcPlanes[0]=srcBuf;
   1710 	strides[0]=PAD(pw0, pad);
   1711 	if(subsamp==TJSAMP_GRAY)
   1712 	{
   1713 		strides[1]=strides[2]=0;
   1714 		srcPlanes[1]=srcPlanes[2]=NULL;
   1715 	}
   1716 	else
   1717 	{
   1718 		int pw1=tjPlaneWidth(1, width, subsamp);
   1719 		int ph1=tjPlaneHeight(1, height, subsamp);
   1720 		strides[1]=strides[2]=PAD(pw1, pad);
   1721 		srcPlanes[1]=srcPlanes[0]+strides[0]*ph0;
   1722 		srcPlanes[2]=srcPlanes[1]+strides[1]*ph1;
   1723 	}
   1724 
   1725 	return tjDecodeYUVPlanes(handle, srcPlanes, strides, subsamp, dstBuf, width,
   1726 		pitch, height, pixelFormat, flags);
   1727 
   1728 	bailout:
   1729 	return retval;
   1730 }
   1731 
   1732 DLLEXPORT int DLLCALL tjDecompressToYUVPlanes(tjhandle handle,
   1733 	const unsigned char *jpegBuf, unsigned long jpegSize,
   1734 	unsigned char **dstPlanes, int width, int *strides, int height, int flags)
   1735 {
   1736 	int i, sfi, row, retval=0;  JSAMPROW *outbuf[MAX_COMPONENTS];
   1737 	int jpegwidth, jpegheight, jpegSubsamp, scaledw, scaledh;
   1738 	int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS],
   1739 		tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
   1740 	JSAMPLE *_tmpbuf=NULL, *ptr;  JSAMPROW *tmpbuf[MAX_COMPONENTS];
   1741 	int dctsize;
   1742 
   1743 	getdinstance(handle);
   1744 
   1745 	for(i=0; i<MAX_COMPONENTS; i++)
   1746 	{
   1747 		tmpbuf[i]=NULL;  outbuf[i]=NULL;
   1748 	}
   1749 
   1750 	if((this->init&DECOMPRESS)==0)
   1751 		_throw("tjDecompressToYUVPlanes(): Instance has not been initialized for decompression");
   1752 
   1753 	if(jpegBuf==NULL || jpegSize<=0 || !dstPlanes || !dstPlanes[0] || width<0
   1754 		|| height<0)
   1755 		_throw("tjDecompressToYUVPlanes(): Invalid argument");
   1756 
   1757 	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
   1758 	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
   1759 	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
   1760 
   1761 	if(setjmp(this->jerr.setjmp_buffer))
   1762 	{
   1763 		/* If we get here, the JPEG code has signaled an error. */
   1764 		retval=-1;
   1765 		goto bailout;
   1766 	}
   1767 
   1768 	if(!this->headerRead)
   1769 	{
   1770 		jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
   1771 		jpeg_read_header(dinfo, TRUE);
   1772 	}
   1773 	this->headerRead=0;
   1774 	jpegSubsamp=getSubsamp(dinfo);
   1775 	if(jpegSubsamp<0)
   1776 		_throw("tjDecompressToYUVPlanes(): Could not determine subsampling type for JPEG image");
   1777 
   1778 	if(jpegSubsamp!=TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2]))
   1779 		_throw("tjDecompressToYUVPlanes(): Invalid argument");
   1780 
   1781 	jpegwidth=dinfo->image_width;  jpegheight=dinfo->image_height;
   1782 	if(width==0) width=jpegwidth;
   1783 	if(height==0) height=jpegheight;
   1784 	for(i=0; i<NUMSF; i++)
   1785 	{
   1786 		scaledw=TJSCALED(jpegwidth, sf[i]);
   1787 		scaledh=TJSCALED(jpegheight, sf[i]);
   1788 		if(scaledw<=width && scaledh<=height)
   1789 			break;
   1790 	}
   1791 	if(i>=NUMSF)
   1792 		_throw("tjDecompressToYUVPlanes(): Could not scale down to desired image dimensions");
   1793 	if(dinfo->num_components>3)
   1794 		_throw("tjDecompressToYUVPlanes(): JPEG image must have 3 or fewer components");
   1795 
   1796 	width=scaledw;  height=scaledh;
   1797 	dinfo->scale_num=sf[i].num;
   1798 	dinfo->scale_denom=sf[i].denom;
   1799 	sfi=i;
   1800 	jpeg_calc_output_dimensions(dinfo);
   1801 
   1802 	dctsize=DCTSIZE*sf[sfi].num/sf[sfi].denom;
   1803 
   1804 	for(i=0; i<dinfo->num_components; i++)
   1805 	{
   1806 		jpeg_component_info *compptr=&dinfo->comp_info[i];
   1807 		int ih;
   1808 		iw[i]=compptr->width_in_blocks*dctsize;
   1809 		ih=compptr->height_in_blocks*dctsize;
   1810 		pw[i]=PAD(dinfo->output_width, dinfo->max_h_samp_factor)
   1811 			*compptr->h_samp_factor/dinfo->max_h_samp_factor;
   1812 		ph[i]=PAD(dinfo->output_height, dinfo->max_v_samp_factor)
   1813 			*compptr->v_samp_factor/dinfo->max_v_samp_factor;
   1814 		if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1;
   1815 		th[i]=compptr->v_samp_factor*dctsize;
   1816 		tmpbufsize+=iw[i]*th[i];
   1817 		if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]))==NULL)
   1818 			_throw("tjDecompressToYUVPlanes(): Memory allocation failure");
   1819 		ptr=dstPlanes[i];
   1820 		for(row=0; row<ph[i]; row++)
   1821 		{
   1822 			outbuf[i][row]=ptr;
   1823 			ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
   1824 		}
   1825 	}
   1826 	if(usetmpbuf)
   1827 	{
   1828 		if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
   1829 			_throw("tjDecompressToYUVPlanes(): Memory allocation failure");
   1830 		ptr=_tmpbuf;
   1831 		for(i=0; i<dinfo->num_components; i++)
   1832 		{
   1833 			if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
   1834 				_throw("tjDecompressToYUVPlanes(): Memory allocation failure");
   1835 			for(row=0; row<th[i]; row++)
   1836 			{
   1837 				tmpbuf[i][row]=ptr;
   1838 				ptr+=iw[i];
   1839 			}
   1840 		}
   1841 	}
   1842 
   1843 	if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
   1844 	if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
   1845 	dinfo->raw_data_out=TRUE;
   1846 
   1847 	jpeg_start_decompress(dinfo);
   1848 	for(row=0; row<(int)dinfo->output_height;
   1849 		row+=dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size)
   1850 	{
   1851 		JSAMPARRAY yuvptr[MAX_COMPONENTS];
   1852 		int crow[MAX_COMPONENTS];
   1853 		for(i=0; i<dinfo->num_components; i++)
   1854 		{
   1855 			jpeg_component_info *compptr=&dinfo->comp_info[i];
   1856 			if(jpegSubsamp==TJ_420)
   1857 			{
   1858 				/* When 4:2:0 subsampling is used with IDCT scaling, libjpeg will try
   1859 				   to be clever and use the IDCT to perform upsampling on the U and V
   1860 				   planes.  For instance, if the output image is to be scaled by 1/2
   1861 				   relative to the JPEG image, then the scaling factor and upsampling
   1862 				   effectively cancel each other, so a normal 8x8 IDCT can be used.
   1863 				   However, this is not desirable when using the decompress-to-YUV
   1864 				   functionality in TurboJPEG, since we want to output the U and V
   1865 				   planes in their subsampled form.  Thus, we have to override some
   1866 				   internal libjpeg parameters to force it to use the "scaled" IDCT
   1867 				   functions on the U and V planes. */
   1868 				compptr->_DCT_scaled_size=dctsize;
   1869 				compptr->MCU_sample_width=tjMCUWidth[jpegSubsamp]*
   1870 					sf[sfi].num/sf[sfi].denom*
   1871 					compptr->v_samp_factor/dinfo->max_v_samp_factor;
   1872 				dinfo->idct->inverse_DCT[i] = dinfo->idct->inverse_DCT[0];
   1873 			}
   1874 			crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
   1875 			if(usetmpbuf) yuvptr[i]=tmpbuf[i];
   1876 			else yuvptr[i]=&outbuf[i][crow[i]];
   1877 		}
   1878 		jpeg_read_raw_data(dinfo, yuvptr,
   1879 			dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size);
   1880 		if(usetmpbuf)
   1881 		{
   1882 			int j;
   1883 			for(i=0; i<dinfo->num_components; i++)
   1884 			{
   1885 				for(j=0; j<min(th[i], ph[i]-crow[i]); j++)
   1886 				{
   1887 					memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], pw[i]);
   1888 				}
   1889 			}
   1890 		}
   1891 	}
   1892 	jpeg_finish_decompress(dinfo);
   1893 
   1894 	bailout:
   1895 	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
   1896 	for(i=0; i<MAX_COMPONENTS; i++)
   1897 	{
   1898 		if(tmpbuf[i]) free(tmpbuf[i]);
   1899 		if(outbuf[i]) free(outbuf[i]);
   1900 	}
   1901 	if(_tmpbuf) free(_tmpbuf);
   1902 	if(this->jerr.warning) retval=-1;
   1903 	return retval;
   1904 }
   1905 
   1906 DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle,
   1907 	const unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
   1908 	int width, int pad, int height, int flags)
   1909 {
   1910 	unsigned char *dstPlanes[3];
   1911 	int pw0, ph0, strides[3], retval=-1, jpegSubsamp=-1;
   1912 	int i, jpegwidth, jpegheight, scaledw, scaledh;
   1913 
   1914 	getdinstance(handle);
   1915 
   1916 	if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pad<1
   1917 		|| !isPow2(pad) || height<0)
   1918 		_throw("tjDecompressToYUV2(): Invalid argument");
   1919 
   1920 	if(setjmp(this->jerr.setjmp_buffer))
   1921 	{
   1922 		/* If we get here, the JPEG code has signaled an error. */
   1923 		return -1;
   1924 	}
   1925 
   1926 	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
   1927 	jpeg_read_header(dinfo, TRUE);
   1928 	jpegSubsamp=getSubsamp(dinfo);
   1929 	if(jpegSubsamp<0)
   1930 		_throw("tjDecompressToYUV2(): Could not determine subsampling type for JPEG image");
   1931 
   1932 	jpegwidth=dinfo->image_width;  jpegheight=dinfo->image_height;
   1933 	if(width==0) width=jpegwidth;
   1934 	if(height==0) height=jpegheight;
   1935 
   1936 	for(i=0; i<NUMSF; i++)
   1937 	{
   1938 		scaledw=TJSCALED(jpegwidth, sf[i]);
   1939 		scaledh=TJSCALED(jpegheight, sf[i]);
   1940 		if(scaledw<=width && scaledh<=height)
   1941 			break;
   1942 	}
   1943 	if(i>=NUMSF)
   1944 		_throw("tjDecompressToYUV2(): Could not scale down to desired image dimensions");
   1945 
   1946 	pw0=tjPlaneWidth(0, width, jpegSubsamp);
   1947 	ph0=tjPlaneHeight(0, height, jpegSubsamp);
   1948 	dstPlanes[0]=dstBuf;
   1949 	strides[0]=PAD(pw0, pad);
   1950 	if(jpegSubsamp==TJSAMP_GRAY)
   1951 	{
   1952 		strides[1]=strides[2]=0;
   1953 		dstPlanes[1]=dstPlanes[2]=NULL;
   1954 	}
   1955 	else
   1956 	{
   1957 		int pw1=tjPlaneWidth(1, width, jpegSubsamp);
   1958 		int ph1=tjPlaneHeight(1, height, jpegSubsamp);
   1959 		strides[1]=strides[2]=PAD(pw1, pad);
   1960 		dstPlanes[1]=dstPlanes[0]+strides[0]*ph0;
   1961 		dstPlanes[2]=dstPlanes[1]+strides[1]*ph1;
   1962 	}
   1963 
   1964 	this->headerRead=1;
   1965 	return tjDecompressToYUVPlanes(handle, jpegBuf, jpegSize, dstPlanes, width,
   1966 		strides, height, flags);
   1967 
   1968 	bailout:
   1969 	return retval;
   1970 
   1971 }
   1972 
   1973 DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle,
   1974 	unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
   1975 	int flags)
   1976 {
   1977 	return tjDecompressToYUV2(handle, jpegBuf, jpegSize, dstBuf, 0, 4, 0, flags);
   1978 }
   1979 
   1980 
   1981 /* Transformer */
   1982 
   1983 DLLEXPORT tjhandle DLLCALL tjInitTransform(void)
   1984 {
   1985 	tjinstance *this=NULL;  tjhandle handle=NULL;
   1986 	if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
   1987 	{
   1988 		snprintf(errStr, JMSG_LENGTH_MAX,
   1989 			"tjInitTransform(): Memory allocation failure");
   1990 		return NULL;
   1991 	}
   1992 	MEMZERO(this, sizeof(tjinstance));
   1993 	handle=_tjInitCompress(this);
   1994 	if(!handle) return NULL;
   1995 	handle=_tjInitDecompress(this);
   1996 	return handle;
   1997 }
   1998 
   1999 
   2000 DLLEXPORT int DLLCALL tjTransform(tjhandle handle,
   2001 	const unsigned char *jpegBuf, unsigned long jpegSize, int n,
   2002 	unsigned char **dstBufs, unsigned long *dstSizes, tjtransform *t, int flags)
   2003 {
   2004 	jpeg_transform_info *xinfo=NULL;
   2005 	jvirt_barray_ptr *srccoefs, *dstcoefs;
   2006 	int retval=0, i, jpegSubsamp;
   2007 
   2008 	getinstance(handle);
   2009 	if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0)
   2010 		_throw("tjTransform(): Instance has not been initialized for transformation");
   2011 
   2012 	if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL
   2013 		|| t==NULL || flags<0)
   2014 		_throw("tjTransform(): Invalid argument");
   2015 
   2016 	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
   2017 	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
   2018 	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
   2019 
   2020 	if(setjmp(this->jerr.setjmp_buffer))
   2021 	{
   2022 		/* If we get here, the JPEG code has signaled an error. */
   2023 		retval=-1;
   2024 		goto bailout;
   2025 	}
   2026 
   2027 	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
   2028 
   2029 	if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n))
   2030 		==NULL)
   2031 		_throw("tjTransform(): Memory allocation failure");
   2032 	MEMZERO(xinfo, sizeof(jpeg_transform_info)*n);
   2033 
   2034 	for(i=0; i<n; i++)
   2035 	{
   2036 		xinfo[i].transform=xformtypes[t[i].op];
   2037 		xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0;
   2038 		xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0;
   2039 		xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0;
   2040 		xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0;
   2041 		if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1;
   2042 		else xinfo[i].slow_hflip=0;
   2043 
   2044 		if(xinfo[i].crop)
   2045 		{
   2046 			xinfo[i].crop_xoffset=t[i].r.x;  xinfo[i].crop_xoffset_set=JCROP_POS;
   2047 			xinfo[i].crop_yoffset=t[i].r.y;  xinfo[i].crop_yoffset_set=JCROP_POS;
   2048 			if(t[i].r.w!=0)
   2049 			{
   2050 				xinfo[i].crop_width=t[i].r.w;  xinfo[i].crop_width_set=JCROP_POS;
   2051 			}
   2052 			else xinfo[i].crop_width=JCROP_UNSET;
   2053 			if(t[i].r.h!=0)
   2054 			{
   2055 				xinfo[i].crop_height=t[i].r.h;  xinfo[i].crop_height_set=JCROP_POS;
   2056 			}
   2057 			else xinfo[i].crop_height=JCROP_UNSET;
   2058 		}
   2059 	}
   2060 
   2061 	jcopy_markers_setup(dinfo, JCOPYOPT_ALL);
   2062 	jpeg_read_header(dinfo, TRUE);
   2063 	jpegSubsamp=getSubsamp(dinfo);
   2064 	if(jpegSubsamp<0)
   2065 		_throw("tjTransform(): Could not determine subsampling type for JPEG image");
   2066 
   2067 	for(i=0; i<n; i++)
   2068 	{
   2069 		if(!jtransform_request_workspace(dinfo, &xinfo[i]))
   2070 			_throw("tjTransform(): Transform is not perfect");
   2071 
   2072 		if(xinfo[i].crop)
   2073 		{
   2074 			if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0
   2075 				|| (t[i].r.y%xinfo[i].iMCU_sample_height)!=0)
   2076 			{
   2077 				snprintf(errStr, JMSG_LENGTH_MAX,
   2078 					"To crop this JPEG image, x must be a multiple of %d\n"
   2079 					"and y must be a multiple of %d.\n",
   2080 					xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height);
   2081 				retval=-1;  goto bailout;
   2082 			}
   2083 		}
   2084 	}
   2085 
   2086 	srccoefs=jpeg_read_coefficients(dinfo);
   2087 
   2088 	for(i=0; i<n; i++)
   2089 	{
   2090 		int w, h, alloc=1;
   2091 		if(!xinfo[i].crop)
   2092 		{
   2093 			w=dinfo->image_width;  h=dinfo->image_height;
   2094 		}
   2095 		else
   2096 		{
   2097 			w=xinfo[i].crop_width;  h=xinfo[i].crop_height;
   2098 		}
   2099 		if(flags&TJFLAG_NOREALLOC)
   2100 		{
   2101 			alloc=0;  dstSizes[i]=tjBufSize(w, h, jpegSubsamp);
   2102 		}
   2103 		if(!(t[i].options&TJXOPT_NOOUTPUT))
   2104 			jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc);
   2105 		jpeg_copy_critical_parameters(dinfo, cinfo);
   2106 		dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs,
   2107 			&xinfo[i]);
   2108 		if(!(t[i].options&TJXOPT_NOOUTPUT))
   2109 		{
   2110 			jpeg_write_coefficients(cinfo, dstcoefs);
   2111 			jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL);
   2112 		}
   2113 		else jinit_c_master_control(cinfo, TRUE);
   2114 		jtransform_execute_transformation(dinfo, cinfo, srccoefs,
   2115 			&xinfo[i]);
   2116 		if(t[i].customFilter)
   2117 		{
   2118 			int ci, y;  JDIMENSION by;
   2119 			for(ci=0; ci<cinfo->num_components; ci++)
   2120 			{
   2121 				jpeg_component_info *compptr=&cinfo->comp_info[ci];
   2122 				tjregion arrayRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
   2123 					DCTSIZE};
   2124 				tjregion planeRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
   2125 					compptr->height_in_blocks*DCTSIZE};
   2126 				for(by=0; by<compptr->height_in_blocks; by+=compptr->v_samp_factor)
   2127 				{
   2128 					JBLOCKARRAY barray=(dinfo->mem->access_virt_barray)
   2129 						((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor,
   2130 						TRUE);
   2131 					for(y=0; y<compptr->v_samp_factor; y++)
   2132 					{
   2133 						if(t[i].customFilter(barray[y][0], arrayRegion, planeRegion,
   2134 							ci, i, &t[i])==-1)
   2135 							_throw("tjTransform(): Error in custom filter");
   2136 						arrayRegion.y+=DCTSIZE;
   2137 					}
   2138 				}
   2139 			}
   2140 		}
   2141 		if(!(t[i].options&TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo);
   2142 	}
   2143 
   2144 	jpeg_finish_decompress(dinfo);
   2145 
   2146 	bailout:
   2147 	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
   2148 	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
   2149 	if(xinfo) free(xinfo);
   2150 	if(this->jerr.warning) retval=-1;
   2151 	return retval;
   2152 }
   2153