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