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