19b28defe6ac85dd8a52479cf276606beae24920eDRC/*
21f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC * Copyright (C)2009-2015 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
29bdfcb74d509b2c151cdc4c8b388c8a5975a7da65DRC/* TurboJPEG/LJT:  this implements the TurboJPEG API using libjpeg or
30bdfcb74d509b2c151cdc4c8b388c8a5975a7da65DRC   libjpeg-turbo */
312e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
322e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC#include <stdio.h>
332e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC#include <stdlib.h>
340713c1bb542672257c08782a5a930a577eb20167DRC#include <ctype.h>
35296c71ba0ffb034390a3d0b00a0cc6d6fa014b6eDRC#include <jinclude.h>
36fbb674707e01a61e8b7083faa632dfd46c568b13DRC#define JPEG_INTERNALS
372e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC#include <jpeglib.h>
382e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC#include <jerror.h>
392e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC#include <setjmp.h>
402e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC#include "./turbojpeg.h"
41a29294a94637d4d5efac2b03e115eb69aeeb83d0DRC#include "./tjutil.h"
42890f1e0413b54c40b663208779d4ea9dae20eaefDRC#include "transupp.h"
43418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC#include "./jpegcomp.h"
442a2e451ddc9e3c093a903ccb5a06962d05c21b67DRC
459b28defe6ac85dd8a52479cf276606beae24920eDRCextern void jpeg_mem_dest_tj(j_compress_ptr, unsigned char **,
469b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long *, boolean);
479b28defe6ac85dd8a52479cf276606beae24920eDRCextern void jpeg_mem_src_tj(j_decompress_ptr, unsigned char *, unsigned long);
489b28defe6ac85dd8a52479cf276606beae24920eDRC
49fbb674707e01a61e8b7083faa632dfd46c568b13DRC#define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
50f610d61fcc38b36a8a29879e5c053015164242f8DRC#define isPow2(x) (((x)&(x-1))==0)
512e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
522e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
539b28defe6ac85dd8a52479cf276606beae24920eDRC/* Error handling (based on example in example.c) */
542e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
559b28defe6ac85dd8a52479cf276606beae24920eDRCstatic char errStr[JMSG_LENGTH_MAX]="No error";
562e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
579b28defe6ac85dd8a52479cf276606beae24920eDRCstruct my_error_mgr
582e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
592e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC	struct jpeg_error_mgr pub;
609b28defe6ac85dd8a52479cf276606beae24920eDRC	jmp_buf setjmp_buffer;
611f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	void (*emit_message)(j_common_ptr, int);
621f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	boolean warning;
639b28defe6ac85dd8a52479cf276606beae24920eDRC};
649b28defe6ac85dd8a52479cf276606beae24920eDRCtypedef struct my_error_mgr *my_error_ptr;
652e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
662e7b76b28c0a872ae6ca002fd32bbba0769f990eDRCstatic void my_error_exit(j_common_ptr cinfo)
672e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
689b28defe6ac85dd8a52479cf276606beae24920eDRC	my_error_ptr myerr=(my_error_ptr)cinfo->err;
692e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC	(*cinfo->err->output_message)(cinfo);
709b28defe6ac85dd8a52479cf276606beae24920eDRC	longjmp(myerr->setjmp_buffer, 1);
712e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
722e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
739b28defe6ac85dd8a52479cf276606beae24920eDRC/* Based on output_message() in jerror.c */
749b28defe6ac85dd8a52479cf276606beae24920eDRC
752e7b76b28c0a872ae6ca002fd32bbba0769f990eDRCstatic void my_output_message(j_common_ptr cinfo)
762e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
779b28defe6ac85dd8a52479cf276606beae24920eDRC	(*cinfo->err->format_message)(cinfo, errStr);
782e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
792e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
801f79c7c8c8c5e993042ea816e1dd161fb69061a3DRCstatic void my_emit_message(j_common_ptr cinfo, int msg_level)
811f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC{
821f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	my_error_ptr myerr=(my_error_ptr)cinfo->err;
831f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	myerr->emit_message(cinfo, msg_level);
841f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	if(msg_level<0) myerr->warning=TRUE;
851f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC}
861f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC
872e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
889b28defe6ac85dd8a52479cf276606beae24920eDRC/* Global structures, macros, etc. */
892e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
909b28defe6ac85dd8a52479cf276606beae24920eDRCenum {COMPRESS=1, DECOMPRESS=2};
919b28defe6ac85dd8a52479cf276606beae24920eDRC
929b28defe6ac85dd8a52479cf276606beae24920eDRCtypedef struct _tjinstance
932e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
942e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC	struct jpeg_compress_struct cinfo;
952e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC	struct jpeg_decompress_struct dinfo;
969b28defe6ac85dd8a52479cf276606beae24920eDRC	struct my_error_mgr jerr;
97aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	int init, headerRead;
989b28defe6ac85dd8a52479cf276606beae24920eDRC} tjinstance;
992e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
1001f3635c4969f2319a01c9fe561958815b733227fDRCstatic const int pixelsize[TJ_NUMSAMP]={3, 3, 3, 1, 3, 3};
1019b28defe6ac85dd8a52479cf276606beae24920eDRC
102007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRCstatic const JXFORM_CODE xformtypes[TJ_NUMXOP]=
103007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC{
104890f1e0413b54c40b663208779d4ea9dae20eaefDRC	JXFORM_NONE, JXFORM_FLIP_H, JXFORM_FLIP_V, JXFORM_TRANSPOSE,
105890f1e0413b54c40b663208779d4ea9dae20eaefDRC	JXFORM_TRANSVERSE, JXFORM_ROT_90, JXFORM_ROT_180, JXFORM_ROT_270
106890f1e0413b54c40b663208779d4ea9dae20eaefDRC};
1079b28defe6ac85dd8a52479cf276606beae24920eDRC
108ab2df6ea1bfd89df619742b3a8f26e2dd7deefdbDRC#define NUMSF 16
109109a578e89ea8cd2c39d50b012698148dd11dedbDRCstatic const tjscalingfactor sf[NUMSF]={
110ab2df6ea1bfd89df619742b3a8f26e2dd7deefdbDRC	{2, 1},
111ab2df6ea1bfd89df619742b3a8f26e2dd7deefdbDRC	{15, 8},
112ab2df6ea1bfd89df619742b3a8f26e2dd7deefdbDRC	{7, 4},
113ab2df6ea1bfd89df619742b3a8f26e2dd7deefdbDRC	{13, 8},
114ab2df6ea1bfd89df619742b3a8f26e2dd7deefdbDRC	{3, 2},
115ab2df6ea1bfd89df619742b3a8f26e2dd7deefdbDRC	{11, 8},
116ab2df6ea1bfd89df619742b3a8f26e2dd7deefdbDRC	{5, 4},
117ab2df6ea1bfd89df619742b3a8f26e2dd7deefdbDRC	{9, 8},
118109a578e89ea8cd2c39d50b012698148dd11dedbDRC	{1, 1},
119ab2df6ea1bfd89df619742b3a8f26e2dd7deefdbDRC	{7, 8},
120ab2df6ea1bfd89df619742b3a8f26e2dd7deefdbDRC	{3, 4},
121ab2df6ea1bfd89df619742b3a8f26e2dd7deefdbDRC	{5, 8},
122109a578e89ea8cd2c39d50b012698148dd11dedbDRC	{1, 2},
123ab2df6ea1bfd89df619742b3a8f26e2dd7deefdbDRC	{3, 8},
124109a578e89ea8cd2c39d50b012698148dd11dedbDRC	{1, 4},
125109a578e89ea8cd2c39d50b012698148dd11dedbDRC	{1, 8}
126109a578e89ea8cd2c39d50b012698148dd11dedbDRC};
1272e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
128a29294a94637d4d5efac2b03e115eb69aeeb83d0DRC#define _throw(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s", m);  \
129da5220acdd525242bff4e40b1d90324ebb889825DRC	retval=-1;  goto bailout;}
1309b28defe6ac85dd8a52479cf276606beae24920eDRC#define getinstance(handle) tjinstance *this=(tjinstance *)handle;  \
1319b28defe6ac85dd8a52479cf276606beae24920eDRC	j_compress_ptr cinfo=NULL;  j_decompress_ptr dinfo=NULL;  \
1329b28defe6ac85dd8a52479cf276606beae24920eDRC	if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle");  \
1339b28defe6ac85dd8a52479cf276606beae24920eDRC		return -1;}  \
1341f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	cinfo=&this->cinfo;  dinfo=&this->dinfo;  \
1351f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	this->jerr.warning=FALSE;
136418616266582fa978d4d1950cf739bbdac7ebee5DRC#define getcinstance(handle) tjinstance *this=(tjinstance *)handle;  \
137418616266582fa978d4d1950cf739bbdac7ebee5DRC	j_compress_ptr cinfo=NULL;  \
138418616266582fa978d4d1950cf739bbdac7ebee5DRC	if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle");  \
139418616266582fa978d4d1950cf739bbdac7ebee5DRC		return -1;}  \
1401f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	cinfo=&this->cinfo;  \
1411f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	this->jerr.warning=FALSE;
142418616266582fa978d4d1950cf739bbdac7ebee5DRC#define getdinstance(handle) tjinstance *this=(tjinstance *)handle;  \
143418616266582fa978d4d1950cf739bbdac7ebee5DRC	j_decompress_ptr dinfo=NULL;  \
144418616266582fa978d4d1950cf739bbdac7ebee5DRC	if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle");  \
145418616266582fa978d4d1950cf739bbdac7ebee5DRC		return -1;}  \
1461f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	dinfo=&this->dinfo;  \
1471f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	this->jerr.warning=FALSE;
1489b28defe6ac85dd8a52479cf276606beae24920eDRC
1499b28defe6ac85dd8a52479cf276606beae24920eDRCstatic int getPixelFormat(int pixelSize, int flags)
1509b28defe6ac85dd8a52479cf276606beae24920eDRC{
15125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(pixelSize==1) return TJPF_GRAY;
1529b28defe6ac85dd8a52479cf276606beae24920eDRC	if(pixelSize==3)
1539b28defe6ac85dd8a52479cf276606beae24920eDRC	{
15425b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		if(flags&TJ_BGR) return TJPF_BGR;
15525b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		else return TJPF_RGB;
1569b28defe6ac85dd8a52479cf276606beae24920eDRC	}
1579b28defe6ac85dd8a52479cf276606beae24920eDRC	if(pixelSize==4)
1589b28defe6ac85dd8a52479cf276606beae24920eDRC	{
1599b28defe6ac85dd8a52479cf276606beae24920eDRC		if(flags&TJ_ALPHAFIRST)
1609b28defe6ac85dd8a52479cf276606beae24920eDRC		{
16125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC			if(flags&TJ_BGR) return TJPF_XBGR;
16225b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC			else return TJPF_XRGB;
1639b28defe6ac85dd8a52479cf276606beae24920eDRC		}
1649b28defe6ac85dd8a52479cf276606beae24920eDRC		else
1659b28defe6ac85dd8a52479cf276606beae24920eDRC		{
16625b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC			if(flags&TJ_BGR) return TJPF_BGRX;
16725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC			else return TJPF_RGBX;
1689b28defe6ac85dd8a52479cf276606beae24920eDRC		}
1699b28defe6ac85dd8a52479cf276606beae24920eDRC	}
1709b28defe6ac85dd8a52479cf276606beae24920eDRC	return -1;
1719b28defe6ac85dd8a52479cf276606beae24920eDRC}
1729b28defe6ac85dd8a52479cf276606beae24920eDRC
173f12bb305c26a25eb76d4e3d73651ef927b352c2bDRCstatic int setCompDefaults(struct jpeg_compress_struct *cinfo,
17473d74c132b399fc761ebd9a5b2f60ae2a25f5955DRC	int pixelFormat, int subsamp, int jpegQual, int flags)
1759b28defe6ac85dd8a52479cf276606beae24920eDRC{
176f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC	int retval=0;
1770713c1bb542672257c08782a5a930a577eb20167DRC	char *env=NULL;
178f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC
1799b28defe6ac85dd8a52479cf276606beae24920eDRC	switch(pixelFormat)
1809b28defe6ac85dd8a52479cf276606beae24920eDRC	{
18125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_GRAY:
1829b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_GRAYSCALE;  break;
1839b28defe6ac85dd8a52479cf276606beae24920eDRC		#if JCS_EXTENSIONS==1
18425b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGB:
1859b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_RGB;  break;
18625b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_BGR:
1879b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_BGR;  break;
18825b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGBX:
18967ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		case TJPF_RGBA:
1909b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_RGBX;  break;
19125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_BGRX:
19267ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		case TJPF_BGRA:
1939b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_BGRX;  break;
19425b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_XRGB:
19567ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		case TJPF_ARGB:
1969b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_XRGB;  break;
19725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_XBGR:
19867ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		case TJPF_ABGR:
1999b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->in_color_space=JCS_EXT_XBGR;  break;
2009b28defe6ac85dd8a52479cf276606beae24920eDRC		#else
20125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGB:
202afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_BGR:
203afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_RGBX:
204afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_BGRX:
205afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_XRGB:
206afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_XBGR:
207afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_RGBA:
208afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_BGRA:
209afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_ARGB:
210afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_ABGR:
211afc06929e0a9cf64bdf50da30326076235df7b4fDRC			cinfo->in_color_space=JCS_RGB;  pixelFormat=TJPF_RGB;
212afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
2139b28defe6ac85dd8a52479cf276606beae24920eDRC		#endif
214cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		case TJPF_CMYK:
215cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC			cinfo->in_color_space=JCS_CMYK;  break;
2169b28defe6ac85dd8a52479cf276606beae24920eDRC	}
2179b28defe6ac85dd8a52479cf276606beae24920eDRC
2189b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->input_components=tjPixelSize[pixelFormat];
2199b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_set_defaults(cinfo);
2200713c1bb542672257c08782a5a930a577eb20167DRC
221feccdcf8c89f44bd6a139200b6748daac0d39b1eDRC#ifndef NO_GETENV
2220713c1bb542672257c08782a5a930a577eb20167DRC	if((env=getenv("TJ_OPTIMIZE"))!=NULL && strlen(env)>0 && !strcmp(env, "1"))
2230713c1bb542672257c08782a5a930a577eb20167DRC		cinfo->optimize_coding=TRUE;
2240713c1bb542672257c08782a5a930a577eb20167DRC	if((env=getenv("TJ_ARITHMETIC"))!=NULL && strlen(env)>0	&& !strcmp(env, "1"))
2250713c1bb542672257c08782a5a930a577eb20167DRC		cinfo->arith_code=TRUE;
2260713c1bb542672257c08782a5a930a577eb20167DRC	if((env=getenv("TJ_RESTART"))!=NULL && strlen(env)>0)
2270713c1bb542672257c08782a5a930a577eb20167DRC	{
2280713c1bb542672257c08782a5a930a577eb20167DRC		int temp=-1;  char tempc=0;
2290713c1bb542672257c08782a5a930a577eb20167DRC		if(sscanf(env, "%d%c", &temp, &tempc)>=1 && temp>=0 && temp<=65535)
2300713c1bb542672257c08782a5a930a577eb20167DRC		{
2310713c1bb542672257c08782a5a930a577eb20167DRC			if(toupper(tempc)=='B')
2320713c1bb542672257c08782a5a930a577eb20167DRC			{
2330713c1bb542672257c08782a5a930a577eb20167DRC				cinfo->restart_interval=temp;
2340713c1bb542672257c08782a5a930a577eb20167DRC				cinfo->restart_in_rows=0;
2350713c1bb542672257c08782a5a930a577eb20167DRC			}
2360713c1bb542672257c08782a5a930a577eb20167DRC			else
2370713c1bb542672257c08782a5a930a577eb20167DRC				cinfo->restart_in_rows=temp;
2380713c1bb542672257c08782a5a930a577eb20167DRC		}
2390713c1bb542672257c08782a5a930a577eb20167DRC	}
240feccdcf8c89f44bd6a139200b6748daac0d39b1eDRC#endif
2410713c1bb542672257c08782a5a930a577eb20167DRC
2429b28defe6ac85dd8a52479cf276606beae24920eDRC	if(jpegQual>=0)
2439b28defe6ac85dd8a52479cf276606beae24920eDRC	{
2449b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_set_quality(cinfo, jpegQual, TRUE);
24573d74c132b399fc761ebd9a5b2f60ae2a25f5955DRC		if(jpegQual>=96 || flags&TJFLAG_ACCURATEDCT) cinfo->dct_method=JDCT_ISLOW;
2469b28defe6ac85dd8a52479cf276606beae24920eDRC		else cinfo->dct_method=JDCT_FASTEST;
2479b28defe6ac85dd8a52479cf276606beae24920eDRC	}
24825b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(subsamp==TJSAMP_GRAY)
2499b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
250cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC	else if(pixelFormat==TJPF_CMYK)
251cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		jpeg_set_colorspace(cinfo, JCS_YCCK);
252cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC	else jpeg_set_colorspace(cinfo, JCS_YCbCr);
2539b28defe6ac85dd8a52479cf276606beae24920eDRC
254feccdcf8c89f44bd6a139200b6748daac0d39b1eDRC#ifndef NO_GETENV
2550713c1bb542672257c08782a5a930a577eb20167DRC	if((env=getenv("TJ_PROGRESSIVE"))!=NULL && strlen(env)>0
2560713c1bb542672257c08782a5a930a577eb20167DRC		&& !strcmp(env, "1"))
2570713c1bb542672257c08782a5a930a577eb20167DRC		jpeg_simple_progression(cinfo);
258feccdcf8c89f44bd6a139200b6748daac0d39b1eDRC#endif
2590713c1bb542672257c08782a5a930a577eb20167DRC
2609b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[0].h_samp_factor=tjMCUWidth[subsamp]/8;
2619b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[1].h_samp_factor=1;
2629b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[2].h_samp_factor=1;
263cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC	if(cinfo->num_components>3)
264cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		cinfo->comp_info[3].h_samp_factor=tjMCUWidth[subsamp]/8;
2659b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[0].v_samp_factor=tjMCUHeight[subsamp]/8;
2669b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[1].v_samp_factor=1;
2679b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->comp_info[2].v_samp_factor=1;
268cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC	if(cinfo->num_components>3)
269cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		cinfo->comp_info[3].v_samp_factor=tjMCUHeight[subsamp]/8;
270f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC
271f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC	return retval;
2729b28defe6ac85dd8a52479cf276606beae24920eDRC}
2739b28defe6ac85dd8a52479cf276606beae24920eDRC
274f12bb305c26a25eb76d4e3d73651ef927b352c2bDRCstatic int setDecompDefaults(struct jpeg_decompress_struct *dinfo,
27573d74c132b399fc761ebd9a5b2f60ae2a25f5955DRC	int pixelFormat, int flags)
2769b28defe6ac85dd8a52479cf276606beae24920eDRC{
277f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC	int retval=0;
278f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC
2799b28defe6ac85dd8a52479cf276606beae24920eDRC	switch(pixelFormat)
2809b28defe6ac85dd8a52479cf276606beae24920eDRC	{
28125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_GRAY:
2829b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_GRAYSCALE;  break;
2839b28defe6ac85dd8a52479cf276606beae24920eDRC		#if JCS_EXTENSIONS==1
28425b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGB:
2859b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_RGB;  break;
28625b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_BGR:
2879b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_BGR;  break;
28825b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGBX:
2899b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_RGBX;  break;
29025b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_BGRX:
2919b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_BGRX;  break;
29225b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_XRGB:
2939b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_XRGB;  break;
29425b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_XBGR:
2959b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->out_color_space=JCS_EXT_XBGR;  break;
29667ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		#if JCS_ALPHA_EXTENSIONS==1
29767ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		case TJPF_RGBA:
29867ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC			dinfo->out_color_space=JCS_EXT_RGBA;  break;
29967ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		case TJPF_BGRA:
30067ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC			dinfo->out_color_space=JCS_EXT_BGRA;  break;
30167ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		case TJPF_ARGB:
30267ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC			dinfo->out_color_space=JCS_EXT_ARGB;  break;
30367ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		case TJPF_ABGR:
30467ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC			dinfo->out_color_space=JCS_EXT_ABGR;  break;
30567ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		#endif
3069b28defe6ac85dd8a52479cf276606beae24920eDRC		#else
30725b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		case TJPF_RGB:
308afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_BGR:
309afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_RGBX:
310afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_BGRX:
311afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_XRGB:
312afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_XBGR:
313afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_RGBA:
314afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_BGRA:
315afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_ARGB:
316afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_ABGR:
317afc06929e0a9cf64bdf50da30326076235df7b4fDRC			dinfo->out_color_space=JCS_RGB;  break;
31867ce3b2352fe1f7511edbfed74ec6960e41e97dcDRC		#endif
319cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		case TJPF_CMYK:
320cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC			dinfo->out_color_space=JCS_CMYK;  break;
3219b28defe6ac85dd8a52479cf276606beae24920eDRC		default:
3229b28defe6ac85dd8a52479cf276606beae24920eDRC			_throw("Unsupported pixel format");
3239b28defe6ac85dd8a52479cf276606beae24920eDRC	}
324f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC
32573d74c132b399fc761ebd9a5b2f60ae2a25f5955DRC	if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
32673d74c132b399fc761ebd9a5b2f60ae2a25f5955DRC
327f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC	bailout:
328f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC	return retval;
3299b28defe6ac85dd8a52479cf276606beae24920eDRC}
3302e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
3312e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
3329b49f0e4c77c727648c6d3a4915eefdf5436de4aDRCstatic int getSubsamp(j_decompress_ptr dinfo)
3339b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC{
3349b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	int retval=-1, i, k;
335ea1eea47423df40809f165519094761045e832aeDRC
336ea1eea47423df40809f165519094761045e832aeDRC	/* The sampling factors actually have no meaning with grayscale JPEG files,
337ea1eea47423df40809f165519094761045e832aeDRC	   and in fact it's possible to generate grayscale JPEGs with sampling
338ea1eea47423df40809f165519094761045e832aeDRC	   factors > 1 (even though those sampling factors are ignored by the
339ea1eea47423df40809f165519094761045e832aeDRC	   decompressor.)  Thus, we need to treat grayscale as a special case. */
340ea1eea47423df40809f165519094761045e832aeDRC	if(dinfo->num_components==1 && dinfo->jpeg_color_space==JCS_GRAYSCALE)
341ea1eea47423df40809f165519094761045e832aeDRC		return TJSAMP_GRAY;
342ea1eea47423df40809f165519094761045e832aeDRC
3439b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	for(i=0; i<NUMSUBOPT; i++)
3449b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	{
345cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		if(dinfo->num_components==pixelsize[i]
346cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC			|| ((dinfo->jpeg_color_space==JCS_YCCK
347cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC				|| dinfo->jpeg_color_space==JCS_CMYK)
348cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC					&& pixelsize[i]==3 && dinfo->num_components==4))
3499b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC		{
3509b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC			if(dinfo->comp_info[0].h_samp_factor==tjMCUWidth[i]/8
3519b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC				&& dinfo->comp_info[0].v_samp_factor==tjMCUHeight[i]/8)
3529b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC			{
3539b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC				int match=0;
3549b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC				for(k=1; k<dinfo->num_components; k++)
3559b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC				{
356cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC					int href=1, vref=1;
357cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC					if(dinfo->jpeg_color_space==JCS_YCCK && k==3)
358cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC					{
359cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC						href=tjMCUWidth[i]/8;  vref=tjMCUHeight[i]/8;
360cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC					}
361cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC					if(dinfo->comp_info[k].h_samp_factor==href
362cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC						&& dinfo->comp_info[k].v_samp_factor==vref)
3639b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC						match++;
3649b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC				}
3659b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC				if(match==dinfo->num_components-1)
3669b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC				{
3679b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC					retval=i;  break;
3689b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC				}
3699b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC			}
3709b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC		}
3719b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	}
3729b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	return retval;
3739b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC}
3749b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC
3759b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC
376afc06929e0a9cf64bdf50da30326076235df7b4fDRC#ifndef JCS_EXTENSIONS
377afc06929e0a9cf64bdf50da30326076235df7b4fDRC
378afc06929e0a9cf64bdf50da30326076235df7b4fDRC/* Conversion functions to emulate the colorspace extensions.  This allows the
379afc06929e0a9cf64bdf50da30326076235df7b4fDRC   TurboJPEG wrapper to be used with libjpeg */
380afc06929e0a9cf64bdf50da30326076235df7b4fDRC
381afc06929e0a9cf64bdf50da30326076235df7b4fDRC#define TORGB(PS, ROFFSET, GOFFSET, BOFFSET) {  \
382afc06929e0a9cf64bdf50da30326076235df7b4fDRC	int rowPad=pitch-width*PS;  \
383afc06929e0a9cf64bdf50da30326076235df7b4fDRC	while(height--)  \
384afc06929e0a9cf64bdf50da30326076235df7b4fDRC	{  \
385afc06929e0a9cf64bdf50da30326076235df7b4fDRC		unsigned char *endOfRow=src+width*PS;  \
386afc06929e0a9cf64bdf50da30326076235df7b4fDRC		while(src<endOfRow)  \
387afc06929e0a9cf64bdf50da30326076235df7b4fDRC		{  \
388afc06929e0a9cf64bdf50da30326076235df7b4fDRC			dst[RGB_RED]=src[ROFFSET];  \
389afc06929e0a9cf64bdf50da30326076235df7b4fDRC			dst[RGB_GREEN]=src[GOFFSET];  \
390afc06929e0a9cf64bdf50da30326076235df7b4fDRC			dst[RGB_BLUE]=src[BOFFSET];  \
391afc06929e0a9cf64bdf50da30326076235df7b4fDRC			dst+=RGB_PIXELSIZE;  src+=PS;  \
392afc06929e0a9cf64bdf50da30326076235df7b4fDRC		}  \
393afc06929e0a9cf64bdf50da30326076235df7b4fDRC		src+=rowPad;  \
394afc06929e0a9cf64bdf50da30326076235df7b4fDRC	}  \
395afc06929e0a9cf64bdf50da30326076235df7b4fDRC}
396afc06929e0a9cf64bdf50da30326076235df7b4fDRC
397afc06929e0a9cf64bdf50da30326076235df7b4fDRCstatic unsigned char *toRGB(unsigned char *src, int width, int pitch,
398afc06929e0a9cf64bdf50da30326076235df7b4fDRC	int height, int pixelFormat, unsigned char *dst)
399afc06929e0a9cf64bdf50da30326076235df7b4fDRC{
400afc06929e0a9cf64bdf50da30326076235df7b4fDRC	unsigned char *retval=src;
401afc06929e0a9cf64bdf50da30326076235df7b4fDRC	switch(pixelFormat)
402afc06929e0a9cf64bdf50da30326076235df7b4fDRC	{
403afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_RGB:
404afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3
405afc06929e0a9cf64bdf50da30326076235df7b4fDRC			retval=dst;  TORGB(3, 0, 1, 2);
406afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#endif
407afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
408afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_BGR:
409afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3
410afc06929e0a9cf64bdf50da30326076235df7b4fDRC			retval=dst;  TORGB(3, 2, 1, 0);
411afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#endif
412afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
413afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_RGBX:
414afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_RGBA:
415afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
416afc06929e0a9cf64bdf50da30326076235df7b4fDRC			retval=dst;  TORGB(4, 0, 1, 2);
417afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#endif
418afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
419afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_BGRX:
420afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_BGRA:
421afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
422afc06929e0a9cf64bdf50da30326076235df7b4fDRC			retval=dst;  TORGB(4, 2, 1, 0);
423afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#endif
424afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
425afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_XRGB:
426afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_ARGB:
427afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
428afc06929e0a9cf64bdf50da30326076235df7b4fDRC			retval=dst;  TORGB(4, 1, 2, 3);
429afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#endif
430afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
431afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_XBGR:
432afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_ABGR:
433afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
434afc06929e0a9cf64bdf50da30326076235df7b4fDRC			retval=dst;  TORGB(4, 3, 2, 1);
435afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#endif
436afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
437afc06929e0a9cf64bdf50da30326076235df7b4fDRC	}
438afc06929e0a9cf64bdf50da30326076235df7b4fDRC	return retval;
439afc06929e0a9cf64bdf50da30326076235df7b4fDRC}
440afc06929e0a9cf64bdf50da30326076235df7b4fDRC
441afc06929e0a9cf64bdf50da30326076235df7b4fDRC#define FROMRGB(PS, ROFFSET, GOFFSET, BOFFSET, SETALPHA) {  \
442afc06929e0a9cf64bdf50da30326076235df7b4fDRC	int rowPad=pitch-width*PS;  \
443afc06929e0a9cf64bdf50da30326076235df7b4fDRC	while(height--)  \
444afc06929e0a9cf64bdf50da30326076235df7b4fDRC	{  \
445afc06929e0a9cf64bdf50da30326076235df7b4fDRC		unsigned char *endOfRow=dst+width*PS;  \
446afc06929e0a9cf64bdf50da30326076235df7b4fDRC		while(dst<endOfRow)  \
447afc06929e0a9cf64bdf50da30326076235df7b4fDRC		{  \
448afc06929e0a9cf64bdf50da30326076235df7b4fDRC			dst[ROFFSET]=src[RGB_RED];  \
449afc06929e0a9cf64bdf50da30326076235df7b4fDRC			dst[GOFFSET]=src[RGB_GREEN];  \
450afc06929e0a9cf64bdf50da30326076235df7b4fDRC			dst[BOFFSET]=src[RGB_BLUE];  \
451afc06929e0a9cf64bdf50da30326076235df7b4fDRC			SETALPHA  \
452afc06929e0a9cf64bdf50da30326076235df7b4fDRC			dst+=PS;  src+=RGB_PIXELSIZE;  \
453afc06929e0a9cf64bdf50da30326076235df7b4fDRC		}  \
454afc06929e0a9cf64bdf50da30326076235df7b4fDRC		dst+=rowPad;  \
455afc06929e0a9cf64bdf50da30326076235df7b4fDRC	}  \
456afc06929e0a9cf64bdf50da30326076235df7b4fDRC}
457afc06929e0a9cf64bdf50da30326076235df7b4fDRC
458afc06929e0a9cf64bdf50da30326076235df7b4fDRCstatic void fromRGB(unsigned char *src, unsigned char *dst, int width,
459afc06929e0a9cf64bdf50da30326076235df7b4fDRC	int pitch, int height, int pixelFormat)
460afc06929e0a9cf64bdf50da30326076235df7b4fDRC{
461afc06929e0a9cf64bdf50da30326076235df7b4fDRC	switch(pixelFormat)
462afc06929e0a9cf64bdf50da30326076235df7b4fDRC	{
463afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_RGB:
464afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3
465afc06929e0a9cf64bdf50da30326076235df7b4fDRC			FROMRGB(3, 0, 1, 2,);
466afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#endif
467afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
468afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_BGR:
469afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3
470afc06929e0a9cf64bdf50da30326076235df7b4fDRC			FROMRGB(3, 2, 1, 0,);
471afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#endif
472afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
473afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_RGBX:
474afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
475afc06929e0a9cf64bdf50da30326076235df7b4fDRC			FROMRGB(4, 0, 1, 2,);
476afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#endif
477afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
478afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_RGBA:
479afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
480afc06929e0a9cf64bdf50da30326076235df7b4fDRC			FROMRGB(4, 0, 1, 2, dst[3]=0xFF;);
481afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#endif
482afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
483afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_BGRX:
484afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
485afc06929e0a9cf64bdf50da30326076235df7b4fDRC			FROMRGB(4, 2, 1, 0,);
486afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#endif
487afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
488afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_BGRA:
489afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
490afc06929e0a9cf64bdf50da30326076235df7b4fDRC			FROMRGB(4, 2, 1, 0, dst[3]=0xFF;);  return;
491afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#endif
492afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
493afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_XRGB:
494afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
495afc06929e0a9cf64bdf50da30326076235df7b4fDRC			FROMRGB(4, 1, 2, 3,);  return;
496afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#endif
497afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
498afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_ARGB:
499afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
500afc06929e0a9cf64bdf50da30326076235df7b4fDRC			FROMRGB(4, 1, 2, 3, dst[0]=0xFF;);  return;
501afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#endif
502afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
503afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_XBGR:
504afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
505afc06929e0a9cf64bdf50da30326076235df7b4fDRC			FROMRGB(4, 3, 2, 1,);  return;
506afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#endif
507afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
508afc06929e0a9cf64bdf50da30326076235df7b4fDRC		case TJPF_ABGR:
509afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
510afc06929e0a9cf64bdf50da30326076235df7b4fDRC			FROMRGB(4, 3, 2, 1, dst[0]=0xFF;);  return;
511afc06929e0a9cf64bdf50da30326076235df7b4fDRC			#endif
512afc06929e0a9cf64bdf50da30326076235df7b4fDRC			break;
513afc06929e0a9cf64bdf50da30326076235df7b4fDRC	}
514afc06929e0a9cf64bdf50da30326076235df7b4fDRC}
515afc06929e0a9cf64bdf50da30326076235df7b4fDRC
516afc06929e0a9cf64bdf50da30326076235df7b4fDRC#endif
517afc06929e0a9cf64bdf50da30326076235df7b4fDRC
518afc06929e0a9cf64bdf50da30326076235df7b4fDRC
5199b28defe6ac85dd8a52479cf276606beae24920eDRC/* General API functions */
5202e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5219b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT char* DLLCALL tjGetErrorStr(void)
5222e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
5239b28defe6ac85dd8a52479cf276606beae24920eDRC	return errStr;
5242e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
5252e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5269b28defe6ac85dd8a52479cf276606beae24920eDRC
5279b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjDestroy(tjhandle handle)
5282e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
5299b28defe6ac85dd8a52479cf276606beae24920eDRC	getinstance(handle);
5309b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer)) return -1;
5319b28defe6ac85dd8a52479cf276606beae24920eDRC	if(this->init&COMPRESS) jpeg_destroy_compress(cinfo);
5329b28defe6ac85dd8a52479cf276606beae24920eDRC	if(this->init&DECOMPRESS) jpeg_destroy_decompress(dinfo);
5339b28defe6ac85dd8a52479cf276606beae24920eDRC	free(this);
5349b28defe6ac85dd8a52479cf276606beae24920eDRC	return 0;
5352e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
5362e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5379b28defe6ac85dd8a52479cf276606beae24920eDRC
5386b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC/* These are exposed mainly because Windows can't malloc() and free() across
5396b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC   DLL boundaries except when the CRT DLL is used, and we don't use the CRT DLL
5406b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC   with turbojpeg.dll for compatibility reasons.  However, these functions
5416b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC   can potentially be used for other purposes by different implementations. */
5426b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC
5436b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRCDLLEXPORT void DLLCALL tjFree(unsigned char *buf)
5446b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC{
5456b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC	if(buf) free(buf);
5466b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC}
5476b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC
5486b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC
5496b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRCDLLEXPORT unsigned char *DLLCALL tjAlloc(int bytes)
5506b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC{
5516b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC	return (unsigned char *)malloc(bytes);
5526b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC}
5536b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC
5546b76f75d2c0ebdc462f6bc663289fa4bfde1629aDRC
5559b28defe6ac85dd8a52479cf276606beae24920eDRC/* Compressor  */
5569b28defe6ac85dd8a52479cf276606beae24920eDRC
5579b28defe6ac85dd8a52479cf276606beae24920eDRCstatic tjhandle _tjInitCompress(tjinstance *this)
5582e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
5599b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned char buffer[1], *buf=buffer;  unsigned long size=1;
5609b28defe6ac85dd8a52479cf276606beae24920eDRC
5619b28defe6ac85dd8a52479cf276606beae24920eDRC	/* This is also straight out of example.c */
5629b28defe6ac85dd8a52479cf276606beae24920eDRC	this->cinfo.err=jpeg_std_error(&this->jerr.pub);
5639b28defe6ac85dd8a52479cf276606beae24920eDRC	this->jerr.pub.error_exit=my_error_exit;
5649b28defe6ac85dd8a52479cf276606beae24920eDRC	this->jerr.pub.output_message=my_output_message;
5651f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	this->jerr.emit_message=this->jerr.pub.emit_message;
5661f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	this->jerr.pub.emit_message=my_emit_message;
5672e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5689b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
5699b28defe6ac85dd8a52479cf276606beae24920eDRC	{
5709b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
5719b28defe6ac85dd8a52479cf276606beae24920eDRC		if(this) free(this);  return NULL;
572efa4ddcc88783c7b8bf5cba42c6680132eefa628DRC	}
5732e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
5749b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_create_compress(&this->cinfo);
5759b28defe6ac85dd8a52479cf276606beae24920eDRC	/* Make an initial call so it will create the destination manager */
5769b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_dest_tj(&this->cinfo, &buf, &size, 0);
5772e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
578007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	this->init|=COMPRESS;
5799b28defe6ac85dd8a52479cf276606beae24920eDRC	return (tjhandle)this;
5802e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
5812e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
582890f1e0413b54c40b663208779d4ea9dae20eaefDRCDLLEXPORT tjhandle DLLCALL tjInitCompress(void)
583890f1e0413b54c40b663208779d4ea9dae20eaefDRC{
5849b28defe6ac85dd8a52479cf276606beae24920eDRC	tjinstance *this=NULL;
5859b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
586da5220acdd525242bff4e40b1d90324ebb889825DRC	{
587007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		snprintf(errStr, JMSG_LENGTH_MAX,
588007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			"tjInitCompress(): Memory allocation failure");
589da5220acdd525242bff4e40b1d90324ebb889825DRC		return NULL;
590da5220acdd525242bff4e40b1d90324ebb889825DRC	}
591007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	MEMZERO(this, sizeof(tjinstance));
5929b28defe6ac85dd8a52479cf276606beae24920eDRC	return _tjInitCompress(this);
593890f1e0413b54c40b663208779d4ea9dae20eaefDRC}
594890f1e0413b54c40b663208779d4ea9dae20eaefDRC
595842416034561f6d5320165a4fe98825e999a4a37DRC
5969b49f0e4c77c727648c6d3a4915eefdf5436de4aDRCDLLEXPORT unsigned long DLLCALL tjBufSize(int width, int height,
5979b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	int jpegSubsamp)
5989b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC{
5999b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	unsigned long retval=0;  int mcuw, mcuh, chromasf;
6009b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	if(width<1 || height<1 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT)
6019b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC		_throw("tjBufSize(): Invalid argument");
6029b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC
603006bc58dd6a8c68f4b3a26511e8684f5f3f1508aDRC	/* This allows for rare corner cases in which a JPEG image can actually be
604006bc58dd6a8c68f4b3a26511e8684f5f3f1508aDRC	   larger than the uncompressed input (we wouldn't mention it if it hadn't
605006bc58dd6a8c68f4b3a26511e8684f5f3f1508aDRC	   happened before.) */
6069b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	mcuw=tjMCUWidth[jpegSubsamp];
6079b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	mcuh=tjMCUHeight[jpegSubsamp];
6089b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	chromasf=jpegSubsamp==TJSAMP_GRAY? 0: 4*64/(mcuw*mcuh);
6099b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	retval=PAD(width, mcuw) * PAD(height, mcuh) * (2 + chromasf) + 2048;
6109b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC
6119b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	bailout:
6129b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	return retval;
6139b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC}
6149b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC
6152e7b76b28c0a872ae6ca002fd32bbba0769f990eDRCDLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
6162e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
617f3cf973e8e51e0078f402ca5547c026967c27321DRC	unsigned long retval=0;
618f3cf973e8e51e0078f402ca5547c026967c27321DRC	if(width<1 || height<1)
619007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("TJBUFSIZE(): Invalid argument");
620f3cf973e8e51e0078f402ca5547c026967c27321DRC
621006bc58dd6a8c68f4b3a26511e8684f5f3f1508aDRC	/* This allows for rare corner cases in which a JPEG image can actually be
622006bc58dd6a8c68f4b3a26511e8684f5f3f1508aDRC	   larger than the uncompressed input (we wouldn't mention it if it hadn't
623006bc58dd6a8c68f4b3a26511e8684f5f3f1508aDRC	   happened before.) */
624007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	retval=PAD(width, 16) * PAD(height, 16) * 6 + 2048;
625f3cf973e8e51e0078f402ca5547c026967c27321DRC
626f3cf973e8e51e0078f402ca5547c026967c27321DRC	bailout:
627f3cf973e8e51e0078f402ca5547c026967c27321DRC	return retval;
628f3cf973e8e51e0078f402ca5547c026967c27321DRC}
629f3cf973e8e51e0078f402ca5547c026967c27321DRC
630842416034561f6d5320165a4fe98825e999a4a37DRC
631f610d61fcc38b36a8a29879e5c053015164242f8DRCDLLEXPORT unsigned long DLLCALL tjBufSizeYUV2(int width, int pad, int height,
632f3cf973e8e51e0078f402ca5547c026967c27321DRC	int subsamp)
633f3cf973e8e51e0078f402ca5547c026967c27321DRC{
63440dd3146cde2ba5036fe76a4f09e1125b4592347DRC	int retval=0, nc, i;
63540dd3146cde2ba5036fe76a4f09e1125b4592347DRC
63640dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if(subsamp<0 || subsamp>=NUMSUBOPT)
637f610d61fcc38b36a8a29879e5c053015164242f8DRC		_throw("tjBufSizeYUV2(): Invalid argument");
63840dd3146cde2ba5036fe76a4f09e1125b4592347DRC
63940dd3146cde2ba5036fe76a4f09e1125b4592347DRC	nc=(subsamp==TJSAMP_GRAY? 1:3);
64040dd3146cde2ba5036fe76a4f09e1125b4592347DRC	for(i=0; i<nc; i++)
64140dd3146cde2ba5036fe76a4f09e1125b4592347DRC	{
64255620c6ef28b02524dc763ba5ffc438c4a08419bDRC		int pw=tjPlaneWidth(i, width, subsamp);
64355620c6ef28b02524dc763ba5ffc438c4a08419bDRC		int stride=PAD(pw, pad);
64440dd3146cde2ba5036fe76a4f09e1125b4592347DRC		int ph=tjPlaneHeight(i, height, subsamp);
64555620c6ef28b02524dc763ba5ffc438c4a08419bDRC		if(pw<0 || ph<0) return -1;
64640dd3146cde2ba5036fe76a4f09e1125b4592347DRC		else retval+=stride*ph;
64740dd3146cde2ba5036fe76a4f09e1125b4592347DRC	}
648f3cf973e8e51e0078f402ca5547c026967c27321DRC
649f3cf973e8e51e0078f402ca5547c026967c27321DRC	bailout:
650f3cf973e8e51e0078f402ca5547c026967c27321DRC	return retval;
6512e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
6522e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
653f610d61fcc38b36a8a29879e5c053015164242f8DRCDLLEXPORT unsigned long DLLCALL tjBufSizeYUV(int width, int height,
654f610d61fcc38b36a8a29879e5c053015164242f8DRC	int subsamp)
655f610d61fcc38b36a8a29879e5c053015164242f8DRC{
656f610d61fcc38b36a8a29879e5c053015164242f8DRC	return tjBufSizeYUV2(width, 4, height, subsamp);
657f610d61fcc38b36a8a29879e5c053015164242f8DRC}
658842416034561f6d5320165a4fe98825e999a4a37DRC
6599b49f0e4c77c727648c6d3a4915eefdf5436de4aDRCDLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
6609b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	int subsamp)
6619b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC{
6629b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	return tjBufSizeYUV(width, height, subsamp);
6639b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC}
6649b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC
6659b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC
66640dd3146cde2ba5036fe76a4f09e1125b4592347DRCDLLEXPORT int tjPlaneWidth(int componentID, int width, int subsamp)
66740dd3146cde2ba5036fe76a4f09e1125b4592347DRC{
66840dd3146cde2ba5036fe76a4f09e1125b4592347DRC	int pw, nc, retval=0;
66940dd3146cde2ba5036fe76a4f09e1125b4592347DRC
67040dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if(width<1 || subsamp<0 || subsamp>=TJ_NUMSAMP)
67140dd3146cde2ba5036fe76a4f09e1125b4592347DRC		_throw("tjPlaneWidth(): Invalid argument");
67240dd3146cde2ba5036fe76a4f09e1125b4592347DRC	nc=(subsamp==TJSAMP_GRAY? 1:3);
67340dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if(componentID<0 || componentID>=nc)
67440dd3146cde2ba5036fe76a4f09e1125b4592347DRC		_throw("tjPlaneWidth(): Invalid argument");
67540dd3146cde2ba5036fe76a4f09e1125b4592347DRC
67640dd3146cde2ba5036fe76a4f09e1125b4592347DRC	pw=PAD(width, tjMCUWidth[subsamp]/8);
67740dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if(componentID==0)
67840dd3146cde2ba5036fe76a4f09e1125b4592347DRC		retval=pw;
67940dd3146cde2ba5036fe76a4f09e1125b4592347DRC	else
68040dd3146cde2ba5036fe76a4f09e1125b4592347DRC		retval=pw*8/tjMCUWidth[subsamp];
68140dd3146cde2ba5036fe76a4f09e1125b4592347DRC
68240dd3146cde2ba5036fe76a4f09e1125b4592347DRC	bailout:
68340dd3146cde2ba5036fe76a4f09e1125b4592347DRC	return retval;
68440dd3146cde2ba5036fe76a4f09e1125b4592347DRC}
68540dd3146cde2ba5036fe76a4f09e1125b4592347DRC
68640dd3146cde2ba5036fe76a4f09e1125b4592347DRC
68740dd3146cde2ba5036fe76a4f09e1125b4592347DRCDLLEXPORT int tjPlaneHeight(int componentID, int height, int subsamp)
68840dd3146cde2ba5036fe76a4f09e1125b4592347DRC{
68940dd3146cde2ba5036fe76a4f09e1125b4592347DRC	int ph, nc, retval=0;
69040dd3146cde2ba5036fe76a4f09e1125b4592347DRC
69140dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if(height<1 || subsamp<0 || subsamp>=TJ_NUMSAMP)
69240dd3146cde2ba5036fe76a4f09e1125b4592347DRC		_throw("tjPlaneHeight(): Invalid argument");
69340dd3146cde2ba5036fe76a4f09e1125b4592347DRC	nc=(subsamp==TJSAMP_GRAY? 1:3);
69440dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if(componentID<0 || componentID>=nc)
69540dd3146cde2ba5036fe76a4f09e1125b4592347DRC		_throw("tjPlaneHeight(): Invalid argument");
69640dd3146cde2ba5036fe76a4f09e1125b4592347DRC
69740dd3146cde2ba5036fe76a4f09e1125b4592347DRC	ph=PAD(height, tjMCUHeight[subsamp]/8);
69840dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if(componentID==0)
69940dd3146cde2ba5036fe76a4f09e1125b4592347DRC		retval=ph;
70040dd3146cde2ba5036fe76a4f09e1125b4592347DRC	else
70140dd3146cde2ba5036fe76a4f09e1125b4592347DRC		retval=ph*8/tjMCUHeight[subsamp];
70240dd3146cde2ba5036fe76a4f09e1125b4592347DRC
70340dd3146cde2ba5036fe76a4f09e1125b4592347DRC	bailout:
70440dd3146cde2ba5036fe76a4f09e1125b4592347DRC	return retval;
70540dd3146cde2ba5036fe76a4f09e1125b4592347DRC}
70640dd3146cde2ba5036fe76a4f09e1125b4592347DRC
70740dd3146cde2ba5036fe76a4f09e1125b4592347DRC
70840dd3146cde2ba5036fe76a4f09e1125b4592347DRCDLLEXPORT unsigned long DLLCALL tjPlaneSizeYUV(int componentID, int width,
70940dd3146cde2ba5036fe76a4f09e1125b4592347DRC	int stride, int height, int subsamp)
71040dd3146cde2ba5036fe76a4f09e1125b4592347DRC{
71140dd3146cde2ba5036fe76a4f09e1125b4592347DRC	unsigned long retval=0;
71240dd3146cde2ba5036fe76a4f09e1125b4592347DRC	int pw, ph;
71340dd3146cde2ba5036fe76a4f09e1125b4592347DRC
71440dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if(width<1 || height<1 || subsamp<0 || subsamp>=NUMSUBOPT)
71540dd3146cde2ba5036fe76a4f09e1125b4592347DRC		_throw("tjPlaneSizeYUV(): Invalid argument");
71640dd3146cde2ba5036fe76a4f09e1125b4592347DRC
71740dd3146cde2ba5036fe76a4f09e1125b4592347DRC	pw=tjPlaneWidth(componentID, width, subsamp);
71840dd3146cde2ba5036fe76a4f09e1125b4592347DRC	ph=tjPlaneHeight(componentID, height, subsamp);
7192240974d5dc23a27ceb513af3cfc18f7298af0dcDRC	if(pw<0 || ph<0) return -1;
72040dd3146cde2ba5036fe76a4f09e1125b4592347DRC
72140dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if(stride==0) stride=pw;
72240dd3146cde2ba5036fe76a4f09e1125b4592347DRC	else stride=abs(stride);
72340dd3146cde2ba5036fe76a4f09e1125b4592347DRC
72440dd3146cde2ba5036fe76a4f09e1125b4592347DRC	retval=stride*(ph-1)+pw;
72540dd3146cde2ba5036fe76a4f09e1125b4592347DRC
72640dd3146cde2ba5036fe76a4f09e1125b4592347DRC	bailout:
72740dd3146cde2ba5036fe76a4f09e1125b4592347DRC	return retval;
72840dd3146cde2ba5036fe76a4f09e1125b4592347DRC}
72940dd3146cde2ba5036fe76a4f09e1125b4592347DRC
73040dd3146cde2ba5036fe76a4f09e1125b4592347DRC
7319b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf,
7329b28defe6ac85dd8a52479cf276606beae24920eDRC	int width, int pitch, int height, int pixelFormat, unsigned char **jpegBuf,
7339b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
7349b28defe6ac85dd8a52479cf276606beae24920eDRC{
735ff78e37595c8462f64fd100f928aa1d08539527eDRC	int i, retval=0, alloc=1;  JSAMPROW *row_pointer=NULL;
736afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#ifndef JCS_EXTENSIONS
737afc06929e0a9cf64bdf50da30326076235df7b4fDRC	unsigned char *rgbBuf=NULL;
738afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#endif
7399b28defe6ac85dd8a52479cf276606beae24920eDRC
740418616266582fa978d4d1950cf739bbdac7ebee5DRC	getcinstance(handle)
7419b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this->init&COMPRESS)==0)
742007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjCompress2(): Instance has not been initialized for compression");
7439b28defe6ac85dd8a52479cf276606beae24920eDRC
7449b28defe6ac85dd8a52479cf276606beae24920eDRC	if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
7459b28defe6ac85dd8a52479cf276606beae24920eDRC		|| pixelFormat>=TJ_NUMPF || jpegBuf==NULL || jpegSize==NULL
7469b28defe6ac85dd8a52479cf276606beae24920eDRC		|| jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT || jpegQual<0 || jpegQual>100)
747007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjCompress2(): Invalid argument");
7489b28defe6ac85dd8a52479cf276606beae24920eDRC
7499b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
7509b28defe6ac85dd8a52479cf276606beae24920eDRC	{
7519b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
7529b28defe6ac85dd8a52479cf276606beae24920eDRC		retval=-1;
7539b28defe6ac85dd8a52479cf276606beae24920eDRC		goto bailout;
7549b28defe6ac85dd8a52479cf276606beae24920eDRC	}
7559b28defe6ac85dd8a52479cf276606beae24920eDRC
7569b28defe6ac85dd8a52479cf276606beae24920eDRC	if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
7579b28defe6ac85dd8a52479cf276606beae24920eDRC
758afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#ifndef JCS_EXTENSIONS
759230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC	if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK)
760afc06929e0a9cf64bdf50da30326076235df7b4fDRC	{
761afc06929e0a9cf64bdf50da30326076235df7b4fDRC		rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
762afc06929e0a9cf64bdf50da30326076235df7b4fDRC		if(!rgbBuf) _throw("tjCompress2(): Memory allocation failure");
763afc06929e0a9cf64bdf50da30326076235df7b4fDRC		srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
764afc06929e0a9cf64bdf50da30326076235df7b4fDRC		pitch=width*RGB_PIXELSIZE;
765afc06929e0a9cf64bdf50da30326076235df7b4fDRC	}
766afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#endif
767afc06929e0a9cf64bdf50da30326076235df7b4fDRC
7689b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->image_width=width;
7699b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->image_height=height;
7709b28defe6ac85dd8a52479cf276606beae24920eDRC
771bec45b162bb77a57c147a9c44113af1968a79be4DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
772bec45b162bb77a57c147a9c44113af1968a79be4DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
773bec45b162bb77a57c147a9c44113af1968a79be4DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
7749b28defe6ac85dd8a52479cf276606beae24920eDRC
775ff78e37595c8462f64fd100f928aa1d08539527eDRC	if(flags&TJFLAG_NOREALLOC)
776ff78e37595c8462f64fd100f928aa1d08539527eDRC	{
7779b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC		alloc=0;  *jpegSize=tjBufSize(width, height, jpegSubsamp);
778ff78e37595c8462f64fd100f928aa1d08539527eDRC	}
779ff78e37595c8462f64fd100f928aa1d08539527eDRC	jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
78073d74c132b399fc761ebd9a5b2f60ae2a25f5955DRC	if(setCompDefaults(cinfo, pixelFormat, jpegSubsamp, jpegQual, flags)==-1)
781f12bb305c26a25eb76d4e3d73651ef927b352c2bDRC		return -1;
7829b28defe6ac85dd8a52479cf276606beae24920eDRC
7839b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_start_compress(cinfo, TRUE);
7849b28defe6ac85dd8a52479cf276606beae24920eDRC	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
785007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjCompress2(): Memory allocation failure");
7869b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<height; i++)
7879b28defe6ac85dd8a52479cf276606beae24920eDRC	{
78825b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
7899b28defe6ac85dd8a52479cf276606beae24920eDRC		else row_pointer[i]=&srcBuf[i*pitch];
7909b28defe6ac85dd8a52479cf276606beae24920eDRC	}
7919b28defe6ac85dd8a52479cf276606beae24920eDRC	while(cinfo->next_scanline<cinfo->image_height)
7929b28defe6ac85dd8a52479cf276606beae24920eDRC	{
7939b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_write_scanlines(cinfo, &row_pointer[cinfo->next_scanline],
7949b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->image_height-cinfo->next_scanline);
7959b28defe6ac85dd8a52479cf276606beae24920eDRC	}
7969b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_finish_compress(cinfo);
7979b28defe6ac85dd8a52479cf276606beae24920eDRC
7989b28defe6ac85dd8a52479cf276606beae24920eDRC	bailout:
7999b28defe6ac85dd8a52479cf276606beae24920eDRC	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
800afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#ifndef JCS_EXTENSIONS
801ea3396a9456fbe403e0defd2991a308d7c400abcDRC	if(rgbBuf) free(rgbBuf);
802afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#endif
8039b28defe6ac85dd8a52479cf276606beae24920eDRC	if(row_pointer) free(row_pointer);
8041f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	if(this->jerr.warning) retval=-1;
8059b28defe6ac85dd8a52479cf276606beae24920eDRC	return retval;
8069b28defe6ac85dd8a52479cf276606beae24920eDRC}
8079b28defe6ac85dd8a52479cf276606beae24920eDRC
8089b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjCompress(tjhandle handle, unsigned char *srcBuf,
8099b28defe6ac85dd8a52479cf276606beae24920eDRC	int width, int pitch, int height, int pixelSize, unsigned char *jpegBuf,
8109b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
8119b28defe6ac85dd8a52479cf276606beae24920eDRC{
8129b28defe6ac85dd8a52479cf276606beae24920eDRC	int retval=0;  unsigned long size;
8139b28defe6ac85dd8a52479cf276606beae24920eDRC	if(flags&TJ_YUV)
8149b28defe6ac85dd8a52479cf276606beae24920eDRC	{
8159b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC		size=tjBufSizeYUV(width, height, jpegSubsamp);
8169b28defe6ac85dd8a52479cf276606beae24920eDRC		retval=tjEncodeYUV2(handle, srcBuf, width, pitch, height,
8179b28defe6ac85dd8a52479cf276606beae24920eDRC			getPixelFormat(pixelSize, flags), jpegBuf, jpegSubsamp, flags);
8189b28defe6ac85dd8a52479cf276606beae24920eDRC	}
8199b28defe6ac85dd8a52479cf276606beae24920eDRC	else
8209b28defe6ac85dd8a52479cf276606beae24920eDRC	{
8219b28defe6ac85dd8a52479cf276606beae24920eDRC		retval=tjCompress2(handle, srcBuf, width, pitch, height,
8229b28defe6ac85dd8a52479cf276606beae24920eDRC			getPixelFormat(pixelSize, flags), &jpegBuf, &size, jpegSubsamp, jpegQual,
82325b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC			flags|TJFLAG_NOREALLOC);
8249b28defe6ac85dd8a52479cf276606beae24920eDRC	}
8259b28defe6ac85dd8a52479cf276606beae24920eDRC	*jpegSize=size;
8269b28defe6ac85dd8a52479cf276606beae24920eDRC	return retval;
8279b28defe6ac85dd8a52479cf276606beae24920eDRC}
8289b28defe6ac85dd8a52479cf276606beae24920eDRC
8299b28defe6ac85dd8a52479cf276606beae24920eDRC
830aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRCDLLEXPORT int DLLCALL tjEncodeYUVPlanes(tjhandle handle, unsigned char *srcBuf,
831aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	int width, int pitch, int height, int pixelFormat, unsigned char **dstPlanes,
832aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	int *strides, int subsamp, int flags)
8332e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
83491e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	int i, retval=0;  JSAMPROW *row_pointer=NULL;
835fbb674707e01a61e8b7083faa632dfd46c568b13DRC	JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS];
836fbb674707e01a61e8b7083faa632dfd46c568b13DRC	JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
837fbb674707e01a61e8b7083faa632dfd46c568b13DRC	JSAMPROW *outbuf[MAX_COMPONENTS];
83840dd3146cde2ba5036fe76a4f09e1125b4592347DRC	int row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS];
839aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	JSAMPLE *ptr;
8409b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_component_info *compptr;
841afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#ifndef JCS_EXTENSIONS
842afc06929e0a9cf64bdf50da30326076235df7b4fDRC	unsigned char *rgbBuf=NULL;
843afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#endif
8442e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
845418616266582fa978d4d1950cf739bbdac7ebee5DRC	getcinstance(handle);
846b51ee895d8266529af7f96cb24fba53df273d32eDRC
847fbb674707e01a61e8b7083faa632dfd46c568b13DRC	for(i=0; i<MAX_COMPONENTS; i++)
848fbb674707e01a61e8b7083faa632dfd46c568b13DRC	{
849fbb674707e01a61e8b7083faa632dfd46c568b13DRC		tmpbuf[i]=NULL;  _tmpbuf[i]=NULL;
850fbb674707e01a61e8b7083faa632dfd46c568b13DRC		tmpbuf2[i]=NULL;  _tmpbuf2[i]=NULL;  outbuf[i]=NULL;
851fbb674707e01a61e8b7083faa632dfd46c568b13DRC	}
852fbb674707e01a61e8b7083faa632dfd46c568b13DRC
853e2f8e694d0d1ec333c18d803cf0ba083e9feb1c0DRC	if((this->init&COMPRESS)==0)
854aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjEncodeYUVPlanes(): Instance has not been initialized for compression");
855e2f8e694d0d1ec333c18d803cf0ba083e9feb1c0DRC
8569b28defe6ac85dd8a52479cf276606beae24920eDRC	if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
857aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		|| pixelFormat>=TJ_NUMPF || !dstPlanes || !dstPlanes[0] || subsamp<0
858aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		|| subsamp>=NUMSUBOPT)
859aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjEncodeYUVPlanes(): Invalid argument");
860aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	if(subsamp!=TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2]))
861aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjEncodeYUVPlanes(): Invalid argument");
8622e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
8639b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
8649b28defe6ac85dd8a52479cf276606beae24920eDRC	{
8659b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
86691e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC		retval=-1;
86791e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC		goto bailout;
868efa4ddcc88783c7b8bf5cba42c6680132eefa628DRC	}
8692e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
870cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC	if(pixelFormat==TJPF_CMYK)
871aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjEncodeYUVPlanes(): Cannot generate YUV images from CMYK pixels");
872cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC
8739b28defe6ac85dd8a52479cf276606beae24920eDRC	if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
8742e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
875afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#ifndef JCS_EXTENSIONS
876230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC	if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK)
877afc06929e0a9cf64bdf50da30326076235df7b4fDRC	{
878afc06929e0a9cf64bdf50da30326076235df7b4fDRC		rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
879aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		if(!rgbBuf) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
880afc06929e0a9cf64bdf50da30326076235df7b4fDRC		srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
881afc06929e0a9cf64bdf50da30326076235df7b4fDRC		pitch=width*RGB_PIXELSIZE;
882afc06929e0a9cf64bdf50da30326076235df7b4fDRC	}
883afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#endif
884afc06929e0a9cf64bdf50da30326076235df7b4fDRC
8859b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->image_width=width;
8869b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->image_height=height;
8872e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
888bec45b162bb77a57c147a9c44113af1968a79be4DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
889bec45b162bb77a57c147a9c44113af1968a79be4DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
890bec45b162bb77a57c147a9c44113af1968a79be4DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
8912e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
89273d74c132b399fc761ebd9a5b2f60ae2a25f5955DRC	if(setCompDefaults(cinfo, pixelFormat, subsamp, -1, flags)==-1) return -1;
8932e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
89438c9970b95f8f83769b5476a9d7e6062714c19f6DRC	/* Execute only the parts of jpeg_start_compress() that we need.  If we
89538c9970b95f8f83769b5476a9d7e6062714c19f6DRC	   were to call the whole jpeg_start_compress() function, then it would try
89638c9970b95f8f83769b5476a9d7e6062714c19f6DRC	   to write the file headers, which could overflow the output buffer if the
89738c9970b95f8f83769b5476a9d7e6062714c19f6DRC	   YUV image were very small. */
89838c9970b95f8f83769b5476a9d7e6062714c19f6DRC	if(cinfo->global_state!=CSTATE_START)
899aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjEncodeYUVPlanes(): libjpeg API is in the wrong state");
90038c9970b95f8f83769b5476a9d7e6062714c19f6DRC	(*cinfo->err->reset_error_mgr)((j_common_ptr)cinfo);
90138c9970b95f8f83769b5476a9d7e6062714c19f6DRC	jinit_c_master_control(cinfo, FALSE);
90238c9970b95f8f83769b5476a9d7e6062714c19f6DRC	jinit_color_converter(cinfo);
90338c9970b95f8f83769b5476a9d7e6062714c19f6DRC	jinit_downsampler(cinfo);
90450cfc464b8fdee7f7388ef14284c632b553c2f4aDRC	(*cinfo->cconvert->start_pass)(cinfo);
90538c9970b95f8f83769b5476a9d7e6062714c19f6DRC
90640dd3146cde2ba5036fe76a4f09e1125b4592347DRC	pw0=PAD(width, cinfo->max_h_samp_factor);
90740dd3146cde2ba5036fe76a4f09e1125b4592347DRC	ph0=PAD(height, cinfo->max_v_samp_factor);
9089b28defe6ac85dd8a52479cf276606beae24920eDRC
90940dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL)
910aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjEncodeYUVPlanes(): Memory allocation failure");
9119b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<height; i++)
9122e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC	{
91325b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
9149b28defe6ac85dd8a52479cf276606beae24920eDRC		else row_pointer[i]=&srcBuf[i*pitch];
9159b28defe6ac85dd8a52479cf276606beae24920eDRC	}
91640dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if(height<ph0)
91740dd3146cde2ba5036fe76a4f09e1125b4592347DRC		for(i=height; i<ph0; i++) row_pointer[i]=row_pointer[height-1];
918fbb674707e01a61e8b7083faa632dfd46c568b13DRC
9199b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<cinfo->num_components; i++)
9209b28defe6ac85dd8a52479cf276606beae24920eDRC	{
9219b28defe6ac85dd8a52479cf276606beae24920eDRC		compptr=&cinfo->comp_info[i];
9229b28defe6ac85dd8a52479cf276606beae24920eDRC		_tmpbuf[i]=(JSAMPLE *)malloc(
9239b28defe6ac85dd8a52479cf276606beae24920eDRC			PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
9249b28defe6ac85dd8a52479cf276606beae24920eDRC				/compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
925aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		if(!_tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
9269b28defe6ac85dd8a52479cf276606beae24920eDRC		tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
927aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		if(!tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
9289b28defe6ac85dd8a52479cf276606beae24920eDRC		for(row=0; row<cinfo->max_v_samp_factor; row++)
929fbb674707e01a61e8b7083faa632dfd46c568b13DRC		{
9309b28defe6ac85dd8a52479cf276606beae24920eDRC			unsigned char *_tmpbuf_aligned=
9319b28defe6ac85dd8a52479cf276606beae24920eDRC				(unsigned char *)PAD((size_t)_tmpbuf[i], 16);
9329b28defe6ac85dd8a52479cf276606beae24920eDRC			tmpbuf[i][row]=&_tmpbuf_aligned[
933fbb674707e01a61e8b7083faa632dfd46c568b13DRC				PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
9349b28defe6ac85dd8a52479cf276606beae24920eDRC					/compptr->h_samp_factor, 16) * row];
935fbb674707e01a61e8b7083faa632dfd46c568b13DRC		}
9369b28defe6ac85dd8a52479cf276606beae24920eDRC		_tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
9379b28defe6ac85dd8a52479cf276606beae24920eDRC			* compptr->v_samp_factor + 16);
938aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		if(!_tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
9399b28defe6ac85dd8a52479cf276606beae24920eDRC		tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
940aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		if(!tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
9419b28defe6ac85dd8a52479cf276606beae24920eDRC		for(row=0; row<compptr->v_samp_factor; row++)
942fbb674707e01a61e8b7083faa632dfd46c568b13DRC		{
9439b28defe6ac85dd8a52479cf276606beae24920eDRC			unsigned char *_tmpbuf2_aligned=
9449b28defe6ac85dd8a52479cf276606beae24920eDRC				(unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
9459b28defe6ac85dd8a52479cf276606beae24920eDRC			tmpbuf2[i][row]=&_tmpbuf2_aligned[
9469b28defe6ac85dd8a52479cf276606beae24920eDRC				PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
947fbb674707e01a61e8b7083faa632dfd46c568b13DRC		}
94840dd3146cde2ba5036fe76a4f09e1125b4592347DRC		pw[i]=pw0*compptr->h_samp_factor/cinfo->max_h_samp_factor;
94940dd3146cde2ba5036fe76a4f09e1125b4592347DRC		ph[i]=ph0*compptr->v_samp_factor/cinfo->max_v_samp_factor;
95040dd3146cde2ba5036fe76a4f09e1125b4592347DRC		outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]);
951aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		if(!outbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
952aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		ptr=dstPlanes[i];
95340dd3146cde2ba5036fe76a4f09e1125b4592347DRC		for(row=0; row<ph[i]; row++)
954fbb674707e01a61e8b7083faa632dfd46c568b13DRC		{
9559b28defe6ac85dd8a52479cf276606beae24920eDRC			outbuf[i][row]=ptr;
95640dd3146cde2ba5036fe76a4f09e1125b4592347DRC			ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
957fbb674707e01a61e8b7083faa632dfd46c568b13DRC		}
9586ee54594591d0ae958b81adc8ba3cacde522e5e3DRC	}
9599b28defe6ac85dd8a52479cf276606beae24920eDRC
96040dd3146cde2ba5036fe76a4f09e1125b4592347DRC	for(row=0; row<ph0; row+=cinfo->max_v_samp_factor)
9619b28defe6ac85dd8a52479cf276606beae24920eDRC	{
9629b28defe6ac85dd8a52479cf276606beae24920eDRC		(*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0,
9639b28defe6ac85dd8a52479cf276606beae24920eDRC			cinfo->max_v_samp_factor);
9649b28defe6ac85dd8a52479cf276606beae24920eDRC		(cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
9659b28defe6ac85dd8a52479cf276606beae24920eDRC		for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++)
9669b28defe6ac85dd8a52479cf276606beae24920eDRC			jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
9679b28defe6ac85dd8a52479cf276606beae24920eDRC				row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
96840dd3146cde2ba5036fe76a4f09e1125b4592347DRC				compptr->v_samp_factor, pw[i]);
9699b28defe6ac85dd8a52479cf276606beae24920eDRC	}
9709b28defe6ac85dd8a52479cf276606beae24920eDRC	cinfo->next_scanline+=height;
9719b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_abort_compress(cinfo);
9722e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
97391e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	bailout:
9749b28defe6ac85dd8a52479cf276606beae24920eDRC	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
975afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#ifndef JCS_EXTENSIONS
976ea3396a9456fbe403e0defd2991a308d7c400abcDRC	if(rgbBuf) free(rgbBuf);
977afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#endif
9782e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC	if(row_pointer) free(row_pointer);
979fbb674707e01a61e8b7083faa632dfd46c568b13DRC	for(i=0; i<MAX_COMPONENTS; i++)
980fbb674707e01a61e8b7083faa632dfd46c568b13DRC	{
981fbb674707e01a61e8b7083faa632dfd46c568b13DRC		if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
98257423076e6189717441763de3253072dee42ff7eDRC		if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
983fbb674707e01a61e8b7083faa632dfd46c568b13DRC		if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
98457423076e6189717441763de3253072dee42ff7eDRC		if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
985fbb674707e01a61e8b7083faa632dfd46c568b13DRC		if(outbuf[i]!=NULL) free(outbuf[i]);
986fbb674707e01a61e8b7083faa632dfd46c568b13DRC	}
9871f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	if(this->jerr.warning) retval=-1;
98891e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	return retval;
9892e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
9902e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
991aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRCDLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf,
992aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
993aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	int pad, int subsamp, int flags)
994aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC{
995aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	unsigned char *dstPlanes[3];
99640dd3146cde2ba5036fe76a4f09e1125b4592347DRC	int pw0, ph0, strides[3], retval=-1;
997aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
998aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	if(width<=0 || height<=0 || dstBuf==NULL || pad<0 || !isPow2(pad)
999aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		|| subsamp<0 || subsamp>=NUMSUBOPT)
1000aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjEncodeYUV3(): Invalid argument");
1001aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
100240dd3146cde2ba5036fe76a4f09e1125b4592347DRC	pw0=tjPlaneWidth(0, width, subsamp);
100340dd3146cde2ba5036fe76a4f09e1125b4592347DRC	ph0=tjPlaneHeight(0, height, subsamp);
1004aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	dstPlanes[0]=dstBuf;
100540dd3146cde2ba5036fe76a4f09e1125b4592347DRC	strides[0]=PAD(pw0, pad);
100640dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if(subsamp==TJSAMP_GRAY)
100740dd3146cde2ba5036fe76a4f09e1125b4592347DRC	{
100840dd3146cde2ba5036fe76a4f09e1125b4592347DRC		strides[1]=strides[2]=0;
100940dd3146cde2ba5036fe76a4f09e1125b4592347DRC		dstPlanes[1]=dstPlanes[2]=NULL;
101040dd3146cde2ba5036fe76a4f09e1125b4592347DRC	}
101140dd3146cde2ba5036fe76a4f09e1125b4592347DRC	else
101240dd3146cde2ba5036fe76a4f09e1125b4592347DRC	{
101340dd3146cde2ba5036fe76a4f09e1125b4592347DRC		int pw1=tjPlaneWidth(1, width, subsamp);
101440dd3146cde2ba5036fe76a4f09e1125b4592347DRC		int ph1=tjPlaneHeight(1, height, subsamp);
101540dd3146cde2ba5036fe76a4f09e1125b4592347DRC		strides[1]=strides[2]=PAD(pw1, pad);
101640dd3146cde2ba5036fe76a4f09e1125b4592347DRC		dstPlanes[1]=dstPlanes[0]+strides[0]*ph0;
101740dd3146cde2ba5036fe76a4f09e1125b4592347DRC		dstPlanes[2]=dstPlanes[1]+strides[1]*ph1;
101840dd3146cde2ba5036fe76a4f09e1125b4592347DRC	}
1019aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1020aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	return tjEncodeYUVPlanes(handle, srcBuf, width, pitch, height, pixelFormat,
1021aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		dstPlanes, strides, subsamp, flags);
1022aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1023aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	bailout:
1024aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	return retval;
1025aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC}
1026aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1027f610d61fcc38b36a8a29879e5c053015164242f8DRCDLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
1028f610d61fcc38b36a8a29879e5c053015164242f8DRC	int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
1029f610d61fcc38b36a8a29879e5c053015164242f8DRC	int subsamp, int flags)
1030f610d61fcc38b36a8a29879e5c053015164242f8DRC{
1031f610d61fcc38b36a8a29879e5c053015164242f8DRC	return tjEncodeYUV3(handle, srcBuf, width, pitch, height, pixelFormat,
1032f610d61fcc38b36a8a29879e5c053015164242f8DRC		dstBuf, 4, subsamp, flags);
1033f610d61fcc38b36a8a29879e5c053015164242f8DRC}
1034f610d61fcc38b36a8a29879e5c053015164242f8DRC
10359b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf,
10369b28defe6ac85dd8a52479cf276606beae24920eDRC	int width, int pitch, int height, int pixelSize, unsigned char *dstBuf,
10379b28defe6ac85dd8a52479cf276606beae24920eDRC	int subsamp, int flags)
1038842416034561f6d5320165a4fe98825e999a4a37DRC{
10399b28defe6ac85dd8a52479cf276606beae24920eDRC	return tjEncodeYUV2(handle, srcBuf, width, pitch, height,
10409b28defe6ac85dd8a52479cf276606beae24920eDRC		getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags);
1041842416034561f6d5320165a4fe98825e999a4a37DRC}
1042842416034561f6d5320165a4fe98825e999a4a37DRC
1043842416034561f6d5320165a4fe98825e999a4a37DRC
1044aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRCDLLEXPORT int DLLCALL tjCompressFromYUVPlanes(tjhandle handle,
1045aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	unsigned char **srcPlanes, int width, int *strides, int height, int subsamp,
1046aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual, int flags)
1047910a35725cb52913c248f39e3f273a4baadbd7ddDRC{
1048910a35725cb52913c248f39e3f273a4baadbd7ddDRC	int i, row, retval=0, alloc=1;  JSAMPROW *inbuf[MAX_COMPONENTS];
104940dd3146cde2ba5036fe76a4f09e1125b4592347DRC	int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS],
1050910a35725cb52913c248f39e3f273a4baadbd7ddDRC		tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
1051aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	JSAMPLE *_tmpbuf=NULL, *ptr;  JSAMPROW *tmpbuf[MAX_COMPONENTS];
1052910a35725cb52913c248f39e3f273a4baadbd7ddDRC
1053418616266582fa978d4d1950cf739bbdac7ebee5DRC	getcinstance(handle)
1054b51ee895d8266529af7f96cb24fba53df273d32eDRC
1055910a35725cb52913c248f39e3f273a4baadbd7ddDRC	for(i=0; i<MAX_COMPONENTS; i++)
1056910a35725cb52913c248f39e3f273a4baadbd7ddDRC	{
1057910a35725cb52913c248f39e3f273a4baadbd7ddDRC		tmpbuf[i]=NULL;  inbuf[i]=NULL;
1058910a35725cb52913c248f39e3f273a4baadbd7ddDRC	}
1059910a35725cb52913c248f39e3f273a4baadbd7ddDRC
1060910a35725cb52913c248f39e3f273a4baadbd7ddDRC	if((this->init&COMPRESS)==0)
1061aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjCompressFromYUVPlanes(): Instance has not been initialized for compression");
1062910a35725cb52913c248f39e3f273a4baadbd7ddDRC
1063aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	if(!srcPlanes || !srcPlanes[0] || width<=0 || height<=0 || subsamp<0
1064910a35725cb52913c248f39e3f273a4baadbd7ddDRC		|| subsamp>=NUMSUBOPT || jpegBuf==NULL || jpegSize==NULL || jpegQual<0
1065910a35725cb52913c248f39e3f273a4baadbd7ddDRC		|| jpegQual>100)
1066aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjCompressFromYUVPlanes(): Invalid argument");
1067aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2]))
1068aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjCompressFromYUVPlanes(): Invalid argument");
1069910a35725cb52913c248f39e3f273a4baadbd7ddDRC
1070910a35725cb52913c248f39e3f273a4baadbd7ddDRC	if(setjmp(this->jerr.setjmp_buffer))
1071910a35725cb52913c248f39e3f273a4baadbd7ddDRC	{
1072910a35725cb52913c248f39e3f273a4baadbd7ddDRC		/* If we get here, the JPEG code has signaled an error. */
1073910a35725cb52913c248f39e3f273a4baadbd7ddDRC		retval=-1;
1074910a35725cb52913c248f39e3f273a4baadbd7ddDRC		goto bailout;
1075910a35725cb52913c248f39e3f273a4baadbd7ddDRC	}
1076910a35725cb52913c248f39e3f273a4baadbd7ddDRC
1077910a35725cb52913c248f39e3f273a4baadbd7ddDRC	cinfo->image_width=width;
1078910a35725cb52913c248f39e3f273a4baadbd7ddDRC	cinfo->image_height=height;
1079910a35725cb52913c248f39e3f273a4baadbd7ddDRC
1080bec45b162bb77a57c147a9c44113af1968a79be4DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1081bec45b162bb77a57c147a9c44113af1968a79be4DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1082bec45b162bb77a57c147a9c44113af1968a79be4DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
1083910a35725cb52913c248f39e3f273a4baadbd7ddDRC
1084910a35725cb52913c248f39e3f273a4baadbd7ddDRC	if(flags&TJFLAG_NOREALLOC)
1085910a35725cb52913c248f39e3f273a4baadbd7ddDRC	{
1086910a35725cb52913c248f39e3f273a4baadbd7ddDRC		alloc=0;  *jpegSize=tjBufSize(width, height, subsamp);
1087910a35725cb52913c248f39e3f273a4baadbd7ddDRC	}
1088910a35725cb52913c248f39e3f273a4baadbd7ddDRC	jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
1089910a35725cb52913c248f39e3f273a4baadbd7ddDRC	if(setCompDefaults(cinfo, TJPF_RGB, subsamp, jpegQual, flags)==-1)
1090910a35725cb52913c248f39e3f273a4baadbd7ddDRC		return -1;
1091910a35725cb52913c248f39e3f273a4baadbd7ddDRC	cinfo->raw_data_in=TRUE;
1092910a35725cb52913c248f39e3f273a4baadbd7ddDRC
1093910a35725cb52913c248f39e3f273a4baadbd7ddDRC	jpeg_start_compress(cinfo, TRUE);
1094910a35725cb52913c248f39e3f273a4baadbd7ddDRC	for(i=0; i<cinfo->num_components; i++)
1095910a35725cb52913c248f39e3f273a4baadbd7ddDRC	{
1096910a35725cb52913c248f39e3f273a4baadbd7ddDRC		jpeg_component_info *compptr=&cinfo->comp_info[i];
1097910a35725cb52913c248f39e3f273a4baadbd7ddDRC		int ih;
1098910a35725cb52913c248f39e3f273a4baadbd7ddDRC		iw[i]=compptr->width_in_blocks*DCTSIZE;
1099910a35725cb52913c248f39e3f273a4baadbd7ddDRC		ih=compptr->height_in_blocks*DCTSIZE;
110040dd3146cde2ba5036fe76a4f09e1125b4592347DRC		pw[i]=PAD(cinfo->image_width, cinfo->max_h_samp_factor)
1101910a35725cb52913c248f39e3f273a4baadbd7ddDRC			*compptr->h_samp_factor/cinfo->max_h_samp_factor;
110240dd3146cde2ba5036fe76a4f09e1125b4592347DRC		ph[i]=PAD(cinfo->image_height, cinfo->max_v_samp_factor)
1103910a35725cb52913c248f39e3f273a4baadbd7ddDRC			*compptr->v_samp_factor/cinfo->max_v_samp_factor;
110440dd3146cde2ba5036fe76a4f09e1125b4592347DRC		if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1;
1105910a35725cb52913c248f39e3f273a4baadbd7ddDRC		th[i]=compptr->v_samp_factor*DCTSIZE;
1106910a35725cb52913c248f39e3f273a4baadbd7ddDRC		tmpbufsize+=iw[i]*th[i];
110740dd3146cde2ba5036fe76a4f09e1125b4592347DRC		if((inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]))==NULL)
1108aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC			_throw("tjCompressFromYUVPlanes(): Memory allocation failure");
1109aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		ptr=srcPlanes[i];
111040dd3146cde2ba5036fe76a4f09e1125b4592347DRC		for(row=0; row<ph[i]; row++)
1111910a35725cb52913c248f39e3f273a4baadbd7ddDRC		{
1112910a35725cb52913c248f39e3f273a4baadbd7ddDRC			inbuf[i][row]=ptr;
111340dd3146cde2ba5036fe76a4f09e1125b4592347DRC			ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
1114910a35725cb52913c248f39e3f273a4baadbd7ddDRC		}
1115910a35725cb52913c248f39e3f273a4baadbd7ddDRC	}
1116910a35725cb52913c248f39e3f273a4baadbd7ddDRC	if(usetmpbuf)
1117910a35725cb52913c248f39e3f273a4baadbd7ddDRC	{
1118910a35725cb52913c248f39e3f273a4baadbd7ddDRC		if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
1119aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC			_throw("tjCompressFromYUVPlanes(): Memory allocation failure");
1120910a35725cb52913c248f39e3f273a4baadbd7ddDRC		ptr=_tmpbuf;
1121910a35725cb52913c248f39e3f273a4baadbd7ddDRC		for(i=0; i<cinfo->num_components; i++)
1122910a35725cb52913c248f39e3f273a4baadbd7ddDRC		{
1123910a35725cb52913c248f39e3f273a4baadbd7ddDRC			if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
1124aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC				_throw("tjCompressFromYUVPlanes(): Memory allocation failure");
1125910a35725cb52913c248f39e3f273a4baadbd7ddDRC			for(row=0; row<th[i]; row++)
1126910a35725cb52913c248f39e3f273a4baadbd7ddDRC			{
1127910a35725cb52913c248f39e3f273a4baadbd7ddDRC				tmpbuf[i][row]=ptr;
1128910a35725cb52913c248f39e3f273a4baadbd7ddDRC				ptr+=iw[i];
1129910a35725cb52913c248f39e3f273a4baadbd7ddDRC			}
1130910a35725cb52913c248f39e3f273a4baadbd7ddDRC		}
1131910a35725cb52913c248f39e3f273a4baadbd7ddDRC	}
1132910a35725cb52913c248f39e3f273a4baadbd7ddDRC
1133910a35725cb52913c248f39e3f273a4baadbd7ddDRC	for(row=0; row<(int)cinfo->image_height;
1134910a35725cb52913c248f39e3f273a4baadbd7ddDRC		row+=cinfo->max_v_samp_factor*DCTSIZE)
1135910a35725cb52913c248f39e3f273a4baadbd7ddDRC	{
1136910a35725cb52913c248f39e3f273a4baadbd7ddDRC		JSAMPARRAY yuvptr[MAX_COMPONENTS];
1137910a35725cb52913c248f39e3f273a4baadbd7ddDRC		int crow[MAX_COMPONENTS];
1138910a35725cb52913c248f39e3f273a4baadbd7ddDRC		for(i=0; i<cinfo->num_components; i++)
1139910a35725cb52913c248f39e3f273a4baadbd7ddDRC		{
1140910a35725cb52913c248f39e3f273a4baadbd7ddDRC			jpeg_component_info *compptr=&cinfo->comp_info[i];
1141910a35725cb52913c248f39e3f273a4baadbd7ddDRC			crow[i]=row*compptr->v_samp_factor/cinfo->max_v_samp_factor;
1142910a35725cb52913c248f39e3f273a4baadbd7ddDRC			if(usetmpbuf)
1143910a35725cb52913c248f39e3f273a4baadbd7ddDRC			{
1144910a35725cb52913c248f39e3f273a4baadbd7ddDRC				int j, k;
114540dd3146cde2ba5036fe76a4f09e1125b4592347DRC				for(j=0; j<min(th[i], ph[i]-crow[i]); j++)
1146910a35725cb52913c248f39e3f273a4baadbd7ddDRC				{
114740dd3146cde2ba5036fe76a4f09e1125b4592347DRC					memcpy(tmpbuf[i][j], inbuf[i][crow[i]+j], pw[i]);
1148006bc58dd6a8c68f4b3a26511e8684f5f3f1508aDRC					/* Duplicate last sample in row to fill out MCU */
114940dd3146cde2ba5036fe76a4f09e1125b4592347DRC					for(k=pw[i]; k<iw[i]; k++) tmpbuf[i][j][k]=tmpbuf[i][j][pw[i]-1];
1150910a35725cb52913c248f39e3f273a4baadbd7ddDRC				}
1151006bc58dd6a8c68f4b3a26511e8684f5f3f1508aDRC				/* Duplicate last row to fill out MCU */
115240dd3146cde2ba5036fe76a4f09e1125b4592347DRC				for(j=ph[i]-crow[i]; j<th[i]; j++)
115340dd3146cde2ba5036fe76a4f09e1125b4592347DRC					memcpy(tmpbuf[i][j], tmpbuf[i][ph[i]-crow[i]-1], iw[i]);
1154910a35725cb52913c248f39e3f273a4baadbd7ddDRC				yuvptr[i]=tmpbuf[i];
1155910a35725cb52913c248f39e3f273a4baadbd7ddDRC			}
1156910a35725cb52913c248f39e3f273a4baadbd7ddDRC			else
1157910a35725cb52913c248f39e3f273a4baadbd7ddDRC				yuvptr[i]=&inbuf[i][crow[i]];
1158910a35725cb52913c248f39e3f273a4baadbd7ddDRC		}
1159910a35725cb52913c248f39e3f273a4baadbd7ddDRC		jpeg_write_raw_data(cinfo, yuvptr, cinfo->max_v_samp_factor*DCTSIZE);
1160910a35725cb52913c248f39e3f273a4baadbd7ddDRC	}
1161910a35725cb52913c248f39e3f273a4baadbd7ddDRC	jpeg_finish_compress(cinfo);
1162910a35725cb52913c248f39e3f273a4baadbd7ddDRC
1163910a35725cb52913c248f39e3f273a4baadbd7ddDRC	bailout:
1164910a35725cb52913c248f39e3f273a4baadbd7ddDRC	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
1165910a35725cb52913c248f39e3f273a4baadbd7ddDRC	for(i=0; i<MAX_COMPONENTS; i++)
1166910a35725cb52913c248f39e3f273a4baadbd7ddDRC	{
1167910a35725cb52913c248f39e3f273a4baadbd7ddDRC		if(tmpbuf[i]) free(tmpbuf[i]);
1168910a35725cb52913c248f39e3f273a4baadbd7ddDRC		if(inbuf[i]) free(inbuf[i]);
1169910a35725cb52913c248f39e3f273a4baadbd7ddDRC	}
1170910a35725cb52913c248f39e3f273a4baadbd7ddDRC	if(_tmpbuf) free(_tmpbuf);
11711f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	if(this->jerr.warning) retval=-1;
1172910a35725cb52913c248f39e3f273a4baadbd7ddDRC	return retval;
1173910a35725cb52913c248f39e3f273a4baadbd7ddDRC}
1174910a35725cb52913c248f39e3f273a4baadbd7ddDRC
1175aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRCDLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle, unsigned char *srcBuf,
1176aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	int width, int pad, int height, int subsamp, unsigned char **jpegBuf,
1177aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	unsigned long *jpegSize, int jpegQual, int flags)
1178aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC{
1179aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	unsigned char *srcPlanes[3];
118040dd3146cde2ba5036fe76a4f09e1125b4592347DRC	int pw0, ph0, strides[3], retval=-1;
1181aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1182aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	if(srcBuf==NULL || width<=0 || pad<1 || height<=0 || subsamp<0
1183aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		|| subsamp>=NUMSUBOPT)
1184aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjCompressFromYUV(): Invalid argument");
1185aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
118640dd3146cde2ba5036fe76a4f09e1125b4592347DRC	pw0=tjPlaneWidth(0, width, subsamp);
118740dd3146cde2ba5036fe76a4f09e1125b4592347DRC	ph0=tjPlaneHeight(0, height, subsamp);
1188aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	srcPlanes[0]=srcBuf;
118940dd3146cde2ba5036fe76a4f09e1125b4592347DRC	strides[0]=PAD(pw0, pad);
119040dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if(subsamp==TJSAMP_GRAY)
119140dd3146cde2ba5036fe76a4f09e1125b4592347DRC	{
119240dd3146cde2ba5036fe76a4f09e1125b4592347DRC		strides[1]=strides[2]=0;
119340dd3146cde2ba5036fe76a4f09e1125b4592347DRC		srcPlanes[1]=srcPlanes[2]=NULL;
119440dd3146cde2ba5036fe76a4f09e1125b4592347DRC	}
119540dd3146cde2ba5036fe76a4f09e1125b4592347DRC	else
119640dd3146cde2ba5036fe76a4f09e1125b4592347DRC	{
119740dd3146cde2ba5036fe76a4f09e1125b4592347DRC		int pw1=tjPlaneWidth(1, width, subsamp);
119840dd3146cde2ba5036fe76a4f09e1125b4592347DRC		int ph1=tjPlaneHeight(1, height, subsamp);
119940dd3146cde2ba5036fe76a4f09e1125b4592347DRC		strides[1]=strides[2]=PAD(pw1, pad);
120040dd3146cde2ba5036fe76a4f09e1125b4592347DRC		srcPlanes[1]=srcPlanes[0]+strides[0]*ph0;
120140dd3146cde2ba5036fe76a4f09e1125b4592347DRC		srcPlanes[2]=srcPlanes[1]+strides[1]*ph1;
120240dd3146cde2ba5036fe76a4f09e1125b4592347DRC	}
1203aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1204aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	return tjCompressFromYUVPlanes(handle, srcPlanes, width, strides, height,
1205aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		subsamp, jpegBuf, jpegSize, jpegQual, flags);
1206aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1207aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	bailout:
1208aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	return retval;
1209aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC}
1210aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1211910a35725cb52913c248f39e3f273a4baadbd7ddDRC
12129b28defe6ac85dd8a52479cf276606beae24920eDRC/* Decompressor */
12132e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
12149b28defe6ac85dd8a52479cf276606beae24920eDRCstatic tjhandle _tjInitDecompress(tjinstance *this)
12152e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
12169b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned char buffer[1];
12172e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
12189b28defe6ac85dd8a52479cf276606beae24920eDRC	/* This is also straight out of example.c */
12199b28defe6ac85dd8a52479cf276606beae24920eDRC	this->dinfo.err=jpeg_std_error(&this->jerr.pub);
12209b28defe6ac85dd8a52479cf276606beae24920eDRC	this->jerr.pub.error_exit=my_error_exit;
12219b28defe6ac85dd8a52479cf276606beae24920eDRC	this->jerr.pub.output_message=my_output_message;
12221f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	this->jerr.emit_message=this->jerr.pub.emit_message;
12231f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	this->jerr.pub.emit_message=my_emit_message;
12242e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
12259b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
12269b28defe6ac85dd8a52479cf276606beae24920eDRC	{
12279b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
12289b28defe6ac85dd8a52479cf276606beae24920eDRC		if(this) free(this);  return NULL;
12299e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	}
12302e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
12319b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_create_decompress(&this->dinfo);
12329b28defe6ac85dd8a52479cf276606beae24920eDRC	/* Make an initial call so it will create the source manager */
12339b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_src_tj(&this->dinfo, buffer, 1);
12342e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
1235007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	this->init|=DECOMPRESS;
12369b28defe6ac85dd8a52479cf276606beae24920eDRC	return (tjhandle)this;
12372e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
12382e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
1239890f1e0413b54c40b663208779d4ea9dae20eaefDRCDLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
1240890f1e0413b54c40b663208779d4ea9dae20eaefDRC{
12419b28defe6ac85dd8a52479cf276606beae24920eDRC	tjinstance *this;
12429b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
1243da5220acdd525242bff4e40b1d90324ebb889825DRC	{
1244007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		snprintf(errStr, JMSG_LENGTH_MAX,
1245007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			"tjInitDecompress(): Memory allocation failure");
1246da5220acdd525242bff4e40b1d90324ebb889825DRC		return NULL;
1247da5220acdd525242bff4e40b1d90324ebb889825DRC	}
1248007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	MEMZERO(this, sizeof(tjinstance));
12499b28defe6ac85dd8a52479cf276606beae24920eDRC	return _tjInitDecompress(this);
1250890f1e0413b54c40b663208779d4ea9dae20eaefDRC}
1251890f1e0413b54c40b663208779d4ea9dae20eaefDRC
12522e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
1253cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRCDLLEXPORT int DLLCALL tjDecompressHeader3(tjhandle handle,
12549b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
1255cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC	int *jpegSubsamp, int *jpegColorspace)
12561fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC{
12579b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	int retval=0;
12581fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
1259418616266582fa978d4d1950cf739bbdac7ebee5DRC	getdinstance(handle);
12609b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this->init&DECOMPRESS)==0)
1261cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		_throw("tjDecompressHeader3(): Instance has not been initialized for decompression");
12621fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
12639b28defe6ac85dd8a52479cf276606beae24920eDRC	if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL
1264cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		|| jpegSubsamp==NULL || jpegColorspace==NULL)
1265cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		_throw("tjDecompressHeader3(): Invalid argument");
12661fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
12679b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
12689b28defe6ac85dd8a52479cf276606beae24920eDRC	{
12699b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
12701fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC		return -1;
12711fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC	}
12721fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
12739b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
12749b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_read_header(dinfo, TRUE);
12751fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
12769b28defe6ac85dd8a52479cf276606beae24920eDRC	*width=dinfo->image_width;
12779b28defe6ac85dd8a52479cf276606beae24920eDRC	*height=dinfo->image_height;
12789b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	*jpegSubsamp=getSubsamp(dinfo);
1279cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC	switch(dinfo->jpeg_color_space)
1280cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC	{
1281cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		case JCS_GRAYSCALE:  *jpegColorspace=TJCS_GRAY;  break;
1282cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		case JCS_RGB:        *jpegColorspace=TJCS_RGB;  break;
1283cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		case JCS_YCbCr:      *jpegColorspace=TJCS_YCbCr;  break;
1284cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		case JCS_CMYK:       *jpegColorspace=TJCS_CMYK;  break;
1285cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		case JCS_YCCK:       *jpegColorspace=TJCS_YCCK;  break;
1286cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		default:             *jpegColorspace=-1;  break;
1287cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC	}
12881fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
12899b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_abort_decompress(dinfo);
12901fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
12919b28defe6ac85dd8a52479cf276606beae24920eDRC	if(*jpegSubsamp<0)
1292cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		_throw("tjDecompressHeader3(): Could not determine subsampling type for JPEG image");
1293cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC	if(*jpegColorspace<0)
1294cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		_throw("tjDecompressHeader3(): Could not determine colorspace of JPEG image");
1295007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	if(*width<1 || *height<1)
1296cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		_throw("tjDecompressHeader3(): Invalid data returned in header");
129791e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC
129891e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	bailout:
12991f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	if(this->jerr.warning) retval=-1;
130091e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	return retval;
130191e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC}
130291e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC
1303cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRCDLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle,
1304cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC	unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
1305cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC	int *jpegSubsamp)
1306cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC{
1307cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC	int jpegColorspace;
1308cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC	return tjDecompressHeader3(handle, jpegBuf, jpegSize, width, height,
1309cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC		jpegSubsamp, &jpegColorspace);
1310cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC}
1311cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC
13129b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle,
13139b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height)
131491e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC{
13159b28defe6ac85dd8a52479cf276606beae24920eDRC	int jpegSubsamp;
13169b28defe6ac85dd8a52479cf276606beae24920eDRC	return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height,
13179b28defe6ac85dd8a52479cf276606beae24920eDRC		&jpegSubsamp);
13181fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC}
13191fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
13201fe80f80f57a975d5de01f2cae48f0981d9fd8d7DRC
1321109a578e89ea8cd2c39d50b012698148dd11dedbDRCDLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors)
1322b28fc5710a510410d2b498255a423dd62b353b3aDRC{
1323109a578e89ea8cd2c39d50b012698148dd11dedbDRC	if(numscalingfactors==NULL)
1324b28fc5710a510410d2b498255a423dd62b353b3aDRC	{
13259b28defe6ac85dd8a52479cf276606beae24920eDRC		snprintf(errStr, JMSG_LENGTH_MAX,
1326007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			"tjGetScalingFactors(): Invalid argument");
1327109a578e89ea8cd2c39d50b012698148dd11dedbDRC		return NULL;
1328b28fc5710a510410d2b498255a423dd62b353b3aDRC	}
1329b28fc5710a510410d2b498255a423dd62b353b3aDRC
1330109a578e89ea8cd2c39d50b012698148dd11dedbDRC	*numscalingfactors=NUMSF;
1331109a578e89ea8cd2c39d50b012698148dd11dedbDRC	return (tjscalingfactor *)sf;
1332b28fc5710a510410d2b498255a423dd62b353b3aDRC}
1333b28fc5710a510410d2b498255a423dd62b353b3aDRC
1334b28fc5710a510410d2b498255a423dd62b353b3aDRC
13359b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, unsigned char *jpegBuf,
13369b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
13379b28defe6ac85dd8a52479cf276606beae24920eDRC	int height, int pixelFormat, int flags)
13389b28defe6ac85dd8a52479cf276606beae24920eDRC{
13399b28defe6ac85dd8a52479cf276606beae24920eDRC	int i, retval=0;  JSAMPROW *row_pointer=NULL;
13409b28defe6ac85dd8a52479cf276606beae24920eDRC	int jpegwidth, jpegheight, scaledw, scaledh;
1341afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#ifndef JCS_EXTENSIONS
1342afc06929e0a9cf64bdf50da30326076235df7b4fDRC	unsigned char *rgbBuf=NULL;
1343afc06929e0a9cf64bdf50da30326076235df7b4fDRC	unsigned char *_dstBuf=NULL;  int _pitch=0;
1344afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#endif
13459b28defe6ac85dd8a52479cf276606beae24920eDRC
1346418616266582fa978d4d1950cf739bbdac7ebee5DRC	getdinstance(handle);
13479b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this->init&DECOMPRESS)==0)
1348007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompress2(): Instance has not been initialized for decompression");
13499b28defe6ac85dd8a52479cf276606beae24920eDRC
13509b28defe6ac85dd8a52479cf276606beae24920eDRC	if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0
13519b28defe6ac85dd8a52479cf276606beae24920eDRC		|| height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF)
13529b28defe6ac85dd8a52479cf276606beae24920eDRC		_throw("tjDecompress2(): Invalid argument");
13539b28defe6ac85dd8a52479cf276606beae24920eDRC
1354bec45b162bb77a57c147a9c44113af1968a79be4DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1355bec45b162bb77a57c147a9c44113af1968a79be4DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1356bec45b162bb77a57c147a9c44113af1968a79be4DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
13579b28defe6ac85dd8a52479cf276606beae24920eDRC
13589b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
13599b28defe6ac85dd8a52479cf276606beae24920eDRC	{
13609b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
13619b28defe6ac85dd8a52479cf276606beae24920eDRC		retval=-1;
13629b28defe6ac85dd8a52479cf276606beae24920eDRC		goto bailout;
13639b28defe6ac85dd8a52479cf276606beae24920eDRC	}
13649b28defe6ac85dd8a52479cf276606beae24920eDRC
13659b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
13669b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_read_header(dinfo, TRUE);
136773d74c132b399fc761ebd9a5b2f60ae2a25f5955DRC	if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
13682eda8212e4b01c9b4d343dd0eaa579f0bba036e7DRC	{
13692eda8212e4b01c9b4d343dd0eaa579f0bba036e7DRC		retval=-1;  goto bailout;
13702eda8212e4b01c9b4d343dd0eaa579f0bba036e7DRC	}
13719b28defe6ac85dd8a52479cf276606beae24920eDRC
137225b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
13739b28defe6ac85dd8a52479cf276606beae24920eDRC
13749b28defe6ac85dd8a52479cf276606beae24920eDRC	jpegwidth=dinfo->image_width;  jpegheight=dinfo->image_height;
13759b28defe6ac85dd8a52479cf276606beae24920eDRC	if(width==0) width=jpegwidth;
13769b28defe6ac85dd8a52479cf276606beae24920eDRC	if(height==0) height=jpegheight;
13779b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<NUMSF; i++)
13789b28defe6ac85dd8a52479cf276606beae24920eDRC	{
13799b28defe6ac85dd8a52479cf276606beae24920eDRC		scaledw=TJSCALED(jpegwidth, sf[i]);
13809b28defe6ac85dd8a52479cf276606beae24920eDRC		scaledh=TJSCALED(jpegheight, sf[i]);
13819b28defe6ac85dd8a52479cf276606beae24920eDRC		if(scaledw<=width && scaledh<=height)
1382f610d61fcc38b36a8a29879e5c053015164242f8DRC			break;
13839b28defe6ac85dd8a52479cf276606beae24920eDRC	}
138458ae401e503ac61babb9d66be8fc06bfb0445dbfDRC	if(i>=NUMSF)
1385007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompress2(): Could not scale down to desired image dimensions");
13869b28defe6ac85dd8a52479cf276606beae24920eDRC	width=scaledw;  height=scaledh;
13879b28defe6ac85dd8a52479cf276606beae24920eDRC	dinfo->scale_num=sf[i].num;
13889b28defe6ac85dd8a52479cf276606beae24920eDRC	dinfo->scale_denom=sf[i].denom;
13899b28defe6ac85dd8a52479cf276606beae24920eDRC
13909b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_start_decompress(dinfo);
13919b28defe6ac85dd8a52479cf276606beae24920eDRC	if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
1392afc06929e0a9cf64bdf50da30326076235df7b4fDRC
1393afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#ifndef JCS_EXTENSIONS
1394230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC	if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK &&
1395afc06929e0a9cf64bdf50da30326076235df7b4fDRC		(RGB_RED!=tjRedOffset[pixelFormat] ||
1396afc06929e0a9cf64bdf50da30326076235df7b4fDRC			RGB_GREEN!=tjGreenOffset[pixelFormat] ||
1397afc06929e0a9cf64bdf50da30326076235df7b4fDRC			RGB_BLUE!=tjBlueOffset[pixelFormat] ||
1398afc06929e0a9cf64bdf50da30326076235df7b4fDRC			RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
1399afc06929e0a9cf64bdf50da30326076235df7b4fDRC	{
1400afc06929e0a9cf64bdf50da30326076235df7b4fDRC		rgbBuf=(unsigned char *)malloc(width*height*3);
1401afc06929e0a9cf64bdf50da30326076235df7b4fDRC		if(!rgbBuf) _throw("tjDecompress2(): Memory allocation failure");
1402afc06929e0a9cf64bdf50da30326076235df7b4fDRC		_pitch=pitch;  pitch=width*3;
1403afc06929e0a9cf64bdf50da30326076235df7b4fDRC		_dstBuf=dstBuf;  dstBuf=rgbBuf;
1404afc06929e0a9cf64bdf50da30326076235df7b4fDRC	}
1405afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#endif
1406afc06929e0a9cf64bdf50da30326076235df7b4fDRC
14079b28defe6ac85dd8a52479cf276606beae24920eDRC	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
14089b28defe6ac85dd8a52479cf276606beae24920eDRC		*dinfo->output_height))==NULL)
1409007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjDecompress2(): Memory allocation failure");
14109b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<(int)dinfo->output_height; i++)
14119b28defe6ac85dd8a52479cf276606beae24920eDRC	{
141225b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		if(flags&TJFLAG_BOTTOMUP)
14139b28defe6ac85dd8a52479cf276606beae24920eDRC			row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*pitch];
14149b28defe6ac85dd8a52479cf276606beae24920eDRC		else row_pointer[i]=&dstBuf[i*pitch];
14159b28defe6ac85dd8a52479cf276606beae24920eDRC	}
14169b28defe6ac85dd8a52479cf276606beae24920eDRC	while(dinfo->output_scanline<dinfo->output_height)
14179b28defe6ac85dd8a52479cf276606beae24920eDRC	{
14189b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline],
14199b28defe6ac85dd8a52479cf276606beae24920eDRC			dinfo->output_height-dinfo->output_scanline);
14209b28defe6ac85dd8a52479cf276606beae24920eDRC	}
14219b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_finish_decompress(dinfo);
14229b28defe6ac85dd8a52479cf276606beae24920eDRC
1423afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#ifndef JCS_EXTENSIONS
1424afc06929e0a9cf64bdf50da30326076235df7b4fDRC	fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
1425afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#endif
1426afc06929e0a9cf64bdf50da30326076235df7b4fDRC
14279b28defe6ac85dd8a52479cf276606beae24920eDRC	bailout:
14289b28defe6ac85dd8a52479cf276606beae24920eDRC	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
1429afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#ifndef JCS_EXTENSIONS
1430ea3396a9456fbe403e0defd2991a308d7c400abcDRC	if(rgbBuf) free(rgbBuf);
1431afc06929e0a9cf64bdf50da30326076235df7b4fDRC	#endif
14329b28defe6ac85dd8a52479cf276606beae24920eDRC	if(row_pointer) free(row_pointer);
14331f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	if(this->jerr.warning) retval=-1;
14349b28defe6ac85dd8a52479cf276606beae24920eDRC	return retval;
14359b28defe6ac85dd8a52479cf276606beae24920eDRC}
14369b28defe6ac85dd8a52479cf276606beae24920eDRC
14379b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf,
14389b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
14399b28defe6ac85dd8a52479cf276606beae24920eDRC	int height, int pixelSize, int flags)
14409b28defe6ac85dd8a52479cf276606beae24920eDRC{
14419b28defe6ac85dd8a52479cf276606beae24920eDRC	if(flags&TJ_YUV)
14429b28defe6ac85dd8a52479cf276606beae24920eDRC		return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags);
14439b28defe6ac85dd8a52479cf276606beae24920eDRC	else
14449b28defe6ac85dd8a52479cf276606beae24920eDRC		return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch,
14459b28defe6ac85dd8a52479cf276606beae24920eDRC			height, getPixelFormat(pixelSize, flags), flags);
14469b28defe6ac85dd8a52479cf276606beae24920eDRC}
14479b28defe6ac85dd8a52479cf276606beae24920eDRC
14489b28defe6ac85dd8a52479cf276606beae24920eDRC
144934dca052271f4a75b3c0f7b11a2c5024159628d4DRCstatic int setDecodeDefaults(struct jpeg_decompress_struct *dinfo,
145034dca052271f4a75b3c0f7b11a2c5024159628d4DRC	int pixelFormat, int subsamp, int flags)
145134dca052271f4a75b3c0f7b11a2c5024159628d4DRC{
1452895fd6d0d370d64df9dbb1bc53342c734a6933fcDRC	int i;
1453895fd6d0d370d64df9dbb1bc53342c734a6933fcDRC
145434dca052271f4a75b3c0f7b11a2c5024159628d4DRC	dinfo->scale_num=dinfo->scale_denom=1;
145534dca052271f4a75b3c0f7b11a2c5024159628d4DRC
145634dca052271f4a75b3c0f7b11a2c5024159628d4DRC	if(subsamp==TJSAMP_GRAY)
145734dca052271f4a75b3c0f7b11a2c5024159628d4DRC	{
1458c90144950ffc9e58f942f1be7fc18e7820a14eb7DRC		dinfo->num_components=dinfo->comps_in_scan=1;
145934dca052271f4a75b3c0f7b11a2c5024159628d4DRC		dinfo->jpeg_color_space=JCS_GRAYSCALE;
146034dca052271f4a75b3c0f7b11a2c5024159628d4DRC	}
146134dca052271f4a75b3c0f7b11a2c5024159628d4DRC	else
146234dca052271f4a75b3c0f7b11a2c5024159628d4DRC	{
1463c90144950ffc9e58f942f1be7fc18e7820a14eb7DRC		dinfo->num_components=dinfo->comps_in_scan=3;
146434dca052271f4a75b3c0f7b11a2c5024159628d4DRC		dinfo->jpeg_color_space=JCS_YCbCr;
146534dca052271f4a75b3c0f7b11a2c5024159628d4DRC	}
146634dca052271f4a75b3c0f7b11a2c5024159628d4DRC
146734dca052271f4a75b3c0f7b11a2c5024159628d4DRC	dinfo->comp_info=(jpeg_component_info *)
146834dca052271f4a75b3c0f7b11a2c5024159628d4DRC		(*dinfo->mem->alloc_small)((j_common_ptr)dinfo, JPOOL_IMAGE,
14695de454b291f48382648a5d1dc2aa0fca8b5786d4DRC			dinfo->num_components*sizeof(jpeg_component_info));
147034dca052271f4a75b3c0f7b11a2c5024159628d4DRC
14712bdc0425df6d014a9f64549da4f7c2a4aa6b82b3DRC	for(i=0; i<dinfo->num_components; i++)
147234dca052271f4a75b3c0f7b11a2c5024159628d4DRC	{
14732bdc0425df6d014a9f64549da4f7c2a4aa6b82b3DRC		jpeg_component_info *compptr=&dinfo->comp_info[i];
14742bdc0425df6d014a9f64549da4f7c2a4aa6b82b3DRC		compptr->h_samp_factor=(i==0)? tjMCUWidth[subsamp]/8:1;
14752bdc0425df6d014a9f64549da4f7c2a4aa6b82b3DRC		compptr->v_samp_factor=(i==0)? tjMCUHeight[subsamp]/8:1;
14762bdc0425df6d014a9f64549da4f7c2a4aa6b82b3DRC		compptr->component_index=i;
147715c0876191b927cbe4d797b9ef89b51b08a12cc2DRC		compptr->component_id=i+1;
14782bdc0425df6d014a9f64549da4f7c2a4aa6b82b3DRC		compptr->quant_tbl_no=compptr->dc_tbl_no=compptr->ac_tbl_no=
14792bdc0425df6d014a9f64549da4f7c2a4aa6b82b3DRC			(i==0)? 0:1;
14802bdc0425df6d014a9f64549da4f7c2a4aa6b82b3DRC		dinfo->cur_comp_info[i]=compptr;
148134dca052271f4a75b3c0f7b11a2c5024159628d4DRC	}
1482c90144950ffc9e58f942f1be7fc18e7820a14eb7DRC	dinfo->data_precision=8;
1483c90144950ffc9e58f942f1be7fc18e7820a14eb7DRC	for(i=0; i<2; i++)
1484c90144950ffc9e58f942f1be7fc18e7820a14eb7DRC	{
1485c90144950ffc9e58f942f1be7fc18e7820a14eb7DRC		if(dinfo->quant_tbl_ptrs[i]==NULL)
1486c90144950ffc9e58f942f1be7fc18e7820a14eb7DRC			dinfo->quant_tbl_ptrs[i]=jpeg_alloc_quant_table((j_common_ptr)dinfo);
1487c90144950ffc9e58f942f1be7fc18e7820a14eb7DRC	}
148834dca052271f4a75b3c0f7b11a2c5024159628d4DRC
148934dca052271f4a75b3c0f7b11a2c5024159628d4DRC	return 0;
149034dca052271f4a75b3c0f7b11a2c5024159628d4DRC}
149134dca052271f4a75b3c0f7b11a2c5024159628d4DRC
149234dca052271f4a75b3c0f7b11a2c5024159628d4DRC
149334dca052271f4a75b3c0f7b11a2c5024159628d4DRCint my_read_markers(j_decompress_ptr dinfo)
149434dca052271f4a75b3c0f7b11a2c5024159628d4DRC{
149534dca052271f4a75b3c0f7b11a2c5024159628d4DRC	return JPEG_REACHED_SOS;
149634dca052271f4a75b3c0f7b11a2c5024159628d4DRC}
149734dca052271f4a75b3c0f7b11a2c5024159628d4DRC
149834dca052271f4a75b3c0f7b11a2c5024159628d4DRCvoid my_reset_marker_reader(j_decompress_ptr dinfo)
149934dca052271f4a75b3c0f7b11a2c5024159628d4DRC{
150034dca052271f4a75b3c0f7b11a2c5024159628d4DRC}
150134dca052271f4a75b3c0f7b11a2c5024159628d4DRC
1502aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRCDLLEXPORT int DLLCALL tjDecodeYUVPlanes(tjhandle handle,
1503aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	unsigned char **srcPlanes, int *strides, int subsamp, unsigned char *dstBuf,
1504aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	int width, int pitch, int height, int pixelFormat, int flags)
150534dca052271f4a75b3c0f7b11a2c5024159628d4DRC{
150634dca052271f4a75b3c0f7b11a2c5024159628d4DRC	int i, retval=0;  JSAMPROW *row_pointer=NULL;
150734dca052271f4a75b3c0f7b11a2c5024159628d4DRC	JSAMPLE *_tmpbuf[MAX_COMPONENTS];
150834dca052271f4a75b3c0f7b11a2c5024159628d4DRC	JSAMPROW *tmpbuf[MAX_COMPONENTS], *inbuf[MAX_COMPONENTS];
150940dd3146cde2ba5036fe76a4f09e1125b4592347DRC	int row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS];
1510aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	JSAMPLE *ptr;
151134dca052271f4a75b3c0f7b11a2c5024159628d4DRC	jpeg_component_info *compptr;
151234dca052271f4a75b3c0f7b11a2c5024159628d4DRC	#ifndef JCS_EXTENSIONS
151334dca052271f4a75b3c0f7b11a2c5024159628d4DRC	unsigned char *rgbBuf=NULL;
1514230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC	unsigned char *_dstBuf=NULL;  int _pitch=0;
151534dca052271f4a75b3c0f7b11a2c5024159628d4DRC	#endif
1516bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC	int (*old_read_markers)(j_decompress_ptr);
1517bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC	void (*old_reset_marker_reader)(j_decompress_ptr);
151834dca052271f4a75b3c0f7b11a2c5024159628d4DRC
1519418616266582fa978d4d1950cf739bbdac7ebee5DRC	getdinstance(handle);
152034dca052271f4a75b3c0f7b11a2c5024159628d4DRC
152134dca052271f4a75b3c0f7b11a2c5024159628d4DRC	for(i=0; i<MAX_COMPONENTS; i++)
152234dca052271f4a75b3c0f7b11a2c5024159628d4DRC	{
152334dca052271f4a75b3c0f7b11a2c5024159628d4DRC		tmpbuf[i]=NULL;  _tmpbuf[i]=NULL;  inbuf[i]=NULL;
152434dca052271f4a75b3c0f7b11a2c5024159628d4DRC	}
152534dca052271f4a75b3c0f7b11a2c5024159628d4DRC
152634dca052271f4a75b3c0f7b11a2c5024159628d4DRC	if((this->init&DECOMPRESS)==0)
1527aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjDecodeYUVPlanes(): Instance has not been initialized for decompression");
152834dca052271f4a75b3c0f7b11a2c5024159628d4DRC
1529aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	if(!srcPlanes || !srcPlanes[0] || subsamp<0 || subsamp>=NUMSUBOPT
153034dca052271f4a75b3c0f7b11a2c5024159628d4DRC		|| dstBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
153134dca052271f4a75b3c0f7b11a2c5024159628d4DRC		|| pixelFormat>=TJ_NUMPF)
1532aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjDecodeYUVPlanes(): Invalid argument");
1533aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2]))
1534aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjDecodeYUVPlanes(): Invalid argument");
153534dca052271f4a75b3c0f7b11a2c5024159628d4DRC
153634dca052271f4a75b3c0f7b11a2c5024159628d4DRC	if(setjmp(this->jerr.setjmp_buffer))
153734dca052271f4a75b3c0f7b11a2c5024159628d4DRC	{
153834dca052271f4a75b3c0f7b11a2c5024159628d4DRC		/* If we get here, the JPEG code has signaled an error. */
153934dca052271f4a75b3c0f7b11a2c5024159628d4DRC		retval=-1;
154034dca052271f4a75b3c0f7b11a2c5024159628d4DRC		goto bailout;
154134dca052271f4a75b3c0f7b11a2c5024159628d4DRC	}
154234dca052271f4a75b3c0f7b11a2c5024159628d4DRC
154334dca052271f4a75b3c0f7b11a2c5024159628d4DRC	if(pixelFormat==TJPF_CMYK)
1544aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjDecodeYUVPlanes(): Cannot decode YUV images into CMYK pixels.");
154534dca052271f4a75b3c0f7b11a2c5024159628d4DRC
154634dca052271f4a75b3c0f7b11a2c5024159628d4DRC	if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
154734dca052271f4a75b3c0f7b11a2c5024159628d4DRC	dinfo->image_width=width;
154834dca052271f4a75b3c0f7b11a2c5024159628d4DRC	dinfo->image_height=height;
154934dca052271f4a75b3c0f7b11a2c5024159628d4DRC
1550bec45b162bb77a57c147a9c44113af1968a79be4DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1551bec45b162bb77a57c147a9c44113af1968a79be4DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1552bec45b162bb77a57c147a9c44113af1968a79be4DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
155334dca052271f4a75b3c0f7b11a2c5024159628d4DRC
155434dca052271f4a75b3c0f7b11a2c5024159628d4DRC	if(setDecodeDefaults(dinfo, pixelFormat, subsamp, flags)==-1)
155534dca052271f4a75b3c0f7b11a2c5024159628d4DRC	{
155634dca052271f4a75b3c0f7b11a2c5024159628d4DRC		retval=-1;  goto bailout;
155734dca052271f4a75b3c0f7b11a2c5024159628d4DRC	}
155834dca052271f4a75b3c0f7b11a2c5024159628d4DRC	old_read_markers=dinfo->marker->read_markers;
155934dca052271f4a75b3c0f7b11a2c5024159628d4DRC	dinfo->marker->read_markers=my_read_markers;
156034dca052271f4a75b3c0f7b11a2c5024159628d4DRC	old_reset_marker_reader=dinfo->marker->reset_marker_reader;
156134dca052271f4a75b3c0f7b11a2c5024159628d4DRC	dinfo->marker->reset_marker_reader=my_reset_marker_reader;
156234dca052271f4a75b3c0f7b11a2c5024159628d4DRC	jpeg_read_header(dinfo, TRUE);
156334dca052271f4a75b3c0f7b11a2c5024159628d4DRC	dinfo->marker->read_markers=old_read_markers;
156434dca052271f4a75b3c0f7b11a2c5024159628d4DRC	dinfo->marker->reset_marker_reader=old_reset_marker_reader;
156534dca052271f4a75b3c0f7b11a2c5024159628d4DRC
156634dca052271f4a75b3c0f7b11a2c5024159628d4DRC	if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
156734dca052271f4a75b3c0f7b11a2c5024159628d4DRC	{
156834dca052271f4a75b3c0f7b11a2c5024159628d4DRC		retval=-1;  goto bailout;
156934dca052271f4a75b3c0f7b11a2c5024159628d4DRC	}
15707d9f758e5251e129431b03cdab1160710d4b3fb8DRC	dinfo->do_fancy_upsampling=FALSE;
1571db6d8fca591c924ba3da8ef525925b92e261e66aDRC	dinfo->Se=DCTSIZE2-1;
15722bdc0425df6d014a9f64549da4f7c2a4aa6b82b3DRC	jinit_master_decompress(dinfo);
157334dca052271f4a75b3c0f7b11a2c5024159628d4DRC	(*dinfo->upsample->start_pass)(dinfo);
157434dca052271f4a75b3c0f7b11a2c5024159628d4DRC
157540dd3146cde2ba5036fe76a4f09e1125b4592347DRC	pw0=PAD(width, dinfo->max_h_samp_factor);
157640dd3146cde2ba5036fe76a4f09e1125b4592347DRC	ph0=PAD(height, dinfo->max_v_samp_factor);
157734dca052271f4a75b3c0f7b11a2c5024159628d4DRC
157834dca052271f4a75b3c0f7b11a2c5024159628d4DRC	if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
157934dca052271f4a75b3c0f7b11a2c5024159628d4DRC
1580230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC	#ifndef JCS_EXTENSIONS
1581230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC	if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK &&
1582230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC		(RGB_RED!=tjRedOffset[pixelFormat] ||
1583230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC			RGB_GREEN!=tjGreenOffset[pixelFormat] ||
1584230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC			RGB_BLUE!=tjBlueOffset[pixelFormat] ||
1585230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC			RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
1586230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC	{
1587230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC		rgbBuf=(unsigned char *)malloc(width*height*3);
1588aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		if(!rgbBuf) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1589230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC		_pitch=pitch;  pitch=width*3;
1590230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC		_dstBuf=dstBuf;  dstBuf=rgbBuf;
1591230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC	}
1592230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC	#endif
1593230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC
159440dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL)
1595aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjDecodeYUVPlanes(): Memory allocation failure");
159634dca052271f4a75b3c0f7b11a2c5024159628d4DRC	for(i=0; i<height; i++)
159734dca052271f4a75b3c0f7b11a2c5024159628d4DRC	{
159834dca052271f4a75b3c0f7b11a2c5024159628d4DRC		if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&dstBuf[(height-i-1)*pitch];
159934dca052271f4a75b3c0f7b11a2c5024159628d4DRC		else row_pointer[i]=&dstBuf[i*pitch];
160034dca052271f4a75b3c0f7b11a2c5024159628d4DRC	}
160140dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if(height<ph0)
160240dd3146cde2ba5036fe76a4f09e1125b4592347DRC		for(i=height; i<ph0; i++) row_pointer[i]=row_pointer[height-1];
160334dca052271f4a75b3c0f7b11a2c5024159628d4DRC
160434dca052271f4a75b3c0f7b11a2c5024159628d4DRC	for(i=0; i<dinfo->num_components; i++)
160534dca052271f4a75b3c0f7b11a2c5024159628d4DRC	{
160634dca052271f4a75b3c0f7b11a2c5024159628d4DRC		compptr=&dinfo->comp_info[i];
160734dca052271f4a75b3c0f7b11a2c5024159628d4DRC		_tmpbuf[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
160834dca052271f4a75b3c0f7b11a2c5024159628d4DRC			* compptr->v_samp_factor + 16);
1609aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		if(!_tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
161034dca052271f4a75b3c0f7b11a2c5024159628d4DRC		tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
1611aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		if(!tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
161234dca052271f4a75b3c0f7b11a2c5024159628d4DRC		for(row=0; row<compptr->v_samp_factor; row++)
161334dca052271f4a75b3c0f7b11a2c5024159628d4DRC		{
161434dca052271f4a75b3c0f7b11a2c5024159628d4DRC			unsigned char *_tmpbuf_aligned=
161534dca052271f4a75b3c0f7b11a2c5024159628d4DRC				(unsigned char *)PAD((size_t)_tmpbuf[i], 16);
161634dca052271f4a75b3c0f7b11a2c5024159628d4DRC			tmpbuf[i][row]=&_tmpbuf_aligned[
161734dca052271f4a75b3c0f7b11a2c5024159628d4DRC				PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
161834dca052271f4a75b3c0f7b11a2c5024159628d4DRC		}
161940dd3146cde2ba5036fe76a4f09e1125b4592347DRC		pw[i]=pw0*compptr->h_samp_factor/dinfo->max_h_samp_factor;
162040dd3146cde2ba5036fe76a4f09e1125b4592347DRC		ph[i]=ph0*compptr->v_samp_factor/dinfo->max_v_samp_factor;
162140dd3146cde2ba5036fe76a4f09e1125b4592347DRC		inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]);
1622aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		if(!inbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1623aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		ptr=srcPlanes[i];
162440dd3146cde2ba5036fe76a4f09e1125b4592347DRC		for(row=0; row<ph[i]; row++)
162534dca052271f4a75b3c0f7b11a2c5024159628d4DRC		{
162634dca052271f4a75b3c0f7b11a2c5024159628d4DRC			inbuf[i][row]=ptr;
162740dd3146cde2ba5036fe76a4f09e1125b4592347DRC			ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
162834dca052271f4a75b3c0f7b11a2c5024159628d4DRC		}
162934dca052271f4a75b3c0f7b11a2c5024159628d4DRC	}
163034dca052271f4a75b3c0f7b11a2c5024159628d4DRC
163140dd3146cde2ba5036fe76a4f09e1125b4592347DRC	for(row=0; row<ph0; row+=dinfo->max_v_samp_factor)
163234dca052271f4a75b3c0f7b11a2c5024159628d4DRC	{
163334dca052271f4a75b3c0f7b11a2c5024159628d4DRC		JDIMENSION inrow=0, outrow=0;
163434dca052271f4a75b3c0f7b11a2c5024159628d4DRC		for(i=0, compptr=dinfo->comp_info; i<dinfo->num_components; i++, compptr++)
163534dca052271f4a75b3c0f7b11a2c5024159628d4DRC			jcopy_sample_rows(inbuf[i],
163634dca052271f4a75b3c0f7b11a2c5024159628d4DRC				row*compptr->v_samp_factor/dinfo->max_v_samp_factor, tmpbuf[i], 0,
163740dd3146cde2ba5036fe76a4f09e1125b4592347DRC				compptr->v_samp_factor, pw[i]);
163834dca052271f4a75b3c0f7b11a2c5024159628d4DRC		(dinfo->upsample->upsample)(dinfo, tmpbuf, &inrow,
163934dca052271f4a75b3c0f7b11a2c5024159628d4DRC			dinfo->max_v_samp_factor, &row_pointer[row], &outrow,
164034dca052271f4a75b3c0f7b11a2c5024159628d4DRC			dinfo->max_v_samp_factor);
164134dca052271f4a75b3c0f7b11a2c5024159628d4DRC	}
164234dca052271f4a75b3c0f7b11a2c5024159628d4DRC	jpeg_abort_decompress(dinfo);
164334dca052271f4a75b3c0f7b11a2c5024159628d4DRC
1644230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC	#ifndef JCS_EXTENSIONS
1645230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC	fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
1646230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC	#endif
1647230d09dbed4b7f2dfb52b9009770b2979b2aeb8fDRC
164834dca052271f4a75b3c0f7b11a2c5024159628d4DRC	bailout:
164934dca052271f4a75b3c0f7b11a2c5024159628d4DRC	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
165034dca052271f4a75b3c0f7b11a2c5024159628d4DRC	#ifndef JCS_EXTENSIONS
165134dca052271f4a75b3c0f7b11a2c5024159628d4DRC	if(rgbBuf) free(rgbBuf);
165234dca052271f4a75b3c0f7b11a2c5024159628d4DRC	#endif
165334dca052271f4a75b3c0f7b11a2c5024159628d4DRC	if(row_pointer) free(row_pointer);
165434dca052271f4a75b3c0f7b11a2c5024159628d4DRC	for(i=0; i<MAX_COMPONENTS; i++)
165534dca052271f4a75b3c0f7b11a2c5024159628d4DRC	{
165634dca052271f4a75b3c0f7b11a2c5024159628d4DRC		if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
165734dca052271f4a75b3c0f7b11a2c5024159628d4DRC		if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
165834dca052271f4a75b3c0f7b11a2c5024159628d4DRC		if(inbuf[i]!=NULL) free(inbuf[i]);
165934dca052271f4a75b3c0f7b11a2c5024159628d4DRC	}
16601f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	if(this->jerr.warning) retval=-1;
166134dca052271f4a75b3c0f7b11a2c5024159628d4DRC	return retval;
166234dca052271f4a75b3c0f7b11a2c5024159628d4DRC}
166334dca052271f4a75b3c0f7b11a2c5024159628d4DRC
1664aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRCDLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, unsigned char *srcBuf,
1665aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	int pad, int subsamp, unsigned char *dstBuf, int width, int pitch,
1666aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	int height, int pixelFormat, int flags)
1667aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC{
1668aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	unsigned char *srcPlanes[3];
166940dd3146cde2ba5036fe76a4f09e1125b4592347DRC	int pw0, ph0, strides[3], retval=-1;
167034dca052271f4a75b3c0f7b11a2c5024159628d4DRC
1671aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	if(srcBuf==NULL || pad<0 || !isPow2(pad) || subsamp<0 || subsamp>=NUMSUBOPT
1672aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		|| width<=0 || height<=0)
1673aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjDecodeYUV(): Invalid argument");
1674aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
167540dd3146cde2ba5036fe76a4f09e1125b4592347DRC	pw0=tjPlaneWidth(0, width, subsamp);
167640dd3146cde2ba5036fe76a4f09e1125b4592347DRC	ph0=tjPlaneHeight(0, height, subsamp);
1677aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	srcPlanes[0]=srcBuf;
167840dd3146cde2ba5036fe76a4f09e1125b4592347DRC	strides[0]=PAD(pw0, pad);
167940dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if(subsamp==TJSAMP_GRAY)
168040dd3146cde2ba5036fe76a4f09e1125b4592347DRC	{
168140dd3146cde2ba5036fe76a4f09e1125b4592347DRC		strides[1]=strides[2]=0;
168240dd3146cde2ba5036fe76a4f09e1125b4592347DRC		srcPlanes[1]=srcPlanes[2]=NULL;
168340dd3146cde2ba5036fe76a4f09e1125b4592347DRC	}
168440dd3146cde2ba5036fe76a4f09e1125b4592347DRC	else
168540dd3146cde2ba5036fe76a4f09e1125b4592347DRC	{
168640dd3146cde2ba5036fe76a4f09e1125b4592347DRC		int pw1=tjPlaneWidth(1, width, subsamp);
168740dd3146cde2ba5036fe76a4f09e1125b4592347DRC		int ph1=tjPlaneHeight(1, height, subsamp);
168840dd3146cde2ba5036fe76a4f09e1125b4592347DRC		strides[1]=strides[2]=PAD(pw1, pad);
168940dd3146cde2ba5036fe76a4f09e1125b4592347DRC		srcPlanes[1]=srcPlanes[0]+strides[0]*ph0;
169040dd3146cde2ba5036fe76a4f09e1125b4592347DRC		srcPlanes[2]=srcPlanes[1]+strides[1]*ph1;
169140dd3146cde2ba5036fe76a4f09e1125b4592347DRC	}
1692aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1693aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	return tjDecodeYUVPlanes(handle, srcPlanes, strides, subsamp, dstBuf, width,
1694aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		pitch, height, pixelFormat, flags);
1695aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1696aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	bailout:
1697aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	return retval;
1698aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC}
1699aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1700aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRCDLLEXPORT int DLLCALL tjDecompressToYUVPlanes(tjhandle handle,
1701aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	unsigned char *jpegBuf, unsigned long jpegSize, unsigned char **dstPlanes,
1702aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	int width, int *strides, int height, int flags)
17032e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC{
1704f610d61fcc38b36a8a29879e5c053015164242f8DRC	int i, sfi, row, retval=0;  JSAMPROW *outbuf[MAX_COMPONENTS];
1705418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC	int jpegwidth, jpegheight, jpegSubsamp, scaledw, scaledh;
170640dd3146cde2ba5036fe76a4f09e1125b4592347DRC	int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS],
1707f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC		tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
1708aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	JSAMPLE *_tmpbuf=NULL, *ptr;  JSAMPROW *tmpbuf[MAX_COMPONENTS];
1709418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC	int dctsize;
17102e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
1711418616266582fa978d4d1950cf739bbdac7ebee5DRC	getdinstance(handle);
1712b51ee895d8266529af7f96cb24fba53df273d32eDRC
1713f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	for(i=0; i<MAX_COMPONENTS; i++)
1714f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	{
1715f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC		tmpbuf[i]=NULL;  outbuf[i]=NULL;
1716f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	}
17179e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC
1718e2f8e694d0d1ec333c18d803cf0ba083e9feb1c0DRC	if((this->init&DECOMPRESS)==0)
1719aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjDecompressToYUVPlanes(): Instance has not been initialized for decompression");
1720e2f8e694d0d1ec333c18d803cf0ba083e9feb1c0DRC
1721aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	if(jpegBuf==NULL || jpegSize<=0 || !dstPlanes || !dstPlanes[0] || width<0
1722aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		|| height<0)
1723aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjDecompressToYUVPlanes(): Invalid argument");
17242e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
1725bec45b162bb77a57c147a9c44113af1968a79be4DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1726bec45b162bb77a57c147a9c44113af1968a79be4DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1727bec45b162bb77a57c147a9c44113af1968a79be4DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
17280c6a271f974529e4795332c9ad428500ef17fb42DRC
17299b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
17309b28defe6ac85dd8a52479cf276606beae24920eDRC	{
17319b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
173291e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC		retval=-1;
173391e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC		goto bailout;
17349e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	}
17352e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
1736aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	if(!this->headerRead)
1737aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	{
1738aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1739aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		jpeg_read_header(dinfo, TRUE);
1740aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	}
1741aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	this->headerRead=0;
1742418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC	jpegSubsamp=getSubsamp(dinfo);
1743418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC	if(jpegSubsamp<0)
1744aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjDecompressToYUVPlanes(): Could not determine subsampling type for JPEG image");
1745aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1746aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	if(jpegSubsamp!=TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2]))
1747aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjDecompressToYUVPlanes(): Invalid argument");
17482e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
1749f610d61fcc38b36a8a29879e5c053015164242f8DRC	jpegwidth=dinfo->image_width;  jpegheight=dinfo->image_height;
1750f610d61fcc38b36a8a29879e5c053015164242f8DRC	if(width==0) width=jpegwidth;
1751f610d61fcc38b36a8a29879e5c053015164242f8DRC	if(height==0) height=jpegheight;
1752f610d61fcc38b36a8a29879e5c053015164242f8DRC	for(i=0; i<NUMSF; i++)
1753f610d61fcc38b36a8a29879e5c053015164242f8DRC	{
1754f610d61fcc38b36a8a29879e5c053015164242f8DRC		scaledw=TJSCALED(jpegwidth, sf[i]);
1755f610d61fcc38b36a8a29879e5c053015164242f8DRC		scaledh=TJSCALED(jpegheight, sf[i]);
1756f610d61fcc38b36a8a29879e5c053015164242f8DRC		if(scaledw<=width && scaledh<=height)
1757f610d61fcc38b36a8a29879e5c053015164242f8DRC			break;
1758f610d61fcc38b36a8a29879e5c053015164242f8DRC	}
175958ae401e503ac61babb9d66be8fc06bfb0445dbfDRC	if(i>=NUMSF)
1760aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjDecompressToYUVPlanes(): Could not scale down to desired image dimensions");
1761cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC	if(dinfo->num_components>3)
1762aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjDecompressToYUVPlanes(): JPEG image must have 3 or fewer components");
1763cd7c3e6672cce3779450c6dd10d0d70b0c2278b2DRC
1764f610d61fcc38b36a8a29879e5c053015164242f8DRC	width=scaledw;  height=scaledh;
1765f610d61fcc38b36a8a29879e5c053015164242f8DRC	dinfo->scale_num=sf[i].num;
1766f610d61fcc38b36a8a29879e5c053015164242f8DRC	dinfo->scale_denom=sf[i].denom;
1767f610d61fcc38b36a8a29879e5c053015164242f8DRC	sfi=i;
1768f610d61fcc38b36a8a29879e5c053015164242f8DRC	jpeg_calc_output_dimensions(dinfo);
1769f610d61fcc38b36a8a29879e5c053015164242f8DRC
1770418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC	dctsize=DCTSIZE*sf[sfi].num/sf[sfi].denom;
1771418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC
17729b28defe6ac85dd8a52479cf276606beae24920eDRC	for(i=0; i<dinfo->num_components; i++)
17739e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	{
17749b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_component_info *compptr=&dinfo->comp_info[i];
17759b28defe6ac85dd8a52479cf276606beae24920eDRC		int ih;
1776418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC		iw[i]=compptr->width_in_blocks*dctsize;
1777418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC		ih=compptr->height_in_blocks*dctsize;
177840dd3146cde2ba5036fe76a4f09e1125b4592347DRC		pw[i]=PAD(dinfo->output_width, dinfo->max_h_samp_factor)
17799b28defe6ac85dd8a52479cf276606beae24920eDRC			*compptr->h_samp_factor/dinfo->max_h_samp_factor;
178040dd3146cde2ba5036fe76a4f09e1125b4592347DRC		ph[i]=PAD(dinfo->output_height, dinfo->max_v_samp_factor)
17819b28defe6ac85dd8a52479cf276606beae24920eDRC			*compptr->v_samp_factor/dinfo->max_v_samp_factor;
178240dd3146cde2ba5036fe76a4f09e1125b4592347DRC		if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1;
1783418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC		th[i]=compptr->v_samp_factor*dctsize;
17849b28defe6ac85dd8a52479cf276606beae24920eDRC		tmpbufsize+=iw[i]*th[i];
178540dd3146cde2ba5036fe76a4f09e1125b4592347DRC		if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]))==NULL)
1786aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC			_throw("tjDecompressToYUVPlanes(): Memory allocation failure");
1787aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		ptr=dstPlanes[i];
178840dd3146cde2ba5036fe76a4f09e1125b4592347DRC		for(row=0; row<ph[i]; row++)
17899e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC		{
17909b28defe6ac85dd8a52479cf276606beae24920eDRC			outbuf[i][row]=ptr;
179140dd3146cde2ba5036fe76a4f09e1125b4592347DRC			ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
1792f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC		}
17939b28defe6ac85dd8a52479cf276606beae24920eDRC	}
17949b28defe6ac85dd8a52479cf276606beae24920eDRC	if(usetmpbuf)
17959b28defe6ac85dd8a52479cf276606beae24920eDRC	{
17969b28defe6ac85dd8a52479cf276606beae24920eDRC		if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
1797aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC			_throw("tjDecompressToYUVPlanes(): Memory allocation failure");
17989b28defe6ac85dd8a52479cf276606beae24920eDRC		ptr=_tmpbuf;
17999b28defe6ac85dd8a52479cf276606beae24920eDRC		for(i=0; i<dinfo->num_components; i++)
1800f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC		{
18019b28defe6ac85dd8a52479cf276606beae24920eDRC			if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
1802aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC				_throw("tjDecompressToYUVPlanes(): Memory allocation failure");
18039b28defe6ac85dd8a52479cf276606beae24920eDRC			for(row=0; row<th[i]; row++)
1804f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC			{
18059b28defe6ac85dd8a52479cf276606beae24920eDRC				tmpbuf[i][row]=ptr;
18069b28defe6ac85dd8a52479cf276606beae24920eDRC				ptr+=iw[i];
18079e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC			}
18089e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC		}
18099e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	}
18102e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
181125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC	if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
1812e0419b530b3cecb9d7546893d893489a24d21032DRC	if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
18139b28defe6ac85dd8a52479cf276606beae24920eDRC	dinfo->raw_data_out=TRUE;
18149b28defe6ac85dd8a52479cf276606beae24920eDRC
18159b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_start_decompress(dinfo);
18169b28defe6ac85dd8a52479cf276606beae24920eDRC	for(row=0; row<(int)dinfo->output_height;
1817418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC		row+=dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size)
18188ed7b814039172fe3cbfadfee3922801a3888b73DRC	{
18199b28defe6ac85dd8a52479cf276606beae24920eDRC		JSAMPARRAY yuvptr[MAX_COMPONENTS];
18209b28defe6ac85dd8a52479cf276606beae24920eDRC		int crow[MAX_COMPONENTS];
18219b28defe6ac85dd8a52479cf276606beae24920eDRC		for(i=0; i<dinfo->num_components; i++)
1822842416034561f6d5320165a4fe98825e999a4a37DRC		{
18239b28defe6ac85dd8a52479cf276606beae24920eDRC			jpeg_component_info *compptr=&dinfo->comp_info[i];
1824418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC			if(jpegSubsamp==TJ_420)
1825418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC			{
1826418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC				/* When 4:2:0 subsampling is used with IDCT scaling, libjpeg will try
1827418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC				   to be clever and use the IDCT to perform upsampling on the U and V
1828418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC				   planes.  For instance, if the output image is to be scaled by 1/2
1829418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC				   relative to the JPEG image, then the scaling factor and upsampling
1830418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC				   effectively cancel each other, so a normal 8x8 IDCT can be used.
1831418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC				   However, this is not desirable when using the decompress-to-YUV
1832418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC				   functionality in TurboJPEG, since we want to output the U and V
1833418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC				   planes in their subsampled form.  Thus, we have to override some
1834418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC				   internal libjpeg parameters to force it to use the "scaled" IDCT
1835418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC				   functions on the U and V planes. */
1836418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC				compptr->_DCT_scaled_size=dctsize;
1837418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC				compptr->MCU_sample_width=tjMCUWidth[jpegSubsamp]*
1838418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC					sf[sfi].num/sf[sfi].denom*
1839418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC					compptr->v_samp_factor/dinfo->max_v_samp_factor;
1840418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC				dinfo->idct->inverse_DCT[i] = dinfo->idct->inverse_DCT[0];
1841418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC			}
18429b28defe6ac85dd8a52479cf276606beae24920eDRC			crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
18439b28defe6ac85dd8a52479cf276606beae24920eDRC			if(usetmpbuf) yuvptr[i]=tmpbuf[i];
18449b28defe6ac85dd8a52479cf276606beae24920eDRC			else yuvptr[i]=&outbuf[i][crow[i]];
1845842416034561f6d5320165a4fe98825e999a4a37DRC		}
1846f610d61fcc38b36a8a29879e5c053015164242f8DRC		jpeg_read_raw_data(dinfo, yuvptr,
1847418fe286c2fe90dcd3338f1f1d2f221c0e0e2bf3DRC			dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size);
18489b28defe6ac85dd8a52479cf276606beae24920eDRC		if(usetmpbuf)
18499e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC		{
18509b28defe6ac85dd8a52479cf276606beae24920eDRC			int j;
1851f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC			for(i=0; i<dinfo->num_components; i++)
18529e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC			{
185340dd3146cde2ba5036fe76a4f09e1125b4592347DRC				for(j=0; j<min(th[i], ph[i]-crow[i]); j++)
1854f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC				{
185540dd3146cde2ba5036fe76a4f09e1125b4592347DRC					memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], pw[i]);
1856f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC				}
18579e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC			}
18589e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC		}
18599e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	}
18609b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_finish_decompress(dinfo);
18612e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
186291e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	bailout:
18639b28defe6ac85dd8a52479cf276606beae24920eDRC	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
18649e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC	for(i=0; i<MAX_COMPONENTS; i++)
1865f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	{
1866f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC		if(tmpbuf[i]) free(tmpbuf[i]);
18679e17f7d9bcfe77c82550d90ea674b795baef5a5aDRC		if(outbuf[i]) free(outbuf[i]);
1868f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	}
1869f9cf5c799d76cfb1652b75b10c8a51e28546170dDRC	if(_tmpbuf) free(_tmpbuf);
18701f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	if(this->jerr.warning) retval=-1;
187191e86ba6cf9bf73bfd0a09d75b3a3845d64d4046DRC	return retval;
18722e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC}
18732e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
1874aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRCDLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle,
1875aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
1876aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	int width, int pad, int height, int flags)
1877aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC{
1878aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	unsigned char *dstPlanes[3];
187940dd3146cde2ba5036fe76a4f09e1125b4592347DRC	int pw0, ph0, strides[3], retval=-1, jpegSubsamp=-1;
1880aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	int i, jpegwidth, jpegheight, scaledw, scaledh;
1881aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1882aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	getdinstance(handle);
1883aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1884aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pad<1
1885aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		|| !isPow2(pad) || height<0)
1886aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjDecompressToYUV2(): Invalid argument");
1887aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1888aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1889aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	jpeg_read_header(dinfo, TRUE);
1890aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	jpegSubsamp=getSubsamp(dinfo);
1891aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	if(jpegSubsamp<0)
1892aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjDecompressToYUV2(): Could not determine subsampling type for JPEG image");
1893aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1894aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	jpegwidth=dinfo->image_width;  jpegheight=dinfo->image_height;
1895aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	if(width==0) width=jpegwidth;
1896aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	if(height==0) height=jpegheight;
1897aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1898aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	for(i=0; i<NUMSF; i++)
1899aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	{
1900aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		scaledw=TJSCALED(jpegwidth, sf[i]);
1901aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		scaledh=TJSCALED(jpegheight, sf[i]);
1902aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		if(scaledw<=width && scaledh<=height)
1903aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC			break;
1904aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	}
190558ae401e503ac61babb9d66be8fc06bfb0445dbfDRC	if(i>=NUMSF)
1906aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		_throw("tjDecompressToYUV2(): Could not scale down to desired image dimensions");
1907aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
190840dd3146cde2ba5036fe76a4f09e1125b4592347DRC	pw0=tjPlaneWidth(0, width, jpegSubsamp);
190940dd3146cde2ba5036fe76a4f09e1125b4592347DRC	ph0=tjPlaneHeight(0, height, jpegSubsamp);
1910aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	dstPlanes[0]=dstBuf;
191140dd3146cde2ba5036fe76a4f09e1125b4592347DRC	strides[0]=PAD(pw0, pad);
191240dd3146cde2ba5036fe76a4f09e1125b4592347DRC	if(jpegSubsamp==TJSAMP_GRAY)
191340dd3146cde2ba5036fe76a4f09e1125b4592347DRC	{
191440dd3146cde2ba5036fe76a4f09e1125b4592347DRC		strides[1]=strides[2]=0;
191540dd3146cde2ba5036fe76a4f09e1125b4592347DRC		dstPlanes[1]=dstPlanes[2]=NULL;
191640dd3146cde2ba5036fe76a4f09e1125b4592347DRC	}
191740dd3146cde2ba5036fe76a4f09e1125b4592347DRC	else
191840dd3146cde2ba5036fe76a4f09e1125b4592347DRC	{
191940dd3146cde2ba5036fe76a4f09e1125b4592347DRC		int pw1=tjPlaneWidth(1, width, jpegSubsamp);
192040dd3146cde2ba5036fe76a4f09e1125b4592347DRC		int ph1=tjPlaneHeight(1, height, jpegSubsamp);
192140dd3146cde2ba5036fe76a4f09e1125b4592347DRC		strides[1]=strides[2]=PAD(pw1, pad);
192240dd3146cde2ba5036fe76a4f09e1125b4592347DRC		dstPlanes[1]=dstPlanes[0]+strides[0]*ph0;
192340dd3146cde2ba5036fe76a4f09e1125b4592347DRC		dstPlanes[2]=dstPlanes[1]+strides[1]*ph1;
192440dd3146cde2ba5036fe76a4f09e1125b4592347DRC	}
1925aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1926aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	this->headerRead=1;
1927aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	return tjDecompressToYUVPlanes(handle, jpegBuf, jpegSize, dstPlanes, width,
1928aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC		strides, height, flags);
1929aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1930aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	bailout:
1931aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC	return retval;
1932aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1933aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC}
1934aecea388c7b3c22cb2ed1747acbcaefb8fd8e9a8DRC
1935f610d61fcc38b36a8a29879e5c053015164242f8DRCDLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle,
1936f610d61fcc38b36a8a29879e5c053015164242f8DRC	unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
1937f610d61fcc38b36a8a29879e5c053015164242f8DRC	int flags)
1938f610d61fcc38b36a8a29879e5c053015164242f8DRC{
1939f610d61fcc38b36a8a29879e5c053015164242f8DRC	return tjDecompressToYUV2(handle, jpegBuf, jpegSize, dstBuf, 0, 4, 0, flags);
1940f610d61fcc38b36a8a29879e5c053015164242f8DRC}
1941f610d61fcc38b36a8a29879e5c053015164242f8DRC
19422e7b76b28c0a872ae6ca002fd32bbba0769f990eDRC
19439b28defe6ac85dd8a52479cf276606beae24920eDRC/* Transformer */
1944890f1e0413b54c40b663208779d4ea9dae20eaefDRC
1945890f1e0413b54c40b663208779d4ea9dae20eaefDRCDLLEXPORT tjhandle DLLCALL tjInitTransform(void)
1946890f1e0413b54c40b663208779d4ea9dae20eaefDRC{
19479b28defe6ac85dd8a52479cf276606beae24920eDRC	tjinstance *this=NULL;  tjhandle handle=NULL;
19489b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
1949da5220acdd525242bff4e40b1d90324ebb889825DRC	{
1950007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		snprintf(errStr, JMSG_LENGTH_MAX,
1951007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			"tjInitTransform(): Memory allocation failure");
1952da5220acdd525242bff4e40b1d90324ebb889825DRC		return NULL;
1953da5220acdd525242bff4e40b1d90324ebb889825DRC	}
1954007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	MEMZERO(this, sizeof(tjinstance));
19559b28defe6ac85dd8a52479cf276606beae24920eDRC	handle=_tjInitCompress(this);
19569b28defe6ac85dd8a52479cf276606beae24920eDRC	if(!handle) return NULL;
19579b28defe6ac85dd8a52479cf276606beae24920eDRC	handle=_tjInitDecompress(this);
19589b28defe6ac85dd8a52479cf276606beae24920eDRC	return handle;
1959890f1e0413b54c40b663208779d4ea9dae20eaefDRC}
1960890f1e0413b54c40b663208779d4ea9dae20eaefDRC
1961890f1e0413b54c40b663208779d4ea9dae20eaefDRC
19629b28defe6ac85dd8a52479cf276606beae24920eDRCDLLEXPORT int DLLCALL tjTransform(tjhandle handle, unsigned char *jpegBuf,
19639b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long jpegSize, int n, unsigned char **dstBufs,
19649b28defe6ac85dd8a52479cf276606beae24920eDRC	unsigned long *dstSizes, tjtransform *t, int flags)
1965890f1e0413b54c40b663208779d4ea9dae20eaefDRC{
19660a325197dedd2eede99731c68ae0e0a145473f64DRC	jpeg_transform_info *xinfo=NULL;
1967890f1e0413b54c40b663208779d4ea9dae20eaefDRC	jvirt_barray_ptr *srccoefs, *dstcoefs;
19689b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	int retval=0, i, jpegSubsamp;
1969890f1e0413b54c40b663208779d4ea9dae20eaefDRC
19709b28defe6ac85dd8a52479cf276606beae24920eDRC	getinstance(handle);
19719b28defe6ac85dd8a52479cf276606beae24920eDRC	if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0)
1972007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjTransform(): Instance has not been initialized for transformation");
1973890f1e0413b54c40b663208779d4ea9dae20eaefDRC
19749b28defe6ac85dd8a52479cf276606beae24920eDRC	if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL
19750a325197dedd2eede99731c68ae0e0a145473f64DRC		|| t==NULL || flags<0)
19769b28defe6ac85dd8a52479cf276606beae24920eDRC		_throw("tjTransform(): Invalid argument");
1977890f1e0413b54c40b663208779d4ea9dae20eaefDRC
1978bec45b162bb77a57c147a9c44113af1968a79be4DRC	if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1979bec45b162bb77a57c147a9c44113af1968a79be4DRC	else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1980bec45b162bb77a57c147a9c44113af1968a79be4DRC	else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
1981890f1e0413b54c40b663208779d4ea9dae20eaefDRC
19829b28defe6ac85dd8a52479cf276606beae24920eDRC	if(setjmp(this->jerr.setjmp_buffer))
19839b28defe6ac85dd8a52479cf276606beae24920eDRC	{
19849b28defe6ac85dd8a52479cf276606beae24920eDRC		/* If we get here, the JPEG code has signaled an error. */
1985890f1e0413b54c40b663208779d4ea9dae20eaefDRC		retval=-1;
1986890f1e0413b54c40b663208779d4ea9dae20eaefDRC		goto bailout;
1987890f1e0413b54c40b663208779d4ea9dae20eaefDRC	}
1988890f1e0413b54c40b663208779d4ea9dae20eaefDRC
19899b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1990890f1e0413b54c40b663208779d4ea9dae20eaefDRC
19910a325197dedd2eede99731c68ae0e0a145473f64DRC	if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n))
19920a325197dedd2eede99731c68ae0e0a145473f64DRC		==NULL)
1993007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC		_throw("tjTransform(): Memory allocation failure");
1994007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC	MEMZERO(xinfo, sizeof(jpeg_transform_info)*n);
1995890f1e0413b54c40b663208779d4ea9dae20eaefDRC
19960a325197dedd2eede99731c68ae0e0a145473f64DRC	for(i=0; i<n; i++)
1997890f1e0413b54c40b663208779d4ea9dae20eaefDRC	{
19980a325197dedd2eede99731c68ae0e0a145473f64DRC		xinfo[i].transform=xformtypes[t[i].op];
199925b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0;
200025b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0;
200125b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0;
200225b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0;
200325b995ad4dd93d7f0dd2593fac10b8cb42c86209DRC		if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1;
2004ba5ea5143e48b71234414139e3b4cb244599e875DRC		else xinfo[i].slow_hflip=0;
20050a325197dedd2eede99731c68ae0e0a145473f64DRC
20060a325197dedd2eede99731c68ae0e0a145473f64DRC		if(xinfo[i].crop)
2007890f1e0413b54c40b663208779d4ea9dae20eaefDRC		{
20080a325197dedd2eede99731c68ae0e0a145473f64DRC			xinfo[i].crop_xoffset=t[i].r.x;  xinfo[i].crop_xoffset_set=JCROP_POS;
20090a325197dedd2eede99731c68ae0e0a145473f64DRC			xinfo[i].crop_yoffset=t[i].r.y;  xinfo[i].crop_yoffset_set=JCROP_POS;
20100a325197dedd2eede99731c68ae0e0a145473f64DRC			if(t[i].r.w!=0)
20110a325197dedd2eede99731c68ae0e0a145473f64DRC			{
20120a325197dedd2eede99731c68ae0e0a145473f64DRC				xinfo[i].crop_width=t[i].r.w;  xinfo[i].crop_width_set=JCROP_POS;
20130a325197dedd2eede99731c68ae0e0a145473f64DRC			}
2014d932e582178e2352b7e1da5622183e3e6082f5b3DRC			else xinfo[i].crop_width=JCROP_UNSET;
20150a325197dedd2eede99731c68ae0e0a145473f64DRC			if(t[i].r.h!=0)
20160a325197dedd2eede99731c68ae0e0a145473f64DRC			{
20170a325197dedd2eede99731c68ae0e0a145473f64DRC				xinfo[i].crop_height=t[i].r.h;  xinfo[i].crop_height_set=JCROP_POS;
20180a325197dedd2eede99731c68ae0e0a145473f64DRC			}
2019d932e582178e2352b7e1da5622183e3e6082f5b3DRC			else xinfo[i].crop_height=JCROP_UNSET;
2020890f1e0413b54c40b663208779d4ea9dae20eaefDRC		}
2021890f1e0413b54c40b663208779d4ea9dae20eaefDRC	}
2022890f1e0413b54c40b663208779d4ea9dae20eaefDRC
20239b28defe6ac85dd8a52479cf276606beae24920eDRC	jcopy_markers_setup(dinfo, JCOPYOPT_ALL);
20249b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_read_header(dinfo, TRUE);
20259b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	jpegSubsamp=getSubsamp(dinfo);
20269b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC	if(jpegSubsamp<0)
20279b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC		_throw("tjTransform(): Could not determine subsampling type for JPEG image");
2028890f1e0413b54c40b663208779d4ea9dae20eaefDRC
20290a325197dedd2eede99731c68ae0e0a145473f64DRC	for(i=0; i<n; i++)
2030890f1e0413b54c40b663208779d4ea9dae20eaefDRC	{
20319b28defe6ac85dd8a52479cf276606beae24920eDRC		if(!jtransform_request_workspace(dinfo, &xinfo[i]))
2032007a42cda4d3b6c4ec614aef0d46536ef2dfb8d4DRC			_throw("tjTransform(): Transform is not perfect");
20330a325197dedd2eede99731c68ae0e0a145473f64DRC
20340a325197dedd2eede99731c68ae0e0a145473f64DRC		if(xinfo[i].crop)
20350a325197dedd2eede99731c68ae0e0a145473f64DRC		{
20360a325197dedd2eede99731c68ae0e0a145473f64DRC			if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0
20370a325197dedd2eede99731c68ae0e0a145473f64DRC				|| (t[i].r.y%xinfo[i].iMCU_sample_height)!=0)
20380a325197dedd2eede99731c68ae0e0a145473f64DRC			{
20399b28defe6ac85dd8a52479cf276606beae24920eDRC				snprintf(errStr, JMSG_LENGTH_MAX,
20400a325197dedd2eede99731c68ae0e0a145473f64DRC					"To crop this JPEG image, x must be a multiple of %d\n"
20410a325197dedd2eede99731c68ae0e0a145473f64DRC					"and y must be a multiple of %d.\n",
20420a325197dedd2eede99731c68ae0e0a145473f64DRC					xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height);
20430a325197dedd2eede99731c68ae0e0a145473f64DRC				retval=-1;  goto bailout;
20440a325197dedd2eede99731c68ae0e0a145473f64DRC			}
20450a325197dedd2eede99731c68ae0e0a145473f64DRC		}
2046890f1e0413b54c40b663208779d4ea9dae20eaefDRC	}
2047890f1e0413b54c40b663208779d4ea9dae20eaefDRC
20489b28defe6ac85dd8a52479cf276606beae24920eDRC	srccoefs=jpeg_read_coefficients(dinfo);
2049890f1e0413b54c40b663208779d4ea9dae20eaefDRC
20500a325197dedd2eede99731c68ae0e0a145473f64DRC	for(i=0; i<n; i++)
2051890f1e0413b54c40b663208779d4ea9dae20eaefDRC	{
2052ff78e37595c8462f64fd100f928aa1d08539527eDRC		int w, h, alloc=1;
20530a325197dedd2eede99731c68ae0e0a145473f64DRC		if(!xinfo[i].crop)
2054890f1e0413b54c40b663208779d4ea9dae20eaefDRC		{
20559b28defe6ac85dd8a52479cf276606beae24920eDRC			w=dinfo->image_width;  h=dinfo->image_height;
2056890f1e0413b54c40b663208779d4ea9dae20eaefDRC		}
20570a325197dedd2eede99731c68ae0e0a145473f64DRC		else
20580a325197dedd2eede99731c68ae0e0a145473f64DRC		{
20590a325197dedd2eede99731c68ae0e0a145473f64DRC			w=xinfo[i].crop_width;  h=xinfo[i].crop_height;
20600a325197dedd2eede99731c68ae0e0a145473f64DRC		}
2061ff78e37595c8462f64fd100f928aa1d08539527eDRC		if(flags&TJFLAG_NOREALLOC)
2062ff78e37595c8462f64fd100f928aa1d08539527eDRC		{
20639b49f0e4c77c727648c6d3a4915eefdf5436de4aDRC			alloc=0;  dstSizes[i]=tjBufSize(w, h, jpegSubsamp);
2064ff78e37595c8462f64fd100f928aa1d08539527eDRC		}
20657bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		if(!(t[i].options&TJXOPT_NOOUTPUT))
20667bf04d399ebf9a3b39a6d5b5639d895df618353dDRC			jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc);
20679b28defe6ac85dd8a52479cf276606beae24920eDRC		jpeg_copy_critical_parameters(dinfo, cinfo);
20689b28defe6ac85dd8a52479cf276606beae24920eDRC		dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs,
20690a325197dedd2eede99731c68ae0e0a145473f64DRC			&xinfo[i]);
20707bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		if(!(t[i].options&TJXOPT_NOOUTPUT))
20717bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		{
20727bf04d399ebf9a3b39a6d5b5639d895df618353dDRC			jpeg_write_coefficients(cinfo, dstcoefs);
20737bf04d399ebf9a3b39a6d5b5639d895df618353dDRC			jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL);
20747bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		}
20757bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		else jinit_c_master_control(cinfo, TRUE);
20769b28defe6ac85dd8a52479cf276606beae24920eDRC		jtransform_execute_transformation(dinfo, cinfo, srccoefs,
20770a325197dedd2eede99731c68ae0e0a145473f64DRC			&xinfo[i]);
20787bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		if(t[i].customFilter)
20797bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		{
2080efe28cec4b29b5a7357d9cd1c30a066486d19b12DRC			int ci, y;  JDIMENSION by;
20817bf04d399ebf9a3b39a6d5b5639d895df618353dDRC			for(ci=0; ci<cinfo->num_components; ci++)
20827bf04d399ebf9a3b39a6d5b5639d895df618353dDRC			{
20837bf04d399ebf9a3b39a6d5b5639d895df618353dDRC				jpeg_component_info *compptr=&cinfo->comp_info[ci];
20847bf04d399ebf9a3b39a6d5b5639d895df618353dDRC				tjregion arrayRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
20857bf04d399ebf9a3b39a6d5b5639d895df618353dDRC					DCTSIZE};
20867bf04d399ebf9a3b39a6d5b5639d895df618353dDRC				tjregion planeRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
20877bf04d399ebf9a3b39a6d5b5639d895df618353dDRC					compptr->height_in_blocks*DCTSIZE};
20887bf04d399ebf9a3b39a6d5b5639d895df618353dDRC				for(by=0; by<compptr->height_in_blocks; by+=compptr->v_samp_factor)
20897bf04d399ebf9a3b39a6d5b5639d895df618353dDRC				{
20907bf04d399ebf9a3b39a6d5b5639d895df618353dDRC					JBLOCKARRAY barray=(dinfo->mem->access_virt_barray)
20917bf04d399ebf9a3b39a6d5b5639d895df618353dDRC						((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor,
20927bf04d399ebf9a3b39a6d5b5639d895df618353dDRC						TRUE);
20937bf04d399ebf9a3b39a6d5b5639d895df618353dDRC					for(y=0; y<compptr->v_samp_factor; y++)
20947bf04d399ebf9a3b39a6d5b5639d895df618353dDRC					{
20957bf04d399ebf9a3b39a6d5b5639d895df618353dDRC						if(t[i].customFilter(barray[y][0], arrayRegion, planeRegion,
2096f5467110763f7a44ca8baf1c035eb39a68c913c6DRC							ci, i, &t[i])==-1)
20977bf04d399ebf9a3b39a6d5b5639d895df618353dDRC							_throw("tjTransform(): Error in custom filter");
20987bf04d399ebf9a3b39a6d5b5639d895df618353dDRC						arrayRegion.y+=DCTSIZE;
20997bf04d399ebf9a3b39a6d5b5639d895df618353dDRC					}
21007bf04d399ebf9a3b39a6d5b5639d895df618353dDRC				}
21017bf04d399ebf9a3b39a6d5b5639d895df618353dDRC			}
21027bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		}
21037bf04d399ebf9a3b39a6d5b5639d895df618353dDRC		if(!(t[i].options&TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo);
2104890f1e0413b54c40b663208779d4ea9dae20eaefDRC	}
2105890f1e0413b54c40b663208779d4ea9dae20eaefDRC
21069b28defe6ac85dd8a52479cf276606beae24920eDRC	jpeg_finish_decompress(dinfo);
2107890f1e0413b54c40b663208779d4ea9dae20eaefDRC
2108890f1e0413b54c40b663208779d4ea9dae20eaefDRC	bailout:
21099b28defe6ac85dd8a52479cf276606beae24920eDRC	if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
21109b28defe6ac85dd8a52479cf276606beae24920eDRC	if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
21110a325197dedd2eede99731c68ae0e0a145473f64DRC	if(xinfo) free(xinfo);
21121f79c7c8c8c5e993042ea816e1dd161fb69061a3DRC	if(this->jerr.warning) retval=-1;
2113890f1e0413b54c40b663208779d4ea9dae20eaefDRC	return retval;
2114890f1e0413b54c40b663208779d4ea9dae20eaefDRC}
2115