1 /* 2 * Copyright 2007 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 9 #include "SkImageDecoder.h" 10 #include "SkImageEncoder.h" 11 #include "SkJpegUtility.h" 12 #include "SkColorPriv.h" 13 #include "SkDither.h" 14 #include "SkScaledBitmapSampler.h" 15 #include "SkStream.h" 16 #include "SkTemplates.h" 17 #include "SkTime.h" 18 #include "SkUtils.h" 19 #include "SkRect.h" 20 #include "SkCanvas.h" 21 22 #include <stdio.h> 23 extern "C" { 24 #include "jpeglib.h" 25 #include "jerror.h" 26 } 27 28 // These enable timing code that report milliseconds for an encoding/decoding 29 //#define TIME_ENCODE 30 //#define TIME_DECODE 31 32 // this enables our rgb->yuv code, which is faster than libjpeg on ARM 33 #define WE_CONVERT_TO_YUV 34 35 // If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offers 36 // support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565. 37 38 ////////////////////////////////////////////////////////////////////////// 39 ////////////////////////////////////////////////////////////////////////// 40 41 static void overwrite_mem_buffer_size(jpeg_decompress_struct* cinfo) { 42 #ifdef SK_BUILD_FOR_ANDROID 43 /* Check if the device indicates that it has a large amount of system memory 44 * if so, increase the memory allocation to 30MB instead of the default 5MB. 45 */ 46 #ifdef ANDROID_LARGE_MEMORY_DEVICE 47 cinfo->mem->max_memory_to_use = 30 * 1024 * 1024; 48 #else 49 cinfo->mem->max_memory_to_use = 5 * 1024 * 1024; 50 #endif 51 #endif // SK_BUILD_FOR_ANDROID 52 } 53 54 ////////////////////////////////////////////////////////////////////////// 55 ////////////////////////////////////////////////////////////////////////// 56 57 static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* src_mgr) { 58 SkASSERT(cinfo != NULL); 59 SkASSERT(src_mgr != NULL); 60 jpeg_create_decompress(cinfo); 61 overwrite_mem_buffer_size(cinfo); 62 cinfo->src = src_mgr; 63 } 64 65 #ifdef SK_BUILD_FOR_ANDROID 66 class SkJPEGImageIndex { 67 public: 68 SkJPEGImageIndex(SkStream* stream, SkImageDecoder* decoder) 69 : fSrcMgr(stream, decoder) 70 , fInfoInitialized(false) 71 , fHuffmanCreated(false) 72 , fDecompressStarted(false) 73 { 74 SkDEBUGCODE(fReadHeaderSucceeded = false;) 75 } 76 77 ~SkJPEGImageIndex() { 78 if (fHuffmanCreated) { 79 // Set to false before calling the libjpeg function, in case 80 // the libjpeg function calls longjmp. Our setjmp handler may 81 // attempt to delete this SkJPEGImageIndex, thus entering this 82 // destructor again. Setting fHuffmanCreated to false first 83 // prevents an infinite loop. 84 fHuffmanCreated = false; 85 jpeg_destroy_huffman_index(&fHuffmanIndex); 86 } 87 if (fDecompressStarted) { 88 // Like fHuffmanCreated, set to false before calling libjpeg 89 // function to prevent potential infinite loop. 90 fDecompressStarted = false; 91 jpeg_finish_decompress(&fCInfo); 92 } 93 if (fInfoInitialized) { 94 this->destroyInfo(); 95 } 96 } 97 98 /** 99 * Destroy the cinfo struct. 100 * After this call, if a huffman index was already built, it 101 * can be used after calling initializeInfoAndReadHeader 102 * again. Must not be called after startTileDecompress except 103 * in the destructor. 104 */ 105 void destroyInfo() { 106 SkASSERT(fInfoInitialized); 107 SkASSERT(!fDecompressStarted); 108 // Like fHuffmanCreated, set to false before calling libjpeg 109 // function to prevent potential infinite loop. 110 fInfoInitialized = false; 111 jpeg_destroy_decompress(&fCInfo); 112 SkDEBUGCODE(fReadHeaderSucceeded = false;) 113 } 114 115 /** 116 * Initialize the cinfo struct. 117 * Calls jpeg_create_decompress, makes customizations, and 118 * finally calls jpeg_read_header. Returns true if jpeg_read_header 119 * returns JPEG_HEADER_OK. 120 * If cinfo was already initialized, destroyInfo must be called to 121 * destroy the old one. Must not be called after startTileDecompress. 122 */ 123 bool initializeInfoAndReadHeader() { 124 SkASSERT(!fInfoInitialized && !fDecompressStarted); 125 initialize_info(&fCInfo, &fSrcMgr); 126 fInfoInitialized = true; 127 const bool success = (JPEG_HEADER_OK == jpeg_read_header(&fCInfo, true)); 128 SkDEBUGCODE(fReadHeaderSucceeded = success;) 129 return success; 130 } 131 132 jpeg_decompress_struct* cinfo() { return &fCInfo; } 133 134 huffman_index* huffmanIndex() { return &fHuffmanIndex; } 135 136 /** 137 * Build the index to be used for tile based decoding. 138 * Must only be called after a successful call to 139 * initializeInfoAndReadHeader and must not be called more 140 * than once. 141 */ 142 bool buildHuffmanIndex() { 143 SkASSERT(fReadHeaderSucceeded); 144 SkASSERT(!fHuffmanCreated); 145 jpeg_create_huffman_index(&fCInfo, &fHuffmanIndex); 146 fHuffmanCreated = true; 147 SkASSERT(1 == fCInfo.scale_num && 1 == fCInfo.scale_denom); 148 return jpeg_build_huffman_index(&fCInfo, &fHuffmanIndex); 149 } 150 151 /** 152 * Start tile based decoding. Must only be called after a 153 * successful call to buildHuffmanIndex, and must only be 154 * called once. 155 */ 156 bool startTileDecompress() { 157 SkASSERT(fHuffmanCreated); 158 SkASSERT(fReadHeaderSucceeded); 159 SkASSERT(!fDecompressStarted); 160 if (jpeg_start_tile_decompress(&fCInfo)) { 161 fDecompressStarted = true; 162 return true; 163 } 164 return false; 165 } 166 167 private: 168 skjpeg_source_mgr fSrcMgr; 169 jpeg_decompress_struct fCInfo; 170 huffman_index fHuffmanIndex; 171 bool fInfoInitialized; 172 bool fHuffmanCreated; 173 bool fDecompressStarted; 174 SkDEBUGCODE(bool fReadHeaderSucceeded;) 175 }; 176 #endif 177 178 class SkJPEGImageDecoder : public SkImageDecoder { 179 public: 180 #ifdef SK_BUILD_FOR_ANDROID 181 SkJPEGImageDecoder() { 182 fImageIndex = NULL; 183 fImageWidth = 0; 184 fImageHeight = 0; 185 } 186 187 virtual ~SkJPEGImageDecoder() { 188 SkDELETE(fImageIndex); 189 } 190 #endif 191 192 virtual Format getFormat() const { 193 return kJPEG_Format; 194 } 195 196 protected: 197 #ifdef SK_BUILD_FOR_ANDROID 198 virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height) SK_OVERRIDE; 199 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRIDE; 200 #endif 201 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; 202 203 private: 204 #ifdef SK_BUILD_FOR_ANDROID 205 SkJPEGImageIndex* fImageIndex; 206 int fImageWidth; 207 int fImageHeight; 208 #endif 209 210 /** 211 * Determine the appropriate bitmap config and out_color_space based on 212 * both the preference of the caller and the jpeg_color_space on the 213 * jpeg_decompress_struct passed in. 214 * Must be called after jpeg_read_header. 215 */ 216 SkBitmap::Config getBitmapConfig(jpeg_decompress_struct*); 217 218 typedef SkImageDecoder INHERITED; 219 }; 220 221 ////////////////////////////////////////////////////////////////////////// 222 223 /* Automatically clean up after throwing an exception */ 224 class JPEGAutoClean { 225 public: 226 JPEGAutoClean(): cinfo_ptr(NULL) {} 227 ~JPEGAutoClean() { 228 if (cinfo_ptr) { 229 jpeg_destroy_decompress(cinfo_ptr); 230 } 231 } 232 void set(jpeg_decompress_struct* info) { 233 cinfo_ptr = info; 234 } 235 private: 236 jpeg_decompress_struct* cinfo_ptr; 237 }; 238 239 /////////////////////////////////////////////////////////////////////////////// 240 241 /* If we need to better match the request, we might examine the image and 242 output dimensions, and determine if the downsampling jpeg provided is 243 not sufficient. If so, we can recompute a modified sampleSize value to 244 make up the difference. 245 246 To skip this additional scaling, just set sampleSize = 1; below. 247 */ 248 static int recompute_sampleSize(int sampleSize, 249 const jpeg_decompress_struct& cinfo) { 250 return sampleSize * cinfo.output_width / cinfo.image_width; 251 } 252 253 static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) { 254 /* These are initialized to 0, so if they have non-zero values, we assume 255 they are "valid" (i.e. have been computed by libjpeg) 256 */ 257 return 0 != cinfo.output_width && 0 != cinfo.output_height; 258 } 259 260 static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count) { 261 for (int i = 0; i < count; i++) { 262 JSAMPLE* rowptr = (JSAMPLE*)buffer; 263 int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1); 264 if (1 != row_count) { 265 return false; 266 } 267 } 268 return true; 269 } 270 271 #ifdef SK_BUILD_FOR_ANDROID 272 static bool skip_src_rows_tile(jpeg_decompress_struct* cinfo, 273 huffman_index *index, void* buffer, int count) { 274 for (int i = 0; i < count; i++) { 275 JSAMPLE* rowptr = (JSAMPLE*)buffer; 276 int row_count = jpeg_read_tile_scanline(cinfo, index, &rowptr); 277 if (1 != row_count) { 278 return false; 279 } 280 } 281 return true; 282 } 283 #endif 284 285 // This guy exists just to aid in debugging, as it allows debuggers to just 286 // set a break-point in one place to see all error exists. 287 static bool return_false(const jpeg_decompress_struct& cinfo, 288 const SkBitmap& bm, const char msg[]) { 289 #ifdef SK_DEBUG 290 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n", cinfo.err->msg_code, 291 cinfo.err->jpeg_message_table[cinfo.err->msg_code], msg, 292 bm.width(), bm.height()); 293 #endif 294 return false; // must always return false 295 } 296 297 // Convert a scanline of CMYK samples to RGBX in place. Note that this 298 // method moves the "scanline" pointer in its processing 299 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) { 300 // At this point we've received CMYK pixels from libjpeg. We 301 // perform a crude conversion to RGB (based on the formulae 302 // from easyrgb.com): 303 // CMYK -> CMY 304 // C = ( C * (1 - K) + K ) // for each CMY component 305 // CMY -> RGB 306 // R = ( 1 - C ) * 255 // for each RGB component 307 // Unfortunately we are seeing inverted CMYK so all the original terms 308 // are 1-. This yields: 309 // CMYK -> CMY 310 // C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K 311 // The conversion from CMY->RGB remains the same 312 for (unsigned int x = 0; x < width; ++x, scanline += 4) { 313 scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]); 314 scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]); 315 scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]); 316 scanline[3] = 255; 317 } 318 } 319 320 /** 321 * Common code for setting the error manager. 322 */ 323 static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* errorManager) { 324 SkASSERT(cinfo != NULL); 325 SkASSERT(errorManager != NULL); 326 cinfo->err = jpeg_std_error(errorManager); 327 errorManager->error_exit = skjpeg_error_exit; 328 } 329 330 /** 331 * Common code for turning off upsampling and smoothing. Turning these 332 * off helps performance without showing noticable differences in the 333 * resulting bitmap. 334 */ 335 static void turn_off_visual_optimizations(jpeg_decompress_struct* cinfo) { 336 SkASSERT(cinfo != NULL); 337 /* this gives about 30% performance improvement. In theory it may 338 reduce the visual quality, in practice I'm not seeing a difference 339 */ 340 cinfo->do_fancy_upsampling = 0; 341 342 /* this gives another few percents */ 343 cinfo->do_block_smoothing = 0; 344 } 345 346 /** 347 * Common code for setting the dct method. 348 */ 349 static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct* cinfo) { 350 SkASSERT(cinfo != NULL); 351 #ifdef DCT_IFAST_SUPPORTED 352 if (decoder.getPreferQualityOverSpeed()) { 353 cinfo->dct_method = JDCT_ISLOW; 354 } else { 355 cinfo->dct_method = JDCT_IFAST; 356 } 357 #else 358 cinfo->dct_method = JDCT_ISLOW; 359 #endif 360 } 361 362 SkBitmap::Config SkJPEGImageDecoder::getBitmapConfig(jpeg_decompress_struct* cinfo) { 363 SkASSERT(cinfo != NULL); 364 365 SrcDepth srcDepth = k32Bit_SrcDepth; 366 if (JCS_GRAYSCALE == cinfo->jpeg_color_space) { 367 srcDepth = k8BitGray_SrcDepth; 368 } 369 370 SkBitmap::Config config = this->getPrefConfig(srcDepth, /*hasAlpha*/ false); 371 switch (config) { 372 case SkBitmap::kA8_Config: 373 // Only respect A8 config if the original is grayscale, 374 // in which case we will treat the grayscale as alpha 375 // values. 376 if (cinfo->jpeg_color_space != JCS_GRAYSCALE) { 377 config = SkBitmap::kARGB_8888_Config; 378 } 379 break; 380 case SkBitmap::kARGB_8888_Config: 381 // Fall through. 382 case SkBitmap::kARGB_4444_Config: 383 // Fall through. 384 case SkBitmap::kRGB_565_Config: 385 // These are acceptable destination configs. 386 break; 387 default: 388 // Force all other configs to 8888. 389 config = SkBitmap::kARGB_8888_Config; 390 break; 391 } 392 393 switch (cinfo->jpeg_color_space) { 394 case JCS_CMYK: 395 // Fall through. 396 case JCS_YCCK: 397 // libjpeg cannot convert from CMYK or YCCK to RGB - here we set up 398 // so libjpeg will give us CMYK samples back and we will later 399 // manually convert them to RGB 400 cinfo->out_color_space = JCS_CMYK; 401 break; 402 case JCS_GRAYSCALE: 403 if (SkBitmap::kA8_Config == config) { 404 cinfo->out_color_space = JCS_GRAYSCALE; 405 break; 406 } 407 // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB 408 // config. Fall through to set to the default. 409 default: 410 cinfo->out_color_space = JCS_RGB; 411 break; 412 } 413 return config; 414 } 415 416 #ifdef ANDROID_RGB 417 /** 418 * Based on the config and dither mode, adjust out_color_space and 419 * dither_mode of cinfo. 420 */ 421 static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo, 422 SkBitmap::Config config, 423 const SkImageDecoder& decoder) { 424 SkASSERT(cinfo != NULL); 425 cinfo->dither_mode = JDITHER_NONE; 426 if (JCS_CMYK == cinfo->out_color_space) { 427 return; 428 } 429 switch(config) { 430 case SkBitmap::kARGB_8888_Config: 431 cinfo->out_color_space = JCS_RGBA_8888; 432 break; 433 case SkBitmap::kRGB_565_Config: 434 cinfo->out_color_space = JCS_RGB_565; 435 if (decoder.getDitherImage()) { 436 cinfo->dither_mode = JDITHER_ORDERED; 437 } 438 break; 439 default: 440 break; 441 } 442 } 443 #endif 444 445 bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { 446 #ifdef TIME_DECODE 447 SkAutoTime atm("JPEG Decode"); 448 #endif 449 450 JPEGAutoClean autoClean; 451 452 jpeg_decompress_struct cinfo; 453 skjpeg_source_mgr srcManager(stream, this); 454 455 skjpeg_error_mgr errorManager; 456 set_error_mgr(&cinfo, &errorManager); 457 458 // All objects need to be instantiated before this setjmp call so that 459 // they will be cleaned up properly if an error occurs. 460 if (setjmp(errorManager.fJmpBuf)) { 461 return return_false(cinfo, *bm, "setjmp"); 462 } 463 464 initialize_info(&cinfo, &srcManager); 465 autoClean.set(&cinfo); 466 467 int status = jpeg_read_header(&cinfo, true); 468 if (status != JPEG_HEADER_OK) { 469 return return_false(cinfo, *bm, "read_header"); 470 } 471 472 /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it 473 can) much faster that we, just use their num/denom api to approximate 474 the size. 475 */ 476 int sampleSize = this->getSampleSize(); 477 478 set_dct_method(*this, &cinfo); 479 480 SkASSERT(1 == cinfo.scale_num); 481 cinfo.scale_denom = sampleSize; 482 483 turn_off_visual_optimizations(&cinfo); 484 485 const SkBitmap::Config config = this->getBitmapConfig(&cinfo); 486 487 #ifdef ANDROID_RGB 488 adjust_out_color_space_and_dither(&cinfo, config, *this); 489 #endif 490 491 if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) { 492 bm->setConfig(config, cinfo.image_width, cinfo.image_height); 493 bm->setIsOpaque(config != SkBitmap::kA8_Config); 494 return true; 495 } 496 497 /* image_width and image_height are the original dimensions, available 498 after jpeg_read_header(). To see the scaled dimensions, we have to call 499 jpeg_start_decompress(), and then read output_width and output_height. 500 */ 501 if (!jpeg_start_decompress(&cinfo)) { 502 /* If we failed here, we may still have enough information to return 503 to the caller if they just wanted (subsampled bounds). If sampleSize 504 was 1, then we would have already returned. Thus we just check if 505 we're in kDecodeBounds_Mode, and that we have valid output sizes. 506 507 One reason to fail here is that we have insufficient stream data 508 to complete the setup. However, output dimensions seem to get 509 computed very early, which is why this special check can pay off. 510 */ 511 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimensions(cinfo)) { 512 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height, 513 recompute_sampleSize(sampleSize, cinfo)); 514 bm->setConfig(config, smpl.scaledWidth(), smpl.scaledHeight()); 515 bm->setIsOpaque(config != SkBitmap::kA8_Config); 516 return true; 517 } else { 518 return return_false(cinfo, *bm, "start_decompress"); 519 } 520 } 521 sampleSize = recompute_sampleSize(sampleSize, cinfo); 522 523 // should we allow the Chooser (if present) to pick a config for us??? 524 if (!this->chooseFromOneChoice(config, cinfo.output_width, cinfo.output_height)) { 525 return return_false(cinfo, *bm, "chooseFromOneChoice"); 526 } 527 528 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize); 529 bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight()); 530 bm->setIsOpaque(config != SkBitmap::kA8_Config); 531 if (SkImageDecoder::kDecodeBounds_Mode == mode) { 532 return true; 533 } 534 if (!this->allocPixelRef(bm, NULL)) { 535 return return_false(cinfo, *bm, "allocPixelRef"); 536 } 537 538 SkAutoLockPixels alp(*bm); 539 540 #ifdef ANDROID_RGB 541 /* short-circuit the SkScaledBitmapSampler when possible, as this gives 542 a significant performance boost. 543 */ 544 if (sampleSize == 1 && 545 ((config == SkBitmap::kARGB_8888_Config && 546 cinfo.out_color_space == JCS_RGBA_8888) || 547 (config == SkBitmap::kRGB_565_Config && 548 cinfo.out_color_space == JCS_RGB_565))) 549 { 550 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); 551 INT32 const bpr = bm->rowBytes(); 552 553 while (cinfo.output_scanline < cinfo.output_height) { 554 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 555 // if row_count == 0, then we didn't get a scanline, so abort. 556 // if we supported partial images, we might return true in this case 557 if (0 == row_count) { 558 return return_false(cinfo, *bm, "read_scanlines"); 559 } 560 if (this->shouldCancelDecode()) { 561 return return_false(cinfo, *bm, "shouldCancelDecode"); 562 } 563 rowptr += bpr; 564 } 565 jpeg_finish_decompress(&cinfo); 566 return true; 567 } 568 #endif 569 570 // check for supported formats 571 SkScaledBitmapSampler::SrcConfig sc; 572 if (JCS_CMYK == cinfo.out_color_space) { 573 // In this case we will manually convert the CMYK values to RGB 574 sc = SkScaledBitmapSampler::kRGBX; 575 } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) { 576 sc = SkScaledBitmapSampler::kRGB; 577 #ifdef ANDROID_RGB 578 } else if (JCS_RGBA_8888 == cinfo.out_color_space) { 579 sc = SkScaledBitmapSampler::kRGBX; 580 } else if (JCS_RGB_565 == cinfo.out_color_space) { 581 sc = SkScaledBitmapSampler::kRGB_565; 582 #endif 583 } else if (1 == cinfo.out_color_components && 584 JCS_GRAYSCALE == cinfo.out_color_space) { 585 sc = SkScaledBitmapSampler::kGray; 586 } else { 587 return return_false(cinfo, *bm, "jpeg colorspace"); 588 } 589 590 if (!sampler.begin(bm, sc, this->getDitherImage())) { 591 return return_false(cinfo, *bm, "sampler.begin"); 592 } 593 594 // The CMYK work-around relies on 4 components per pixel here 595 SkAutoMalloc srcStorage(cinfo.output_width * 4); 596 uint8_t* srcRow = (uint8_t*)srcStorage.get(); 597 598 // Possibly skip initial rows [sampler.srcY0] 599 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) { 600 return return_false(cinfo, *bm, "skip rows"); 601 } 602 603 // now loop through scanlines until y == bm->height() - 1 604 for (int y = 0;; y++) { 605 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 606 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 607 if (0 == row_count) { 608 return return_false(cinfo, *bm, "read_scanlines"); 609 } 610 if (this->shouldCancelDecode()) { 611 return return_false(cinfo, *bm, "shouldCancelDecode"); 612 } 613 614 if (JCS_CMYK == cinfo.out_color_space) { 615 convert_CMYK_to_RGB(srcRow, cinfo.output_width); 616 } 617 618 sampler.next(srcRow); 619 if (bm->height() - 1 == y) { 620 // we're done 621 break; 622 } 623 624 if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) { 625 return return_false(cinfo, *bm, "skip rows"); 626 } 627 } 628 629 // we formally skip the rest, so we don't get a complaint from libjpeg 630 if (!skip_src_rows(&cinfo, srcRow, 631 cinfo.output_height - cinfo.output_scanline)) { 632 return return_false(cinfo, *bm, "skip rows"); 633 } 634 jpeg_finish_decompress(&cinfo); 635 636 return true; 637 } 638 639 #ifdef SK_BUILD_FOR_ANDROID 640 bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream, int *width, int *height) { 641 642 SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (stream, this))); 643 jpeg_decompress_struct* cinfo = imageIndex->cinfo(); 644 645 skjpeg_error_mgr sk_err; 646 set_error_mgr(cinfo, &sk_err); 647 648 // All objects need to be instantiated before this setjmp call so that 649 // they will be cleaned up properly if an error occurs. 650 if (setjmp(sk_err.fJmpBuf)) { 651 return false; 652 } 653 654 // create the cinfo used to create/build the huffmanIndex 655 if (!imageIndex->initializeInfoAndReadHeader()) { 656 return false; 657 } 658 659 if (!imageIndex->buildHuffmanIndex()) { 660 return false; 661 } 662 663 // destroy the cinfo used to create/build the huffman index 664 imageIndex->destroyInfo(); 665 666 // Init decoder to image decode mode 667 if (!imageIndex->initializeInfoAndReadHeader()) { 668 return false; 669 } 670 671 // FIXME: This sets cinfo->out_color_space, which we may change later 672 // based on the config in onDecodeSubset. This should be fine, since 673 // jpeg_init_read_tile_scanline will check out_color_space again after 674 // that change (when it calls jinit_color_deconverter). 675 (void) this->getBitmapConfig(cinfo); 676 677 turn_off_visual_optimizations(cinfo); 678 679 // instead of jpeg_start_decompress() we start a tiled decompress 680 if (!imageIndex->startTileDecompress()) { 681 return false; 682 } 683 684 SkASSERT(1 == cinfo->scale_num); 685 fImageWidth = cinfo->output_width; 686 fImageHeight = cinfo->output_height; 687 688 if (width) { 689 *width = fImageWidth; 690 } 691 if (height) { 692 *height = fImageHeight; 693 } 694 695 SkDELETE(fImageIndex); 696 fImageIndex = imageIndex.detach(); 697 698 return true; 699 } 700 701 bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { 702 if (NULL == fImageIndex) { 703 return false; 704 } 705 jpeg_decompress_struct* cinfo = fImageIndex->cinfo(); 706 707 SkIRect rect = SkIRect::MakeWH(fImageWidth, fImageHeight); 708 if (!rect.intersect(region)) { 709 // If the requested region is entirely outside the image return false 710 return false; 711 } 712 713 714 skjpeg_error_mgr errorManager; 715 set_error_mgr(cinfo, &errorManager); 716 717 if (setjmp(errorManager.fJmpBuf)) { 718 return false; 719 } 720 721 int requestedSampleSize = this->getSampleSize(); 722 cinfo->scale_denom = requestedSampleSize; 723 724 set_dct_method(*this, cinfo); 725 726 const SkBitmap::Config config = this->getBitmapConfig(cinfo); 727 #ifdef ANDROID_RGB 728 adjust_out_color_space_and_dither(cinfo, config, *this); 729 #endif 730 731 int startX = rect.fLeft; 732 int startY = rect.fTop; 733 int width = rect.width(); 734 int height = rect.height(); 735 736 jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), 737 &startX, &startY, &width, &height); 738 int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo); 739 int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_size); 740 741 SkScaledBitmapSampler sampler(width, height, skiaSampleSize); 742 743 SkBitmap bitmap; 744 bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight()); 745 bitmap.setIsOpaque(true); 746 747 // Check ahead of time if the swap(dest, src) is possible or not. 748 // If yes, then we will stick to AllocPixelRef since it's cheaper with the 749 // swap happening. If no, then we will use alloc to allocate pixels to 750 // prevent garbage collection. 751 int w = rect.width() / actualSampleSize; 752 int h = rect.height() / actualSampleSize; 753 bool swapOnly = (rect == region) && bm->isNull() && 754 (w == bitmap.width()) && (h == bitmap.height()) && 755 ((startX - rect.x()) / actualSampleSize == 0) && 756 ((startY - rect.y()) / actualSampleSize == 0); 757 if (swapOnly) { 758 if (!this->allocPixelRef(&bitmap, NULL)) { 759 return return_false(*cinfo, bitmap, "allocPixelRef"); 760 } 761 } else { 762 if (!bitmap.allocPixels()) { 763 return return_false(*cinfo, bitmap, "allocPixels"); 764 } 765 } 766 767 SkAutoLockPixels alp(bitmap); 768 769 #ifdef ANDROID_RGB 770 /* short-circuit the SkScaledBitmapSampler when possible, as this gives 771 a significant performance boost. 772 */ 773 if (skiaSampleSize == 1 && 774 ((config == SkBitmap::kARGB_8888_Config && 775 cinfo->out_color_space == JCS_RGBA_8888) || 776 (config == SkBitmap::kRGB_565_Config && 777 cinfo->out_color_space == JCS_RGB_565))) 778 { 779 JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels(); 780 INT32 const bpr = bitmap.rowBytes(); 781 int rowTotalCount = 0; 782 783 while (rowTotalCount < height) { 784 int rowCount = jpeg_read_tile_scanline(cinfo, 785 fImageIndex->huffmanIndex(), 786 &rowptr); 787 // if row_count == 0, then we didn't get a scanline, so abort. 788 // if we supported partial images, we might return true in this case 789 if (0 == rowCount) { 790 return return_false(*cinfo, bitmap, "read_scanlines"); 791 } 792 if (this->shouldCancelDecode()) { 793 return return_false(*cinfo, bitmap, "shouldCancelDecode"); 794 } 795 rowTotalCount += rowCount; 796 rowptr += bpr; 797 } 798 799 if (swapOnly) { 800 bm->swap(bitmap); 801 } else { 802 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(), 803 region.width(), region.height(), startX, startY); 804 } 805 return true; 806 } 807 #endif 808 809 // check for supported formats 810 SkScaledBitmapSampler::SrcConfig sc; 811 if (JCS_CMYK == cinfo->out_color_space) { 812 // In this case we will manually convert the CMYK values to RGB 813 sc = SkScaledBitmapSampler::kRGBX; 814 } else if (3 == cinfo->out_color_components && JCS_RGB == cinfo->out_color_space) { 815 sc = SkScaledBitmapSampler::kRGB; 816 #ifdef ANDROID_RGB 817 } else if (JCS_RGBA_8888 == cinfo->out_color_space) { 818 sc = SkScaledBitmapSampler::kRGBX; 819 } else if (JCS_RGB_565 == cinfo->out_color_space) { 820 sc = SkScaledBitmapSampler::kRGB_565; 821 #endif 822 } else if (1 == cinfo->out_color_components && 823 JCS_GRAYSCALE == cinfo->out_color_space) { 824 sc = SkScaledBitmapSampler::kGray; 825 } else { 826 return return_false(*cinfo, *bm, "jpeg colorspace"); 827 } 828 829 if (!sampler.begin(&bitmap, sc, this->getDitherImage())) { 830 return return_false(*cinfo, bitmap, "sampler.begin"); 831 } 832 833 // The CMYK work-around relies on 4 components per pixel here 834 SkAutoMalloc srcStorage(width * 4); 835 uint8_t* srcRow = (uint8_t*)srcStorage.get(); 836 837 // Possibly skip initial rows [sampler.srcY0] 838 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler.srcY0())) { 839 return return_false(*cinfo, bitmap, "skip rows"); 840 } 841 842 // now loop through scanlines until y == bitmap->height() - 1 843 for (int y = 0;; y++) { 844 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 845 int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), &rowptr); 846 if (0 == row_count) { 847 return return_false(*cinfo, bitmap, "read_scanlines"); 848 } 849 if (this->shouldCancelDecode()) { 850 return return_false(*cinfo, bitmap, "shouldCancelDecode"); 851 } 852 853 if (JCS_CMYK == cinfo->out_color_space) { 854 convert_CMYK_to_RGB(srcRow, width); 855 } 856 857 sampler.next(srcRow); 858 if (bitmap.height() - 1 == y) { 859 // we're done 860 break; 861 } 862 863 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, 864 sampler.srcDY() - 1)) { 865 return return_false(*cinfo, bitmap, "skip rows"); 866 } 867 } 868 if (swapOnly) { 869 bm->swap(bitmap); 870 } else { 871 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(), 872 region.width(), region.height(), startX, startY); 873 } 874 return true; 875 } 876 #endif 877 878 /////////////////////////////////////////////////////////////////////////////// 879 880 #include "SkColorPriv.h" 881 882 // taken from jcolor.c in libjpeg 883 #if 0 // 16bit - precise but slow 884 #define CYR 19595 // 0.299 885 #define CYG 38470 // 0.587 886 #define CYB 7471 // 0.114 887 888 #define CUR -11059 // -0.16874 889 #define CUG -21709 // -0.33126 890 #define CUB 32768 // 0.5 891 892 #define CVR 32768 // 0.5 893 #define CVG -27439 // -0.41869 894 #define CVB -5329 // -0.08131 895 896 #define CSHIFT 16 897 #else // 8bit - fast, slightly less precise 898 #define CYR 77 // 0.299 899 #define CYG 150 // 0.587 900 #define CYB 29 // 0.114 901 902 #define CUR -43 // -0.16874 903 #define CUG -85 // -0.33126 904 #define CUB 128 // 0.5 905 906 #define CVR 128 // 0.5 907 #define CVG -107 // -0.41869 908 #define CVB -21 // -0.08131 909 910 #define CSHIFT 8 911 #endif 912 913 static void rgb2yuv_32(uint8_t dst[], SkPMColor c) { 914 int r = SkGetPackedR32(c); 915 int g = SkGetPackedG32(c); 916 int b = SkGetPackedB32(c); 917 918 int y = ( CYR*r + CYG*g + CYB*b ) >> CSHIFT; 919 int u = ( CUR*r + CUG*g + CUB*b ) >> CSHIFT; 920 int v = ( CVR*r + CVG*g + CVB*b ) >> CSHIFT; 921 922 dst[0] = SkToU8(y); 923 dst[1] = SkToU8(u + 128); 924 dst[2] = SkToU8(v + 128); 925 } 926 927 static void rgb2yuv_4444(uint8_t dst[], U16CPU c) { 928 int r = SkGetPackedR4444(c); 929 int g = SkGetPackedG4444(c); 930 int b = SkGetPackedB4444(c); 931 932 int y = ( CYR*r + CYG*g + CYB*b ) >> (CSHIFT - 4); 933 int u = ( CUR*r + CUG*g + CUB*b ) >> (CSHIFT - 4); 934 int v = ( CVR*r + CVG*g + CVB*b ) >> (CSHIFT - 4); 935 936 dst[0] = SkToU8(y); 937 dst[1] = SkToU8(u + 128); 938 dst[2] = SkToU8(v + 128); 939 } 940 941 static void rgb2yuv_16(uint8_t dst[], U16CPU c) { 942 int r = SkGetPackedR16(c); 943 int g = SkGetPackedG16(c); 944 int b = SkGetPackedB16(c); 945 946 int y = ( 2*CYR*r + CYG*g + 2*CYB*b ) >> (CSHIFT - 2); 947 int u = ( 2*CUR*r + CUG*g + 2*CUB*b ) >> (CSHIFT - 2); 948 int v = ( 2*CVR*r + CVG*g + 2*CVB*b ) >> (CSHIFT - 2); 949 950 dst[0] = SkToU8(y); 951 dst[1] = SkToU8(u + 128); 952 dst[2] = SkToU8(v + 128); 953 } 954 955 /////////////////////////////////////////////////////////////////////////////// 956 957 typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst, 958 const void* SK_RESTRICT src, int width, 959 const SkPMColor* SK_RESTRICT ctable); 960 961 static void Write_32_YUV(uint8_t* SK_RESTRICT dst, 962 const void* SK_RESTRICT srcRow, int width, 963 const SkPMColor*) { 964 const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow; 965 while (--width >= 0) { 966 #ifdef WE_CONVERT_TO_YUV 967 rgb2yuv_32(dst, *src++); 968 #else 969 uint32_t c = *src++; 970 dst[0] = SkGetPackedR32(c); 971 dst[1] = SkGetPackedG32(c); 972 dst[2] = SkGetPackedB32(c); 973 #endif 974 dst += 3; 975 } 976 } 977 978 static void Write_4444_YUV(uint8_t* SK_RESTRICT dst, 979 const void* SK_RESTRICT srcRow, int width, 980 const SkPMColor*) { 981 const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow; 982 while (--width >= 0) { 983 #ifdef WE_CONVERT_TO_YUV 984 rgb2yuv_4444(dst, *src++); 985 #else 986 SkPMColor16 c = *src++; 987 dst[0] = SkPacked4444ToR32(c); 988 dst[1] = SkPacked4444ToG32(c); 989 dst[2] = SkPacked4444ToB32(c); 990 #endif 991 dst += 3; 992 } 993 } 994 995 static void Write_16_YUV(uint8_t* SK_RESTRICT dst, 996 const void* SK_RESTRICT srcRow, int width, 997 const SkPMColor*) { 998 const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow; 999 while (--width >= 0) { 1000 #ifdef WE_CONVERT_TO_YUV 1001 rgb2yuv_16(dst, *src++); 1002 #else 1003 uint16_t c = *src++; 1004 dst[0] = SkPacked16ToR32(c); 1005 dst[1] = SkPacked16ToG32(c); 1006 dst[2] = SkPacked16ToB32(c); 1007 #endif 1008 dst += 3; 1009 } 1010 } 1011 1012 static void Write_Index_YUV(uint8_t* SK_RESTRICT dst, 1013 const void* SK_RESTRICT srcRow, int width, 1014 const SkPMColor* SK_RESTRICT ctable) { 1015 const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow; 1016 while (--width >= 0) { 1017 #ifdef WE_CONVERT_TO_YUV 1018 rgb2yuv_32(dst, ctable[*src++]); 1019 #else 1020 uint32_t c = ctable[*src++]; 1021 dst[0] = SkGetPackedR32(c); 1022 dst[1] = SkGetPackedG32(c); 1023 dst[2] = SkGetPackedB32(c); 1024 #endif 1025 dst += 3; 1026 } 1027 } 1028 1029 static WriteScanline ChooseWriter(const SkBitmap& bm) { 1030 switch (bm.config()) { 1031 case SkBitmap::kARGB_8888_Config: 1032 return Write_32_YUV; 1033 case SkBitmap::kRGB_565_Config: 1034 return Write_16_YUV; 1035 case SkBitmap::kARGB_4444_Config: 1036 return Write_4444_YUV; 1037 case SkBitmap::kIndex8_Config: 1038 return Write_Index_YUV; 1039 default: 1040 return NULL; 1041 } 1042 } 1043 1044 class SkJPEGImageEncoder : public SkImageEncoder { 1045 protected: 1046 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) { 1047 #ifdef TIME_ENCODE 1048 SkAutoTime atm("JPEG Encode"); 1049 #endif 1050 1051 SkAutoLockPixels alp(bm); 1052 if (NULL == bm.getPixels()) { 1053 return false; 1054 } 1055 1056 jpeg_compress_struct cinfo; 1057 skjpeg_error_mgr sk_err; 1058 skjpeg_destination_mgr sk_wstream(stream); 1059 1060 // allocate these before set call setjmp 1061 SkAutoMalloc oneRow; 1062 SkAutoLockColors ctLocker; 1063 1064 cinfo.err = jpeg_std_error(&sk_err); 1065 sk_err.error_exit = skjpeg_error_exit; 1066 if (setjmp(sk_err.fJmpBuf)) { 1067 return false; 1068 } 1069 1070 // Keep after setjmp or mark volatile. 1071 const WriteScanline writer = ChooseWriter(bm); 1072 if (NULL == writer) { 1073 return false; 1074 } 1075 1076 jpeg_create_compress(&cinfo); 1077 cinfo.dest = &sk_wstream; 1078 cinfo.image_width = bm.width(); 1079 cinfo.image_height = bm.height(); 1080 cinfo.input_components = 3; 1081 #ifdef WE_CONVERT_TO_YUV 1082 cinfo.in_color_space = JCS_YCbCr; 1083 #else 1084 cinfo.in_color_space = JCS_RGB; 1085 #endif 1086 cinfo.input_gamma = 1; 1087 1088 jpeg_set_defaults(&cinfo); 1089 jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); 1090 #ifdef DCT_IFAST_SUPPORTED 1091 cinfo.dct_method = JDCT_IFAST; 1092 #endif 1093 1094 jpeg_start_compress(&cinfo, TRUE); 1095 1096 const int width = bm.width(); 1097 uint8_t* oneRowP = (uint8_t*)oneRow.reset(width * 3); 1098 1099 const SkPMColor* colors = ctLocker.lockColors(bm); 1100 const void* srcRow = bm.getPixels(); 1101 1102 while (cinfo.next_scanline < cinfo.image_height) { 1103 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ 1104 1105 writer(oneRowP, srcRow, width, colors); 1106 row_pointer[0] = oneRowP; 1107 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); 1108 srcRow = (const void*)((const char*)srcRow + bm.rowBytes()); 1109 } 1110 1111 jpeg_finish_compress(&cinfo); 1112 jpeg_destroy_compress(&cinfo); 1113 1114 return true; 1115 } 1116 }; 1117 1118 /////////////////////////////////////////////////////////////////////////////// 1119 DEFINE_DECODER_CREATOR(JPEGImageDecoder); 1120 DEFINE_ENCODER_CREATOR(JPEGImageEncoder); 1121 /////////////////////////////////////////////////////////////////////////////// 1122 1123 static bool is_jpeg(SkStream* stream) { 1124 static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF }; 1125 static const size_t HEADER_SIZE = sizeof(gHeader); 1126 1127 char buffer[HEADER_SIZE]; 1128 size_t len = stream->read(buffer, HEADER_SIZE); 1129 1130 if (len != HEADER_SIZE) { 1131 return false; // can't read enough 1132 } 1133 if (memcmp(buffer, gHeader, HEADER_SIZE)) { 1134 return false; 1135 } 1136 return true; 1137 } 1138 1139 #include "SkTRegistry.h" 1140 1141 static SkImageDecoder* sk_libjpeg_dfactory(SkStream* stream) { 1142 if (is_jpeg(stream)) { 1143 return SkNEW(SkJPEGImageDecoder); 1144 } 1145 return NULL; 1146 } 1147 1148 static SkImageDecoder::Format get_format_jpeg(SkStream* stream) { 1149 if (is_jpeg(stream)) { 1150 return SkImageDecoder::kJPEG_Format; 1151 } 1152 return SkImageDecoder::kUnknown_Format; 1153 } 1154 1155 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { 1156 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; 1157 } 1158 1159 1160 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libjpeg_dfactory); 1161 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_jpeg); 1162 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libjpeg_efactory); 1163