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