1 /*
2 * Copyright (C)2009-2016 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
my_error_exit(j_common_ptr cinfo)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
my_output_message(j_common_ptr cinfo)76 static void my_output_message(j_common_ptr cinfo)
77 {
78 (*cinfo->err->format_message)(cinfo, errStr);
79 }
80
my_emit_message(j_common_ptr cinfo,int msg_level)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
getPixelFormat(int pixelSize,int flags)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
setCompDefaults(struct jpeg_compress_struct * cinfo,int pixelFormat,int subsamp,int jpegQual,int flags)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
setDecompDefaults(struct jpeg_decompress_struct * dinfo,int pixelFormat,int flags)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
getSubsamp(j_decompress_ptr dinfo)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
toRGB(unsigned char * src,int width,int pitch,int height,int pixelFormat,unsigned char * dst)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
fromRGB(unsigned char * src,unsigned char * dst,int width,int pitch,int height,int pixelFormat)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
tjGetErrorStr(void)545 DLLEXPORT char* DLLCALL tjGetErrorStr(void)
546 {
547 return errStr;
548 }
549
550
tjDestroy(tjhandle handle)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
tjFree(unsigned char * buf)567 DLLEXPORT void DLLCALL tjFree(unsigned char *buf)
568 {
569 if(buf) free(buf);
570 }
571
572
tjAlloc(int bytes)573 DLLEXPORT unsigned char *DLLCALL tjAlloc(int bytes)
574 {
575 return (unsigned char *)malloc(bytes);
576 }
577
578
579 /* Compressor */
580
_tjInitCompress(tjinstance * this)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
tjInitCompress(void)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
tjBufSize(int width,int height,int jpegSubsamp)622 DLLEXPORT unsigned long DLLCALL tjBufSize(int width, int height,
623 int jpegSubsamp)
624 {
625 unsigned long 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) * (2ULL + chromasf) + 2048ULL;
636 if (retval > (unsigned long long)((unsigned long)-1))
637 _throw("tjBufSize(): Image is too large");
638
639 bailout:
640 return (unsigned long)retval;
641 }
642
TJBUFSIZE(int width,int height)643 DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
644 {
645 unsigned long long retval=0;
646 if(width<1 || height<1)
647 _throw("TJBUFSIZE(): Invalid argument");
648
649 /* This allows for rare corner cases in which a JPEG image can actually be
650 larger than the uncompressed input (we wouldn't mention it if it hadn't
651 happened before.) */
652 retval=PAD(width, 16) * PAD(height, 16) * 6 + 2048;
653 if (retval > (unsigned long long)((unsigned long)-1))
654 _throw("tjBufSize(): Image is too large");
655
656 bailout:
657 return (unsigned long)retval;
658 }
659
660
tjBufSizeYUV2(int width,int pad,int height,int subsamp)661 DLLEXPORT unsigned long DLLCALL tjBufSizeYUV2(int width, int pad, int height,
662 int subsamp)
663 {
664 unsigned long long retval=0;
665 int nc, i;
666
667 if(subsamp<0 || subsamp>=NUMSUBOPT)
668 _throw("tjBufSizeYUV2(): Invalid argument");
669
670 nc=(subsamp==TJSAMP_GRAY? 1:3);
671 for(i=0; i<nc; i++)
672 {
673 int pw=tjPlaneWidth(i, width, subsamp);
674 int stride=PAD(pw, pad);
675 int ph=tjPlaneHeight(i, height, subsamp);
676 if(pw<0 || ph<0) return -1;
677 else retval+=(unsigned long long)stride*ph;
678 }
679 if (retval > (unsigned long long)((unsigned long)-1))
680 _throw("tjBufSize(): Image is too large");
681
682 bailout:
683 return (unsigned long)retval;
684 }
685
tjBufSizeYUV(int width,int height,int subsamp)686 DLLEXPORT unsigned long DLLCALL tjBufSizeYUV(int width, int height,
687 int subsamp)
688 {
689 return tjBufSizeYUV2(width, 4, height, subsamp);
690 }
691
TJBUFSIZEYUV(int width,int height,int subsamp)692 DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
693 int subsamp)
694 {
695 return tjBufSizeYUV(width, height, subsamp);
696 }
697
698
tjPlaneWidth(int componentID,int width,int subsamp)699 DLLEXPORT int tjPlaneWidth(int componentID, int width, int subsamp)
700 {
701 int pw, nc, retval=0;
702
703 if(width<1 || subsamp<0 || subsamp>=TJ_NUMSAMP)
704 _throw("tjPlaneWidth(): Invalid argument");
705 nc=(subsamp==TJSAMP_GRAY? 1:3);
706 if(componentID<0 || componentID>=nc)
707 _throw("tjPlaneWidth(): Invalid argument");
708
709 pw=PAD(width, tjMCUWidth[subsamp]/8);
710 if(componentID==0)
711 retval=pw;
712 else
713 retval=pw*8/tjMCUWidth[subsamp];
714
715 bailout:
716 return retval;
717 }
718
719
tjPlaneHeight(int componentID,int height,int subsamp)720 DLLEXPORT int tjPlaneHeight(int componentID, int height, int subsamp)
721 {
722 int ph, nc, retval=0;
723
724 if(height<1 || subsamp<0 || subsamp>=TJ_NUMSAMP)
725 _throw("tjPlaneHeight(): Invalid argument");
726 nc=(subsamp==TJSAMP_GRAY? 1:3);
727 if(componentID<0 || componentID>=nc)
728 _throw("tjPlaneHeight(): Invalid argument");
729
730 ph=PAD(height, tjMCUHeight[subsamp]/8);
731 if(componentID==0)
732 retval=ph;
733 else
734 retval=ph*8/tjMCUHeight[subsamp];
735
736 bailout:
737 return retval;
738 }
739
740
tjPlaneSizeYUV(int componentID,int width,int stride,int height,int subsamp)741 DLLEXPORT unsigned long DLLCALL tjPlaneSizeYUV(int componentID, int width,
742 int stride, int height, int subsamp)
743 {
744 unsigned long long retval=0;
745 int pw, ph;
746
747 if(width<1 || height<1 || subsamp<0 || subsamp>=NUMSUBOPT)
748 _throw("tjPlaneSizeYUV(): Invalid argument");
749
750 pw=tjPlaneWidth(componentID, width, subsamp);
751 ph=tjPlaneHeight(componentID, height, subsamp);
752 if(pw<0 || ph<0) return -1;
753
754 if(stride==0) stride=pw;
755 else stride=abs(stride);
756
757 retval=(unsigned long long)stride*(ph-1)+pw;
758 if (retval > (unsigned long long)((unsigned long)-1))
759 _throw("tjPlaneSizeYUV(): Image is too large");
760
761 bailout:
762 return (unsigned long)retval;
763 }
764
765
tjCompress2(tjhandle handle,const unsigned char * srcBuf,int width,int pitch,int height,int pixelFormat,unsigned char ** jpegBuf,unsigned long * jpegSize,int jpegSubsamp,int jpegQual,int flags)766 DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, const unsigned char *srcBuf,
767 int width, int pitch, int height, int pixelFormat, unsigned char **jpegBuf,
768 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
769 {
770 int i, retval=0, alloc=1; JSAMPROW *row_pointer=NULL;
771 #ifndef JCS_EXTENSIONS
772 unsigned char *rgbBuf=NULL;
773 #endif
774
775 getcinstance(handle)
776 if((this->init&COMPRESS)==0)
777 _throw("tjCompress2(): Instance has not been initialized for compression");
778
779 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
780 || pixelFormat>=TJ_NUMPF || jpegBuf==NULL || jpegSize==NULL
781 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT || jpegQual<0 || jpegQual>100)
782 _throw("tjCompress2(): Invalid argument");
783
784 if(setjmp(this->jerr.setjmp_buffer))
785 {
786 /* If we get here, the JPEG code has signaled an error. */
787 retval=-1;
788 goto bailout;
789 }
790
791 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
792
793 #ifndef JCS_EXTENSIONS
794 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK)
795 {
796 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
797 if(!rgbBuf) _throw("tjCompress2(): Memory allocation failure");
798 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
799 pitch=width*RGB_PIXELSIZE;
800 }
801 #endif
802
803 cinfo->image_width=width;
804 cinfo->image_height=height;
805
806 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
807 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
808 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
809
810 if(flags&TJFLAG_NOREALLOC)
811 {
812 alloc=0; *jpegSize=tjBufSize(width, height, jpegSubsamp);
813 }
814 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
815 if(setCompDefaults(cinfo, pixelFormat, jpegSubsamp, jpegQual, flags)==-1)
816 return -1;
817
818 jpeg_start_compress(cinfo, TRUE);
819 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
820 _throw("tjCompress2(): Memory allocation failure");
821 for(i=0; i<height; i++)
822 {
823 if(flags&TJFLAG_BOTTOMUP)
824 row_pointer[i]=(JSAMPROW)&srcBuf[(height-i-1)*(size_t)pitch];
825 else row_pointer[i]=(JSAMPROW)&srcBuf[i*(size_t)pitch];
826 }
827 while(cinfo->next_scanline<cinfo->image_height)
828 {
829 jpeg_write_scanlines(cinfo, &row_pointer[cinfo->next_scanline],
830 cinfo->image_height-cinfo->next_scanline);
831 }
832 jpeg_finish_compress(cinfo);
833
834 bailout:
835 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
836 #ifndef JCS_EXTENSIONS
837 if(rgbBuf) free(rgbBuf);
838 #endif
839 if(row_pointer) free(row_pointer);
840 if(this->jerr.warning) retval=-1;
841 return retval;
842 }
843
tjCompress(tjhandle handle,unsigned char * srcBuf,int width,int pitch,int height,int pixelSize,unsigned char * jpegBuf,unsigned long * jpegSize,int jpegSubsamp,int jpegQual,int flags)844 DLLEXPORT int DLLCALL tjCompress(tjhandle handle, unsigned char *srcBuf,
845 int width, int pitch, int height, int pixelSize, unsigned char *jpegBuf,
846 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
847 {
848 int retval=0; unsigned long size;
849 if(flags&TJ_YUV)
850 {
851 size=tjBufSizeYUV(width, height, jpegSubsamp);
852 retval=tjEncodeYUV2(handle, srcBuf, width, pitch, height,
853 getPixelFormat(pixelSize, flags), jpegBuf, jpegSubsamp, flags);
854 }
855 else
856 {
857 retval=tjCompress2(handle, srcBuf, width, pitch, height,
858 getPixelFormat(pixelSize, flags), &jpegBuf, &size, jpegSubsamp, jpegQual,
859 flags|TJFLAG_NOREALLOC);
860 }
861 *jpegSize=size;
862 return retval;
863 }
864
865
tjEncodeYUVPlanes(tjhandle handle,const unsigned char * srcBuf,int width,int pitch,int height,int pixelFormat,unsigned char ** dstPlanes,int * strides,int subsamp,int flags)866 DLLEXPORT int DLLCALL tjEncodeYUVPlanes(tjhandle handle,
867 const unsigned char *srcBuf, int width, int pitch, int height,
868 int pixelFormat, unsigned char **dstPlanes, int *strides, int subsamp,
869 int flags)
870 {
871 int i, retval=0; JSAMPROW *row_pointer=NULL;
872 JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS];
873 JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
874 JSAMPROW *outbuf[MAX_COMPONENTS];
875 int row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS];
876 JSAMPLE *ptr;
877 jpeg_component_info *compptr;
878 #ifndef JCS_EXTENSIONS
879 unsigned char *rgbBuf=NULL;
880 #endif
881
882 getcinstance(handle);
883
884 for(i=0; i<MAX_COMPONENTS; i++)
885 {
886 tmpbuf[i]=NULL; _tmpbuf[i]=NULL;
887 tmpbuf2[i]=NULL; _tmpbuf2[i]=NULL; outbuf[i]=NULL;
888 }
889
890 if((this->init&COMPRESS)==0)
891 _throw("tjEncodeYUVPlanes(): Instance has not been initialized for compression");
892
893 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
894 || pixelFormat>=TJ_NUMPF || !dstPlanes || !dstPlanes[0] || subsamp<0
895 || subsamp>=NUMSUBOPT)
896 _throw("tjEncodeYUVPlanes(): Invalid argument");
897 if(subsamp!=TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2]))
898 _throw("tjEncodeYUVPlanes(): Invalid argument");
899
900 if(setjmp(this->jerr.setjmp_buffer))
901 {
902 /* If we get here, the JPEG code has signaled an error. */
903 retval=-1;
904 goto bailout;
905 }
906
907 if(pixelFormat==TJPF_CMYK)
908 _throw("tjEncodeYUVPlanes(): Cannot generate YUV images from CMYK pixels");
909
910 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
911
912 #ifndef JCS_EXTENSIONS
913 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK)
914 {
915 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
916 if(!rgbBuf) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
917 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
918 pitch=width*RGB_PIXELSIZE;
919 }
920 #endif
921
922 cinfo->image_width=width;
923 cinfo->image_height=height;
924
925 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
926 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
927 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
928
929 if(setCompDefaults(cinfo, pixelFormat, subsamp, -1, flags)==-1) return -1;
930
931 /* Execute only the parts of jpeg_start_compress() that we need. If we
932 were to call the whole jpeg_start_compress() function, then it would try
933 to write the file headers, which could overflow the output buffer if the
934 YUV image were very small. */
935 if(cinfo->global_state!=CSTATE_START)
936 _throw("tjEncodeYUVPlanes(): libjpeg API is in the wrong state");
937 (*cinfo->err->reset_error_mgr)((j_common_ptr)cinfo);
938 jinit_c_master_control(cinfo, FALSE);
939 jinit_color_converter(cinfo);
940 jinit_downsampler(cinfo);
941 (*cinfo->cconvert->start_pass)(cinfo);
942
943 pw0=PAD(width, cinfo->max_h_samp_factor);
944 ph0=PAD(height, cinfo->max_v_samp_factor);
945
946 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL)
947 _throw("tjEncodeYUVPlanes(): Memory allocation failure");
948 for(i=0; i<height; i++)
949 {
950 if(flags&TJFLAG_BOTTOMUP)
951 row_pointer[i]=(JSAMPROW)&srcBuf[(height-i-1)*(size_t)pitch];
952 else row_pointer[i]=(JSAMPROW)&srcBuf[i*(size_t)pitch];
953 }
954 if(height<ph0)
955 for(i=height; i<ph0; i++) row_pointer[i]=row_pointer[height-1];
956
957 for(i=0; i<cinfo->num_components; i++)
958 {
959 compptr=&cinfo->comp_info[i];
960 _tmpbuf[i]=(JSAMPLE *)malloc(
961 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
962 /compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
963 if(!_tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
964 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
965 if(!tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
966 for(row=0; row<cinfo->max_v_samp_factor; row++)
967 {
968 unsigned char *_tmpbuf_aligned=
969 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
970 tmpbuf[i][row]=&_tmpbuf_aligned[
971 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
972 /compptr->h_samp_factor, 16) * row];
973 }
974 _tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
975 * compptr->v_samp_factor + 16);
976 if(!_tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
977 tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
978 if(!tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
979 for(row=0; row<compptr->v_samp_factor; row++)
980 {
981 unsigned char *_tmpbuf2_aligned=
982 (unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
983 tmpbuf2[i][row]=&_tmpbuf2_aligned[
984 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
985 }
986 pw[i]=pw0*compptr->h_samp_factor/cinfo->max_h_samp_factor;
987 ph[i]=ph0*compptr->v_samp_factor/cinfo->max_v_samp_factor;
988 outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]);
989 if(!outbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
990 ptr=dstPlanes[i];
991 for(row=0; row<ph[i]; row++)
992 {
993 outbuf[i][row]=ptr;
994 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
995 }
996 }
997
998 for(row=0; row<ph0; row+=cinfo->max_v_samp_factor)
999 {
1000 (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0,
1001 cinfo->max_v_samp_factor);
1002 (cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
1003 for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++)
1004 jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
1005 row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
1006 compptr->v_samp_factor, pw[i]);
1007 }
1008 cinfo->next_scanline+=height;
1009 jpeg_abort_compress(cinfo);
1010
1011 bailout:
1012 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
1013 #ifndef JCS_EXTENSIONS
1014 if(rgbBuf) free(rgbBuf);
1015 #endif
1016 if(row_pointer) free(row_pointer);
1017 for(i=0; i<MAX_COMPONENTS; i++)
1018 {
1019 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
1020 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
1021 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
1022 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
1023 if(outbuf[i]!=NULL) free(outbuf[i]);
1024 }
1025 if(this->jerr.warning) retval=-1;
1026 return retval;
1027 }
1028
tjEncodeYUV3(tjhandle handle,const unsigned char * srcBuf,int width,int pitch,int height,int pixelFormat,unsigned char * dstBuf,int pad,int subsamp,int flags)1029 DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle,
1030 const unsigned char *srcBuf, int width, int pitch, int height,
1031 int pixelFormat, unsigned char *dstBuf, int pad, int subsamp, int flags)
1032 {
1033 unsigned char *dstPlanes[3];
1034 int pw0, ph0, strides[3], retval=-1;
1035
1036 if(width<=0 || height<=0 || dstBuf==NULL || pad<0 || !isPow2(pad)
1037 || subsamp<0 || subsamp>=NUMSUBOPT)
1038 _throw("tjEncodeYUV3(): Invalid argument");
1039
1040 pw0=tjPlaneWidth(0, width, subsamp);
1041 ph0=tjPlaneHeight(0, height, subsamp);
1042 dstPlanes[0]=dstBuf;
1043 strides[0]=PAD(pw0, pad);
1044 if(subsamp==TJSAMP_GRAY)
1045 {
1046 strides[1]=strides[2]=0;
1047 dstPlanes[1]=dstPlanes[2]=NULL;
1048 }
1049 else
1050 {
1051 int pw1=tjPlaneWidth(1, width, subsamp);
1052 int ph1=tjPlaneHeight(1, height, subsamp);
1053 strides[1]=strides[2]=PAD(pw1, pad);
1054 dstPlanes[1]=dstPlanes[0]+strides[0]*ph0;
1055 dstPlanes[2]=dstPlanes[1]+strides[1]*ph1;
1056 }
1057
1058 return tjEncodeYUVPlanes(handle, srcBuf, width, pitch, height, pixelFormat,
1059 dstPlanes, strides, subsamp, flags);
1060
1061 bailout:
1062 return retval;
1063 }
1064
tjEncodeYUV2(tjhandle handle,unsigned char * srcBuf,int width,int pitch,int height,int pixelFormat,unsigned char * dstBuf,int subsamp,int flags)1065 DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
1066 int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
1067 int subsamp, int flags)
1068 {
1069 return tjEncodeYUV3(handle, srcBuf, width, pitch, height, pixelFormat,
1070 dstBuf, 4, subsamp, flags);
1071 }
1072
tjEncodeYUV(tjhandle handle,unsigned char * srcBuf,int width,int pitch,int height,int pixelSize,unsigned char * dstBuf,int subsamp,int flags)1073 DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf,
1074 int width, int pitch, int height, int pixelSize, unsigned char *dstBuf,
1075 int subsamp, int flags)
1076 {
1077 return tjEncodeYUV2(handle, srcBuf, width, pitch, height,
1078 getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags);
1079 }
1080
1081
tjCompressFromYUVPlanes(tjhandle handle,const unsigned char ** srcPlanes,int width,const int * strides,int height,int subsamp,unsigned char ** jpegBuf,unsigned long * jpegSize,int jpegQual,int flags)1082 DLLEXPORT int DLLCALL tjCompressFromYUVPlanes(tjhandle handle,
1083 const unsigned char **srcPlanes, int width, const int *strides, int height,
1084 int subsamp, unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual,
1085 int flags)
1086 {
1087 int i, row, retval=0, alloc=1; JSAMPROW *inbuf[MAX_COMPONENTS];
1088 int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS],
1089 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
1090 JSAMPLE *_tmpbuf=NULL, *ptr; JSAMPROW *tmpbuf[MAX_COMPONENTS];
1091
1092 getcinstance(handle)
1093
1094 for(i=0; i<MAX_COMPONENTS; i++)
1095 {
1096 tmpbuf[i]=NULL; inbuf[i]=NULL;
1097 }
1098
1099 if((this->init&COMPRESS)==0)
1100 _throw("tjCompressFromYUVPlanes(): Instance has not been initialized for compression");
1101
1102 if(!srcPlanes || !srcPlanes[0] || width<=0 || height<=0 || subsamp<0
1103 || subsamp>=NUMSUBOPT || jpegBuf==NULL || jpegSize==NULL || jpegQual<0
1104 || jpegQual>100)
1105 _throw("tjCompressFromYUVPlanes(): Invalid argument");
1106 if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2]))
1107 _throw("tjCompressFromYUVPlanes(): Invalid argument");
1108
1109 if(setjmp(this->jerr.setjmp_buffer))
1110 {
1111 /* If we get here, the JPEG code has signaled an error. */
1112 retval=-1;
1113 goto bailout;
1114 }
1115
1116 cinfo->image_width=width;
1117 cinfo->image_height=height;
1118
1119 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1120 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1121 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
1122
1123 if(flags&TJFLAG_NOREALLOC)
1124 {
1125 alloc=0; *jpegSize=tjBufSize(width, height, subsamp);
1126 }
1127 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
1128 if(setCompDefaults(cinfo, TJPF_RGB, subsamp, jpegQual, flags)==-1)
1129 return -1;
1130 cinfo->raw_data_in=TRUE;
1131
1132 jpeg_start_compress(cinfo, TRUE);
1133 for(i=0; i<cinfo->num_components; i++)
1134 {
1135 jpeg_component_info *compptr=&cinfo->comp_info[i];
1136 int ih;
1137 iw[i]=compptr->width_in_blocks*DCTSIZE;
1138 ih=compptr->height_in_blocks*DCTSIZE;
1139 pw[i]=PAD(cinfo->image_width, cinfo->max_h_samp_factor)
1140 *compptr->h_samp_factor/cinfo->max_h_samp_factor;
1141 ph[i]=PAD(cinfo->image_height, cinfo->max_v_samp_factor)
1142 *compptr->v_samp_factor/cinfo->max_v_samp_factor;
1143 if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1;
1144 th[i]=compptr->v_samp_factor*DCTSIZE;
1145 tmpbufsize+=iw[i]*th[i];
1146 if((inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]))==NULL)
1147 _throw("tjCompressFromYUVPlanes(): Memory allocation failure");
1148 ptr=(JSAMPLE *)srcPlanes[i];
1149 for(row=0; row<ph[i]; row++)
1150 {
1151 inbuf[i][row]=ptr;
1152 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
1153 }
1154 }
1155 if(usetmpbuf)
1156 {
1157 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
1158 _throw("tjCompressFromYUVPlanes(): Memory allocation failure");
1159 ptr=_tmpbuf;
1160 for(i=0; i<cinfo->num_components; i++)
1161 {
1162 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
1163 _throw("tjCompressFromYUVPlanes(): Memory allocation failure");
1164 for(row=0; row<th[i]; row++)
1165 {
1166 tmpbuf[i][row]=ptr;
1167 ptr+=iw[i];
1168 }
1169 }
1170 }
1171
1172 for(row=0; row<(int)cinfo->image_height;
1173 row+=cinfo->max_v_samp_factor*DCTSIZE)
1174 {
1175 JSAMPARRAY yuvptr[MAX_COMPONENTS];
1176 int crow[MAX_COMPONENTS];
1177 for(i=0; i<cinfo->num_components; i++)
1178 {
1179 jpeg_component_info *compptr=&cinfo->comp_info[i];
1180 crow[i]=row*compptr->v_samp_factor/cinfo->max_v_samp_factor;
1181 if(usetmpbuf)
1182 {
1183 int j, k;
1184 for(j=0; j<min(th[i], ph[i]-crow[i]); j++)
1185 {
1186 memcpy(tmpbuf[i][j], inbuf[i][crow[i]+j], pw[i]);
1187 /* Duplicate last sample in row to fill out MCU */
1188 for(k=pw[i]; k<iw[i]; k++) tmpbuf[i][j][k]=tmpbuf[i][j][pw[i]-1];
1189 }
1190 /* Duplicate last row to fill out MCU */
1191 for(j=ph[i]-crow[i]; j<th[i]; j++)
1192 memcpy(tmpbuf[i][j], tmpbuf[i][ph[i]-crow[i]-1], iw[i]);
1193 yuvptr[i]=tmpbuf[i];
1194 }
1195 else
1196 yuvptr[i]=&inbuf[i][crow[i]];
1197 }
1198 jpeg_write_raw_data(cinfo, yuvptr, cinfo->max_v_samp_factor*DCTSIZE);
1199 }
1200 jpeg_finish_compress(cinfo);
1201
1202 bailout:
1203 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
1204 for(i=0; i<MAX_COMPONENTS; i++)
1205 {
1206 if(tmpbuf[i]) free(tmpbuf[i]);
1207 if(inbuf[i]) free(inbuf[i]);
1208 }
1209 if(_tmpbuf) free(_tmpbuf);
1210 if(this->jerr.warning) retval=-1;
1211 return retval;
1212 }
1213
tjCompressFromYUV(tjhandle handle,const unsigned char * srcBuf,int width,int pad,int height,int subsamp,unsigned char ** jpegBuf,unsigned long * jpegSize,int jpegQual,int flags)1214 DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle,
1215 const unsigned char *srcBuf, int width, int pad, int height, int subsamp,
1216 unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual, int flags)
1217 {
1218 const unsigned char *srcPlanes[3];
1219 int pw0, ph0, strides[3], retval=-1;
1220
1221 if(srcBuf==NULL || width<=0 || pad<1 || height<=0 || subsamp<0
1222 || subsamp>=NUMSUBOPT)
1223 _throw("tjCompressFromYUV(): Invalid argument");
1224
1225 pw0=tjPlaneWidth(0, width, subsamp);
1226 ph0=tjPlaneHeight(0, height, subsamp);
1227 srcPlanes[0]=srcBuf;
1228 strides[0]=PAD(pw0, pad);
1229 if(subsamp==TJSAMP_GRAY)
1230 {
1231 strides[1]=strides[2]=0;
1232 srcPlanes[1]=srcPlanes[2]=NULL;
1233 }
1234 else
1235 {
1236 int pw1=tjPlaneWidth(1, width, subsamp);
1237 int ph1=tjPlaneHeight(1, height, subsamp);
1238 strides[1]=strides[2]=PAD(pw1, pad);
1239 srcPlanes[1]=srcPlanes[0]+strides[0]*ph0;
1240 srcPlanes[2]=srcPlanes[1]+strides[1]*ph1;
1241 }
1242
1243 return tjCompressFromYUVPlanes(handle, srcPlanes, width, strides, height,
1244 subsamp, jpegBuf, jpegSize, jpegQual, flags);
1245
1246 bailout:
1247 return retval;
1248 }
1249
1250
1251 /* Decompressor */
1252
_tjInitDecompress(tjinstance * this)1253 static tjhandle _tjInitDecompress(tjinstance *this)
1254 {
1255 static unsigned char buffer[1];
1256
1257 /* This is also straight out of example.c */
1258 this->dinfo.err=jpeg_std_error(&this->jerr.pub);
1259 this->jerr.pub.error_exit=my_error_exit;
1260 this->jerr.pub.output_message=my_output_message;
1261 this->jerr.emit_message=this->jerr.pub.emit_message;
1262 this->jerr.pub.emit_message=my_emit_message;
1263
1264 if(setjmp(this->jerr.setjmp_buffer))
1265 {
1266 /* If we get here, the JPEG code has signaled an error. */
1267 if(this) free(this);
1268 return NULL;
1269 }
1270
1271 jpeg_create_decompress(&this->dinfo);
1272 /* Make an initial call so it will create the source manager */
1273 jpeg_mem_src_tj(&this->dinfo, buffer, 1);
1274
1275 this->init|=DECOMPRESS;
1276 return (tjhandle)this;
1277 }
1278
tjInitDecompress(void)1279 DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
1280 {
1281 tjinstance *this;
1282 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
1283 {
1284 snprintf(errStr, JMSG_LENGTH_MAX,
1285 "tjInitDecompress(): Memory allocation failure");
1286 return NULL;
1287 }
1288 MEMZERO(this, sizeof(tjinstance));
1289 return _tjInitDecompress(this);
1290 }
1291
1292
tjDecompressHeader3(tjhandle handle,const unsigned char * jpegBuf,unsigned long jpegSize,int * width,int * height,int * jpegSubsamp,int * jpegColorspace)1293 DLLEXPORT int DLLCALL tjDecompressHeader3(tjhandle handle,
1294 const unsigned char *jpegBuf, unsigned long jpegSize, int *width,
1295 int *height, int *jpegSubsamp, int *jpegColorspace)
1296 {
1297 int retval=0;
1298
1299 getdinstance(handle);
1300 if((this->init&DECOMPRESS)==0)
1301 _throw("tjDecompressHeader3(): Instance has not been initialized for decompression");
1302
1303 if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL
1304 || jpegSubsamp==NULL || jpegColorspace==NULL)
1305 _throw("tjDecompressHeader3(): Invalid argument");
1306
1307 if(setjmp(this->jerr.setjmp_buffer))
1308 {
1309 /* If we get here, the JPEG code has signaled an error. */
1310 return -1;
1311 }
1312
1313 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1314 jpeg_read_header(dinfo, TRUE);
1315
1316 *width=dinfo->image_width;
1317 *height=dinfo->image_height;
1318 *jpegSubsamp=getSubsamp(dinfo);
1319 switch(dinfo->jpeg_color_space)
1320 {
1321 case JCS_GRAYSCALE: *jpegColorspace=TJCS_GRAY; break;
1322 case JCS_RGB: *jpegColorspace=TJCS_RGB; break;
1323 case JCS_YCbCr: *jpegColorspace=TJCS_YCbCr; break;
1324 case JCS_CMYK: *jpegColorspace=TJCS_CMYK; break;
1325 case JCS_YCCK: *jpegColorspace=TJCS_YCCK; break;
1326 default: *jpegColorspace=-1; break;
1327 }
1328
1329 jpeg_abort_decompress(dinfo);
1330
1331 if(*jpegSubsamp<0)
1332 _throw("tjDecompressHeader3(): Could not determine subsampling type for JPEG image");
1333 if(*jpegColorspace<0)
1334 _throw("tjDecompressHeader3(): Could not determine colorspace of JPEG image");
1335 if(*width<1 || *height<1)
1336 _throw("tjDecompressHeader3(): Invalid data returned in header");
1337
1338 bailout:
1339 if(this->jerr.warning) retval=-1;
1340 return retval;
1341 }
1342
tjDecompressHeader2(tjhandle handle,unsigned char * jpegBuf,unsigned long jpegSize,int * width,int * height,int * jpegSubsamp)1343 DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle,
1344 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
1345 int *jpegSubsamp)
1346 {
1347 int jpegColorspace;
1348 return tjDecompressHeader3(handle, jpegBuf, jpegSize, width, height,
1349 jpegSubsamp, &jpegColorspace);
1350 }
1351
tjDecompressHeader(tjhandle handle,unsigned char * jpegBuf,unsigned long jpegSize,int * width,int * height)1352 DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle,
1353 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height)
1354 {
1355 int jpegSubsamp;
1356 return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height,
1357 &jpegSubsamp);
1358 }
1359
1360
tjGetScalingFactors(int * numscalingfactors)1361 DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors)
1362 {
1363 if(numscalingfactors==NULL)
1364 {
1365 snprintf(errStr, JMSG_LENGTH_MAX,
1366 "tjGetScalingFactors(): Invalid argument");
1367 return NULL;
1368 }
1369
1370 *numscalingfactors=NUMSF;
1371 return (tjscalingfactor *)sf;
1372 }
1373
1374
tjDecompress2(tjhandle handle,const unsigned char * jpegBuf,unsigned long jpegSize,unsigned char * dstBuf,int width,int pitch,int height,int pixelFormat,int flags)1375 DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle,
1376 const unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
1377 int width, int pitch, int height, int pixelFormat, int flags)
1378 {
1379 int i, retval=0; JSAMPROW *row_pointer=NULL;
1380 int jpegwidth, jpegheight, scaledw, scaledh;
1381 #ifndef JCS_EXTENSIONS
1382 unsigned char *rgbBuf=NULL;
1383 unsigned char *_dstBuf=NULL; int _pitch=0;
1384 #endif
1385
1386 getdinstance(handle);
1387 if((this->init&DECOMPRESS)==0)
1388 _throw("tjDecompress2(): Instance has not been initialized for decompression");
1389
1390 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0
1391 || height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF)
1392 _throw("tjDecompress2(): Invalid argument");
1393
1394 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1395 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1396 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
1397
1398 if(setjmp(this->jerr.setjmp_buffer))
1399 {
1400 /* If we get here, the JPEG code has signaled an error. */
1401 retval=-1;
1402 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 for(i=0; i<(int)dinfo->output_height; i++)
1451 {
1452 if(flags&TJFLAG_BOTTOMUP)
1453 row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*(size_t)pitch];
1454 else row_pointer[i]=&dstBuf[i*(size_t)pitch];
1455 }
1456 while(dinfo->output_scanline<dinfo->output_height)
1457 {
1458 jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline],
1459 dinfo->output_height-dinfo->output_scanline);
1460 }
1461 jpeg_finish_decompress(dinfo);
1462
1463 #ifndef JCS_EXTENSIONS
1464 fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
1465 #endif
1466
1467 bailout:
1468 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
1469 #ifndef JCS_EXTENSIONS
1470 if(rgbBuf) free(rgbBuf);
1471 #endif
1472 if(row_pointer) free(row_pointer);
1473 if(this->jerr.warning) retval=-1;
1474 return retval;
1475 }
1476
tjDecompress(tjhandle handle,unsigned char * jpegBuf,unsigned long jpegSize,unsigned char * dstBuf,int width,int pitch,int height,int pixelSize,int flags)1477 DLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf,
1478 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
1479 int height, int pixelSize, int flags)
1480 {
1481 if(flags&TJ_YUV)
1482 return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags);
1483 else
1484 return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch,
1485 height, getPixelFormat(pixelSize, flags), flags);
1486 }
1487
1488
setDecodeDefaults(struct jpeg_decompress_struct * dinfo,int pixelFormat,int subsamp,int flags)1489 static int setDecodeDefaults(struct jpeg_decompress_struct *dinfo,
1490 int pixelFormat, int subsamp, int flags)
1491 {
1492 int i;
1493
1494 dinfo->scale_num=dinfo->scale_denom=1;
1495
1496 if(subsamp==TJSAMP_GRAY)
1497 {
1498 dinfo->num_components=dinfo->comps_in_scan=1;
1499 dinfo->jpeg_color_space=JCS_GRAYSCALE;
1500 }
1501 else
1502 {
1503 dinfo->num_components=dinfo->comps_in_scan=3;
1504 dinfo->jpeg_color_space=JCS_YCbCr;
1505 }
1506
1507 dinfo->comp_info=(jpeg_component_info *)
1508 (*dinfo->mem->alloc_small)((j_common_ptr)dinfo, JPOOL_IMAGE,
1509 dinfo->num_components*sizeof(jpeg_component_info));
1510
1511 for(i=0; i<dinfo->num_components; i++)
1512 {
1513 jpeg_component_info *compptr=&dinfo->comp_info[i];
1514 compptr->h_samp_factor=(i==0)? tjMCUWidth[subsamp]/8:1;
1515 compptr->v_samp_factor=(i==0)? tjMCUHeight[subsamp]/8:1;
1516 compptr->component_index=i;
1517 compptr->component_id=i+1;
1518 compptr->quant_tbl_no=compptr->dc_tbl_no=compptr->ac_tbl_no=
1519 (i==0)? 0:1;
1520 dinfo->cur_comp_info[i]=compptr;
1521 }
1522 dinfo->data_precision=8;
1523 for(i=0; i<2; i++)
1524 {
1525 if(dinfo->quant_tbl_ptrs[i]==NULL)
1526 dinfo->quant_tbl_ptrs[i]=jpeg_alloc_quant_table((j_common_ptr)dinfo);
1527 }
1528
1529 return 0;
1530 }
1531
1532
my_read_markers(j_decompress_ptr dinfo)1533 int my_read_markers(j_decompress_ptr dinfo)
1534 {
1535 return JPEG_REACHED_SOS;
1536 }
1537
my_reset_marker_reader(j_decompress_ptr dinfo)1538 void my_reset_marker_reader(j_decompress_ptr dinfo)
1539 {
1540 }
1541
tjDecodeYUVPlanes(tjhandle handle,const unsigned char ** srcPlanes,const int * strides,int subsamp,unsigned char * dstBuf,int width,int pitch,int height,int pixelFormat,int flags)1542 DLLEXPORT int DLLCALL tjDecodeYUVPlanes(tjhandle handle,
1543 const unsigned char **srcPlanes, const int *strides, int subsamp,
1544 unsigned char *dstBuf, int width, int pitch, int height, int pixelFormat,
1545 int flags)
1546 {
1547 int i, retval=0; JSAMPROW *row_pointer=NULL;
1548 JSAMPLE *_tmpbuf[MAX_COMPONENTS];
1549 JSAMPROW *tmpbuf[MAX_COMPONENTS], *inbuf[MAX_COMPONENTS];
1550 int row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS];
1551 JSAMPLE *ptr;
1552 jpeg_component_info *compptr;
1553 #ifndef JCS_EXTENSIONS
1554 unsigned char *rgbBuf=NULL;
1555 unsigned char *_dstBuf=NULL; int _pitch=0;
1556 #endif
1557 int (*old_read_markers)(j_decompress_ptr);
1558 void (*old_reset_marker_reader)(j_decompress_ptr);
1559
1560 getdinstance(handle);
1561
1562 for(i=0; i<MAX_COMPONENTS; i++)
1563 {
1564 tmpbuf[i]=NULL; _tmpbuf[i]=NULL; inbuf[i]=NULL;
1565 }
1566
1567 if((this->init&DECOMPRESS)==0)
1568 _throw("tjDecodeYUVPlanes(): Instance has not been initialized for decompression");
1569
1570 if(!srcPlanes || !srcPlanes[0] || subsamp<0 || subsamp>=NUMSUBOPT
1571 || dstBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
1572 || pixelFormat>=TJ_NUMPF)
1573 _throw("tjDecodeYUVPlanes(): Invalid argument");
1574 if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2]))
1575 _throw("tjDecodeYUVPlanes(): Invalid argument");
1576
1577 if(setjmp(this->jerr.setjmp_buffer))
1578 {
1579 /* If we get here, the JPEG code has signaled an error. */
1580 retval=-1;
1581 goto bailout;
1582 }
1583
1584 if(pixelFormat==TJPF_CMYK)
1585 _throw("tjDecodeYUVPlanes(): Cannot decode YUV images into CMYK pixels.");
1586
1587 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
1588 dinfo->image_width=width;
1589 dinfo->image_height=height;
1590
1591 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1592 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1593 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
1594
1595 if(setDecodeDefaults(dinfo, pixelFormat, subsamp, flags)==-1)
1596 {
1597 retval=-1; goto bailout;
1598 }
1599 old_read_markers=dinfo->marker->read_markers;
1600 dinfo->marker->read_markers=my_read_markers;
1601 old_reset_marker_reader=dinfo->marker->reset_marker_reader;
1602 dinfo->marker->reset_marker_reader=my_reset_marker_reader;
1603 jpeg_read_header(dinfo, TRUE);
1604 dinfo->marker->read_markers=old_read_markers;
1605 dinfo->marker->reset_marker_reader=old_reset_marker_reader;
1606
1607 if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
1608 {
1609 retval=-1; goto bailout;
1610 }
1611 dinfo->do_fancy_upsampling=FALSE;
1612 dinfo->Se=DCTSIZE2-1;
1613 jinit_master_decompress(dinfo);
1614 (*dinfo->upsample->start_pass)(dinfo);
1615
1616 pw0=PAD(width, dinfo->max_h_samp_factor);
1617 ph0=PAD(height, dinfo->max_v_samp_factor);
1618
1619 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
1620
1621 #ifndef JCS_EXTENSIONS
1622 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK &&
1623 (RGB_RED!=tjRedOffset[pixelFormat] ||
1624 RGB_GREEN!=tjGreenOffset[pixelFormat] ||
1625 RGB_BLUE!=tjBlueOffset[pixelFormat] ||
1626 RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
1627 {
1628 rgbBuf=(unsigned char *)malloc(width*height*3);
1629 if(!rgbBuf) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1630 _pitch=pitch; pitch=width*3;
1631 _dstBuf=dstBuf; dstBuf=rgbBuf;
1632 }
1633 #endif
1634
1635 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL)
1636 _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1637 for(i=0; i<height; i++)
1638 {
1639 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&dstBuf[(height-i-1)*(size_t)pitch];
1640 else row_pointer[i]=&dstBuf[i*(size_t)pitch];
1641 }
1642 if(height<ph0)
1643 for(i=height; i<ph0; i++) row_pointer[i]=row_pointer[height-1];
1644
1645 for(i=0; i<dinfo->num_components; i++)
1646 {
1647 compptr=&dinfo->comp_info[i];
1648 _tmpbuf[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
1649 * compptr->v_samp_factor + 16);
1650 if(!_tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1651 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
1652 if(!tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1653 for(row=0; row<compptr->v_samp_factor; row++)
1654 {
1655 unsigned char *_tmpbuf_aligned=
1656 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
1657 tmpbuf[i][row]=&_tmpbuf_aligned[
1658 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
1659 }
1660 pw[i]=pw0*compptr->h_samp_factor/dinfo->max_h_samp_factor;
1661 ph[i]=ph0*compptr->v_samp_factor/dinfo->max_v_samp_factor;
1662 inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]);
1663 if(!inbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1664 ptr=(JSAMPLE *)srcPlanes[i];
1665 for(row=0; row<ph[i]; row++)
1666 {
1667 inbuf[i][row]=ptr;
1668 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
1669 }
1670 }
1671
1672 for(row=0; row<ph0; row+=dinfo->max_v_samp_factor)
1673 {
1674 JDIMENSION inrow=0, outrow=0;
1675 for(i=0, compptr=dinfo->comp_info; i<dinfo->num_components; i++, compptr++)
1676 jcopy_sample_rows(inbuf[i],
1677 row*compptr->v_samp_factor/dinfo->max_v_samp_factor, tmpbuf[i], 0,
1678 compptr->v_samp_factor, pw[i]);
1679 (dinfo->upsample->upsample)(dinfo, tmpbuf, &inrow,
1680 dinfo->max_v_samp_factor, &row_pointer[row], &outrow,
1681 dinfo->max_v_samp_factor);
1682 }
1683 jpeg_abort_decompress(dinfo);
1684
1685 #ifndef JCS_EXTENSIONS
1686 fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
1687 #endif
1688
1689 bailout:
1690 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
1691 #ifndef JCS_EXTENSIONS
1692 if(rgbBuf) free(rgbBuf);
1693 #endif
1694 if(row_pointer) free(row_pointer);
1695 for(i=0; i<MAX_COMPONENTS; i++)
1696 {
1697 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
1698 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
1699 if(inbuf[i]!=NULL) free(inbuf[i]);
1700 }
1701 if(this->jerr.warning) retval=-1;
1702 return retval;
1703 }
1704
tjDecodeYUV(tjhandle handle,const unsigned char * srcBuf,int pad,int subsamp,unsigned char * dstBuf,int width,int pitch,int height,int pixelFormat,int flags)1705 DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, const unsigned char *srcBuf,
1706 int pad, int subsamp, unsigned char *dstBuf, int width, int pitch,
1707 int height, int pixelFormat, int flags)
1708 {
1709 const unsigned char *srcPlanes[3];
1710 int pw0, ph0, strides[3], retval=-1;
1711
1712 if(srcBuf==NULL || pad<0 || !isPow2(pad) || subsamp<0 || subsamp>=NUMSUBOPT
1713 || width<=0 || height<=0)
1714 _throw("tjDecodeYUV(): Invalid argument");
1715
1716 pw0=tjPlaneWidth(0, width, subsamp);
1717 ph0=tjPlaneHeight(0, height, subsamp);
1718 srcPlanes[0]=srcBuf;
1719 strides[0]=PAD(pw0, pad);
1720 if(subsamp==TJSAMP_GRAY)
1721 {
1722 strides[1]=strides[2]=0;
1723 srcPlanes[1]=srcPlanes[2]=NULL;
1724 }
1725 else
1726 {
1727 int pw1=tjPlaneWidth(1, width, subsamp);
1728 int ph1=tjPlaneHeight(1, height, subsamp);
1729 strides[1]=strides[2]=PAD(pw1, pad);
1730 srcPlanes[1]=srcPlanes[0]+strides[0]*ph0;
1731 srcPlanes[2]=srcPlanes[1]+strides[1]*ph1;
1732 }
1733
1734 return tjDecodeYUVPlanes(handle, srcPlanes, strides, subsamp, dstBuf, width,
1735 pitch, height, pixelFormat, flags);
1736
1737 bailout:
1738 return retval;
1739 }
1740
tjDecompressToYUVPlanes(tjhandle handle,const unsigned char * jpegBuf,unsigned long jpegSize,unsigned char ** dstPlanes,int width,int * strides,int height,int flags)1741 DLLEXPORT int DLLCALL tjDecompressToYUVPlanes(tjhandle handle,
1742 const unsigned char *jpegBuf, unsigned long jpegSize,
1743 unsigned char **dstPlanes, int width, int *strides, int height, int flags)
1744 {
1745 int i, sfi, row, retval=0; JSAMPROW *outbuf[MAX_COMPONENTS];
1746 int jpegwidth, jpegheight, jpegSubsamp, scaledw, scaledh;
1747 int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS],
1748 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
1749 JSAMPLE *_tmpbuf=NULL, *ptr; JSAMPROW *tmpbuf[MAX_COMPONENTS];
1750 int dctsize;
1751
1752 getdinstance(handle);
1753
1754 for(i=0; i<MAX_COMPONENTS; i++)
1755 {
1756 tmpbuf[i]=NULL; outbuf[i]=NULL;
1757 }
1758
1759 if((this->init&DECOMPRESS)==0)
1760 _throw("tjDecompressToYUVPlanes(): Instance has not been initialized for decompression");
1761
1762 if(jpegBuf==NULL || jpegSize<=0 || !dstPlanes || !dstPlanes[0] || width<0
1763 || height<0)
1764 _throw("tjDecompressToYUVPlanes(): Invalid argument");
1765
1766 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1767 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1768 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
1769
1770 if(setjmp(this->jerr.setjmp_buffer))
1771 {
1772 /* If we get here, the JPEG code has signaled an error. */
1773 retval=-1;
1774 goto bailout;
1775 }
1776
1777 if(!this->headerRead)
1778 {
1779 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1780 jpeg_read_header(dinfo, TRUE);
1781 }
1782 this->headerRead=0;
1783 jpegSubsamp=getSubsamp(dinfo);
1784 if(jpegSubsamp<0)
1785 _throw("tjDecompressToYUVPlanes(): Could not determine subsampling type for JPEG image");
1786
1787 if(jpegSubsamp!=TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2]))
1788 _throw("tjDecompressToYUVPlanes(): Invalid argument");
1789
1790 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
1791 if(width==0) width=jpegwidth;
1792 if(height==0) height=jpegheight;
1793 for(i=0; i<NUMSF; i++)
1794 {
1795 scaledw=TJSCALED(jpegwidth, sf[i]);
1796 scaledh=TJSCALED(jpegheight, sf[i]);
1797 if(scaledw<=width && scaledh<=height)
1798 break;
1799 }
1800 if(i>=NUMSF)
1801 _throw("tjDecompressToYUVPlanes(): Could not scale down to desired image dimensions");
1802 if(dinfo->num_components>3)
1803 _throw("tjDecompressToYUVPlanes(): JPEG image must have 3 or fewer components");
1804
1805 width=scaledw; height=scaledh;
1806 dinfo->scale_num=sf[i].num;
1807 dinfo->scale_denom=sf[i].denom;
1808 sfi=i;
1809 jpeg_calc_output_dimensions(dinfo);
1810
1811 dctsize=DCTSIZE*sf[sfi].num/sf[sfi].denom;
1812
1813 for(i=0; i<dinfo->num_components; i++)
1814 {
1815 jpeg_component_info *compptr=&dinfo->comp_info[i];
1816 int ih;
1817 iw[i]=compptr->width_in_blocks*dctsize;
1818 ih=compptr->height_in_blocks*dctsize;
1819 pw[i]=PAD(dinfo->output_width, dinfo->max_h_samp_factor)
1820 *compptr->h_samp_factor/dinfo->max_h_samp_factor;
1821 ph[i]=PAD(dinfo->output_height, dinfo->max_v_samp_factor)
1822 *compptr->v_samp_factor/dinfo->max_v_samp_factor;
1823 if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1;
1824 th[i]=compptr->v_samp_factor*dctsize;
1825 tmpbufsize+=iw[i]*th[i];
1826 if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]))==NULL)
1827 _throw("tjDecompressToYUVPlanes(): Memory allocation failure");
1828 ptr=dstPlanes[i];
1829 for(row=0; row<ph[i]; row++)
1830 {
1831 outbuf[i][row]=ptr;
1832 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
1833 }
1834 }
1835 if(usetmpbuf)
1836 {
1837 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
1838 _throw("tjDecompressToYUVPlanes(): Memory allocation failure");
1839 ptr=_tmpbuf;
1840 for(i=0; i<dinfo->num_components; i++)
1841 {
1842 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
1843 _throw("tjDecompressToYUVPlanes(): Memory allocation failure");
1844 for(row=0; row<th[i]; row++)
1845 {
1846 tmpbuf[i][row]=ptr;
1847 ptr+=iw[i];
1848 }
1849 }
1850 }
1851
1852 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
1853 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
1854 dinfo->raw_data_out=TRUE;
1855
1856 jpeg_start_decompress(dinfo);
1857 for(row=0; row<(int)dinfo->output_height;
1858 row+=dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size)
1859 {
1860 JSAMPARRAY yuvptr[MAX_COMPONENTS];
1861 int crow[MAX_COMPONENTS];
1862 for(i=0; i<dinfo->num_components; i++)
1863 {
1864 jpeg_component_info *compptr=&dinfo->comp_info[i];
1865 if(jpegSubsamp==TJ_420)
1866 {
1867 /* When 4:2:0 subsampling is used with IDCT scaling, libjpeg will try
1868 to be clever and use the IDCT to perform upsampling on the U and V
1869 planes. For instance, if the output image is to be scaled by 1/2
1870 relative to the JPEG image, then the scaling factor and upsampling
1871 effectively cancel each other, so a normal 8x8 IDCT can be used.
1872 However, this is not desirable when using the decompress-to-YUV
1873 functionality in TurboJPEG, since we want to output the U and V
1874 planes in their subsampled form. Thus, we have to override some
1875 internal libjpeg parameters to force it to use the "scaled" IDCT
1876 functions on the U and V planes. */
1877 compptr->_DCT_scaled_size=dctsize;
1878 compptr->MCU_sample_width=tjMCUWidth[jpegSubsamp]*
1879 sf[sfi].num/sf[sfi].denom*
1880 compptr->v_samp_factor/dinfo->max_v_samp_factor;
1881 dinfo->idct->inverse_DCT[i] = dinfo->idct->inverse_DCT[0];
1882 }
1883 crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
1884 if(usetmpbuf) yuvptr[i]=tmpbuf[i];
1885 else yuvptr[i]=&outbuf[i][crow[i]];
1886 }
1887 jpeg_read_raw_data(dinfo, yuvptr,
1888 dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size);
1889 if(usetmpbuf)
1890 {
1891 int j;
1892 for(i=0; i<dinfo->num_components; i++)
1893 {
1894 for(j=0; j<min(th[i], ph[i]-crow[i]); j++)
1895 {
1896 memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], pw[i]);
1897 }
1898 }
1899 }
1900 }
1901 jpeg_finish_decompress(dinfo);
1902
1903 bailout:
1904 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
1905 for(i=0; i<MAX_COMPONENTS; i++)
1906 {
1907 if(tmpbuf[i]) free(tmpbuf[i]);
1908 if(outbuf[i]) free(outbuf[i]);
1909 }
1910 if(_tmpbuf) free(_tmpbuf);
1911 if(this->jerr.warning) retval=-1;
1912 return retval;
1913 }
1914
tjDecompressToYUV2(tjhandle handle,const unsigned char * jpegBuf,unsigned long jpegSize,unsigned char * dstBuf,int width,int pad,int height,int flags)1915 DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle,
1916 const unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
1917 int width, int pad, int height, int flags)
1918 {
1919 unsigned char *dstPlanes[3];
1920 int pw0, ph0, strides[3], retval=-1, jpegSubsamp=-1;
1921 int i, jpegwidth, jpegheight, scaledw, scaledh;
1922
1923 getdinstance(handle);
1924
1925 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pad<1
1926 || !isPow2(pad) || height<0)
1927 _throw("tjDecompressToYUV2(): Invalid argument");
1928
1929 if(setjmp(this->jerr.setjmp_buffer))
1930 {
1931 /* If we get here, the JPEG code has signaled an error. */
1932 return -1;
1933 }
1934
1935 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1936 jpeg_read_header(dinfo, TRUE);
1937 jpegSubsamp=getSubsamp(dinfo);
1938 if(jpegSubsamp<0)
1939 _throw("tjDecompressToYUV2(): Could not determine subsampling type for JPEG image");
1940
1941 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
1942 if(width==0) width=jpegwidth;
1943 if(height==0) height=jpegheight;
1944
1945 for(i=0; i<NUMSF; i++)
1946 {
1947 scaledw=TJSCALED(jpegwidth, sf[i]);
1948 scaledh=TJSCALED(jpegheight, sf[i]);
1949 if(scaledw<=width && scaledh<=height)
1950 break;
1951 }
1952 if(i>=NUMSF)
1953 _throw("tjDecompressToYUV2(): Could not scale down to desired image dimensions");
1954
1955 pw0=tjPlaneWidth(0, width, jpegSubsamp);
1956 ph0=tjPlaneHeight(0, height, jpegSubsamp);
1957 dstPlanes[0]=dstBuf;
1958 strides[0]=PAD(pw0, pad);
1959 if(jpegSubsamp==TJSAMP_GRAY)
1960 {
1961 strides[1]=strides[2]=0;
1962 dstPlanes[1]=dstPlanes[2]=NULL;
1963 }
1964 else
1965 {
1966 int pw1=tjPlaneWidth(1, width, jpegSubsamp);
1967 int ph1=tjPlaneHeight(1, height, jpegSubsamp);
1968 strides[1]=strides[2]=PAD(pw1, pad);
1969 dstPlanes[1]=dstPlanes[0]+strides[0]*ph0;
1970 dstPlanes[2]=dstPlanes[1]+strides[1]*ph1;
1971 }
1972
1973 this->headerRead=1;
1974 return tjDecompressToYUVPlanes(handle, jpegBuf, jpegSize, dstPlanes, width,
1975 strides, height, flags);
1976
1977 bailout:
1978 return retval;
1979
1980 }
1981
tjDecompressToYUV(tjhandle handle,unsigned char * jpegBuf,unsigned long jpegSize,unsigned char * dstBuf,int flags)1982 DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle,
1983 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
1984 int flags)
1985 {
1986 return tjDecompressToYUV2(handle, jpegBuf, jpegSize, dstBuf, 0, 4, 0, flags);
1987 }
1988
1989
1990 /* Transformer */
1991
tjInitTransform(void)1992 DLLEXPORT tjhandle DLLCALL tjInitTransform(void)
1993 {
1994 tjinstance *this=NULL; tjhandle handle=NULL;
1995 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
1996 {
1997 snprintf(errStr, JMSG_LENGTH_MAX,
1998 "tjInitTransform(): Memory allocation failure");
1999 return NULL;
2000 }
2001 MEMZERO(this, sizeof(tjinstance));
2002 handle=_tjInitCompress(this);
2003 if(!handle) return NULL;
2004 handle=_tjInitDecompress(this);
2005 return handle;
2006 }
2007
2008
tjTransform(tjhandle handle,const unsigned char * jpegBuf,unsigned long jpegSize,int n,unsigned char ** dstBufs,unsigned long * dstSizes,tjtransform * t,int flags)2009 DLLEXPORT int DLLCALL tjTransform(tjhandle handle,
2010 const unsigned char *jpegBuf, unsigned long jpegSize, int n,
2011 unsigned char **dstBufs, unsigned long *dstSizes, tjtransform *t, int flags)
2012 {
2013 jpeg_transform_info *xinfo=NULL;
2014 jvirt_barray_ptr *srccoefs, *dstcoefs;
2015 int retval=0, i, jpegSubsamp;
2016
2017 getinstance(handle);
2018 if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0)
2019 _throw("tjTransform(): Instance has not been initialized for transformation");
2020
2021 if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL
2022 || t==NULL || flags<0)
2023 _throw("tjTransform(): Invalid argument");
2024
2025 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
2026 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
2027 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
2028
2029 if(setjmp(this->jerr.setjmp_buffer))
2030 {
2031 /* If we get here, the JPEG code has signaled an error. */
2032 retval=-1;
2033 goto bailout;
2034 }
2035
2036 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
2037
2038 if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n))
2039 ==NULL)
2040 _throw("tjTransform(): Memory allocation failure");
2041 MEMZERO(xinfo, sizeof(jpeg_transform_info)*n);
2042
2043 for(i=0; i<n; i++)
2044 {
2045 xinfo[i].transform=xformtypes[t[i].op];
2046 xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0;
2047 xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0;
2048 xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0;
2049 xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0;
2050 if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1;
2051 else xinfo[i].slow_hflip=0;
2052
2053 if(xinfo[i].crop)
2054 {
2055 xinfo[i].crop_xoffset=t[i].r.x; xinfo[i].crop_xoffset_set=JCROP_POS;
2056 xinfo[i].crop_yoffset=t[i].r.y; xinfo[i].crop_yoffset_set=JCROP_POS;
2057 if(t[i].r.w!=0)
2058 {
2059 xinfo[i].crop_width=t[i].r.w; xinfo[i].crop_width_set=JCROP_POS;
2060 }
2061 else xinfo[i].crop_width=JCROP_UNSET;
2062 if(t[i].r.h!=0)
2063 {
2064 xinfo[i].crop_height=t[i].r.h; xinfo[i].crop_height_set=JCROP_POS;
2065 }
2066 else xinfo[i].crop_height=JCROP_UNSET;
2067 }
2068 }
2069
2070 jcopy_markers_setup(dinfo, JCOPYOPT_ALL);
2071 jpeg_read_header(dinfo, TRUE);
2072 jpegSubsamp=getSubsamp(dinfo);
2073 if(jpegSubsamp<0)
2074 _throw("tjTransform(): Could not determine subsampling type for JPEG image");
2075
2076 for(i=0; i<n; i++)
2077 {
2078 if(!jtransform_request_workspace(dinfo, &xinfo[i]))
2079 _throw("tjTransform(): Transform is not perfect");
2080
2081 if(xinfo[i].crop)
2082 {
2083 if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0
2084 || (t[i].r.y%xinfo[i].iMCU_sample_height)!=0)
2085 {
2086 snprintf(errStr, JMSG_LENGTH_MAX,
2087 "To crop this JPEG image, x must be a multiple of %d\n"
2088 "and y must be a multiple of %d.\n",
2089 xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height);
2090 retval=-1; goto bailout;
2091 }
2092 }
2093 }
2094
2095 srccoefs=jpeg_read_coefficients(dinfo);
2096
2097 for(i=0; i<n; i++)
2098 {
2099 int w, h, alloc=1;
2100 if(!xinfo[i].crop)
2101 {
2102 w=dinfo->image_width; h=dinfo->image_height;
2103 }
2104 else
2105 {
2106 w=xinfo[i].crop_width; h=xinfo[i].crop_height;
2107 }
2108 if(flags&TJFLAG_NOREALLOC)
2109 {
2110 alloc=0; dstSizes[i]=tjBufSize(w, h, jpegSubsamp);
2111 }
2112 if(!(t[i].options&TJXOPT_NOOUTPUT))
2113 jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc);
2114 jpeg_copy_critical_parameters(dinfo, cinfo);
2115 dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs,
2116 &xinfo[i]);
2117 if(!(t[i].options&TJXOPT_NOOUTPUT))
2118 {
2119 jpeg_write_coefficients(cinfo, dstcoefs);
2120 jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL);
2121 }
2122 else jinit_c_master_control(cinfo, TRUE);
2123 jtransform_execute_transformation(dinfo, cinfo, srccoefs,
2124 &xinfo[i]);
2125 if(t[i].customFilter)
2126 {
2127 int ci, y; JDIMENSION by;
2128 for(ci=0; ci<cinfo->num_components; ci++)
2129 {
2130 jpeg_component_info *compptr=&cinfo->comp_info[ci];
2131 tjregion arrayRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
2132 DCTSIZE};
2133 tjregion planeRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
2134 compptr->height_in_blocks*DCTSIZE};
2135 for(by=0; by<compptr->height_in_blocks; by+=compptr->v_samp_factor)
2136 {
2137 JBLOCKARRAY barray=(dinfo->mem->access_virt_barray)
2138 ((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor,
2139 TRUE);
2140 for(y=0; y<compptr->v_samp_factor; y++)
2141 {
2142 if(t[i].customFilter(barray[y][0], arrayRegion, planeRegion,
2143 ci, i, &t[i])==-1)
2144 _throw("tjTransform(): Error in custom filter");
2145 arrayRegion.y+=DCTSIZE;
2146 }
2147 }
2148 }
2149 }
2150 if(!(t[i].options&TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo);
2151 }
2152
2153 jpeg_finish_decompress(dinfo);
2154
2155 bailout:
2156 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
2157 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
2158 if(xinfo) free(xinfo);
2159 if(this->jerr.warning) retval=-1;
2160 return retval;
2161 }
2162