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