2 * Copyright (C)2009-2015 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, unsigned char *, unsigned long);
49 #define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
50 #define isPow2(x) (((x)&(x-1))==0)
53 /* Error handling (based on example in example.c) */
55 static char errStr[JMSG_LENGTH_MAX]="No error";
59 struct jpeg_error_mgr pub;
60 jmp_buf setjmp_buffer;
61 void (*emit_message)(j_common_ptr, int);
64 typedef struct my_error_mgr *my_error_ptr;
66 static void my_error_exit(j_common_ptr cinfo)
68 my_error_ptr myerr=(my_error_ptr)cinfo->err;
69 (*cinfo->err->output_message)(cinfo);
70 longjmp(myerr->setjmp_buffer, 1);
73 /* Based on output_message() in jerror.c */
75 static void my_output_message(j_common_ptr cinfo)
77 (*cinfo->err->format_message)(cinfo, errStr);
80 static void my_emit_message(j_common_ptr cinfo, int msg_level)
82 my_error_ptr myerr=(my_error_ptr)cinfo->err;
83 myerr->emit_message(cinfo, msg_level);
84 if(msg_level<0) myerr->warning=TRUE;
88 /* Global structures, macros, etc. */
90 enum {COMPRESS=1, DECOMPRESS=2};
92 typedef struct _tjinstance
94 struct jpeg_compress_struct cinfo;
95 struct jpeg_decompress_struct dinfo;
96 struct my_error_mgr jerr;
100 static const int pixelsize[TJ_NUMSAMP]={3, 3, 3, 1, 3, 3};
102 static const JXFORM_CODE xformtypes[TJ_NUMXOP]=
104 JXFORM_NONE, JXFORM_FLIP_H, JXFORM_FLIP_V, JXFORM_TRANSPOSE,
105 JXFORM_TRANSVERSE, JXFORM_ROT_90, JXFORM_ROT_180, JXFORM_ROT_270
109 static const tjscalingfactor sf[NUMSF]={
128 #define _throw(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s", m); \
129 retval=-1; goto bailout;}
130 #define getinstance(handle) tjinstance *this=(tjinstance *)handle; \
131 j_compress_ptr cinfo=NULL; j_decompress_ptr dinfo=NULL; \
132 if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
134 cinfo=&this->cinfo; dinfo=&this->dinfo; \
135 this->jerr.warning=FALSE;
136 #define getcinstance(handle) tjinstance *this=(tjinstance *)handle; \
137 j_compress_ptr cinfo=NULL; \
138 if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
140 cinfo=&this->cinfo; \
141 this->jerr.warning=FALSE;
142 #define getdinstance(handle) tjinstance *this=(tjinstance *)handle; \
143 j_decompress_ptr dinfo=NULL; \
144 if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
146 dinfo=&this->dinfo; \
147 this->jerr.warning=FALSE;
149 static int getPixelFormat(int pixelSize, int flags)
151 if(pixelSize==1) return TJPF_GRAY;
154 if(flags&TJ_BGR) return TJPF_BGR;
155 else return TJPF_RGB;
159 if(flags&TJ_ALPHAFIRST)
161 if(flags&TJ_BGR) return TJPF_XBGR;
162 else return TJPF_XRGB;
166 if(flags&TJ_BGR) return TJPF_BGRX;
167 else return TJPF_RGBX;
173 static int setCompDefaults(struct jpeg_compress_struct *cinfo,
174 int pixelFormat, int subsamp, int jpegQual, int flags)
182 cinfo->in_color_space=JCS_GRAYSCALE; break;
183 #if JCS_EXTENSIONS==1
185 cinfo->in_color_space=JCS_EXT_RGB; break;
187 cinfo->in_color_space=JCS_EXT_BGR; break;
190 cinfo->in_color_space=JCS_EXT_RGBX; break;
193 cinfo->in_color_space=JCS_EXT_BGRX; break;
196 cinfo->in_color_space=JCS_EXT_XRGB; break;
199 cinfo->in_color_space=JCS_EXT_XBGR; break;
211 cinfo->in_color_space=JCS_RGB; pixelFormat=TJPF_RGB;
215 cinfo->in_color_space=JCS_CMYK; break;
218 cinfo->input_components=tjPixelSize[pixelFormat];
219 jpeg_set_defaults(cinfo);
222 if((env=getenv("TJ_OPTIMIZE"))!=NULL && strlen(env)>0 && !strcmp(env, "1"))
223 cinfo->optimize_coding=TRUE;
224 if((env=getenv("TJ_ARITHMETIC"))!=NULL && strlen(env)>0 && !strcmp(env, "1"))
225 cinfo->arith_code=TRUE;
226 if((env=getenv("TJ_RESTART"))!=NULL && strlen(env)>0)
228 int temp=-1; char tempc=0;
229 if(sscanf(env, "%d%c", &temp, &tempc)>=1 && temp>=0 && temp<=65535)
231 if(toupper(tempc)=='B')
233 cinfo->restart_interval=temp;
234 cinfo->restart_in_rows=0;
237 cinfo->restart_in_rows=temp;
244 jpeg_set_quality(cinfo, jpegQual, TRUE);
245 if(jpegQual>=96 || flags&TJFLAG_ACCURATEDCT) cinfo->dct_method=JDCT_ISLOW;
246 else cinfo->dct_method=JDCT_FASTEST;
248 if(subsamp==TJSAMP_GRAY)
249 jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
250 else if(pixelFormat==TJPF_CMYK)
251 jpeg_set_colorspace(cinfo, JCS_YCCK);
252 else jpeg_set_colorspace(cinfo, JCS_YCbCr);
255 if((env=getenv("TJ_PROGRESSIVE"))!=NULL && strlen(env)>0
256 && !strcmp(env, "1"))
257 jpeg_simple_progression(cinfo);
260 cinfo->comp_info[0].h_samp_factor=tjMCUWidth[subsamp]/8;
261 cinfo->comp_info[1].h_samp_factor=1;
262 cinfo->comp_info[2].h_samp_factor=1;
263 if(cinfo->num_components>3)
264 cinfo->comp_info[3].h_samp_factor=tjMCUWidth[subsamp]/8;
265 cinfo->comp_info[0].v_samp_factor=tjMCUHeight[subsamp]/8;
266 cinfo->comp_info[1].v_samp_factor=1;
267 cinfo->comp_info[2].v_samp_factor=1;
268 if(cinfo->num_components>3)
269 cinfo->comp_info[3].v_samp_factor=tjMCUHeight[subsamp]/8;
274 static int setDecompDefaults(struct jpeg_decompress_struct *dinfo,
275 int pixelFormat, int flags)
282 dinfo->out_color_space=JCS_GRAYSCALE; break;
283 #if JCS_EXTENSIONS==1
285 dinfo->out_color_space=JCS_EXT_RGB; break;
287 dinfo->out_color_space=JCS_EXT_BGR; break;
289 dinfo->out_color_space=JCS_EXT_RGBX; break;
291 dinfo->out_color_space=JCS_EXT_BGRX; break;
293 dinfo->out_color_space=JCS_EXT_XRGB; break;
295 dinfo->out_color_space=JCS_EXT_XBGR; break;
296 #if JCS_ALPHA_EXTENSIONS==1
298 dinfo->out_color_space=JCS_EXT_RGBA; break;
300 dinfo->out_color_space=JCS_EXT_BGRA; break;
302 dinfo->out_color_space=JCS_EXT_ARGB; break;
304 dinfo->out_color_space=JCS_EXT_ABGR; break;
317 dinfo->out_color_space=JCS_RGB; break;
320 dinfo->out_color_space=JCS_CMYK; break;
322 _throw("Unsupported pixel format");
325 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
332 static int getSubsamp(j_decompress_ptr dinfo)
336 /* The sampling factors actually have no meaning with grayscale JPEG files,
337 and in fact it's possible to generate grayscale JPEGs with sampling
338 factors > 1 (even though those sampling factors are ignored by the
339 decompressor.) Thus, we need to treat grayscale as a special case. */
340 if(dinfo->num_components==1 && dinfo->jpeg_color_space==JCS_GRAYSCALE)
343 for(i=0; i<NUMSUBOPT; i++)
345 if(dinfo->num_components==pixelsize[i]
346 || ((dinfo->jpeg_color_space==JCS_YCCK
347 || dinfo->jpeg_color_space==JCS_CMYK)
348 && pixelsize[i]==3 && dinfo->num_components==4))
350 if(dinfo->comp_info[0].h_samp_factor==tjMCUWidth[i]/8
351 && dinfo->comp_info[0].v_samp_factor==tjMCUHeight[i]/8)
354 for(k=1; k<dinfo->num_components; k++)
357 if(dinfo->jpeg_color_space==JCS_YCCK && k==3)
359 href=tjMCUWidth[i]/8; vref=tjMCUHeight[i]/8;
361 if(dinfo->comp_info[k].h_samp_factor==href
362 && dinfo->comp_info[k].v_samp_factor==vref)
365 if(match==dinfo->num_components-1)
376 #ifndef JCS_EXTENSIONS
378 /* Conversion functions to emulate the colorspace extensions. This allows the
379 TurboJPEG wrapper to be used with libjpeg */
381 #define TORGB(PS, ROFFSET, GOFFSET, BOFFSET) { \
382 int rowPad=pitch-width*PS; \
385 unsigned char *endOfRow=src+width*PS; \
386 while(src<endOfRow) \
388 dst[RGB_RED]=src[ROFFSET]; \
389 dst[RGB_GREEN]=src[GOFFSET]; \
390 dst[RGB_BLUE]=src[BOFFSET]; \
391 dst+=RGB_PIXELSIZE; src+=PS; \
397 static unsigned char *toRGB(unsigned char *src, int width, int pitch,
398 int height, int pixelFormat, unsigned char *dst)
400 unsigned char *retval=src;
404 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3
405 retval=dst; TORGB(3, 0, 1, 2);
409 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3
410 retval=dst; TORGB(3, 2, 1, 0);
415 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
416 retval=dst; TORGB(4, 0, 1, 2);
421 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
422 retval=dst; TORGB(4, 2, 1, 0);
427 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
428 retval=dst; TORGB(4, 1, 2, 3);
433 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
434 retval=dst; TORGB(4, 3, 2, 1);
441 #define FROMRGB(PS, ROFFSET, GOFFSET, BOFFSET, SETALPHA) { \
442 int rowPad=pitch-width*PS; \
445 unsigned char *endOfRow=dst+width*PS; \
446 while(dst<endOfRow) \
448 dst[ROFFSET]=src[RGB_RED]; \
449 dst[GOFFSET]=src[RGB_GREEN]; \
450 dst[BOFFSET]=src[RGB_BLUE]; \
452 dst+=PS; src+=RGB_PIXELSIZE; \
458 static void fromRGB(unsigned char *src, unsigned char *dst, int width,
459 int pitch, int height, int pixelFormat)
464 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3
465 FROMRGB(3, 0, 1, 2,);
469 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3
470 FROMRGB(3, 2, 1, 0,);
474 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
475 FROMRGB(4, 0, 1, 2,);
479 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
480 FROMRGB(4, 0, 1, 2, dst[3]=0xFF;);
484 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
485 FROMRGB(4, 2, 1, 0,);
489 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
490 FROMRGB(4, 2, 1, 0, dst[3]=0xFF;); return;
494 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
495 FROMRGB(4, 1, 2, 3,); return;
499 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
500 FROMRGB(4, 1, 2, 3, dst[0]=0xFF;); return;
504 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
505 FROMRGB(4, 3, 2, 1,); return;
509 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
510 FROMRGB(4, 3, 2, 1, dst[0]=0xFF;); return;
519 /* General API functions */
521 DLLEXPORT char* DLLCALL tjGetErrorStr(void)
527 DLLEXPORT int DLLCALL tjDestroy(tjhandle handle)
530 if(setjmp(this->jerr.setjmp_buffer)) return -1;
531 if(this->init&COMPRESS) jpeg_destroy_compress(cinfo);
532 if(this->init&DECOMPRESS) jpeg_destroy_decompress(dinfo);
538 /* These are exposed mainly because Windows can't malloc() and free() across
539 DLL boundaries except when the CRT DLL is used, and we don't use the CRT DLL
540 with turbojpeg.dll for compatibility reasons. However, these functions
541 can potentially be used for other purposes by different implementations. */
543 DLLEXPORT void DLLCALL tjFree(unsigned char *buf)
549 DLLEXPORT unsigned char *DLLCALL tjAlloc(int bytes)
551 return (unsigned char *)malloc(bytes);
557 static tjhandle _tjInitCompress(tjinstance *this)
559 unsigned char buffer[1], *buf=buffer; unsigned long size=1;
561 /* This is also straight out of example.c */
562 this->cinfo.err=jpeg_std_error(&this->jerr.pub);
563 this->jerr.pub.error_exit=my_error_exit;
564 this->jerr.pub.output_message=my_output_message;
565 this->jerr.emit_message=this->jerr.pub.emit_message;
566 this->jerr.pub.emit_message=my_emit_message;
568 if(setjmp(this->jerr.setjmp_buffer))
570 /* If we get here, the JPEG code has signaled an error. */
571 if(this) free(this); return NULL;
574 jpeg_create_compress(&this->cinfo);
575 /* Make an initial call so it will create the destination manager */
576 jpeg_mem_dest_tj(&this->cinfo, &buf, &size, 0);
578 this->init|=COMPRESS;
579 return (tjhandle)this;
582 DLLEXPORT tjhandle DLLCALL tjInitCompress(void)
584 tjinstance *this=NULL;
585 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
587 snprintf(errStr, JMSG_LENGTH_MAX,
588 "tjInitCompress(): Memory allocation failure");
591 MEMZERO(this, sizeof(tjinstance));
592 return _tjInitCompress(this);
596 DLLEXPORT unsigned long DLLCALL tjBufSize(int width, int height,
599 unsigned long retval=0; int mcuw, mcuh, chromasf;
600 if(width<1 || height<1 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT)
601 _throw("tjBufSize(): Invalid argument");
603 /* This allows for rare corner cases in which a JPEG image can actually be
604 larger than the uncompressed input (we wouldn't mention it if it hadn't
606 mcuw=tjMCUWidth[jpegSubsamp];
607 mcuh=tjMCUHeight[jpegSubsamp];
608 chromasf=jpegSubsamp==TJSAMP_GRAY? 0: 4*64/(mcuw*mcuh);
609 retval=PAD(width, mcuw) * PAD(height, mcuh) * (2 + chromasf) + 2048;
615 DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
617 unsigned long retval=0;
618 if(width<1 || height<1)
619 _throw("TJBUFSIZE(): Invalid argument");
621 /* This allows for rare corner cases in which a JPEG image can actually be
622 larger than the uncompressed input (we wouldn't mention it if it hadn't
624 retval=PAD(width, 16) * PAD(height, 16) * 6 + 2048;
631 DLLEXPORT unsigned long DLLCALL tjBufSizeYUV2(int width, int pad, int height,
636 if(subsamp<0 || subsamp>=NUMSUBOPT)
637 _throw("tjBufSizeYUV2(): Invalid argument");
639 nc=(subsamp==TJSAMP_GRAY? 1:3);
642 int pw=tjPlaneWidth(i, width, subsamp);
643 int stride=PAD(pw, pad);
644 int ph=tjPlaneHeight(i, height, subsamp);
645 if(pw<0 || ph<0) return -1;
646 else retval+=stride*ph;
653 DLLEXPORT unsigned long DLLCALL tjBufSizeYUV(int width, int height,
656 return tjBufSizeYUV2(width, 4, height, subsamp);
659 DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
662 return tjBufSizeYUV(width, height, subsamp);
666 DLLEXPORT int tjPlaneWidth(int componentID, int width, int subsamp)
668 int pw, nc, retval=0;
670 if(width<1 || subsamp<0 || subsamp>=TJ_NUMSAMP)
671 _throw("tjPlaneWidth(): Invalid argument");
672 nc=(subsamp==TJSAMP_GRAY? 1:3);
673 if(componentID<0 || componentID>=nc)
674 _throw("tjPlaneWidth(): Invalid argument");
676 pw=PAD(width, tjMCUWidth[subsamp]/8);
680 retval=pw*8/tjMCUWidth[subsamp];
687 DLLEXPORT int tjPlaneHeight(int componentID, int height, int subsamp)
689 int ph, nc, retval=0;
691 if(height<1 || subsamp<0 || subsamp>=TJ_NUMSAMP)
692 _throw("tjPlaneHeight(): Invalid argument");
693 nc=(subsamp==TJSAMP_GRAY? 1:3);
694 if(componentID<0 || componentID>=nc)
695 _throw("tjPlaneHeight(): Invalid argument");
697 ph=PAD(height, tjMCUHeight[subsamp]/8);
701 retval=ph*8/tjMCUHeight[subsamp];
708 DLLEXPORT unsigned long DLLCALL tjPlaneSizeYUV(int componentID, int width,
709 int stride, int height, int subsamp)
711 unsigned long retval=0;
714 if(width<1 || height<1 || subsamp<0 || subsamp>=NUMSUBOPT)
715 _throw("tjPlaneSizeYUV(): Invalid argument");
717 pw=tjPlaneWidth(componentID, width, subsamp);
718 ph=tjPlaneHeight(componentID, height, subsamp);
719 if(pw<0 || ph<0) return -1;
721 if(stride==0) stride=pw;
722 else stride=abs(stride);
724 retval=stride*(ph-1)+pw;
731 DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf,
732 int width, int pitch, int height, int pixelFormat, unsigned char **jpegBuf,
733 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
735 int i, retval=0, alloc=1; JSAMPROW *row_pointer=NULL;
736 #ifndef JCS_EXTENSIONS
737 unsigned char *rgbBuf=NULL;
741 if((this->init&COMPRESS)==0)
742 _throw("tjCompress2(): Instance has not been initialized for compression");
744 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
745 || pixelFormat>=TJ_NUMPF || jpegBuf==NULL || jpegSize==NULL
746 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT || jpegQual<0 || jpegQual>100)
747 _throw("tjCompress2(): Invalid argument");
749 if(setjmp(this->jerr.setjmp_buffer))
751 /* If we get here, the JPEG code has signaled an error. */
756 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
758 #ifndef JCS_EXTENSIONS
759 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK)
761 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
762 if(!rgbBuf) _throw("tjCompress2(): Memory allocation failure");
763 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
764 pitch=width*RGB_PIXELSIZE;
768 cinfo->image_width=width;
769 cinfo->image_height=height;
771 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
772 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
773 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
775 if(flags&TJFLAG_NOREALLOC)
777 alloc=0; *jpegSize=tjBufSize(width, height, jpegSubsamp);
779 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
780 if(setCompDefaults(cinfo, pixelFormat, jpegSubsamp, jpegQual, flags)==-1)
783 jpeg_start_compress(cinfo, TRUE);
784 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
785 _throw("tjCompress2(): Memory allocation failure");
786 for(i=0; i<height; i++)
788 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
789 else row_pointer[i]=&srcBuf[i*pitch];
791 while(cinfo->next_scanline<cinfo->image_height)
793 jpeg_write_scanlines(cinfo, &row_pointer[cinfo->next_scanline],
794 cinfo->image_height-cinfo->next_scanline);
796 jpeg_finish_compress(cinfo);
799 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
800 #ifndef JCS_EXTENSIONS
801 if(rgbBuf) free(rgbBuf);
803 if(row_pointer) free(row_pointer);
804 if(this->jerr.warning) retval=-1;
808 DLLEXPORT int DLLCALL tjCompress(tjhandle handle, unsigned char *srcBuf,
809 int width, int pitch, int height, int pixelSize, unsigned char *jpegBuf,
810 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
812 int retval=0; unsigned long size;
815 size=tjBufSizeYUV(width, height, jpegSubsamp);
816 retval=tjEncodeYUV2(handle, srcBuf, width, pitch, height,
817 getPixelFormat(pixelSize, flags), jpegBuf, jpegSubsamp, flags);
821 retval=tjCompress2(handle, srcBuf, width, pitch, height,
822 getPixelFormat(pixelSize, flags), &jpegBuf, &size, jpegSubsamp, jpegQual,
823 flags|TJFLAG_NOREALLOC);
830 DLLEXPORT int DLLCALL tjEncodeYUVPlanes(tjhandle handle, unsigned char *srcBuf,
831 int width, int pitch, int height, int pixelFormat, unsigned char **dstPlanes,
832 int *strides, int subsamp, int flags)
834 int i, retval=0; JSAMPROW *row_pointer=NULL;
835 JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS];
836 JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
837 JSAMPROW *outbuf[MAX_COMPONENTS];
838 int row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS];
840 jpeg_component_info *compptr;
841 #ifndef JCS_EXTENSIONS
842 unsigned char *rgbBuf=NULL;
845 getcinstance(handle);
847 for(i=0; i<MAX_COMPONENTS; i++)
849 tmpbuf[i]=NULL; _tmpbuf[i]=NULL;
850 tmpbuf2[i]=NULL; _tmpbuf2[i]=NULL; outbuf[i]=NULL;
853 if((this->init&COMPRESS)==0)
854 _throw("tjEncodeYUVPlanes(): Instance has not been initialized for compression");
856 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
857 || pixelFormat>=TJ_NUMPF || !dstPlanes || !dstPlanes[0] || subsamp<0
858 || subsamp>=NUMSUBOPT)
859 _throw("tjEncodeYUVPlanes(): Invalid argument");
860 if(subsamp!=TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2]))
861 _throw("tjEncodeYUVPlanes(): Invalid argument");
863 if(setjmp(this->jerr.setjmp_buffer))
865 /* If we get here, the JPEG code has signaled an error. */
870 if(pixelFormat==TJPF_CMYK)
871 _throw("tjEncodeYUVPlanes(): Cannot generate YUV images from CMYK pixels");
873 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
875 #ifndef JCS_EXTENSIONS
876 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK)
878 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
879 if(!rgbBuf) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
880 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
881 pitch=width*RGB_PIXELSIZE;
885 cinfo->image_width=width;
886 cinfo->image_height=height;
888 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
889 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
890 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
892 if(setCompDefaults(cinfo, pixelFormat, subsamp, -1, flags)==-1) return -1;
894 /* Execute only the parts of jpeg_start_compress() that we need. If we
895 were to call the whole jpeg_start_compress() function, then it would try
896 to write the file headers, which could overflow the output buffer if the
897 YUV image were very small. */
898 if(cinfo->global_state!=CSTATE_START)
899 _throw("tjEncodeYUVPlanes(): libjpeg API is in the wrong state");
900 (*cinfo->err->reset_error_mgr)((j_common_ptr)cinfo);
901 jinit_c_master_control(cinfo, FALSE);
902 jinit_color_converter(cinfo);
903 jinit_downsampler(cinfo);
904 (*cinfo->cconvert->start_pass)(cinfo);
906 pw0=PAD(width, cinfo->max_h_samp_factor);
907 ph0=PAD(height, cinfo->max_v_samp_factor);
909 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL)
910 _throw("tjEncodeYUVPlanes(): Memory allocation failure");
911 for(i=0; i<height; i++)
913 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch];
914 else row_pointer[i]=&srcBuf[i*pitch];
917 for(i=height; i<ph0; i++) row_pointer[i]=row_pointer[height-1];
919 for(i=0; i<cinfo->num_components; i++)
921 compptr=&cinfo->comp_info[i];
922 _tmpbuf[i]=(JSAMPLE *)malloc(
923 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
924 /compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16);
925 if(!_tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
926 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor);
927 if(!tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
928 for(row=0; row<cinfo->max_v_samp_factor; row++)
930 unsigned char *_tmpbuf_aligned=
931 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
932 tmpbuf[i][row]=&_tmpbuf_aligned[
933 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE)
934 /compptr->h_samp_factor, 16) * row];
936 _tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
937 * compptr->v_samp_factor + 16);
938 if(!_tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
939 tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
940 if(!tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
941 for(row=0; row<compptr->v_samp_factor; row++)
943 unsigned char *_tmpbuf2_aligned=
944 (unsigned char *)PAD((size_t)_tmpbuf2[i], 16);
945 tmpbuf2[i][row]=&_tmpbuf2_aligned[
946 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
948 pw[i]=pw0*compptr->h_samp_factor/cinfo->max_h_samp_factor;
949 ph[i]=ph0*compptr->v_samp_factor/cinfo->max_v_samp_factor;
950 outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]);
951 if(!outbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure");
953 for(row=0; row<ph[i]; row++)
956 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
960 for(row=0; row<ph0; row+=cinfo->max_v_samp_factor)
962 (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0,
963 cinfo->max_v_samp_factor);
964 (cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0);
965 for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++)
966 jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i],
967 row*compptr->v_samp_factor/cinfo->max_v_samp_factor,
968 compptr->v_samp_factor, pw[i]);
970 cinfo->next_scanline+=height;
971 jpeg_abort_compress(cinfo);
974 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
975 #ifndef JCS_EXTENSIONS
976 if(rgbBuf) free(rgbBuf);
978 if(row_pointer) free(row_pointer);
979 for(i=0; i<MAX_COMPONENTS; i++)
981 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
982 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
983 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]);
984 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]);
985 if(outbuf[i]!=NULL) free(outbuf[i]);
987 if(this->jerr.warning) retval=-1;
991 DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, unsigned char *srcBuf,
992 int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
993 int pad, int subsamp, int flags)
995 unsigned char *dstPlanes[3];
996 int pw0, ph0, strides[3], retval=-1;
998 if(width<=0 || height<=0 || dstBuf==NULL || pad<0 || !isPow2(pad)
999 || subsamp<0 || subsamp>=NUMSUBOPT)
1000 _throw("tjEncodeYUV3(): Invalid argument");
1002 pw0=tjPlaneWidth(0, width, subsamp);
1003 ph0=tjPlaneHeight(0, height, subsamp);
1004 dstPlanes[0]=dstBuf;
1005 strides[0]=PAD(pw0, pad);
1006 if(subsamp==TJSAMP_GRAY)
1008 strides[1]=strides[2]=0;
1009 dstPlanes[1]=dstPlanes[2]=NULL;
1013 int pw1=tjPlaneWidth(1, width, subsamp);
1014 int ph1=tjPlaneHeight(1, height, subsamp);
1015 strides[1]=strides[2]=PAD(pw1, pad);
1016 dstPlanes[1]=dstPlanes[0]+strides[0]*ph0;
1017 dstPlanes[2]=dstPlanes[1]+strides[1]*ph1;
1020 return tjEncodeYUVPlanes(handle, srcBuf, width, pitch, height, pixelFormat,
1021 dstPlanes, strides, subsamp, flags);
1027 DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
1028 int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf,
1029 int subsamp, int flags)
1031 return tjEncodeYUV3(handle, srcBuf, width, pitch, height, pixelFormat,
1032 dstBuf, 4, subsamp, flags);
1035 DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf,
1036 int width, int pitch, int height, int pixelSize, unsigned char *dstBuf,
1037 int subsamp, int flags)
1039 return tjEncodeYUV2(handle, srcBuf, width, pitch, height,
1040 getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags);
1044 DLLEXPORT int DLLCALL tjCompressFromYUVPlanes(tjhandle handle,
1045 unsigned char **srcPlanes, int width, int *strides, int height, int subsamp,
1046 unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual, int flags)
1048 int i, row, retval=0, alloc=1; JSAMPROW *inbuf[MAX_COMPONENTS];
1049 int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS],
1050 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
1051 JSAMPLE *_tmpbuf=NULL, *ptr; JSAMPROW *tmpbuf[MAX_COMPONENTS];
1053 getcinstance(handle)
1055 for(i=0; i<MAX_COMPONENTS; i++)
1057 tmpbuf[i]=NULL; inbuf[i]=NULL;
1060 if((this->init&COMPRESS)==0)
1061 _throw("tjCompressFromYUVPlanes(): Instance has not been initialized for compression");
1063 if(!srcPlanes || !srcPlanes[0] || width<=0 || height<=0 || subsamp<0
1064 || subsamp>=NUMSUBOPT || jpegBuf==NULL || jpegSize==NULL || jpegQual<0
1066 _throw("tjCompressFromYUVPlanes(): Invalid argument");
1067 if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2]))
1068 _throw("tjCompressFromYUVPlanes(): Invalid argument");
1070 if(setjmp(this->jerr.setjmp_buffer))
1072 /* If we get here, the JPEG code has signaled an error. */
1077 cinfo->image_width=width;
1078 cinfo->image_height=height;
1080 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1081 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1082 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
1084 if(flags&TJFLAG_NOREALLOC)
1086 alloc=0; *jpegSize=tjBufSize(width, height, subsamp);
1088 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
1089 if(setCompDefaults(cinfo, TJPF_RGB, subsamp, jpegQual, flags)==-1)
1091 cinfo->raw_data_in=TRUE;
1093 jpeg_start_compress(cinfo, TRUE);
1094 for(i=0; i<cinfo->num_components; i++)
1096 jpeg_component_info *compptr=&cinfo->comp_info[i];
1098 iw[i]=compptr->width_in_blocks*DCTSIZE;
1099 ih=compptr->height_in_blocks*DCTSIZE;
1100 pw[i]=PAD(cinfo->image_width, cinfo->max_h_samp_factor)
1101 *compptr->h_samp_factor/cinfo->max_h_samp_factor;
1102 ph[i]=PAD(cinfo->image_height, cinfo->max_v_samp_factor)
1103 *compptr->v_samp_factor/cinfo->max_v_samp_factor;
1104 if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1;
1105 th[i]=compptr->v_samp_factor*DCTSIZE;
1106 tmpbufsize+=iw[i]*th[i];
1107 if((inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]))==NULL)
1108 _throw("tjCompressFromYUVPlanes(): Memory allocation failure");
1110 for(row=0; row<ph[i]; row++)
1113 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
1118 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
1119 _throw("tjCompressFromYUVPlanes(): Memory allocation failure");
1121 for(i=0; i<cinfo->num_components; i++)
1123 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
1124 _throw("tjCompressFromYUVPlanes(): Memory allocation failure");
1125 for(row=0; row<th[i]; row++)
1133 for(row=0; row<(int)cinfo->image_height;
1134 row+=cinfo->max_v_samp_factor*DCTSIZE)
1136 JSAMPARRAY yuvptr[MAX_COMPONENTS];
1137 int crow[MAX_COMPONENTS];
1138 for(i=0; i<cinfo->num_components; i++)
1140 jpeg_component_info *compptr=&cinfo->comp_info[i];
1141 crow[i]=row*compptr->v_samp_factor/cinfo->max_v_samp_factor;
1145 for(j=0; j<min(th[i], ph[i]-crow[i]); j++)
1147 memcpy(tmpbuf[i][j], inbuf[i][crow[i]+j], pw[i]);
1148 /* Duplicate last sample in row to fill out MCU */
1149 for(k=pw[i]; k<iw[i]; k++) tmpbuf[i][j][k]=tmpbuf[i][j][pw[i]-1];
1151 /* Duplicate last row to fill out MCU */
1152 for(j=ph[i]-crow[i]; j<th[i]; j++)
1153 memcpy(tmpbuf[i][j], tmpbuf[i][ph[i]-crow[i]-1], iw[i]);
1154 yuvptr[i]=tmpbuf[i];
1157 yuvptr[i]=&inbuf[i][crow[i]];
1159 jpeg_write_raw_data(cinfo, yuvptr, cinfo->max_v_samp_factor*DCTSIZE);
1161 jpeg_finish_compress(cinfo);
1164 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
1165 for(i=0; i<MAX_COMPONENTS; i++)
1167 if(tmpbuf[i]) free(tmpbuf[i]);
1168 if(inbuf[i]) free(inbuf[i]);
1170 if(_tmpbuf) free(_tmpbuf);
1171 if(this->jerr.warning) retval=-1;
1175 DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle, unsigned char *srcBuf,
1176 int width, int pad, int height, int subsamp, unsigned char **jpegBuf,
1177 unsigned long *jpegSize, int jpegQual, int flags)
1179 unsigned char *srcPlanes[3];
1180 int pw0, ph0, strides[3], retval=-1;
1182 if(srcBuf==NULL || width<=0 || pad<1 || height<=0 || subsamp<0
1183 || subsamp>=NUMSUBOPT)
1184 _throw("tjCompressFromYUV(): Invalid argument");
1186 pw0=tjPlaneWidth(0, width, subsamp);
1187 ph0=tjPlaneHeight(0, height, subsamp);
1188 srcPlanes[0]=srcBuf;
1189 strides[0]=PAD(pw0, pad);
1190 if(subsamp==TJSAMP_GRAY)
1192 strides[1]=strides[2]=0;
1193 srcPlanes[1]=srcPlanes[2]=NULL;
1197 int pw1=tjPlaneWidth(1, width, subsamp);
1198 int ph1=tjPlaneHeight(1, height, subsamp);
1199 strides[1]=strides[2]=PAD(pw1, pad);
1200 srcPlanes[1]=srcPlanes[0]+strides[0]*ph0;
1201 srcPlanes[2]=srcPlanes[1]+strides[1]*ph1;
1204 return tjCompressFromYUVPlanes(handle, srcPlanes, width, strides, height,
1205 subsamp, jpegBuf, jpegSize, jpegQual, flags);
1214 static tjhandle _tjInitDecompress(tjinstance *this)
1216 unsigned char buffer[1];
1218 /* This is also straight out of example.c */
1219 this->dinfo.err=jpeg_std_error(&this->jerr.pub);
1220 this->jerr.pub.error_exit=my_error_exit;
1221 this->jerr.pub.output_message=my_output_message;
1222 this->jerr.emit_message=this->jerr.pub.emit_message;
1223 this->jerr.pub.emit_message=my_emit_message;
1225 if(setjmp(this->jerr.setjmp_buffer))
1227 /* If we get here, the JPEG code has signaled an error. */
1228 if(this) free(this); return NULL;
1231 jpeg_create_decompress(&this->dinfo);
1232 /* Make an initial call so it will create the source manager */
1233 jpeg_mem_src_tj(&this->dinfo, buffer, 1);
1235 this->init|=DECOMPRESS;
1236 return (tjhandle)this;
1239 DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
1242 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
1244 snprintf(errStr, JMSG_LENGTH_MAX,
1245 "tjInitDecompress(): Memory allocation failure");
1248 MEMZERO(this, sizeof(tjinstance));
1249 return _tjInitDecompress(this);
1253 DLLEXPORT int DLLCALL tjDecompressHeader3(tjhandle handle,
1254 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
1255 int *jpegSubsamp, int *jpegColorspace)
1259 getdinstance(handle);
1260 if((this->init&DECOMPRESS)==0)
1261 _throw("tjDecompressHeader3(): Instance has not been initialized for decompression");
1263 if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL
1264 || jpegSubsamp==NULL || jpegColorspace==NULL)
1265 _throw("tjDecompressHeader3(): Invalid argument");
1267 if(setjmp(this->jerr.setjmp_buffer))
1269 /* If we get here, the JPEG code has signaled an error. */
1273 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1274 jpeg_read_header(dinfo, TRUE);
1276 *width=dinfo->image_width;
1277 *height=dinfo->image_height;
1278 *jpegSubsamp=getSubsamp(dinfo);
1279 switch(dinfo->jpeg_color_space)
1281 case JCS_GRAYSCALE: *jpegColorspace=TJCS_GRAY; break;
1282 case JCS_RGB: *jpegColorspace=TJCS_RGB; break;
1283 case JCS_YCbCr: *jpegColorspace=TJCS_YCbCr; break;
1284 case JCS_CMYK: *jpegColorspace=TJCS_CMYK; break;
1285 case JCS_YCCK: *jpegColorspace=TJCS_YCCK; break;
1286 default: *jpegColorspace=-1; break;
1289 jpeg_abort_decompress(dinfo);
1292 _throw("tjDecompressHeader3(): Could not determine subsampling type for JPEG image");
1293 if(*jpegColorspace<0)
1294 _throw("tjDecompressHeader3(): Could not determine colorspace of JPEG image");
1295 if(*width<1 || *height<1)
1296 _throw("tjDecompressHeader3(): Invalid data returned in header");
1299 if(this->jerr.warning) retval=-1;
1303 DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle,
1304 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height,
1308 return tjDecompressHeader3(handle, jpegBuf, jpegSize, width, height,
1309 jpegSubsamp, &jpegColorspace);
1312 DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle,
1313 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height)
1316 return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height,
1321 DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors)
1323 if(numscalingfactors==NULL)
1325 snprintf(errStr, JMSG_LENGTH_MAX,
1326 "tjGetScalingFactors(): Invalid argument");
1330 *numscalingfactors=NUMSF;
1331 return (tjscalingfactor *)sf;
1335 DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, unsigned char *jpegBuf,
1336 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
1337 int height, int pixelFormat, int flags)
1339 int i, retval=0; JSAMPROW *row_pointer=NULL;
1340 int jpegwidth, jpegheight, scaledw, scaledh;
1341 #ifndef JCS_EXTENSIONS
1342 unsigned char *rgbBuf=NULL;
1343 unsigned char *_dstBuf=NULL; int _pitch=0;
1346 getdinstance(handle);
1347 if((this->init&DECOMPRESS)==0)
1348 _throw("tjDecompress2(): Instance has not been initialized for decompression");
1350 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0
1351 || height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF)
1352 _throw("tjDecompress2(): Invalid argument");
1354 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1355 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1356 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
1358 if(setjmp(this->jerr.setjmp_buffer))
1360 /* If we get here, the JPEG code has signaled an error. */
1365 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1366 jpeg_read_header(dinfo, TRUE);
1367 if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
1369 retval=-1; goto bailout;
1372 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
1374 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
1375 if(width==0) width=jpegwidth;
1376 if(height==0) height=jpegheight;
1377 for(i=0; i<NUMSF; i++)
1379 scaledw=TJSCALED(jpegwidth, sf[i]);
1380 scaledh=TJSCALED(jpegheight, sf[i]);
1381 if(scaledw<=width && scaledh<=height)
1385 _throw("tjDecompress2(): Could not scale down to desired image dimensions");
1386 width=scaledw; height=scaledh;
1387 dinfo->scale_num=sf[i].num;
1388 dinfo->scale_denom=sf[i].denom;
1390 jpeg_start_decompress(dinfo);
1391 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
1393 #ifndef JCS_EXTENSIONS
1394 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK &&
1395 (RGB_RED!=tjRedOffset[pixelFormat] ||
1396 RGB_GREEN!=tjGreenOffset[pixelFormat] ||
1397 RGB_BLUE!=tjBlueOffset[pixelFormat] ||
1398 RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
1400 rgbBuf=(unsigned char *)malloc(width*height*3);
1401 if(!rgbBuf) _throw("tjDecompress2(): Memory allocation failure");
1402 _pitch=pitch; pitch=width*3;
1403 _dstBuf=dstBuf; dstBuf=rgbBuf;
1407 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
1408 *dinfo->output_height))==NULL)
1409 _throw("tjDecompress2(): Memory allocation failure");
1410 for(i=0; i<(int)dinfo->output_height; i++)
1412 if(flags&TJFLAG_BOTTOMUP)
1413 row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*pitch];
1414 else row_pointer[i]=&dstBuf[i*pitch];
1416 while(dinfo->output_scanline<dinfo->output_height)
1418 jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline],
1419 dinfo->output_height-dinfo->output_scanline);
1421 jpeg_finish_decompress(dinfo);
1423 #ifndef JCS_EXTENSIONS
1424 fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
1428 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
1429 #ifndef JCS_EXTENSIONS
1430 if(rgbBuf) free(rgbBuf);
1432 if(row_pointer) free(row_pointer);
1433 if(this->jerr.warning) retval=-1;
1437 DLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf,
1438 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch,
1439 int height, int pixelSize, int flags)
1442 return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags);
1444 return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch,
1445 height, getPixelFormat(pixelSize, flags), flags);
1449 static int setDecodeDefaults(struct jpeg_decompress_struct *dinfo,
1450 int pixelFormat, int subsamp, int flags)
1454 dinfo->scale_num=dinfo->scale_denom=1;
1456 if(subsamp==TJSAMP_GRAY)
1458 dinfo->num_components=dinfo->comps_in_scan=1;
1459 dinfo->jpeg_color_space=JCS_GRAYSCALE;
1463 dinfo->num_components=dinfo->comps_in_scan=3;
1464 dinfo->jpeg_color_space=JCS_YCbCr;
1467 dinfo->comp_info=(jpeg_component_info *)
1468 (*dinfo->mem->alloc_small)((j_common_ptr)dinfo, JPOOL_IMAGE,
1469 dinfo->num_components*sizeof(jpeg_component_info));
1471 for(i=0; i<dinfo->num_components; i++)
1473 jpeg_component_info *compptr=&dinfo->comp_info[i];
1474 compptr->h_samp_factor=(i==0)? tjMCUWidth[subsamp]/8:1;
1475 compptr->v_samp_factor=(i==0)? tjMCUHeight[subsamp]/8:1;
1476 compptr->component_index=i;
1477 compptr->component_id=i+1;
1478 compptr->quant_tbl_no=compptr->dc_tbl_no=compptr->ac_tbl_no=
1480 dinfo->cur_comp_info[i]=compptr;
1482 dinfo->data_precision=8;
1485 if(dinfo->quant_tbl_ptrs[i]==NULL)
1486 dinfo->quant_tbl_ptrs[i]=jpeg_alloc_quant_table((j_common_ptr)dinfo);
1493 int my_read_markers(j_decompress_ptr dinfo)
1495 return JPEG_REACHED_SOS;
1498 void my_reset_marker_reader(j_decompress_ptr dinfo)
1502 DLLEXPORT int DLLCALL tjDecodeYUVPlanes(tjhandle handle,
1503 unsigned char **srcPlanes, int *strides, int subsamp, unsigned char *dstBuf,
1504 int width, int pitch, int height, int pixelFormat, int flags)
1506 int i, retval=0; JSAMPROW *row_pointer=NULL;
1507 JSAMPLE *_tmpbuf[MAX_COMPONENTS];
1508 JSAMPROW *tmpbuf[MAX_COMPONENTS], *inbuf[MAX_COMPONENTS];
1509 int row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS];
1511 jpeg_component_info *compptr;
1512 #ifndef JCS_EXTENSIONS
1513 unsigned char *rgbBuf=NULL;
1514 unsigned char *_dstBuf=NULL; int _pitch=0;
1516 int (*old_read_markers)(j_decompress_ptr);
1517 void (*old_reset_marker_reader)(j_decompress_ptr);
1519 getdinstance(handle);
1521 for(i=0; i<MAX_COMPONENTS; i++)
1523 tmpbuf[i]=NULL; _tmpbuf[i]=NULL; inbuf[i]=NULL;
1526 if((this->init&DECOMPRESS)==0)
1527 _throw("tjDecodeYUVPlanes(): Instance has not been initialized for decompression");
1529 if(!srcPlanes || !srcPlanes[0] || subsamp<0 || subsamp>=NUMSUBOPT
1530 || dstBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0
1531 || pixelFormat>=TJ_NUMPF)
1532 _throw("tjDecodeYUVPlanes(): Invalid argument");
1533 if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2]))
1534 _throw("tjDecodeYUVPlanes(): Invalid argument");
1536 if(setjmp(this->jerr.setjmp_buffer))
1538 /* If we get here, the JPEG code has signaled an error. */
1543 if(pixelFormat==TJPF_CMYK)
1544 _throw("tjDecodeYUVPlanes(): Cannot decode YUV images into CMYK pixels.");
1546 if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
1547 dinfo->image_width=width;
1548 dinfo->image_height=height;
1550 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1551 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1552 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
1554 if(setDecodeDefaults(dinfo, pixelFormat, subsamp, flags)==-1)
1556 retval=-1; goto bailout;
1558 old_read_markers=dinfo->marker->read_markers;
1559 dinfo->marker->read_markers=my_read_markers;
1560 old_reset_marker_reader=dinfo->marker->reset_marker_reader;
1561 dinfo->marker->reset_marker_reader=my_reset_marker_reader;
1562 jpeg_read_header(dinfo, TRUE);
1563 dinfo->marker->read_markers=old_read_markers;
1564 dinfo->marker->reset_marker_reader=old_reset_marker_reader;
1566 if(setDecompDefaults(dinfo, pixelFormat, flags)==-1)
1568 retval=-1; goto bailout;
1570 dinfo->do_fancy_upsampling=FALSE;
1571 dinfo->Se=DCTSIZE2-1;
1572 jinit_master_decompress(dinfo);
1573 (*dinfo->upsample->start_pass)(dinfo);
1575 pw0=PAD(width, dinfo->max_h_samp_factor);
1576 ph0=PAD(height, dinfo->max_v_samp_factor);
1578 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
1580 #ifndef JCS_EXTENSIONS
1581 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK &&
1582 (RGB_RED!=tjRedOffset[pixelFormat] ||
1583 RGB_GREEN!=tjGreenOffset[pixelFormat] ||
1584 RGB_BLUE!=tjBlueOffset[pixelFormat] ||
1585 RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
1587 rgbBuf=(unsigned char *)malloc(width*height*3);
1588 if(!rgbBuf) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1589 _pitch=pitch; pitch=width*3;
1590 _dstBuf=dstBuf; dstBuf=rgbBuf;
1594 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL)
1595 _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1596 for(i=0; i<height; i++)
1598 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&dstBuf[(height-i-1)*pitch];
1599 else row_pointer[i]=&dstBuf[i*pitch];
1602 for(i=height; i<ph0; i++) row_pointer[i]=row_pointer[height-1];
1604 for(i=0; i<dinfo->num_components; i++)
1606 compptr=&dinfo->comp_info[i];
1607 _tmpbuf[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16)
1608 * compptr->v_samp_factor + 16);
1609 if(!_tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1610 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor);
1611 if(!tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1612 for(row=0; row<compptr->v_samp_factor; row++)
1614 unsigned char *_tmpbuf_aligned=
1615 (unsigned char *)PAD((size_t)_tmpbuf[i], 16);
1616 tmpbuf[i][row]=&_tmpbuf_aligned[
1617 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row];
1619 pw[i]=pw0*compptr->h_samp_factor/dinfo->max_h_samp_factor;
1620 ph[i]=ph0*compptr->v_samp_factor/dinfo->max_v_samp_factor;
1621 inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]);
1622 if(!inbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure");
1624 for(row=0; row<ph[i]; row++)
1627 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
1631 for(row=0; row<ph0; row+=dinfo->max_v_samp_factor)
1633 JDIMENSION inrow=0, outrow=0;
1634 for(i=0, compptr=dinfo->comp_info; i<dinfo->num_components; i++, compptr++)
1635 jcopy_sample_rows(inbuf[i],
1636 row*compptr->v_samp_factor/dinfo->max_v_samp_factor, tmpbuf[i], 0,
1637 compptr->v_samp_factor, pw[i]);
1638 (dinfo->upsample->upsample)(dinfo, tmpbuf, &inrow,
1639 dinfo->max_v_samp_factor, &row_pointer[row], &outrow,
1640 dinfo->max_v_samp_factor);
1642 jpeg_abort_decompress(dinfo);
1644 #ifndef JCS_EXTENSIONS
1645 fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
1649 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
1650 #ifndef JCS_EXTENSIONS
1651 if(rgbBuf) free(rgbBuf);
1653 if(row_pointer) free(row_pointer);
1654 for(i=0; i<MAX_COMPONENTS; i++)
1656 if(tmpbuf[i]!=NULL) free(tmpbuf[i]);
1657 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]);
1658 if(inbuf[i]!=NULL) free(inbuf[i]);
1660 if(this->jerr.warning) retval=-1;
1664 DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, unsigned char *srcBuf,
1665 int pad, int subsamp, unsigned char *dstBuf, int width, int pitch,
1666 int height, int pixelFormat, int flags)
1668 unsigned char *srcPlanes[3];
1669 int pw0, ph0, strides[3], retval=-1;
1671 if(srcBuf==NULL || pad<0 || !isPow2(pad) || subsamp<0 || subsamp>=NUMSUBOPT
1672 || width<=0 || height<=0)
1673 _throw("tjDecodeYUV(): Invalid argument");
1675 pw0=tjPlaneWidth(0, width, subsamp);
1676 ph0=tjPlaneHeight(0, height, subsamp);
1677 srcPlanes[0]=srcBuf;
1678 strides[0]=PAD(pw0, pad);
1679 if(subsamp==TJSAMP_GRAY)
1681 strides[1]=strides[2]=0;
1682 srcPlanes[1]=srcPlanes[2]=NULL;
1686 int pw1=tjPlaneWidth(1, width, subsamp);
1687 int ph1=tjPlaneHeight(1, height, subsamp);
1688 strides[1]=strides[2]=PAD(pw1, pad);
1689 srcPlanes[1]=srcPlanes[0]+strides[0]*ph0;
1690 srcPlanes[2]=srcPlanes[1]+strides[1]*ph1;
1693 return tjDecodeYUVPlanes(handle, srcPlanes, strides, subsamp, dstBuf, width,
1694 pitch, height, pixelFormat, flags);
1700 DLLEXPORT int DLLCALL tjDecompressToYUVPlanes(tjhandle handle,
1701 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char **dstPlanes,
1702 int width, int *strides, int height, int flags)
1704 int i, sfi, row, retval=0; JSAMPROW *outbuf[MAX_COMPONENTS];
1705 int jpegwidth, jpegheight, jpegSubsamp, scaledw, scaledh;
1706 int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS],
1707 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
1708 JSAMPLE *_tmpbuf=NULL, *ptr; JSAMPROW *tmpbuf[MAX_COMPONENTS];
1711 getdinstance(handle);
1713 for(i=0; i<MAX_COMPONENTS; i++)
1715 tmpbuf[i]=NULL; outbuf[i]=NULL;
1718 if((this->init&DECOMPRESS)==0)
1719 _throw("tjDecompressToYUVPlanes(): Instance has not been initialized for decompression");
1721 if(jpegBuf==NULL || jpegSize<=0 || !dstPlanes || !dstPlanes[0] || width<0
1723 _throw("tjDecompressToYUVPlanes(): Invalid argument");
1725 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1726 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1727 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
1729 if(setjmp(this->jerr.setjmp_buffer))
1731 /* If we get here, the JPEG code has signaled an error. */
1736 if(!this->headerRead)
1738 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1739 jpeg_read_header(dinfo, TRUE);
1742 jpegSubsamp=getSubsamp(dinfo);
1744 _throw("tjDecompressToYUVPlanes(): Could not determine subsampling type for JPEG image");
1746 if(jpegSubsamp!=TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2]))
1747 _throw("tjDecompressToYUVPlanes(): Invalid argument");
1749 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
1750 if(width==0) width=jpegwidth;
1751 if(height==0) height=jpegheight;
1752 for(i=0; i<NUMSF; i++)
1754 scaledw=TJSCALED(jpegwidth, sf[i]);
1755 scaledh=TJSCALED(jpegheight, sf[i]);
1756 if(scaledw<=width && scaledh<=height)
1760 _throw("tjDecompressToYUVPlanes(): Could not scale down to desired image dimensions");
1761 if(dinfo->num_components>3)
1762 _throw("tjDecompressToYUVPlanes(): JPEG image must have 3 or fewer components");
1764 width=scaledw; height=scaledh;
1765 dinfo->scale_num=sf[i].num;
1766 dinfo->scale_denom=sf[i].denom;
1768 jpeg_calc_output_dimensions(dinfo);
1770 dctsize=DCTSIZE*sf[sfi].num/sf[sfi].denom;
1772 for(i=0; i<dinfo->num_components; i++)
1774 jpeg_component_info *compptr=&dinfo->comp_info[i];
1776 iw[i]=compptr->width_in_blocks*dctsize;
1777 ih=compptr->height_in_blocks*dctsize;
1778 pw[i]=PAD(dinfo->output_width, dinfo->max_h_samp_factor)
1779 *compptr->h_samp_factor/dinfo->max_h_samp_factor;
1780 ph[i]=PAD(dinfo->output_height, dinfo->max_v_samp_factor)
1781 *compptr->v_samp_factor/dinfo->max_v_samp_factor;
1782 if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1;
1783 th[i]=compptr->v_samp_factor*dctsize;
1784 tmpbufsize+=iw[i]*th[i];
1785 if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]))==NULL)
1786 _throw("tjDecompressToYUVPlanes(): Memory allocation failure");
1788 for(row=0; row<ph[i]; row++)
1791 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i];
1796 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
1797 _throw("tjDecompressToYUVPlanes(): Memory allocation failure");
1799 for(i=0; i<dinfo->num_components; i++)
1801 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
1802 _throw("tjDecompressToYUVPlanes(): Memory allocation failure");
1803 for(row=0; row<th[i]; row++)
1811 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE;
1812 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST;
1813 dinfo->raw_data_out=TRUE;
1815 jpeg_start_decompress(dinfo);
1816 for(row=0; row<(int)dinfo->output_height;
1817 row+=dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size)
1819 JSAMPARRAY yuvptr[MAX_COMPONENTS];
1820 int crow[MAX_COMPONENTS];
1821 for(i=0; i<dinfo->num_components; i++)
1823 jpeg_component_info *compptr=&dinfo->comp_info[i];
1824 if(jpegSubsamp==TJ_420)
1826 /* When 4:2:0 subsampling is used with IDCT scaling, libjpeg will try
1827 to be clever and use the IDCT to perform upsampling on the U and V
1828 planes. For instance, if the output image is to be scaled by 1/2
1829 relative to the JPEG image, then the scaling factor and upsampling
1830 effectively cancel each other, so a normal 8x8 IDCT can be used.
1831 However, this is not desirable when using the decompress-to-YUV
1832 functionality in TurboJPEG, since we want to output the U and V
1833 planes in their subsampled form. Thus, we have to override some
1834 internal libjpeg parameters to force it to use the "scaled" IDCT
1835 functions on the U and V planes. */
1836 compptr->_DCT_scaled_size=dctsize;
1837 compptr->MCU_sample_width=tjMCUWidth[jpegSubsamp]*
1838 sf[sfi].num/sf[sfi].denom*
1839 compptr->v_samp_factor/dinfo->max_v_samp_factor;
1840 dinfo->idct->inverse_DCT[i] = dinfo->idct->inverse_DCT[0];
1842 crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor;
1843 if(usetmpbuf) yuvptr[i]=tmpbuf[i];
1844 else yuvptr[i]=&outbuf[i][crow[i]];
1846 jpeg_read_raw_data(dinfo, yuvptr,
1847 dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size);
1851 for(i=0; i<dinfo->num_components; i++)
1853 for(j=0; j<min(th[i], ph[i]-crow[i]); j++)
1855 memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], pw[i]);
1860 jpeg_finish_decompress(dinfo);
1863 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
1864 for(i=0; i<MAX_COMPONENTS; i++)
1866 if(tmpbuf[i]) free(tmpbuf[i]);
1867 if(outbuf[i]) free(outbuf[i]);
1869 if(_tmpbuf) free(_tmpbuf);
1870 if(this->jerr.warning) retval=-1;
1874 DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle,
1875 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
1876 int width, int pad, int height, int flags)
1878 unsigned char *dstPlanes[3];
1879 int pw0, ph0, strides[3], retval=-1, jpegSubsamp=-1;
1880 int i, jpegwidth, jpegheight, scaledw, scaledh;
1882 getdinstance(handle);
1884 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pad<1
1885 || !isPow2(pad) || height<0)
1886 _throw("tjDecompressToYUV2(): Invalid argument");
1888 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1889 jpeg_read_header(dinfo, TRUE);
1890 jpegSubsamp=getSubsamp(dinfo);
1892 _throw("tjDecompressToYUV2(): Could not determine subsampling type for JPEG image");
1894 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height;
1895 if(width==0) width=jpegwidth;
1896 if(height==0) height=jpegheight;
1898 for(i=0; i<NUMSF; i++)
1900 scaledw=TJSCALED(jpegwidth, sf[i]);
1901 scaledh=TJSCALED(jpegheight, sf[i]);
1902 if(scaledw<=width && scaledh<=height)
1906 _throw("tjDecompressToYUV2(): Could not scale down to desired image dimensions");
1908 pw0=tjPlaneWidth(0, width, jpegSubsamp);
1909 ph0=tjPlaneHeight(0, height, jpegSubsamp);
1910 dstPlanes[0]=dstBuf;
1911 strides[0]=PAD(pw0, pad);
1912 if(jpegSubsamp==TJSAMP_GRAY)
1914 strides[1]=strides[2]=0;
1915 dstPlanes[1]=dstPlanes[2]=NULL;
1919 int pw1=tjPlaneWidth(1, width, jpegSubsamp);
1920 int ph1=tjPlaneHeight(1, height, jpegSubsamp);
1921 strides[1]=strides[2]=PAD(pw1, pad);
1922 dstPlanes[1]=dstPlanes[0]+strides[0]*ph0;
1923 dstPlanes[2]=dstPlanes[1]+strides[1]*ph1;
1927 return tjDecompressToYUVPlanes(handle, jpegBuf, jpegSize, dstPlanes, width,
1928 strides, height, flags);
1935 DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle,
1936 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf,
1939 return tjDecompressToYUV2(handle, jpegBuf, jpegSize, dstBuf, 0, 4, 0, flags);
1945 DLLEXPORT tjhandle DLLCALL tjInitTransform(void)
1947 tjinstance *this=NULL; tjhandle handle=NULL;
1948 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL)
1950 snprintf(errStr, JMSG_LENGTH_MAX,
1951 "tjInitTransform(): Memory allocation failure");
1954 MEMZERO(this, sizeof(tjinstance));
1955 handle=_tjInitCompress(this);
1956 if(!handle) return NULL;
1957 handle=_tjInitDecompress(this);
1962 DLLEXPORT int DLLCALL tjTransform(tjhandle handle, unsigned char *jpegBuf,
1963 unsigned long jpegSize, int n, unsigned char **dstBufs,
1964 unsigned long *dstSizes, tjtransform *t, int flags)
1966 jpeg_transform_info *xinfo=NULL;
1967 jvirt_barray_ptr *srccoefs, *dstcoefs;
1968 int retval=0, i, jpegSubsamp;
1970 getinstance(handle);
1971 if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0)
1972 _throw("tjTransform(): Instance has not been initialized for transformation");
1974 if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL
1975 || t==NULL || flags<0)
1976 _throw("tjTransform(): Invalid argument");
1978 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
1979 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
1980 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
1982 if(setjmp(this->jerr.setjmp_buffer))
1984 /* If we get here, the JPEG code has signaled an error. */
1989 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
1991 if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n))
1993 _throw("tjTransform(): Memory allocation failure");
1994 MEMZERO(xinfo, sizeof(jpeg_transform_info)*n);
1998 xinfo[i].transform=xformtypes[t[i].op];
1999 xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0;
2000 xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0;
2001 xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0;
2002 xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0;
2003 if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1;
2004 else xinfo[i].slow_hflip=0;
2008 xinfo[i].crop_xoffset=t[i].r.x; xinfo[i].crop_xoffset_set=JCROP_POS;
2009 xinfo[i].crop_yoffset=t[i].r.y; xinfo[i].crop_yoffset_set=JCROP_POS;
2012 xinfo[i].crop_width=t[i].r.w; xinfo[i].crop_width_set=JCROP_POS;
2014 else xinfo[i].crop_width=JCROP_UNSET;
2017 xinfo[i].crop_height=t[i].r.h; xinfo[i].crop_height_set=JCROP_POS;
2019 else xinfo[i].crop_height=JCROP_UNSET;
2023 jcopy_markers_setup(dinfo, JCOPYOPT_ALL);
2024 jpeg_read_header(dinfo, TRUE);
2025 jpegSubsamp=getSubsamp(dinfo);
2027 _throw("tjTransform(): Could not determine subsampling type for JPEG image");
2031 if(!jtransform_request_workspace(dinfo, &xinfo[i]))
2032 _throw("tjTransform(): Transform is not perfect");
2036 if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0
2037 || (t[i].r.y%xinfo[i].iMCU_sample_height)!=0)
2039 snprintf(errStr, JMSG_LENGTH_MAX,
2040 "To crop this JPEG image, x must be a multiple of %d\n"
2041 "and y must be a multiple of %d.\n",
2042 xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height);
2043 retval=-1; goto bailout;
2048 srccoefs=jpeg_read_coefficients(dinfo);
2055 w=dinfo->image_width; h=dinfo->image_height;
2059 w=xinfo[i].crop_width; h=xinfo[i].crop_height;
2061 if(flags&TJFLAG_NOREALLOC)
2063 alloc=0; dstSizes[i]=tjBufSize(w, h, jpegSubsamp);
2065 if(!(t[i].options&TJXOPT_NOOUTPUT))
2066 jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc);
2067 jpeg_copy_critical_parameters(dinfo, cinfo);
2068 dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs,
2070 if(!(t[i].options&TJXOPT_NOOUTPUT))
2072 jpeg_write_coefficients(cinfo, dstcoefs);
2073 jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL);
2075 else jinit_c_master_control(cinfo, TRUE);
2076 jtransform_execute_transformation(dinfo, cinfo, srccoefs,
2078 if(t[i].customFilter)
2080 int ci, y; JDIMENSION by;
2081 for(ci=0; ci<cinfo->num_components; ci++)
2083 jpeg_component_info *compptr=&cinfo->comp_info[ci];
2084 tjregion arrayRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
2086 tjregion planeRegion={0, 0, compptr->width_in_blocks*DCTSIZE,
2087 compptr->height_in_blocks*DCTSIZE};
2088 for(by=0; by<compptr->height_in_blocks; by+=compptr->v_samp_factor)
2090 JBLOCKARRAY barray=(dinfo->mem->access_virt_barray)
2091 ((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor,
2093 for(y=0; y<compptr->v_samp_factor; y++)
2095 if(t[i].customFilter(barray[y][0], arrayRegion, planeRegion,
2097 _throw("tjTransform(): Error in custom filter");
2098 arrayRegion.y+=DCTSIZE;
2103 if(!(t[i].options&TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo);
2106 jpeg_finish_decompress(dinfo);
2109 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
2110 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
2111 if(xinfo) free(xinfo);
2112 if(this->jerr.warning) retval=-1;