turbojpeg.c revision 67ce3b2352fe1f7511edbfed74ec6960e41e97dc
19b28defe6ac85dd8a52479cf276606beae24920eDRC/*
29b28defe6ac85dd8a52479cf276606beae24920eDRC * Copyright (C)2009-2011 D. R. Commander.  All Rights Reserved.
32e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC *
49b28defe6ac85dd8a52479cf276606beae24920eDRC * Redistribution and use in source and binary forms, with or without
59b28defe6ac85dd8a52479cf276606beae24920eDRC * modification, are permitted provided that the following conditions are met:
62e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC *
79b28defe6ac85dd8a52479cf276606beae24920eDRC * - Redistributions of source code must retain the above copyright notice,
89b28defe6ac85dd8a52479cf276606beae24920eDRC *   this list of conditions and the following disclaimer.
99b28defe6ac85dd8a52479cf276606beae24920eDRC * - Redistributions in binary form must reproduce the above copyright notice,
109b28defe6ac85dd8a52479cf276606beae24920eDRC *   this list of conditions and the following disclaimer in the documentation
119b28defe6ac85dd8a52479cf276606beae24920eDRC *   and/or other materials provided with the distribution.
129b28defe6ac85dd8a52479cf276606beae24920eDRC * - Neither the name of the libjpeg-turbo Project nor the names of its
139b28defe6ac85dd8a52479cf276606beae24920eDRC *   contributors may be used to endorse or promote products derived from this
149b28defe6ac85dd8a52479cf276606beae24920eDRC *   software without specific prior written permission.
159b28defe6ac85dd8a52479cf276606beae24920eDRC *
169b28defe6ac85dd8a52479cf276606beae24920eDRC * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
179b28defe6ac85dd8a52479cf276606beae24920eDRC * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
189b28defe6ac85dd8a52479cf276606beae24920eDRC * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
199b28defe6ac85dd8a52479cf276606beae24920eDRC * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
209b28defe6ac85dd8a52479cf276606beae24920eDRC * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
219b28defe6ac85dd8a52479cf276606beae24920eDRC * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
229b28defe6ac85dd8a52479cf276606beae24920eDRC * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
239b28defe6ac85dd8a52479cf276606beae24920eDRC * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
249b28defe6ac85dd8a52479cf276606beae24920eDRC * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
259b28defe6ac85dd8a52479cf276606beae24920eDRC * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
269b28defe6ac85dd8a52479cf276606beae24920eDRC * POSSIBILITY OF SUCH DAMAGE.
272e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC */
282e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
299b28defe6ac85dd8a52479cf276606beae24920eDRC/* TurboJPEG/OSS:  this implements the TurboJPEG API using libjpeg-turbo */
302e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
312e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC#include <stdio.h>
322e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC#include <stdlib.h>
33296c71ba0ffb034390a3d0b00a0cc6d6fa014b6eDRC#include <jinclude.h>
34fbb674707e01a61e8b7083faa632dfd46c568b13DRC#define JPEG_INTERNALS
352e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC#include <jpeglib.h>
362e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC#include <jerror.h>
372e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC#include <setjmp.h>
382e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC#include "./turbojpeg.h"
39a29294a94637d4d5efac2b03e115eb69aeeb83d0DRC#include "./tjutil.h"
40890f1e0413b54c40b663208779d4ea9dae20eaefDRC#include "transupp.h"
412a2e451ddc9e3c093a903ccb5a06962d05c21b67DRC
429b28defe6ac85dd8a52479cf276606beae24920eDRCextern void jpeg_mem_dest_tj(j_compress_ptr, unsigned char **,
439b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long *, boolean);
449b28defe6ac85dd8a52479cf276606beae24920eDRCextern void jpeg_mem_src_tj(j_decompress_ptr, unsigned char *, unsigned long);
459b28defe6ac85dd8a52479cf276606beae24920eDRC
46fbb674707e01a61e8b7083faa632dfd46c568b13DRC#define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
472e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
482e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
499b28defe6ac85dd8a52479cf276606beae24920eDRC/* Error handling (based on example in example.c) */
502e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
519b28defe6ac85dd8a52479cf276606beae24920eDRCstatic char errStr[JMSG_LENGTH_MAX]="No error";
522e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
539b28defe6ac85dd8a52479cf276606beae24920eDRCstruct my_error_mgr
542e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
552e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC	struct jpeg_error_mgr pub;
569b28defe6ac85dd8a52479cf276606beae24920eDRC	jmp_buf setjmp_buffer;
579b28defe6ac85dd8a52479cf276606beae24920eDRC};
589b28defe6ac85dd8a52479cf276606beae24920eDRCtypedef struct my_error_mgr *my_error_ptr;
592e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
602e7b76b28c0a872ae6ca002fd32bbba0769f990eDRCstatic void my_error_exit(j_common_ptr cinfo)
612e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
629b28defe6ac85dd8a52479cf276606beae24920eDRC	my_error_ptr myerr=(my_error_ptr)cinfo->err;
632e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC	(*cinfo->err->output_message)(cinfo);
649b28defe6ac85dd8a52479cf276606beae24920eDRC	longjmp(myerr->setjmp_buffer, 1);
652e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
662e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
679b28defe6ac85dd8a52479cf276606beae24920eDRC/* Based on output_message() in jerror.c */
689b28defe6ac85dd8a52479cf276606beae24920eDRC
692e7b76b28c0a872ae6ca002fd32bbba0769f990eDRCstatic void my_output_message(j_common_ptr cinfo)
702e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
719b28defe6ac85dd8a52479cf276606beae24920eDRC	(*cinfo->err->format_message)(cinfo, errStr);
722e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
732e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
742e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
759b28defe6ac85dd8a52479cf276606beae24920eDRC/* Global structures, macros, etc. */
762e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
779b28defe6ac85dd8a52479cf276606beae24920eDRCenum {COMPRESS=1, DECOMPRESS=2};
789b28defe6ac85dd8a52479cf276606beae24920eDRC
799b28defe6ac85dd8a52479cf276606beae24920eDRCtypedef struct _tjinstance
802e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
812e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC	struct jpeg_compress_struct cinfo;
822e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC	struct jpeg_decompress_struct dinfo;
839b28defe6ac85dd8a52479cf276606beae24920eDRC	struct my_error_mgr jerr;
849b28defe6ac85dd8a52479cf276606beae24920eDRC	int init;
859b28defe6ac85dd8a52479cf276606beae24920eDRC} tjinstance;
862e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
87007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRCstatic const int pixelsize[TJ_NUMSAMP]={3, 3, 3, 1, 3};
889b28defe6ac85dd8a52479cf276606beae24920eDRC
89007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRCstatic const JXFORM_CODE xformtypes[TJ_NUMXOP]=
90007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC{
91890f1e0413b54c40b663208779d4ea9dae20eaefDRC	JXFORM_NONE, JXFORM_FLIP_H, JXFORM_FLIP_V, JXFORM_TRANSPOSE,
92890f1e0413b54c40b663208779d4ea9dae20eaefDRC	JXFORM_TRANSVERSE, JXFORM_ROT_90, JXFORM_ROT_180, JXFORM_ROT_270
93890f1e0413b54c40b663208779d4ea9dae20eaefDRC};
949b28defe6ac85dd8a52479cf276606beae24920eDRC
95109a578e89ea8cd2c39d50b012698148dd11dedbDRC#define NUMSF 4
96109a578e89ea8cd2c39d50b012698148dd11dedbDRCstatic const tjscalingfactor sf[NUMSF]={
97109a578e89ea8cd2c39d50b012698148dd11dedbDRC	{1, 1},
98109a578e89ea8cd2c39d50b012698148dd11dedbDRC	{1, 2},
99109a578e89ea8cd2c39d50b012698148dd11dedbDRC	{1, 4},
100109a578e89ea8cd2c39d50b012698148dd11dedbDRC	{1, 8}
101109a578e89ea8cd2c39d50b012698148dd11dedbDRC};
1022e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
103a29294a94637d4d5efac2b03e115eb69aeeb83d0DRC#define _throw(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s", m);  \
104da5220acdd525242bff4e40b1d90324ebb889825DRC	retval=-1;  goto bailout;}
1059b28defe6ac85dd8a52479cf276606beae24920eDRC#define getinstance(handle) tjinstance *this=(tjinstance *)handle;  \
1069b28defe6ac85dd8a52479cf276606beae24920eDRC	j_compress_ptr cinfo=NULL;  j_decompress_ptr dinfo=NULL;  \
1079b28defe6ac85dd8a52479cf276606beae24920eDRC	if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle");  \
1089b28defe6ac85dd8a52479cf276606beae24920eDRC		return -1;}  \
1099b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo=&this->cinfo;  dinfo=&this->dinfo;
1109b28defe6ac85dd8a52479cf276606beae24920eDRC
1119b28defe6ac85dd8a52479cf276606beae24920eDRCstatic int getPixelFormat(int pixelSize, int flags)
1129b28defe6ac85dd8a52479cf276606beae24920eDRC{
11325b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(pixelSize==1) return TJPF_GRAY;
1149b28defe6ac85dd8a52479cf276606beae24920eDRC	if(pixelSize==3)
1159b28defe6ac85dd8a52479cf276606beae24920eDRC	{
11625b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		if(flags&TJ_BGR) return TJPF_BGR;
11725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		else return TJPF_RGB;
1189b28defe6ac85dd8a52479cf276606beae24920eDRC	}
1199b28defe6ac85dd8a52479cf276606beae24920eDRC	if(pixelSize==4)
1209b28defe6ac85dd8a52479cf276606beae24920eDRC	{
1219b28defe6ac85dd8a52479cf276606beae24920eDRC		if(flags&TJ_ALPHAFIRST)
1229b28defe6ac85dd8a52479cf276606beae24920eDRC		{
12325b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC			if(flags&TJ_BGR) return TJPF_XBGR;
12425b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC			else return TJPF_XRGB;
1259b28defe6ac85dd8a52479cf276606beae24920eDRC		}
1269b28defe6ac85dd8a52479cf276606beae24920eDRC		else
1279b28defe6ac85dd8a52479cf276606beae24920eDRC		{
12825b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC			if(flags&TJ_BGR) return TJPF_BGRX;
12925b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC			else return TJPF_RGBX;
1309b28defe6ac85dd8a52479cf276606beae24920eDRC		}
1319b28defe6ac85dd8a52479cf276606beae24920eDRC	}
1329b28defe6ac85dd8a52479cf276606beae24920eDRC	return -1;
1339b28defe6ac85dd8a52479cf276606beae24920eDRC}
1349b28defe6ac85dd8a52479cf276606beae24920eDRC
135f12bb305c26a25eb76d4e3d73651ef927b352c2bDRCstatic int setCompDefaults(struct jpeg_compress_struct *cinfo,
1369b28defe6ac85dd8a52479cf276606beae24920eDRC	int pixelFormat, int subsamp, int jpegQual)
1379b28defe6ac85dd8a52479cf276606beae24920eDRC{
138f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC	int retval=0;
139f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC
1409b28defe6ac85dd8a52479cf276606beae24920eDRC	switch(pixelFormat)
1419b28defe6ac85dd8a52479cf276606beae24920eDRC	{
14225b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_GRAY:
1439b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_GRAYSCALE;  break;
1449b28defe6ac85dd8a52479cf276606beae24920eDRC		#if JCS_EXTENSIONS==1
14525b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGB:
1469b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_RGB;  break;
14725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_BGR:
1489b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_BGR;  break;
14925b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGBX:
15067ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		case TJPF_RGBA:
1519b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_RGBX;  break;
15225b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_BGRX:
15367ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		case TJPF_BGRA:
1549b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_BGRX;  break;
15525b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_XRGB:
15667ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		case TJPF_ARGB:
1579b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_XRGB;  break;
15825b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_XBGR:
15967ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		case TJPF_ABGR:
1609b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_XBGR;  break;
1619b28defe6ac85dd8a52479cf276606beae24920eDRC		#else
16225b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGB:
1639b28defe6ac85dd8a52479cf276606beae24920eDRC			if(RGB_RED==0 && RGB_GREEN==1 && RGB_BLUE==2 && RGB_PIXELSIZE==3)
1649b28defe6ac85dd8a52479cf276606beae24920eDRC			{
1659b28defe6ac85dd8a52479cf276606beae24920eDRC				cinfo->in_color_space=JCS_RGB;  break;
1669b28defe6ac85dd8a52479cf276606beae24920eDRC			}
1679b28defe6ac85dd8a52479cf276606beae24920eDRC		default:
1689b28defe6ac85dd8a52479cf276606beae24920eDRC			_throw("Unsupported pixel format");
1699b28defe6ac85dd8a52479cf276606beae24920eDRC		#endif
1709b28defe6ac85dd8a52479cf276606beae24920eDRC	}
1719b28defe6ac85dd8a52479cf276606beae24920eDRC
1729b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->input_components=tjPixelSize[pixelFormat];
1739b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_set_defaults(cinfo);
1749b28defe6ac85dd8a52479cf276606beae24920eDRC	if(jpegQual>=0)
1759b28defe6ac85dd8a52479cf276606beae24920eDRC	{
1769b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_set_quality(cinfo, jpegQual, TRUE);
1779b28defe6ac85dd8a52479cf276606beae24920eDRC		if(jpegQual>=96) cinfo->dct_method=JDCT_ISLOW;
1789b28defe6ac85dd8a52479cf276606beae24920eDRC		else cinfo->dct_method=JDCT_FASTEST;
1799b28defe6ac85dd8a52479cf276606beae24920eDRC	}
18025b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(subsamp==TJSAMP_GRAY)
1819b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
1829b28defe6ac85dd8a52479cf276606beae24920eDRC	else
1839b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_set_colorspace(cinfo, JCS_YCbCr);
1849b28defe6ac85dd8a52479cf276606beae24920eDRC
1859b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[0].h_samp_factor=tjMCUWidth[subsamp]/8;
1869b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[1].h_samp_factor=1;
1879b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[2].h_samp_factor=1;
1889b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[0].v_samp_factor=tjMCUHeight[subsamp]/8;
1899b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[1].v_samp_factor=1;
1909b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[2].v_samp_factor=1;
191f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC
192f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC	#if JCS_EXTENSIONS!=1
193f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC	bailout:
194f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC	#endif
195f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC	return retval;
1969b28defe6ac85dd8a52479cf276606beae24920eDRC}
1979b28defe6ac85dd8a52479cf276606beae24920eDRC
198f12bb305c26a25eb76d4e3d73651ef927b352c2bDRCstatic int setDecompDefaults(struct jpeg_decompress_struct *dinfo,
1999b28defe6ac85dd8a52479cf276606beae24920eDRC	int pixelFormat)
2009b28defe6ac85dd8a52479cf276606beae24920eDRC{
201f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC	int retval=0;
202f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC
2039b28defe6ac85dd8a52479cf276606beae24920eDRC	switch(pixelFormat)
2049b28defe6ac85dd8a52479cf276606beae24920eDRC	{
20525b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_GRAY:
2069b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_GRAYSCALE;  break;
2079b28defe6ac85dd8a52479cf276606beae24920eDRC		#if JCS_EXTENSIONS==1
20825b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGB:
2099b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_RGB;  break;
21025b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_BGR:
2119b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_BGR;  break;
21225b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGBX:
2139b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_RGBX;  break;
21425b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_BGRX:
2159b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_BGRX;  break;
21625b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_XRGB:
2179b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_XRGB;  break;
21825b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_XBGR:
2199b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_XBGR;  break;
22067ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		#if JCS_ALPHA_EXTENSIONS==1
22167ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		case TJPF_RGBA:
22267ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC			dinfo->out_color_space=JCS_EXT_RGBA;  break;
22367ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		case TJPF_BGRA:
22467ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC			dinfo->out_color_space=JCS_EXT_BGRA;  break;
22567ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		case TJPF_ARGB:
22667ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC			dinfo->out_color_space=JCS_EXT_ARGB;  break;
22767ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		case TJPF_ABGR:
22867ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC			dinfo->out_color_space=JCS_EXT_ABGR;  break;
22967ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		#endif
2309b28defe6ac85dd8a52479cf276606beae24920eDRC		#else
23125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGB:
2329b28defe6ac85dd8a52479cf276606beae24920eDRC			if(RGB_RED==0 && RGB_GREEN==1 && RGB_BLUE==2 && RGB_PIXELSIZE==3)
2339b28defe6ac85dd8a52479cf276606beae24920eDRC			{
2349b28defe6ac85dd8a52479cf276606beae24920eDRC				dinfo->out_color_space=JCS_RGB;  break;
2359b28defe6ac85dd8a52479cf276606beae24920eDRC			}
23667ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		#endif
2379b28defe6ac85dd8a52479cf276606beae24920eDRC		default:
2389b28defe6ac85dd8a52479cf276606beae24920eDRC			_throw("Unsupported pixel format");
2399b28defe6ac85dd8a52479cf276606beae24920eDRC	}
240f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC
241f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC	bailout:
242f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC	return retval;
2439b28defe6ac85dd8a52479cf276606beae24920eDRC}
2442e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
2452e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
2469b49f0e4c77c727648c6d3a4915eefdf5436de4aDRCstatic int getSubsamp(j_decompress_ptr dinfo)
2479b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC{
2489b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	int retval=-1, i, k;
2499b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	for(i=0; i<NUMSUBOPT; i++)
2509b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	{
2519b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC		if(dinfo->num_components==pixelsize[i])
2529b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC		{
2539b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC			if(dinfo->comp_info[0].h_samp_factor==tjMCUWidth[i]/8
2549b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC				&& dinfo->comp_info[0].v_samp_factor==tjMCUHeight[i]/8)
2559b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC			{
2569b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC				int match=0;
2579b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC				for(k=1; k<dinfo->num_components; k++)
2589b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC				{
2599b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC					if(dinfo->comp_info[k].h_samp_factor==1
2609b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC						&& dinfo->comp_info[k].v_samp_factor==1)
2619b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC						match++;
2629b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC				}
2639b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC				if(match==dinfo->num_components-1)
2649b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC				{
2659b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC					retval=i;  break;
2669b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC				}
2679b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC			}
2689b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC		}
2699b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	}
2709b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	return retval;
2719b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC}
2729b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC
2739b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC
2749b28defe6ac85dd8a52479cf276606beae24920eDRC/* General API functions */
2752e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
2769b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT char* DLLCALL tjGetErrorStr(void)
2772e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
2789b28defe6ac85dd8a52479cf276606beae24920eDRC	return errStr;
2792e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
2802e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
2819b28defe6ac85dd8a52479cf276606beae24920eDRC
2829b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjDestroy(tjhandle handle)
2832e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
2849b28defe6ac85dd8a52479cf276606beae24920eDRC	getinstance(handle);
2859b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer)) return -1;
2869b28defe6ac85dd8a52479cf276606beae24920eDRC	if(this->init&COMPRESS) jpeg_destroy_compress(cinfo);
2879b28defe6ac85dd8a52479cf276606beae24920eDRC	if(this->init&DECOMPRESS) jpeg_destroy_decompress(dinfo);
2889b28defe6ac85dd8a52479cf276606beae24920eDRC	free(this);
2899b28defe6ac85dd8a52479cf276606beae24920eDRC	return 0;
2902e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
2912e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
2929b28defe6ac85dd8a52479cf276606beae24920eDRC
2936b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC/* These are exposed mainly because Windows can't malloc() and free() across
2946b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC   DLL boundaries except when the CRT DLL is used, and we don't use the CRT DLL
2956b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC   with turbojpeg.dll for compatibility reasons.  However, these functions
2966b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC   can potentially be used for other purposes by different implementations. */
2976b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC
2986b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRCDLLEXPORT void DLLCALL tjFree(unsigned char *buf)
2996b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC{
3006b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC	if(buf) free(buf);
3016b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC}
3026b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC
3036b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC
3046b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRCDLLEXPORT unsigned char *DLLCALL tjAlloc(int bytes)
3056b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC{
3066b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC	return (unsigned char *)malloc(bytes);
3076b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC}
3086b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC
3096b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC
3109b28defe6ac85dd8a52479cf276606beae24920eDRC/* Compressor  */
3119b28defe6ac85dd8a52479cf276606beae24920eDRC
3129b28defe6ac85dd8a52479cf276606beae24920eDRCstatic tjhandle _tjInitCompress(tjinstance *this)
3132e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
3149b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned char buffer[1], *buf=buffer;  unsigned long size=1;
3159b28defe6ac85dd8a52479cf276606beae24920eDRC
3169b28defe6ac85dd8a52479cf276606beae24920eDRC	/* This is also straight out of example.c */
3179b28defe6ac85dd8a52479cf276606beae24920eDRC	this->cinfo.err=jpeg_std_error(&this->jerr.pub);
3189b28defe6ac85dd8a52479cf276606beae24920eDRC	this->jerr.pub.error_exit=my_error_exit;
3199b28defe6ac85dd8a52479cf276606beae24920eDRC	this->jerr.pub.output_message=my_output_message;
3202e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
3219b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
3229b28defe6ac85dd8a52479cf276606beae24920eDRC	{
3239b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
3249b28defe6ac85dd8a52479cf276606beae24920eDRC		if(this) free(this);  return NULL;
325efa4ddcc88783c7b8bf5cba42c6680132eefa628DRC	}
3262e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
3279b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_create_compress(&this->cinfo);
3289b28defe6ac85dd8a52479cf276606beae24920eDRC	/* Make an initial call so it will create the destination manager */
3299b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_dest_tj(&this->cinfo, &buf, &size, 0);
3302e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
331007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	this->init|=COMPRESS;
3329b28defe6ac85dd8a52479cf276606beae24920eDRC	return (tjhandle)this;
3332e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
3342e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
335890f1e0413b54c40b663208779d4ea9dae20eaefDRCDLLEXPORT tjhandle DLLCALL tjInitCompress(void)
336890f1e0413b54c40b663208779d4ea9dae20eaefDRC{
3379b28defe6ac85dd8a52479cf276606beae24920eDRC	tjinstance *this=NULL;
3389b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
339da5220acdd525242bff4e40b1d90324ebb889825DRC	{
340007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		snprintf(errStr, JMSG_LENGTH_MAX,
341007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			"tjInitCompress(): Memory allocation failure");
342da5220acdd525242bff4e40b1d90324ebb889825DRC		return NULL;
343da5220acdd525242bff4e40b1d90324ebb889825DRC	}
344007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	MEMZERO(this, sizeof(tjinstance));
3459b28defe6ac85dd8a52479cf276606beae24920eDRC	return _tjInitCompress(this);
346890f1e0413b54c40b663208779d4ea9dae20eaefDRC}
347890f1e0413b54c40b663208779d4ea9dae20eaefDRC
348842416034561f6d5320165a4fe98825e999a4a37DRC
3499b49f0e4c77c727648c6d3a4915eefdf5436de4aDRCDLLEXPORT unsigned long DLLCALL tjBufSize(int width, int height,
3509b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	int jpegSubsamp)
3519b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC{
3529b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	unsigned long retval=0;  int mcuw, mcuh, chromasf;
3539b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	if(width<1 || height<1 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT)
3549b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC		_throw("tjBufSize(): Invalid argument");
3559b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC
3569b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	// This allows for rare corner cases in which a JPEG image can actually be
3579b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	// larger than the uncompressed input (we wouldn't mention it if it hadn't
3589b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	// happened before.)
3599b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	mcuw=tjMCUWidth[jpegSubsamp];
3609b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	mcuh=tjMCUHeight[jpegSubsamp];
3619b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	chromasf=jpegSubsamp==TJSAMP_GRAY? 0: 4*64/(mcuw*mcuh);
3629b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	retval=PAD(width, mcuw) * PAD(height, mcuh) * (2 + chromasf) + 2048;
3639b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC
3649b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	bailout:
3659b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	return retval;
3669b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC}
3679b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC
3689b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC
3692e7b76b28c0a872ae6ca002fd32bbba0769f990eDRCDLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
3702e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
371f3cf973e8e51e0078f402ca5547c026967c27321DRC	unsigned long retval=0;
372f3cf973e8e51e0078f402ca5547c026967c27321DRC	if(width<1 || height<1)
373007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("TJBUFSIZE(): Invalid argument");
374f3cf973e8e51e0078f402ca5547c026967c27321DRC
375f3cf973e8e51e0078f402ca5547c026967c27321DRC	// This allows for rare corner cases in which a JPEG image can actually be
376f3cf973e8e51e0078f402ca5547c026967c27321DRC	// larger than the uncompressed input (we wouldn't mention it if it hadn't
377b28fc5710a510410d2b498255a423dd62b353b3aDRC	// happened before.)
378007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	retval=PAD(width, 16) * PAD(height, 16) * 6 + 2048;
379f3cf973e8e51e0078f402ca5547c026967c27321DRC
380f3cf973e8e51e0078f402ca5547c026967c27321DRC	bailout:
381f3cf973e8e51e0078f402ca5547c026967c27321DRC	return retval;
382f3cf973e8e51e0078f402ca5547c026967c27321DRC}
383f3cf973e8e51e0078f402ca5547c026967c27321DRC
384842416034561f6d5320165a4fe98825e999a4a37DRC
3859b49f0e4c77c727648c6d3a4915eefdf5436de4aDRCDLLEXPORT unsigned long DLLCALL tjBufSizeYUV(int width, int height,
386f3cf973e8e51e0078f402ca5547c026967c27321DRC	int subsamp)
387f3cf973e8e51e0078f402ca5547c026967c27321DRC{
388f3cf973e8e51e0078f402ca5547c026967c27321DRC	unsigned long retval=0;
389f3cf973e8e51e0078f402ca5547c026967c27321DRC	int pw, ph, cw, ch;
390f3cf973e8e51e0078f402ca5547c026967c27321DRC	if(width<1 || height<1 || subsamp<0 || subsamp>=NUMSUBOPT)
3919b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC		_throw("tjBufSizeYUV(): Invalid argument");
3929b28defe6ac85dd8a52479cf276606beae24920eDRC	pw=PAD(width, tjMCUWidth[subsamp]/8);
3939b28defe6ac85dd8a52479cf276606beae24920eDRC	ph=PAD(height, tjMCUHeight[subsamp]/8);
3949b28defe6ac85dd8a52479cf276606beae24920eDRC	cw=pw*8/tjMCUWidth[subsamp];  ch=ph*8/tjMCUHeight[subsamp];
39525b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	retval=PAD(pw, 4)*ph + (subsamp==TJSAMP_GRAY? 0:PAD(cw, 4)*ch*2);
396f3cf973e8e51e0078f402ca5547c026967c27321DRC
397f3cf973e8e51e0078f402ca5547c026967c27321DRC	bailout:
398f3cf973e8e51e0078f402ca5547c026967c27321DRC	return retval;
3992e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
4002e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
401842416034561f6d5320165a4fe98825e999a4a37DRC
4029b49f0e4c77c727648c6d3a4915eefdf5436de4aDRCDLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
4039b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	int subsamp)
4049b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC{
4059b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	return tjBufSizeYUV(width, height, subsamp);
4069b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC}
4079b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC
4089b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC
4099b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf,
4109b28defe6ac85dd8a52479cf276606beae24920eDRC	int width, int pitch, int height, int pixelFormat, unsigned char **jpegBuf,
4119b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
4129b28defe6ac85dd8a52479cf276606beae24920eDRC{
413ff78e37595c8462f64fd100f928aa1d08539527eDRC	int i, retval=0, alloc=1;  JSAMPROW *row_pointer=NULL;
4149b28defe6ac85dd8a52479cf276606beae24920eDRC
4159b28defe6ac85dd8a52479cf276606beae24920eDRC	getinstance(handle)
4169b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this->init&COMPRESS)==0)
417007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjCompress2(): Instance has not been initialized for compression");
4189b28defe6ac85dd8a52479cf276606beae24920eDRC
4199b28defe6ac85dd8a52479cf276606beae24920eDRC	if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
4209b28defe6ac85dd8a52479cf276606beae24920eDRC		|| pixelFormat>=TJ_NUMPF || jpegBuf==NULL || jpegSize==NULL
4219b28defe6ac85dd8a52479cf276606beae24920eDRC		|| jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT || jpegQual<0 || jpegQual>100)
422007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjCompress2(): Invalid argument");
4239b28defe6ac85dd8a52479cf276606beae24920eDRC
4249b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
4259b28defe6ac85dd8a52479cf276606beae24920eDRC	{
4269b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
4279b28defe6ac85dd8a52479cf276606beae24920eDRC		retval=-1;
4289b28defe6ac85dd8a52479cf276606beae24920eDRC		goto bailout;
4299b28defe6ac85dd8a52479cf276606beae24920eDRC	}
4309b28defe6ac85dd8a52479cf276606beae24920eDRC
4319b28defe6ac85dd8a52479cf276606beae24920eDRC	if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
4329b28defe6ac85dd8a52479cf276606beae24920eDRC
4339b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->image_width=width;
4349b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->image_height=height;
4359b28defe6ac85dd8a52479cf276606beae24920eDRC
43625b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
43725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
43825b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
4399b28defe6ac85dd8a52479cf276606beae24920eDRC
440ff78e37595c8462f64fd100f928aa1d08539527eDRC	if(flags&TJFLAG_NOREALLOC)
441ff78e37595c8462f64fd100f928aa1d08539527eDRC	{
4429b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC		alloc=0;  *jpegSize=tjBufSize(width, height, jpegSubsamp);
443ff78e37595c8462f64fd100f928aa1d08539527eDRC	}
444ff78e37595c8462f64fd100f928aa1d08539527eDRC	jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
445f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC	if(setCompDefaults(cinfo, pixelFormat, jpegSubsamp, jpegQual)==-1)
446f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC		return -1;
4479b28defe6ac85dd8a52479cf276606beae24920eDRC
4489b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_start_compress(cinfo, TRUE);
4499b28defe6ac85dd8a52479cf276606beae24920eDRC	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
450007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjCompress2(): Memory allocation failure");
4519b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<height; i++)
4529b28defe6ac85dd8a52479cf276606beae24920eDRC	{
45325b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
4549b28defe6ac85dd8a52479cf276606beae24920eDRC		else row_pointer[i]=&srcBuf[i*pitch];
4559b28defe6ac85dd8a52479cf276606beae24920eDRC	}
4569b28defe6ac85dd8a52479cf276606beae24920eDRC	while(cinfo->next_scanline<cinfo->image_height)
4579b28defe6ac85dd8a52479cf276606beae24920eDRC	{
4589b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_write_scanlines(cinfo, &row_pointer[cinfo->next_scanline],
4599b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->image_height-cinfo->next_scanline);
4609b28defe6ac85dd8a52479cf276606beae24920eDRC	}
4619b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_finish_compress(cinfo);
4629b28defe6ac85dd8a52479cf276606beae24920eDRC
4639b28defe6ac85dd8a52479cf276606beae24920eDRC	bailout:
4649b28defe6ac85dd8a52479cf276606beae24920eDRC	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
4659b28defe6ac85dd8a52479cf276606beae24920eDRC	if(row_pointer) free(row_pointer);
4669b28defe6ac85dd8a52479cf276606beae24920eDRC	return retval;
4679b28defe6ac85dd8a52479cf276606beae24920eDRC}
4689b28defe6ac85dd8a52479cf276606beae24920eDRC
4699b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjCompress(tjhandle handle, unsigned char *srcBuf,
4709b28defe6ac85dd8a52479cf276606beae24920eDRC	int width, int pitch, int height, int pixelSize, unsigned char *jpegBuf,
4719b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
4729b28defe6ac85dd8a52479cf276606beae24920eDRC{
4739b28defe6ac85dd8a52479cf276606beae24920eDRC	int retval=0;  unsigned long size;
4749b28defe6ac85dd8a52479cf276606beae24920eDRC	if(flags&TJ_YUV)
4759b28defe6ac85dd8a52479cf276606beae24920eDRC	{
4769b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC		size=tjBufSizeYUV(width, height, jpegSubsamp);
4779b28defe6ac85dd8a52479cf276606beae24920eDRC		retval=tjEncodeYUV2(handle, srcBuf, width, pitch, height,
4789b28defe6ac85dd8a52479cf276606beae24920eDRC			getPixelFormat(pixelSize, flags), jpegBuf, jpegSubsamp, flags);
4799b28defe6ac85dd8a52479cf276606beae24920eDRC	}
4809b28defe6ac85dd8a52479cf276606beae24920eDRC	else
4819b28defe6ac85dd8a52479cf276606beae24920eDRC	{
4829b28defe6ac85dd8a52479cf276606beae24920eDRC		retval=tjCompress2(handle, srcBuf, width, pitch, height,
4839b28defe6ac85dd8a52479cf276606beae24920eDRC			getPixelFormat(pixelSize, flags), &jpegBuf, &size, jpegSubsamp, jpegQual,
48425b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC			flags|TJFLAG_NOREALLOC);
4859b28defe6ac85dd8a52479cf276606beae24920eDRC	}
4869b28defe6ac85dd8a52479cf276606beae24920eDRC	*jpegSize=size;
4879b28defe6ac85dd8a52479cf276606beae24920eDRC	return retval;
4889b28defe6ac85dd8a52479cf276606beae24920eDRC}
4899b28defe6ac85dd8a52479cf276606beae24920eDRC
4909b28defe6ac85dd8a52479cf276606beae24920eDRC
4919b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
4929b28defe6ac85dd8a52479cf276606beae24920eDRC	int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
4939b28defe6ac85dd8a52479cf276606beae24920eDRC	int subsamp, int flags)
4942e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
49591e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	int i, retval=0;  JSAMPROW *row_pointer=NULL;
496fbb674707e01a61e8b7083faa632dfd46c568b13DRC	JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS];
497fbb674707e01a61e8b7083faa632dfd46c568b13DRC	JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
498fbb674707e01a61e8b7083faa632dfd46c568b13DRC	JSAMPROW *outbuf[MAX_COMPONENTS];
4999b28defe6ac85dd8a52479cf276606beae24920eDRC	int row, pw, ph, cw[MAX_COMPONENTS], ch[MAX_COMPONENTS];
5009b28defe6ac85dd8a52479cf276606beae24920eDRC	JSAMPLE *ptr=dstBuf;
5019b28defe6ac85dd8a52479cf276606beae24920eDRC  unsigned long yuvsize=0;
5029b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_component_info *compptr;
5032e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5049b28defe6ac85dd8a52479cf276606beae24920eDRC	getinstance(handle);
5059b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this->init&COMPRESS)==0)
506007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjEncodeYUV2(): Instance has not been initialized for compression");
5072e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
508fbb674707e01a61e8b7083faa632dfd46c568b13DRC	for(i=0; i<MAX_COMPONENTS; i++)
509fbb674707e01a61e8b7083faa632dfd46c568b13DRC	{
510fbb674707e01a61e8b7083faa632dfd46c568b13DRC		tmpbuf[i]=NULL;  _tmpbuf[i]=NULL;
511fbb674707e01a61e8b7083faa632dfd46c568b13DRC		tmpbuf2[i]=NULL;  _tmpbuf2[i]=NULL;  outbuf[i]=NULL;
512fbb674707e01a61e8b7083faa632dfd46c568b13DRC	}
513fbb674707e01a61e8b7083faa632dfd46c568b13DRC
5149b28defe6ac85dd8a52479cf276606beae24920eDRC	if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
5159b28defe6ac85dd8a52479cf276606beae24920eDRC		|| pixelFormat>=TJ_NUMPF || dstBuf==NULL || subsamp<0
5169b28defe6ac85dd8a52479cf276606beae24920eDRC		|| subsamp>=NUMSUBOPT)
5179b28defe6ac85dd8a52479cf276606beae24920eDRC		_throw("tjEncodeYUV2(): Invalid argument");
5182e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5199b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
5209b28defe6ac85dd8a52479cf276606beae24920eDRC	{
5219b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
52291e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC		retval=-1;
52391e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC		goto bailout;
524efa4ddcc88783c7b8bf5cba42c6680132eefa628DRC	}
5252e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5269b28defe6ac85dd8a52479cf276606beae24920eDRC	if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
5272e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5289b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->image_width=width;
5299b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->image_height=height;
5302e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
53125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
53225b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
53325b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
5342e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5359b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	yuvsize=tjBufSizeYUV(width, height, subsamp);
5369b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_dest_tj(cinfo, &dstBuf, &yuvsize, 0);
537f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC	if(setCompDefaults(cinfo, pixelFormat, subsamp, -1)==-1) return -1;
5382e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5399b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_start_compress(cinfo, TRUE);
5409b28defe6ac85dd8a52479cf276606beae24920eDRC	pw=PAD(width, cinfo->max_h_samp_factor);
5419b28defe6ac85dd8a52479cf276606beae24920eDRC	ph=PAD(height, cinfo->max_v_samp_factor);
5429b28defe6ac85dd8a52479cf276606beae24920eDRC
5439b28defe6ac85dd8a52479cf276606beae24920eDRC	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph))==NULL)
544007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjEncodeYUV2(): Memory allocation failure");
5459b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<height; i++)
5462e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC	{
54725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
5489b28defe6ac85dd8a52479cf276606beae24920eDRC		else row_pointer[i]=&srcBuf[i*pitch];
5499b28defe6ac85dd8a52479cf276606beae24920eDRC	}
5509b28defe6ac85dd8a52479cf276606beae24920eDRC	if(height<ph)
5519b28defe6ac85dd8a52479cf276606beae24920eDRC		for(i=height; i<ph; i++) row_pointer[i]=row_pointer[height-1];
552fbb674707e01a61e8b7083faa632dfd46c568b13DRC
5539b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<cinfo->num_components; i++)
5549b28defe6ac85dd8a52479cf276606beae24920eDRC	{
5559b28defe6ac85dd8a52479cf276606beae24920eDRC		compptr=&cinfo->comp_info[i];
5569b28defe6ac85dd8a52479cf276606beae24920eDRC		_tmpbuf[i]=(JSAMPLE *)malloc(
5579b28defe6ac85dd8a52479cf276606beae24920eDRC			PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
5589b28defe6ac85dd8a52479cf276606beae24920eDRC				/compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
559007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		if(!_tmpbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
5609b28defe6ac85dd8a52479cf276606beae24920eDRC		tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
561007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		if(!tmpbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
5629b28defe6ac85dd8a52479cf276606beae24920eDRC		for(row=0; row<cinfo->max_v_samp_factor; row++)
563fbb674707e01a61e8b7083faa632dfd46c568b13DRC		{
5649b28defe6ac85dd8a52479cf276606beae24920eDRC			unsigned char *_tmpbuf_aligned=
5659b28defe6ac85dd8a52479cf276606beae24920eDRC				(unsigned char *)PAD((size_t)_tmpbuf[i], 16);
5669b28defe6ac85dd8a52479cf276606beae24920eDRC			tmpbuf[i][row]=&_tmpbuf_aligned[
567fbb674707e01a61e8b7083faa632dfd46c568b13DRC				PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
5689b28defe6ac85dd8a52479cf276606beae24920eDRC					/compptr->h_samp_factor, 16) * row];
569fbb674707e01a61e8b7083faa632dfd46c568b13DRC		}
5709b28defe6ac85dd8a52479cf276606beae24920eDRC		_tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
5719b28defe6ac85dd8a52479cf276606beae24920eDRC			* compptr->v_samp_factor + 16);
572007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		if(!_tmpbuf2[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
5739b28defe6ac85dd8a52479cf276606beae24920eDRC		tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
574007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		if(!tmpbuf2[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
5759b28defe6ac85dd8a52479cf276606beae24920eDRC		for(row=0; row<compptr->v_samp_factor; row++)
576fbb674707e01a61e8b7083faa632dfd46c568b13DRC		{
5779b28defe6ac85dd8a52479cf276606beae24920eDRC			unsigned char *_tmpbuf2_aligned=
5789b28defe6ac85dd8a52479cf276606beae24920eDRC				(unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
5799b28defe6ac85dd8a52479cf276606beae24920eDRC			tmpbuf2[i][row]=&_tmpbuf2_aligned[
5809b28defe6ac85dd8a52479cf276606beae24920eDRC				PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
581fbb674707e01a61e8b7083faa632dfd46c568b13DRC		}
5829b28defe6ac85dd8a52479cf276606beae24920eDRC		cw[i]=pw*compptr->h_samp_factor/cinfo->max_h_samp_factor;
5839b28defe6ac85dd8a52479cf276606beae24920eDRC		ch[i]=ph*compptr->v_samp_factor/cinfo->max_v_samp_factor;
5849b28defe6ac85dd8a52479cf276606beae24920eDRC		outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]);
585007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		if(!outbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
5869b28defe6ac85dd8a52479cf276606beae24920eDRC		for(row=0; row<ch[i]; row++)
587fbb674707e01a61e8b7083faa632dfd46c568b13DRC		{
5889b28defe6ac85dd8a52479cf276606beae24920eDRC			outbuf[i][row]=ptr;
5899b28defe6ac85dd8a52479cf276606beae24920eDRC			ptr+=PAD(cw[i], 4);
590fbb674707e01a61e8b7083faa632dfd46c568b13DRC		}
5916ee54594591d0ae958b81adc8ba3cacde522e5e3DRC	}
5929b28defe6ac85dd8a52479cf276606beae24920eDRC	if(yuvsize!=(unsigned long)(ptr-dstBuf))
5939b28defe6ac85dd8a52479cf276606beae24920eDRC		_throw("tjEncodeYUV2(): Generated image is not the correct size");
5949b28defe6ac85dd8a52479cf276606beae24920eDRC
5959b28defe6ac85dd8a52479cf276606beae24920eDRC	for(row=0; row<ph; row+=cinfo->max_v_samp_factor)
5969b28defe6ac85dd8a52479cf276606beae24920eDRC	{
5979b28defe6ac85dd8a52479cf276606beae24920eDRC		(*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0,
5989b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->max_v_samp_factor);
5999b28defe6ac85dd8a52479cf276606beae24920eDRC		(cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
6009b28defe6ac85dd8a52479cf276606beae24920eDRC		for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++)
6019b28defe6ac85dd8a52479cf276606beae24920eDRC			jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
6029b28defe6ac85dd8a52479cf276606beae24920eDRC				row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
6039b28defe6ac85dd8a52479cf276606beae24920eDRC				compptr->v_samp_factor, cw[i]);
6049b28defe6ac85dd8a52479cf276606beae24920eDRC	}
6059b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->next_scanline+=height;
6069b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_abort_compress(cinfo);
6072e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
60891e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	bailout:
6099b28defe6ac85dd8a52479cf276606beae24920eDRC	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
6102e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC	if(row_pointer) free(row_pointer);
611fbb674707e01a61e8b7083faa632dfd46c568b13DRC	for(i=0; i<MAX_COMPONENTS; i++)
612fbb674707e01a61e8b7083faa632dfd46c568b13DRC	{
613fbb674707e01a61e8b7083faa632dfd46c568b13DRC		if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
61457423076e6189717441763de3253072dee42ff7eDRC		if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
615fbb674707e01a61e8b7083faa632dfd46c568b13DRC		if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
61657423076e6189717441763de3253072dee42ff7eDRC		if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
617fbb674707e01a61e8b7083faa632dfd46c568b13DRC		if(outbuf[i]!=NULL) free(outbuf[i]);
618fbb674707e01a61e8b7083faa632dfd46c568b13DRC	}
61991e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	return retval;
6202e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
6212e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
6229b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf,
6239b28defe6ac85dd8a52479cf276606beae24920eDRC	int width, int pitch, int height, int pixelSize, unsigned char *dstBuf,
6249b28defe6ac85dd8a52479cf276606beae24920eDRC	int subsamp, int flags)
625842416034561f6d5320165a4fe98825e999a4a37DRC{
6269b28defe6ac85dd8a52479cf276606beae24920eDRC	return tjEncodeYUV2(handle, srcBuf, width, pitch, height,
6279b28defe6ac85dd8a52479cf276606beae24920eDRC		getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags);
628842416034561f6d5320165a4fe98825e999a4a37DRC}
629842416034561f6d5320165a4fe98825e999a4a37DRC
630842416034561f6d5320165a4fe98825e999a4a37DRC
6319b28defe6ac85dd8a52479cf276606beae24920eDRC/* Decompressor */
6322e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
6339b28defe6ac85dd8a52479cf276606beae24920eDRCstatic tjhandle _tjInitDecompress(tjinstance *this)
6342e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
6359b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned char buffer[1];
6362e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
6379b28defe6ac85dd8a52479cf276606beae24920eDRC	/* This is also straight out of example.c */
6389b28defe6ac85dd8a52479cf276606beae24920eDRC	this->dinfo.err=jpeg_std_error(&this->jerr.pub);
6399b28defe6ac85dd8a52479cf276606beae24920eDRC	this->jerr.pub.error_exit=my_error_exit;
6409b28defe6ac85dd8a52479cf276606beae24920eDRC	this->jerr.pub.output_message=my_output_message;
6412e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
6429b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
6439b28defe6ac85dd8a52479cf276606beae24920eDRC	{
6449b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
6459b28defe6ac85dd8a52479cf276606beae24920eDRC		if(this) free(this);  return NULL;
6469e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	}
6472e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
6489b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_create_decompress(&this->dinfo);
6499b28defe6ac85dd8a52479cf276606beae24920eDRC	/* Make an initial call so it will create the source manager */
6509b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_src_tj(&this->dinfo, buffer, 1);
6512e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
652007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	this->init|=DECOMPRESS;
6539b28defe6ac85dd8a52479cf276606beae24920eDRC	return (tjhandle)this;
6542e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
6552e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
656890f1e0413b54c40b663208779d4ea9dae20eaefDRCDLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
657890f1e0413b54c40b663208779d4ea9dae20eaefDRC{
6589b28defe6ac85dd8a52479cf276606beae24920eDRC	tjinstance *this;
6599b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
660da5220acdd525242bff4e40b1d90324ebb889825DRC	{
661007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		snprintf(errStr, JMSG_LENGTH_MAX,
662007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			"tjInitDecompress(): Memory allocation failure");
663da5220acdd525242bff4e40b1d90324ebb889825DRC		return NULL;
664da5220acdd525242bff4e40b1d90324ebb889825DRC	}
665007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	MEMZERO(this, sizeof(tjinstance));
6669b28defe6ac85dd8a52479cf276606beae24920eDRC	return _tjInitDecompress(this);
667890f1e0413b54c40b663208779d4ea9dae20eaefDRC}
668890f1e0413b54c40b663208779d4ea9dae20eaefDRC
6692e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
6709b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle,
6719b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
6729b28defe6ac85dd8a52479cf276606beae24920eDRC	int *jpegSubsamp)
6731fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC{
6749b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	int retval=0;
6751fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
6769b28defe6ac85dd8a52479cf276606beae24920eDRC	getinstance(handle);
6779b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this->init&DECOMPRESS)==0)
678007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompressHeader2(): Instance has not been initialized for decompression");
6791fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
6809b28defe6ac85dd8a52479cf276606beae24920eDRC	if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL
6819b28defe6ac85dd8a52479cf276606beae24920eDRC		|| jpegSubsamp==NULL)
6829b28defe6ac85dd8a52479cf276606beae24920eDRC		_throw("tjDecompressHeader2(): Invalid argument");
6831fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
6849b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
6859b28defe6ac85dd8a52479cf276606beae24920eDRC	{
6869b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
6871fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC		return -1;
6881fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC	}
6891fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
6909b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
6919b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_read_header(dinfo, TRUE);
6921fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
6939b28defe6ac85dd8a52479cf276606beae24920eDRC	*width=dinfo->image_width;
6949b28defe6ac85dd8a52479cf276606beae24920eDRC	*height=dinfo->image_height;
6959b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	*jpegSubsamp=getSubsamp(dinfo);
6961fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
6979b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_abort_decompress(dinfo);
6981fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
6999b28defe6ac85dd8a52479cf276606beae24920eDRC	if(*jpegSubsamp<0)
700007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompressHeader2(): Could not determine subsampling type for JPEG image");
701007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	if(*width<1 || *height<1)
702007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompressHeader2(): Invalid data returned in header");
70391e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC
70491e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	bailout:
70591e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	return retval;
70691e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC}
70791e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC
7089b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle,
7099b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height)
71091e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC{
7119b28defe6ac85dd8a52479cf276606beae24920eDRC	int jpegSubsamp;
7129b28defe6ac85dd8a52479cf276606beae24920eDRC	return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height,
7139b28defe6ac85dd8a52479cf276606beae24920eDRC		&jpegSubsamp);
7141fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC}
7151fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
7161fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
717109a578e89ea8cd2c39d50b012698148dd11dedbDRCDLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors)
718b28fc5710a510410d2b498255a423dd62b353b3aDRC{
719109a578e89ea8cd2c39d50b012698148dd11dedbDRC	if(numscalingfactors==NULL)
720b28fc5710a510410d2b498255a423dd62b353b3aDRC	{
7219b28defe6ac85dd8a52479cf276606beae24920eDRC		snprintf(errStr, JMSG_LENGTH_MAX,
722007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			"tjGetScalingFactors(): Invalid argument");
723109a578e89ea8cd2c39d50b012698148dd11dedbDRC		return NULL;
724b28fc5710a510410d2b498255a423dd62b353b3aDRC	}
725b28fc5710a510410d2b498255a423dd62b353b3aDRC
726109a578e89ea8cd2c39d50b012698148dd11dedbDRC	*numscalingfactors=NUMSF;
727109a578e89ea8cd2c39d50b012698148dd11dedbDRC	return (tjscalingfactor *)sf;
728b28fc5710a510410d2b498255a423dd62b353b3aDRC}
729b28fc5710a510410d2b498255a423dd62b353b3aDRC
730b28fc5710a510410d2b498255a423dd62b353b3aDRC
7319b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, unsigned char *jpegBuf,
7329b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
7339b28defe6ac85dd8a52479cf276606beae24920eDRC	int height, int pixelFormat, int flags)
7349b28defe6ac85dd8a52479cf276606beae24920eDRC{
7359b28defe6ac85dd8a52479cf276606beae24920eDRC	int i, retval=0;  JSAMPROW *row_pointer=NULL;
7369b28defe6ac85dd8a52479cf276606beae24920eDRC	int jpegwidth, jpegheight, scaledw, scaledh;
7379b28defe6ac85dd8a52479cf276606beae24920eDRC
7389b28defe6ac85dd8a52479cf276606beae24920eDRC	getinstance(handle);
7399b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this->init&DECOMPRESS)==0)
740007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompress2(): Instance has not been initialized for decompression");
7419b28defe6ac85dd8a52479cf276606beae24920eDRC
7429b28defe6ac85dd8a52479cf276606beae24920eDRC	if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0
7439b28defe6ac85dd8a52479cf276606beae24920eDRC		|| height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF)
7449b28defe6ac85dd8a52479cf276606beae24920eDRC		_throw("tjDecompress2(): Invalid argument");
7459b28defe6ac85dd8a52479cf276606beae24920eDRC
74625b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
74725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
74825b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
7499b28defe6ac85dd8a52479cf276606beae24920eDRC
7509b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
7519b28defe6ac85dd8a52479cf276606beae24920eDRC	{
7529b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
7539b28defe6ac85dd8a52479cf276606beae24920eDRC		retval=-1;
7549b28defe6ac85dd8a52479cf276606beae24920eDRC		goto bailout;
7559b28defe6ac85dd8a52479cf276606beae24920eDRC	}
7569b28defe6ac85dd8a52479cf276606beae24920eDRC
7579b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
7589b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_read_header(dinfo, TRUE);
759f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC	if(setDecompDefaults(dinfo, pixelFormat)==-1) return -1;
7609b28defe6ac85dd8a52479cf276606beae24920eDRC
76125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
7629b28defe6ac85dd8a52479cf276606beae24920eDRC
7639b28defe6ac85dd8a52479cf276606beae24920eDRC	jpegwidth=dinfo->image_width;  jpegheight=dinfo->image_height;
7649b28defe6ac85dd8a52479cf276606beae24920eDRC	if(width==0) width=jpegwidth;
7659b28defe6ac85dd8a52479cf276606beae24920eDRC	if(height==0) height=jpegheight;
7669b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<NUMSF; i++)
7679b28defe6ac85dd8a52479cf276606beae24920eDRC	{
7689b28defe6ac85dd8a52479cf276606beae24920eDRC		scaledw=TJSCALED(jpegwidth, sf[i]);
7699b28defe6ac85dd8a52479cf276606beae24920eDRC		scaledh=TJSCALED(jpegheight, sf[i]);
7709b28defe6ac85dd8a52479cf276606beae24920eDRC		if(scaledw<=width && scaledh<=height)
7719b28defe6ac85dd8a52479cf276606beae24920eDRC				break;
7729b28defe6ac85dd8a52479cf276606beae24920eDRC	}
7739b28defe6ac85dd8a52479cf276606beae24920eDRC	if(scaledw>width || scaledh>height)
774007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompress2(): Could not scale down to desired image dimensions");
7759b28defe6ac85dd8a52479cf276606beae24920eDRC	width=scaledw;  height=scaledh;
7769b28defe6ac85dd8a52479cf276606beae24920eDRC	dinfo->scale_num=sf[i].num;
7779b28defe6ac85dd8a52479cf276606beae24920eDRC	dinfo->scale_denom=sf[i].denom;
7789b28defe6ac85dd8a52479cf276606beae24920eDRC
7799b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_start_decompress(dinfo);
7809b28defe6ac85dd8a52479cf276606beae24920eDRC	if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
7819b28defe6ac85dd8a52479cf276606beae24920eDRC	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
7829b28defe6ac85dd8a52479cf276606beae24920eDRC		*dinfo->output_height))==NULL)
783007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompress2(): Memory allocation failure");
7849b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<(int)dinfo->output_height; i++)
7859b28defe6ac85dd8a52479cf276606beae24920eDRC	{
78625b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		if(flags&TJFLAG_BOTTOMUP)
7879b28defe6ac85dd8a52479cf276606beae24920eDRC			row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*pitch];
7889b28defe6ac85dd8a52479cf276606beae24920eDRC		else row_pointer[i]=&dstBuf[i*pitch];
7899b28defe6ac85dd8a52479cf276606beae24920eDRC	}
7909b28defe6ac85dd8a52479cf276606beae24920eDRC	while(dinfo->output_scanline<dinfo->output_height)
7919b28defe6ac85dd8a52479cf276606beae24920eDRC	{
7929b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline],
7939b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->output_height-dinfo->output_scanline);
7949b28defe6ac85dd8a52479cf276606beae24920eDRC	}
7959b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_finish_decompress(dinfo);
7969b28defe6ac85dd8a52479cf276606beae24920eDRC
7979b28defe6ac85dd8a52479cf276606beae24920eDRC	bailout:
7989b28defe6ac85dd8a52479cf276606beae24920eDRC	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
7999b28defe6ac85dd8a52479cf276606beae24920eDRC	if(row_pointer) free(row_pointer);
8009b28defe6ac85dd8a52479cf276606beae24920eDRC	return retval;
8019b28defe6ac85dd8a52479cf276606beae24920eDRC}
8029b28defe6ac85dd8a52479cf276606beae24920eDRC
8039b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf,
8049b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
8059b28defe6ac85dd8a52479cf276606beae24920eDRC	int height, int pixelSize, int flags)
8069b28defe6ac85dd8a52479cf276606beae24920eDRC{
8079b28defe6ac85dd8a52479cf276606beae24920eDRC	if(flags&TJ_YUV)
8089b28defe6ac85dd8a52479cf276606beae24920eDRC		return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags);
8099b28defe6ac85dd8a52479cf276606beae24920eDRC	else
8109b28defe6ac85dd8a52479cf276606beae24920eDRC		return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch,
8119b28defe6ac85dd8a52479cf276606beae24920eDRC			height, getPixelFormat(pixelSize, flags), flags);
8129b28defe6ac85dd8a52479cf276606beae24920eDRC}
8139b28defe6ac85dd8a52479cf276606beae24920eDRC
8149b28defe6ac85dd8a52479cf276606beae24920eDRC
8159b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle,
8169b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
817b28fc5710a510410d2b498255a423dd62b353b3aDRC	int flags)
8182e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
8199b28defe6ac85dd8a52479cf276606beae24920eDRC	int i, row, retval=0;  JSAMPROW *outbuf[MAX_COMPONENTS];
820f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS],
821f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC		tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
8229b28defe6ac85dd8a52479cf276606beae24920eDRC	JSAMPLE *_tmpbuf=NULL, *ptr=dstBuf;  JSAMPROW *tmpbuf[MAX_COMPONENTS];
8232e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
8249b28defe6ac85dd8a52479cf276606beae24920eDRC	getinstance(handle);
8259b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this->init&DECOMPRESS)==0)
826007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompressToYUV(): Instance has not been initialized for decompression");
8272e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
828f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	for(i=0; i<MAX_COMPONENTS; i++)
829f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	{
830f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC		tmpbuf[i]=NULL;  outbuf[i]=NULL;
831f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	}
8329e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC
8339b28defe6ac85dd8a52479cf276606beae24920eDRC	if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL)
8349b28defe6ac85dd8a52479cf276606beae24920eDRC		_throw("tjDecompressToYUV(): Invalid argument");
8352e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
83625b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
83725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
83825b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
8390c6a271f974529e4795332c9ad428500ef17fb42DRC
8409b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
8419b28defe6ac85dd8a52479cf276606beae24920eDRC	{
8429b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
84391e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC		retval=-1;
84491e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC		goto bailout;
8459e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	}
8462e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
8479b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
8489b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_read_header(dinfo, TRUE);
8492e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
8509b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<dinfo->num_components; i++)
8519e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	{
8529b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_component_info *compptr=&dinfo->comp_info[i];
8539b28defe6ac85dd8a52479cf276606beae24920eDRC		int ih;
8549b28defe6ac85dd8a52479cf276606beae24920eDRC		iw[i]=compptr->width_in_blocks*DCTSIZE;
8559b28defe6ac85dd8a52479cf276606beae24920eDRC		ih=compptr->height_in_blocks*DCTSIZE;
8569b28defe6ac85dd8a52479cf276606beae24920eDRC		cw[i]=PAD(dinfo->image_width, dinfo->max_h_samp_factor)
8579b28defe6ac85dd8a52479cf276606beae24920eDRC			*compptr->h_samp_factor/dinfo->max_h_samp_factor;
8589b28defe6ac85dd8a52479cf276606beae24920eDRC		ch[i]=PAD(dinfo->image_height, dinfo->max_v_samp_factor)
8599b28defe6ac85dd8a52479cf276606beae24920eDRC			*compptr->v_samp_factor/dinfo->max_v_samp_factor;
8609b28defe6ac85dd8a52479cf276606beae24920eDRC		if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1;
8619b28defe6ac85dd8a52479cf276606beae24920eDRC		th[i]=compptr->v_samp_factor*DCTSIZE;
8629b28defe6ac85dd8a52479cf276606beae24920eDRC		tmpbufsize+=iw[i]*th[i];
8639b28defe6ac85dd8a52479cf276606beae24920eDRC		if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL)
864007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			_throw("tjDecompressToYUV(): Memory allocation failure");
8659b28defe6ac85dd8a52479cf276606beae24920eDRC		for(row=0; row<ch[i]; row++)
8669e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC		{
8679b28defe6ac85dd8a52479cf276606beae24920eDRC			outbuf[i][row]=ptr;
8689b28defe6ac85dd8a52479cf276606beae24920eDRC			ptr+=PAD(cw[i], 4);
869f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC		}
8709b28defe6ac85dd8a52479cf276606beae24920eDRC	}
8719b28defe6ac85dd8a52479cf276606beae24920eDRC	if(usetmpbuf)
8729b28defe6ac85dd8a52479cf276606beae24920eDRC	{
8739b28defe6ac85dd8a52479cf276606beae24920eDRC		if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
874007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			_throw("tjDecompressToYUV(): Memory allocation failure");
8759b28defe6ac85dd8a52479cf276606beae24920eDRC		ptr=_tmpbuf;
8769b28defe6ac85dd8a52479cf276606beae24920eDRC		for(i=0; i<dinfo->num_components; i++)
877f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC		{
8789b28defe6ac85dd8a52479cf276606beae24920eDRC			if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
879007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC				_throw("tjDecompressToYUV(): Memory allocation failure");
8809b28defe6ac85dd8a52479cf276606beae24920eDRC			for(row=0; row<th[i]; row++)
881f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC			{
8829b28defe6ac85dd8a52479cf276606beae24920eDRC				tmpbuf[i][row]=ptr;
8839b28defe6ac85dd8a52479cf276606beae24920eDRC				ptr+=iw[i];
8849e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC			}
8859e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC		}
8869e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	}
8872e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
88825b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
8899b28defe6ac85dd8a52479cf276606beae24920eDRC	dinfo->raw_data_out=TRUE;
8909b28defe6ac85dd8a52479cf276606beae24920eDRC
8919b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_start_decompress(dinfo);
8929b28defe6ac85dd8a52479cf276606beae24920eDRC	for(row=0; row<(int)dinfo->output_height;
8939b28defe6ac85dd8a52479cf276606beae24920eDRC		row+=dinfo->max_v_samp_factor*DCTSIZE)
8948ed7b814039172fe3cbfadfee3922801a3888b73DRC	{
8959b28defe6ac85dd8a52479cf276606beae24920eDRC		JSAMPARRAY yuvptr[MAX_COMPONENTS];
8969b28defe6ac85dd8a52479cf276606beae24920eDRC		int crow[MAX_COMPONENTS];
8979b28defe6ac85dd8a52479cf276606beae24920eDRC		for(i=0; i<dinfo->num_components; i++)
898842416034561f6d5320165a4fe98825e999a4a37DRC		{
8999b28defe6ac85dd8a52479cf276606beae24920eDRC			jpeg_component_info *compptr=&dinfo->comp_info[i];
9009b28defe6ac85dd8a52479cf276606beae24920eDRC			crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
9019b28defe6ac85dd8a52479cf276606beae24920eDRC			if(usetmpbuf) yuvptr[i]=tmpbuf[i];
9029b28defe6ac85dd8a52479cf276606beae24920eDRC			else yuvptr[i]=&outbuf[i][crow[i]];
903842416034561f6d5320165a4fe98825e999a4a37DRC		}
9049b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_read_raw_data(dinfo, yuvptr, dinfo->max_v_samp_factor*DCTSIZE);
9059b28defe6ac85dd8a52479cf276606beae24920eDRC		if(usetmpbuf)
9069e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC		{
9079b28defe6ac85dd8a52479cf276606beae24920eDRC			int j;
908f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC			for(i=0; i<dinfo->num_components; i++)
9099e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC			{
9109b28defe6ac85dd8a52479cf276606beae24920eDRC				for(j=0; j<min(th[i], ch[i]-crow[i]); j++)
911f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC				{
9129b28defe6ac85dd8a52479cf276606beae24920eDRC					memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], cw[i]);
913f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC				}
9149e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC			}
9159e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC		}
9169e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	}
9179b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_finish_decompress(dinfo);
9182e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
91991e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	bailout:
9209b28defe6ac85dd8a52479cf276606beae24920eDRC	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
9219e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	for(i=0; i<MAX_COMPONENTS; i++)
922f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	{
923f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC		if(tmpbuf[i]) free(tmpbuf[i]);
9249e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC		if(outbuf[i]) free(outbuf[i]);
925f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	}
926f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	if(_tmpbuf) free(_tmpbuf);
92791e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	return retval;
9282e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
9292e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
9302e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
9319b28defe6ac85dd8a52479cf276606beae24920eDRC/* Transformer */
932890f1e0413b54c40b663208779d4ea9dae20eaefDRC
933890f1e0413b54c40b663208779d4ea9dae20eaefDRCDLLEXPORT tjhandle DLLCALL tjInitTransform(void)
934890f1e0413b54c40b663208779d4ea9dae20eaefDRC{
9359b28defe6ac85dd8a52479cf276606beae24920eDRC	tjinstance *this=NULL;  tjhandle handle=NULL;
9369b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
937da5220acdd525242bff4e40b1d90324ebb889825DRC	{
938007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		snprintf(errStr, JMSG_LENGTH_MAX,
939007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			"tjInitTransform(): Memory allocation failure");
940da5220acdd525242bff4e40b1d90324ebb889825DRC		return NULL;
941da5220acdd525242bff4e40b1d90324ebb889825DRC	}
942007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	MEMZERO(this, sizeof(tjinstance));
9439b28defe6ac85dd8a52479cf276606beae24920eDRC	handle=_tjInitCompress(this);
9449b28defe6ac85dd8a52479cf276606beae24920eDRC	if(!handle) return NULL;
9459b28defe6ac85dd8a52479cf276606beae24920eDRC	handle=_tjInitDecompress(this);
9469b28defe6ac85dd8a52479cf276606beae24920eDRC	return handle;
947890f1e0413b54c40b663208779d4ea9dae20eaefDRC}
948890f1e0413b54c40b663208779d4ea9dae20eaefDRC
949890f1e0413b54c40b663208779d4ea9dae20eaefDRC
9509b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjTransform(tjhandle handle, unsigned char *jpegBuf,
9519b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long jpegSize, int n, unsigned char **dstBufs,
9529b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long *dstSizes, tjtransform *t, int flags)
953890f1e0413b54c40b663208779d4ea9dae20eaefDRC{
9540a325197dedd2eede99731c68ae0e0a145473f64DRC	jpeg_transform_info *xinfo=NULL;
955890f1e0413b54c40b663208779d4ea9dae20eaefDRC	jvirt_barray_ptr *srccoefs, *dstcoefs;
9569b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	int retval=0, i, jpegSubsamp;
957890f1e0413b54c40b663208779d4ea9dae20eaefDRC
9589b28defe6ac85dd8a52479cf276606beae24920eDRC	getinstance(handle);
9599b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0)
960007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjTransform(): Instance has not been initialized for transformation");
961890f1e0413b54c40b663208779d4ea9dae20eaefDRC
9629b28defe6ac85dd8a52479cf276606beae24920eDRC	if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL
9630a325197dedd2eede99731c68ae0e0a145473f64DRC		|| t==NULL || flags<0)
9649b28defe6ac85dd8a52479cf276606beae24920eDRC		_throw("tjTransform(): Invalid argument");
965890f1e0413b54c40b663208779d4ea9dae20eaefDRC
96625b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
96725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
96825b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
969890f1e0413b54c40b663208779d4ea9dae20eaefDRC
9709b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
9719b28defe6ac85dd8a52479cf276606beae24920eDRC	{
9729b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
973890f1e0413b54c40b663208779d4ea9dae20eaefDRC		retval=-1;
974890f1e0413b54c40b663208779d4ea9dae20eaefDRC		goto bailout;
975890f1e0413b54c40b663208779d4ea9dae20eaefDRC	}
976890f1e0413b54c40b663208779d4ea9dae20eaefDRC
9779b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
978890f1e0413b54c40b663208779d4ea9dae20eaefDRC
9790a325197dedd2eede99731c68ae0e0a145473f64DRC	if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n))
9800a325197dedd2eede99731c68ae0e0a145473f64DRC		==NULL)
981007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjTransform(): Memory allocation failure");
982007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	MEMZERO(xinfo, sizeof(jpeg_transform_info)*n);
983890f1e0413b54c40b663208779d4ea9dae20eaefDRC
9840a325197dedd2eede99731c68ae0e0a145473f64DRC	for(i=0; i<n; i++)
985890f1e0413b54c40b663208779d4ea9dae20eaefDRC	{
9860a325197dedd2eede99731c68ae0e0a145473f64DRC		xinfo[i].transform=xformtypes[t[i].op];
98725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0;
98825b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0;
98925b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0;
99025b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0;
99125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1;
992ba5ea5143e48b71234414139e3b4cb244599e875DRC		else xinfo[i].slow_hflip=0;
9930a325197dedd2eede99731c68ae0e0a145473f64DRC
9940a325197dedd2eede99731c68ae0e0a145473f64DRC		if(xinfo[i].crop)
995890f1e0413b54c40b663208779d4ea9dae20eaefDRC		{
9960a325197dedd2eede99731c68ae0e0a145473f64DRC			xinfo[i].crop_xoffset=t[i].r.x;  xinfo[i].crop_xoffset_set=JCROP_POS;
9970a325197dedd2eede99731c68ae0e0a145473f64DRC			xinfo[i].crop_yoffset=t[i].r.y;  xinfo[i].crop_yoffset_set=JCROP_POS;
9980a325197dedd2eede99731c68ae0e0a145473f64DRC			if(t[i].r.w!=0)
9990a325197dedd2eede99731c68ae0e0a145473f64DRC			{
10000a325197dedd2eede99731c68ae0e0a145473f64DRC				xinfo[i].crop_width=t[i].r.w;  xinfo[i].crop_width_set=JCROP_POS;
10010a325197dedd2eede99731c68ae0e0a145473f64DRC			}
1002d932e582178e2352b7e1da5622183e3e6082f5b3DRC			else xinfo[i].crop_width=JCROP_UNSET;
10030a325197dedd2eede99731c68ae0e0a145473f64DRC			if(t[i].r.h!=0)
10040a325197dedd2eede99731c68ae0e0a145473f64DRC			{
10050a325197dedd2eede99731c68ae0e0a145473f64DRC				xinfo[i].crop_height=t[i].r.h;  xinfo[i].crop_height_set=JCROP_POS;
10060a325197dedd2eede99731c68ae0e0a145473f64DRC			}
1007d932e582178e2352b7e1da5622183e3e6082f5b3DRC			else xinfo[i].crop_height=JCROP_UNSET;
1008890f1e0413b54c40b663208779d4ea9dae20eaefDRC		}
1009890f1e0413b54c40b663208779d4ea9dae20eaefDRC	}
1010890f1e0413b54c40b663208779d4ea9dae20eaefDRC
10119b28defe6ac85dd8a52479cf276606beae24920eDRC	jcopy_markers_setup(dinfo, JCOPYOPT_ALL);
10129b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_read_header(dinfo, TRUE);
10139b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	jpegSubsamp=getSubsamp(dinfo);
10149b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	if(jpegSubsamp<0)
10159b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC		_throw("tjTransform(): Could not determine subsampling type for JPEG image");
1016890f1e0413b54c40b663208779d4ea9dae20eaefDRC
10170a325197dedd2eede99731c68ae0e0a145473f64DRC	for(i=0; i<n; i++)
1018890f1e0413b54c40b663208779d4ea9dae20eaefDRC	{
10199b28defe6ac85dd8a52479cf276606beae24920eDRC		if(!jtransform_request_workspace(dinfo, &xinfo[i]))
1020007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			_throw("tjTransform(): Transform is not perfect");
10210a325197dedd2eede99731c68ae0e0a145473f64DRC
10220a325197dedd2eede99731c68ae0e0a145473f64DRC		if(xinfo[i].crop)
10230a325197dedd2eede99731c68ae0e0a145473f64DRC		{
10240a325197dedd2eede99731c68ae0e0a145473f64DRC			if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0
10250a325197dedd2eede99731c68ae0e0a145473f64DRC				|| (t[i].r.y%xinfo[i].iMCU_sample_height)!=0)
10260a325197dedd2eede99731c68ae0e0a145473f64DRC			{
10279b28defe6ac85dd8a52479cf276606beae24920eDRC				snprintf(errStr, JMSG_LENGTH_MAX,
10280a325197dedd2eede99731c68ae0e0a145473f64DRC					"To crop this JPEG image, x must be a multiple of %d\n"
10290a325197dedd2eede99731c68ae0e0a145473f64DRC					"and y must be a multiple of %d.\n",
10300a325197dedd2eede99731c68ae0e0a145473f64DRC					xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height);
10310a325197dedd2eede99731c68ae0e0a145473f64DRC				retval=-1;  goto bailout;
10320a325197dedd2eede99731c68ae0e0a145473f64DRC			}
10330a325197dedd2eede99731c68ae0e0a145473f64DRC		}
1034890f1e0413b54c40b663208779d4ea9dae20eaefDRC	}
1035890f1e0413b54c40b663208779d4ea9dae20eaefDRC
10369b28defe6ac85dd8a52479cf276606beae24920eDRC	srccoefs=jpeg_read_coefficients(dinfo);
1037890f1e0413b54c40b663208779d4ea9dae20eaefDRC
10380a325197dedd2eede99731c68ae0e0a145473f64DRC	for(i=0; i<n; i++)
1039890f1e0413b54c40b663208779d4ea9dae20eaefDRC	{
1040ff78e37595c8462f64fd100f928aa1d08539527eDRC		int w, h, alloc=1;
10410a325197dedd2eede99731c68ae0e0a145473f64DRC		if(!xinfo[i].crop)
1042890f1e0413b54c40b663208779d4ea9dae20eaefDRC		{
10439b28defe6ac85dd8a52479cf276606beae24920eDRC			w=dinfo->image_width;  h=dinfo->image_height;
1044890f1e0413b54c40b663208779d4ea9dae20eaefDRC		}
10450a325197dedd2eede99731c68ae0e0a145473f64DRC		else
10460a325197dedd2eede99731c68ae0e0a145473f64DRC		{
10470a325197dedd2eede99731c68ae0e0a145473f64DRC			w=xinfo[i].crop_width;  h=xinfo[i].crop_height;
10480a325197dedd2eede99731c68ae0e0a145473f64DRC		}
1049ff78e37595c8462f64fd100f928aa1d08539527eDRC		if(flags&TJFLAG_NOREALLOC)
1050ff78e37595c8462f64fd100f928aa1d08539527eDRC		{
10519b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC			alloc=0;  dstSizes[i]=tjBufSize(w, h, jpegSubsamp);
1052ff78e37595c8462f64fd100f928aa1d08539527eDRC		}
10537bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		if(!(t[i].options&TJXOPT_NOOUTPUT))
10547bf04d399ebf9a3b39a6d5b5639d895df618353dDRC			jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc);
10559b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_copy_critical_parameters(dinfo, cinfo);
10569b28defe6ac85dd8a52479cf276606beae24920eDRC		dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs,
10570a325197dedd2eede99731c68ae0e0a145473f64DRC			&xinfo[i]);
10587bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		if(!(t[i].options&TJXOPT_NOOUTPUT))
10597bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		{
10607bf04d399ebf9a3b39a6d5b5639d895df618353dDRC			jpeg_write_coefficients(cinfo, dstcoefs);
10617bf04d399ebf9a3b39a6d5b5639d895df618353dDRC			jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL);
10627bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		}
10637bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		else jinit_c_master_control(cinfo, TRUE);
10649b28defe6ac85dd8a52479cf276606beae24920eDRC		jtransform_execute_transformation(dinfo, cinfo, srccoefs,
10650a325197dedd2eede99731c68ae0e0a145473f64DRC			&xinfo[i]);
10667bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		if(t[i].customFilter)
10677bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		{
10687bf04d399ebf9a3b39a6d5b5639d895df618353dDRC			int ci, by, y;
10697bf04d399ebf9a3b39a6d5b5639d895df618353dDRC			for(ci=0; ci<cinfo->num_components; ci++)
10707bf04d399ebf9a3b39a6d5b5639d895df618353dDRC			{
10717bf04d399ebf9a3b39a6d5b5639d895df618353dDRC				jpeg_component_info *compptr=&cinfo->comp_info[ci];
10727bf04d399ebf9a3b39a6d5b5639d895df618353dDRC				tjregion arrayRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
10737bf04d399ebf9a3b39a6d5b5639d895df618353dDRC					DCTSIZE};
10747bf04d399ebf9a3b39a6d5b5639d895df618353dDRC				tjregion planeRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
10757bf04d399ebf9a3b39a6d5b5639d895df618353dDRC					compptr->height_in_blocks*DCTSIZE};
10767bf04d399ebf9a3b39a6d5b5639d895df618353dDRC				for(by=0; by<compptr->height_in_blocks; by+=compptr->v_samp_factor)
10777bf04d399ebf9a3b39a6d5b5639d895df618353dDRC				{
10787bf04d399ebf9a3b39a6d5b5639d895df618353dDRC					JBLOCKARRAY barray=(dinfo->mem->access_virt_barray)
10797bf04d399ebf9a3b39a6d5b5639d895df618353dDRC						((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor,
10807bf04d399ebf9a3b39a6d5b5639d895df618353dDRC						TRUE);
10817bf04d399ebf9a3b39a6d5b5639d895df618353dDRC					for(y=0; y<compptr->v_samp_factor; y++)
10827bf04d399ebf9a3b39a6d5b5639d895df618353dDRC					{
10837bf04d399ebf9a3b39a6d5b5639d895df618353dDRC						if(t[i].customFilter(barray[y][0], arrayRegion, planeRegion,
1084f5467110763f7a44ca8baf1c035eb39a68c913c6DRC							ci, i, &t[i])==-1)
10857bf04d399ebf9a3b39a6d5b5639d895df618353dDRC							_throw("tjTransform(): Error in custom filter");
10867bf04d399ebf9a3b39a6d5b5639d895df618353dDRC						arrayRegion.y+=DCTSIZE;
10877bf04d399ebf9a3b39a6d5b5639d895df618353dDRC					}
10887bf04d399ebf9a3b39a6d5b5639d895df618353dDRC				}
10897bf04d399ebf9a3b39a6d5b5639d895df618353dDRC			}
10907bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		}
10917bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		if(!(t[i].options&TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo);
1092890f1e0413b54c40b663208779d4ea9dae20eaefDRC	}
1093890f1e0413b54c40b663208779d4ea9dae20eaefDRC
10949b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_finish_decompress(dinfo);
1095890f1e0413b54c40b663208779d4ea9dae20eaefDRC
1096890f1e0413b54c40b663208779d4ea9dae20eaefDRC	bailout:
10979b28defe6ac85dd8a52479cf276606beae24920eDRC	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
10989b28defe6ac85dd8a52479cf276606beae24920eDRC	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
10990a325197dedd2eede99731c68ae0e0a145473f64DRC	if(xinfo) free(xinfo);
1100890f1e0413b54c40b663208779d4ea9dae20eaefDRC	return retval;
1101890f1e0413b54c40b663208779d4ea9dae20eaefDRC}
1102