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