1 /* 2 * Copyright (C)2009-2012, 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 43 extern void jpeg_mem_dest_tj(j_compress_ptr, unsigned char **, 44 unsigned long *, boolean); 45 extern void jpeg_mem_src_tj(j_decompress_ptr, unsigned char *, unsigned long); 46 47 #define PAD(v, p) ((v+(p)-1)&(~((p)-1))) 48 49 50 /* Error handling (based on example in example.c) */ 51 52 static char errStr[JMSG_LENGTH_MAX]="No error"; 53 54 struct my_error_mgr 55 { 56 struct jpeg_error_mgr pub; 57 jmp_buf setjmp_buffer; 58 }; 59 typedef struct my_error_mgr *my_error_ptr; 60 61 static void my_error_exit(j_common_ptr cinfo) 62 { 63 my_error_ptr myerr=(my_error_ptr)cinfo->err; 64 (*cinfo->err->output_message)(cinfo); 65 longjmp(myerr->setjmp_buffer, 1); 66 } 67 68 /* Based on output_message() in jerror.c */ 69 70 static void my_output_message(j_common_ptr cinfo) 71 { 72 (*cinfo->err->format_message)(cinfo, errStr); 73 } 74 75 76 /* Global structures, macros, etc. */ 77 78 enum {COMPRESS=1, DECOMPRESS=2}; 79 80 typedef struct _tjinstance 81 { 82 struct jpeg_compress_struct cinfo; 83 struct jpeg_decompress_struct dinfo; 84 struct my_error_mgr jerr; 85 int init; 86 } tjinstance; 87 88 static const int pixelsize[TJ_NUMSAMP]={3, 3, 3, 1, 3}; 89 90 static const JXFORM_CODE xformtypes[TJ_NUMXOP]= 91 { 92 JXFORM_NONE, JXFORM_FLIP_H, JXFORM_FLIP_V, JXFORM_TRANSPOSE, 93 JXFORM_TRANSVERSE, JXFORM_ROT_90, JXFORM_ROT_180, JXFORM_ROT_270 94 }; 95 96 #define NUMSF 16 97 static const tjscalingfactor sf[NUMSF]={ 98 {2, 1}, 99 {15, 8}, 100 {7, 4}, 101 {13, 8}, 102 {3, 2}, 103 {11, 8}, 104 {5, 4}, 105 {9, 8}, 106 {1, 1}, 107 {7, 8}, 108 {3, 4}, 109 {5, 8}, 110 {1, 2}, 111 {3, 8}, 112 {1, 4}, 113 {1, 8} 114 }; 115 116 #define _throw(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s", m); \ 117 retval=-1; goto bailout;} 118 #define getinstance(handle) tjinstance *this=(tjinstance *)handle; \ 119 j_compress_ptr cinfo=NULL; j_decompress_ptr dinfo=NULL; \ 120 if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \ 121 return -1;} \ 122 cinfo=&this->cinfo; dinfo=&this->dinfo; 123 124 static int getPixelFormat(int pixelSize, int flags) 125 { 126 if(pixelSize==1) return TJPF_GRAY; 127 if(pixelSize==3) 128 { 129 if(flags&TJ_BGR) return TJPF_BGR; 130 else return TJPF_RGB; 131 } 132 if(pixelSize==4) 133 { 134 if(flags&TJ_ALPHAFIRST) 135 { 136 if(flags&TJ_BGR) return TJPF_XBGR; 137 else return TJPF_XRGB; 138 } 139 else 140 { 141 if(flags&TJ_BGR) return TJPF_BGRX; 142 else return TJPF_RGBX; 143 } 144 } 145 return -1; 146 } 147 148 static int setCompDefaults(struct jpeg_compress_struct *cinfo, 149 int pixelFormat, int subsamp, int jpegQual, int flags) 150 { 151 int retval=0; 152 153 switch(pixelFormat) 154 { 155 case TJPF_GRAY: 156 cinfo->in_color_space=JCS_GRAYSCALE; break; 157 #if JCS_EXTENSIONS==1 158 case TJPF_RGB: 159 cinfo->in_color_space=JCS_EXT_RGB; break; 160 case TJPF_BGR: 161 cinfo->in_color_space=JCS_EXT_BGR; break; 162 case TJPF_RGBX: 163 case TJPF_RGBA: 164 cinfo->in_color_space=JCS_EXT_RGBX; break; 165 case TJPF_BGRX: 166 case TJPF_BGRA: 167 cinfo->in_color_space=JCS_EXT_BGRX; break; 168 case TJPF_XRGB: 169 case TJPF_ARGB: 170 cinfo->in_color_space=JCS_EXT_XRGB; break; 171 case TJPF_XBGR: 172 case TJPF_ABGR: 173 cinfo->in_color_space=JCS_EXT_XBGR; break; 174 #else 175 case TJPF_RGB: 176 case TJPF_BGR: 177 case TJPF_RGBX: 178 case TJPF_BGRX: 179 case TJPF_XRGB: 180 case TJPF_XBGR: 181 case TJPF_RGBA: 182 case TJPF_BGRA: 183 case TJPF_ARGB: 184 case TJPF_ABGR: 185 cinfo->in_color_space=JCS_RGB; pixelFormat=TJPF_RGB; 186 break; 187 #endif 188 } 189 190 cinfo->input_components=tjPixelSize[pixelFormat]; 191 jpeg_set_defaults(cinfo); 192 if(jpegQual>=0) 193 { 194 jpeg_set_quality(cinfo, jpegQual, TRUE); 195 if(jpegQual>=96 || flags&TJFLAG_ACCURATEDCT) cinfo->dct_method=JDCT_ISLOW; 196 else cinfo->dct_method=JDCT_FASTEST; 197 } 198 if(subsamp==TJSAMP_GRAY) 199 jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); 200 else 201 jpeg_set_colorspace(cinfo, JCS_YCbCr); 202 203 cinfo->comp_info[0].h_samp_factor=tjMCUWidth[subsamp]/8; 204 cinfo->comp_info[1].h_samp_factor=1; 205 cinfo->comp_info[2].h_samp_factor=1; 206 cinfo->comp_info[0].v_samp_factor=tjMCUHeight[subsamp]/8; 207 cinfo->comp_info[1].v_samp_factor=1; 208 cinfo->comp_info[2].v_samp_factor=1; 209 210 return retval; 211 } 212 213 static int setDecompDefaults(struct jpeg_decompress_struct *dinfo, 214 int pixelFormat, int flags) 215 { 216 int retval=0; 217 218 switch(pixelFormat) 219 { 220 case TJPF_GRAY: 221 dinfo->out_color_space=JCS_GRAYSCALE; break; 222 #if JCS_EXTENSIONS==1 223 case TJPF_RGB: 224 dinfo->out_color_space=JCS_EXT_RGB; break; 225 case TJPF_BGR: 226 dinfo->out_color_space=JCS_EXT_BGR; break; 227 case TJPF_RGBX: 228 dinfo->out_color_space=JCS_EXT_RGBX; break; 229 case TJPF_BGRX: 230 dinfo->out_color_space=JCS_EXT_BGRX; break; 231 case TJPF_XRGB: 232 dinfo->out_color_space=JCS_EXT_XRGB; break; 233 case TJPF_XBGR: 234 dinfo->out_color_space=JCS_EXT_XBGR; break; 235 #if JCS_ALPHA_EXTENSIONS==1 236 case TJPF_RGBA: 237 dinfo->out_color_space=JCS_EXT_RGBA; break; 238 case TJPF_BGRA: 239 dinfo->out_color_space=JCS_EXT_BGRA; break; 240 case TJPF_ARGB: 241 dinfo->out_color_space=JCS_EXT_ARGB; break; 242 case TJPF_ABGR: 243 dinfo->out_color_space=JCS_EXT_ABGR; break; 244 #endif 245 #else 246 case TJPF_RGB: 247 case TJPF_BGR: 248 case TJPF_RGBX: 249 case TJPF_BGRX: 250 case TJPF_XRGB: 251 case TJPF_XBGR: 252 case TJPF_RGBA: 253 case TJPF_BGRA: 254 case TJPF_ARGB: 255 case TJPF_ABGR: 256 dinfo->out_color_space=JCS_RGB; break; 257 #endif 258 default: 259 _throw("Unsupported pixel format"); 260 } 261 262 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST; 263 264 bailout: 265 return retval; 266 } 267 268 269 static int getSubsamp(j_decompress_ptr dinfo) 270 { 271 int retval=-1, i, k; 272 for(i=0; i<NUMSUBOPT; i++) 273 { 274 if(dinfo->num_components==pixelsize[i]) 275 { 276 if(dinfo->comp_info[0].h_samp_factor==tjMCUWidth[i]/8 277 && dinfo->comp_info[0].v_samp_factor==tjMCUHeight[i]/8) 278 { 279 int match=0; 280 for(k=1; k<dinfo->num_components; k++) 281 { 282 if(dinfo->comp_info[k].h_samp_factor==1 283 && dinfo->comp_info[k].v_samp_factor==1) 284 match++; 285 } 286 if(match==dinfo->num_components-1) 287 { 288 retval=i; break; 289 } 290 } 291 } 292 } 293 return retval; 294 } 295 296 297 #ifndef JCS_EXTENSIONS 298 299 /* Conversion functions to emulate the colorspace extensions. This allows the 300 TurboJPEG wrapper to be used with libjpeg */ 301 302 #define TORGB(PS, ROFFSET, GOFFSET, BOFFSET) { \ 303 int rowPad=pitch-width*PS; \ 304 while(height--) \ 305 { \ 306 unsigned char *endOfRow=src+width*PS; \ 307 while(src<endOfRow) \ 308 { \ 309 dst[RGB_RED]=src[ROFFSET]; \ 310 dst[RGB_GREEN]=src[GOFFSET]; \ 311 dst[RGB_BLUE]=src[BOFFSET]; \ 312 dst+=RGB_PIXELSIZE; src+=PS; \ 313 } \ 314 src+=rowPad; \ 315 } \ 316 } 317 318 static unsigned char *toRGB(unsigned char *src, int width, int pitch, 319 int height, int pixelFormat, unsigned char *dst) 320 { 321 unsigned char *retval=src; 322 switch(pixelFormat) 323 { 324 case TJPF_RGB: 325 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3 326 retval=dst; TORGB(3, 0, 1, 2); 327 #endif 328 break; 329 case TJPF_BGR: 330 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3 331 retval=dst; TORGB(3, 2, 1, 0); 332 #endif 333 break; 334 case TJPF_RGBX: 335 case TJPF_RGBA: 336 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4 337 retval=dst; TORGB(4, 0, 1, 2); 338 #endif 339 break; 340 case TJPF_BGRX: 341 case TJPF_BGRA: 342 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4 343 retval=dst; TORGB(4, 2, 1, 0); 344 #endif 345 break; 346 case TJPF_XRGB: 347 case TJPF_ARGB: 348 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4 349 retval=dst; TORGB(4, 1, 2, 3); 350 #endif 351 break; 352 case TJPF_XBGR: 353 case TJPF_ABGR: 354 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4 355 retval=dst; TORGB(4, 3, 2, 1); 356 #endif 357 break; 358 } 359 return retval; 360 } 361 362 #define FROMRGB(PS, ROFFSET, GOFFSET, BOFFSET, SETALPHA) { \ 363 int rowPad=pitch-width*PS; \ 364 while(height--) \ 365 { \ 366 unsigned char *endOfRow=dst+width*PS; \ 367 while(dst<endOfRow) \ 368 { \ 369 dst[ROFFSET]=src[RGB_RED]; \ 370 dst[GOFFSET]=src[RGB_GREEN]; \ 371 dst[BOFFSET]=src[RGB_BLUE]; \ 372 SETALPHA \ 373 dst+=PS; src+=RGB_PIXELSIZE; \ 374 } \ 375 dst+=rowPad; \ 376 } \ 377 } 378 379 static void fromRGB(unsigned char *src, unsigned char *dst, int width, 380 int pitch, int height, int pixelFormat) 381 { 382 switch(pixelFormat) 383 { 384 case TJPF_RGB: 385 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3 386 FROMRGB(3, 0, 1, 2,); 387 #endif 388 break; 389 case TJPF_BGR: 390 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3 391 FROMRGB(3, 2, 1, 0,); 392 #endif 393 break; 394 case TJPF_RGBX: 395 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4 396 FROMRGB(4, 0, 1, 2,); 397 #endif 398 break; 399 case TJPF_RGBA: 400 #if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4 401 FROMRGB(4, 0, 1, 2, dst[3]=0xFF;); 402 #endif 403 break; 404 case TJPF_BGRX: 405 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4 406 FROMRGB(4, 2, 1, 0,); 407 #endif 408 break; 409 case TJPF_BGRA: 410 #if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4 411 FROMRGB(4, 2, 1, 0, dst[3]=0xFF;); return; 412 #endif 413 break; 414 case TJPF_XRGB: 415 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4 416 FROMRGB(4, 1, 2, 3,); return; 417 #endif 418 break; 419 case TJPF_ARGB: 420 #if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4 421 FROMRGB(4, 1, 2, 3, dst[0]=0xFF;); return; 422 #endif 423 break; 424 case TJPF_XBGR: 425 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4 426 FROMRGB(4, 3, 2, 1,); return; 427 #endif 428 break; 429 case TJPF_ABGR: 430 #if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4 431 FROMRGB(4, 3, 2, 1, dst[0]=0xFF;); return; 432 #endif 433 break; 434 } 435 } 436 437 #endif 438 439 440 /* General API functions */ 441 442 DLLEXPORT char* DLLCALL tjGetErrorStr(void) 443 { 444 return errStr; 445 } 446 447 448 DLLEXPORT int DLLCALL tjDestroy(tjhandle handle) 449 { 450 getinstance(handle); 451 if(setjmp(this->jerr.setjmp_buffer)) return -1; 452 if(this->init&COMPRESS) jpeg_destroy_compress(cinfo); 453 if(this->init&DECOMPRESS) jpeg_destroy_decompress(dinfo); 454 free(this); 455 return 0; 456 } 457 458 459 /* These are exposed mainly because Windows can't malloc() and free() across 460 DLL boundaries except when the CRT DLL is used, and we don't use the CRT DLL 461 with turbojpeg.dll for compatibility reasons. However, these functions 462 can potentially be used for other purposes by different implementations. */ 463 464 DLLEXPORT void DLLCALL tjFree(unsigned char *buf) 465 { 466 if(buf) free(buf); 467 } 468 469 470 DLLEXPORT unsigned char *DLLCALL tjAlloc(int bytes) 471 { 472 return (unsigned char *)malloc(bytes); 473 } 474 475 476 /* Compressor */ 477 478 static tjhandle _tjInitCompress(tjinstance *this) 479 { 480 unsigned char buffer[1], *buf=buffer; unsigned long size=1; 481 482 /* This is also straight out of example.c */ 483 this->cinfo.err=jpeg_std_error(&this->jerr.pub); 484 this->jerr.pub.error_exit=my_error_exit; 485 this->jerr.pub.output_message=my_output_message; 486 487 if(setjmp(this->jerr.setjmp_buffer)) 488 { 489 /* If we get here, the JPEG code has signaled an error. */ 490 if(this) free(this); return NULL; 491 } 492 493 jpeg_create_compress(&this->cinfo); 494 /* Make an initial call so it will create the destination manager */ 495 jpeg_mem_dest_tj(&this->cinfo, &buf, &size, 0); 496 497 this->init|=COMPRESS; 498 return (tjhandle)this; 499 } 500 501 DLLEXPORT tjhandle DLLCALL tjInitCompress(void) 502 { 503 tjinstance *this=NULL; 504 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL) 505 { 506 snprintf(errStr, JMSG_LENGTH_MAX, 507 "tjInitCompress(): Memory allocation failure"); 508 return NULL; 509 } 510 MEMZERO(this, sizeof(tjinstance)); 511 return _tjInitCompress(this); 512 } 513 514 515 DLLEXPORT unsigned long DLLCALL tjBufSize(int width, int height, 516 int jpegSubsamp) 517 { 518 unsigned long retval=0; int mcuw, mcuh, chromasf; 519 if(width<1 || height<1 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT) 520 _throw("tjBufSize(): Invalid argument"); 521 522 /* This allows for rare corner cases in which a JPEG image can actually be 523 larger than the uncompressed input (we wouldn't mention it if it hadn't 524 happened before.) */ 525 mcuw=tjMCUWidth[jpegSubsamp]; 526 mcuh=tjMCUHeight[jpegSubsamp]; 527 chromasf=jpegSubsamp==TJSAMP_GRAY? 0: 4*64/(mcuw*mcuh); 528 retval=PAD(width, mcuw) * PAD(height, mcuh) * (2 + chromasf) + 2048; 529 530 bailout: 531 return retval; 532 } 533 534 DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height) 535 { 536 unsigned long retval=0; 537 if(width<1 || height<1) 538 _throw("TJBUFSIZE(): Invalid argument"); 539 540 /* This allows for rare corner cases in which a JPEG image can actually be 541 larger than the uncompressed input (we wouldn't mention it if it hadn't 542 happened before.) */ 543 retval=PAD(width, 16) * PAD(height, 16) * 6 + 2048; 544 545 bailout: 546 return retval; 547 } 548 549 550 DLLEXPORT unsigned long DLLCALL tjBufSizeYUV(int width, int height, 551 int subsamp) 552 { 553 unsigned long retval=0; 554 int pw, ph, cw, ch; 555 if(width<1 || height<1 || subsamp<0 || subsamp>=NUMSUBOPT) 556 _throw("tjBufSizeYUV(): Invalid argument"); 557 pw=PAD(width, tjMCUWidth[subsamp]/8); 558 ph=PAD(height, tjMCUHeight[subsamp]/8); 559 cw=pw*8/tjMCUWidth[subsamp]; ch=ph*8/tjMCUHeight[subsamp]; 560 retval=PAD(pw, 4)*ph + (subsamp==TJSAMP_GRAY? 0:PAD(cw, 4)*ch*2); 561 562 bailout: 563 return retval; 564 } 565 566 567 DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height, 568 int subsamp) 569 { 570 return tjBufSizeYUV(width, height, subsamp); 571 } 572 573 574 DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf, 575 int width, int pitch, int height, int pixelFormat, unsigned char **jpegBuf, 576 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags) 577 { 578 int i, retval=0, alloc=1; JSAMPROW *row_pointer=NULL; 579 #ifndef JCS_EXTENSIONS 580 unsigned char *rgbBuf=NULL; 581 #endif 582 583 getinstance(handle) 584 if((this->init&COMPRESS)==0) 585 _throw("tjCompress2(): Instance has not been initialized for compression"); 586 587 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0 588 || pixelFormat>=TJ_NUMPF || jpegBuf==NULL || jpegSize==NULL 589 || jpegSubsamp<0 || jpegSubsamp>=NUMSUBOPT || jpegQual<0 || jpegQual>100) 590 _throw("tjCompress2(): Invalid argument"); 591 592 if(setjmp(this->jerr.setjmp_buffer)) 593 { 594 /* If we get here, the JPEG code has signaled an error. */ 595 retval=-1; 596 goto bailout; 597 } 598 599 if(pitch==0) pitch=width*tjPixelSize[pixelFormat]; 600 601 #ifndef JCS_EXTENSIONS 602 if(pixelFormat!=TJPF_GRAY) 603 { 604 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE); 605 if(!rgbBuf) _throw("tjCompress2(): Memory allocation failure"); 606 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf); 607 pitch=width*RGB_PIXELSIZE; 608 } 609 #endif 610 611 cinfo->image_width=width; 612 cinfo->image_height=height; 613 614 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); 615 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); 616 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); 617 618 if(flags&TJFLAG_NOREALLOC) 619 { 620 alloc=0; *jpegSize=tjBufSize(width, height, jpegSubsamp); 621 } 622 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc); 623 if(setCompDefaults(cinfo, pixelFormat, jpegSubsamp, jpegQual, flags)==-1) 624 return -1; 625 626 jpeg_start_compress(cinfo, TRUE); 627 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL) 628 _throw("tjCompress2(): Memory allocation failure"); 629 for(i=0; i<height; i++) 630 { 631 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch]; 632 else row_pointer[i]=&srcBuf[i*pitch]; 633 } 634 while(cinfo->next_scanline<cinfo->image_height) 635 { 636 jpeg_write_scanlines(cinfo, &row_pointer[cinfo->next_scanline], 637 cinfo->image_height-cinfo->next_scanline); 638 } 639 jpeg_finish_compress(cinfo); 640 641 bailout: 642 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo); 643 #ifndef JCS_EXTENSIONS 644 if(rgbBuf) free(rgbBuf); 645 #endif 646 if(row_pointer) free(row_pointer); 647 return retval; 648 } 649 650 DLLEXPORT int DLLCALL tjCompress(tjhandle handle, unsigned char *srcBuf, 651 int width, int pitch, int height, int pixelSize, unsigned char *jpegBuf, 652 unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags) 653 { 654 int retval=0; unsigned long size; 655 if(flags&TJ_YUV) 656 { 657 size=tjBufSizeYUV(width, height, jpegSubsamp); 658 retval=tjEncodeYUV2(handle, srcBuf, width, pitch, height, 659 getPixelFormat(pixelSize, flags), jpegBuf, jpegSubsamp, flags); 660 } 661 else 662 { 663 retval=tjCompress2(handle, srcBuf, width, pitch, height, 664 getPixelFormat(pixelSize, flags), &jpegBuf, &size, jpegSubsamp, jpegQual, 665 flags|TJFLAG_NOREALLOC); 666 } 667 *jpegSize=size; 668 return retval; 669 } 670 671 672 DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf, 673 int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf, 674 int subsamp, int flags) 675 { 676 int i, retval=0; JSAMPROW *row_pointer=NULL; 677 JSAMPLE *_tmpbuf[MAX_COMPONENTS], *_tmpbuf2[MAX_COMPONENTS]; 678 JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS]; 679 JSAMPROW *outbuf[MAX_COMPONENTS]; 680 int row, pw, ph, cw[MAX_COMPONENTS], ch[MAX_COMPONENTS]; 681 JSAMPLE *ptr=dstBuf; 682 unsigned long yuvsize=0; 683 jpeg_component_info *compptr; 684 #ifndef JCS_EXTENSIONS 685 unsigned char *rgbBuf=NULL; 686 #endif 687 688 getinstance(handle); 689 690 for(i=0; i<MAX_COMPONENTS; i++) 691 { 692 tmpbuf[i]=NULL; _tmpbuf[i]=NULL; 693 tmpbuf2[i]=NULL; _tmpbuf2[i]=NULL; outbuf[i]=NULL; 694 } 695 696 if((this->init&COMPRESS)==0) 697 _throw("tjEncodeYUV2(): Instance has not been initialized for compression"); 698 699 if(srcBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0 700 || pixelFormat>=TJ_NUMPF || dstBuf==NULL || subsamp<0 701 || subsamp>=NUMSUBOPT) 702 _throw("tjEncodeYUV2(): Invalid argument"); 703 704 if(setjmp(this->jerr.setjmp_buffer)) 705 { 706 /* If we get here, the JPEG code has signaled an error. */ 707 retval=-1; 708 goto bailout; 709 } 710 711 if(pitch==0) pitch=width*tjPixelSize[pixelFormat]; 712 713 #ifndef JCS_EXTENSIONS 714 if(pixelFormat!=TJPF_GRAY) 715 { 716 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE); 717 if(!rgbBuf) _throw("tjEncodeYUV2(): Memory allocation failure"); 718 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf); 719 pitch=width*RGB_PIXELSIZE; 720 } 721 #endif 722 723 cinfo->image_width=width; 724 cinfo->image_height=height; 725 726 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); 727 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); 728 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); 729 730 yuvsize=tjBufSizeYUV(width, height, subsamp); 731 if(setCompDefaults(cinfo, pixelFormat, subsamp, -1, flags)==-1) return -1; 732 733 /* Execute only the parts of jpeg_start_compress() that we need. If we 734 were to call the whole jpeg_start_compress() function, then it would try 735 to write the file headers, which could overflow the output buffer if the 736 YUV image were very small. */ 737 if(cinfo->global_state!=CSTATE_START) 738 _throw("tjEncodeYUV3(): libjpeg API is in the wrong state"); 739 (*cinfo->err->reset_error_mgr)((j_common_ptr)cinfo); 740 jinit_c_master_control(cinfo, FALSE); 741 jinit_color_converter(cinfo); 742 jinit_downsampler(cinfo); 743 (*cinfo->cconvert->start_pass)(cinfo); 744 745 pw=PAD(width, cinfo->max_h_samp_factor); 746 ph=PAD(height, cinfo->max_v_samp_factor); 747 748 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph))==NULL) 749 _throw("tjEncodeYUV2(): Memory allocation failure"); 750 for(i=0; i<height; i++) 751 { 752 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch]; 753 else row_pointer[i]=&srcBuf[i*pitch]; 754 } 755 if(height<ph) 756 for(i=height; i<ph; i++) row_pointer[i]=row_pointer[height-1]; 757 758 for(i=0; i<cinfo->num_components; i++) 759 { 760 compptr=&cinfo->comp_info[i]; 761 _tmpbuf[i]=(JSAMPLE *)malloc( 762 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE) 763 /compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16); 764 if(!_tmpbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure"); 765 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor); 766 if(!tmpbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure"); 767 for(row=0; row<cinfo->max_v_samp_factor; row++) 768 { 769 unsigned char *_tmpbuf_aligned= 770 (unsigned char *)PAD((size_t)_tmpbuf[i], 16); 771 tmpbuf[i][row]=&_tmpbuf_aligned[ 772 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE) 773 /compptr->h_samp_factor, 16) * row]; 774 } 775 _tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16) 776 * compptr->v_samp_factor + 16); 777 if(!_tmpbuf2[i]) _throw("tjEncodeYUV2(): Memory allocation failure"); 778 tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor); 779 if(!tmpbuf2[i]) _throw("tjEncodeYUV2(): Memory allocation failure"); 780 for(row=0; row<compptr->v_samp_factor; row++) 781 { 782 unsigned char *_tmpbuf2_aligned= 783 (unsigned char *)PAD((size_t)_tmpbuf2[i], 16); 784 tmpbuf2[i][row]=&_tmpbuf2_aligned[ 785 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row]; 786 } 787 cw[i]=pw*compptr->h_samp_factor/cinfo->max_h_samp_factor; 788 ch[i]=ph*compptr->v_samp_factor/cinfo->max_v_samp_factor; 789 outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]); 790 if(!outbuf[i]) _throw("tjEncodeYUV2(): Memory allocation failure"); 791 for(row=0; row<ch[i]; row++) 792 { 793 outbuf[i][row]=ptr; 794 ptr+=PAD(cw[i], 4); 795 } 796 } 797 if(yuvsize!=(unsigned long)(ptr-dstBuf)) 798 _throw("tjEncodeYUV2(): Generated image is not the correct size"); 799 800 for(row=0; row<ph; row+=cinfo->max_v_samp_factor) 801 { 802 (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0, 803 cinfo->max_v_samp_factor); 804 (cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0); 805 for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++) 806 jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i], 807 row*compptr->v_samp_factor/cinfo->max_v_samp_factor, 808 compptr->v_samp_factor, cw[i]); 809 } 810 cinfo->next_scanline+=height; 811 jpeg_abort_compress(cinfo); 812 813 bailout: 814 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo); 815 #ifndef JCS_EXTENSIONS 816 if(rgbBuf) free(rgbBuf); 817 #endif 818 if(row_pointer) free(row_pointer); 819 for(i=0; i<MAX_COMPONENTS; i++) 820 { 821 if(tmpbuf[i]!=NULL) free(tmpbuf[i]); 822 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]); 823 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]); 824 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]); 825 if(outbuf[i]!=NULL) free(outbuf[i]); 826 } 827 return retval; 828 } 829 830 DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf, 831 int width, int pitch, int height, int pixelSize, unsigned char *dstBuf, 832 int subsamp, int flags) 833 { 834 return tjEncodeYUV2(handle, srcBuf, width, pitch, height, 835 getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags); 836 } 837 838 839 /* Decompressor */ 840 841 static tjhandle _tjInitDecompress(tjinstance *this) 842 { 843 unsigned char buffer[1]; 844 845 /* This is also straight out of example.c */ 846 this->dinfo.err=jpeg_std_error(&this->jerr.pub); 847 this->jerr.pub.error_exit=my_error_exit; 848 this->jerr.pub.output_message=my_output_message; 849 850 if(setjmp(this->jerr.setjmp_buffer)) 851 { 852 /* If we get here, the JPEG code has signaled an error. */ 853 if(this) free(this); return NULL; 854 } 855 856 jpeg_create_decompress(&this->dinfo); 857 /* Make an initial call so it will create the source manager */ 858 jpeg_mem_src_tj(&this->dinfo, buffer, 1); 859 860 this->init|=DECOMPRESS; 861 return (tjhandle)this; 862 } 863 864 DLLEXPORT tjhandle DLLCALL tjInitDecompress(void) 865 { 866 tjinstance *this; 867 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL) 868 { 869 snprintf(errStr, JMSG_LENGTH_MAX, 870 "tjInitDecompress(): Memory allocation failure"); 871 return NULL; 872 } 873 MEMZERO(this, sizeof(tjinstance)); 874 return _tjInitDecompress(this); 875 } 876 877 878 DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle, 879 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height, 880 int *jpegSubsamp) 881 { 882 int retval=0; 883 884 getinstance(handle); 885 if((this->init&DECOMPRESS)==0) 886 _throw("tjDecompressHeader2(): Instance has not been initialized for decompression"); 887 888 if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL 889 || jpegSubsamp==NULL) 890 _throw("tjDecompressHeader2(): Invalid argument"); 891 892 if(setjmp(this->jerr.setjmp_buffer)) 893 { 894 /* If we get here, the JPEG code has signaled an error. */ 895 return -1; 896 } 897 898 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); 899 jpeg_read_header(dinfo, TRUE); 900 901 *width=dinfo->image_width; 902 *height=dinfo->image_height; 903 *jpegSubsamp=getSubsamp(dinfo); 904 905 jpeg_abort_decompress(dinfo); 906 907 if(*jpegSubsamp<0) 908 _throw("tjDecompressHeader2(): Could not determine subsampling type for JPEG image"); 909 if(*width<1 || *height<1) 910 _throw("tjDecompressHeader2(): Invalid data returned in header"); 911 912 bailout: 913 return retval; 914 } 915 916 DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle, 917 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height) 918 { 919 int jpegSubsamp; 920 return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height, 921 &jpegSubsamp); 922 } 923 924 925 DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors) 926 { 927 if(numscalingfactors==NULL) 928 { 929 snprintf(errStr, JMSG_LENGTH_MAX, 930 "tjGetScalingFactors(): Invalid argument"); 931 return NULL; 932 } 933 934 *numscalingfactors=NUMSF; 935 return (tjscalingfactor *)sf; 936 } 937 938 939 DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, unsigned char *jpegBuf, 940 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch, 941 int height, int pixelFormat, int flags) 942 { 943 int i, retval=0; JSAMPROW *row_pointer=NULL; 944 int jpegwidth, jpegheight, scaledw, scaledh; 945 #ifndef JCS_EXTENSIONS 946 unsigned char *rgbBuf=NULL; 947 unsigned char *_dstBuf=NULL; int _pitch=0; 948 #endif 949 950 getinstance(handle); 951 if((this->init&DECOMPRESS)==0) 952 _throw("tjDecompress2(): Instance has not been initialized for decompression"); 953 954 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0 955 || height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF) 956 _throw("tjDecompress2(): Invalid argument"); 957 958 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); 959 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); 960 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); 961 962 if(setjmp(this->jerr.setjmp_buffer)) 963 { 964 /* If we get here, the JPEG code has signaled an error. */ 965 retval=-1; 966 goto bailout; 967 } 968 969 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); 970 jpeg_read_header(dinfo, TRUE); 971 if(setDecompDefaults(dinfo, pixelFormat, flags)==-1) 972 { 973 retval=-1; goto bailout; 974 } 975 976 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE; 977 978 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height; 979 if(width==0) width=jpegwidth; 980 if(height==0) height=jpegheight; 981 for(i=0; i<NUMSF; i++) 982 { 983 scaledw=TJSCALED(jpegwidth, sf[i]); 984 scaledh=TJSCALED(jpegheight, sf[i]); 985 if(scaledw<=width && scaledh<=height) 986 break; 987 } 988 if(scaledw>width || scaledh>height) 989 _throw("tjDecompress2(): Could not scale down to desired image dimensions"); 990 width=scaledw; height=scaledh; 991 dinfo->scale_num=sf[i].num; 992 dinfo->scale_denom=sf[i].denom; 993 994 jpeg_start_decompress(dinfo); 995 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat]; 996 997 #ifndef JCS_EXTENSIONS 998 if(pixelFormat!=TJPF_GRAY && 999 (RGB_RED!=tjRedOffset[pixelFormat] || 1000 RGB_GREEN!=tjGreenOffset[pixelFormat] || 1001 RGB_BLUE!=tjBlueOffset[pixelFormat] || 1002 RGB_PIXELSIZE!=tjPixelSize[pixelFormat])) 1003 { 1004 rgbBuf=(unsigned char *)malloc(width*height*3); 1005 if(!rgbBuf) _throw("tjDecompress2(): Memory allocation failure"); 1006 _pitch=pitch; pitch=width*3; 1007 _dstBuf=dstBuf; dstBuf=rgbBuf; 1008 } 1009 #endif 1010 1011 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW) 1012 *dinfo->output_height))==NULL) 1013 _throw("tjDecompress2(): Memory allocation failure"); 1014 for(i=0; i<(int)dinfo->output_height; i++) 1015 { 1016 if(flags&TJFLAG_BOTTOMUP) 1017 row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*pitch]; 1018 else row_pointer[i]=&dstBuf[i*pitch]; 1019 } 1020 while(dinfo->output_scanline<dinfo->output_height) 1021 { 1022 jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline], 1023 dinfo->output_height-dinfo->output_scanline); 1024 } 1025 jpeg_finish_decompress(dinfo); 1026 1027 #ifndef JCS_EXTENSIONS 1028 fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat); 1029 #endif 1030 1031 bailout: 1032 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo); 1033 #ifndef JCS_EXTENSIONS 1034 if(rgbBuf) free(rgbBuf); 1035 #endif 1036 if(row_pointer) free(row_pointer); 1037 return retval; 1038 } 1039 1040 DLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf, 1041 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch, 1042 int height, int pixelSize, int flags) 1043 { 1044 if(flags&TJ_YUV) 1045 return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags); 1046 else 1047 return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch, 1048 height, getPixelFormat(pixelSize, flags), flags); 1049 } 1050 1051 1052 DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle, 1053 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf, 1054 int flags) 1055 { 1056 int i, row, retval=0; JSAMPROW *outbuf[MAX_COMPONENTS]; 1057 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS], 1058 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS]; 1059 JSAMPLE *_tmpbuf=NULL, *ptr=dstBuf; JSAMPROW *tmpbuf[MAX_COMPONENTS]; 1060 1061 getinstance(handle); 1062 1063 for(i=0; i<MAX_COMPONENTS; i++) 1064 { 1065 tmpbuf[i]=NULL; outbuf[i]=NULL; 1066 } 1067 1068 if((this->init&DECOMPRESS)==0) 1069 _throw("tjDecompressToYUV(): Instance has not been initialized for decompression"); 1070 1071 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL) 1072 _throw("tjDecompressToYUV(): Invalid argument"); 1073 1074 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); 1075 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); 1076 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); 1077 1078 if(setjmp(this->jerr.setjmp_buffer)) 1079 { 1080 /* If we get here, the JPEG code has signaled an error. */ 1081 retval=-1; 1082 goto bailout; 1083 } 1084 1085 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); 1086 jpeg_read_header(dinfo, TRUE); 1087 1088 for(i=0; i<dinfo->num_components; i++) 1089 { 1090 jpeg_component_info *compptr=&dinfo->comp_info[i]; 1091 int ih; 1092 iw[i]=compptr->width_in_blocks*DCTSIZE; 1093 ih=compptr->height_in_blocks*DCTSIZE; 1094 cw[i]=PAD(dinfo->image_width, dinfo->max_h_samp_factor) 1095 *compptr->h_samp_factor/dinfo->max_h_samp_factor; 1096 ch[i]=PAD(dinfo->image_height, dinfo->max_v_samp_factor) 1097 *compptr->v_samp_factor/dinfo->max_v_samp_factor; 1098 if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1; 1099 th[i]=compptr->v_samp_factor*DCTSIZE; 1100 tmpbufsize+=iw[i]*th[i]; 1101 if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL) 1102 _throw("tjDecompressToYUV(): Memory allocation failure"); 1103 for(row=0; row<ch[i]; row++) 1104 { 1105 outbuf[i][row]=ptr; 1106 ptr+=PAD(cw[i], 4); 1107 } 1108 } 1109 if(usetmpbuf) 1110 { 1111 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL) 1112 _throw("tjDecompressToYUV(): Memory allocation failure"); 1113 ptr=_tmpbuf; 1114 for(i=0; i<dinfo->num_components; i++) 1115 { 1116 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL) 1117 _throw("tjDecompressToYUV(): Memory allocation failure"); 1118 for(row=0; row<th[i]; row++) 1119 { 1120 tmpbuf[i][row]=ptr; 1121 ptr+=iw[i]; 1122 } 1123 } 1124 } 1125 1126 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE; 1127 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST; 1128 dinfo->raw_data_out=TRUE; 1129 1130 jpeg_start_decompress(dinfo); 1131 for(row=0; row<(int)dinfo->output_height; 1132 row+=dinfo->max_v_samp_factor*DCTSIZE) 1133 { 1134 JSAMPARRAY yuvptr[MAX_COMPONENTS]; 1135 int crow[MAX_COMPONENTS]; 1136 for(i=0; i<dinfo->num_components; i++) 1137 { 1138 jpeg_component_info *compptr=&dinfo->comp_info[i]; 1139 crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor; 1140 if(usetmpbuf) yuvptr[i]=tmpbuf[i]; 1141 else yuvptr[i]=&outbuf[i][crow[i]]; 1142 } 1143 jpeg_read_raw_data(dinfo, yuvptr, dinfo->max_v_samp_factor*DCTSIZE); 1144 if(usetmpbuf) 1145 { 1146 int j; 1147 for(i=0; i<dinfo->num_components; i++) 1148 { 1149 for(j=0; j<min(th[i], ch[i]-crow[i]); j++) 1150 { 1151 memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], cw[i]); 1152 } 1153 } 1154 } 1155 } 1156 jpeg_finish_decompress(dinfo); 1157 1158 bailout: 1159 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo); 1160 for(i=0; i<MAX_COMPONENTS; i++) 1161 { 1162 if(tmpbuf[i]) free(tmpbuf[i]); 1163 if(outbuf[i]) free(outbuf[i]); 1164 } 1165 if(_tmpbuf) free(_tmpbuf); 1166 return retval; 1167 } 1168 1169 1170 /* Transformer */ 1171 1172 DLLEXPORT tjhandle DLLCALL tjInitTransform(void) 1173 { 1174 tjinstance *this=NULL; tjhandle handle=NULL; 1175 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL) 1176 { 1177 snprintf(errStr, JMSG_LENGTH_MAX, 1178 "tjInitTransform(): Memory allocation failure"); 1179 return NULL; 1180 } 1181 MEMZERO(this, sizeof(tjinstance)); 1182 handle=_tjInitCompress(this); 1183 if(!handle) return NULL; 1184 handle=_tjInitDecompress(this); 1185 return handle; 1186 } 1187 1188 1189 DLLEXPORT int DLLCALL tjTransform(tjhandle handle, unsigned char *jpegBuf, 1190 unsigned long jpegSize, int n, unsigned char **dstBufs, 1191 unsigned long *dstSizes, tjtransform *t, int flags) 1192 { 1193 jpeg_transform_info *xinfo=NULL; 1194 jvirt_barray_ptr *srccoefs, *dstcoefs; 1195 int retval=0, i, jpegSubsamp; 1196 1197 getinstance(handle); 1198 if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0) 1199 _throw("tjTransform(): Instance has not been initialized for transformation"); 1200 1201 if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL 1202 || t==NULL || flags<0) 1203 _throw("tjTransform(): Invalid argument"); 1204 1205 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); 1206 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); 1207 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); 1208 1209 if(setjmp(this->jerr.setjmp_buffer)) 1210 { 1211 /* If we get here, the JPEG code has signaled an error. */ 1212 retval=-1; 1213 goto bailout; 1214 } 1215 1216 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); 1217 1218 if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n)) 1219 ==NULL) 1220 _throw("tjTransform(): Memory allocation failure"); 1221 MEMZERO(xinfo, sizeof(jpeg_transform_info)*n); 1222 1223 for(i=0; i<n; i++) 1224 { 1225 xinfo[i].transform=xformtypes[t[i].op]; 1226 xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0; 1227 xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0; 1228 xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0; 1229 xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0; 1230 if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1; 1231 else xinfo[i].slow_hflip=0; 1232 1233 if(xinfo[i].crop) 1234 { 1235 xinfo[i].crop_xoffset=t[i].r.x; xinfo[i].crop_xoffset_set=JCROP_POS; 1236 xinfo[i].crop_yoffset=t[i].r.y; xinfo[i].crop_yoffset_set=JCROP_POS; 1237 if(t[i].r.w!=0) 1238 { 1239 xinfo[i].crop_width=t[i].r.w; xinfo[i].crop_width_set=JCROP_POS; 1240 } 1241 else xinfo[i].crop_width=JCROP_UNSET; 1242 if(t[i].r.h!=0) 1243 { 1244 xinfo[i].crop_height=t[i].r.h; xinfo[i].crop_height_set=JCROP_POS; 1245 } 1246 else xinfo[i].crop_height=JCROP_UNSET; 1247 } 1248 } 1249 1250 jcopy_markers_setup(dinfo, JCOPYOPT_ALL); 1251 jpeg_read_header(dinfo, TRUE); 1252 jpegSubsamp=getSubsamp(dinfo); 1253 if(jpegSubsamp<0) 1254 _throw("tjTransform(): Could not determine subsampling type for JPEG image"); 1255 1256 for(i=0; i<n; i++) 1257 { 1258 if(!jtransform_request_workspace(dinfo, &xinfo[i])) 1259 _throw("tjTransform(): Transform is not perfect"); 1260 1261 if(xinfo[i].crop) 1262 { 1263 if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0 1264 || (t[i].r.y%xinfo[i].iMCU_sample_height)!=0) 1265 { 1266 snprintf(errStr, JMSG_LENGTH_MAX, 1267 "To crop this JPEG image, x must be a multiple of %d\n" 1268 "and y must be a multiple of %d.\n", 1269 xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height); 1270 retval=-1; goto bailout; 1271 } 1272 } 1273 } 1274 1275 srccoefs=jpeg_read_coefficients(dinfo); 1276 1277 for(i=0; i<n; i++) 1278 { 1279 int w, h, alloc=1; 1280 if(!xinfo[i].crop) 1281 { 1282 w=dinfo->image_width; h=dinfo->image_height; 1283 } 1284 else 1285 { 1286 w=xinfo[i].crop_width; h=xinfo[i].crop_height; 1287 } 1288 if(flags&TJFLAG_NOREALLOC) 1289 { 1290 alloc=0; dstSizes[i]=tjBufSize(w, h, jpegSubsamp); 1291 } 1292 if(!(t[i].options&TJXOPT_NOOUTPUT)) 1293 jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc); 1294 jpeg_copy_critical_parameters(dinfo, cinfo); 1295 dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs, 1296 &xinfo[i]); 1297 if(!(t[i].options&TJXOPT_NOOUTPUT)) 1298 { 1299 jpeg_write_coefficients(cinfo, dstcoefs); 1300 jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL); 1301 } 1302 else jinit_c_master_control(cinfo, TRUE); 1303 jtransform_execute_transformation(dinfo, cinfo, srccoefs, 1304 &xinfo[i]); 1305 if(t[i].customFilter) 1306 { 1307 int ci, y; JDIMENSION by; 1308 for(ci=0; ci<cinfo->num_components; ci++) 1309 { 1310 jpeg_component_info *compptr=&cinfo->comp_info[ci]; 1311 tjregion arrayRegion={0, 0, compptr->width_in_blocks*DCTSIZE, 1312 DCTSIZE}; 1313 tjregion planeRegion={0, 0, compptr->width_in_blocks*DCTSIZE, 1314 compptr->height_in_blocks*DCTSIZE}; 1315 for(by=0; by<compptr->height_in_blocks; by+=compptr->v_samp_factor) 1316 { 1317 JBLOCKARRAY barray=(dinfo->mem->access_virt_barray) 1318 ((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor, 1319 TRUE); 1320 for(y=0; y<compptr->v_samp_factor; y++) 1321 { 1322 if(t[i].customFilter(barray[y][0], arrayRegion, planeRegion, 1323 ci, i, &t[i])==-1) 1324 _throw("tjTransform(): Error in custom filter"); 1325 arrayRegion.y+=DCTSIZE; 1326 } 1327 } 1328 } 1329 } 1330 if(!(t[i].options&TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo); 1331 } 1332 1333 jpeg_finish_decompress(dinfo); 1334 1335 bailout: 1336 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo); 1337 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo); 1338 if(xinfo) free(xinfo); 1339 return retval; 1340 } 1341