2 * Copyright (C)2009-2017 D. R. Commander. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
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.
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.
29 /* TurboJPEG/LJT: this implements the TurboJPEG API using libjpeg or
36 #define JPEG_INTERNALS
40 #include "./turbojpeg.h"
43 #include "./jpegcomp.h"
45 extern void jpeg_mem_dest_tj(j_compress_ptr, unsigned char **,
46 unsigned long *, boolean);
47 extern void jpeg_mem_src_tj(j_decompress_ptr, const unsigned char *,
50 #define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
51 #define isPow2(x) (((x)&(x-1))==0)
54 /* Error handling (based on example in example.c) */
56 static char errStr[JMSG_LENGTH_MAX]="No error";
60 struct jpeg_error_mgr pub;
61 jmp_buf setjmp_buffer;
62 void (*emit_message)(j_common_ptr, int);
65 typedef struct my_error_mgr *my_error_ptr;
67 static void my_error_exit(j_common_ptr cinfo)
69 my_error_ptr myerr=(my_error_ptr)cinfo->err;
70 (*cinfo->err->output_message)(cinfo);
71 longjmp(myerr->setjmp_buffer, 1);
74 /* Based on output_message() in jerror.c */
76 static void my_output_message(j_common_ptr cinfo)
78 (*cinfo->err->format_message)(cinfo, errStr);
81 static void my_emit_message(j_common_ptr cinfo, int msg_level)
83 my_error_ptr myerr=(my_error_ptr)cinfo->err;
84 myerr->emit_message(cinfo, msg_level);
85 if(msg_level<0) myerr->warning=TRUE;
89 /* Global structures, macros, etc. */
91 enum {COMPRESS=1, DECOMPRESS=2};
93 typedef struct _tjinstance
95 struct jpeg_compress_struct cinfo;
96 struct jpeg_decompress_struct dinfo;
97 struct my_error_mgr jerr;
101 static const int pixelsize[TJ_NUMSAMP]={3, 3, 3, 1, 3, 3};
103 static const JXFORM_CODE xformtypes[TJ_NUMXOP]=
105 JXFORM_NONE, JXFORM_FLIP_H, JXFORM_FLIP_V, JXFORM_TRANSPOSE,
106 JXFORM_TRANSVERSE, JXFORM_ROT_90, JXFORM_ROT_180, JXFORM_ROT_270
110 static const tjscalingfactor sf[NUMSF]={
129 #define _throw(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s", m); \
130 retval=-1; goto bailout;}
131 #define getinstance(handle) tjinstance *this=(tjinstance *)handle; \
132 j_compress_ptr cinfo=NULL; j_decompress_ptr dinfo=NULL; \
133 if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
135 cinfo=&this->cinfo; dinfo=&this->dinfo; \
136 this->jerr.warning=FALSE;
137 #define getcinstance(handle) tjinstance *this=(tjinstance *)handle; \
138 j_compress_ptr cinfo=NULL; \
139 if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
141 cinfo=&this->cinfo; \
142 this->jerr.warning=FALSE;
143 #define getdinstance(handle) tjinstance *this=(tjinstance *)handle; \
144 j_decompress_ptr dinfo=NULL; \
145 if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
147 dinfo=&this->dinfo; \
148 this->jerr.warning=FALSE;
150 static int getPixelFormat(int pixelSize, int flags)
152 if(pixelSize==1) return TJPF_GRAY;
155 if(flags&TJ_BGR) return TJPF_BGR;
156 else return TJPF_RGB;
160 if(flags&TJ_ALPHAFIRST)
162 if(flags&TJ_BGR) return TJPF_XBGR;
163 else return TJPF_XRGB;
167 if(flags&TJ_BGR) return TJPF_BGRX;
168 else return TJPF_RGBX;
174 static int setCompDefaults(struct jpeg_compress_struct *cinfo,
175 int pixelFormat, int subsamp, int jpegQual, int flags)
183 cinfo->in_color_space=JCS_GRAYSCALE; break;
184 #if JCS_EXTENSIONS==1
186 cinfo->in_color_space=JCS_EXT_RGB; break;
188 cinfo->in_color_space=JCS_EXT_BGR; break;
191 cinfo->in_color_space=JCS_EXT_RGBX; break;
194 cinfo->in_color_space=JCS_EXT_BGRX; break;
197 cinfo->in_color_space=JCS_EXT_XRGB; break;
200 cinfo->in_color_space=JCS_EXT_XBGR; break;
212 cinfo->in_color_space=JCS_RGB; pixelFormat=TJPF_RGB;
216 cinfo->in_color_space=JCS_CMYK; break;
219 cinfo->input_components=tjPixelSize[pixelFormat];
220 jpeg_set_defaults(cinfo);
223 if((env=getenv("TJ_OPTIMIZE"))!=NULL && strlen(env)>0 && !strcmp(env, "1"))
224 cinfo->optimize_coding=TRUE;
225 if((env=getenv("TJ_ARITHMETIC"))!=NULL && strlen(env)>0 && !strcmp(env, "1"))
226 cinfo->arith_code=TRUE;
227 if((env=getenv("TJ_RESTART"))!=NULL && strlen(env)>0)
229 int temp=-1; char tempc=0;
230 if(sscanf(env, "%d%c", &temp, &tempc)>=1 && temp>=0 && temp<=65535)
232 if(toupper(tempc)=='B')
234 cinfo->restart_interval=temp;
235 cinfo->restart_in_rows=0;
238 cinfo->restart_in_rows=temp;
245 jpeg_set_quality(cinfo, jpegQual, TRUE);
246 if(jpegQual>=96 || flags&TJFLAG_ACCURATEDCT) cinfo->dct_method=JDCT_ISLOW;
247 else cinfo->dct_method=JDCT_FASTEST;
249 if(subsamp==TJSAMP_GRAY)
250 jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
251 else if(pixelFormat==TJPF_CMYK)
252 jpeg_set_colorspace(cinfo, JCS_YCCK);
253 else jpeg_set_colorspace(cinfo, JCS_YCbCr);
256 if((env=getenv("TJ_PROGRESSIVE"))!=NULL && strlen(env)>0
257 && !strcmp(env, "1"))
258 jpeg_simple_progression(cinfo);
261 cinfo->comp_info[0].h_samp_factor=tjMCUWidth[subsamp]/8;
262 cinfo->comp_info[1].h_samp_factor=1;
263 cinfo->comp_info[2].h_samp_factor=1;
264 if(cinfo->num_components>3)
265 cinfo->comp_info[3].h_samp_factor=tjMCUWidth[subsamp]/8;
266 cinfo->comp_info[0].v_samp_factor=tjMCUHeight[subsamp]/8;
267 cinfo->comp_info[1].v_samp_factor=1;
268 cinfo->comp_info[2].v_samp_factor=1;
269 if(cinfo->num_components>3)
270 cinfo->comp_info[3].v_samp_factor=tjMCUHeight[subsamp]/8;
275 static int setDecompDefaults(struct jpeg_decompress_struct *dinfo,
276 int pixelFormat, int flags)
283 dinfo->out_color_space=JCS_GRAYSCALE; break;
284 #if JCS_EXTENSIONS==1
286 dinfo->out_color_space=JCS_EXT_RGB; break;
288 dinfo->out_color_space=JCS_EXT_BGR; break;
290 dinfo->out_color_space=JCS_EXT_RGBX; break;
292 dinfo->out_color_space=JCS_EXT_BGRX; break;
294 dinfo->out_color_space=JCS_EXT_XRGB; break;
296 dinfo->out_color_space=JCS_EXT_XBGR; break;
297 #if JCS_ALPHA_EXTENSIONS==1
299 dinfo->out_color_space=JCS_EXT_RGBA; break;
301 dinfo->out_color_space=JCS_EXT_BGRA; break;
303 dinfo->out_color_space=JCS_EXT_ARGB; break;
305 dinfo->out_color_space=JCS_EXT_ABGR; break;
318 dinfo->out_color_space=JCS_RGB; break;
321 dinfo->out_color_space=JCS_CMYK; break;
323 _throw("Unsupported pixel format");
326 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
333 static int getSubsamp(j_decompress_ptr dinfo)
337 /* The sampling factors actually have no meaning with grayscale JPEG files,
338 and in fact it's possible to generate grayscale JPEGs with sampling
339 factors > 1 (even though those sampling factors are ignored by the
340 decompressor.) Thus, we need to treat grayscale as a special case. */
341 if(dinfo->num_components==1 && dinfo->jpeg_color_space==JCS_GRAYSCALE)
344 for(i=0; i<NUMSUBOPT; i++)
346 if(dinfo->num_components==pixelsize[i]
347 || ((dinfo->jpeg_color_space==JCS_YCCK
348 || dinfo->jpeg_color_space==JCS_CMYK)
349 && pixelsize[i]==3 && dinfo->num_components==4))
351 if(dinfo->comp_info[0].h_samp_factor==tjMCUWidth[i]/8
352 && dinfo->comp_info[0].v_samp_factor==tjMCUHeight[i]/8)
355 for(k=1; k<dinfo->num_components; k++)
358 if(dinfo->jpeg_color_space==JCS_YCCK && k==3)
360 href=tjMCUWidth[i]/8; vref=tjMCUHeight[i]/8;
362 if(dinfo->comp_info[k].h_samp_factor==href
363 && dinfo->comp_info[k].v_samp_factor==vref)
366 if(match==dinfo->num_components-1)
371 /* Handle 4:2:2 and 4:4:0 images whose sampling factors are specified
372 in non-standard ways. */
373 if(dinfo->comp_info[0].h_samp_factor==2 &&
374 dinfo->comp_info[0].v_samp_factor==2 &&
375 (i==TJSAMP_422 || i==TJSAMP_440))
378 for(k=1; k<dinfo->num_components; k++)
380 int href=tjMCUHeight[i]/8, vref=tjMCUWidth[i]/8;
381 if(dinfo->jpeg_color_space==JCS_YCCK && k==3)
385 if(dinfo->comp_info[k].h_samp_factor==href
386 && dinfo->comp_info[k].v_samp_factor==vref)
389 if(match==dinfo->num_components-1)
400 #ifndef JCS_EXTENSIONS
402 /* Conversion functions to emulate the colorspace extensions. This allows the
403 TurboJPEG wrapper to be used with libjpeg */
405 #define TORGB(PS, ROFFSET, GOFFSET, BOFFSET) { \
406 int rowPad=pitch-width*PS; \
409 unsigned char *endOfRow=src+width*PS; \
410 while(src<endOfRow) \
412 dst[RGB_RED]=src[ROFFSET]; \
413 dst[RGB_GREEN]=src[GOFFSET]; \
414 dst[RGB_BLUE]=src[BOFFSET]; \
415 dst+=RGB_PIXELSIZE; src+=PS; \
421 static unsigned char *toRGB(unsigned char *src, int width, int pitch,
422 int height, int pixelFormat, unsigned char *dst)
424 unsigned char *retval=src;
428 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3
429 retval=dst; TORGB(3, 0, 1, 2);
433 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3
434 retval=dst; TORGB(3, 2, 1, 0);
439 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
440 retval=dst; TORGB(4, 0, 1, 2);
445 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
446 retval=dst; TORGB(4, 2, 1, 0);
451 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
452 retval=dst; TORGB(4, 1, 2, 3);
457 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
458 retval=dst; TORGB(4, 3, 2, 1);
465 #define FROMRGB(PS, ROFFSET, GOFFSET, BOFFSET, SETALPHA) { \
466 int rowPad=pitch-width*PS; \
469 unsigned char *endOfRow=dst+width*PS; \
470 while(dst<endOfRow) \
472 dst[ROFFSET]=src[RGB_RED]; \
473 dst[GOFFSET]=src[RGB_GREEN]; \
474 dst[BOFFSET]=src[RGB_BLUE]; \
476 dst+=PS; src+=RGB_PIXELSIZE; \
482 static void fromRGB(unsigned char *src, unsigned char *dst, int width,
483 int pitch, int height, int pixelFormat)
488 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3
489 FROMRGB(3, 0, 1, 2,);
493 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3
494 FROMRGB(3, 2, 1, 0,);
498 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
499 FROMRGB(4, 0, 1, 2,);
503 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
504 FROMRGB(4, 0, 1, 2, dst[3]=0xFF;);
508 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
509 FROMRGB(4, 2, 1, 0,);
513 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
514 FROMRGB(4, 2, 1, 0, dst[3]=0xFF;); return;
518 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
519 FROMRGB(4, 1, 2, 3,); return;
523 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
524 FROMRGB(4, 1, 2, 3, dst[0]=0xFF;); return;
528 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
529 FROMRGB(4, 3, 2, 1,); return;
533 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
534 FROMRGB(4, 3, 2, 1, dst[0]=0xFF;); return;
543 /* General API functions */
545 DLLEXPORT char* DLLCALL tjGetErrorStr(void)
551 DLLEXPORT int DLLCALL tjDestroy(tjhandle handle)
554 if(setjmp(this->jerr.setjmp_buffer)) return -1;
555 if(this->init&COMPRESS) jpeg_destroy_compress(cinfo);
556 if(this->init&DECOMPRESS) jpeg_destroy_decompress(dinfo);
562 /* These are exposed mainly because Windows can't malloc() and free() across
563 DLL boundaries except when the CRT DLL is used, and we don't use the CRT DLL
564 with turbojpeg.dll for compatibility reasons. However, these functions
565 can potentially be used for other purposes by different implementations. */
567 DLLEXPORT void DLLCALL tjFree(unsigned char *buf)
573 DLLEXPORT unsigned char *DLLCALL tjAlloc(int bytes)
575 return (unsigned char *)malloc(bytes);
581 static tjhandle _tjInitCompress(tjinstance *this)
583 static unsigned char buffer[1];
584 unsigned char *buf=buffer; unsigned long size=1;
586 /* This is also straight out of example.c */
587 this->cinfo.err=jpeg_std_error(&this->jerr.pub);
588 this->jerr.pub.error_exit=my_error_exit;
589 this->jerr.pub.output_message=my_output_message;
590 this->jerr.emit_message=this->jerr.pub.emit_message;
591 this->jerr.pub.emit_message=my_emit_message;
593 if(setjmp(this->jerr.setjmp_buffer))
595 /* If we get here, the JPEG code has signaled an error. */
600 jpeg_create_compress(&this->cinfo);
601 /* Make an initial call so it will create the destination manager */
602 jpeg_mem_dest_tj(&this->cinfo, &buf, &size, 0);
604 this->init|=COMPRESS;
605 return (tjhandle)this;
608 DLLEXPORT tjhandle DLLCALL tjInitCompress(void)
610 tjinstance *this=NULL;
611 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
613 snprintf(errStr, JMSG_LENGTH_MAX,
614 "tjInitCompress(): Memory allocation failure");
617 MEMZERO(this, sizeof(tjinstance));
618 return _tjInitCompress(this);
622 DLLEXPORT unsigned long DLLCALL tjBufSize(int width, int height,
625 unsigned long retval=0; int mcuw, mcuh, chromasf;
626 if(width<1 || height<1 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT)
627 _throw("tjBufSize(): Invalid argument");
629 /* This allows for rare corner cases in which a JPEG image can actually be
630 larger than the uncompressed input (we wouldn't mention it if it hadn't
632 mcuw=tjMCUWidth[jpegSubsamp];
633 mcuh=tjMCUHeight[jpegSubsamp];
634 chromasf=jpegSubsamp==TJSAMP_GRAY? 0: 4*64/(mcuw*mcuh);
635 retval=PAD(width, mcuw) * PAD(height, mcuh) * (2 + chromasf) + 2048;
641 DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
643 unsigned long retval=0;
644 if(width<1 || height<1)
645 _throw("TJBUFSIZE(): Invalid argument");
647 /* This allows for rare corner cases in which a JPEG image can actually be
648 larger than the uncompressed input (we wouldn't mention it if it hadn't
650 retval=PAD(width, 16) * PAD(height, 16) * 6 + 2048;
657 DLLEXPORT unsigned long DLLCALL tjBufSizeYUV2(int width, int pad, int height,
662 if(subsamp<0 || subsamp>=NUMSUBOPT)
663 _throw("tjBufSizeYUV2(): Invalid argument");
665 nc=(subsamp==TJSAMP_GRAY? 1:3);
668 int pw=tjPlaneWidth(i, width, subsamp);
669 int stride=PAD(pw, pad);
670 int ph=tjPlaneHeight(i, height, subsamp);
671 if(pw<0 || ph<0) return -1;
672 else retval+=stride*ph;
679 DLLEXPORT unsigned long DLLCALL tjBufSizeYUV(int width, int height,
682 return tjBufSizeYUV2(width, 4, height, subsamp);
685 DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
688 return tjBufSizeYUV(width, height, subsamp);
692 DLLEXPORT int tjPlaneWidth(int componentID, int width, int subsamp)
694 int pw, nc, retval=0;
696 if(width<1 || subsamp<0 || subsamp>=TJ_NUMSAMP)
697 _throw("tjPlaneWidth(): Invalid argument");
698 nc=(subsamp==TJSAMP_GRAY? 1:3);
699 if(componentID<0 || componentID>=nc)
700 _throw("tjPlaneWidth(): Invalid argument");
702 pw=PAD(width, tjMCUWidth[subsamp]/8);
706 retval=pw*8/tjMCUWidth[subsamp];
713 DLLEXPORT int tjPlaneHeight(int componentID, int height, int subsamp)
715 int ph, nc, retval=0;
717 if(height<1 || subsamp<0 || subsamp>=TJ_NUMSAMP)
718 _throw("tjPlaneHeight(): Invalid argument");
719 nc=(subsamp==TJSAMP_GRAY? 1:3);
720 if(componentID<0 || componentID>=nc)
721 _throw("tjPlaneHeight(): Invalid argument");
723 ph=PAD(height, tjMCUHeight[subsamp]/8);
727 retval=ph*8/tjMCUHeight[subsamp];
734 DLLEXPORT unsigned long DLLCALL tjPlaneSizeYUV(int componentID, int width,
735 int stride, int height, int subsamp)
737 unsigned long retval=0;
740 if(width<1 || height<1 || subsamp<0 || subsamp>=NUMSUBOPT)
741 _throw("tjPlaneSizeYUV(): Invalid argument");
743 pw=tjPlaneWidth(componentID, width, subsamp);
744 ph=tjPlaneHeight(componentID, height, subsamp);
745 if(pw<0 || ph<0) return -1;
747 if(stride==0) stride=pw;
748 else stride=abs(stride);
750 retval=stride*(ph-1)+pw;
757 DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, const unsigned char *srcBuf,
758 int width, int pitch, int height, int pixelFormat, unsigned char **jpegBuf,
759 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
761 int i, retval=0, alloc=1; JSAMPROW *row_pointer=NULL;
762 #ifndef JCS_EXTENSIONS
763 unsigned char *rgbBuf=NULL;
767 if((this->init&COMPRESS)==0)
768 _throw("tjCompress2(): Instance has not been initialized for compression");
770 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
771 || pixelFormat>=TJ_NUMPF || jpegBuf==NULL || jpegSize==NULL
772 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT || jpegQual<0 || jpegQual>100)
773 _throw("tjCompress2(): Invalid argument");
775 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
777 #ifndef JCS_EXTENSIONS
778 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK)
780 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
781 if(!rgbBuf) _throw("tjCompress2(): Memory allocation failure");
782 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
783 pitch=width*RGB_PIXELSIZE;
787 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
788 _throw("tjCompress2(): Memory allocation failure");
790 if(setjmp(this->jerr.setjmp_buffer))
792 /* If we get here, the JPEG code has signaled an error. */
793 retval=-1; goto bailout;
796 cinfo->image_width=width;
797 cinfo->image_height=height;
799 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
800 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
801 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
803 if(flags&TJFLAG_NOREALLOC)
805 alloc=0; *jpegSize=tjBufSize(width, height, jpegSubsamp);
807 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
808 if(setCompDefaults(cinfo, pixelFormat, jpegSubsamp, jpegQual, flags)==-1)
811 jpeg_start_compress(cinfo, TRUE);
812 for(i=0; i<height; i++)
814 if(flags&TJFLAG_BOTTOMUP)
815 row_pointer[i]=(JSAMPROW)&srcBuf[(height-i-1)*pitch];
816 else row_pointer[i]=(JSAMPROW)&srcBuf[i*pitch];
818 while(cinfo->next_scanline<cinfo->image_height)
820 jpeg_write_scanlines(cinfo, &row_pointer[cinfo->next_scanline],
821 cinfo->image_height-cinfo->next_scanline);
823 jpeg_finish_compress(cinfo);
826 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
827 #ifndef JCS_EXTENSIONS
828 if(rgbBuf) free(rgbBuf);
830 if(row_pointer) free(row_pointer);
831 if(this->jerr.warning) retval=-1;
835 DLLEXPORT int DLLCALL tjCompress(tjhandle handle, unsigned char *srcBuf,
836 int width, int pitch, int height, int pixelSize, unsigned char *jpegBuf,
837 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
839 int retval=0; unsigned long size;
842 size=tjBufSizeYUV(width, height, jpegSubsamp);
843 retval=tjEncodeYUV2(handle, srcBuf, width, pitch, height,
844 getPixelFormat(pixelSize, flags), jpegBuf, jpegSubsamp, flags);
848 retval=tjCompress2(handle, srcBuf, width, pitch, height,
849 getPixelFormat(pixelSize, flags), &jpegBuf, &size, jpegSubsamp, jpegQual,
850 flags|TJFLAG_NOREALLOC);
857 DLLEXPORT int DLLCALL tjEncodeYUVPlanes(tjhandle handle,
858 const unsigned char *srcBuf, int width, int pitch, int height,
859 int pixelFormat, unsigned char **dstPlanes, int *strides, int subsamp,
862 int i, retval=0; JSAMPROW *row_pointer=NULL;
863 JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS];
864 JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
865 JSAMPROW *outbuf[MAX_COMPONENTS];
866 int row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS];
868 jpeg_component_info *compptr;
869 #ifndef JCS_EXTENSIONS
870 unsigned char *rgbBuf=NULL;
873 getcinstance(handle);
875 for(i=0; i<MAX_COMPONENTS; i++)
877 tmpbuf[i]=NULL; _tmpbuf[i]=NULL;
878 tmpbuf2[i]=NULL; _tmpbuf2[i]=NULL; outbuf[i]=NULL;
881 if((this->init&COMPRESS)==0)
882 _throw("tjEncodeYUVPlanes(): Instance has not been initialized for compression");
884 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
885 || pixelFormat>=TJ_NUMPF || !dstPlanes || !dstPlanes[0] || subsamp<0
886 || subsamp>=NUMSUBOPT)
887 _throw("tjEncodeYUVPlanes(): Invalid argument");
888 if(subsamp!=TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2]))
889 _throw("tjEncodeYUVPlanes(): Invalid argument");
891 if(pixelFormat==TJPF_CMYK)
892 _throw("tjEncodeYUVPlanes(): Cannot generate YUV images from CMYK pixels");
894 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
896 #ifndef JCS_EXTENSIONS
897 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK)
899 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
900 if(!rgbBuf) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
901 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
902 pitch=width*RGB_PIXELSIZE;
906 if(setjmp(this->jerr.setjmp_buffer))
908 /* If we get here, the JPEG code has signaled an error. */
909 retval=-1; goto bailout;
912 cinfo->image_width=width;
913 cinfo->image_height=height;
915 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
916 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
917 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
919 if(setCompDefaults(cinfo, pixelFormat, subsamp, -1, flags)==-1) return -1;
921 /* Execute only the parts of jpeg_start_compress() that we need. If we
922 were to call the whole jpeg_start_compress() function, then it would try
923 to write the file headers, which could overflow the output buffer if the
924 YUV image were very small. */
925 if(cinfo->global_state!=CSTATE_START)
926 _throw("tjEncodeYUVPlanes(): libjpeg API is in the wrong state");
927 (*cinfo->err->reset_error_mgr)((j_common_ptr)cinfo);
928 jinit_c_master_control(cinfo, FALSE);
929 jinit_color_converter(cinfo);
930 jinit_downsampler(cinfo);
931 (*cinfo->cconvert->start_pass)(cinfo);
933 pw0=PAD(width, cinfo->max_h_samp_factor);
934 ph0=PAD(height, cinfo->max_v_samp_factor);
936 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL)
937 _throw("tjEncodeYUVPlanes(): Memory allocation failure");
938 for(i=0; i<height; i++)
940 if(flags&TJFLAG_BOTTOMUP)
941 row_pointer[i]=(JSAMPROW)&srcBuf[(height-i-1)*pitch];
942 else row_pointer[i]=(JSAMPROW)&srcBuf[i*pitch];
945 for(i=height; i<ph0; i++) row_pointer[i]=row_pointer[height-1];
947 for(i=0; i<cinfo->num_components; i++)
949 compptr=&cinfo->comp_info[i];
950 _tmpbuf[i]=(JSAMPLE *)malloc(
951 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
952 /compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
953 if(!_tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
954 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
955 if(!tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
956 for(row=0; row<cinfo->max_v_samp_factor; row++)
958 unsigned char *_tmpbuf_aligned=
959 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
960 tmpbuf[i][row]=&_tmpbuf_aligned[
961 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
962 /compptr->h_samp_factor, 16) * row];
964 _tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
965 * compptr->v_samp_factor + 16);
966 if(!_tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
967 tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
968 if(!tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
969 for(row=0; row<compptr->v_samp_factor; row++)
971 unsigned char *_tmpbuf2_aligned=
972 (unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
973 tmpbuf2[i][row]=&_tmpbuf2_aligned[
974 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
976 pw[i]=pw0*compptr->h_samp_factor/cinfo->max_h_samp_factor;
977 ph[i]=ph0*compptr->v_samp_factor/cinfo->max_v_samp_factor;
978 outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]);
979 if(!outbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
981 for(row=0; row<ph[i]; row++)
984 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
988 if(setjmp(this->jerr.setjmp_buffer))
990 /* If we get here, the JPEG code has signaled an error. */
991 retval=-1; goto bailout;
994 for(row=0; row<ph0; row+=cinfo->max_v_samp_factor)
996 (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0,
997 cinfo->max_v_samp_factor);
998 (cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
999 for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++)
1000 jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
1001 row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
1002 compptr->v_samp_factor, pw[i]);
1004 cinfo->next_scanline+=height;
1005 jpeg_abort_compress(cinfo);
1008 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
1009 #ifndef JCS_EXTENSIONS
1010 if(rgbBuf) free(rgbBuf);
1012 if(row_pointer) free(row_pointer);
1013 for(i=0; i<MAX_COMPONENTS; i++)
1015 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
1016 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
1017 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
1018 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
1019 if(outbuf[i]!=NULL) free(outbuf[i]);
1021 if(this->jerr.warning) retval=-1;
1025 DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle,
1026 const unsigned char *srcBuf, int width, int pitch, int height,
1027 int pixelFormat, unsigned char *dstBuf, int pad, int subsamp, int flags)
1029 unsigned char *dstPlanes[3];
1030 int pw0, ph0, strides[3], retval=-1;
1032 if(width<=0 || height<=0 || dstBuf==NULL || pad<0 || !isPow2(pad)
1033 || subsamp<0 || subsamp>=NUMSUBOPT)
1034 _throw("tjEncodeYUV3(): Invalid argument");
1036 pw0=tjPlaneWidth(0, width, subsamp);
1037 ph0=tjPlaneHeight(0, height, subsamp);
1038 dstPlanes[0]=dstBuf;
1039 strides[0]=PAD(pw0, pad);
1040 if(subsamp==TJSAMP_GRAY)
1042 strides[1]=strides[2]=0;
1043 dstPlanes[1]=dstPlanes[2]=NULL;
1047 int pw1=tjPlaneWidth(1, width, subsamp);
1048 int ph1=tjPlaneHeight(1, height, subsamp);
1049 strides[1]=strides[2]=PAD(pw1, pad);
1050 dstPlanes[1]=dstPlanes[0]+strides[0]*ph0;
1051 dstPlanes[2]=dstPlanes[1]+strides[1]*ph1;
1054 return tjEncodeYUVPlanes(handle, srcBuf, width, pitch, height, pixelFormat,
1055 dstPlanes, strides, subsamp, flags);
1061 DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
1062 int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
1063 int subsamp, int flags)
1065 return tjEncodeYUV3(handle, srcBuf, width, pitch, height, pixelFormat,
1066 dstBuf, 4, subsamp, flags);
1069 DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf,
1070 int width, int pitch, int height, int pixelSize, unsigned char *dstBuf,
1071 int subsamp, int flags)
1073 return tjEncodeYUV2(handle, srcBuf, width, pitch, height,
1074 getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags);
1078 DLLEXPORT int DLLCALL tjCompressFromYUVPlanes(tjhandle handle,
1079 const unsigned char **srcPlanes, int width, const int *strides, int height,
1080 int subsamp, unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual,
1083 int i, row, retval=0, alloc=1; JSAMPROW *inbuf[MAX_COMPONENTS];
1084 int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS],
1085 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
1086 JSAMPLE *_tmpbuf=NULL, *ptr; JSAMPROW *tmpbuf[MAX_COMPONENTS];
1088 getcinstance(handle)
1090 for(i=0; i<MAX_COMPONENTS; i++)
1092 tmpbuf[i]=NULL; inbuf[i]=NULL;
1095 if((this->init&COMPRESS)==0)
1096 _throw("tjCompressFromYUVPlanes(): Instance has not been initialized for compression");
1098 if(!srcPlanes || !srcPlanes[0] || width<=0 || height<=0 || subsamp<0
1099 || subsamp>=NUMSUBOPT || jpegBuf==NULL || jpegSize==NULL || jpegQual<0
1101 _throw("tjCompressFromYUVPlanes(): Invalid argument");
1102 if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2]))
1103 _throw("tjCompressFromYUVPlanes(): Invalid argument");
1105 if(setjmp(this->jerr.setjmp_buffer))
1107 /* If we get here, the JPEG code has signaled an error. */
1108 retval=-1; goto bailout;
1111 cinfo->image_width=width;
1112 cinfo->image_height=height;
1114 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1115 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1116 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
1118 if(flags&TJFLAG_NOREALLOC)
1120 alloc=0; *jpegSize=tjBufSize(width, height, subsamp);
1122 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
1123 if(setCompDefaults(cinfo, TJPF_RGB, subsamp, jpegQual, flags)==-1)
1125 cinfo->raw_data_in=TRUE;
1127 jpeg_start_compress(cinfo, TRUE);
1128 for(i=0; i<cinfo->num_components; i++)
1130 jpeg_component_info *compptr=&cinfo->comp_info[i];
1132 iw[i]=compptr->width_in_blocks*DCTSIZE;
1133 ih=compptr->height_in_blocks*DCTSIZE;
1134 pw[i]=PAD(cinfo->image_width, cinfo->max_h_samp_factor)
1135 *compptr->h_samp_factor/cinfo->max_h_samp_factor;
1136 ph[i]=PAD(cinfo->image_height, cinfo->max_v_samp_factor)
1137 *compptr->v_samp_factor/cinfo->max_v_samp_factor;
1138 if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1;
1139 th[i]=compptr->v_samp_factor*DCTSIZE;
1140 tmpbufsize+=iw[i]*th[i];
1141 if((inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]))==NULL)
1142 _throw("tjCompressFromYUVPlanes(): Memory allocation failure");
1143 ptr=(JSAMPLE *)srcPlanes[i];
1144 for(row=0; row<ph[i]; row++)
1147 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
1152 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
1153 _throw("tjCompressFromYUVPlanes(): Memory allocation failure");
1155 for(i=0; i<cinfo->num_components; i++)
1157 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
1158 _throw("tjCompressFromYUVPlanes(): Memory allocation failure");
1159 for(row=0; row<th[i]; row++)
1167 if(setjmp(this->jerr.setjmp_buffer))
1169 /* If we get here, the JPEG code has signaled an error. */
1170 retval=-1; goto bailout;
1173 for(row=0; row<(int)cinfo->image_height;
1174 row+=cinfo->max_v_samp_factor*DCTSIZE)
1176 JSAMPARRAY yuvptr[MAX_COMPONENTS];
1177 int crow[MAX_COMPONENTS];
1178 for(i=0; i<cinfo->num_components; i++)
1180 jpeg_component_info *compptr=&cinfo->comp_info[i];
1181 crow[i]=row*compptr->v_samp_factor/cinfo->max_v_samp_factor;
1185 for(j=0; j<min(th[i], ph[i]-crow[i]); j++)
1187 memcpy(tmpbuf[i][j], inbuf[i][crow[i]+j], pw[i]);
1188 /* Duplicate last sample in row to fill out MCU */
1189 for(k=pw[i]; k<iw[i]; k++) tmpbuf[i][j][k]=tmpbuf[i][j][pw[i]-1];
1191 /* Duplicate last row to fill out MCU */
1192 for(j=ph[i]-crow[i]; j<th[i]; j++)
1193 memcpy(tmpbuf[i][j], tmpbuf[i][ph[i]-crow[i]-1], iw[i]);
1194 yuvptr[i]=tmpbuf[i];
1197 yuvptr[i]=&inbuf[i][crow[i]];
1199 jpeg_write_raw_data(cinfo, yuvptr, cinfo->max_v_samp_factor*DCTSIZE);
1201 jpeg_finish_compress(cinfo);
1204 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
1205 for(i=0; i<MAX_COMPONENTS; i++)
1207 if(tmpbuf[i]) free(tmpbuf[i]);
1208 if(inbuf[i]) free(inbuf[i]);
1210 if(_tmpbuf) free(_tmpbuf);
1211 if(this->jerr.warning) retval=-1;
1215 DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle,
1216 const unsigned char *srcBuf, int width, int pad, int height, int subsamp,
1217 unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual, int flags)
1219 const unsigned char *srcPlanes[3];
1220 int pw0, ph0, strides[3], retval=-1;
1222 if(srcBuf==NULL || width<=0 || pad<1 || height<=0 || subsamp<0
1223 || subsamp>=NUMSUBOPT)
1224 _throw("tjCompressFromYUV(): Invalid argument");
1226 pw0=tjPlaneWidth(0, width, subsamp);
1227 ph0=tjPlaneHeight(0, height, subsamp);
1228 srcPlanes[0]=srcBuf;
1229 strides[0]=PAD(pw0, pad);
1230 if(subsamp==TJSAMP_GRAY)
1232 strides[1]=strides[2]=0;
1233 srcPlanes[1]=srcPlanes[2]=NULL;
1237 int pw1=tjPlaneWidth(1, width, subsamp);
1238 int ph1=tjPlaneHeight(1, height, subsamp);
1239 strides[1]=strides[2]=PAD(pw1, pad);
1240 srcPlanes[1]=srcPlanes[0]+strides[0]*ph0;
1241 srcPlanes[2]=srcPlanes[1]+strides[1]*ph1;
1244 return tjCompressFromYUVPlanes(handle, srcPlanes, width, strides, height,
1245 subsamp, jpegBuf, jpegSize, jpegQual, flags);
1254 static tjhandle _tjInitDecompress(tjinstance *this)
1256 static unsigned char buffer[1];
1258 /* This is also straight out of example.c */
1259 this->dinfo.err=jpeg_std_error(&this->jerr.pub);
1260 this->jerr.pub.error_exit=my_error_exit;
1261 this->jerr.pub.output_message=my_output_message;
1262 this->jerr.emit_message=this->jerr.pub.emit_message;
1263 this->jerr.pub.emit_message=my_emit_message;
1265 if(setjmp(this->jerr.setjmp_buffer))
1267 /* If we get here, the JPEG code has signaled an error. */
1268 if(this) free(this);
1272 jpeg_create_decompress(&this->dinfo);
1273 /* Make an initial call so it will create the source manager */
1274 jpeg_mem_src_tj(&this->dinfo, buffer, 1);
1276 this->init|=DECOMPRESS;
1277 return (tjhandle)this;
1280 DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
1283 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
1285 snprintf(errStr, JMSG_LENGTH_MAX,
1286 "tjInitDecompress(): Memory allocation failure");
1289 MEMZERO(this, sizeof(tjinstance));
1290 return _tjInitDecompress(this);
1294 DLLEXPORT int DLLCALL tjDecompressHeader3(tjhandle handle,
1295 const unsigned char *jpegBuf, unsigned long jpegSize, int *width,
1296 int *height, int *jpegSubsamp, int *jpegColorspace)
1300 getdinstance(handle);
1301 if((this->init&DECOMPRESS)==0)
1302 _throw("tjDecompressHeader3(): Instance has not been initialized for decompression");
1304 if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL
1305 || jpegSubsamp==NULL || jpegColorspace==NULL)
1306 _throw("tjDecompressHeader3(): Invalid argument");
1308 if(setjmp(this->jerr.setjmp_buffer))
1310 /* If we get here, the JPEG code has signaled an error. */
1314 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1315 jpeg_read_header(dinfo, TRUE);
1317 *width=dinfo->image_width;
1318 *height=dinfo->image_height;
1319 *jpegSubsamp=getSubsamp(dinfo);
1320 switch(dinfo->jpeg_color_space)
1322 case JCS_GRAYSCALE: *jpegColorspace=TJCS_GRAY; break;
1323 case JCS_RGB: *jpegColorspace=TJCS_RGB; break;
1324 case JCS_YCbCr: *jpegColorspace=TJCS_YCbCr; break;
1325 case JCS_CMYK: *jpegColorspace=TJCS_CMYK; break;
1326 case JCS_YCCK: *jpegColorspace=TJCS_YCCK; break;
1327 default: *jpegColorspace=-1; break;
1330 jpeg_abort_decompress(dinfo);
1333 _throw("tjDecompressHeader3(): Could not determine subsampling type for JPEG image");
1334 if(*jpegColorspace<0)
1335 _throw("tjDecompressHeader3(): Could not determine colorspace of JPEG image");
1336 if(*width<1 || *height<1)
1337 _throw("tjDecompressHeader3(): Invalid data returned in header");
1340 if(this->jerr.warning) retval=-1;
1344 DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle,
1345 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
1349 return tjDecompressHeader3(handle, jpegBuf, jpegSize, width, height,
1350 jpegSubsamp, &jpegColorspace);
1353 DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle,
1354 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height)
1357 return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height,
1362 DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors)
1364 if(numscalingfactors==NULL)
1366 snprintf(errStr, JMSG_LENGTH_MAX,
1367 "tjGetScalingFactors(): Invalid argument");
1371 *numscalingfactors=NUMSF;
1372 return (tjscalingfactor *)sf;
1376 DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle,
1377 const unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
1378 int width, int pitch, int height, int pixelFormat, int flags)
1380 int i, retval=0; JSAMPROW *row_pointer=NULL;
1381 int jpegwidth, jpegheight, scaledw, scaledh;
1382 #ifndef JCS_EXTENSIONS
1383 unsigned char *rgbBuf=NULL;
1384 unsigned char *_dstBuf=NULL; int _pitch=0;
1387 getdinstance(handle);
1388 if((this->init&DECOMPRESS)==0)
1389 _throw("tjDecompress2(): Instance has not been initialized for decompression");
1391 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0
1392 || height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF)
1393 _throw("tjDecompress2(): Invalid argument");
1395 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1396 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1397 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
1399 if(setjmp(this->jerr.setjmp_buffer))
1401 /* If we get here, the JPEG code has signaled an error. */
1402 retval=-1; goto bailout;
1405 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1406 jpeg_read_header(dinfo, TRUE);
1407 if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
1409 retval=-1; goto bailout;
1412 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
1414 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
1415 if(width==0) width=jpegwidth;
1416 if(height==0) height=jpegheight;
1417 for(i=0; i<NUMSF; i++)
1419 scaledw=TJSCALED(jpegwidth, sf[i]);
1420 scaledh=TJSCALED(jpegheight, sf[i]);
1421 if(scaledw<=width && scaledh<=height)
1425 _throw("tjDecompress2(): Could not scale down to desired image dimensions");
1426 width=scaledw; height=scaledh;
1427 dinfo->scale_num=sf[i].num;
1428 dinfo->scale_denom=sf[i].denom;
1430 jpeg_start_decompress(dinfo);
1431 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
1433 #ifndef JCS_EXTENSIONS
1434 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK &&
1435 (RGB_RED!=tjRedOffset[pixelFormat] ||
1436 RGB_GREEN!=tjGreenOffset[pixelFormat] ||
1437 RGB_BLUE!=tjBlueOffset[pixelFormat] ||
1438 RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
1440 rgbBuf=(unsigned char *)malloc(width*height*3);
1441 if(!rgbBuf) _throw("tjDecompress2(): Memory allocation failure");
1442 _pitch=pitch; pitch=width*3;
1443 _dstBuf=dstBuf; dstBuf=rgbBuf;
1447 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
1448 *dinfo->output_height))==NULL)
1449 _throw("tjDecompress2(): Memory allocation failure");
1450 if(setjmp(this->jerr.setjmp_buffer))
1452 /* If we get here, the JPEG code has signaled an error. */
1453 retval=-1; goto bailout;
1455 for(i=0; i<(int)dinfo->output_height; i++)
1457 if(flags&TJFLAG_BOTTOMUP)
1458 row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*pitch];
1459 else row_pointer[i]=&dstBuf[i*pitch];
1461 while(dinfo->output_scanline<dinfo->output_height)
1463 jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline],
1464 dinfo->output_height-dinfo->output_scanline);
1466 jpeg_finish_decompress(dinfo);
1468 #ifndef JCS_EXTENSIONS
1469 fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
1473 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
1474 #ifndef JCS_EXTENSIONS
1475 if(rgbBuf) free(rgbBuf);
1477 if(row_pointer) free(row_pointer);
1478 if(this->jerr.warning) retval=-1;
1482 DLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf,
1483 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
1484 int height, int pixelSize, int flags)
1487 return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags);
1489 return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch,
1490 height, getPixelFormat(pixelSize, flags), flags);
1494 static int setDecodeDefaults(struct jpeg_decompress_struct *dinfo,
1495 int pixelFormat, int subsamp, int flags)
1499 dinfo->scale_num=dinfo->scale_denom=1;
1501 if(subsamp==TJSAMP_GRAY)
1503 dinfo->num_components=dinfo->comps_in_scan=1;
1504 dinfo->jpeg_color_space=JCS_GRAYSCALE;
1508 dinfo->num_components=dinfo->comps_in_scan=3;
1509 dinfo->jpeg_color_space=JCS_YCbCr;
1512 dinfo->comp_info=(jpeg_component_info *)
1513 (*dinfo->mem->alloc_small)((j_common_ptr)dinfo, JPOOL_IMAGE,
1514 dinfo->num_components*sizeof(jpeg_component_info));
1516 for(i=0; i<dinfo->num_components; i++)
1518 jpeg_component_info *compptr=&dinfo->comp_info[i];
1519 compptr->h_samp_factor=(i==0)? tjMCUWidth[subsamp]/8:1;
1520 compptr->v_samp_factor=(i==0)? tjMCUHeight[subsamp]/8:1;
1521 compptr->component_index=i;
1522 compptr->component_id=i+1;
1523 compptr->quant_tbl_no=compptr->dc_tbl_no=compptr->ac_tbl_no=
1525 dinfo->cur_comp_info[i]=compptr;
1527 dinfo->data_precision=8;
1530 if(dinfo->quant_tbl_ptrs[i]==NULL)
1531 dinfo->quant_tbl_ptrs[i]=jpeg_alloc_quant_table((j_common_ptr)dinfo);
1538 int my_read_markers(j_decompress_ptr dinfo)
1540 return JPEG_REACHED_SOS;
1543 void my_reset_marker_reader(j_decompress_ptr dinfo)
1547 DLLEXPORT int DLLCALL tjDecodeYUVPlanes(tjhandle handle,
1548 const unsigned char **srcPlanes, const int *strides, int subsamp,
1549 unsigned char *dstBuf, int width, int pitch, int height, int pixelFormat,
1552 int i, retval=0; JSAMPROW *row_pointer=NULL;
1553 JSAMPLE *_tmpbuf[MAX_COMPONENTS];
1554 JSAMPROW *tmpbuf[MAX_COMPONENTS], *inbuf[MAX_COMPONENTS];
1555 int row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS];
1557 jpeg_component_info *compptr;
1558 #ifndef JCS_EXTENSIONS
1559 unsigned char *rgbBuf=NULL;
1560 unsigned char *_dstBuf=NULL; int _pitch=0;
1562 int (*old_read_markers)(j_decompress_ptr);
1563 void (*old_reset_marker_reader)(j_decompress_ptr);
1565 getdinstance(handle);
1567 for(i=0; i<MAX_COMPONENTS; i++)
1569 tmpbuf[i]=NULL; _tmpbuf[i]=NULL; inbuf[i]=NULL;
1572 if((this->init&DECOMPRESS)==0)
1573 _throw("tjDecodeYUVPlanes(): Instance has not been initialized for decompression");
1575 if(!srcPlanes || !srcPlanes[0] || subsamp<0 || subsamp>=NUMSUBOPT
1576 || dstBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
1577 || pixelFormat>=TJ_NUMPF)
1578 _throw("tjDecodeYUVPlanes(): Invalid argument");
1579 if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2]))
1580 _throw("tjDecodeYUVPlanes(): Invalid argument");
1582 if(setjmp(this->jerr.setjmp_buffer))
1584 /* If we get here, the JPEG code has signaled an error. */
1585 retval=-1; goto bailout;
1588 if(pixelFormat==TJPF_CMYK)
1589 _throw("tjDecodeYUVPlanes(): Cannot decode YUV images into CMYK pixels.");
1591 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
1592 dinfo->image_width=width;
1593 dinfo->image_height=height;
1595 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1596 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1597 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
1599 if(setDecodeDefaults(dinfo, pixelFormat, subsamp, flags)==-1)
1601 retval=-1; goto bailout;
1603 old_read_markers=dinfo->marker->read_markers;
1604 dinfo->marker->read_markers=my_read_markers;
1605 old_reset_marker_reader=dinfo->marker->reset_marker_reader;
1606 dinfo->marker->reset_marker_reader=my_reset_marker_reader;
1607 jpeg_read_header(dinfo, TRUE);
1608 dinfo->marker->read_markers=old_read_markers;
1609 dinfo->marker->reset_marker_reader=old_reset_marker_reader;
1611 if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
1613 retval=-1; goto bailout;
1615 dinfo->do_fancy_upsampling=FALSE;
1616 dinfo->Se=DCTSIZE2-1;
1617 jinit_master_decompress(dinfo);
1618 (*dinfo->upsample->start_pass)(dinfo);
1620 pw0=PAD(width, dinfo->max_h_samp_factor);
1621 ph0=PAD(height, dinfo->max_v_samp_factor);
1623 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
1625 #ifndef JCS_EXTENSIONS
1626 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK &&
1627 (RGB_RED!=tjRedOffset[pixelFormat] ||
1628 RGB_GREEN!=tjGreenOffset[pixelFormat] ||
1629 RGB_BLUE!=tjBlueOffset[pixelFormat] ||
1630 RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
1632 rgbBuf=(unsigned char *)malloc(width*height*3);
1633 if(!rgbBuf) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1634 _pitch=pitch; pitch=width*3;
1635 _dstBuf=dstBuf; dstBuf=rgbBuf;
1639 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL)
1640 _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1641 for(i=0; i<height; i++)
1643 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&dstBuf[(height-i-1)*pitch];
1644 else row_pointer[i]=&dstBuf[i*pitch];
1647 for(i=height; i<ph0; i++) row_pointer[i]=row_pointer[height-1];
1649 for(i=0; i<dinfo->num_components; i++)
1651 compptr=&dinfo->comp_info[i];
1652 _tmpbuf[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
1653 * compptr->v_samp_factor + 16);
1654 if(!_tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1655 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
1656 if(!tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1657 for(row=0; row<compptr->v_samp_factor; row++)
1659 unsigned char *_tmpbuf_aligned=
1660 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
1661 tmpbuf[i][row]=&_tmpbuf_aligned[
1662 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
1664 pw[i]=pw0*compptr->h_samp_factor/dinfo->max_h_samp_factor;
1665 ph[i]=ph0*compptr->v_samp_factor/dinfo->max_v_samp_factor;
1666 inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]);
1667 if(!inbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1668 ptr=(JSAMPLE *)srcPlanes[i];
1669 for(row=0; row<ph[i]; row++)
1672 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
1676 if(setjmp(this->jerr.setjmp_buffer))
1678 /* If we get here, the JPEG code has signaled an error. */
1679 retval=-1; goto bailout;
1682 for(row=0; row<ph0; row+=dinfo->max_v_samp_factor)
1684 JDIMENSION inrow=0, outrow=0;
1685 for(i=0, compptr=dinfo->comp_info; i<dinfo->num_components; i++, compptr++)
1686 jcopy_sample_rows(inbuf[i],
1687 row*compptr->v_samp_factor/dinfo->max_v_samp_factor, tmpbuf[i], 0,
1688 compptr->v_samp_factor, pw[i]);
1689 (dinfo->upsample->upsample)(dinfo, tmpbuf, &inrow,
1690 dinfo->max_v_samp_factor, &row_pointer[row], &outrow,
1691 dinfo->max_v_samp_factor);
1693 jpeg_abort_decompress(dinfo);
1695 #ifndef JCS_EXTENSIONS
1696 fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
1700 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
1701 #ifndef JCS_EXTENSIONS
1702 if(rgbBuf) free(rgbBuf);
1704 if(row_pointer) free(row_pointer);
1705 for(i=0; i<MAX_COMPONENTS; i++)
1707 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
1708 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
1709 if(inbuf[i]!=NULL) free(inbuf[i]);
1711 if(this->jerr.warning) retval=-1;
1715 DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, const unsigned char *srcBuf,
1716 int pad, int subsamp, unsigned char *dstBuf, int width, int pitch,
1717 int height, int pixelFormat, int flags)
1719 const unsigned char *srcPlanes[3];
1720 int pw0, ph0, strides[3], retval=-1;
1722 if(srcBuf==NULL || pad<0 || !isPow2(pad) || subsamp<0 || subsamp>=NUMSUBOPT
1723 || width<=0 || height<=0)
1724 _throw("tjDecodeYUV(): Invalid argument");
1726 pw0=tjPlaneWidth(0, width, subsamp);
1727 ph0=tjPlaneHeight(0, height, subsamp);
1728 srcPlanes[0]=srcBuf;
1729 strides[0]=PAD(pw0, pad);
1730 if(subsamp==TJSAMP_GRAY)
1732 strides[1]=strides[2]=0;
1733 srcPlanes[1]=srcPlanes[2]=NULL;
1737 int pw1=tjPlaneWidth(1, width, subsamp);
1738 int ph1=tjPlaneHeight(1, height, subsamp);
1739 strides[1]=strides[2]=PAD(pw1, pad);
1740 srcPlanes[1]=srcPlanes[0]+strides[0]*ph0;
1741 srcPlanes[2]=srcPlanes[1]+strides[1]*ph1;
1744 return tjDecodeYUVPlanes(handle, srcPlanes, strides, subsamp, dstBuf, width,
1745 pitch, height, pixelFormat, flags);
1751 DLLEXPORT int DLLCALL tjDecompressToYUVPlanes(tjhandle handle,
1752 const unsigned char *jpegBuf, unsigned long jpegSize,
1753 unsigned char **dstPlanes, int width, int *strides, int height, int flags)
1755 int i, sfi, row, retval=0; JSAMPROW *outbuf[MAX_COMPONENTS];
1756 int jpegwidth, jpegheight, jpegSubsamp, scaledw, scaledh;
1757 int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS],
1758 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
1759 JSAMPLE *_tmpbuf=NULL, *ptr; JSAMPROW *tmpbuf[MAX_COMPONENTS];
1762 getdinstance(handle);
1764 for(i=0; i<MAX_COMPONENTS; i++)
1766 tmpbuf[i]=NULL; outbuf[i]=NULL;
1769 if((this->init&DECOMPRESS)==0)
1770 _throw("tjDecompressToYUVPlanes(): Instance has not been initialized for decompression");
1772 if(jpegBuf==NULL || jpegSize<=0 || !dstPlanes || !dstPlanes[0] || width<0
1774 _throw("tjDecompressToYUVPlanes(): Invalid argument");
1776 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1777 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1778 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
1780 if(setjmp(this->jerr.setjmp_buffer))
1782 /* If we get here, the JPEG code has signaled an error. */
1783 retval=-1; goto bailout;
1786 if(!this->headerRead)
1788 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1789 jpeg_read_header(dinfo, TRUE);
1792 jpegSubsamp=getSubsamp(dinfo);
1794 _throw("tjDecompressToYUVPlanes(): Could not determine subsampling type for JPEG image");
1796 if(jpegSubsamp!=TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2]))
1797 _throw("tjDecompressToYUVPlanes(): Invalid argument");
1799 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
1800 if(width==0) width=jpegwidth;
1801 if(height==0) height=jpegheight;
1802 for(i=0; i<NUMSF; i++)
1804 scaledw=TJSCALED(jpegwidth, sf[i]);
1805 scaledh=TJSCALED(jpegheight, sf[i]);
1806 if(scaledw<=width && scaledh<=height)
1810 _throw("tjDecompressToYUVPlanes(): Could not scale down to desired image dimensions");
1811 if(dinfo->num_components>3)
1812 _throw("tjDecompressToYUVPlanes(): JPEG image must have 3 or fewer components");
1814 width=scaledw; height=scaledh;
1815 dinfo->scale_num=sf[i].num;
1816 dinfo->scale_denom=sf[i].denom;
1818 jpeg_calc_output_dimensions(dinfo);
1820 dctsize=DCTSIZE*sf[sfi].num/sf[sfi].denom;
1822 for(i=0; i<dinfo->num_components; i++)
1824 jpeg_component_info *compptr=&dinfo->comp_info[i];
1826 iw[i]=compptr->width_in_blocks*dctsize;
1827 ih=compptr->height_in_blocks*dctsize;
1828 pw[i]=PAD(dinfo->output_width, dinfo->max_h_samp_factor)
1829 *compptr->h_samp_factor/dinfo->max_h_samp_factor;
1830 ph[i]=PAD(dinfo->output_height, dinfo->max_v_samp_factor)
1831 *compptr->v_samp_factor/dinfo->max_v_samp_factor;
1832 if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1;
1833 th[i]=compptr->v_samp_factor*dctsize;
1834 tmpbufsize+=iw[i]*th[i];
1835 if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]))==NULL)
1836 _throw("tjDecompressToYUVPlanes(): Memory allocation failure");
1838 for(row=0; row<ph[i]; row++)
1841 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
1846 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
1847 _throw("tjDecompressToYUVPlanes(): Memory allocation failure");
1849 for(i=0; i<dinfo->num_components; i++)
1851 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
1852 _throw("tjDecompressToYUVPlanes(): Memory allocation failure");
1853 for(row=0; row<th[i]; row++)
1861 if(setjmp(this->jerr.setjmp_buffer))
1863 /* If we get here, the JPEG code has signaled an error. */
1864 retval=-1; goto bailout;
1867 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
1868 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
1869 dinfo->raw_data_out=TRUE;
1871 jpeg_start_decompress(dinfo);
1872 for(row=0; row<(int)dinfo->output_height;
1873 row+=dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size)
1875 JSAMPARRAY yuvptr[MAX_COMPONENTS];
1876 int crow[MAX_COMPONENTS];
1877 for(i=0; i<dinfo->num_components; i++)
1879 jpeg_component_info *compptr=&dinfo->comp_info[i];
1880 if(jpegSubsamp==TJ_420)
1882 /* When 4:2:0 subsampling is used with IDCT scaling, libjpeg will try
1883 to be clever and use the IDCT to perform upsampling on the U and V
1884 planes. For instance, if the output image is to be scaled by 1/2
1885 relative to the JPEG image, then the scaling factor and upsampling
1886 effectively cancel each other, so a normal 8x8 IDCT can be used.
1887 However, this is not desirable when using the decompress-to-YUV
1888 functionality in TurboJPEG, since we want to output the U and V
1889 planes in their subsampled form. Thus, we have to override some
1890 internal libjpeg parameters to force it to use the "scaled" IDCT
1891 functions on the U and V planes. */
1892 compptr->_DCT_scaled_size=dctsize;
1893 compptr->MCU_sample_width=tjMCUWidth[jpegSubsamp]*
1894 sf[sfi].num/sf[sfi].denom*
1895 compptr->v_samp_factor/dinfo->max_v_samp_factor;
1896 dinfo->idct->inverse_DCT[i] = dinfo->idct->inverse_DCT[0];
1898 crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
1899 if(usetmpbuf) yuvptr[i]=tmpbuf[i];
1900 else yuvptr[i]=&outbuf[i][crow[i]];
1902 jpeg_read_raw_data(dinfo, yuvptr,
1903 dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size);
1907 for(i=0; i<dinfo->num_components; i++)
1909 for(j=0; j<min(th[i], ph[i]-crow[i]); j++)
1911 memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], pw[i]);
1916 jpeg_finish_decompress(dinfo);
1919 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
1920 for(i=0; i<MAX_COMPONENTS; i++)
1922 if(tmpbuf[i]) free(tmpbuf[i]);
1923 if(outbuf[i]) free(outbuf[i]);
1925 if(_tmpbuf) free(_tmpbuf);
1926 if(this->jerr.warning) retval=-1;
1930 DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle,
1931 const unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
1932 int width, int pad, int height, int flags)
1934 unsigned char *dstPlanes[3];
1935 int pw0, ph0, strides[3], retval=-1, jpegSubsamp=-1;
1936 int i, jpegwidth, jpegheight, scaledw, scaledh;
1938 getdinstance(handle);
1940 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pad<1
1941 || !isPow2(pad) || height<0)
1942 _throw("tjDecompressToYUV2(): Invalid argument");
1944 if(setjmp(this->jerr.setjmp_buffer))
1946 /* If we get here, the JPEG code has signaled an error. */
1950 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1951 jpeg_read_header(dinfo, TRUE);
1952 jpegSubsamp=getSubsamp(dinfo);
1954 _throw("tjDecompressToYUV2(): Could not determine subsampling type for JPEG image");
1956 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
1957 if(width==0) width=jpegwidth;
1958 if(height==0) height=jpegheight;
1960 for(i=0; i<NUMSF; i++)
1962 scaledw=TJSCALED(jpegwidth, sf[i]);
1963 scaledh=TJSCALED(jpegheight, sf[i]);
1964 if(scaledw<=width && scaledh<=height)
1968 _throw("tjDecompressToYUV2(): Could not scale down to desired image dimensions");
1970 pw0=tjPlaneWidth(0, width, jpegSubsamp);
1971 ph0=tjPlaneHeight(0, height, jpegSubsamp);
1972 dstPlanes[0]=dstBuf;
1973 strides[0]=PAD(pw0, pad);
1974 if(jpegSubsamp==TJSAMP_GRAY)
1976 strides[1]=strides[2]=0;
1977 dstPlanes[1]=dstPlanes[2]=NULL;
1981 int pw1=tjPlaneWidth(1, width, jpegSubsamp);
1982 int ph1=tjPlaneHeight(1, height, jpegSubsamp);
1983 strides[1]=strides[2]=PAD(pw1, pad);
1984 dstPlanes[1]=dstPlanes[0]+strides[0]*ph0;
1985 dstPlanes[2]=dstPlanes[1]+strides[1]*ph1;
1989 return tjDecompressToYUVPlanes(handle, jpegBuf, jpegSize, dstPlanes, width,
1990 strides, height, flags);
1997 DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle,
1998 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
2001 return tjDecompressToYUV2(handle, jpegBuf, jpegSize, dstBuf, 0, 4, 0, flags);
2007 DLLEXPORT tjhandle DLLCALL tjInitTransform(void)
2009 tjinstance *this=NULL; tjhandle handle=NULL;
2010 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
2012 snprintf(errStr, JMSG_LENGTH_MAX,
2013 "tjInitTransform(): Memory allocation failure");
2016 MEMZERO(this, sizeof(tjinstance));
2017 handle=_tjInitCompress(this);
2018 if(!handle) return NULL;
2019 handle=_tjInitDecompress(this);
2024 DLLEXPORT int DLLCALL tjTransform(tjhandle handle,
2025 const unsigned char *jpegBuf, unsigned long jpegSize, int n,
2026 unsigned char **dstBufs, unsigned long *dstSizes, tjtransform *t, int flags)
2028 jpeg_transform_info *xinfo=NULL;
2029 jvirt_barray_ptr *srccoefs, *dstcoefs;
2030 int retval=0, i, jpegSubsamp;
2032 getinstance(handle);
2033 if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0)
2034 _throw("tjTransform(): Instance has not been initialized for transformation");
2036 if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL
2037 || t==NULL || flags<0)
2038 _throw("tjTransform(): Invalid argument");
2040 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
2041 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
2042 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
2044 if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n))
2046 _throw("tjTransform(): Memory allocation failure");
2047 MEMZERO(xinfo, sizeof(jpeg_transform_info)*n);
2049 if(setjmp(this->jerr.setjmp_buffer))
2051 /* If we get here, the JPEG code has signaled an error. */
2052 retval=-1; goto bailout;
2055 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
2059 xinfo[i].transform=xformtypes[t[i].op];
2060 xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0;
2061 xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0;
2062 xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0;
2063 xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0;
2064 if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1;
2065 else xinfo[i].slow_hflip=0;
2069 xinfo[i].crop_xoffset=t[i].r.x; xinfo[i].crop_xoffset_set=JCROP_POS;
2070 xinfo[i].crop_yoffset=t[i].r.y; xinfo[i].crop_yoffset_set=JCROP_POS;
2073 xinfo[i].crop_width=t[i].r.w; xinfo[i].crop_width_set=JCROP_POS;
2075 else xinfo[i].crop_width=JCROP_UNSET;
2078 xinfo[i].crop_height=t[i].r.h; xinfo[i].crop_height_set=JCROP_POS;
2080 else xinfo[i].crop_height=JCROP_UNSET;
2084 jcopy_markers_setup(dinfo, JCOPYOPT_ALL);
2085 jpeg_read_header(dinfo, TRUE);
2086 jpegSubsamp=getSubsamp(dinfo);
2088 _throw("tjTransform(): Could not determine subsampling type for JPEG image");
2092 if(!jtransform_request_workspace(dinfo, &xinfo[i]))
2093 _throw("tjTransform(): Transform is not perfect");
2097 if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0
2098 || (t[i].r.y%xinfo[i].iMCU_sample_height)!=0)
2100 snprintf(errStr, JMSG_LENGTH_MAX,
2101 "To crop this JPEG image, x must be a multiple of %d\n"
2102 "and y must be a multiple of %d.\n",
2103 xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height);
2104 retval=-1; goto bailout;
2109 srccoefs=jpeg_read_coefficients(dinfo);
2116 w=dinfo->image_width; h=dinfo->image_height;
2120 w=xinfo[i].crop_width; h=xinfo[i].crop_height;
2122 if(flags&TJFLAG_NOREALLOC)
2124 alloc=0; dstSizes[i]=tjBufSize(w, h, jpegSubsamp);
2126 if(!(t[i].options&TJXOPT_NOOUTPUT))
2127 jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc);
2128 jpeg_copy_critical_parameters(dinfo, cinfo);
2129 dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs,
2131 if(!(t[i].options&TJXOPT_NOOUTPUT))
2133 jpeg_write_coefficients(cinfo, dstcoefs);
2134 jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL);
2136 else jinit_c_master_control(cinfo, TRUE);
2137 jtransform_execute_transformation(dinfo, cinfo, srccoefs,
2139 if(t[i].customFilter)
2141 int ci, y; JDIMENSION by;
2142 for(ci=0; ci<cinfo->num_components; ci++)
2144 jpeg_component_info *compptr=&cinfo->comp_info[ci];
2145 tjregion arrayRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
2147 tjregion planeRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
2148 compptr->height_in_blocks*DCTSIZE};
2149 for(by=0; by<compptr->height_in_blocks; by+=compptr->v_samp_factor)
2151 JBLOCKARRAY barray=(dinfo->mem->access_virt_barray)
2152 ((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor,
2154 for(y=0; y<compptr->v_samp_factor; y++)
2156 if(t[i].customFilter(barray[y][0], arrayRegion, planeRegion,
2158 _throw("tjTransform(): Error in custom filter");
2159 arrayRegion.y+=DCTSIZE;
2164 if(!(t[i].options&TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo);
2167 jpeg_finish_decompress(dinfo);
2170 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
2171 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
2172 if(xinfo) free(xinfo);
2173 if(this->jerr.warning) retval=-1;