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
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 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
TJBUFSIZE(int width,int height)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
tjBufSizeYUV2(int width,int pad,int height,int subsamp)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
tjBufSizeYUV(int width,int height,int subsamp)679 DLLEXPORT unsigned long DLLCALL tjBufSizeYUV(int width, int height,
680 int subsamp)
681 {
682 return tjBufSizeYUV2(width, 4, height, subsamp);
683 }
684
TJBUFSIZEYUV(int width,int height,int subsamp)685 DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
686 int subsamp)
687 {
688 return tjBufSizeYUV(width, height, subsamp);
689 }
690
691
tjPlaneWidth(int componentID,int width,int subsamp)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
tjPlaneHeight(int componentID,int height,int subsamp)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
tjPlaneSizeYUV(int componentID,int width,int stride,int height,int subsamp)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
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)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
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)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
tjEncodeYUVPlanes(tjhandle handle,const unsigned char * srcBuf,int width,int pitch,int height,int pixelFormat,unsigned char ** dstPlanes,int * strides,int subsamp,int flags)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
tjEncodeYUV3(tjhandle handle,const unsigned char * srcBuf,int width,int pitch,int height,int pixelFormat,unsigned char * dstBuf,int pad,int subsamp,int flags)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
tjEncodeYUV2(tjhandle handle,unsigned char * srcBuf,int width,int pitch,int height,int pixelFormat,unsigned char * dstBuf,int subsamp,int flags)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
tjEncodeYUV(tjhandle handle,unsigned char * srcBuf,int width,int pitch,int height,int pixelSize,unsigned char * dstBuf,int subsamp,int flags)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
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)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
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)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
_tjInitDecompress(tjinstance * this)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
tjInitDecompress(void)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
tjDecompressHeader3(tjhandle handle,const unsigned char * jpegBuf,unsigned long jpegSize,int * width,int * height,int * jpegSubsamp,int * jpegColorspace)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
tjDecompressHeader2(tjhandle handle,unsigned char * jpegBuf,unsigned long jpegSize,int * width,int * height,int * jpegSubsamp)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
tjDecompressHeader(tjhandle handle,unsigned char * jpegBuf,unsigned long jpegSize,int * width,int * height)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
tjGetScalingFactors(int * numscalingfactors)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
tjDecompress2(tjhandle handle,const unsigned char * jpegBuf,unsigned long jpegSize,unsigned char * dstBuf,int width,int pitch,int height,int pixelFormat,int flags)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
tjDecompress(tjhandle handle,unsigned char * jpegBuf,unsigned long jpegSize,unsigned char * dstBuf,int width,int pitch,int height,int pixelSize,int flags)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
setDecodeDefaults(struct jpeg_decompress_struct * dinfo,int pixelFormat,int subsamp,int flags)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
my_read_markers(j_decompress_ptr dinfo)1538 int my_read_markers(j_decompress_ptr dinfo)
1539 {
1540 return JPEG_REACHED_SOS;
1541 }
1542
my_reset_marker_reader(j_decompress_ptr dinfo)1543 void my_reset_marker_reader(j_decompress_ptr dinfo)
1544 {
1545 }
1546
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)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
tjDecodeYUV(tjhandle handle,const unsigned char * srcBuf,int pad,int subsamp,unsigned char * dstBuf,int width,int pitch,int height,int pixelFormat,int flags)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
tjDecompressToYUVPlanes(tjhandle handle,const unsigned char * jpegBuf,unsigned long jpegSize,unsigned char ** dstPlanes,int width,int * strides,int height,int flags)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
tjDecompressToYUV2(tjhandle handle,const unsigned char * jpegBuf,unsigned long jpegSize,unsigned char * dstBuf,int width,int pad,int height,int flags)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
tjDecompressToYUV(tjhandle handle,unsigned char * jpegBuf,unsigned long jpegSize,unsigned char * dstBuf,int flags)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
tjInitTransform(void)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
tjTransform(tjhandle handle,const unsigned char * jpegBuf,unsigned long jpegSize,int n,unsigned char ** dstBufs,unsigned long * dstSizes,tjtransform * t,int flags)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 }
2176