blob: e27f0da078a7b32321de766702ab83171eb634cd [file] [log] [blame]
hbono@chromium.org98626972011-08-03 03:13:08 +00001/*
2 * Copyright (C)2009-2011 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/OSS: this implements the TurboJPEG API using libjpeg-turbo */
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <jinclude.h>
34#define JPEG_INTERNALS
35#include <jpeglib.h>
36#include <jerror.h>
37#include <setjmp.h>
38#include "./turbojpeg.h"
39#include "./tjutil.h"
40#include "transupp.h"
41
42extern void jpeg_mem_dest_tj(j_compress_ptr, unsigned char **,
43 unsigned long *, boolean);
44extern void jpeg_mem_src_tj(j_decompress_ptr, unsigned char *, unsigned long);
45
46#define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
47
48
49/* Error handling (based on example in example.c) */
50
51static char errStr[JMSG_LENGTH_MAX]="No error";
52
53struct my_error_mgr
54{
55 struct jpeg_error_mgr pub;
56 jmp_buf setjmp_buffer;
57};
58typedef struct my_error_mgr *my_error_ptr;
59
60static void my_error_exit(j_common_ptr cinfo)
61{
62 my_error_ptr myerr=(my_error_ptr)cinfo->err;
63 (*cinfo->err->output_message)(cinfo);
64 longjmp(myerr->setjmp_buffer, 1);
65}
66
67/* Based on output_message() in jerror.c */
68
69static void my_output_message(j_common_ptr cinfo)
70{
71 (*cinfo->err->format_message)(cinfo, errStr);
72}
73
74
75/* Global structures, macros, etc. */
76
77enum {COMPRESS=1, DECOMPRESS=2};
78
79typedef struct _tjinstance
80{
81 struct jpeg_compress_struct cinfo;
82 struct jpeg_decompress_struct dinfo;
83 struct my_error_mgr jerr;
84 int init;
85} tjinstance;
86
87static const int pixelsize[TJ_NUMSAMP]={3, 3, 3, 1, 3};
88
89static const JXFORM_CODE xformtypes[TJ_NUMXOP]=
90{
91 JXFORM_NONE, JXFORM_FLIP_H, JXFORM_FLIP_V, JXFORM_TRANSPOSE,
92 JXFORM_TRANSVERSE, JXFORM_ROT_90, JXFORM_ROT_180, JXFORM_ROT_270
93};
94
95#define NUMSF 4
96static const tjscalingfactor sf[NUMSF]={
97 {1, 1},
98 {1, 2},
99 {1, 4},
100 {1, 8}
101};
102
103#define _throw(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s", m); \
104 retval=-1; goto bailout;}
105#define getinstance(handle) tjinstance *this=(tjinstance *)handle; \
106 j_compress_ptr cinfo=NULL; j_decompress_ptr dinfo=NULL; \
107 if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
108 return -1;} \
109 cinfo=&this->cinfo; dinfo=&this->dinfo;
110
111static int getPixelFormat(int pixelSize, int flags)
112{
113 if(pixelSize==1) return TJPF_GRAY;
114 if(pixelSize==3)
115 {
116 if(flags&TJ_BGR) return TJPF_BGR;
117 else return TJPF_RGB;
118 }
119 if(pixelSize==4)
120 {
121 if(flags&TJ_ALPHAFIRST)
122 {
123 if(flags&TJ_BGR) return TJPF_XBGR;
124 else return TJPF_XRGB;
125 }
126 else
127 {
128 if(flags&TJ_BGR) return TJPF_BGRX;
129 else return TJPF_RGBX;
130 }
131 }
132 return -1;
133}
134
hbono@chromium.orgc6beb742011-11-29 05:16:26 +0000135static int setCompDefaults(struct jpeg_compress_struct *cinfo,
hbono@chromium.org98626972011-08-03 03:13:08 +0000136 int pixelFormat, int subsamp, int jpegQual)
137{
hbono@chromium.orgc6beb742011-11-29 05:16:26 +0000138 int retval=0;
139
hbono@chromium.org98626972011-08-03 03:13:08 +0000140 switch(pixelFormat)
141 {
142 case TJPF_GRAY:
143 cinfo->in_color_space=JCS_GRAYSCALE; break;
144 #if JCS_EXTENSIONS==1
145 case TJPF_RGB:
146 cinfo->in_color_space=JCS_EXT_RGB; break;
147 case TJPF_BGR:
148 cinfo->in_color_space=JCS_EXT_BGR; break;
149 case TJPF_RGBX:
hbono@chromium.org0ec930e2012-01-18 07:01:04 +0000150 case TJPF_RGBA:
hbono@chromium.org98626972011-08-03 03:13:08 +0000151 cinfo->in_color_space=JCS_EXT_RGBX; break;
152 case TJPF_BGRX:
hbono@chromium.org0ec930e2012-01-18 07:01:04 +0000153 case TJPF_BGRA:
hbono@chromium.org98626972011-08-03 03:13:08 +0000154 cinfo->in_color_space=JCS_EXT_BGRX; break;
155 case TJPF_XRGB:
hbono@chromium.org0ec930e2012-01-18 07:01:04 +0000156 case TJPF_ARGB:
hbono@chromium.org98626972011-08-03 03:13:08 +0000157 cinfo->in_color_space=JCS_EXT_XRGB; break;
158 case TJPF_XBGR:
hbono@chromium.org0ec930e2012-01-18 07:01:04 +0000159 case TJPF_ABGR:
hbono@chromium.org98626972011-08-03 03:13:08 +0000160 cinfo->in_color_space=JCS_EXT_XBGR; break;
161 #else
162 case TJPF_RGB:
163 if(RGB_RED==0 && RGB_GREEN==1 && RGB_BLUE==2 && RGB_PIXELSIZE==3)
164 {
165 cinfo->in_color_space=JCS_RGB; break;
166 }
167 default:
168 _throw("Unsupported pixel format");
169 #endif
170 }
171
172 cinfo->input_components=tjPixelSize[pixelFormat];
173 jpeg_set_defaults(cinfo);
174 if(jpegQual>=0)
175 {
176 jpeg_set_quality(cinfo, jpegQual, TRUE);
177 if(jpegQual>=96) cinfo->dct_method=JDCT_ISLOW;
178 else cinfo->dct_method=JDCT_FASTEST;
179 }
180 if(subsamp==TJSAMP_GRAY)
181 jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
182 else
183 jpeg_set_colorspace(cinfo, JCS_YCbCr);
184
185 cinfo->comp_info[0].h_samp_factor=tjMCUWidth[subsamp]/8;
186 cinfo->comp_info[1].h_samp_factor=1;
187 cinfo->comp_info[2].h_samp_factor=1;
188 cinfo->comp_info[0].v_samp_factor=tjMCUHeight[subsamp]/8;
189 cinfo->comp_info[1].v_samp_factor=1;
190 cinfo->comp_info[2].v_samp_factor=1;
hbono@chromium.orgc6beb742011-11-29 05:16:26 +0000191
192 #if JCS_EXTENSIONS!=1
193 bailout:
194 #endif
195 return retval;
hbono@chromium.org98626972011-08-03 03:13:08 +0000196}
197
hbono@chromium.orgc6beb742011-11-29 05:16:26 +0000198static int setDecompDefaults(struct jpeg_decompress_struct *dinfo,
hbono@chromium.org98626972011-08-03 03:13:08 +0000199 int pixelFormat)
200{
hbono@chromium.orgc6beb742011-11-29 05:16:26 +0000201 int retval=0;
202
hbono@chromium.org98626972011-08-03 03:13:08 +0000203 switch(pixelFormat)
204 {
205 case TJPF_GRAY:
206 dinfo->out_color_space=JCS_GRAYSCALE; break;
207 #if JCS_EXTENSIONS==1
208 case TJPF_RGB:
209 dinfo->out_color_space=JCS_EXT_RGB; break;
210 case TJPF_BGR:
211 dinfo->out_color_space=JCS_EXT_BGR; break;
212 case TJPF_RGBX:
213 dinfo->out_color_space=JCS_EXT_RGBX; break;
214 case TJPF_BGRX:
215 dinfo->out_color_space=JCS_EXT_BGRX; break;
216 case TJPF_XRGB:
217 dinfo->out_color_space=JCS_EXT_XRGB; break;
218 case TJPF_XBGR:
219 dinfo->out_color_space=JCS_EXT_XBGR; break;
hbono@chromium.org0ec930e2012-01-18 07:01:04 +0000220 #if JCS_ALPHA_EXTENSIONS==1
221 case TJPF_RGBA:
222 dinfo->out_color_space=JCS_EXT_RGBA; break;
223 case TJPF_BGRA:
224 dinfo->out_color_space=JCS_EXT_BGRA; break;
225 case TJPF_ARGB:
226 dinfo->out_color_space=JCS_EXT_ARGB; break;
227 case TJPF_ABGR:
228 dinfo->out_color_space=JCS_EXT_ABGR; break;
229 #endif
hbono@chromium.org98626972011-08-03 03:13:08 +0000230 #else
231 case TJPF_RGB:
232 if(RGB_RED==0 && RGB_GREEN==1 && RGB_BLUE==2 && RGB_PIXELSIZE==3)
233 {
234 dinfo->out_color_space=JCS_RGB; break;
235 }
hbono@chromium.org0ec930e2012-01-18 07:01:04 +0000236 #endif
hbono@chromium.org98626972011-08-03 03:13:08 +0000237 default:
238 _throw("Unsupported pixel format");
hbono@chromium.org98626972011-08-03 03:13:08 +0000239 }
hbono@chromium.orgc6beb742011-11-29 05:16:26 +0000240
hbono@chromium.orgc6beb742011-11-29 05:16:26 +0000241 bailout:
hbono@chromium.orgc6beb742011-11-29 05:16:26 +0000242 return retval;
hbono@chromium.org98626972011-08-03 03:13:08 +0000243}
244
245
246static int getSubsamp(j_decompress_ptr dinfo)
247{
248 int retval=-1, i, k;
249 for(i=0; i<NUMSUBOPT; i++)
250 {
251 if(dinfo->num_components==pixelsize[i])
252 {
253 if(dinfo->comp_info[0].h_samp_factor==tjMCUWidth[i]/8
254 && dinfo->comp_info[0].v_samp_factor==tjMCUHeight[i]/8)
255 {
256 int match=0;
257 for(k=1; k<dinfo->num_components; k++)
258 {
259 if(dinfo->comp_info[k].h_samp_factor==1
260 && dinfo->comp_info[k].v_samp_factor==1)
261 match++;
262 }
263 if(match==dinfo->num_components-1)
264 {
265 retval=i; break;
266 }
267 }
268 }
269 }
270 return retval;
271}
272
273
274/* General API functions */
275
276DLLEXPORT char* DLLCALL tjGetErrorStr(void)
277{
278 return errStr;
279}
280
281
282DLLEXPORT int DLLCALL tjDestroy(tjhandle handle)
283{
284 getinstance(handle);
285 if(setjmp(this->jerr.setjmp_buffer)) return -1;
286 if(this->init&COMPRESS) jpeg_destroy_compress(cinfo);
287 if(this->init&DECOMPRESS) jpeg_destroy_decompress(dinfo);
288 free(this);
289 return 0;
290}
291
292
293/* These are exposed mainly because Windows can't malloc() and free() across
294 DLL boundaries except when the CRT DLL is used, and we don't use the CRT DLL
295 with turbojpeg.dll for compatibility reasons. However, these functions
296 can potentially be used for other purposes by different implementations. */
297
298DLLEXPORT void DLLCALL tjFree(unsigned char *buf)
299{
300 if(buf) free(buf);
301}
302
303
304DLLEXPORT unsigned char *DLLCALL tjAlloc(int bytes)
305{
306 return (unsigned char *)malloc(bytes);
307}
308
309
310/* Compressor */
311
312static tjhandle _tjInitCompress(tjinstance *this)
313{
314 unsigned char buffer[1], *buf=buffer; unsigned long size=1;
315
316 /* This is also straight out of example.c */
317 this->cinfo.err=jpeg_std_error(&this->jerr.pub);
318 this->jerr.pub.error_exit=my_error_exit;
319 this->jerr.pub.output_message=my_output_message;
320
321 if(setjmp(this->jerr.setjmp_buffer))
322 {
323 /* If we get here, the JPEG code has signaled an error. */
324 if(this) free(this); return NULL;
325 }
326
327 jpeg_create_compress(&this->cinfo);
328 /* Make an initial call so it will create the destination manager */
329 jpeg_mem_dest_tj(&this->cinfo, &buf, &size, 0);
330
331 this->init|=COMPRESS;
332 return (tjhandle)this;
333}
334
335DLLEXPORT tjhandle DLLCALL tjInitCompress(void)
336{
337 tjinstance *this=NULL;
338 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
339 {
340 snprintf(errStr, JMSG_LENGTH_MAX,
341 "tjInitCompress(): Memory allocation failure");
342 return NULL;
343 }
344 MEMZERO(this, sizeof(tjinstance));
345 return _tjInitCompress(this);
346}
347
348
349DLLEXPORT unsigned long DLLCALL tjBufSize(int width, int height,
350 int jpegSubsamp)
351{
352 unsigned long retval=0; int mcuw, mcuh, chromasf;
353 if(width<1 || height<1 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT)
354 _throw("tjBufSize(): Invalid argument");
355
356 // This allows for rare corner cases in which a JPEG image can actually be
357 // larger than the uncompressed input (we wouldn't mention it if it hadn't
358 // happened before.)
359 mcuw=tjMCUWidth[jpegSubsamp];
360 mcuh=tjMCUHeight[jpegSubsamp];
361 chromasf=jpegSubsamp==TJSAMP_GRAY? 0: 4*64/(mcuw*mcuh);
362 retval=PAD(width, mcuw) * PAD(height, mcuh) * (2 + chromasf) + 2048;
363
364 bailout:
365 return retval;
366}
367
368
369DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
370{
371 unsigned long retval=0;
372 if(width<1 || height<1)
373 _throw("TJBUFSIZE(): Invalid argument");
374
375 // This allows for rare corner cases in which a JPEG image can actually be
376 // larger than the uncompressed input (we wouldn't mention it if it hadn't
377 // happened before.)
378 retval=PAD(width, 16) * PAD(height, 16) * 6 + 2048;
379
380 bailout:
381 return retval;
382}
383
384
385DLLEXPORT unsigned long DLLCALL tjBufSizeYUV(int width, int height,
386 int subsamp)
387{
388 unsigned long retval=0;
389 int pw, ph, cw, ch;
390 if(width<1 || height<1 || subsamp<0 || subsamp>=NUMSUBOPT)
391 _throw("tjBufSizeYUV(): Invalid argument");
392 pw=PAD(width, tjMCUWidth[subsamp]/8);
393 ph=PAD(height, tjMCUHeight[subsamp]/8);
394 cw=pw*8/tjMCUWidth[subsamp]; ch=ph*8/tjMCUHeight[subsamp];
395 retval=PAD(pw, 4)*ph + (subsamp==TJSAMP_GRAY? 0:PAD(cw, 4)*ch*2);
396
397 bailout:
398 return retval;
399}
400
401
402DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
403 int subsamp)
404{
405 return tjBufSizeYUV(width, height, subsamp);
406}
407
408
409DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf,
410 int width, int pitch, int height, int pixelFormat, unsigned char **jpegBuf,
411 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
412{
413 int i, retval=0, alloc=1; JSAMPROW *row_pointer=NULL;
414
415 getinstance(handle)
416 if((this->init&COMPRESS)==0)
417 _throw("tjCompress2(): Instance has not been initialized for compression");
418
419 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
420 || pixelFormat>=TJ_NUMPF || jpegBuf==NULL || jpegSize==NULL
421 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT || jpegQual<0 || jpegQual>100)
422 _throw("tjCompress2(): Invalid argument");
423
424 if(setjmp(this->jerr.setjmp_buffer))
425 {
426 /* If we get here, the JPEG code has signaled an error. */
427 retval=-1;
428 goto bailout;
429 }
430
431 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
432
433 cinfo->image_width=width;
434 cinfo->image_height=height;
435
436 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
437 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
438 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
439
440 if(flags&TJFLAG_NOREALLOC)
441 {
442 alloc=0; *jpegSize=tjBufSize(width, height, jpegSubsamp);
443 }
444 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
hbono@chromium.orgc6beb742011-11-29 05:16:26 +0000445 if(setCompDefaults(cinfo, pixelFormat, jpegSubsamp, jpegQual)==-1)
446 return -1;
hbono@chromium.org98626972011-08-03 03:13:08 +0000447
448 jpeg_start_compress(cinfo, TRUE);
449 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
450 _throw("tjCompress2(): Memory allocation failure");
451 for(i=0; i<height; i++)
452 {
453 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
454 else row_pointer[i]=&srcBuf[i*pitch];
455 }
456 while(cinfo->next_scanline<cinfo->image_height)
457 {
458 jpeg_write_scanlines(cinfo, &row_pointer[cinfo->next_scanline],
459 cinfo->image_height-cinfo->next_scanline);
460 }
461 jpeg_finish_compress(cinfo);
462
463 bailout:
464 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
465 if(row_pointer) free(row_pointer);
466 return retval;
467}
468
469DLLEXPORT int DLLCALL tjCompress(tjhandle handle, unsigned char *srcBuf,
470 int width, int pitch, int height, int pixelSize, unsigned char *jpegBuf,
471 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
472{
473 int retval=0; unsigned long size;
474 if(flags&TJ_YUV)
475 {
476 size=tjBufSizeYUV(width, height, jpegSubsamp);
477 retval=tjEncodeYUV2(handle, srcBuf, width, pitch, height,
478 getPixelFormat(pixelSize, flags), jpegBuf, jpegSubsamp, flags);
479 }
480 else
481 {
482 retval=tjCompress2(handle, srcBuf, width, pitch, height,
483 getPixelFormat(pixelSize, flags), &jpegBuf, &size, jpegSubsamp, jpegQual,
484 flags|TJFLAG_NOREALLOC);
485 }
486 *jpegSize=size;
487 return retval;
488}
489
490
491DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
492 int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
493 int subsamp, int flags)
494{
495 int i, retval=0; JSAMPROW *row_pointer=NULL;
496 JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS];
497 JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
498 JSAMPROW *outbuf[MAX_COMPONENTS];
499 int row, pw, ph, cw[MAX_COMPONENTS], ch[MAX_COMPONENTS];
500 JSAMPLE *ptr=dstBuf;
501 unsigned long yuvsize=0;
502 jpeg_component_info *compptr;
503
504 getinstance(handle);
505 if((this->init&COMPRESS)==0)
506 _throw("tjEncodeYUV2(): Instance has not been initialized for compression");
507
508 for(i=0; i<MAX_COMPONENTS; i++)
509 {
510 tmpbuf[i]=NULL; _tmpbuf[i]=NULL;
511 tmpbuf2[i]=NULL; _tmpbuf2[i]=NULL; outbuf[i]=NULL;
512 }
513
514 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
515 || pixelFormat>=TJ_NUMPF || dstBuf==NULL || subsamp<0
516 || subsamp>=NUMSUBOPT)
517 _throw("tjEncodeYUV2(): Invalid argument");
518
519 if(setjmp(this->jerr.setjmp_buffer))
520 {
521 /* If we get here, the JPEG code has signaled an error. */
522 retval=-1;
523 goto bailout;
524 }
525
526 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
527
528 cinfo->image_width=width;
529 cinfo->image_height=height;
530
531 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
532 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
533 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
534
535 yuvsize=tjBufSizeYUV(width, height, subsamp);
536 jpeg_mem_dest_tj(cinfo, &dstBuf, &yuvsize, 0);
hbono@chromium.orgc6beb742011-11-29 05:16:26 +0000537 if(setCompDefaults(cinfo, pixelFormat, subsamp, -1)==-1) return -1;
hbono@chromium.org98626972011-08-03 03:13:08 +0000538
539 jpeg_start_compress(cinfo, TRUE);
540 pw=PAD(width, cinfo->max_h_samp_factor);
541 ph=PAD(height, cinfo->max_v_samp_factor);
542
543 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph))==NULL)
544 _throw("tjEncodeYUV2(): Memory allocation failure");
545 for(i=0; i<height; i++)
546 {
547 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
548 else row_pointer[i]=&srcBuf[i*pitch];
549 }
550 if(height<ph)
551 for(i=height; i<ph; i++) row_pointer[i]=row_pointer[height-1];
552
553 for(i=0; i<cinfo->num_components; i++)
554 {
555 compptr=&cinfo->comp_info[i];
556 _tmpbuf[i]=(JSAMPLE *)malloc(
557 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
558 /compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
559 if(!_tmpbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
560 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
561 if(!tmpbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
562 for(row=0; row<cinfo->max_v_samp_factor; row++)
563 {
564 unsigned char *_tmpbuf_aligned=
565 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
566 tmpbuf[i][row]=&_tmpbuf_aligned[
567 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
568 /compptr->h_samp_factor, 16) * row];
569 }
570 _tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
571 * compptr->v_samp_factor + 16);
572 if(!_tmpbuf2[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
573 tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
574 if(!tmpbuf2[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
575 for(row=0; row<compptr->v_samp_factor; row++)
576 {
577 unsigned char *_tmpbuf2_aligned=
578 (unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
579 tmpbuf2[i][row]=&_tmpbuf2_aligned[
580 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
581 }
582 cw[i]=pw*compptr->h_samp_factor/cinfo->max_h_samp_factor;
583 ch[i]=ph*compptr->v_samp_factor/cinfo->max_v_samp_factor;
584 outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]);
585 if(!outbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure");
586 for(row=0; row<ch[i]; row++)
587 {
588 outbuf[i][row]=ptr;
589 ptr+=PAD(cw[i], 4);
590 }
591 }
592 if(yuvsize!=(unsigned long)(ptr-dstBuf))
593 _throw("tjEncodeYUV2(): Generated image is not the correct size");
594
595 for(row=0; row<ph; row+=cinfo->max_v_samp_factor)
596 {
597 (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0,
598 cinfo->max_v_samp_factor);
599 (cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
600 for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++)
601 jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
602 row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
603 compptr->v_samp_factor, cw[i]);
604 }
605 cinfo->next_scanline+=height;
606 jpeg_abort_compress(cinfo);
607
608 bailout:
609 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
610 if(row_pointer) free(row_pointer);
611 for(i=0; i<MAX_COMPONENTS; i++)
612 {
613 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
614 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
615 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
616 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
617 if(outbuf[i]!=NULL) free(outbuf[i]);
618 }
619 return retval;
620}
621
622DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf,
623 int width, int pitch, int height, int pixelSize, unsigned char *dstBuf,
624 int subsamp, int flags)
625{
626 return tjEncodeYUV2(handle, srcBuf, width, pitch, height,
627 getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags);
628}
629
630
631/* Decompressor */
632
633static tjhandle _tjInitDecompress(tjinstance *this)
634{
635 unsigned char buffer[1];
636
637 /* This is also straight out of example.c */
638 this->dinfo.err=jpeg_std_error(&this->jerr.pub);
639 this->jerr.pub.error_exit=my_error_exit;
640 this->jerr.pub.output_message=my_output_message;
641
642 if(setjmp(this->jerr.setjmp_buffer))
643 {
644 /* If we get here, the JPEG code has signaled an error. */
645 if(this) free(this); return NULL;
646 }
647
648 jpeg_create_decompress(&this->dinfo);
649 /* Make an initial call so it will create the source manager */
650 jpeg_mem_src_tj(&this->dinfo, buffer, 1);
651
652 this->init|=DECOMPRESS;
653 return (tjhandle)this;
654}
655
656DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
657{
658 tjinstance *this;
659 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
660 {
661 snprintf(errStr, JMSG_LENGTH_MAX,
662 "tjInitDecompress(): Memory allocation failure");
663 return NULL;
664 }
665 MEMZERO(this, sizeof(tjinstance));
666 return _tjInitDecompress(this);
667}
668
669
670DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle,
671 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
672 int *jpegSubsamp)
673{
674 int retval=0;
675
676 getinstance(handle);
677 if((this->init&DECOMPRESS)==0)
678 _throw("tjDecompressHeader2(): Instance has not been initialized for decompression");
679
680 if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL
681 || jpegSubsamp==NULL)
682 _throw("tjDecompressHeader2(): Invalid argument");
683
684 if(setjmp(this->jerr.setjmp_buffer))
685 {
686 /* If we get here, the JPEG code has signaled an error. */
687 return -1;
688 }
689
690 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
691 jpeg_read_header(dinfo, TRUE);
692
693 *width=dinfo->image_width;
694 *height=dinfo->image_height;
695 *jpegSubsamp=getSubsamp(dinfo);
696
697 jpeg_abort_decompress(dinfo);
698
699 if(*jpegSubsamp<0)
700 _throw("tjDecompressHeader2(): Could not determine subsampling type for JPEG image");
701 if(*width<1 || *height<1)
702 _throw("tjDecompressHeader2(): Invalid data returned in header");
703
704 bailout:
705 return retval;
706}
707
708DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle,
709 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height)
710{
711 int jpegSubsamp;
712 return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height,
713 &jpegSubsamp);
714}
715
716
717DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors)
718{
719 if(numscalingfactors==NULL)
720 {
721 snprintf(errStr, JMSG_LENGTH_MAX,
722 "tjGetScalingFactors(): Invalid argument");
723 return NULL;
724 }
725
726 *numscalingfactors=NUMSF;
727 return (tjscalingfactor *)sf;
728}
729
730
731DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, unsigned char *jpegBuf,
732 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
733 int height, int pixelFormat, int flags)
734{
735 int i, retval=0; JSAMPROW *row_pointer=NULL;
736 int jpegwidth, jpegheight, scaledw, scaledh;
737
738 getinstance(handle);
739 if((this->init&DECOMPRESS)==0)
740 _throw("tjDecompress2(): Instance has not been initialized for decompression");
741
742 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0
743 || height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF)
744 _throw("tjDecompress2(): Invalid argument");
745
746 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
747 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
748 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
749
750 if(setjmp(this->jerr.setjmp_buffer))
751 {
752 /* If we get here, the JPEG code has signaled an error. */
753 retval=-1;
754 goto bailout;
755 }
756
757 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
758 jpeg_read_header(dinfo, TRUE);
hbono@chromium.orgc6beb742011-11-29 05:16:26 +0000759 if(setDecompDefaults(dinfo, pixelFormat)==-1) return -1;
hbono@chromium.org98626972011-08-03 03:13:08 +0000760
761 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
762
763 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
764 if(width==0) width=jpegwidth;
765 if(height==0) height=jpegheight;
766 for(i=0; i<NUMSF; i++)
767 {
768 scaledw=TJSCALED(jpegwidth, sf[i]);
769 scaledh=TJSCALED(jpegheight, sf[i]);
770 if(scaledw<=width && scaledh<=height)
771 break;
772 }
773 if(scaledw>width || scaledh>height)
774 _throw("tjDecompress2(): Could not scale down to desired image dimensions");
775 width=scaledw; height=scaledh;
776 dinfo->scale_num=sf[i].num;
777 dinfo->scale_denom=sf[i].denom;
778
779 jpeg_start_decompress(dinfo);
780 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
781 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
782 *dinfo->output_height))==NULL)
783 _throw("tjDecompress2(): Memory allocation failure");
784 for(i=0; i<(int)dinfo->output_height; i++)
785 {
786 if(flags&TJFLAG_BOTTOMUP)
787 row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*pitch];
788 else row_pointer[i]=&dstBuf[i*pitch];
789 }
790 while(dinfo->output_scanline<dinfo->output_height)
791 {
792 jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline],
793 dinfo->output_height-dinfo->output_scanline);
794 }
795 jpeg_finish_decompress(dinfo);
796
797 bailout:
798 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
799 if(row_pointer) free(row_pointer);
800 return retval;
801}
802
803DLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf,
804 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
805 int height, int pixelSize, int flags)
806{
807 if(flags&TJ_YUV)
808 return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags);
809 else
810 return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch,
811 height, getPixelFormat(pixelSize, flags), flags);
812}
813
814
815DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle,
816 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
817 int flags)
818{
819 int i, row, retval=0; JSAMPROW *outbuf[MAX_COMPONENTS];
820 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS],
821 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
822 JSAMPLE *_tmpbuf=NULL, *ptr=dstBuf; JSAMPROW *tmpbuf[MAX_COMPONENTS];
823
824 getinstance(handle);
825 if((this->init&DECOMPRESS)==0)
826 _throw("tjDecompressToYUV(): Instance has not been initialized for decompression");
827
828 for(i=0; i<MAX_COMPONENTS; i++)
829 {
830 tmpbuf[i]=NULL; outbuf[i]=NULL;
831 }
832
833 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL)
834 _throw("tjDecompressToYUV(): Invalid argument");
835
836 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
837 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
838 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
839
840 if(setjmp(this->jerr.setjmp_buffer))
841 {
842 /* If we get here, the JPEG code has signaled an error. */
843 retval=-1;
844 goto bailout;
845 }
846
847 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
848 jpeg_read_header(dinfo, TRUE);
849
850 for(i=0; i<dinfo->num_components; i++)
851 {
852 jpeg_component_info *compptr=&dinfo->comp_info[i];
853 int ih;
854 iw[i]=compptr->width_in_blocks*DCTSIZE;
855 ih=compptr->height_in_blocks*DCTSIZE;
856 cw[i]=PAD(dinfo->image_width, dinfo->max_h_samp_factor)
857 *compptr->h_samp_factor/dinfo->max_h_samp_factor;
858 ch[i]=PAD(dinfo->image_height, dinfo->max_v_samp_factor)
859 *compptr->v_samp_factor/dinfo->max_v_samp_factor;
860 if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1;
861 th[i]=compptr->v_samp_factor*DCTSIZE;
862 tmpbufsize+=iw[i]*th[i];
863 if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL)
864 _throw("tjDecompressToYUV(): Memory allocation failure");
865 for(row=0; row<ch[i]; row++)
866 {
867 outbuf[i][row]=ptr;
868 ptr+=PAD(cw[i], 4);
869 }
870 }
871 if(usetmpbuf)
872 {
873 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
874 _throw("tjDecompressToYUV(): Memory allocation failure");
875 ptr=_tmpbuf;
876 for(i=0; i<dinfo->num_components; i++)
877 {
878 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
879 _throw("tjDecompressToYUV(): Memory allocation failure");
880 for(row=0; row<th[i]; row++)
881 {
882 tmpbuf[i][row]=ptr;
883 ptr+=iw[i];
884 }
885 }
886 }
887
888 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
889 dinfo->raw_data_out=TRUE;
890
891 jpeg_start_decompress(dinfo);
892 for(row=0; row<(int)dinfo->output_height;
893 row+=dinfo->max_v_samp_factor*DCTSIZE)
894 {
895 JSAMPARRAY yuvptr[MAX_COMPONENTS];
896 int crow[MAX_COMPONENTS];
897 for(i=0; i<dinfo->num_components; i++)
898 {
899 jpeg_component_info *compptr=&dinfo->comp_info[i];
900 crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
901 if(usetmpbuf) yuvptr[i]=tmpbuf[i];
902 else yuvptr[i]=&outbuf[i][crow[i]];
903 }
904 jpeg_read_raw_data(dinfo, yuvptr, dinfo->max_v_samp_factor*DCTSIZE);
905 if(usetmpbuf)
906 {
907 int j;
908 for(i=0; i<dinfo->num_components; i++)
909 {
910 for(j=0; j<min(th[i], ch[i]-crow[i]); j++)
911 {
912 memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], cw[i]);
913 }
914 }
915 }
916 }
917 jpeg_finish_decompress(dinfo);
918
919 bailout:
920 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
921 for(i=0; i<MAX_COMPONENTS; i++)
922 {
923 if(tmpbuf[i]) free(tmpbuf[i]);
924 if(outbuf[i]) free(outbuf[i]);
925 }
926 if(_tmpbuf) free(_tmpbuf);
927 return retval;
928}
929
930
931/* Transformer */
932
933DLLEXPORT tjhandle DLLCALL tjInitTransform(void)
934{
935 tjinstance *this=NULL; tjhandle handle=NULL;
936 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
937 {
938 snprintf(errStr, JMSG_LENGTH_MAX,
939 "tjInitTransform(): Memory allocation failure");
940 return NULL;
941 }
942 MEMZERO(this, sizeof(tjinstance));
943 handle=_tjInitCompress(this);
944 if(!handle) return NULL;
945 handle=_tjInitDecompress(this);
946 return handle;
947}
948
949
950DLLEXPORT int DLLCALL tjTransform(tjhandle handle, unsigned char *jpegBuf,
951 unsigned long jpegSize, int n, unsigned char **dstBufs,
952 unsigned long *dstSizes, tjtransform *t, int flags)
953{
954 jpeg_transform_info *xinfo=NULL;
955 jvirt_barray_ptr *srccoefs, *dstcoefs;
956 int retval=0, i, jpegSubsamp;
957
958 getinstance(handle);
959 if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0)
960 _throw("tjTransform(): Instance has not been initialized for transformation");
961
962 if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL
963 || t==NULL || flags<0)
964 _throw("tjTransform(): Invalid argument");
965
966 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
967 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
968 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
969
970 if(setjmp(this->jerr.setjmp_buffer))
971 {
972 /* If we get here, the JPEG code has signaled an error. */
973 retval=-1;
974 goto bailout;
975 }
976
977 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
978
979 if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n))
980 ==NULL)
981 _throw("tjTransform(): Memory allocation failure");
982 MEMZERO(xinfo, sizeof(jpeg_transform_info)*n);
983
984 for(i=0; i<n; i++)
985 {
986 xinfo[i].transform=xformtypes[t[i].op];
987 xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0;
988 xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0;
989 xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0;
990 xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0;
991 if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1;
992 else xinfo[i].slow_hflip=0;
993
994 if(xinfo[i].crop)
995 {
996 xinfo[i].crop_xoffset=t[i].r.x; xinfo[i].crop_xoffset_set=JCROP_POS;
997 xinfo[i].crop_yoffset=t[i].r.y; xinfo[i].crop_yoffset_set=JCROP_POS;
998 if(t[i].r.w!=0)
999 {
1000 xinfo[i].crop_width=t[i].r.w; xinfo[i].crop_width_set=JCROP_POS;
1001 }
1002 else xinfo[i].crop_width=JCROP_UNSET;
1003 if(t[i].r.h!=0)
1004 {
1005 xinfo[i].crop_height=t[i].r.h; xinfo[i].crop_height_set=JCROP_POS;
1006 }
1007 else xinfo[i].crop_height=JCROP_UNSET;
1008 }
1009 }
1010
1011 jcopy_markers_setup(dinfo, JCOPYOPT_ALL);
1012 jpeg_read_header(dinfo, TRUE);
1013 jpegSubsamp=getSubsamp(dinfo);
1014 if(jpegSubsamp<0)
1015 _throw("tjTransform(): Could not determine subsampling type for JPEG image");
1016
1017 for(i=0; i<n; i++)
1018 {
1019 if(!jtransform_request_workspace(dinfo, &xinfo[i]))
1020 _throw("tjTransform(): Transform is not perfect");
1021
1022 if(xinfo[i].crop)
1023 {
1024 if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0
1025 || (t[i].r.y%xinfo[i].iMCU_sample_height)!=0)
1026 {
1027 snprintf(errStr, JMSG_LENGTH_MAX,
1028 "To crop this JPEG image, x must be a multiple of %d\n"
1029 "and y must be a multiple of %d.\n",
1030 xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height);
1031 retval=-1; goto bailout;
1032 }
1033 }
1034 }
1035
1036 srccoefs=jpeg_read_coefficients(dinfo);
1037
1038 for(i=0; i<n; i++)
1039 {
1040 int w, h, alloc=1;
1041 if(!xinfo[i].crop)
1042 {
1043 w=dinfo->image_width; h=dinfo->image_height;
1044 }
1045 else
1046 {
1047 w=xinfo[i].crop_width; h=xinfo[i].crop_height;
1048 }
1049 if(flags&TJFLAG_NOREALLOC)
1050 {
1051 alloc=0; dstSizes[i]=tjBufSize(w, h, jpegSubsamp);
1052 }
hbono@chromium.orgc6beb742011-11-29 05:16:26 +00001053 if(!(t[i].options&TJXOPT_NOOUTPUT))
1054 jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc);
hbono@chromium.org98626972011-08-03 03:13:08 +00001055 jpeg_copy_critical_parameters(dinfo, cinfo);
1056 dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs,
1057 &xinfo[i]);
hbono@chromium.orgc6beb742011-11-29 05:16:26 +00001058 if(!(t[i].options&TJXOPT_NOOUTPUT))
1059 {
1060 jpeg_write_coefficients(cinfo, dstcoefs);
1061 jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL);
1062 }
1063 else jinit_c_master_control(cinfo, TRUE);
hbono@chromium.org98626972011-08-03 03:13:08 +00001064 jtransform_execute_transformation(dinfo, cinfo, srccoefs,
1065 &xinfo[i]);
hbono@chromium.orgc6beb742011-11-29 05:16:26 +00001066 if(t[i].customFilter)
1067 {
1068 int ci, by, y;
1069 for(ci=0; ci<cinfo->num_components; ci++)
1070 {
1071 jpeg_component_info *compptr=&cinfo->comp_info[ci];
1072 tjregion arrayRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
1073 DCTSIZE};
1074 tjregion planeRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
1075 compptr->height_in_blocks*DCTSIZE};
1076 for(by=0; by<compptr->height_in_blocks; by+=compptr->v_samp_factor)
1077 {
1078 JBLOCKARRAY barray=(dinfo->mem->access_virt_barray)
1079 ((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor,
1080 TRUE);
1081 for(y=0; y<compptr->v_samp_factor; y++)
1082 {
1083 if(t[i].customFilter(barray[y][0], arrayRegion, planeRegion,
1084 ci, i, &t[i])==-1)
1085 _throw("tjTransform(): Error in custom filter");
1086 arrayRegion.y+=DCTSIZE;
1087 }
1088 }
1089 }
1090 }
1091 if(!(t[i].options&TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo);
hbono@chromium.org98626972011-08-03 03:13:08 +00001092 }
1093
1094 jpeg_finish_decompress(dinfo);
1095
1096 bailout:
1097 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
1098 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
1099 if(xinfo) free(xinfo);
1100 return retval;
1101}