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