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