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