turbojpeg.c revision 006bc58dd6a8c68f4b3a26511e8684f5f3f1508a
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 jpeg_mem_dest_tj(cinfo, &dstBuf, &yuvsize, 0); 760 if(setCompDefaults(cinfo, pixelFormat, subsamp, -1, flags)==-1) return -1; 761 762 /* Execute only the parts of jpeg_start_compress() that we need. If we 763 were to call the whole jpeg_start_compress() function, then it would try 764 to write the file headers, which could overflow the output buffer if the 765 YUV image were very small. */ 766 if(cinfo->global_state!=CSTATE_START) 767 _throw("tjEncodeYUV3(): libjpeg API is in the wrong state"); 768 (*cinfo->err->reset_error_mgr)((j_common_ptr)cinfo); 769 (*cinfo->dest->init_destination)(cinfo); 770 jinit_c_master_control(cinfo, FALSE); 771 jinit_color_converter(cinfo); 772 jinit_downsampler(cinfo); 773 jinit_c_prep_controller(cinfo, FALSE); 774 (*cinfo->mem->realize_virt_arrays)((j_common_ptr)cinfo); 775 776 pw=PAD(width, cinfo->max_h_samp_factor); 777 ph=PAD(height, cinfo->max_v_samp_factor); 778 779 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ph))==NULL) 780 _throw("tjEncodeYUV3(): Memory allocation failure"); 781 for(i=0; i<height; i++) 782 { 783 if(flags&TJFLAG_BOTTOMUP) row_pointer[i]=&srcBuf[(height-i-1)*pitch]; 784 else row_pointer[i]=&srcBuf[i*pitch]; 785 } 786 if(height<ph) 787 for(i=height; i<ph; i++) row_pointer[i]=row_pointer[height-1]; 788 789 for(i=0; i<cinfo->num_components; i++) 790 { 791 compptr=&cinfo->comp_info[i]; 792 _tmpbuf[i]=(JSAMPLE *)malloc( 793 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE) 794 /compptr->h_samp_factor, 16) * cinfo->max_v_samp_factor + 16); 795 if(!_tmpbuf[i]) _throw("tjEncodeYUV3(): Memory allocation failure"); 796 tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*cinfo->max_v_samp_factor); 797 if(!tmpbuf[i]) _throw("tjEncodeYUV3(): Memory allocation failure"); 798 for(row=0; row<cinfo->max_v_samp_factor; row++) 799 { 800 unsigned char *_tmpbuf_aligned= 801 (unsigned char *)PAD((size_t)_tmpbuf[i], 16); 802 tmpbuf[i][row]=&_tmpbuf_aligned[ 803 PAD((compptr->width_in_blocks*cinfo->max_h_samp_factor*DCTSIZE) 804 /compptr->h_samp_factor, 16) * row]; 805 } 806 _tmpbuf2[i]=(JSAMPLE *)malloc(PAD(compptr->width_in_blocks*DCTSIZE, 16) 807 * compptr->v_samp_factor + 16); 808 if(!_tmpbuf2[i]) _throw("tjEncodeYUV3(): Memory allocation failure"); 809 tmpbuf2[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*compptr->v_samp_factor); 810 if(!tmpbuf2[i]) _throw("tjEncodeYUV3(): Memory allocation failure"); 811 for(row=0; row<compptr->v_samp_factor; row++) 812 { 813 unsigned char *_tmpbuf2_aligned= 814 (unsigned char *)PAD((size_t)_tmpbuf2[i], 16); 815 tmpbuf2[i][row]=&_tmpbuf2_aligned[ 816 PAD(compptr->width_in_blocks*DCTSIZE, 16) * row]; 817 } 818 cw[i]=pw*compptr->h_samp_factor/cinfo->max_h_samp_factor; 819 ch[i]=ph*compptr->v_samp_factor/cinfo->max_v_samp_factor; 820 outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]); 821 if(!outbuf[i]) _throw("tjEncodeYUV3(): Memory allocation failure"); 822 for(row=0; row<ch[i]; row++) 823 { 824 outbuf[i][row]=ptr; 825 ptr+=PAD(cw[i], pad); 826 } 827 } 828 if(yuvsize!=(unsigned long)(ptr-dstBuf)) 829 _throw("tjEncodeYUV3(): Generated image is not the correct size"); 830 831 for(row=0; row<ph; row+=cinfo->max_v_samp_factor) 832 { 833 (*cinfo->cconvert->color_convert)(cinfo, &row_pointer[row], tmpbuf, 0, 834 cinfo->max_v_samp_factor); 835 (cinfo->downsample->downsample)(cinfo, tmpbuf, 0, tmpbuf2, 0); 836 for(i=0, compptr=cinfo->comp_info; i<cinfo->num_components; i++, compptr++) 837 jcopy_sample_rows(tmpbuf2[i], 0, outbuf[i], 838 row*compptr->v_samp_factor/cinfo->max_v_samp_factor, 839 compptr->v_samp_factor, cw[i]); 840 } 841 cinfo->next_scanline+=height; 842 jpeg_abort_compress(cinfo); 843 844 bailout: 845 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo); 846 #ifndef JCS_EXTENSIONS 847 if(rgbBuf) free(rgbBuf); 848 #endif 849 if(row_pointer) free(row_pointer); 850 for(i=0; i<MAX_COMPONENTS; i++) 851 { 852 if(tmpbuf[i]!=NULL) free(tmpbuf[i]); 853 if(_tmpbuf[i]!=NULL) free(_tmpbuf[i]); 854 if(tmpbuf2[i]!=NULL) free(tmpbuf2[i]); 855 if(_tmpbuf2[i]!=NULL) free(_tmpbuf2[i]); 856 if(outbuf[i]!=NULL) free(outbuf[i]); 857 } 858 return retval; 859} 860 861DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf, 862 int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf, 863 int subsamp, int flags) 864{ 865 return tjEncodeYUV3(handle, srcBuf, width, pitch, height, pixelFormat, 866 dstBuf, 4, subsamp, flags); 867} 868 869DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle handle, unsigned char *srcBuf, 870 int width, int pitch, int height, int pixelSize, unsigned char *dstBuf, 871 int subsamp, int flags) 872{ 873 return tjEncodeYUV2(handle, srcBuf, width, pitch, height, 874 getPixelFormat(pixelSize, flags), dstBuf, subsamp, flags); 875} 876 877 878DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle, unsigned char *srcBuf, 879 int width, int pad, int height, int subsamp, unsigned char **jpegBuf, 880 unsigned long *jpegSize, int jpegQual, int flags) 881{ 882 int i, row, retval=0, alloc=1; JSAMPROW *inbuf[MAX_COMPONENTS]; 883 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS], 884 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS]; 885 JSAMPLE *_tmpbuf=NULL, *ptr=srcBuf; JSAMPROW *tmpbuf[MAX_COMPONENTS]; 886 887 getinstance(handle) 888 889 for(i=0; i<MAX_COMPONENTS; i++) 890 { 891 tmpbuf[i]=NULL; inbuf[i]=NULL; 892 } 893 894 if((this->init&COMPRESS)==0) 895 _throw("tjCompressFromYUV(): Instance has not been initialized for compression"); 896 897 if(srcBuf==NULL || width<=0 || pad<1 || height<=0 || subsamp<0 898 || subsamp>=NUMSUBOPT || jpegBuf==NULL || jpegSize==NULL || jpegQual<0 899 || jpegQual>100) 900 _throw("tjCompressFromYUV(): Invalid argument"); 901 902 if(setjmp(this->jerr.setjmp_buffer)) 903 { 904 /* If we get here, the JPEG code has signaled an error. */ 905 retval=-1; 906 goto bailout; 907 } 908 909 cinfo->image_width=width; 910 cinfo->image_height=height; 911 912 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); 913 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); 914 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); 915 916 if(flags&TJFLAG_NOREALLOC) 917 { 918 alloc=0; *jpegSize=tjBufSize(width, height, subsamp); 919 } 920 jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc); 921 if(setCompDefaults(cinfo, TJPF_RGB, subsamp, jpegQual, flags)==-1) 922 return -1; 923 cinfo->raw_data_in=TRUE; 924 925 jpeg_start_compress(cinfo, TRUE); 926 for(i=0; i<cinfo->num_components; i++) 927 { 928 jpeg_component_info *compptr=&cinfo->comp_info[i]; 929 int ih; 930 iw[i]=compptr->width_in_blocks*DCTSIZE; 931 ih=compptr->height_in_blocks*DCTSIZE; 932 cw[i]=PAD(cinfo->image_width, cinfo->max_h_samp_factor) 933 *compptr->h_samp_factor/cinfo->max_h_samp_factor; 934 ch[i]=PAD(cinfo->image_height, cinfo->max_v_samp_factor) 935 *compptr->v_samp_factor/cinfo->max_v_samp_factor; 936 if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1; 937 th[i]=compptr->v_samp_factor*DCTSIZE; 938 tmpbufsize+=iw[i]*th[i]; 939 if((inbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL) 940 _throw("tjCompressFromYUV(): Memory allocation failure"); 941 for(row=0; row<ch[i]; row++) 942 { 943 inbuf[i][row]=ptr; 944 ptr+=PAD(cw[i], pad); 945 } 946 } 947 if(usetmpbuf) 948 { 949 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL) 950 _throw("tjCompressFromYUV(): Memory allocation failure"); 951 ptr=_tmpbuf; 952 for(i=0; i<cinfo->num_components; i++) 953 { 954 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL) 955 _throw("tjCompressFromYUV(): Memory allocation failure"); 956 for(row=0; row<th[i]; row++) 957 { 958 tmpbuf[i][row]=ptr; 959 ptr+=iw[i]; 960 } 961 } 962 } 963 964 for(row=0; row<(int)cinfo->image_height; 965 row+=cinfo->max_v_samp_factor*DCTSIZE) 966 { 967 JSAMPARRAY yuvptr[MAX_COMPONENTS]; 968 int crow[MAX_COMPONENTS]; 969 for(i=0; i<cinfo->num_components; i++) 970 { 971 jpeg_component_info *compptr=&cinfo->comp_info[i]; 972 crow[i]=row*compptr->v_samp_factor/cinfo->max_v_samp_factor; 973 if(usetmpbuf) 974 { 975 int j, k; 976 for(j=0; j<min(th[i], ch[i]-crow[i]); j++) 977 { 978 memcpy(tmpbuf[i][j], inbuf[i][crow[i]+j], cw[i]); 979 /* Duplicate last sample in row to fill out MCU */ 980 for(k=cw[i]; k<iw[i]; k++) tmpbuf[i][j][k]=tmpbuf[i][j][cw[i]-1]; 981 } 982 /* Duplicate last row to fill out MCU */ 983 for(j=ch[i]-crow[i]; j<th[i]; j++) 984 memcpy(tmpbuf[i][j], tmpbuf[i][ch[i]-crow[i]-1], iw[i]); 985 yuvptr[i]=tmpbuf[i]; 986 } 987 else 988 yuvptr[i]=&inbuf[i][crow[i]]; 989 } 990 jpeg_write_raw_data(cinfo, yuvptr, cinfo->max_v_samp_factor*DCTSIZE); 991 } 992 jpeg_finish_compress(cinfo); 993 994 bailout: 995 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo); 996 for(i=0; i<MAX_COMPONENTS; i++) 997 { 998 if(tmpbuf[i]) free(tmpbuf[i]); 999 if(inbuf[i]) free(inbuf[i]); 1000 } 1001 if(_tmpbuf) free(_tmpbuf); 1002 return retval; 1003} 1004 1005 1006/* Decompressor */ 1007 1008static tjhandle _tjInitDecompress(tjinstance *this) 1009{ 1010 unsigned char buffer[1]; 1011 1012 /* This is also straight out of example.c */ 1013 this->dinfo.err=jpeg_std_error(&this->jerr.pub); 1014 this->jerr.pub.error_exit=my_error_exit; 1015 this->jerr.pub.output_message=my_output_message; 1016 1017 if(setjmp(this->jerr.setjmp_buffer)) 1018 { 1019 /* If we get here, the JPEG code has signaled an error. */ 1020 if(this) free(this); return NULL; 1021 } 1022 1023 jpeg_create_decompress(&this->dinfo); 1024 /* Make an initial call so it will create the source manager */ 1025 jpeg_mem_src_tj(&this->dinfo, buffer, 1); 1026 1027 this->init|=DECOMPRESS; 1028 return (tjhandle)this; 1029} 1030 1031DLLEXPORT tjhandle DLLCALL tjInitDecompress(void) 1032{ 1033 tjinstance *this; 1034 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL) 1035 { 1036 snprintf(errStr, JMSG_LENGTH_MAX, 1037 "tjInitDecompress(): Memory allocation failure"); 1038 return NULL; 1039 } 1040 MEMZERO(this, sizeof(tjinstance)); 1041 return _tjInitDecompress(this); 1042} 1043 1044 1045DLLEXPORT int DLLCALL tjDecompressHeader3(tjhandle handle, 1046 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height, 1047 int *jpegSubsamp, int *jpegColorspace) 1048{ 1049 int retval=0; 1050 1051 getinstance(handle); 1052 if((this->init&DECOMPRESS)==0) 1053 _throw("tjDecompressHeader3(): Instance has not been initialized for decompression"); 1054 1055 if(jpegBuf==NULL || jpegSize<=0 || width==NULL || height==NULL 1056 || jpegSubsamp==NULL || jpegColorspace==NULL) 1057 _throw("tjDecompressHeader3(): Invalid argument"); 1058 1059 if(setjmp(this->jerr.setjmp_buffer)) 1060 { 1061 /* If we get here, the JPEG code has signaled an error. */ 1062 return -1; 1063 } 1064 1065 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); 1066 jpeg_read_header(dinfo, TRUE); 1067 1068 *width=dinfo->image_width; 1069 *height=dinfo->image_height; 1070 *jpegSubsamp=getSubsamp(dinfo); 1071 switch(dinfo->jpeg_color_space) 1072 { 1073 case JCS_GRAYSCALE: *jpegColorspace=TJCS_GRAY; break; 1074 case JCS_RGB: *jpegColorspace=TJCS_RGB; break; 1075 case JCS_YCbCr: *jpegColorspace=TJCS_YCbCr; break; 1076 case JCS_CMYK: *jpegColorspace=TJCS_CMYK; break; 1077 case JCS_YCCK: *jpegColorspace=TJCS_YCCK; break; 1078 default: *jpegColorspace=-1; break; 1079 } 1080 1081 jpeg_abort_decompress(dinfo); 1082 1083 if(*jpegSubsamp<0) 1084 _throw("tjDecompressHeader3(): Could not determine subsampling type for JPEG image"); 1085 if(*jpegColorspace<0) 1086 _throw("tjDecompressHeader3(): Could not determine colorspace of JPEG image"); 1087 if(*width<1 || *height<1) 1088 _throw("tjDecompressHeader3(): Invalid data returned in header"); 1089 1090 bailout: 1091 return retval; 1092} 1093 1094DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle handle, 1095 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height, 1096 int *jpegSubsamp) 1097{ 1098 int jpegColorspace; 1099 return tjDecompressHeader3(handle, jpegBuf, jpegSize, width, height, 1100 jpegSubsamp, &jpegColorspace); 1101} 1102 1103DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle handle, 1104 unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height) 1105{ 1106 int jpegSubsamp; 1107 return tjDecompressHeader2(handle, jpegBuf, jpegSize, width, height, 1108 &jpegSubsamp); 1109} 1110 1111 1112DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors) 1113{ 1114 if(numscalingfactors==NULL) 1115 { 1116 snprintf(errStr, JMSG_LENGTH_MAX, 1117 "tjGetScalingFactors(): Invalid argument"); 1118 return NULL; 1119 } 1120 1121 *numscalingfactors=NUMSF; 1122 return (tjscalingfactor *)sf; 1123} 1124 1125 1126DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, unsigned char *jpegBuf, 1127 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch, 1128 int height, int pixelFormat, int flags) 1129{ 1130 int i, retval=0; JSAMPROW *row_pointer=NULL; 1131 int jpegwidth, jpegheight, scaledw, scaledh; 1132 #ifndef JCS_EXTENSIONS 1133 unsigned char *rgbBuf=NULL; 1134 unsigned char *_dstBuf=NULL; int _pitch=0; 1135 #endif 1136 1137 getinstance(handle); 1138 if((this->init&DECOMPRESS)==0) 1139 _throw("tjDecompress2(): Instance has not been initialized for decompression"); 1140 1141 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pitch<0 1142 || height<0 || pixelFormat<0 || pixelFormat>=TJ_NUMPF) 1143 _throw("tjDecompress2(): Invalid argument"); 1144 1145 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); 1146 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); 1147 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); 1148 1149 if(setjmp(this->jerr.setjmp_buffer)) 1150 { 1151 /* If we get here, the JPEG code has signaled an error. */ 1152 retval=-1; 1153 goto bailout; 1154 } 1155 1156 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); 1157 jpeg_read_header(dinfo, TRUE); 1158 if(setDecompDefaults(dinfo, pixelFormat, flags)==-1) 1159 { 1160 retval=-1; goto bailout; 1161 } 1162 1163 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE; 1164 1165 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height; 1166 if(width==0) width=jpegwidth; 1167 if(height==0) height=jpegheight; 1168 for(i=0; i<NUMSF; i++) 1169 { 1170 scaledw=TJSCALED(jpegwidth, sf[i]); 1171 scaledh=TJSCALED(jpegheight, sf[i]); 1172 if(scaledw<=width && scaledh<=height) 1173 break; 1174 } 1175 if(scaledw>width || scaledh>height) 1176 _throw("tjDecompress2(): Could not scale down to desired image dimensions"); 1177 width=scaledw; height=scaledh; 1178 dinfo->scale_num=sf[i].num; 1179 dinfo->scale_denom=sf[i].denom; 1180 1181 jpeg_start_decompress(dinfo); 1182 if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat]; 1183 1184 #ifndef JCS_EXTENSIONS 1185 if(pixelFormat!=TJPF_GRAY && 1186 (RGB_RED!=tjRedOffset[pixelFormat] || 1187 RGB_GREEN!=tjGreenOffset[pixelFormat] || 1188 RGB_BLUE!=tjBlueOffset[pixelFormat] || 1189 RGB_PIXELSIZE!=tjPixelSize[pixelFormat])) 1190 { 1191 rgbBuf=(unsigned char *)malloc(width*height*3); 1192 if(!rgbBuf) _throw("tjDecompress2(): Memory allocation failure"); 1193 _pitch=pitch; pitch=width*3; 1194 _dstBuf=dstBuf; dstBuf=rgbBuf; 1195 } 1196 #endif 1197 1198 if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW) 1199 *dinfo->output_height))==NULL) 1200 _throw("tjDecompress2(): Memory allocation failure"); 1201 for(i=0; i<(int)dinfo->output_height; i++) 1202 { 1203 if(flags&TJFLAG_BOTTOMUP) 1204 row_pointer[i]=&dstBuf[(dinfo->output_height-i-1)*pitch]; 1205 else row_pointer[i]=&dstBuf[i*pitch]; 1206 } 1207 while(dinfo->output_scanline<dinfo->output_height) 1208 { 1209 jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline], 1210 dinfo->output_height-dinfo->output_scanline); 1211 } 1212 jpeg_finish_decompress(dinfo); 1213 1214 #ifndef JCS_EXTENSIONS 1215 fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat); 1216 #endif 1217 1218 bailout: 1219 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo); 1220 #ifndef JCS_EXTENSIONS 1221 if(rgbBuf) free(rgbBuf); 1222 #endif 1223 if(row_pointer) free(row_pointer); 1224 return retval; 1225} 1226 1227DLLEXPORT int DLLCALL tjDecompress(tjhandle handle, unsigned char *jpegBuf, 1228 unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch, 1229 int height, int pixelSize, int flags) 1230{ 1231 if(flags&TJ_YUV) 1232 return tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags); 1233 else 1234 return tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, pitch, 1235 height, getPixelFormat(pixelSize, flags), flags); 1236} 1237 1238 1239DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle, 1240 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf, 1241 int width, int pad, int height, int flags) 1242{ 1243 int i, sfi, row, retval=0; JSAMPROW *outbuf[MAX_COMPONENTS]; 1244 int jpegwidth, jpegheight, jpegSubsamp, scaledw, scaledh; 1245 int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS], 1246 tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS]; 1247 JSAMPLE *_tmpbuf=NULL, *ptr=dstBuf; JSAMPROW *tmpbuf[MAX_COMPONENTS]; 1248 int dctsize; 1249 1250 getinstance(handle); 1251 1252 for(i=0; i<MAX_COMPONENTS; i++) 1253 { 1254 tmpbuf[i]=NULL; outbuf[i]=NULL; 1255 } 1256 1257 if((this->init&DECOMPRESS)==0) 1258 _throw("tjDecompressToYUV2(): Instance has not been initialized for decompression"); 1259 1260 if(jpegBuf==NULL || jpegSize<=0 || dstBuf==NULL || width<0 || pad<1 1261 || !isPow2(pad) || height<0) 1262 _throw("tjDecompressToYUV2(): Invalid argument"); 1263 1264 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); 1265 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); 1266 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); 1267 1268 if(setjmp(this->jerr.setjmp_buffer)) 1269 { 1270 /* If we get here, the JPEG code has signaled an error. */ 1271 retval=-1; 1272 goto bailout; 1273 } 1274 1275 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); 1276 jpeg_read_header(dinfo, TRUE); 1277 jpegSubsamp=getSubsamp(dinfo); 1278 if(jpegSubsamp<0) 1279 _throw("tjDecompressToYUV2(): Could not determine subsampling type for JPEG image"); 1280 1281 jpegwidth=dinfo->image_width; jpegheight=dinfo->image_height; 1282 if(width==0) width=jpegwidth; 1283 if(height==0) height=jpegheight; 1284 for(i=0; i<NUMSF; i++) 1285 { 1286 scaledw=TJSCALED(jpegwidth, sf[i]); 1287 scaledh=TJSCALED(jpegheight, sf[i]); 1288 if(scaledw<=width && scaledh<=height) 1289 break; 1290 } 1291 if(scaledw>width || scaledh>height) 1292 _throw("tjDecompressToYUV2(): Could not scale down to desired image dimensions"); 1293 if(dinfo->num_components>3) 1294 _throw("tjDecompressToYUV2(): JPEG image must have 3 or fewer components"); 1295 1296 width=scaledw; height=scaledh; 1297 dinfo->scale_num=sf[i].num; 1298 dinfo->scale_denom=sf[i].denom; 1299 sfi=i; 1300 jpeg_calc_output_dimensions(dinfo); 1301 1302 dctsize=DCTSIZE*sf[sfi].num/sf[sfi].denom; 1303 1304 for(i=0; i<dinfo->num_components; i++) 1305 { 1306 jpeg_component_info *compptr=&dinfo->comp_info[i]; 1307 int ih; 1308 iw[i]=compptr->width_in_blocks*dctsize; 1309 ih=compptr->height_in_blocks*dctsize; 1310 cw[i]=PAD(dinfo->output_width, dinfo->max_h_samp_factor) 1311 *compptr->h_samp_factor/dinfo->max_h_samp_factor; 1312 ch[i]=PAD(dinfo->output_height, dinfo->max_v_samp_factor) 1313 *compptr->v_samp_factor/dinfo->max_v_samp_factor; 1314 if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1; 1315 th[i]=compptr->v_samp_factor*dctsize; 1316 tmpbufsize+=iw[i]*th[i]; 1317 if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL) 1318 _throw("tjDecompressToYUV2(): Memory allocation failure"); 1319 for(row=0; row<ch[i]; row++) 1320 { 1321 outbuf[i][row]=ptr; 1322 ptr+=PAD(cw[i], pad); 1323 } 1324 } 1325 if(usetmpbuf) 1326 { 1327 if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL) 1328 _throw("tjDecompressToYUV2(): Memory allocation failure"); 1329 ptr=_tmpbuf; 1330 for(i=0; i<dinfo->num_components; i++) 1331 { 1332 if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL) 1333 _throw("tjDecompressToYUV2(): Memory allocation failure"); 1334 for(row=0; row<th[i]; row++) 1335 { 1336 tmpbuf[i][row]=ptr; 1337 ptr+=iw[i]; 1338 } 1339 } 1340 } 1341 1342 if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE; 1343 if(flags&TJFLAG_FASTDCT) dinfo->dct_method=JDCT_FASTEST; 1344 dinfo->raw_data_out=TRUE; 1345 1346 jpeg_start_decompress(dinfo); 1347 for(row=0; row<(int)dinfo->output_height; 1348 row+=dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size) 1349 { 1350 JSAMPARRAY yuvptr[MAX_COMPONENTS]; 1351 int crow[MAX_COMPONENTS]; 1352 for(i=0; i<dinfo->num_components; i++) 1353 { 1354 jpeg_component_info *compptr=&dinfo->comp_info[i]; 1355 if(jpegSubsamp==TJ_420) 1356 { 1357 /* When 4:2:0 subsampling is used with IDCT scaling, libjpeg will try 1358 to be clever and use the IDCT to perform upsampling on the U and V 1359 planes. For instance, if the output image is to be scaled by 1/2 1360 relative to the JPEG image, then the scaling factor and upsampling 1361 effectively cancel each other, so a normal 8x8 IDCT can be used. 1362 However, this is not desirable when using the decompress-to-YUV 1363 functionality in TurboJPEG, since we want to output the U and V 1364 planes in their subsampled form. Thus, we have to override some 1365 internal libjpeg parameters to force it to use the "scaled" IDCT 1366 functions on the U and V planes. */ 1367 compptr->_DCT_scaled_size=dctsize; 1368 compptr->MCU_sample_width=tjMCUWidth[jpegSubsamp]* 1369 sf[sfi].num/sf[sfi].denom* 1370 compptr->v_samp_factor/dinfo->max_v_samp_factor; 1371 dinfo->idct->inverse_DCT[i] = dinfo->idct->inverse_DCT[0]; 1372 } 1373 crow[i]=row*compptr->v_samp_factor/dinfo->max_v_samp_factor; 1374 if(usetmpbuf) yuvptr[i]=tmpbuf[i]; 1375 else yuvptr[i]=&outbuf[i][crow[i]]; 1376 } 1377 jpeg_read_raw_data(dinfo, yuvptr, 1378 dinfo->max_v_samp_factor*dinfo->_min_DCT_scaled_size); 1379 if(usetmpbuf) 1380 { 1381 int j; 1382 for(i=0; i<dinfo->num_components; i++) 1383 { 1384 for(j=0; j<min(th[i], ch[i]-crow[i]); j++) 1385 { 1386 memcpy(outbuf[i][crow[i]+j], tmpbuf[i][j], cw[i]); 1387 } 1388 } 1389 } 1390 } 1391 jpeg_finish_decompress(dinfo); 1392 1393 bailout: 1394 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo); 1395 for(i=0; i<MAX_COMPONENTS; i++) 1396 { 1397 if(tmpbuf[i]) free(tmpbuf[i]); 1398 if(outbuf[i]) free(outbuf[i]); 1399 } 1400 if(_tmpbuf) free(_tmpbuf); 1401 return retval; 1402} 1403 1404DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle handle, 1405 unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf, 1406 int flags) 1407{ 1408 return tjDecompressToYUV2(handle, jpegBuf, jpegSize, dstBuf, 0, 4, 0, flags); 1409} 1410 1411 1412/* Transformer */ 1413 1414DLLEXPORT tjhandle DLLCALL tjInitTransform(void) 1415{ 1416 tjinstance *this=NULL; tjhandle handle=NULL; 1417 if((this=(tjinstance *)malloc(sizeof(tjinstance)))==NULL) 1418 { 1419 snprintf(errStr, JMSG_LENGTH_MAX, 1420 "tjInitTransform(): Memory allocation failure"); 1421 return NULL; 1422 } 1423 MEMZERO(this, sizeof(tjinstance)); 1424 handle=_tjInitCompress(this); 1425 if(!handle) return NULL; 1426 handle=_tjInitDecompress(this); 1427 return handle; 1428} 1429 1430 1431DLLEXPORT int DLLCALL tjTransform(tjhandle handle, unsigned char *jpegBuf, 1432 unsigned long jpegSize, int n, unsigned char **dstBufs, 1433 unsigned long *dstSizes, tjtransform *t, int flags) 1434{ 1435 jpeg_transform_info *xinfo=NULL; 1436 jvirt_barray_ptr *srccoefs, *dstcoefs; 1437 int retval=0, i, jpegSubsamp; 1438 1439 getinstance(handle); 1440 if((this->init&COMPRESS)==0 || (this->init&DECOMPRESS)==0) 1441 _throw("tjTransform(): Instance has not been initialized for transformation"); 1442 1443 if(jpegBuf==NULL || jpegSize<=0 || n<1 || dstBufs==NULL || dstSizes==NULL 1444 || t==NULL || flags<0) 1445 _throw("tjTransform(): Invalid argument"); 1446 1447 if(flags&TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1"); 1448 else if(flags&TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1"); 1449 else if(flags&TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1"); 1450 1451 if(setjmp(this->jerr.setjmp_buffer)) 1452 { 1453 /* If we get here, the JPEG code has signaled an error. */ 1454 retval=-1; 1455 goto bailout; 1456 } 1457 1458 jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); 1459 1460 if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n)) 1461 ==NULL) 1462 _throw("tjTransform(): Memory allocation failure"); 1463 MEMZERO(xinfo, sizeof(jpeg_transform_info)*n); 1464 1465 for(i=0; i<n; i++) 1466 { 1467 xinfo[i].transform=xformtypes[t[i].op]; 1468 xinfo[i].perfect=(t[i].options&TJXOPT_PERFECT)? 1:0; 1469 xinfo[i].trim=(t[i].options&TJXOPT_TRIM)? 1:0; 1470 xinfo[i].force_grayscale=(t[i].options&TJXOPT_GRAY)? 1:0; 1471 xinfo[i].crop=(t[i].options&TJXOPT_CROP)? 1:0; 1472 if(n!=1 && t[i].op==TJXOP_HFLIP) xinfo[i].slow_hflip=1; 1473 else xinfo[i].slow_hflip=0; 1474 1475 if(xinfo[i].crop) 1476 { 1477 xinfo[i].crop_xoffset=t[i].r.x; xinfo[i].crop_xoffset_set=JCROP_POS; 1478 xinfo[i].crop_yoffset=t[i].r.y; xinfo[i].crop_yoffset_set=JCROP_POS; 1479 if(t[i].r.w!=0) 1480 { 1481 xinfo[i].crop_width=t[i].r.w; xinfo[i].crop_width_set=JCROP_POS; 1482 } 1483 else xinfo[i].crop_width=JCROP_UNSET; 1484 if(t[i].r.h!=0) 1485 { 1486 xinfo[i].crop_height=t[i].r.h; xinfo[i].crop_height_set=JCROP_POS; 1487 } 1488 else xinfo[i].crop_height=JCROP_UNSET; 1489 } 1490 } 1491 1492 jcopy_markers_setup(dinfo, JCOPYOPT_ALL); 1493 jpeg_read_header(dinfo, TRUE); 1494 jpegSubsamp=getSubsamp(dinfo); 1495 if(jpegSubsamp<0) 1496 _throw("tjTransform(): Could not determine subsampling type for JPEG image"); 1497 1498 for(i=0; i<n; i++) 1499 { 1500 if(!jtransform_request_workspace(dinfo, &xinfo[i])) 1501 _throw("tjTransform(): Transform is not perfect"); 1502 1503 if(xinfo[i].crop) 1504 { 1505 if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0 1506 || (t[i].r.y%xinfo[i].iMCU_sample_height)!=0) 1507 { 1508 snprintf(errStr, JMSG_LENGTH_MAX, 1509 "To crop this JPEG image, x must be a multiple of %d\n" 1510 "and y must be a multiple of %d.\n", 1511 xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height); 1512 retval=-1; goto bailout; 1513 } 1514 } 1515 } 1516 1517 srccoefs=jpeg_read_coefficients(dinfo); 1518 1519 for(i=0; i<n; i++) 1520 { 1521 int w, h, alloc=1; 1522 if(!xinfo[i].crop) 1523 { 1524 w=dinfo->image_width; h=dinfo->image_height; 1525 } 1526 else 1527 { 1528 w=xinfo[i].crop_width; h=xinfo[i].crop_height; 1529 } 1530 if(flags&TJFLAG_NOREALLOC) 1531 { 1532 alloc=0; dstSizes[i]=tjBufSize(w, h, jpegSubsamp); 1533 } 1534 if(!(t[i].options&TJXOPT_NOOUTPUT)) 1535 jpeg_mem_dest_tj(cinfo, &dstBufs[i], &dstSizes[i], alloc); 1536 jpeg_copy_critical_parameters(dinfo, cinfo); 1537 dstcoefs=jtransform_adjust_parameters(dinfo, cinfo, srccoefs, 1538 &xinfo[i]); 1539 if(!(t[i].options&TJXOPT_NOOUTPUT)) 1540 { 1541 jpeg_write_coefficients(cinfo, dstcoefs); 1542 jcopy_markers_execute(dinfo, cinfo, JCOPYOPT_ALL); 1543 } 1544 else jinit_c_master_control(cinfo, TRUE); 1545 jtransform_execute_transformation(dinfo, cinfo, srccoefs, 1546 &xinfo[i]); 1547 if(t[i].customFilter) 1548 { 1549 int ci, y; JDIMENSION by; 1550 for(ci=0; ci<cinfo->num_components; ci++) 1551 { 1552 jpeg_component_info *compptr=&cinfo->comp_info[ci]; 1553 tjregion arrayRegion={0, 0, compptr->width_in_blocks*DCTSIZE, 1554 DCTSIZE}; 1555 tjregion planeRegion={0, 0, compptr->width_in_blocks*DCTSIZE, 1556 compptr->height_in_blocks*DCTSIZE}; 1557 for(by=0; by<compptr->height_in_blocks; by+=compptr->v_samp_factor) 1558 { 1559 JBLOCKARRAY barray=(dinfo->mem->access_virt_barray) 1560 ((j_common_ptr)dinfo, dstcoefs[ci], by, compptr->v_samp_factor, 1561 TRUE); 1562 for(y=0; y<compptr->v_samp_factor; y++) 1563 { 1564 if(t[i].customFilter(barray[y][0], arrayRegion, planeRegion, 1565 ci, i, &t[i])==-1) 1566 _throw("tjTransform(): Error in custom filter"); 1567 arrayRegion.y+=DCTSIZE; 1568 } 1569 } 1570 } 1571 } 1572 if(!(t[i].options&TJXOPT_NOOUTPUT)) jpeg_finish_compress(cinfo); 1573 } 1574 1575 jpeg_finish_decompress(dinfo); 1576 1577 bailout: 1578 if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo); 1579 if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo); 1580 if(xinfo) free(xinfo); 1581 return retval; 1582} 1583