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