1 /* 2 * Copyright (C)2009-2017 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(pitch==0) pitch=width*tjPixelSize[pixelFormat]; 776 777 #ifndef JCS_EXTENSIONS 778 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK) 779 { 780 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE); 781 if(!rgbBuf) _throw("tjCompress2(): Memory allocation failure"); 782 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf); 783 pitch=width*RGB_PIXELSIZE; 784 } 785 #endif 786 787 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL) 788 _throw("tjCompress2(): Memory allocation failure"); 789 790 if(setjmp(this->jerr.setjmp_buffer)) 791 { 792 /* If we get here, the JPEG code has signaled an error. */ 793 retval=-1; goto bailout; 794 } 795 796 cinfo->image_width=width; 797 cinfo->image_height=height; 798 799 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); 800 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); 801 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); 802 803 if(flags&TJFLAG_NOREALLOC) 804 { 805 alloc=0; *jpegSize=tjBufSize(width, height, jpegSubsamp); 806 } 807 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc); 808 if(setCompDefaults(cinfo, pixelFormat, jpegSubsamp, jpegQual, flags)==-1) 809 return -1; 810 811 jpeg_start_compress(cinfo, TRUE); 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(pixelFormat==TJPF_CMYK) 892 _throw("tjEncodeYUVPlanes(): Cannot generate YUV images from CMYK pixels"); 893 894 if(pitch==0) pitch=width*tjPixelSize[pixelFormat]; 895 896 #ifndef JCS_EXTENSIONS 897 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK) 898 { 899 rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE); 900 if(!rgbBuf) _throw("tjEncodeYUVPlanes(): Memory allocation failure"); 901 srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf); 902 pitch=width*RGB_PIXELSIZE; 903 } 904 #endif 905 906 if(setjmp(this->jerr.setjmp_buffer)) 907 { 908 /* If we get here, the JPEG code has signaled an error. */ 909 retval=-1; goto bailout; 910 } 911 912 cinfo->image_width=width; 913 cinfo->image_height=height; 914 915 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); 916 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); 917 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); 918 919 if(setCompDefaults(cinfo, pixelFormat, subsamp, -1, flags)==-1) return -1; 920 921 /* Execute only the parts of jpeg_start_compress() that we need. If we 922 were to call the whole jpeg_start_compress() function, then it would try 923 to write the file headers, which could overflow the output buffer if the 924 YUV image were very small. */ 925 if(cinfo->global_state!=CSTATE_START) 926 _throw("tjEncodeYUVPlanes(): libjpeg API is in the wrong state"); 927 (*cinfo->err->reset_error_mgr)((j_common_ptr)cinfo); 928 jinit_c_master_control(cinfo, FALSE); 929 jinit_color_converter(cinfo); 930 jinit_downsampler(cinfo); 931 (*cinfo->cconvert->start_pass)(cinfo); 932 933 pw0=PAD(width, cinfo->max_h_samp_factor); 934 ph0=PAD(height, cinfo->max_v_samp_factor); 935 936 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL) 937 _throw("tjEncodeYUVPlanes(): Memory allocation failure"); 938 for(i=0; i<height; i++) 939 { 940 if(flags&TJFLAG_BOTTOMUP) 941 row_pointer[i]=(JSAMPROW)&srcBuf[(height-i-1)*pitch]; 942 else row_pointer[i]=(JSAMPROW)&srcBuf[i*pitch]; 943 } 944 if(height<ph0) 945 for(i=height; i<ph0; i++) row_pointer[i]=row_pointer[height-1]; 946 947 for(i=0; i<cinfo->num_components; i++) 948 { 949 compptr=&cinfo->comp_info[i]; 950 _tmpbuf[i]=(JSAMPLE *)malloc( 951 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE) 952 /compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16); 953 if(!_tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure"); 954 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor); 955 if(!tmpbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure"); 956 for(row=0; row<cinfo->max_v_samp_factor; row++) 957 { 958 unsigned char *_tmpbuf_aligned= 959 (unsigned char *)PAD((size_t)_tmpbuf[i], 16); 960 tmpbuf[i][row]=&_tmpbuf_aligned[ 961 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE) 962 /compptr->h_samp_factor, 16) * row]; 963 } 964 _tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16) 965 * compptr->v_samp_factor + 16); 966 if(!_tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure"); 967 tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor); 968 if(!tmpbuf2[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure"); 969 for(row=0; row<compptr->v_samp_factor; row++) 970 { 971 unsigned char *_tmpbuf2_aligned= 972 (unsigned char *)PAD((size_t)_tmpbuf2[i], 16); 973 tmpbuf2[i][row]=&_tmpbuf2_aligned[ 974 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row]; 975 } 976 pw[i]=pw0*compptr->h_samp_factor/cinfo->max_h_samp_factor; 977 ph[i]=ph0*compptr->v_samp_factor/cinfo->max_v_samp_factor; 978 outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]); 979 if(!outbuf[i]) _throw("tjEncodeYUVPlanes(): Memory allocation failure"); 980 ptr=dstPlanes[i]; 981 for(row=0; row<ph[i]; row++) 982 { 983 outbuf[i][row]=ptr; 984 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i]; 985 } 986 } 987 988 if(setjmp(this->jerr.setjmp_buffer)) 989 { 990 /* If we get here, the JPEG code has signaled an error. */ 991 retval=-1; goto bailout; 992 } 993 994 for(row=0; row<ph0; row+=cinfo->max_v_samp_factor) 995 { 996 (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0, 997 cinfo->max_v_samp_factor); 998 (cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0); 999 for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++) 1000 jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i], 1001 row*compptr->v_samp_factor/cinfo->max_v_samp_factor, 1002 compptr->v_samp_factor, pw[i]); 1003 } 1004 cinfo->next_scanline+=height; 1005 jpeg_abort_compress(cinfo); 1006 1007 bailout: 1008 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo); 1009 #ifndef JCS_EXTENSIONS 1010 if(rgbBuf) free(rgbBuf); 1011 #endif 1012 if(row_pointer) free(row_pointer); 1013 for(i=0; i<MAX_COMPONENTS; i++) 1014 { 1015 if(tmpbuf[i]!=NULL) free(tmpbuf[i]); 1016 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]); 1017 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]); 1018 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]); 1019 if(outbuf[i]!=NULL) free(outbuf[i]); 1020 } 1021 if(this->jerr.warning) retval=-1; 1022 return retval; 1023 } 1024 1025 DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, 1026 const unsigned char *srcBuf, int width, int pitch, int height, 1027 int pixelFormat, unsigned char *dstBuf, int pad, int subsamp, int flags) 1028 { 1029 unsigned char *dstPlanes[3]; 1030 int pw0, ph0, strides[3], retval=-1; 1031 1032 if(width<=0 || height<=0 || dstBuf==NULL || pad<0 || !isPow2(pad) 1033 || subsamp<0 || subsamp>=NUMSUBOPT) 1034 _throw("tjEncodeYUV3(): Invalid argument"); 1035 1036 pw0=tjPlaneWidth(0, width, subsamp); 1037 ph0=tjPlaneHeight(0, height, subsamp); 1038 dstPlanes[0]=dstBuf; 1039 strides[0]=PAD(pw0, pad); 1040 if(subsamp==TJSAMP_GRAY) 1041 { 1042 strides[1]=strides[2]=0; 1043 dstPlanes[1]=dstPlanes[2]=NULL; 1044 } 1045 else 1046 { 1047 int pw1=tjPlaneWidth(1, width, subsamp); 1048 int ph1=tjPlaneHeight(1, height, subsamp); 1049 strides[1]=strides[2]=PAD(pw1, pad); 1050 dstPlanes[1]=dstPlanes[0]+strides[0]*ph0; 1051 dstPlanes[2]=dstPlanes[1]+strides[1]*ph1; 1052 } 1053 1054 return tjEncodeYUVPlanes(handle, srcBuf, width, pitch, height, pixelFormat, 1055 dstPlanes, strides, subsamp, flags); 1056 1057 bailout: 1058 return retval; 1059 } 1060 1061 DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf, 1062 int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf, 1063 int subsamp, int flags) 1064 { 1065 return tjEncodeYUV3(handle, srcBuf, width, pitch, height, pixelFormat, 1066 dstBuf, 4, subsamp, flags); 1067 } 1068 1069 DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf, 1070 int width, int pitch, int height, int pixelSize, unsigned char *dstBuf, 1071 int subsamp, int flags) 1072 { 1073 return tjEncodeYUV2(handle, srcBuf, width, pitch, height, 1074 getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags); 1075 } 1076 1077 1078 DLLEXPORT int DLLCALL tjCompressFromYUVPlanes(tjhandle handle, 1079 const unsigned char **srcPlanes, int width, const int *strides, int height, 1080 int subsamp, unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual, 1081 int flags) 1082 { 1083 int i, row, retval=0, alloc=1; JSAMPROW *inbuf[MAX_COMPONENTS]; 1084 int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS], 1085 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS]; 1086 JSAMPLE *_tmpbuf=NULL, *ptr; JSAMPROW *tmpbuf[MAX_COMPONENTS]; 1087 1088 getcinstance(handle) 1089 1090 for(i=0; i<MAX_COMPONENTS; i++) 1091 { 1092 tmpbuf[i]=NULL; inbuf[i]=NULL; 1093 } 1094 1095 if((this->init&COMPRESS)==0) 1096 _throw("tjCompressFromYUVPlanes(): Instance has not been initialized for compression"); 1097 1098 if(!srcPlanes || !srcPlanes[0] || width<=0 || height<=0 || subsamp<0 1099 || subsamp>=NUMSUBOPT || jpegBuf==NULL || jpegSize==NULL || jpegQual<0 1100 || jpegQual>100) 1101 _throw("tjCompressFromYUVPlanes(): Invalid argument"); 1102 if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2])) 1103 _throw("tjCompressFromYUVPlanes(): Invalid argument"); 1104 1105 if(setjmp(this->jerr.setjmp_buffer)) 1106 { 1107 /* If we get here, the JPEG code has signaled an error. */ 1108 retval=-1; goto bailout; 1109 } 1110 1111 cinfo->image_width=width; 1112 cinfo->image_height=height; 1113 1114 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); 1115 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); 1116 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); 1117 1118 if(flags&TJFLAG_NOREALLOC) 1119 { 1120 alloc=0; *jpegSize=tjBufSize(width, height, subsamp); 1121 } 1122 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc); 1123 if(setCompDefaults(cinfo, TJPF_RGB, subsamp, jpegQual, flags)==-1) 1124 return -1; 1125 cinfo->raw_data_in=TRUE; 1126 1127 jpeg_start_compress(cinfo, TRUE); 1128 for(i=0; i<cinfo->num_components; i++) 1129 { 1130 jpeg_component_info *compptr=&cinfo->comp_info[i]; 1131 int ih; 1132 iw[i]=compptr->width_in_blocks*DCTSIZE; 1133 ih=compptr->height_in_blocks*DCTSIZE; 1134 pw[i]=PAD(cinfo->image_width, cinfo->max_h_samp_factor) 1135 *compptr->h_samp_factor/cinfo->max_h_samp_factor; 1136 ph[i]=PAD(cinfo->image_height, cinfo->max_v_samp_factor) 1137 *compptr->v_samp_factor/cinfo->max_v_samp_factor; 1138 if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1; 1139 th[i]=compptr->v_samp_factor*DCTSIZE; 1140 tmpbufsize+=iw[i]*th[i]; 1141 if((inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]))==NULL) 1142 _throw("tjCompressFromYUVPlanes(): Memory allocation failure"); 1143 ptr=(JSAMPLE *)srcPlanes[i]; 1144 for(row=0; row<ph[i]; row++) 1145 { 1146 inbuf[i][row]=ptr; 1147 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i]; 1148 } 1149 } 1150 if(usetmpbuf) 1151 { 1152 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL) 1153 _throw("tjCompressFromYUVPlanes(): Memory allocation failure"); 1154 ptr=_tmpbuf; 1155 for(i=0; i<cinfo->num_components; i++) 1156 { 1157 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL) 1158 _throw("tjCompressFromYUVPlanes(): Memory allocation failure"); 1159 for(row=0; row<th[i]; row++) 1160 { 1161 tmpbuf[i][row]=ptr; 1162 ptr+=iw[i]; 1163 } 1164 } 1165 } 1166 1167 if(setjmp(this->jerr.setjmp_buffer)) 1168 { 1169 /* If we get here, the JPEG code has signaled an error. */ 1170 retval=-1; goto bailout; 1171 } 1172 1173 for(row=0; row<(int)cinfo->image_height; 1174 row+=cinfo->max_v_samp_factor*DCTSIZE) 1175 { 1176 JSAMPARRAY yuvptr[MAX_COMPONENTS]; 1177 int crow[MAX_COMPONENTS]; 1178 for(i=0; i<cinfo->num_components; i++) 1179 { 1180 jpeg_component_info *compptr=&cinfo->comp_info[i]; 1181 crow[i]=row*compptr->v_samp_factor/cinfo->max_v_samp_factor; 1182 if(usetmpbuf) 1183 { 1184 int j, k; 1185 for(j=0; j<min(th[i], ph[i]-crow[i]); j++) 1186 { 1187 memcpy(tmpbuf[i][j], inbuf[i][crow[i]+j], pw[i]); 1188 /* Duplicate last sample in row to fill out MCU */ 1189 for(k=pw[i]; k<iw[i]; k++) tmpbuf[i][j][k]=tmpbuf[i][j][pw[i]-1]; 1190 } 1191 /* Duplicate last row to fill out MCU */ 1192 for(j=ph[i]-crow[i]; j<th[i]; j++) 1193 memcpy(tmpbuf[i][j], tmpbuf[i][ph[i]-crow[i]-1], iw[i]); 1194 yuvptr[i]=tmpbuf[i]; 1195 } 1196 else 1197 yuvptr[i]=&inbuf[i][crow[i]]; 1198 } 1199 jpeg_write_raw_data(cinfo, yuvptr, cinfo->max_v_samp_factor*DCTSIZE); 1200 } 1201 jpeg_finish_compress(cinfo); 1202 1203 bailout: 1204 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo); 1205 for(i=0; i<MAX_COMPONENTS; i++) 1206 { 1207 if(tmpbuf[i]) free(tmpbuf[i]); 1208 if(inbuf[i]) free(inbuf[i]); 1209 } 1210 if(_tmpbuf) free(_tmpbuf); 1211 if(this->jerr.warning) retval=-1; 1212 return retval; 1213 } 1214 1215 DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle, 1216 const unsigned char *srcBuf, int width, int pad, int height, int subsamp, 1217 unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual, int flags) 1218 { 1219 const unsigned char *srcPlanes[3]; 1220 int pw0, ph0, strides[3], retval=-1; 1221 1222 if(srcBuf==NULL || width<=0 || pad<1 || height<=0 || subsamp<0 1223 || subsamp>=NUMSUBOPT) 1224 _throw("tjCompressFromYUV(): Invalid argument"); 1225 1226 pw0=tjPlaneWidth(0, width, subsamp); 1227 ph0=tjPlaneHeight(0, height, subsamp); 1228 srcPlanes[0]=srcBuf; 1229 strides[0]=PAD(pw0, pad); 1230 if(subsamp==TJSAMP_GRAY) 1231 { 1232 strides[1]=strides[2]=0; 1233 srcPlanes[1]=srcPlanes[2]=NULL; 1234 } 1235 else 1236 { 1237 int pw1=tjPlaneWidth(1, width, subsamp); 1238 int ph1=tjPlaneHeight(1, height, subsamp); 1239 strides[1]=strides[2]=PAD(pw1, pad); 1240 srcPlanes[1]=srcPlanes[0]+strides[0]*ph0; 1241 srcPlanes[2]=srcPlanes[1]+strides[1]*ph1; 1242 } 1243 1244 return tjCompressFromYUVPlanes(handle, srcPlanes, width, strides, height, 1245 subsamp, jpegBuf, jpegSize, jpegQual, flags); 1246 1247 bailout: 1248 return retval; 1249 } 1250 1251 1252 /* Decompressor */ 1253 1254 static tjhandle _tjInitDecompress(tjinstance *this) 1255 { 1256 static unsigned char buffer[1]; 1257 1258 /* This is also straight out of example.c */ 1259 this->dinfo.err=jpeg_std_error(&this->jerr.pub); 1260 this->jerr.pub.error_exit=my_error_exit; 1261 this->jerr.pub.output_message=my_output_message; 1262 this->jerr.emit_message=this->jerr.pub.emit_message; 1263 this->jerr.pub.emit_message=my_emit_message; 1264 1265 if(setjmp(this->jerr.setjmp_buffer)) 1266 { 1267 /* If we get here, the JPEG code has signaled an error. */ 1268 if(this) free(this); 1269 return NULL; 1270 } 1271 1272 jpeg_create_decompress(&this->dinfo); 1273 /* Make an initial call so it will create the source manager */ 1274 jpeg_mem_src_tj(&this->dinfo, buffer, 1); 1275 1276 this->init|=DECOMPRESS; 1277 return (tjhandle)this; 1278 } 1279 1280 DLLEXPORT tjhandle DLLCALL tjInitDecompress(void) 1281 { 1282 tjinstance *this; 1283 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL) 1284 { 1285 snprintf(errStr, JMSG_LENGTH_MAX, 1286 "tjInitDecompress(): Memory allocation failure"); 1287 return NULL; 1288 } 1289 MEMZERO(this, sizeof(tjinstance)); 1290 return _tjInitDecompress(this); 1291 } 1292 1293 1294 DLLEXPORT int DLLCALL tjDecompressHeader3(tjhandle handle, 1295 const unsigned char *jpegBuf, unsigned long jpegSize, int *width, 1296 int *height, int *jpegSubsamp, int *jpegColorspace) 1297 { 1298 int retval=0; 1299 1300 getdinstance(handle); 1301 if((this->init&DECOMPRESS)==0) 1302 _throw("tjDecompressHeader3(): Instance has not been initialized for decompression"); 1303 1304 if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL 1305 || jpegSubsamp==NULL || jpegColorspace==NULL) 1306 _throw("tjDecompressHeader3(): Invalid argument"); 1307 1308 if(setjmp(this->jerr.setjmp_buffer)) 1309 { 1310 /* If we get here, the JPEG code has signaled an error. */ 1311 return -1; 1312 } 1313 1314 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); 1315 jpeg_read_header(dinfo, TRUE); 1316 1317 *width=dinfo->image_width; 1318 *height=dinfo->image_height; 1319 *jpegSubsamp=getSubsamp(dinfo); 1320 switch(dinfo->jpeg_color_space) 1321 { 1322 case JCS_GRAYSCALE: *jpegColorspace=TJCS_GRAY; break; 1323 case JCS_RGB: *jpegColorspace=TJCS_RGB; break; 1324 case JCS_YCbCr: *jpegColorspace=TJCS_YCbCr; break; 1325 case JCS_CMYK: *jpegColorspace=TJCS_CMYK; break; 1326 case JCS_YCCK: *jpegColorspace=TJCS_YCCK; break; 1327 default: *jpegColorspace=-1; break; 1328 } 1329 1330 jpeg_abort_decompress(dinfo); 1331 1332 if(*jpegSubsamp<0) 1333 _throw("tjDecompressHeader3(): Could not determine subsampling type for JPEG image"); 1334 if(*jpegColorspace<0) 1335 _throw("tjDecompressHeader3(): Could not determine colorspace of JPEG image"); 1336 if(*width<1 || *height<1) 1337 _throw("tjDecompressHeader3(): Invalid data returned in header"); 1338 1339 bailout: 1340 if(this->jerr.warning) retval=-1; 1341 return retval; 1342 } 1343 1344 DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle, 1345 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height, 1346 int *jpegSubsamp) 1347 { 1348 int jpegColorspace; 1349 return tjDecompressHeader3(handle, jpegBuf, jpegSize, width, height, 1350 jpegSubsamp, &jpegColorspace); 1351 } 1352 1353 DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle, 1354 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height) 1355 { 1356 int jpegSubsamp; 1357 return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height, 1358 &jpegSubsamp); 1359 } 1360 1361 1362 DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors) 1363 { 1364 if(numscalingfactors==NULL) 1365 { 1366 snprintf(errStr, JMSG_LENGTH_MAX, 1367 "tjGetScalingFactors(): Invalid argument"); 1368 return NULL; 1369 } 1370 1371 *numscalingfactors=NUMSF; 1372 return (tjscalingfactor *)sf; 1373 } 1374 1375 1376 DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, 1377 const unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf, 1378 int width, int pitch, int height, int pixelFormat, int flags) 1379 { 1380 int i, retval=0; JSAMPROW *row_pointer=NULL; 1381 int jpegwidth, jpegheight, scaledw, scaledh; 1382 #ifndef JCS_EXTENSIONS 1383 unsigned char *rgbBuf=NULL; 1384 unsigned char *_dstBuf=NULL; int _pitch=0; 1385 #endif 1386 1387 getdinstance(handle); 1388 if((this->init&DECOMPRESS)==0) 1389 _throw("tjDecompress2(): Instance has not been initialized for decompression"); 1390 1391 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0 1392 || height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF) 1393 _throw("tjDecompress2(): Invalid argument"); 1394 1395 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); 1396 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); 1397 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); 1398 1399 if(setjmp(this->jerr.setjmp_buffer)) 1400 { 1401 /* If we get here, the JPEG code has signaled an error. */ 1402 retval=-1; goto bailout; 1403 } 1404 1405 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); 1406 jpeg_read_header(dinfo, TRUE); 1407 if(setDecompDefaults(dinfo, pixelFormat, flags)==-1) 1408 { 1409 retval=-1; goto bailout; 1410 } 1411 1412 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE; 1413 1414 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height; 1415 if(width==0) width=jpegwidth; 1416 if(height==0) height=jpegheight; 1417 for(i=0; i<NUMSF; i++) 1418 { 1419 scaledw=TJSCALED(jpegwidth, sf[i]); 1420 scaledh=TJSCALED(jpegheight, sf[i]); 1421 if(scaledw<=width && scaledh<=height) 1422 break; 1423 } 1424 if(i>=NUMSF) 1425 _throw("tjDecompress2(): Could not scale down to desired image dimensions"); 1426 width=scaledw; height=scaledh; 1427 dinfo->scale_num=sf[i].num; 1428 dinfo->scale_denom=sf[i].denom; 1429 1430 jpeg_start_decompress(dinfo); 1431 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat]; 1432 1433 #ifndef JCS_EXTENSIONS 1434 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK && 1435 (RGB_RED!=tjRedOffset[pixelFormat] || 1436 RGB_GREEN!=tjGreenOffset[pixelFormat] || 1437 RGB_BLUE!=tjBlueOffset[pixelFormat] || 1438 RGB_PIXELSIZE!=tjPixelSize[pixelFormat])) 1439 { 1440 rgbBuf=(unsigned char *)malloc(width*height*3); 1441 if(!rgbBuf) _throw("tjDecompress2(): Memory allocation failure"); 1442 _pitch=pitch; pitch=width*3; 1443 _dstBuf=dstBuf; dstBuf=rgbBuf; 1444 } 1445 #endif 1446 1447 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW) 1448 *dinfo->output_height))==NULL) 1449 _throw("tjDecompress2(): Memory allocation failure"); 1450 if(setjmp(this->jerr.setjmp_buffer)) 1451 { 1452 /* If we get here, the JPEG code has signaled an error. */ 1453 retval=-1; goto bailout; 1454 } 1455 for(i=0; i<(int)dinfo->output_height; i++) 1456 { 1457 if(flags&TJFLAG_BOTTOMUP) 1458 row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*pitch]; 1459 else row_pointer[i]=&dstBuf[i*pitch]; 1460 } 1461 while(dinfo->output_scanline<dinfo->output_height) 1462 { 1463 jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline], 1464 dinfo->output_height-dinfo->output_scanline); 1465 } 1466 jpeg_finish_decompress(dinfo); 1467 1468 #ifndef JCS_EXTENSIONS 1469 fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat); 1470 #endif 1471 1472 bailout: 1473 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo); 1474 #ifndef JCS_EXTENSIONS 1475 if(rgbBuf) free(rgbBuf); 1476 #endif 1477 if(row_pointer) free(row_pointer); 1478 if(this->jerr.warning) retval=-1; 1479 return retval; 1480 } 1481 1482 DLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf, 1483 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch, 1484 int height, int pixelSize, int flags) 1485 { 1486 if(flags&TJ_YUV) 1487 return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags); 1488 else 1489 return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch, 1490 height, getPixelFormat(pixelSize, flags), flags); 1491 } 1492 1493 1494 static int setDecodeDefaults(struct jpeg_decompress_struct *dinfo, 1495 int pixelFormat, int subsamp, int flags) 1496 { 1497 int i; 1498 1499 dinfo->scale_num=dinfo->scale_denom=1; 1500 1501 if(subsamp==TJSAMP_GRAY) 1502 { 1503 dinfo->num_components=dinfo->comps_in_scan=1; 1504 dinfo->jpeg_color_space=JCS_GRAYSCALE; 1505 } 1506 else 1507 { 1508 dinfo->num_components=dinfo->comps_in_scan=3; 1509 dinfo->jpeg_color_space=JCS_YCbCr; 1510 } 1511 1512 dinfo->comp_info=(jpeg_component_info *) 1513 (*dinfo->mem->alloc_small)((j_common_ptr)dinfo, JPOOL_IMAGE, 1514 dinfo->num_components*sizeof(jpeg_component_info)); 1515 1516 for(i=0; i<dinfo->num_components; i++) 1517 { 1518 jpeg_component_info *compptr=&dinfo->comp_info[i]; 1519 compptr->h_samp_factor=(i==0)? tjMCUWidth[subsamp]/8:1; 1520 compptr->v_samp_factor=(i==0)? tjMCUHeight[subsamp]/8:1; 1521 compptr->component_index=i; 1522 compptr->component_id=i+1; 1523 compptr->quant_tbl_no=compptr->dc_tbl_no=compptr->ac_tbl_no= 1524 (i==0)? 0:1; 1525 dinfo->cur_comp_info[i]=compptr; 1526 } 1527 dinfo->data_precision=8; 1528 for(i=0; i<2; i++) 1529 { 1530 if(dinfo->quant_tbl_ptrs[i]==NULL) 1531 dinfo->quant_tbl_ptrs[i]=jpeg_alloc_quant_table((j_common_ptr)dinfo); 1532 } 1533 1534 return 0; 1535 } 1536 1537 1538 int my_read_markers(j_decompress_ptr dinfo) 1539 { 1540 return JPEG_REACHED_SOS; 1541 } 1542 1543 void my_reset_marker_reader(j_decompress_ptr dinfo) 1544 { 1545 } 1546 1547 DLLEXPORT int DLLCALL tjDecodeYUVPlanes(tjhandle handle, 1548 const unsigned char **srcPlanes, const int *strides, int subsamp, 1549 unsigned char *dstBuf, int width, int pitch, int height, int pixelFormat, 1550 int flags) 1551 { 1552 int i, retval=0; JSAMPROW *row_pointer=NULL; 1553 JSAMPLE *_tmpbuf[MAX_COMPONENTS]; 1554 JSAMPROW *tmpbuf[MAX_COMPONENTS], *inbuf[MAX_COMPONENTS]; 1555 int row, pw0, ph0, pw[MAX_COMPONENTS], ph[MAX_COMPONENTS]; 1556 JSAMPLE *ptr; 1557 jpeg_component_info *compptr; 1558 #ifndef JCS_EXTENSIONS 1559 unsigned char *rgbBuf=NULL; 1560 unsigned char *_dstBuf=NULL; int _pitch=0; 1561 #endif 1562 int (*old_read_markers)(j_decompress_ptr); 1563 void (*old_reset_marker_reader)(j_decompress_ptr); 1564 1565 getdinstance(handle); 1566 1567 for(i=0; i<MAX_COMPONENTS; i++) 1568 { 1569 tmpbuf[i]=NULL; _tmpbuf[i]=NULL; inbuf[i]=NULL; 1570 } 1571 1572 if((this->init&DECOMPRESS)==0) 1573 _throw("tjDecodeYUVPlanes(): Instance has not been initialized for decompression"); 1574 1575 if(!srcPlanes || !srcPlanes[0] || subsamp<0 || subsamp>=NUMSUBOPT 1576 || dstBuf==NULL || width<=0 || pitch<0 || height<=0 || pixelFormat<0 1577 || pixelFormat>=TJ_NUMPF) 1578 _throw("tjDecodeYUVPlanes(): Invalid argument"); 1579 if(subsamp!=TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2])) 1580 _throw("tjDecodeYUVPlanes(): Invalid argument"); 1581 1582 if(setjmp(this->jerr.setjmp_buffer)) 1583 { 1584 /* If we get here, the JPEG code has signaled an error. */ 1585 retval=-1; goto bailout; 1586 } 1587 1588 if(pixelFormat==TJPF_CMYK) 1589 _throw("tjDecodeYUVPlanes(): Cannot decode YUV images into CMYK pixels."); 1590 1591 if(pitch==0) pitch=width*tjPixelSize[pixelFormat]; 1592 dinfo->image_width=width; 1593 dinfo->image_height=height; 1594 1595 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); 1596 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); 1597 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); 1598 1599 if(setDecodeDefaults(dinfo, pixelFormat, subsamp, flags)==-1) 1600 { 1601 retval=-1; goto bailout; 1602 } 1603 old_read_markers=dinfo->marker->read_markers; 1604 dinfo->marker->read_markers=my_read_markers; 1605 old_reset_marker_reader=dinfo->marker->reset_marker_reader; 1606 dinfo->marker->reset_marker_reader=my_reset_marker_reader; 1607 jpeg_read_header(dinfo, TRUE); 1608 dinfo->marker->read_markers=old_read_markers; 1609 dinfo->marker->reset_marker_reader=old_reset_marker_reader; 1610 1611 if(setDecompDefaults(dinfo, pixelFormat, flags)==-1) 1612 { 1613 retval=-1; goto bailout; 1614 } 1615 dinfo->do_fancy_upsampling=FALSE; 1616 dinfo->Se=DCTSIZE2-1; 1617 jinit_master_decompress(dinfo); 1618 (*dinfo->upsample->start_pass)(dinfo); 1619 1620 pw0=PAD(width, dinfo->max_h_samp_factor); 1621 ph0=PAD(height, dinfo->max_v_samp_factor); 1622 1623 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat]; 1624 1625 #ifndef JCS_EXTENSIONS 1626 if(pixelFormat!=TJPF_GRAY && pixelFormat!=TJPF_CMYK && 1627 (RGB_RED!=tjRedOffset[pixelFormat] || 1628 RGB_GREEN!=tjGreenOffset[pixelFormat] || 1629 RGB_BLUE!=tjBlueOffset[pixelFormat] || 1630 RGB_PIXELSIZE!=tjPixelSize[pixelFormat])) 1631 { 1632 rgbBuf=(unsigned char *)malloc(width*height*3); 1633 if(!rgbBuf) _throw("tjDecodeYUVPlanes(): Memory allocation failure"); 1634 _pitch=pitch; pitch=width*3; 1635 _dstBuf=dstBuf; dstBuf=rgbBuf; 1636 } 1637 #endif 1638 1639 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph0))==NULL) 1640 _throw("tjDecodeYUVPlanes(): Memory allocation failure"); 1641 for(i=0; i<height; i++) 1642 { 1643 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&dstBuf[(height-i-1)*pitch]; 1644 else row_pointer[i]=&dstBuf[i*pitch]; 1645 } 1646 if(height<ph0) 1647 for(i=height; i<ph0; i++) row_pointer[i]=row_pointer[height-1]; 1648 1649 for(i=0; i<dinfo->num_components; i++) 1650 { 1651 compptr=&dinfo->comp_info[i]; 1652 _tmpbuf[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16) 1653 * compptr->v_samp_factor + 16); 1654 if(!_tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure"); 1655 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor); 1656 if(!tmpbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure"); 1657 for(row=0; row<compptr->v_samp_factor; row++) 1658 { 1659 unsigned char *_tmpbuf_aligned= 1660 (unsigned char *)PAD((size_t)_tmpbuf[i], 16); 1661 tmpbuf[i][row]=&_tmpbuf_aligned[ 1662 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row]; 1663 } 1664 pw[i]=pw0*compptr->h_samp_factor/dinfo->max_h_samp_factor; 1665 ph[i]=ph0*compptr->v_samp_factor/dinfo->max_v_samp_factor; 1666 inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]); 1667 if(!inbuf[i]) _throw("tjDecodeYUVPlanes(): Memory allocation failure"); 1668 ptr=(JSAMPLE *)srcPlanes[i]; 1669 for(row=0; row<ph[i]; row++) 1670 { 1671 inbuf[i][row]=ptr; 1672 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i]; 1673 } 1674 } 1675 1676 if(setjmp(this->jerr.setjmp_buffer)) 1677 { 1678 /* If we get here, the JPEG code has signaled an error. */ 1679 retval=-1; goto bailout; 1680 } 1681 1682 for(row=0; row<ph0; row+=dinfo->max_v_samp_factor) 1683 { 1684 JDIMENSION inrow=0, outrow=0; 1685 for(i=0, compptr=dinfo->comp_info; i<dinfo->num_components; i++, compptr++) 1686 jcopy_sample_rows(inbuf[i], 1687 row*compptr->v_samp_factor/dinfo->max_v_samp_factor, tmpbuf[i], 0, 1688 compptr->v_samp_factor, pw[i]); 1689 (dinfo->upsample->upsample)(dinfo, tmpbuf, &inrow, 1690 dinfo->max_v_samp_factor, &row_pointer[row], &outrow, 1691 dinfo->max_v_samp_factor); 1692 } 1693 jpeg_abort_decompress(dinfo); 1694 1695 #ifndef JCS_EXTENSIONS 1696 fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat); 1697 #endif 1698 1699 bailout: 1700 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo); 1701 #ifndef JCS_EXTENSIONS 1702 if(rgbBuf) free(rgbBuf); 1703 #endif 1704 if(row_pointer) free(row_pointer); 1705 for(i=0; i<MAX_COMPONENTS; i++) 1706 { 1707 if(tmpbuf[i]!=NULL) free(tmpbuf[i]); 1708 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]); 1709 if(inbuf[i]!=NULL) free(inbuf[i]); 1710 } 1711 if(this->jerr.warning) retval=-1; 1712 return retval; 1713 } 1714 1715 DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, const unsigned char *srcBuf, 1716 int pad, int subsamp, unsigned char *dstBuf, int width, int pitch, 1717 int height, int pixelFormat, int flags) 1718 { 1719 const unsigned char *srcPlanes[3]; 1720 int pw0, ph0, strides[3], retval=-1; 1721 1722 if(srcBuf==NULL || pad<0 || !isPow2(pad) || subsamp<0 || subsamp>=NUMSUBOPT 1723 || width<=0 || height<=0) 1724 _throw("tjDecodeYUV(): Invalid argument"); 1725 1726 pw0=tjPlaneWidth(0, width, subsamp); 1727 ph0=tjPlaneHeight(0, height, subsamp); 1728 srcPlanes[0]=srcBuf; 1729 strides[0]=PAD(pw0, pad); 1730 if(subsamp==TJSAMP_GRAY) 1731 { 1732 strides[1]=strides[2]=0; 1733 srcPlanes[1]=srcPlanes[2]=NULL; 1734 } 1735 else 1736 { 1737 int pw1=tjPlaneWidth(1, width, subsamp); 1738 int ph1=tjPlaneHeight(1, height, subsamp); 1739 strides[1]=strides[2]=PAD(pw1, pad); 1740 srcPlanes[1]=srcPlanes[0]+strides[0]*ph0; 1741 srcPlanes[2]=srcPlanes[1]+strides[1]*ph1; 1742 } 1743 1744 return tjDecodeYUVPlanes(handle, srcPlanes, strides, subsamp, dstBuf, width, 1745 pitch, height, pixelFormat, flags); 1746 1747 bailout: 1748 return retval; 1749 } 1750 1751 DLLEXPORT int DLLCALL tjDecompressToYUVPlanes(tjhandle handle, 1752 const unsigned char *jpegBuf, unsigned long jpegSize, 1753 unsigned char **dstPlanes, int width, int *strides, int height, int flags) 1754 { 1755 int i, sfi, row, retval=0; JSAMPROW *outbuf[MAX_COMPONENTS]; 1756 int jpegwidth, jpegheight, jpegSubsamp, scaledw, scaledh; 1757 int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS], 1758 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS]; 1759 JSAMPLE *_tmpbuf=NULL, *ptr; JSAMPROW *tmpbuf[MAX_COMPONENTS]; 1760 int dctsize; 1761 1762 getdinstance(handle); 1763 1764 for(i=0; i<MAX_COMPONENTS; i++) 1765 { 1766 tmpbuf[i]=NULL; outbuf[i]=NULL; 1767 } 1768 1769 if((this->init&DECOMPRESS)==0) 1770 _throw("tjDecompressToYUVPlanes(): Instance has not been initialized for decompression"); 1771 1772 if(jpegBuf==NULL || jpegSize<=0 || !dstPlanes || !dstPlanes[0] || width<0 1773 || height<0) 1774 _throw("tjDecompressToYUVPlanes(): Invalid argument"); 1775 1776 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); 1777 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); 1778 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); 1779 1780 if(setjmp(this->jerr.setjmp_buffer)) 1781 { 1782 /* If we get here, the JPEG code has signaled an error. */ 1783 retval=-1; goto bailout; 1784 } 1785 1786 if(!this->headerRead) 1787 { 1788 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); 1789 jpeg_read_header(dinfo, TRUE); 1790 } 1791 this->headerRead=0; 1792 jpegSubsamp=getSubsamp(dinfo); 1793 if(jpegSubsamp<0) 1794 _throw("tjDecompressToYUVPlanes(): Could not determine subsampling type for JPEG image"); 1795 1796 if(jpegSubsamp!=TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2])) 1797 _throw("tjDecompressToYUVPlanes(): Invalid argument"); 1798 1799 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height; 1800 if(width==0) width=jpegwidth; 1801 if(height==0) height=jpegheight; 1802 for(i=0; i<NUMSF; i++) 1803 { 1804 scaledw=TJSCALED(jpegwidth, sf[i]); 1805 scaledh=TJSCALED(jpegheight, sf[i]); 1806 if(scaledw<=width && scaledh<=height) 1807 break; 1808 } 1809 if(i>=NUMSF) 1810 _throw("tjDecompressToYUVPlanes(): Could not scale down to desired image dimensions"); 1811 if(dinfo->num_components>3) 1812 _throw("tjDecompressToYUVPlanes(): JPEG image must have 3 or fewer components"); 1813 1814 width=scaledw; height=scaledh; 1815 dinfo->scale_num=sf[i].num; 1816 dinfo->scale_denom=sf[i].denom; 1817 sfi=i; 1818 jpeg_calc_output_dimensions(dinfo); 1819 1820 dctsize=DCTSIZE*sf[sfi].num/sf[sfi].denom; 1821 1822 for(i=0; i<dinfo->num_components; i++) 1823 { 1824 jpeg_component_info *compptr=&dinfo->comp_info[i]; 1825 int ih; 1826 iw[i]=compptr->width_in_blocks*dctsize; 1827 ih=compptr->height_in_blocks*dctsize; 1828 pw[i]=PAD(dinfo->output_width, dinfo->max_h_samp_factor) 1829 *compptr->h_samp_factor/dinfo->max_h_samp_factor; 1830 ph[i]=PAD(dinfo->output_height, dinfo->max_v_samp_factor) 1831 *compptr->v_samp_factor/dinfo->max_v_samp_factor; 1832 if(iw[i]!=pw[i] || ih!=ph[i]) usetmpbuf=1; 1833 th[i]=compptr->v_samp_factor*dctsize; 1834 tmpbufsize+=iw[i]*th[i]; 1835 if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph[i]))==NULL) 1836 _throw("tjDecompressToYUVPlanes(): Memory allocation failure"); 1837 ptr=dstPlanes[i]; 1838 for(row=0; row<ph[i]; row++) 1839 { 1840 outbuf[i][row]=ptr; 1841 ptr+=(strides && strides[i]!=0)? strides[i]:pw[i]; 1842 } 1843 } 1844 if(usetmpbuf) 1845 { 1846 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL) 1847 _throw("tjDecompressToYUVPlanes(): Memory allocation failure"); 1848 ptr=_tmpbuf; 1849 for(i=0; i<dinfo->num_components; i++) 1850 { 1851 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL) 1852 _throw("tjDecompressToYUVPlanes(): Memory allocation failure"); 1853 for(row=0; row<th[i]; row++) 1854 { 1855 tmpbuf[i][row]=ptr; 1856 ptr+=iw[i]; 1857 } 1858 } 1859 } 1860 1861 if(setjmp(this->jerr.setjmp_buffer)) 1862 { 1863 /* If we get here, the JPEG code has signaled an error. */ 1864 retval=-1; goto bailout; 1865 } 1866 1867 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE; 1868 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST; 1869 dinfo->raw_data_out=TRUE; 1870 1871 jpeg_start_decompress(dinfo); 1872 for(row=0; row<(int)dinfo->output_height; 1873 row+=dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size) 1874 { 1875 JSAMPARRAY yuvptr[MAX_COMPONENTS]; 1876 int crow[MAX_COMPONENTS]; 1877 for(i=0; i<dinfo->num_components; i++) 1878 { 1879 jpeg_component_info *compptr=&dinfo->comp_info[i]; 1880 if(jpegSubsamp==TJ_420) 1881 { 1882 /* When 4:2:0 subsampling is used with IDCT scaling, libjpeg will try 1883 to be clever and use the IDCT to perform upsampling on the U and V 1884 planes. For instance, if the output image is to be scaled by 1/2 1885 relative to the JPEG image, then the scaling factor and upsampling 1886 effectively cancel each other, so a normal 8x8 IDCT can be used. 1887 However, this is not desirable when using the decompress-to-YUV 1888 functionality in TurboJPEG, since we want to output the U and V 1889 planes in their subsampled form. Thus, we have to override some 1890 internal libjpeg parameters to force it to use the "scaled" IDCT 1891 functions on the U and V planes. */ 1892 compptr->_DCT_scaled_size=dctsize; 1893 compptr->MCU_sample_width=tjMCUWidth[jpegSubsamp]* 1894 sf[sfi].num/sf[sfi].denom* 1895 compptr->v_samp_factor/dinfo->max_v_samp_factor; 1896 dinfo->idct->inverse_DCT[i] = dinfo->idct->inverse_DCT[0]; 1897 } 1898 crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor; 1899 if(usetmpbuf) yuvptr[i]=tmpbuf[i]; 1900 else yuvptr[i]=&outbuf[i][crow[i]]; 1901 } 1902 jpeg_read_raw_data(dinfo, yuvptr, 1903 dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size); 1904 if(usetmpbuf) 1905 { 1906 int j; 1907 for(i=0; i<dinfo->num_components; i++) 1908 { 1909 for(j=0; j<min(th[i], ph[i]-crow[i]); j++) 1910 { 1911 memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], pw[i]); 1912 } 1913 } 1914 } 1915 } 1916 jpeg_finish_decompress(dinfo); 1917 1918 bailout: 1919 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo); 1920 for(i=0; i<MAX_COMPONENTS; i++) 1921 { 1922 if(tmpbuf[i]) free(tmpbuf[i]); 1923 if(outbuf[i]) free(outbuf[i]); 1924 } 1925 if(_tmpbuf) free(_tmpbuf); 1926 if(this->jerr.warning) retval=-1; 1927 return retval; 1928 } 1929 1930 DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle, 1931 const unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf, 1932 int width, int pad, int height, int flags) 1933 { 1934 unsigned char *dstPlanes[3]; 1935 int pw0, ph0, strides[3], retval=-1, jpegSubsamp=-1; 1936 int i, jpegwidth, jpegheight, scaledw, scaledh; 1937 1938 getdinstance(handle); 1939 1940 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pad<1 1941 || !isPow2(pad) || height<0) 1942 _throw("tjDecompressToYUV2(): Invalid argument"); 1943 1944 if(setjmp(this->jerr.setjmp_buffer)) 1945 { 1946 /* If we get here, the JPEG code has signaled an error. */ 1947 return -1; 1948 } 1949 1950 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); 1951 jpeg_read_header(dinfo, TRUE); 1952 jpegSubsamp=getSubsamp(dinfo); 1953 if(jpegSubsamp<0) 1954 _throw("tjDecompressToYUV2(): Could not determine subsampling type for JPEG image"); 1955 1956 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height; 1957 if(width==0) width=jpegwidth; 1958 if(height==0) height=jpegheight; 1959 1960 for(i=0; i<NUMSF; i++) 1961 { 1962 scaledw=TJSCALED(jpegwidth, sf[i]); 1963 scaledh=TJSCALED(jpegheight, sf[i]); 1964 if(scaledw<=width && scaledh<=height) 1965 break; 1966 } 1967 if(i>=NUMSF) 1968 _throw("tjDecompressToYUV2(): Could not scale down to desired image dimensions"); 1969 1970 pw0=tjPlaneWidth(0, width, jpegSubsamp); 1971 ph0=tjPlaneHeight(0, height, jpegSubsamp); 1972 dstPlanes[0]=dstBuf; 1973 strides[0]=PAD(pw0, pad); 1974 if(jpegSubsamp==TJSAMP_GRAY) 1975 { 1976 strides[1]=strides[2]=0; 1977 dstPlanes[1]=dstPlanes[2]=NULL; 1978 } 1979 else 1980 { 1981 int pw1=tjPlaneWidth(1, width, jpegSubsamp); 1982 int ph1=tjPlaneHeight(1, height, jpegSubsamp); 1983 strides[1]=strides[2]=PAD(pw1, pad); 1984 dstPlanes[1]=dstPlanes[0]+strides[0]*ph0; 1985 dstPlanes[2]=dstPlanes[1]+strides[1]*ph1; 1986 } 1987 1988 this->headerRead=1; 1989 return tjDecompressToYUVPlanes(handle, jpegBuf, jpegSize, dstPlanes, width, 1990 strides, height, flags); 1991 1992 bailout: 1993 return retval; 1994 1995 } 1996 1997 DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle, 1998 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf, 1999 int flags) 2000 { 2001 return tjDecompressToYUV2(handle, jpegBuf, jpegSize, dstBuf, 0, 4, 0, flags); 2002 } 2003 2004 2005 /* Transformer */ 2006 2007 DLLEXPORT tjhandle DLLCALL tjInitTransform(void) 2008 { 2009 tjinstance *this=NULL; tjhandle handle=NULL; 2010 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL) 2011 { 2012 snprintf(errStr, JMSG_LENGTH_MAX, 2013 "tjInitTransform(): Memory allocation failure"); 2014 return NULL; 2015 } 2016 MEMZERO(this, sizeof(tjinstance)); 2017 handle=_tjInitCompress(this); 2018 if(!handle) return NULL; 2019 handle=_tjInitDecompress(this); 2020 return handle; 2021 } 2022 2023 2024 DLLEXPORT int DLLCALL tjTransform(tjhandle handle, 2025 const unsigned char *jpegBuf, unsigned long jpegSize, int n, 2026 unsigned char **dstBufs, unsigned long *dstSizes, tjtransform *t, int flags) 2027 { 2028 jpeg_transform_info *xinfo=NULL; 2029 jvirt_barray_ptr *srccoefs, *dstcoefs; 2030 int retval=0, i, jpegSubsamp; 2031 2032 getinstance(handle); 2033 if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0) 2034 _throw("tjTransform(): Instance has not been initialized for transformation"); 2035 2036 if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL 2037 || t==NULL || flags<0) 2038 _throw("tjTransform(): Invalid argument"); 2039 2040 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); 2041 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); 2042 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); 2043 2044 if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n)) 2045 ==NULL) 2046 _throw("tjTransform(): Memory allocation failure"); 2047 MEMZERO(xinfo, sizeof(jpeg_transform_info)*n); 2048 2049 if(setjmp(this->jerr.setjmp_buffer)) 2050 { 2051 /* If we get here, the JPEG code has signaled an error. */ 2052 retval=-1; goto bailout; 2053 } 2054 2055 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); 2056 2057 for(i=0; i<n; i++) 2058 { 2059 xinfo[i].transform=xformtypes[t[i].op]; 2060 xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0; 2061 xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0; 2062 xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0; 2063 xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0; 2064 if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1; 2065 else xinfo[i].slow_hflip=0; 2066 2067 if(xinfo[i].crop) 2068 { 2069 xinfo[i].crop_xoffset=t[i].r.x; xinfo[i].crop_xoffset_set=JCROP_POS; 2070 xinfo[i].crop_yoffset=t[i].r.y; xinfo[i].crop_yoffset_set=JCROP_POS; 2071 if(t[i].r.w!=0) 2072 { 2073 xinfo[i].crop_width=t[i].r.w; xinfo[i].crop_width_set=JCROP_POS; 2074 } 2075 else xinfo[i].crop_width=JCROP_UNSET; 2076 if(t[i].r.h!=0) 2077 { 2078 xinfo[i].crop_height=t[i].r.h; xinfo[i].crop_height_set=JCROP_POS; 2079 } 2080 else xinfo[i].crop_height=JCROP_UNSET; 2081 } 2082 } 2083 2084 jcopy_markers_setup(dinfo, JCOPYOPT_ALL); 2085 jpeg_read_header(dinfo, TRUE); 2086 jpegSubsamp=getSubsamp(dinfo); 2087 if(jpegSubsamp<0) 2088 _throw("tjTransform(): Could not determine subsampling type for JPEG image"); 2089 2090 for(i=0; i<n; i++) 2091 { 2092 if(!jtransform_request_workspace(dinfo, &xinfo[i])) 2093 _throw("tjTransform(): Transform is not perfect"); 2094 2095 if(xinfo[i].crop) 2096 { 2097 if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0 2098 || (t[i].r.y%xinfo[i].iMCU_sample_height)!=0) 2099 { 2100 snprintf(errStr, JMSG_LENGTH_MAX, 2101 "To crop this JPEG image, x must be a multiple of %d\n" 2102 "and y must be a multiple of %d.\n", 2103 xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height); 2104 retval=-1; goto bailout; 2105 } 2106 } 2107 } 2108 2109 srccoefs=jpeg_read_coefficients(dinfo); 2110 2111 for(i=0; i<n; i++) 2112 { 2113 int w, h, alloc=1; 2114 if(!xinfo[i].crop) 2115 { 2116 w=dinfo->image_width; h=dinfo->image_height; 2117 } 2118 else 2119 { 2120 w=xinfo[i].crop_width; h=xinfo[i].crop_height; 2121 } 2122 if(flags&TJFLAG_NOREALLOC) 2123 { 2124 alloc=0; dstSizes[i]=tjBufSize(w, h, jpegSubsamp); 2125 } 2126 if(!(t[i].options&TJXOPT_NOOUTPUT)) 2127 jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc); 2128 jpeg_copy_critical_parameters(dinfo, cinfo); 2129 dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs, 2130 &xinfo[i]); 2131 if(!(t[i].options&TJXOPT_NOOUTPUT)) 2132 { 2133 jpeg_write_coefficients(cinfo, dstcoefs); 2134 jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL); 2135 } 2136 else jinit_c_master_control(cinfo, TRUE); 2137 jtransform_execute_transformation(dinfo, cinfo, srccoefs, 2138 &xinfo[i]); 2139 if(t[i].customFilter) 2140 { 2141 int ci, y; JDIMENSION by; 2142 for(ci=0; ci<cinfo->num_components; ci++) 2143 { 2144 jpeg_component_info *compptr=&cinfo->comp_info[ci]; 2145 tjregion arrayRegion={0, 0, compptr->width_in_blocks*DCTSIZE, 2146 DCTSIZE}; 2147 tjregion planeRegion={0, 0, compptr->width_in_blocks*DCTSIZE, 2148 compptr->height_in_blocks*DCTSIZE}; 2149 for(by=0; by<compptr->height_in_blocks; by+=compptr->v_samp_factor) 2150 { 2151 JBLOCKARRAY barray=(dinfo->mem->access_virt_barray) 2152 ((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor, 2153 TRUE); 2154 for(y=0; y<compptr->v_samp_factor; y++) 2155 { 2156 if(t[i].customFilter(barray[y][0], arrayRegion, planeRegion, 2157 ci, i, &t[i])==-1) 2158 _throw("tjTransform(): Error in custom filter"); 2159 arrayRegion.y+=DCTSIZE; 2160 } 2161 } 2162 } 2163 } 2164 if(!(t[i].options&TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo); 2165 } 2166 2167 jpeg_finish_decompress(dinfo); 2168 2169 bailout: 2170 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo); 2171 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo); 2172 if(xinfo) free(xinfo); 2173 if(this->jerr.warning) retval=-1; 2174 return retval; 2175 } 2176