turbojpeg.c revision 6b76f75d2c0ebdc462f6bc663289fa4bfde1629a
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>
33fbb674707e01a61e8b7083faa632dfd46c568b13DRC#define JPEG_INTERNALS
342e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC#include <jpeglib.h>
352e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC#include <jerror.h>
362e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC#include <setjmp.h>
37007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC#include <jinclude.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
1359b28defe6ac85dd8a52479cf276606beae24920eDRCstatic void setCompDefaults(struct jpeg_compress_struct *cinfo,
1369b28defe6ac85dd8a52479cf276606beae24920eDRC	int pixelFormat, int subsamp, int jpegQual)
1379b28defe6ac85dd8a52479cf276606beae24920eDRC{
1389b28defe6ac85dd8a52479cf276606beae24920eDRC	switch(pixelFormat)
1399b28defe6ac85dd8a52479cf276606beae24920eDRC	{
14025b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_GRAY:
1419b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_GRAYSCALE;  break;
1429b28defe6ac85dd8a52479cf276606beae24920eDRC		#if JCS_EXTENSIONS==1
14325b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGB:
1449b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_RGB;  break;
14525b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_BGR:
1469b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_BGR;  break;
14725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGBX:
1489b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_RGBX;  break;
14925b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_BGRX:
1509b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_BGRX;  break;
15125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_XRGB:
1529b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_XRGB;  break;
15325b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_XBGR:
1549b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_XBGR;  break;
1559b28defe6ac85dd8a52479cf276606beae24920eDRC		#else
15625b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGB:
1579b28defe6ac85dd8a52479cf276606beae24920eDRC			if(RGB_RED==0 && RGB_GREEN==1 && RGB_BLUE==2 && RGB_PIXELSIZE==3)
1589b28defe6ac85dd8a52479cf276606beae24920eDRC			{
1599b28defe6ac85dd8a52479cf276606beae24920eDRC				cinfo->in_color_space=JCS_RGB;  break;
1609b28defe6ac85dd8a52479cf276606beae24920eDRC			}
1619b28defe6ac85dd8a52479cf276606beae24920eDRC		default:
1629b28defe6ac85dd8a52479cf276606beae24920eDRC			_throw("Unsupported pixel format");
1639b28defe6ac85dd8a52479cf276606beae24920eDRC		#endif
1649b28defe6ac85dd8a52479cf276606beae24920eDRC	}
1659b28defe6ac85dd8a52479cf276606beae24920eDRC
1669b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->input_components=tjPixelSize[pixelFormat];
1679b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_set_defaults(cinfo);
1689b28defe6ac85dd8a52479cf276606beae24920eDRC	if(jpegQual>=0)
1699b28defe6ac85dd8a52479cf276606beae24920eDRC	{
1709b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_set_quality(cinfo, jpegQual, TRUE);
1719b28defe6ac85dd8a52479cf276606beae24920eDRC		if(jpegQual>=96) cinfo->dct_method=JDCT_ISLOW;
1729b28defe6ac85dd8a52479cf276606beae24920eDRC		else cinfo->dct_method=JDCT_FASTEST;
1739b28defe6ac85dd8a52479cf276606beae24920eDRC	}
17425b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(subsamp==TJSAMP_GRAY)
1759b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
1769b28defe6ac85dd8a52479cf276606beae24920eDRC	else
1779b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_set_colorspace(cinfo, JCS_YCbCr);
1789b28defe6ac85dd8a52479cf276606beae24920eDRC
1799b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[0].h_samp_factor=tjMCUWidth[subsamp]/8;
1809b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[1].h_samp_factor=1;
1819b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[2].h_samp_factor=1;
1829b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[0].v_samp_factor=tjMCUHeight[subsamp]/8;
1839b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[1].v_samp_factor=1;
1849b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[2].v_samp_factor=1;
1859b28defe6ac85dd8a52479cf276606beae24920eDRC}
1869b28defe6ac85dd8a52479cf276606beae24920eDRC
1879b28defe6ac85dd8a52479cf276606beae24920eDRCstatic void setDecompDefaults(struct jpeg_decompress_struct *dinfo,
1889b28defe6ac85dd8a52479cf276606beae24920eDRC	int pixelFormat)
1899b28defe6ac85dd8a52479cf276606beae24920eDRC{
1909b28defe6ac85dd8a52479cf276606beae24920eDRC	switch(pixelFormat)
1919b28defe6ac85dd8a52479cf276606beae24920eDRC	{
19225b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_GRAY:
1939b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_GRAYSCALE;  break;
1949b28defe6ac85dd8a52479cf276606beae24920eDRC		#if JCS_EXTENSIONS==1
19525b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGB:
1969b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_RGB;  break;
19725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_BGR:
1989b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_BGR;  break;
19925b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGBX:
2009b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_RGBX;  break;
20125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_BGRX:
2029b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_BGRX;  break;
20325b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_XRGB:
2049b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_XRGB;  break;
20525b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_XBGR:
2069b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_XBGR;  break;
2079b28defe6ac85dd8a52479cf276606beae24920eDRC		#else
20825b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGB:
2099b28defe6ac85dd8a52479cf276606beae24920eDRC			if(RGB_RED==0 && RGB_GREEN==1 && RGB_BLUE==2 && RGB_PIXELSIZE==3)
2109b28defe6ac85dd8a52479cf276606beae24920eDRC			{
2119b28defe6ac85dd8a52479cf276606beae24920eDRC				dinfo->out_color_space=JCS_RGB;  break;
2129b28defe6ac85dd8a52479cf276606beae24920eDRC			}
2139b28defe6ac85dd8a52479cf276606beae24920eDRC		default:
2149b28defe6ac85dd8a52479cf276606beae24920eDRC			_throw("Unsupported pixel format");
2159b28defe6ac85dd8a52479cf276606beae24920eDRC		#endif
2169b28defe6ac85dd8a52479cf276606beae24920eDRC	}
2179b28defe6ac85dd8a52479cf276606beae24920eDRC}
2182e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
2192e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
2209b28defe6ac85dd8a52479cf276606beae24920eDRC/* General API functions */
2212e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
2229b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT char* DLLCALL tjGetErrorStr(void)
2232e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
2249b28defe6ac85dd8a52479cf276606beae24920eDRC	return errStr;
2252e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
2262e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
2279b28defe6ac85dd8a52479cf276606beae24920eDRC
2289b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjDestroy(tjhandle handle)
2292e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
2309b28defe6ac85dd8a52479cf276606beae24920eDRC	getinstance(handle);
2319b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer)) return -1;
2329b28defe6ac85dd8a52479cf276606beae24920eDRC	if(this->init&COMPRESS) jpeg_destroy_compress(cinfo);
2339b28defe6ac85dd8a52479cf276606beae24920eDRC	if(this->init&DECOMPRESS) jpeg_destroy_decompress(dinfo);
2349b28defe6ac85dd8a52479cf276606beae24920eDRC	free(this);
2359b28defe6ac85dd8a52479cf276606beae24920eDRC	return 0;
2362e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
2372e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
2389b28defe6ac85dd8a52479cf276606beae24920eDRC
2396b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC/* These are exposed mainly because Windows can't malloc() and free() across
2406b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC   DLL boundaries except when the CRT DLL is used, and we don't use the CRT DLL
2416b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC   with turbojpeg.dll for compatibility reasons.  However, these functions
2426b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC   can potentially be used for other purposes by different implementations. */
2436b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC
2446b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRCDLLEXPORT void DLLCALL tjFree(unsigned char *buf)
2456b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC{
2466b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC	if(buf) free(buf);
2476b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC}
2486b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC
2496b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC
2506b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRCDLLEXPORT unsigned char *DLLCALL tjAlloc(int bytes)
2516b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC{
2526b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC	return (unsigned char *)malloc(bytes);
2536b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC}
2546b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC
2556b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC
2569b28defe6ac85dd8a52479cf276606beae24920eDRC/* Compressor  */
2579b28defe6ac85dd8a52479cf276606beae24920eDRC
2589b28defe6ac85dd8a52479cf276606beae24920eDRCstatic tjhandle _tjInitCompress(tjinstance *this)
2592e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
2609b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned char buffer[1], *buf=buffer;  unsigned long size=1;
2619b28defe6ac85dd8a52479cf276606beae24920eDRC
2629b28defe6ac85dd8a52479cf276606beae24920eDRC	/* This is also straight out of example.c */
2639b28defe6ac85dd8a52479cf276606beae24920eDRC	this->cinfo.err=jpeg_std_error(&this->jerr.pub);
2649b28defe6ac85dd8a52479cf276606beae24920eDRC	this->jerr.pub.error_exit=my_error_exit;
2659b28defe6ac85dd8a52479cf276606beae24920eDRC	this->jerr.pub.output_message=my_output_message;
2662e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
2679b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
2689b28defe6ac85dd8a52479cf276606beae24920eDRC	{
2699b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
2709b28defe6ac85dd8a52479cf276606beae24920eDRC		if(this) free(this);  return NULL;
271efa4ddcc88783c7b8bf5cba42c6680132eefa628DRC	}
2722e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
2739b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_create_compress(&this->cinfo);
2749b28defe6ac85dd8a52479cf276606beae24920eDRC	/* Make an initial call so it will create the destination manager */
2759b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_dest_tj(&this->cinfo, &buf, &size, 0);
2762e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
277007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	this->init|=COMPRESS;
2789b28defe6ac85dd8a52479cf276606beae24920eDRC	return (tjhandle)this;
2792e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
2802e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
281890f1e0413b54c40b663208779d4ea9dae20eaefDRCDLLEXPORT tjhandle DLLCALL tjInitCompress(void)
282890f1e0413b54c40b663208779d4ea9dae20eaefDRC{
2839b28defe6ac85dd8a52479cf276606beae24920eDRC	tjinstance *this=NULL;
2849b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
285da5220acdd525242bff4e40b1d90324ebb889825DRC	{
286007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		snprintf(errStr, JMSG_LENGTH_MAX,
287007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			"tjInitCompress(): Memory allocation failure");
288da5220acdd525242bff4e40b1d90324ebb889825DRC		return NULL;
289da5220acdd525242bff4e40b1d90324ebb889825DRC	}
290007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	MEMZERO(this, sizeof(tjinstance));
2919b28defe6ac85dd8a52479cf276606beae24920eDRC	return _tjInitCompress(this);
292890f1e0413b54c40b663208779d4ea9dae20eaefDRC}
293890f1e0413b54c40b663208779d4ea9dae20eaefDRC
294842416034561f6d5320165a4fe98825e999a4a37DRC
2952e7b76b28c0a872ae6ca002fd32bbba0769f990eDRCDLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
2962e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
297f3cf973e8e51e0078f402ca5547c026967c27321DRC	unsigned long retval=0;
298f3cf973e8e51e0078f402ca5547c026967c27321DRC	if(width<1 || height<1)
299007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("TJBUFSIZE(): Invalid argument");
300f3cf973e8e51e0078f402ca5547c026967c27321DRC
301f3cf973e8e51e0078f402ca5547c026967c27321DRC	// This allows for rare corner cases in which a JPEG image can actually be
302f3cf973e8e51e0078f402ca5547c026967c27321DRC	// larger than the uncompressed input (we wouldn't mention it if it hadn't
303b28fc5710a510410d2b498255a423dd62b353b3aDRC	// happened before.)
304007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	retval=PAD(width, 16) * PAD(height, 16) * 6 + 2048;
305f3cf973e8e51e0078f402ca5547c026967c27321DRC
306f3cf973e8e51e0078f402ca5547c026967c27321DRC	bailout:
307f3cf973e8e51e0078f402ca5547c026967c27321DRC	return retval;
308f3cf973e8e51e0078f402ca5547c026967c27321DRC}
309f3cf973e8e51e0078f402ca5547c026967c27321DRC
310842416034561f6d5320165a4fe98825e999a4a37DRC
311f3cf973e8e51e0078f402ca5547c026967c27321DRCDLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
312f3cf973e8e51e0078f402ca5547c026967c27321DRC	int subsamp)
313f3cf973e8e51e0078f402ca5547c026967c27321DRC{
314f3cf973e8e51e0078f402ca5547c026967c27321DRC	unsigned long retval=0;
315f3cf973e8e51e0078f402ca5547c026967c27321DRC	int pw, ph, cw, ch;
316f3cf973e8e51e0078f402ca5547c026967c27321DRC	if(width<1 || height<1 || subsamp<0 || subsamp>=NUMSUBOPT)
317007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("TJBUFSIZEYUV(): Invalid argument");
3189b28defe6ac85dd8a52479cf276606beae24920eDRC	pw=PAD(width, tjMCUWidth[subsamp]/8);
3199b28defe6ac85dd8a52479cf276606beae24920eDRC	ph=PAD(height, tjMCUHeight[subsamp]/8);
3209b28defe6ac85dd8a52479cf276606beae24920eDRC	cw=pw*8/tjMCUWidth[subsamp];  ch=ph*8/tjMCUHeight[subsamp];
32125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	retval=PAD(pw, 4)*ph + (subsamp==TJSAMP_GRAY? 0:PAD(cw, 4)*ch*2);
322f3cf973e8e51e0078f402ca5547c026967c27321DRC
323f3cf973e8e51e0078f402ca5547c026967c27321DRC	bailout:
324f3cf973e8e51e0078f402ca5547c026967c27321DRC	return retval;
3252e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
3262e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
327842416034561f6d5320165a4fe98825e999a4a37DRC
3289b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf,
3299b28defe6ac85dd8a52479cf276606beae24920eDRC	int width, int pitch, int height, int pixelFormat, unsigned char **jpegBuf,
3309b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
3319b28defe6ac85dd8a52479cf276606beae24920eDRC{
332ff78e37595c8462f64fd100f928aa1d08539527eDRC	int i, retval=0, alloc=1;  JSAMPROW *row_pointer=NULL;
3339b28defe6ac85dd8a52479cf276606beae24920eDRC
3349b28defe6ac85dd8a52479cf276606beae24920eDRC	getinstance(handle)
3359b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this->init&COMPRESS)==0)
336007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjCompress2(): Instance has not been initialized for compression");
3379b28defe6ac85dd8a52479cf276606beae24920eDRC
3389b28defe6ac85dd8a52479cf276606beae24920eDRC	if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
3399b28defe6ac85dd8a52479cf276606beae24920eDRC		|| pixelFormat>=TJ_NUMPF || jpegBuf==NULL || jpegSize==NULL
3409b28defe6ac85dd8a52479cf276606beae24920eDRC		|| jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT || jpegQual<0 || jpegQual>100)
341007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjCompress2(): Invalid argument");
3429b28defe6ac85dd8a52479cf276606beae24920eDRC
3439b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
3449b28defe6ac85dd8a52479cf276606beae24920eDRC	{
3459b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
3469b28defe6ac85dd8a52479cf276606beae24920eDRC		retval=-1;
3479b28defe6ac85dd8a52479cf276606beae24920eDRC		goto bailout;
3489b28defe6ac85dd8a52479cf276606beae24920eDRC	}
3499b28defe6ac85dd8a52479cf276606beae24920eDRC
3509b28defe6ac85dd8a52479cf276606beae24920eDRC	if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
3519b28defe6ac85dd8a52479cf276606beae24920eDRC
3529b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->image_width=width;
3539b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->image_height=height;
3549b28defe6ac85dd8a52479cf276606beae24920eDRC
35525b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
35625b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
35725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
3589b28defe6ac85dd8a52479cf276606beae24920eDRC
359ff78e37595c8462f64fd100f928aa1d08539527eDRC	if(flags&TJFLAG_NOREALLOC)
360ff78e37595c8462f64fd100f928aa1d08539527eDRC	{
361ff78e37595c8462f64fd100f928aa1d08539527eDRC		alloc=0;  *jpegSize=TJBUFSIZE(width, height);
362ff78e37595c8462f64fd100f928aa1d08539527eDRC	}
363ff78e37595c8462f64fd100f928aa1d08539527eDRC	jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
3649b28defe6ac85dd8a52479cf276606beae24920eDRC	setCompDefaults(cinfo, pixelFormat, jpegSubsamp, jpegQual);
3659b28defe6ac85dd8a52479cf276606beae24920eDRC
3669b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_start_compress(cinfo, TRUE);
3679b28defe6ac85dd8a52479cf276606beae24920eDRC	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
368007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjCompress2(): Memory allocation failure");
3699b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<height; i++)
3709b28defe6ac85dd8a52479cf276606beae24920eDRC	{
37125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
3729b28defe6ac85dd8a52479cf276606beae24920eDRC		else row_pointer[i]=&srcBuf[i*pitch];
3739b28defe6ac85dd8a52479cf276606beae24920eDRC	}
3749b28defe6ac85dd8a52479cf276606beae24920eDRC	while(cinfo->next_scanline<cinfo->image_height)
3759b28defe6ac85dd8a52479cf276606beae24920eDRC	{
3769b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_write_scanlines(cinfo, &row_pointer[cinfo->next_scanline],
3779b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->image_height-cinfo->next_scanline);
3789b28defe6ac85dd8a52479cf276606beae24920eDRC	}
3799b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_finish_compress(cinfo);
3809b28defe6ac85dd8a52479cf276606beae24920eDRC
3819b28defe6ac85dd8a52479cf276606beae24920eDRC	bailout:
3829b28defe6ac85dd8a52479cf276606beae24920eDRC	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
3839b28defe6ac85dd8a52479cf276606beae24920eDRC	if(row_pointer) free(row_pointer);
3849b28defe6ac85dd8a52479cf276606beae24920eDRC	return retval;
3859b28defe6ac85dd8a52479cf276606beae24920eDRC}
3869b28defe6ac85dd8a52479cf276606beae24920eDRC
3879b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjCompress(tjhandle handle, unsigned char *srcBuf,
3889b28defe6ac85dd8a52479cf276606beae24920eDRC	int width, int pitch, int height, int pixelSize, unsigned char *jpegBuf,
3899b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
3909b28defe6ac85dd8a52479cf276606beae24920eDRC{
3919b28defe6ac85dd8a52479cf276606beae24920eDRC	int retval=0;  unsigned long size;
3929b28defe6ac85dd8a52479cf276606beae24920eDRC	if(flags&TJ_YUV)
3939b28defe6ac85dd8a52479cf276606beae24920eDRC	{
3949b28defe6ac85dd8a52479cf276606beae24920eDRC		size=TJBUFSIZEYUV(width, height, jpegSubsamp);
3959b28defe6ac85dd8a52479cf276606beae24920eDRC		retval=tjEncodeYUV2(handle, srcBuf, width, pitch, height,
3969b28defe6ac85dd8a52479cf276606beae24920eDRC			getPixelFormat(pixelSize, flags), jpegBuf, jpegSubsamp, flags);
3979b28defe6ac85dd8a52479cf276606beae24920eDRC	}
3989b28defe6ac85dd8a52479cf276606beae24920eDRC	else
3999b28defe6ac85dd8a52479cf276606beae24920eDRC	{
4009b28defe6ac85dd8a52479cf276606beae24920eDRC		retval=tjCompress2(handle, srcBuf, width, pitch, height,
4019b28defe6ac85dd8a52479cf276606beae24920eDRC			getPixelFormat(pixelSize, flags), &jpegBuf, &size, jpegSubsamp, jpegQual,
40225b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC			flags|TJFLAG_NOREALLOC);
4039b28defe6ac85dd8a52479cf276606beae24920eDRC	}
4049b28defe6ac85dd8a52479cf276606beae24920eDRC	*jpegSize=size;
4059b28defe6ac85dd8a52479cf276606beae24920eDRC	return retval;
4069b28defe6ac85dd8a52479cf276606beae24920eDRC}
4079b28defe6ac85dd8a52479cf276606beae24920eDRC
4089b28defe6ac85dd8a52479cf276606beae24920eDRC
4099b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
4109b28defe6ac85dd8a52479cf276606beae24920eDRC	int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
4119b28defe6ac85dd8a52479cf276606beae24920eDRC	int subsamp, int flags)
4122e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
41391e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	int i, retval=0;  JSAMPROW *row_pointer=NULL;
414fbb674707e01a61e8b7083faa632dfd46c568b13DRC	JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS];
415fbb674707e01a61e8b7083faa632dfd46c568b13DRC	JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
416fbb674707e01a61e8b7083faa632dfd46c568b13DRC	JSAMPROW *outbuf[MAX_COMPONENTS];
4179b28defe6ac85dd8a52479cf276606beae24920eDRC	int row, pw, ph, cw[MAX_COMPONENTS], ch[MAX_COMPONENTS];
4189b28defe6ac85dd8a52479cf276606beae24920eDRC	JSAMPLE *ptr=dstBuf;
4199b28defe6ac85dd8a52479cf276606beae24920eDRC  unsigned long yuvsize=0;
4209b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_component_info *compptr;
4212e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
4229b28defe6ac85dd8a52479cf276606beae24920eDRC	getinstance(handle);
4239b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this->init&COMPRESS)==0)
424007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjEncodeYUV2(): Instance has not been initialized for compression");
4252e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
426fbb674707e01a61e8b7083faa632dfd46c568b13DRC	for(i=0; i<MAX_COMPONENTS; i++)
427fbb674707e01a61e8b7083faa632dfd46c568b13DRC	{
428fbb674707e01a61e8b7083faa632dfd46c568b13DRC		tmpbuf[i]=NULL;  _tmpbuf[i]=NULL;
429fbb674707e01a61e8b7083faa632dfd46c568b13DRC		tmpbuf2[i]=NULL;  _tmpbuf2[i]=NULL;  outbuf[i]=NULL;
430fbb674707e01a61e8b7083faa632dfd46c568b13DRC	}
431fbb674707e01a61e8b7083faa632dfd46c568b13DRC
4329b28defe6ac85dd8a52479cf276606beae24920eDRC	if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
4339b28defe6ac85dd8a52479cf276606beae24920eDRC		|| pixelFormat>=TJ_NUMPF || dstBuf==NULL || subsamp<0
4349b28defe6ac85dd8a52479cf276606beae24920eDRC		|| subsamp>=NUMSUBOPT)
4359b28defe6ac85dd8a52479cf276606beae24920eDRC		_throw("tjEncodeYUV2(): Invalid argument");
4362e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
4379b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
4389b28defe6ac85dd8a52479cf276606beae24920eDRC	{
4399b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
44091e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC		retval=-1;
44191e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC		goto bailout;
442efa4ddcc88783c7b8bf5cba42c6680132eefa628DRC	}
4432e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
4449b28defe6ac85dd8a52479cf276606beae24920eDRC	if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
4452e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
4469b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->image_width=width;
4479b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->image_height=height;
4482e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
44925b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
45025b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
45125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
4522e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
4539b28defe6ac85dd8a52479cf276606beae24920eDRC	yuvsize=TJBUFSIZEYUV(width, height, subsamp);
4549b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_dest_tj(cinfo, &dstBuf, &yuvsize, 0);
4559b28defe6ac85dd8a52479cf276606beae24920eDRC	setCompDefaults(cinfo, pixelFormat, subsamp, -1);
4562e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
4579b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_start_compress(cinfo, TRUE);
4589b28defe6ac85dd8a52479cf276606beae24920eDRC	pw=PAD(width, cinfo->max_h_samp_factor);
4599b28defe6ac85dd8a52479cf276606beae24920eDRC	ph=PAD(height, cinfo->max_v_samp_factor);
4609b28defe6ac85dd8a52479cf276606beae24920eDRC
4619b28defe6ac85dd8a52479cf276606beae24920eDRC	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph))==NULL)
462007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjEncodeYUV2(): Memory allocation failure");
4639b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<height; i++)
4642e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC	{
46525b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
4669b28defe6ac85dd8a52479cf276606beae24920eDRC		else row_pointer[i]=&srcBuf[i*pitch];
4679b28defe6ac85dd8a52479cf276606beae24920eDRC	}
4689b28defe6ac85dd8a52479cf276606beae24920eDRC	if(height<ph)
4699b28defe6ac85dd8a52479cf276606beae24920eDRC		for(i=height; i<ph; i++) row_pointer[i]=row_pointer[height-1];
470fbb674707e01a61e8b7083faa632dfd46c568b13DRC
4719b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<cinfo->num_components; i++)
4729b28defe6ac85dd8a52479cf276606beae24920eDRC	{
4739b28defe6ac85dd8a52479cf276606beae24920eDRC		compptr=&cinfo->comp_info[i];
4749b28defe6ac85dd8a52479cf276606beae24920eDRC		_tmpbuf[i]=(JSAMPLE *)malloc(
4759b28defe6ac85dd8a52479cf276606beae24920eDRC			PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
4769b28defe6ac85dd8a52479cf276606beae24920eDRC				/compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
477007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		if(!_tmpbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
4789b28defe6ac85dd8a52479cf276606beae24920eDRC		tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
479007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		if(!tmpbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
4809b28defe6ac85dd8a52479cf276606beae24920eDRC		for(row=0; row<cinfo->max_v_samp_factor; row++)
481fbb674707e01a61e8b7083faa632dfd46c568b13DRC		{
4829b28defe6ac85dd8a52479cf276606beae24920eDRC			unsigned char *_tmpbuf_aligned=
4839b28defe6ac85dd8a52479cf276606beae24920eDRC				(unsigned char *)PAD((size_t)_tmpbuf[i], 16);
4849b28defe6ac85dd8a52479cf276606beae24920eDRC			tmpbuf[i][row]=&_tmpbuf_aligned[
485fbb674707e01a61e8b7083faa632dfd46c568b13DRC				PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
4869b28defe6ac85dd8a52479cf276606beae24920eDRC					/compptr->h_samp_factor, 16) * row];
487fbb674707e01a61e8b7083faa632dfd46c568b13DRC		}
4889b28defe6ac85dd8a52479cf276606beae24920eDRC		_tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
4899b28defe6ac85dd8a52479cf276606beae24920eDRC			* compptr->v_samp_factor + 16);
490007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		if(!_tmpbuf2[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
4919b28defe6ac85dd8a52479cf276606beae24920eDRC		tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
492007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		if(!tmpbuf2[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
4939b28defe6ac85dd8a52479cf276606beae24920eDRC		for(row=0; row<compptr->v_samp_factor; row++)
494fbb674707e01a61e8b7083faa632dfd46c568b13DRC		{
4959b28defe6ac85dd8a52479cf276606beae24920eDRC			unsigned char *_tmpbuf2_aligned=
4969b28defe6ac85dd8a52479cf276606beae24920eDRC				(unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
4979b28defe6ac85dd8a52479cf276606beae24920eDRC			tmpbuf2[i][row]=&_tmpbuf2_aligned[
4989b28defe6ac85dd8a52479cf276606beae24920eDRC				PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
499fbb674707e01a61e8b7083faa632dfd46c568b13DRC		}
5009b28defe6ac85dd8a52479cf276606beae24920eDRC		cw[i]=pw*compptr->h_samp_factor/cinfo->max_h_samp_factor;
5019b28defe6ac85dd8a52479cf276606beae24920eDRC		ch[i]=ph*compptr->v_samp_factor/cinfo->max_v_samp_factor;
5029b28defe6ac85dd8a52479cf276606beae24920eDRC		outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]);
503007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		if(!outbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
5049b28defe6ac85dd8a52479cf276606beae24920eDRC		for(row=0; row<ch[i]; row++)
505fbb674707e01a61e8b7083faa632dfd46c568b13DRC		{
5069b28defe6ac85dd8a52479cf276606beae24920eDRC			outbuf[i][row]=ptr;
5079b28defe6ac85dd8a52479cf276606beae24920eDRC			ptr+=PAD(cw[i], 4);
508fbb674707e01a61e8b7083faa632dfd46c568b13DRC		}
5096ee54594591d0ae958b81adc8ba3cacde522e5e3DRC	}
5109b28defe6ac85dd8a52479cf276606beae24920eDRC	if(yuvsize!=(unsigned long)(ptr-dstBuf))
5119b28defe6ac85dd8a52479cf276606beae24920eDRC		_throw("tjEncodeYUV2(): Generated image is not the correct size");
5129b28defe6ac85dd8a52479cf276606beae24920eDRC
5139b28defe6ac85dd8a52479cf276606beae24920eDRC	for(row=0; row<ph; row+=cinfo->max_v_samp_factor)
5149b28defe6ac85dd8a52479cf276606beae24920eDRC	{
5159b28defe6ac85dd8a52479cf276606beae24920eDRC		(*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0,
5169b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->max_v_samp_factor);
5179b28defe6ac85dd8a52479cf276606beae24920eDRC		(cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
5189b28defe6ac85dd8a52479cf276606beae24920eDRC		for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++)
5199b28defe6ac85dd8a52479cf276606beae24920eDRC			jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
5209b28defe6ac85dd8a52479cf276606beae24920eDRC				row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
5219b28defe6ac85dd8a52479cf276606beae24920eDRC				compptr->v_samp_factor, cw[i]);
5229b28defe6ac85dd8a52479cf276606beae24920eDRC	}
5239b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->next_scanline+=height;
5249b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_abort_compress(cinfo);
5252e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
52691e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	bailout:
5279b28defe6ac85dd8a52479cf276606beae24920eDRC	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
5282e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC	if(row_pointer) free(row_pointer);
529fbb674707e01a61e8b7083faa632dfd46c568b13DRC	for(i=0; i<MAX_COMPONENTS; i++)
530fbb674707e01a61e8b7083faa632dfd46c568b13DRC	{
531fbb674707e01a61e8b7083faa632dfd46c568b13DRC		if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
53257423076e6189717441763de3253072dee42ff7eDRC		if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
533fbb674707e01a61e8b7083faa632dfd46c568b13DRC		if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
53457423076e6189717441763de3253072dee42ff7eDRC		if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
535fbb674707e01a61e8b7083faa632dfd46c568b13DRC		if(outbuf[i]!=NULL) free(outbuf[i]);
536fbb674707e01a61e8b7083faa632dfd46c568b13DRC	}
53791e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	return retval;
5382e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
5392e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5409b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf,
5419b28defe6ac85dd8a52479cf276606beae24920eDRC	int width, int pitch, int height, int pixelSize, unsigned char *dstBuf,
5429b28defe6ac85dd8a52479cf276606beae24920eDRC	int subsamp, int flags)
543842416034561f6d5320165a4fe98825e999a4a37DRC{
5449b28defe6ac85dd8a52479cf276606beae24920eDRC	return tjEncodeYUV2(handle, srcBuf, width, pitch, height,
5459b28defe6ac85dd8a52479cf276606beae24920eDRC		getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags);
546842416034561f6d5320165a4fe98825e999a4a37DRC}
547842416034561f6d5320165a4fe98825e999a4a37DRC
548842416034561f6d5320165a4fe98825e999a4a37DRC
5499b28defe6ac85dd8a52479cf276606beae24920eDRC/* Decompressor */
5502e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5519b28defe6ac85dd8a52479cf276606beae24920eDRCstatic tjhandle _tjInitDecompress(tjinstance *this)
5522e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
5539b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned char buffer[1];
5542e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5559b28defe6ac85dd8a52479cf276606beae24920eDRC	/* This is also straight out of example.c */
5569b28defe6ac85dd8a52479cf276606beae24920eDRC	this->dinfo.err=jpeg_std_error(&this->jerr.pub);
5579b28defe6ac85dd8a52479cf276606beae24920eDRC	this->jerr.pub.error_exit=my_error_exit;
5589b28defe6ac85dd8a52479cf276606beae24920eDRC	this->jerr.pub.output_message=my_output_message;
5592e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5609b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
5619b28defe6ac85dd8a52479cf276606beae24920eDRC	{
5629b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
5639b28defe6ac85dd8a52479cf276606beae24920eDRC		if(this) free(this);  return NULL;
5649e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	}
5652e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5669b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_create_decompress(&this->dinfo);
5679b28defe6ac85dd8a52479cf276606beae24920eDRC	/* Make an initial call so it will create the source manager */
5689b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_src_tj(&this->dinfo, buffer, 1);
5692e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
570007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	this->init|=DECOMPRESS;
5719b28defe6ac85dd8a52479cf276606beae24920eDRC	return (tjhandle)this;
5722e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
5732e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
574890f1e0413b54c40b663208779d4ea9dae20eaefDRCDLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
575890f1e0413b54c40b663208779d4ea9dae20eaefDRC{
5769b28defe6ac85dd8a52479cf276606beae24920eDRC	tjinstance *this;
5779b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
578da5220acdd525242bff4e40b1d90324ebb889825DRC	{
579007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		snprintf(errStr, JMSG_LENGTH_MAX,
580007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			"tjInitDecompress(): Memory allocation failure");
581da5220acdd525242bff4e40b1d90324ebb889825DRC		return NULL;
582da5220acdd525242bff4e40b1d90324ebb889825DRC	}
583007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	MEMZERO(this, sizeof(tjinstance));
5849b28defe6ac85dd8a52479cf276606beae24920eDRC	return _tjInitDecompress(this);
585890f1e0413b54c40b663208779d4ea9dae20eaefDRC}
586890f1e0413b54c40b663208779d4ea9dae20eaefDRC
5872e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5889b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle,
5899b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
5909b28defe6ac85dd8a52479cf276606beae24920eDRC	int *jpegSubsamp)
5911fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC{
59291e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	int i, k, retval=0;
5931fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
5949b28defe6ac85dd8a52479cf276606beae24920eDRC	getinstance(handle);
5959b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this->init&DECOMPRESS)==0)
596007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompressHeader2(): Instance has not been initialized for decompression");
5971fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
5989b28defe6ac85dd8a52479cf276606beae24920eDRC	if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL
5999b28defe6ac85dd8a52479cf276606beae24920eDRC		|| jpegSubsamp==NULL)
6009b28defe6ac85dd8a52479cf276606beae24920eDRC		_throw("tjDecompressHeader2(): Invalid argument");
6011fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
6029b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
6039b28defe6ac85dd8a52479cf276606beae24920eDRC	{
6049b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
6051fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC		return -1;
6061fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC	}
6071fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
6089b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
6099b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_read_header(dinfo, TRUE);
6101fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
6119b28defe6ac85dd8a52479cf276606beae24920eDRC	*width=dinfo->image_width;
6129b28defe6ac85dd8a52479cf276606beae24920eDRC	*height=dinfo->image_height;
6139b28defe6ac85dd8a52479cf276606beae24920eDRC	*jpegSubsamp=-1;
6141fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC	for(i=0; i<NUMSUBOPT; i++)
6151fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC	{
6169b28defe6ac85dd8a52479cf276606beae24920eDRC		if(dinfo->num_components==pixelsize[i])
6171fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC		{
6189b28defe6ac85dd8a52479cf276606beae24920eDRC			if(dinfo->comp_info[0].h_samp_factor==tjMCUWidth[i]/8
6199b28defe6ac85dd8a52479cf276606beae24920eDRC				&& dinfo->comp_info[0].v_samp_factor==tjMCUHeight[i]/8)
6201fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC			{
6211fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC				int match=0;
6229b28defe6ac85dd8a52479cf276606beae24920eDRC				for(k=1; k<dinfo->num_components; k++)
6231fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC				{
6249b28defe6ac85dd8a52479cf276606beae24920eDRC					if(dinfo->comp_info[k].h_samp_factor==1
6259b28defe6ac85dd8a52479cf276606beae24920eDRC						&& dinfo->comp_info[k].v_samp_factor==1)
6261fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC						match++;
6271fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC				}
6289b28defe6ac85dd8a52479cf276606beae24920eDRC				if(match==dinfo->num_components-1)
6291fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC				{
6309b28defe6ac85dd8a52479cf276606beae24920eDRC					*jpegSubsamp=i;  break;
6311fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC				}
6321fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC			}
6331fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC		}
6341fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC	}
6351fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
6369b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_abort_decompress(dinfo);
6371fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
6389b28defe6ac85dd8a52479cf276606beae24920eDRC	if(*jpegSubsamp<0)
639007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompressHeader2(): Could not determine subsampling type for JPEG image");
640007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	if(*width<1 || *height<1)
641007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompressHeader2(): Invalid data returned in header");
64291e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC
64391e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	bailout:
64491e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	return retval;
64591e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC}
64691e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC
6479b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle,
6489b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height)
64991e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC{
6509b28defe6ac85dd8a52479cf276606beae24920eDRC	int jpegSubsamp;
6519b28defe6ac85dd8a52479cf276606beae24920eDRC	return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height,
6529b28defe6ac85dd8a52479cf276606beae24920eDRC		&jpegSubsamp);
6531fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC}
6541fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
6551fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
656109a578e89ea8cd2c39d50b012698148dd11dedbDRCDLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors)
657b28fc5710a510410d2b498255a423dd62b353b3aDRC{
658109a578e89ea8cd2c39d50b012698148dd11dedbDRC	if(numscalingfactors==NULL)
659b28fc5710a510410d2b498255a423dd62b353b3aDRC	{
6609b28defe6ac85dd8a52479cf276606beae24920eDRC		snprintf(errStr, JMSG_LENGTH_MAX,
661007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			"tjGetScalingFactors(): Invalid argument");
662109a578e89ea8cd2c39d50b012698148dd11dedbDRC		return NULL;
663b28fc5710a510410d2b498255a423dd62b353b3aDRC	}
664b28fc5710a510410d2b498255a423dd62b353b3aDRC
665109a578e89ea8cd2c39d50b012698148dd11dedbDRC	*numscalingfactors=NUMSF;
666109a578e89ea8cd2c39d50b012698148dd11dedbDRC	return (tjscalingfactor *)sf;
667b28fc5710a510410d2b498255a423dd62b353b3aDRC}
668b28fc5710a510410d2b498255a423dd62b353b3aDRC
669b28fc5710a510410d2b498255a423dd62b353b3aDRC
6709b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, unsigned char *jpegBuf,
6719b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
6729b28defe6ac85dd8a52479cf276606beae24920eDRC	int height, int pixelFormat, int flags)
6739b28defe6ac85dd8a52479cf276606beae24920eDRC{
6749b28defe6ac85dd8a52479cf276606beae24920eDRC	int i, retval=0;  JSAMPROW *row_pointer=NULL;
6759b28defe6ac85dd8a52479cf276606beae24920eDRC	int jpegwidth, jpegheight, scaledw, scaledh;
6769b28defe6ac85dd8a52479cf276606beae24920eDRC
6779b28defe6ac85dd8a52479cf276606beae24920eDRC	getinstance(handle);
6789b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this->init&DECOMPRESS)==0)
679007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompress2(): Instance has not been initialized for decompression");
6809b28defe6ac85dd8a52479cf276606beae24920eDRC
6819b28defe6ac85dd8a52479cf276606beae24920eDRC	if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0
6829b28defe6ac85dd8a52479cf276606beae24920eDRC		|| height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF)
6839b28defe6ac85dd8a52479cf276606beae24920eDRC		_throw("tjDecompress2(): Invalid argument");
6849b28defe6ac85dd8a52479cf276606beae24920eDRC
68525b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
68625b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
68725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
6889b28defe6ac85dd8a52479cf276606beae24920eDRC
6899b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
6909b28defe6ac85dd8a52479cf276606beae24920eDRC	{
6919b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
6929b28defe6ac85dd8a52479cf276606beae24920eDRC		retval=-1;
6939b28defe6ac85dd8a52479cf276606beae24920eDRC		goto bailout;
6949b28defe6ac85dd8a52479cf276606beae24920eDRC	}
6959b28defe6ac85dd8a52479cf276606beae24920eDRC
6969b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
6979b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_read_header(dinfo, TRUE);
6989b28defe6ac85dd8a52479cf276606beae24920eDRC	setDecompDefaults(dinfo, pixelFormat);
6999b28defe6ac85dd8a52479cf276606beae24920eDRC
70025b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
7019b28defe6ac85dd8a52479cf276606beae24920eDRC
7029b28defe6ac85dd8a52479cf276606beae24920eDRC	jpegwidth=dinfo->image_width;  jpegheight=dinfo->image_height;
7039b28defe6ac85dd8a52479cf276606beae24920eDRC	if(width==0) width=jpegwidth;
7049b28defe6ac85dd8a52479cf276606beae24920eDRC	if(height==0) height=jpegheight;
7059b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<NUMSF; i++)
7069b28defe6ac85dd8a52479cf276606beae24920eDRC	{
7079b28defe6ac85dd8a52479cf276606beae24920eDRC		scaledw=TJSCALED(jpegwidth, sf[i]);
7089b28defe6ac85dd8a52479cf276606beae24920eDRC		scaledh=TJSCALED(jpegheight, sf[i]);
7099b28defe6ac85dd8a52479cf276606beae24920eDRC		if(scaledw<=width && scaledh<=height)
7109b28defe6ac85dd8a52479cf276606beae24920eDRC				break;
7119b28defe6ac85dd8a52479cf276606beae24920eDRC	}
7129b28defe6ac85dd8a52479cf276606beae24920eDRC	if(scaledw>width || scaledh>height)
713007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompress2(): Could not scale down to desired image dimensions");
7149b28defe6ac85dd8a52479cf276606beae24920eDRC	width=scaledw;  height=scaledh;
7159b28defe6ac85dd8a52479cf276606beae24920eDRC	dinfo->scale_num=sf[i].num;
7169b28defe6ac85dd8a52479cf276606beae24920eDRC	dinfo->scale_denom=sf[i].denom;
7179b28defe6ac85dd8a52479cf276606beae24920eDRC
7189b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_start_decompress(dinfo);
7199b28defe6ac85dd8a52479cf276606beae24920eDRC	if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
7209b28defe6ac85dd8a52479cf276606beae24920eDRC	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
7219b28defe6ac85dd8a52479cf276606beae24920eDRC		*dinfo->output_height))==NULL)
722007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompress2(): Memory allocation failure");
7239b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<(int)dinfo->output_height; i++)
7249b28defe6ac85dd8a52479cf276606beae24920eDRC	{
72525b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		if(flags&TJFLAG_BOTTOMUP)
7269b28defe6ac85dd8a52479cf276606beae24920eDRC			row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*pitch];
7279b28defe6ac85dd8a52479cf276606beae24920eDRC		else row_pointer[i]=&dstBuf[i*pitch];
7289b28defe6ac85dd8a52479cf276606beae24920eDRC	}
7299b28defe6ac85dd8a52479cf276606beae24920eDRC	while(dinfo->output_scanline<dinfo->output_height)
7309b28defe6ac85dd8a52479cf276606beae24920eDRC	{
7319b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline],
7329b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->output_height-dinfo->output_scanline);
7339b28defe6ac85dd8a52479cf276606beae24920eDRC	}
7349b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_finish_decompress(dinfo);
7359b28defe6ac85dd8a52479cf276606beae24920eDRC
7369b28defe6ac85dd8a52479cf276606beae24920eDRC	bailout:
7379b28defe6ac85dd8a52479cf276606beae24920eDRC	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
7389b28defe6ac85dd8a52479cf276606beae24920eDRC	if(row_pointer) free(row_pointer);
7399b28defe6ac85dd8a52479cf276606beae24920eDRC	return retval;
7409b28defe6ac85dd8a52479cf276606beae24920eDRC}
7419b28defe6ac85dd8a52479cf276606beae24920eDRC
7429b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf,
7439b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
7449b28defe6ac85dd8a52479cf276606beae24920eDRC	int height, int pixelSize, int flags)
7459b28defe6ac85dd8a52479cf276606beae24920eDRC{
7469b28defe6ac85dd8a52479cf276606beae24920eDRC	if(flags&TJ_YUV)
7479b28defe6ac85dd8a52479cf276606beae24920eDRC		return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags);
7489b28defe6ac85dd8a52479cf276606beae24920eDRC	else
7499b28defe6ac85dd8a52479cf276606beae24920eDRC		return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch,
7509b28defe6ac85dd8a52479cf276606beae24920eDRC			height, getPixelFormat(pixelSize, flags), flags);
7519b28defe6ac85dd8a52479cf276606beae24920eDRC}
7529b28defe6ac85dd8a52479cf276606beae24920eDRC
7539b28defe6ac85dd8a52479cf276606beae24920eDRC
7549b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle,
7559b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
756b28fc5710a510410d2b498255a423dd62b353b3aDRC	int flags)
7572e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
7589b28defe6ac85dd8a52479cf276606beae24920eDRC	int i, row, retval=0;  JSAMPROW *outbuf[MAX_COMPONENTS];
759f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS],
760f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC		tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
7619b28defe6ac85dd8a52479cf276606beae24920eDRC	JSAMPLE *_tmpbuf=NULL, *ptr=dstBuf;  JSAMPROW *tmpbuf[MAX_COMPONENTS];
7622e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
7639b28defe6ac85dd8a52479cf276606beae24920eDRC	getinstance(handle);
7649b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this->init&DECOMPRESS)==0)
765007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompressToYUV(): Instance has not been initialized for decompression");
7662e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
767f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	for(i=0; i<MAX_COMPONENTS; i++)
768f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	{
769f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC		tmpbuf[i]=NULL;  outbuf[i]=NULL;
770f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	}
7719e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC
7729b28defe6ac85dd8a52479cf276606beae24920eDRC	if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL)
7739b28defe6ac85dd8a52479cf276606beae24920eDRC		_throw("tjDecompressToYUV(): Invalid argument");
7742e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
77525b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
77625b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
77725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
7780c6a271f974529e4795332c9ad428500ef17fb42DRC
7799b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
7809b28defe6ac85dd8a52479cf276606beae24920eDRC	{
7819b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
78291e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC		retval=-1;
78391e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC		goto bailout;
7849e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	}
7852e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
7869b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
7879b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_read_header(dinfo, TRUE);
7882e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
7899b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<dinfo->num_components; i++)
7909e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	{
7919b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_component_info *compptr=&dinfo->comp_info[i];
7929b28defe6ac85dd8a52479cf276606beae24920eDRC		int ih;
7939b28defe6ac85dd8a52479cf276606beae24920eDRC		iw[i]=compptr->width_in_blocks*DCTSIZE;
7949b28defe6ac85dd8a52479cf276606beae24920eDRC		ih=compptr->height_in_blocks*DCTSIZE;
7959b28defe6ac85dd8a52479cf276606beae24920eDRC		cw[i]=PAD(dinfo->image_width, dinfo->max_h_samp_factor)
7969b28defe6ac85dd8a52479cf276606beae24920eDRC			*compptr->h_samp_factor/dinfo->max_h_samp_factor;
7979b28defe6ac85dd8a52479cf276606beae24920eDRC		ch[i]=PAD(dinfo->image_height, dinfo->max_v_samp_factor)
7989b28defe6ac85dd8a52479cf276606beae24920eDRC			*compptr->v_samp_factor/dinfo->max_v_samp_factor;
7999b28defe6ac85dd8a52479cf276606beae24920eDRC		if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1;
8009b28defe6ac85dd8a52479cf276606beae24920eDRC		th[i]=compptr->v_samp_factor*DCTSIZE;
8019b28defe6ac85dd8a52479cf276606beae24920eDRC		tmpbufsize+=iw[i]*th[i];
8029b28defe6ac85dd8a52479cf276606beae24920eDRC		if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL)
803007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			_throw("tjDecompressToYUV(): Memory allocation failure");
8049b28defe6ac85dd8a52479cf276606beae24920eDRC		for(row=0; row<ch[i]; row++)
8059e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC		{
8069b28defe6ac85dd8a52479cf276606beae24920eDRC			outbuf[i][row]=ptr;
8079b28defe6ac85dd8a52479cf276606beae24920eDRC			ptr+=PAD(cw[i], 4);
808f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC		}
8099b28defe6ac85dd8a52479cf276606beae24920eDRC	}
8109b28defe6ac85dd8a52479cf276606beae24920eDRC	if(usetmpbuf)
8119b28defe6ac85dd8a52479cf276606beae24920eDRC	{
8129b28defe6ac85dd8a52479cf276606beae24920eDRC		if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
813007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			_throw("tjDecompressToYUV(): Memory allocation failure");
8149b28defe6ac85dd8a52479cf276606beae24920eDRC		ptr=_tmpbuf;
8159b28defe6ac85dd8a52479cf276606beae24920eDRC		for(i=0; i<dinfo->num_components; i++)
816f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC		{
8179b28defe6ac85dd8a52479cf276606beae24920eDRC			if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
818007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC				_throw("tjDecompressToYUV(): Memory allocation failure");
8199b28defe6ac85dd8a52479cf276606beae24920eDRC			for(row=0; row<th[i]; row++)
820f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC			{
8219b28defe6ac85dd8a52479cf276606beae24920eDRC				tmpbuf[i][row]=ptr;
8229b28defe6ac85dd8a52479cf276606beae24920eDRC				ptr+=iw[i];
8239e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC			}
8249e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC		}
8259e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	}
8262e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
82725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
8289b28defe6ac85dd8a52479cf276606beae24920eDRC	dinfo->raw_data_out=TRUE;
8299b28defe6ac85dd8a52479cf276606beae24920eDRC
8309b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_start_decompress(dinfo);
8319b28defe6ac85dd8a52479cf276606beae24920eDRC	for(row=0; row<(int)dinfo->output_height;
8329b28defe6ac85dd8a52479cf276606beae24920eDRC		row+=dinfo->max_v_samp_factor*DCTSIZE)
8338ed7b814039172fe3cbfadfee3922801a3888b73DRC	{
8349b28defe6ac85dd8a52479cf276606beae24920eDRC		JSAMPARRAY yuvptr[MAX_COMPONENTS];
8359b28defe6ac85dd8a52479cf276606beae24920eDRC		int crow[MAX_COMPONENTS];
8369b28defe6ac85dd8a52479cf276606beae24920eDRC		for(i=0; i<dinfo->num_components; i++)
837842416034561f6d5320165a4fe98825e999a4a37DRC		{
8389b28defe6ac85dd8a52479cf276606beae24920eDRC			jpeg_component_info *compptr=&dinfo->comp_info[i];
8399b28defe6ac85dd8a52479cf276606beae24920eDRC			crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
8409b28defe6ac85dd8a52479cf276606beae24920eDRC			if(usetmpbuf) yuvptr[i]=tmpbuf[i];
8419b28defe6ac85dd8a52479cf276606beae24920eDRC			else yuvptr[i]=&outbuf[i][crow[i]];
842842416034561f6d5320165a4fe98825e999a4a37DRC		}
8439b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_read_raw_data(dinfo, yuvptr, dinfo->max_v_samp_factor*DCTSIZE);
8449b28defe6ac85dd8a52479cf276606beae24920eDRC		if(usetmpbuf)
8459e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC		{
8469b28defe6ac85dd8a52479cf276606beae24920eDRC			int j;
847f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC			for(i=0; i<dinfo->num_components; i++)
8489e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC			{
8499b28defe6ac85dd8a52479cf276606beae24920eDRC				for(j=0; j<min(th[i], ch[i]-crow[i]); j++)
850f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC				{
8519b28defe6ac85dd8a52479cf276606beae24920eDRC					memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], cw[i]);
852f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC				}
8539e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC			}
8549e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC		}
8559e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	}
8569b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_finish_decompress(dinfo);
8572e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
85891e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	bailout:
8599b28defe6ac85dd8a52479cf276606beae24920eDRC	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
8609e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	for(i=0; i<MAX_COMPONENTS; i++)
861f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	{
862f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC		if(tmpbuf[i]) free(tmpbuf[i]);
8639e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC		if(outbuf[i]) free(outbuf[i]);
864f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	}
865f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	if(_tmpbuf) free(_tmpbuf);
86691e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	return retval;
8672e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
8682e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
8692e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
8709b28defe6ac85dd8a52479cf276606beae24920eDRC/* Transformer */
871890f1e0413b54c40b663208779d4ea9dae20eaefDRC
872890f1e0413b54c40b663208779d4ea9dae20eaefDRCDLLEXPORT tjhandle DLLCALL tjInitTransform(void)
873890f1e0413b54c40b663208779d4ea9dae20eaefDRC{
8749b28defe6ac85dd8a52479cf276606beae24920eDRC	tjinstance *this=NULL;  tjhandle handle=NULL;
8759b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
876da5220acdd525242bff4e40b1d90324ebb889825DRC	{
877007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		snprintf(errStr, JMSG_LENGTH_MAX,
878007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			"tjInitTransform(): Memory allocation failure");
879da5220acdd525242bff4e40b1d90324ebb889825DRC		return NULL;
880da5220acdd525242bff4e40b1d90324ebb889825DRC	}
881007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	MEMZERO(this, sizeof(tjinstance));
8829b28defe6ac85dd8a52479cf276606beae24920eDRC	handle=_tjInitCompress(this);
8839b28defe6ac85dd8a52479cf276606beae24920eDRC	if(!handle) return NULL;
8849b28defe6ac85dd8a52479cf276606beae24920eDRC	handle=_tjInitDecompress(this);
8859b28defe6ac85dd8a52479cf276606beae24920eDRC	return handle;
886890f1e0413b54c40b663208779d4ea9dae20eaefDRC}
887890f1e0413b54c40b663208779d4ea9dae20eaefDRC
888890f1e0413b54c40b663208779d4ea9dae20eaefDRC
8899b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjTransform(tjhandle handle, unsigned char *jpegBuf,
8909b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long jpegSize, int n, unsigned char **dstBufs,
8919b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long *dstSizes, tjtransform *t, int flags)
892890f1e0413b54c40b663208779d4ea9dae20eaefDRC{
8930a325197dedd2eede99731c68ae0e0a145473f64DRC	jpeg_transform_info *xinfo=NULL;
894890f1e0413b54c40b663208779d4ea9dae20eaefDRC	jvirt_barray_ptr *srccoefs, *dstcoefs;
8950a325197dedd2eede99731c68ae0e0a145473f64DRC	int retval=0, i;
896890f1e0413b54c40b663208779d4ea9dae20eaefDRC
8979b28defe6ac85dd8a52479cf276606beae24920eDRC	getinstance(handle);
8989b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0)
899007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjTransform(): Instance has not been initialized for transformation");
900890f1e0413b54c40b663208779d4ea9dae20eaefDRC
9019b28defe6ac85dd8a52479cf276606beae24920eDRC	if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL
9020a325197dedd2eede99731c68ae0e0a145473f64DRC		|| t==NULL || flags<0)
9039b28defe6ac85dd8a52479cf276606beae24920eDRC		_throw("tjTransform(): Invalid argument");
904890f1e0413b54c40b663208779d4ea9dae20eaefDRC
90525b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
90625b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
90725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
908890f1e0413b54c40b663208779d4ea9dae20eaefDRC
9099b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
9109b28defe6ac85dd8a52479cf276606beae24920eDRC	{
9119b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
912890f1e0413b54c40b663208779d4ea9dae20eaefDRC		retval=-1;
913890f1e0413b54c40b663208779d4ea9dae20eaefDRC		goto bailout;
914890f1e0413b54c40b663208779d4ea9dae20eaefDRC	}
915890f1e0413b54c40b663208779d4ea9dae20eaefDRC
9169b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
917890f1e0413b54c40b663208779d4ea9dae20eaefDRC
9180a325197dedd2eede99731c68ae0e0a145473f64DRC	if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n))
9190a325197dedd2eede99731c68ae0e0a145473f64DRC		==NULL)
920007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjTransform(): Memory allocation failure");
921007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	MEMZERO(xinfo, sizeof(jpeg_transform_info)*n);
922890f1e0413b54c40b663208779d4ea9dae20eaefDRC
9230a325197dedd2eede99731c68ae0e0a145473f64DRC	for(i=0; i<n; i++)
924890f1e0413b54c40b663208779d4ea9dae20eaefDRC	{
9250a325197dedd2eede99731c68ae0e0a145473f64DRC		xinfo[i].transform=xformtypes[t[i].op];
92625b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0;
92725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0;
92825b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0;
92925b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0;
93025b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1;
931ba5ea5143e48b71234414139e3b4cb244599e875DRC		else xinfo[i].slow_hflip=0;
9320a325197dedd2eede99731c68ae0e0a145473f64DRC
9330a325197dedd2eede99731c68ae0e0a145473f64DRC		if(xinfo[i].crop)
934890f1e0413b54c40b663208779d4ea9dae20eaefDRC		{
9350a325197dedd2eede99731c68ae0e0a145473f64DRC			xinfo[i].crop_xoffset=t[i].r.x;  xinfo[i].crop_xoffset_set=JCROP_POS;
9360a325197dedd2eede99731c68ae0e0a145473f64DRC			xinfo[i].crop_yoffset=t[i].r.y;  xinfo[i].crop_yoffset_set=JCROP_POS;
9370a325197dedd2eede99731c68ae0e0a145473f64DRC			if(t[i].r.w!=0)
9380a325197dedd2eede99731c68ae0e0a145473f64DRC			{
9390a325197dedd2eede99731c68ae0e0a145473f64DRC				xinfo[i].crop_width=t[i].r.w;  xinfo[i].crop_width_set=JCROP_POS;
9400a325197dedd2eede99731c68ae0e0a145473f64DRC			}
941d932e582178e2352b7e1da5622183e3e6082f5b3DRC			else xinfo[i].crop_width=JCROP_UNSET;
9420a325197dedd2eede99731c68ae0e0a145473f64DRC			if(t[i].r.h!=0)
9430a325197dedd2eede99731c68ae0e0a145473f64DRC			{
9440a325197dedd2eede99731c68ae0e0a145473f64DRC				xinfo[i].crop_height=t[i].r.h;  xinfo[i].crop_height_set=JCROP_POS;
9450a325197dedd2eede99731c68ae0e0a145473f64DRC			}
946d932e582178e2352b7e1da5622183e3e6082f5b3DRC			else xinfo[i].crop_height=JCROP_UNSET;
947890f1e0413b54c40b663208779d4ea9dae20eaefDRC		}
948890f1e0413b54c40b663208779d4ea9dae20eaefDRC	}
949890f1e0413b54c40b663208779d4ea9dae20eaefDRC
9509b28defe6ac85dd8a52479cf276606beae24920eDRC	jcopy_markers_setup(dinfo, JCOPYOPT_ALL);
9519b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_read_header(dinfo, TRUE);
952890f1e0413b54c40b663208779d4ea9dae20eaefDRC
9530a325197dedd2eede99731c68ae0e0a145473f64DRC	for(i=0; i<n; i++)
954890f1e0413b54c40b663208779d4ea9dae20eaefDRC	{
9559b28defe6ac85dd8a52479cf276606beae24920eDRC		if(!jtransform_request_workspace(dinfo, &xinfo[i]))
956007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			_throw("tjTransform(): Transform is not perfect");
9570a325197dedd2eede99731c68ae0e0a145473f64DRC
9580a325197dedd2eede99731c68ae0e0a145473f64DRC		if(xinfo[i].crop)
9590a325197dedd2eede99731c68ae0e0a145473f64DRC		{
9600a325197dedd2eede99731c68ae0e0a145473f64DRC			if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0
9610a325197dedd2eede99731c68ae0e0a145473f64DRC				|| (t[i].r.y%xinfo[i].iMCU_sample_height)!=0)
9620a325197dedd2eede99731c68ae0e0a145473f64DRC			{
9639b28defe6ac85dd8a52479cf276606beae24920eDRC				snprintf(errStr, JMSG_LENGTH_MAX,
9640a325197dedd2eede99731c68ae0e0a145473f64DRC					"To crop this JPEG image, x must be a multiple of %d\n"
9650a325197dedd2eede99731c68ae0e0a145473f64DRC					"and y must be a multiple of %d.\n",
9660a325197dedd2eede99731c68ae0e0a145473f64DRC					xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height);
9670a325197dedd2eede99731c68ae0e0a145473f64DRC				retval=-1;  goto bailout;
9680a325197dedd2eede99731c68ae0e0a145473f64DRC			}
9690a325197dedd2eede99731c68ae0e0a145473f64DRC		}
970890f1e0413b54c40b663208779d4ea9dae20eaefDRC	}
971890f1e0413b54c40b663208779d4ea9dae20eaefDRC
9729b28defe6ac85dd8a52479cf276606beae24920eDRC	srccoefs=jpeg_read_coefficients(dinfo);
973890f1e0413b54c40b663208779d4ea9dae20eaefDRC
9740a325197dedd2eede99731c68ae0e0a145473f64DRC	for(i=0; i<n; i++)
975890f1e0413b54c40b663208779d4ea9dae20eaefDRC	{
976ff78e37595c8462f64fd100f928aa1d08539527eDRC		int w, h, alloc=1;
9770a325197dedd2eede99731c68ae0e0a145473f64DRC		if(!xinfo[i].crop)
978890f1e0413b54c40b663208779d4ea9dae20eaefDRC		{
9799b28defe6ac85dd8a52479cf276606beae24920eDRC			w=dinfo->image_width;  h=dinfo->image_height;
980890f1e0413b54c40b663208779d4ea9dae20eaefDRC		}
9810a325197dedd2eede99731c68ae0e0a145473f64DRC		else
9820a325197dedd2eede99731c68ae0e0a145473f64DRC		{
9830a325197dedd2eede99731c68ae0e0a145473f64DRC			w=xinfo[i].crop_width;  h=xinfo[i].crop_height;
9840a325197dedd2eede99731c68ae0e0a145473f64DRC		}
985ff78e37595c8462f64fd100f928aa1d08539527eDRC		if(flags&TJFLAG_NOREALLOC)
986ff78e37595c8462f64fd100f928aa1d08539527eDRC		{
987ff78e37595c8462f64fd100f928aa1d08539527eDRC			alloc=0;  dstSizes[i]=TJBUFSIZE(w, h);
988ff78e37595c8462f64fd100f928aa1d08539527eDRC		}
989ff78e37595c8462f64fd100f928aa1d08539527eDRC		jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc);
9909b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_copy_critical_parameters(dinfo, cinfo);
9919b28defe6ac85dd8a52479cf276606beae24920eDRC		dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs,
9920a325197dedd2eede99731c68ae0e0a145473f64DRC			&xinfo[i]);
9939b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_write_coefficients(cinfo, dstcoefs);
9949b28defe6ac85dd8a52479cf276606beae24920eDRC		jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL);
9959b28defe6ac85dd8a52479cf276606beae24920eDRC		jtransform_execute_transformation(dinfo, cinfo, srccoefs,
9960a325197dedd2eede99731c68ae0e0a145473f64DRC			&xinfo[i]);
9979b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_finish_compress(cinfo);
998890f1e0413b54c40b663208779d4ea9dae20eaefDRC	}
999890f1e0413b54c40b663208779d4ea9dae20eaefDRC
10009b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_finish_decompress(dinfo);
1001890f1e0413b54c40b663208779d4ea9dae20eaefDRC
1002890f1e0413b54c40b663208779d4ea9dae20eaefDRC	bailout:
10039b28defe6ac85dd8a52479cf276606beae24920eDRC	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
10049b28defe6ac85dd8a52479cf276606beae24920eDRC	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
10050a325197dedd2eede99731c68ae0e0a145473f64DRC	if(xinfo) free(xinfo);
1006890f1e0413b54c40b663208779d4ea9dae20eaefDRC	return retval;
1007890f1e0413b54c40b663208779d4ea9dae20eaefDRC}
1008