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 "SkRTConf.h" 20#include "SkRect.h" 21#include "SkCanvas.h" 22 23 24#include <stdio.h> 25extern "C" { 26 #include "jpeglib.h" 27 #include "jerror.h" 28} 29 30// These enable timing code that report milliseconds for an encoding/decoding 31//#define TIME_ENCODE 32//#define TIME_DECODE 33 34// this enables our rgb->yuv code, which is faster than libjpeg on ARM 35#define WE_CONVERT_TO_YUV 36 37// If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offers 38// support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565. 39 40#if defined(SK_DEBUG) 41#define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS false 42#define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS false 43#else // !defined(SK_DEBUG) 44#define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS true 45#define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS true 46#endif // defined(SK_DEBUG) 47SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderWarnings, 48 "images.jpeg.suppressDecoderWarnings", 49 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS, 50 "Suppress most JPG warnings when calling decode functions."); 51SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderErrors, 52 "images.jpeg.suppressDecoderErrors", 53 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS, 54 "Suppress most JPG error messages when decode " 55 "function fails."); 56 57////////////////////////////////////////////////////////////////////////// 58////////////////////////////////////////////////////////////////////////// 59 60static void overwrite_mem_buffer_size(jpeg_decompress_struct* cinfo) { 61#ifdef SK_BUILD_FOR_ANDROID 62 /* Check if the device indicates that it has a large amount of system memory 63 * if so, increase the memory allocation to 30MB instead of the default 5MB. 64 */ 65#ifdef ANDROID_LARGE_MEMORY_DEVICE 66 cinfo->mem->max_memory_to_use = 30 * 1024 * 1024; 67#else 68 cinfo->mem->max_memory_to_use = 5 * 1024 * 1024; 69#endif 70#endif // SK_BUILD_FOR_ANDROID 71} 72 73////////////////////////////////////////////////////////////////////////// 74////////////////////////////////////////////////////////////////////////// 75 76static void do_nothing_emit_message(jpeg_common_struct*, int) { 77 /* do nothing */ 78} 79static void do_nothing_output_message(j_common_ptr) { 80 /* do nothing */ 81} 82 83static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* src_mgr) { 84 SkASSERT(cinfo != NULL); 85 SkASSERT(src_mgr != NULL); 86 jpeg_create_decompress(cinfo); 87 overwrite_mem_buffer_size(cinfo); 88 cinfo->src = src_mgr; 89 /* To suppress warnings with a SK_DEBUG binary, set the 90 * environment variable "skia_images_jpeg_suppressDecoderWarnings" 91 * to "true". Inside a program that links to skia: 92 * SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); */ 93 if (c_suppressJPEGImageDecoderWarnings) { 94 cinfo->err->emit_message = &do_nothing_emit_message; 95 } 96 /* To suppress error messages with a SK_DEBUG binary, set the 97 * environment variable "skia_images_jpeg_suppressDecoderErrors" 98 * to "true". Inside a program that links to skia: 99 * SK_CONF_SET("images.jpeg.suppressDecoderErrors", true); */ 100 if (c_suppressJPEGImageDecoderErrors) { 101 cinfo->err->output_message = &do_nothing_output_message; 102 } 103} 104 105#ifdef SK_BUILD_FOR_ANDROID 106class SkJPEGImageIndex { 107public: 108 // Takes ownership of stream. 109 SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder) 110 : fSrcMgr(stream, decoder) 111 , fStream(stream) 112 , fInfoInitialized(false) 113 , fHuffmanCreated(false) 114 , fDecompressStarted(false) 115 { 116 SkDEBUGCODE(fReadHeaderSucceeded = false;) 117 } 118 119 ~SkJPEGImageIndex() { 120 if (fHuffmanCreated) { 121 // Set to false before calling the libjpeg function, in case 122 // the libjpeg function calls longjmp. Our setjmp handler may 123 // attempt to delete this SkJPEGImageIndex, thus entering this 124 // destructor again. Setting fHuffmanCreated to false first 125 // prevents an infinite loop. 126 fHuffmanCreated = false; 127 jpeg_destroy_huffman_index(&fHuffmanIndex); 128 } 129 if (fDecompressStarted) { 130 // Like fHuffmanCreated, set to false before calling libjpeg 131 // function to prevent potential infinite loop. 132 fDecompressStarted = false; 133 jpeg_finish_decompress(&fCInfo); 134 } 135 if (fInfoInitialized) { 136 this->destroyInfo(); 137 } 138 } 139 140 /** 141 * Destroy the cinfo struct. 142 * After this call, if a huffman index was already built, it 143 * can be used after calling initializeInfoAndReadHeader 144 * again. Must not be called after startTileDecompress except 145 * in the destructor. 146 */ 147 void destroyInfo() { 148 SkASSERT(fInfoInitialized); 149 SkASSERT(!fDecompressStarted); 150 // Like fHuffmanCreated, set to false before calling libjpeg 151 // function to prevent potential infinite loop. 152 fInfoInitialized = false; 153 jpeg_destroy_decompress(&fCInfo); 154 SkDEBUGCODE(fReadHeaderSucceeded = false;) 155 } 156 157 /** 158 * Initialize the cinfo struct. 159 * Calls jpeg_create_decompress, makes customizations, and 160 * finally calls jpeg_read_header. Returns true if jpeg_read_header 161 * returns JPEG_HEADER_OK. 162 * If cinfo was already initialized, destroyInfo must be called to 163 * destroy the old one. Must not be called after startTileDecompress. 164 */ 165 bool initializeInfoAndReadHeader() { 166 SkASSERT(!fInfoInitialized && !fDecompressStarted); 167 initialize_info(&fCInfo, &fSrcMgr); 168 fInfoInitialized = true; 169 const bool success = (JPEG_HEADER_OK == jpeg_read_header(&fCInfo, true)); 170 SkDEBUGCODE(fReadHeaderSucceeded = success;) 171 return success; 172 } 173 174 jpeg_decompress_struct* cinfo() { return &fCInfo; } 175 176 huffman_index* huffmanIndex() { return &fHuffmanIndex; } 177 178 /** 179 * Build the index to be used for tile based decoding. 180 * Must only be called after a successful call to 181 * initializeInfoAndReadHeader and must not be called more 182 * than once. 183 */ 184 bool buildHuffmanIndex() { 185 SkASSERT(fReadHeaderSucceeded); 186 SkASSERT(!fHuffmanCreated); 187 jpeg_create_huffman_index(&fCInfo, &fHuffmanIndex); 188 SkASSERT(1 == fCInfo.scale_num && 1 == fCInfo.scale_denom); 189 fHuffmanCreated = jpeg_build_huffman_index(&fCInfo, &fHuffmanIndex); 190 return fHuffmanCreated; 191 } 192 193 /** 194 * Start tile based decoding. Must only be called after a 195 * successful call to buildHuffmanIndex, and must only be 196 * called once. 197 */ 198 bool startTileDecompress() { 199 SkASSERT(fHuffmanCreated); 200 SkASSERT(fReadHeaderSucceeded); 201 SkASSERT(!fDecompressStarted); 202 if (jpeg_start_tile_decompress(&fCInfo)) { 203 fDecompressStarted = true; 204 return true; 205 } 206 return false; 207 } 208 209private: 210 skjpeg_source_mgr fSrcMgr; 211 SkAutoTDelete<SkStream> fStream; 212 jpeg_decompress_struct fCInfo; 213 huffman_index fHuffmanIndex; 214 bool fInfoInitialized; 215 bool fHuffmanCreated; 216 bool fDecompressStarted; 217 SkDEBUGCODE(bool fReadHeaderSucceeded;) 218}; 219#endif 220 221class SkJPEGImageDecoder : public SkImageDecoder { 222public: 223#ifdef SK_BUILD_FOR_ANDROID 224 SkJPEGImageDecoder() { 225 fImageIndex = NULL; 226 fImageWidth = 0; 227 fImageHeight = 0; 228 } 229 230 virtual ~SkJPEGImageDecoder() { 231 SkDELETE(fImageIndex); 232 } 233#endif 234 235 Format getFormat() const override { 236 return kJPEG_Format; 237 } 238 239protected: 240#ifdef SK_BUILD_FOR_ANDROID 241 bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) override; 242 bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) override; 243#endif 244 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override; 245 bool onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3], 246 void* planes[3], size_t rowBytes[3], 247 SkYUVColorSpace* colorSpace) override; 248 249private: 250#ifdef SK_BUILD_FOR_ANDROID 251 SkJPEGImageIndex* fImageIndex; 252 int fImageWidth; 253 int fImageHeight; 254#endif 255 256 /** 257 * Determine the appropriate bitmap colortype and out_color_space based on 258 * both the preference of the caller and the jpeg_color_space on the 259 * jpeg_decompress_struct passed in. 260 * Must be called after jpeg_read_header. 261 */ 262 SkColorType getBitmapColorType(jpeg_decompress_struct*); 263 264 typedef SkImageDecoder INHERITED; 265}; 266 267////////////////////////////////////////////////////////////////////////// 268 269/* Automatically clean up after throwing an exception */ 270class JPEGAutoClean { 271public: 272 JPEGAutoClean(): cinfo_ptr(NULL) {} 273 ~JPEGAutoClean() { 274 if (cinfo_ptr) { 275 jpeg_destroy_decompress(cinfo_ptr); 276 } 277 } 278 void set(jpeg_decompress_struct* info) { 279 cinfo_ptr = info; 280 } 281private: 282 jpeg_decompress_struct* cinfo_ptr; 283}; 284 285/////////////////////////////////////////////////////////////////////////////// 286 287/* If we need to better match the request, we might examine the image and 288 output dimensions, and determine if the downsampling jpeg provided is 289 not sufficient. If so, we can recompute a modified sampleSize value to 290 make up the difference. 291 292 To skip this additional scaling, just set sampleSize = 1; below. 293 */ 294static int recompute_sampleSize(int sampleSize, 295 const jpeg_decompress_struct& cinfo) { 296 return sampleSize * cinfo.output_width / cinfo.image_width; 297} 298 299static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) { 300 /* These are initialized to 0, so if they have non-zero values, we assume 301 they are "valid" (i.e. have been computed by libjpeg) 302 */ 303 return 0 != cinfo.output_width && 0 != cinfo.output_height; 304} 305 306static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count) { 307 for (int i = 0; i < count; i++) { 308 JSAMPLE* rowptr = (JSAMPLE*)buffer; 309 int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1); 310 if (1 != row_count) { 311 return false; 312 } 313 } 314 return true; 315} 316 317#ifdef SK_BUILD_FOR_ANDROID 318static bool skip_src_rows_tile(jpeg_decompress_struct* cinfo, 319 huffman_index *index, void* buffer, int count) { 320 for (int i = 0; i < count; i++) { 321 JSAMPLE* rowptr = (JSAMPLE*)buffer; 322 int row_count = jpeg_read_tile_scanline(cinfo, index, &rowptr); 323 if (1 != row_count) { 324 return false; 325 } 326 } 327 return true; 328} 329#endif 330 331/////////////////////////////////////////////////////////////////////////////// 332 333// This guy exists just to aid in debugging, as it allows debuggers to just 334// set a break-point in one place to see all error exists. 335static void print_jpeg_decoder_errors(const jpeg_decompress_struct& cinfo, 336 int width, int height, const char caller[]) { 337 if (!(c_suppressJPEGImageDecoderErrors)) { 338 char buffer[JMSG_LENGTH_MAX]; 339 cinfo.err->format_message((const j_common_ptr)&cinfo, buffer); 340 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n", 341 cinfo.err->msg_code, buffer, caller, width, height); 342 } 343} 344 345static bool return_false(const jpeg_decompress_struct& cinfo, 346 const char caller[]) { 347 print_jpeg_decoder_errors(cinfo, 0, 0, caller); 348 return false; 349} 350 351#ifdef SK_BUILD_FOR_ANDROID 352static bool return_false(const jpeg_decompress_struct& cinfo, 353 const SkBitmap& bm, const char caller[]) { 354 print_jpeg_decoder_errors(cinfo, bm.width(), bm.height(), caller); 355 return false; 356} 357#endif 358 359static SkImageDecoder::Result return_failure(const jpeg_decompress_struct& cinfo, 360 const SkBitmap& bm, const char caller[]) { 361 print_jpeg_decoder_errors(cinfo, bm.width(), bm.height(), caller); 362 return SkImageDecoder::kFailure; 363} 364 365/////////////////////////////////////////////////////////////////////////////// 366 367// Convert a scanline of CMYK samples to RGBX in place. Note that this 368// method moves the "scanline" pointer in its processing 369static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) { 370 // At this point we've received CMYK pixels from libjpeg. We 371 // perform a crude conversion to RGB (based on the formulae 372 // from easyrgb.com): 373 // CMYK -> CMY 374 // C = ( C * (1 - K) + K ) // for each CMY component 375 // CMY -> RGB 376 // R = ( 1 - C ) * 255 // for each RGB component 377 // Unfortunately we are seeing inverted CMYK so all the original terms 378 // are 1-. This yields: 379 // CMYK -> CMY 380 // C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K 381 // The conversion from CMY->RGB remains the same 382 for (unsigned int x = 0; x < width; ++x, scanline += 4) { 383 scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]); 384 scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]); 385 scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]); 386 scanline[3] = 255; 387 } 388} 389 390/** 391 * Common code for setting the error manager. 392 */ 393static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* errorManager) { 394 SkASSERT(cinfo != NULL); 395 SkASSERT(errorManager != NULL); 396 cinfo->err = jpeg_std_error(errorManager); 397 errorManager->error_exit = skjpeg_error_exit; 398} 399 400/** 401 * Common code for turning off upsampling and smoothing. Turning these 402 * off helps performance without showing noticable differences in the 403 * resulting bitmap. 404 */ 405static void turn_off_visual_optimizations(jpeg_decompress_struct* cinfo) { 406 SkASSERT(cinfo != NULL); 407 /* this gives about 30% performance improvement. In theory it may 408 reduce the visual quality, in practice I'm not seeing a difference 409 */ 410 cinfo->do_fancy_upsampling = 0; 411 412 /* this gives another few percents */ 413 cinfo->do_block_smoothing = 0; 414} 415 416/** 417 * Common code for setting the dct method. 418 */ 419static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct* cinfo) { 420 SkASSERT(cinfo != NULL); 421#ifdef DCT_IFAST_SUPPORTED 422 if (decoder.getPreferQualityOverSpeed()) { 423 cinfo->dct_method = JDCT_ISLOW; 424 } else { 425 cinfo->dct_method = JDCT_IFAST; 426 } 427#else 428 cinfo->dct_method = JDCT_ISLOW; 429#endif 430} 431 432SkColorType SkJPEGImageDecoder::getBitmapColorType(jpeg_decompress_struct* cinfo) { 433 SkASSERT(cinfo != NULL); 434 435 SrcDepth srcDepth = k32Bit_SrcDepth; 436 if (JCS_GRAYSCALE == cinfo->jpeg_color_space) { 437 srcDepth = k8BitGray_SrcDepth; 438 } 439 440 SkColorType colorType = this->getPrefColorType(srcDepth, /*hasAlpha*/ false); 441 switch (colorType) { 442 case kAlpha_8_SkColorType: 443 // Only respect A8 colortype if the original is grayscale, 444 // in which case we will treat the grayscale as alpha 445 // values. 446 if (cinfo->jpeg_color_space != JCS_GRAYSCALE) { 447 colorType = kN32_SkColorType; 448 } 449 break; 450 case kN32_SkColorType: 451 // Fall through. 452 case kARGB_4444_SkColorType: 453 // Fall through. 454 case kRGB_565_SkColorType: 455 // These are acceptable destination colortypes. 456 break; 457 default: 458 // Force all other colortypes to 8888. 459 colorType = kN32_SkColorType; 460 break; 461 } 462 463 switch (cinfo->jpeg_color_space) { 464 case JCS_CMYK: 465 // Fall through. 466 case JCS_YCCK: 467 // libjpeg cannot convert from CMYK or YCCK to RGB - here we set up 468 // so libjpeg will give us CMYK samples back and we will later 469 // manually convert them to RGB 470 cinfo->out_color_space = JCS_CMYK; 471 break; 472 case JCS_GRAYSCALE: 473 if (kAlpha_8_SkColorType == colorType) { 474 cinfo->out_color_space = JCS_GRAYSCALE; 475 break; 476 } 477 // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB 478 // colortype. Fall through to set to the default. 479 default: 480 cinfo->out_color_space = JCS_RGB; 481 break; 482 } 483 return colorType; 484} 485 486/** 487 * Based on the colortype and dither mode, adjust out_color_space and 488 * dither_mode of cinfo. Only does work in ANDROID_RGB 489 */ 490static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo, 491 SkColorType colorType, 492 const SkImageDecoder& decoder) { 493 SkASSERT(cinfo != NULL); 494#ifdef ANDROID_RGB 495 cinfo->dither_mode = JDITHER_NONE; 496 if (JCS_CMYK == cinfo->out_color_space) { 497 return; 498 } 499 switch (colorType) { 500 case kN32_SkColorType: 501 cinfo->out_color_space = JCS_RGBA_8888; 502 break; 503 case kRGB_565_SkColorType: 504 cinfo->out_color_space = JCS_RGB_565; 505 if (decoder.getDitherImage()) { 506 cinfo->dither_mode = JDITHER_ORDERED; 507 } 508 break; 509 default: 510 break; 511 } 512#endif 513} 514 515/** 516 Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y. 517 Used when decoding fails partway through reading scanlines to fill 518 remaining lines. */ 519static void fill_below_level(int y, SkBitmap* bitmap) { 520 SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height()); 521 SkCanvas canvas(*bitmap); 522 canvas.clipRect(SkRect::Make(rect)); 523 canvas.drawColor(SK_ColorWHITE); 524} 525 526/** 527 * Get the config and bytes per pixel of the source data. Return 528 * whether the data is supported. 529 */ 530static bool get_src_config(const jpeg_decompress_struct& cinfo, 531 SkScaledBitmapSampler::SrcConfig* sc, 532 int* srcBytesPerPixel) { 533 SkASSERT(sc != NULL && srcBytesPerPixel != NULL); 534 if (JCS_CMYK == cinfo.out_color_space) { 535 // In this case we will manually convert the CMYK values to RGB 536 *sc = SkScaledBitmapSampler::kRGBX; 537 // The CMYK work-around relies on 4 components per pixel here 538 *srcBytesPerPixel = 4; 539 } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) { 540 *sc = SkScaledBitmapSampler::kRGB; 541 *srcBytesPerPixel = 3; 542#ifdef ANDROID_RGB 543 } else if (JCS_RGBA_8888 == cinfo.out_color_space) { 544 *sc = SkScaledBitmapSampler::kRGBX; 545 *srcBytesPerPixel = 4; 546 } else if (JCS_RGB_565 == cinfo.out_color_space) { 547 *sc = SkScaledBitmapSampler::kRGB_565; 548 *srcBytesPerPixel = 2; 549#endif 550 } else if (1 == cinfo.out_color_components && 551 JCS_GRAYSCALE == cinfo.out_color_space) { 552 *sc = SkScaledBitmapSampler::kGray; 553 *srcBytesPerPixel = 1; 554 } else { 555 return false; 556 } 557 return true; 558} 559 560SkImageDecoder::Result SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { 561#ifdef TIME_DECODE 562 SkAutoTime atm("JPEG Decode"); 563#endif 564 565 JPEGAutoClean autoClean; 566 567 jpeg_decompress_struct cinfo; 568 skjpeg_source_mgr srcManager(stream, this); 569 570 skjpeg_error_mgr errorManager; 571 set_error_mgr(&cinfo, &errorManager); 572 573 // All objects need to be instantiated before this setjmp call so that 574 // they will be cleaned up properly if an error occurs. 575 if (setjmp(errorManager.fJmpBuf)) { 576 return return_failure(cinfo, *bm, "setjmp"); 577 } 578 579 initialize_info(&cinfo, &srcManager); 580 autoClean.set(&cinfo); 581 582 int status = jpeg_read_header(&cinfo, true); 583 if (status != JPEG_HEADER_OK) { 584 return return_failure(cinfo, *bm, "read_header"); 585 } 586 587 /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it 588 can) much faster that we, just use their num/denom api to approximate 589 the size. 590 */ 591 int sampleSize = this->getSampleSize(); 592 593 set_dct_method(*this, &cinfo); 594 595 SkASSERT(1 == cinfo.scale_num); 596 cinfo.scale_denom = sampleSize; 597 598 turn_off_visual_optimizations(&cinfo); 599 600 const SkColorType colorType = this->getBitmapColorType(&cinfo); 601 const SkAlphaType alphaType = kAlpha_8_SkColorType == colorType ? 602 kPremul_SkAlphaType : kOpaque_SkAlphaType; 603 604 adjust_out_color_space_and_dither(&cinfo, colorType, *this); 605 606 if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) { 607 // Assume an A8 bitmap is not opaque to avoid the check of each 608 // individual pixel. It is very unlikely to be opaque, since 609 // an opaque A8 bitmap would not be very interesting. 610 // Otherwise, a jpeg image is opaque. 611 bool success = bm->setInfo(SkImageInfo::Make(cinfo.image_width, cinfo.image_height, 612 colorType, alphaType)); 613 return success ? kSuccess : kFailure; 614 } 615 616 /* image_width and image_height are the original dimensions, available 617 after jpeg_read_header(). To see the scaled dimensions, we have to call 618 jpeg_start_decompress(), and then read output_width and output_height. 619 */ 620 if (!jpeg_start_decompress(&cinfo)) { 621 /* If we failed here, we may still have enough information to return 622 to the caller if they just wanted (subsampled bounds). If sampleSize 623 was 1, then we would have already returned. Thus we just check if 624 we're in kDecodeBounds_Mode, and that we have valid output sizes. 625 626 One reason to fail here is that we have insufficient stream data 627 to complete the setup. However, output dimensions seem to get 628 computed very early, which is why this special check can pay off. 629 */ 630 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimensions(cinfo)) { 631 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height, 632 recompute_sampleSize(sampleSize, cinfo)); 633 // Assume an A8 bitmap is not opaque to avoid the check of each 634 // individual pixel. It is very unlikely to be opaque, since 635 // an opaque A8 bitmap would not be very interesting. 636 // Otherwise, a jpeg image is opaque. 637 bool success = bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaledHeight(), 638 colorType, alphaType)); 639 return success ? kSuccess : kFailure; 640 } else { 641 return return_failure(cinfo, *bm, "start_decompress"); 642 } 643 } 644 sampleSize = recompute_sampleSize(sampleSize, cinfo); 645 646 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize); 647 // Assume an A8 bitmap is not opaque to avoid the check of each 648 // individual pixel. It is very unlikely to be opaque, since 649 // an opaque A8 bitmap would not be very interesting. 650 // Otherwise, a jpeg image is opaque. 651 bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), 652 colorType, alphaType)); 653 if (SkImageDecoder::kDecodeBounds_Mode == mode) { 654 return kSuccess; 655 } 656 if (!this->allocPixelRef(bm, NULL)) { 657 return return_failure(cinfo, *bm, "allocPixelRef"); 658 } 659 660 SkAutoLockPixels alp(*bm); 661 662#ifdef ANDROID_RGB 663 /* short-circuit the SkScaledBitmapSampler when possible, as this gives 664 a significant performance boost. 665 */ 666 if (sampleSize == 1 && 667 ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_8888) || 668 (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_565))) 669 { 670 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); 671 INT32 const bpr = bm->rowBytes(); 672 673 while (cinfo.output_scanline < cinfo.output_height) { 674 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 675 if (0 == row_count) { 676 // if row_count == 0, then we didn't get a scanline, 677 // so return early. We will return a partial image. 678 fill_below_level(cinfo.output_scanline, bm); 679 cinfo.output_scanline = cinfo.output_height; 680 jpeg_finish_decompress(&cinfo); 681 return kPartialSuccess; 682 } 683 if (this->shouldCancelDecode()) { 684 return return_failure(cinfo, *bm, "shouldCancelDecode"); 685 } 686 rowptr += bpr; 687 } 688 jpeg_finish_decompress(&cinfo); 689 return kSuccess; 690 } 691#endif 692 693 // check for supported formats 694 SkScaledBitmapSampler::SrcConfig sc; 695 int srcBytesPerPixel; 696 697 if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) { 698 return return_failure(cinfo, *bm, "jpeg colorspace"); 699 } 700 701 if (!sampler.begin(bm, sc, *this)) { 702 return return_failure(cinfo, *bm, "sampler.begin"); 703 } 704 705 SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel); 706 uint8_t* srcRow = (uint8_t*)srcStorage.get(); 707 708 // Possibly skip initial rows [sampler.srcY0] 709 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) { 710 return return_failure(cinfo, *bm, "skip rows"); 711 } 712 713 // now loop through scanlines until y == bm->height() - 1 714 for (int y = 0;; y++) { 715 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 716 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 717 if (0 == row_count) { 718 // if row_count == 0, then we didn't get a scanline, 719 // so return early. We will return a partial image. 720 fill_below_level(y, bm); 721 cinfo.output_scanline = cinfo.output_height; 722 jpeg_finish_decompress(&cinfo); 723 return kPartialSuccess; 724 } 725 if (this->shouldCancelDecode()) { 726 return return_failure(cinfo, *bm, "shouldCancelDecode"); 727 } 728 729 if (JCS_CMYK == cinfo.out_color_space) { 730 convert_CMYK_to_RGB(srcRow, cinfo.output_width); 731 } 732 733 sampler.next(srcRow); 734 if (bm->height() - 1 == y) { 735 // we're done 736 break; 737 } 738 739 if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) { 740 return return_failure(cinfo, *bm, "skip rows"); 741 } 742 } 743 744 // we formally skip the rest, so we don't get a complaint from libjpeg 745 if (!skip_src_rows(&cinfo, srcRow, 746 cinfo.output_height - cinfo.output_scanline)) { 747 return return_failure(cinfo, *bm, "skip rows"); 748 } 749 jpeg_finish_decompress(&cinfo); 750 751 return kSuccess; 752} 753 754/////////////////////////////////////////////////////////////////////////////// 755 756enum SizeType { 757 kSizeForMemoryAllocation_SizeType, 758 kActualSize_SizeType 759}; 760 761static SkISize compute_yuv_size(const jpeg_decompress_struct& info, int component, 762 SizeType sizeType) { 763 if (sizeType == kSizeForMemoryAllocation_SizeType) { 764 return SkISize::Make(info.cur_comp_info[component]->width_in_blocks * DCTSIZE, 765 info.cur_comp_info[component]->height_in_blocks * DCTSIZE); 766 } 767 return SkISize::Make(info.cur_comp_info[component]->downsampled_width, 768 info.cur_comp_info[component]->downsampled_height); 769} 770 771static bool appears_to_be_yuv(const jpeg_decompress_struct& info) { 772 return (info.jpeg_color_space == JCS_YCbCr) 773 && (DCTSIZE == 8) 774 && (info.num_components == 3) 775 && (info.comps_in_scan >= info.num_components) 776 && (info.scale_denom <= 8) 777 && (info.cur_comp_info[0]) 778 && (info.cur_comp_info[1]) 779 && (info.cur_comp_info[2]) 780 && (info.cur_comp_info[1]->h_samp_factor == 1) 781 && (info.cur_comp_info[1]->v_samp_factor == 1) 782 && (info.cur_comp_info[2]->h_samp_factor == 1) 783 && (info.cur_comp_info[2]->v_samp_factor == 1); 784} 785 786static void update_components_sizes(const jpeg_decompress_struct& cinfo, SkISize componentSizes[3], 787 SizeType sizeType) { 788 SkASSERT(appears_to_be_yuv(cinfo)); 789 for (int i = 0; i < 3; ++i) { 790 componentSizes[i] = compute_yuv_size(cinfo, i, sizeType); 791 } 792} 793 794static bool output_raw_data(jpeg_decompress_struct& cinfo, void* planes[3], size_t rowBytes[3]) { 795 SkASSERT(appears_to_be_yuv(cinfo)); 796 // U size and V size have to be the same if we're calling output_raw_data() 797 SkISize uvSize = compute_yuv_size(cinfo, 1, kSizeForMemoryAllocation_SizeType); 798 SkASSERT(uvSize == compute_yuv_size(cinfo, 2, kSizeForMemoryAllocation_SizeType)); 799 800 JSAMPARRAY bufferraw[3]; 801 JSAMPROW bufferraw2[32]; 802 bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16) 803 bufferraw[1] = &bufferraw2[16]; // U channel rows (8) 804 bufferraw[2] = &bufferraw2[24]; // V channel rows (8) 805 int yWidth = cinfo.output_width; 806 int yHeight = cinfo.output_height; 807 int yMaxH = yHeight - 1; 808 int v = cinfo.cur_comp_info[0]->v_samp_factor; 809 int uvMaxH = uvSize.height() - 1; 810 JSAMPROW outputY = static_cast<JSAMPROW>(planes[0]); 811 JSAMPROW outputU = static_cast<JSAMPROW>(planes[1]); 812 JSAMPROW outputV = static_cast<JSAMPROW>(planes[2]); 813 size_t rowBytesY = rowBytes[0]; 814 size_t rowBytesU = rowBytes[1]; 815 size_t rowBytesV = rowBytes[2]; 816 817 int yScanlinesToRead = DCTSIZE * v; 818 SkAutoMalloc lastRowStorage(rowBytesY * 4); 819 JSAMPROW yLastRow = (JSAMPROW)lastRowStorage.get(); 820 JSAMPROW uLastRow = yLastRow + rowBytesY; 821 JSAMPROW vLastRow = uLastRow + rowBytesY; 822 JSAMPROW dummyRow = vLastRow + rowBytesY; 823 824 while (cinfo.output_scanline < cinfo.output_height) { 825 // Request 8 or 16 scanlines: returns 0 or more scanlines. 826 bool hasYLastRow(false), hasUVLastRow(false); 827 // Assign 8 or 16 rows of memory to read the Y channel. 828 for (int i = 0; i < yScanlinesToRead; ++i) { 829 int scanline = (cinfo.output_scanline + i); 830 if (scanline < yMaxH) { 831 bufferraw2[i] = &outputY[scanline * rowBytesY]; 832 } else if (scanline == yMaxH) { 833 bufferraw2[i] = yLastRow; 834 hasYLastRow = true; 835 } else { 836 bufferraw2[i] = dummyRow; 837 } 838 } 839 int scaledScanline = cinfo.output_scanline / v; 840 // Assign 8 rows of memory to read the U and V channels. 841 for (int i = 0; i < 8; ++i) { 842 int scanline = (scaledScanline + i); 843 if (scanline < uvMaxH) { 844 bufferraw2[16 + i] = &outputU[scanline * rowBytesU]; 845 bufferraw2[24 + i] = &outputV[scanline * rowBytesV]; 846 } else if (scanline == uvMaxH) { 847 bufferraw2[16 + i] = uLastRow; 848 bufferraw2[24 + i] = vLastRow; 849 hasUVLastRow = true; 850 } else { 851 bufferraw2[16 + i] = dummyRow; 852 bufferraw2[24 + i] = dummyRow; 853 } 854 } 855 JDIMENSION scanlinesRead = jpeg_read_raw_data(&cinfo, bufferraw, yScanlinesToRead); 856 857 if (scanlinesRead == 0) { 858 return false; 859 } 860 861 if (hasYLastRow) { 862 memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth); 863 } 864 if (hasUVLastRow) { 865 memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width()); 866 memcpy(&outputV[uvMaxH * rowBytesV], vLastRow, uvSize.width()); 867 } 868 } 869 870 cinfo.output_scanline = SkMin32(cinfo.output_scanline, cinfo.output_height); 871 872 return true; 873} 874 875bool SkJPEGImageDecoder::onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3], 876 void* planes[3], size_t rowBytes[3], 877 SkYUVColorSpace* colorSpace) { 878#ifdef TIME_DECODE 879 SkAutoTime atm("JPEG YUV8 Decode"); 880#endif 881 if (this->getSampleSize() != 1) { 882 return false; // Resizing not supported 883 } 884 885 JPEGAutoClean autoClean; 886 887 jpeg_decompress_struct cinfo; 888 skjpeg_source_mgr srcManager(stream, this); 889 890 skjpeg_error_mgr errorManager; 891 set_error_mgr(&cinfo, &errorManager); 892 893 // All objects need to be instantiated before this setjmp call so that 894 // they will be cleaned up properly if an error occurs. 895 if (setjmp(errorManager.fJmpBuf)) { 896 return return_false(cinfo, "setjmp YUV8"); 897 } 898 899 initialize_info(&cinfo, &srcManager); 900 autoClean.set(&cinfo); 901 902 int status = jpeg_read_header(&cinfo, true); 903 if (status != JPEG_HEADER_OK) { 904 return return_false(cinfo, "read_header YUV8"); 905 } 906 907 if (!appears_to_be_yuv(cinfo)) { 908 // It's not an error to not be encoded in YUV, so no need to use return_false() 909 return false; 910 } 911 912 cinfo.out_color_space = JCS_YCbCr; 913 cinfo.raw_data_out = TRUE; 914 915 if (!planes || !planes[0] || !rowBytes || !rowBytes[0]) { // Compute size only 916 update_components_sizes(cinfo, componentSizes, kSizeForMemoryAllocation_SizeType); 917 return true; 918 } 919 920 set_dct_method(*this, &cinfo); 921 922 SkASSERT(1 == cinfo.scale_num); 923 cinfo.scale_denom = 1; 924 925 turn_off_visual_optimizations(&cinfo); 926 927#ifdef ANDROID_RGB 928 cinfo.dither_mode = JDITHER_NONE; 929#endif 930 931 /* image_width and image_height are the original dimensions, available 932 after jpeg_read_header(). To see the scaled dimensions, we have to call 933 jpeg_start_decompress(), and then read output_width and output_height. 934 */ 935 if (!jpeg_start_decompress(&cinfo)) { 936 return return_false(cinfo, "start_decompress YUV8"); 937 } 938 939 // Seems like jpeg_start_decompress is updating our opinion of whether cinfo represents YUV. 940 // Again, not really an error. 941 if (!appears_to_be_yuv(cinfo)) { 942 return false; 943 } 944 945 if (!output_raw_data(cinfo, planes, rowBytes)) { 946 return return_false(cinfo, "output_raw_data"); 947 } 948 949 update_components_sizes(cinfo, componentSizes, kActualSize_SizeType); 950 jpeg_finish_decompress(&cinfo); 951 952 if (NULL != colorSpace) { 953 *colorSpace = kJPEG_SkYUVColorSpace; 954 } 955 956 return true; 957} 958 959/////////////////////////////////////////////////////////////////////////////// 960 961#ifdef SK_BUILD_FOR_ANDROID 962bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width, int *height) { 963 964 SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (stream, this))); 965 966 skjpeg_error_mgr sk_err; 967 set_error_mgr(imageIndex->cinfo(), &sk_err); 968 969 // All objects need to be instantiated before this setjmp call so that 970 // they will be cleaned up properly if an error occurs. 971 if (setjmp(sk_err.fJmpBuf)) { 972 return false; 973 } 974 975 // create the cinfo used to create/build the huffmanIndex 976 if (!imageIndex->initializeInfoAndReadHeader()) { 977 return false; 978 } 979 980 if (!imageIndex->buildHuffmanIndex()) { 981 return false; 982 } 983 984 // destroy the cinfo used to create/build the huffman index 985 imageIndex->destroyInfo(); 986 987 // Init decoder to image decode mode 988 if (!imageIndex->initializeInfoAndReadHeader()) { 989 return false; 990 } 991 992 jpeg_decompress_struct* cinfo = imageIndex->cinfo(); 993 // We have a new cinfo, so set the error mgr again. 994 set_error_mgr(cinfo, &sk_err); 995 996 // FIXME: This sets cinfo->out_color_space, which we may change later 997 // based on the config in onDecodeSubset. This should be fine, since 998 // jpeg_init_read_tile_scanline will check out_color_space again after 999 // that change (when it calls jinit_color_deconverter). 1000 (void) this->getBitmapColorType(cinfo); 1001 1002 turn_off_visual_optimizations(cinfo); 1003 1004 // instead of jpeg_start_decompress() we start a tiled decompress 1005 if (!imageIndex->startTileDecompress()) { 1006 return false; 1007 } 1008 1009 SkASSERT(1 == cinfo->scale_num); 1010 fImageWidth = cinfo->output_width; 1011 fImageHeight = cinfo->output_height; 1012 1013 if (width) { 1014 *width = fImageWidth; 1015 } 1016 if (height) { 1017 *height = fImageHeight; 1018 } 1019 1020 SkDELETE(fImageIndex); 1021 fImageIndex = imageIndex.detach(); 1022 1023 return true; 1024} 1025 1026bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { 1027 if (NULL == fImageIndex) { 1028 return false; 1029 } 1030 jpeg_decompress_struct* cinfo = fImageIndex->cinfo(); 1031 1032 SkIRect rect = SkIRect::MakeWH(fImageWidth, fImageHeight); 1033 if (!rect.intersect(region)) { 1034 // If the requested region is entirely outside the image return false 1035 return false; 1036 } 1037 1038 1039 skjpeg_error_mgr errorManager; 1040 set_error_mgr(cinfo, &errorManager); 1041 1042 if (setjmp(errorManager.fJmpBuf)) { 1043 return false; 1044 } 1045 1046 int requestedSampleSize = this->getSampleSize(); 1047 cinfo->scale_denom = requestedSampleSize; 1048 1049 set_dct_method(*this, cinfo); 1050 1051 const SkColorType colorType = this->getBitmapColorType(cinfo); 1052 adjust_out_color_space_and_dither(cinfo, colorType, *this); 1053 1054 int startX = rect.fLeft; 1055 int startY = rect.fTop; 1056 int width = rect.width(); 1057 int height = rect.height(); 1058 1059 jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), 1060 &startX, &startY, &width, &height); 1061 int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo); 1062 int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_size); 1063 1064 SkScaledBitmapSampler sampler(width, height, skiaSampleSize); 1065 1066 SkBitmap bitmap; 1067 // Assume an A8 bitmap is not opaque to avoid the check of each 1068 // individual pixel. It is very unlikely to be opaque, since 1069 // an opaque A8 bitmap would not be very interesting. 1070 // Otherwise, a jpeg image is opaque. 1071 bitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), colorType, 1072 kAlpha_8_SkColorType == colorType ? 1073 kPremul_SkAlphaType : kOpaque_SkAlphaType)); 1074 1075 // Check ahead of time if the swap(dest, src) is possible or not. 1076 // If yes, then we will stick to AllocPixelRef since it's cheaper with the 1077 // swap happening. If no, then we will use alloc to allocate pixels to 1078 // prevent garbage collection. 1079 int w = rect.width() / actualSampleSize; 1080 int h = rect.height() / actualSampleSize; 1081 bool swapOnly = (rect == region) && bm->isNull() && 1082 (w == bitmap.width()) && (h == bitmap.height()) && 1083 ((startX - rect.x()) / actualSampleSize == 0) && 1084 ((startY - rect.y()) / actualSampleSize == 0); 1085 if (swapOnly) { 1086 if (!this->allocPixelRef(&bitmap, NULL)) { 1087 return return_false(*cinfo, bitmap, "allocPixelRef"); 1088 } 1089 } else { 1090 if (!bitmap.tryAllocPixels()) { 1091 return return_false(*cinfo, bitmap, "allocPixels"); 1092 } 1093 } 1094 1095 SkAutoLockPixels alp(bitmap); 1096 1097#ifdef ANDROID_RGB 1098 /* short-circuit the SkScaledBitmapSampler when possible, as this gives 1099 a significant performance boost. 1100 */ 1101 if (skiaSampleSize == 1 && 1102 ((kN32_SkColorType == colorType && cinfo->out_color_space == JCS_RGBA_8888) || 1103 (kRGB_565_SkColorType == colorType && cinfo->out_color_space == JCS_RGB_565))) 1104 { 1105 JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels(); 1106 INT32 const bpr = bitmap.rowBytes(); 1107 int rowTotalCount = 0; 1108 1109 while (rowTotalCount < height) { 1110 int rowCount = jpeg_read_tile_scanline(cinfo, 1111 fImageIndex->huffmanIndex(), 1112 &rowptr); 1113 // if rowCount == 0, then we didn't get a scanline, so abort. 1114 // onDecodeSubset() relies on onBuildTileIndex(), which 1115 // needs a complete image to succeed. 1116 if (0 == rowCount) { 1117 return return_false(*cinfo, bitmap, "read_scanlines"); 1118 } 1119 if (this->shouldCancelDecode()) { 1120 return return_false(*cinfo, bitmap, "shouldCancelDecode"); 1121 } 1122 rowTotalCount += rowCount; 1123 rowptr += bpr; 1124 } 1125 1126 if (swapOnly) { 1127 bm->swap(bitmap); 1128 return true; 1129 } 1130 1131 return cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(), 1132 region.width(), region.height(), startX, startY); 1133 } 1134#endif 1135 1136 // check for supported formats 1137 SkScaledBitmapSampler::SrcConfig sc; 1138 int srcBytesPerPixel; 1139 1140 if (!get_src_config(*cinfo, &sc, &srcBytesPerPixel)) { 1141 return return_false(*cinfo, *bm, "jpeg colorspace"); 1142 } 1143 1144 if (!sampler.begin(&bitmap, sc, *this)) { 1145 return return_false(*cinfo, bitmap, "sampler.begin"); 1146 } 1147 1148 SkAutoMalloc srcStorage(width * srcBytesPerPixel); 1149 uint8_t* srcRow = (uint8_t*)srcStorage.get(); 1150 1151 // Possibly skip initial rows [sampler.srcY0] 1152 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler.srcY0())) { 1153 return return_false(*cinfo, bitmap, "skip rows"); 1154 } 1155 1156 // now loop through scanlines until y == bitmap->height() - 1 1157 for (int y = 0;; y++) { 1158 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 1159 int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), &rowptr); 1160 // if row_count == 0, then we didn't get a scanline, so abort. 1161 // onDecodeSubset() relies on onBuildTileIndex(), which 1162 // needs a complete image to succeed. 1163 if (0 == row_count) { 1164 return return_false(*cinfo, bitmap, "read_scanlines"); 1165 } 1166 if (this->shouldCancelDecode()) { 1167 return return_false(*cinfo, bitmap, "shouldCancelDecode"); 1168 } 1169 1170 if (JCS_CMYK == cinfo->out_color_space) { 1171 convert_CMYK_to_RGB(srcRow, width); 1172 } 1173 1174 sampler.next(srcRow); 1175 if (bitmap.height() - 1 == y) { 1176 // we're done 1177 break; 1178 } 1179 1180 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, 1181 sampler.srcDY() - 1)) { 1182 return return_false(*cinfo, bitmap, "skip rows"); 1183 } 1184 } 1185 if (swapOnly) { 1186 bm->swap(bitmap); 1187 return true; 1188 } 1189 return cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(), 1190 region.width(), region.height(), startX, startY); 1191} 1192#endif 1193 1194/////////////////////////////////////////////////////////////////////////////// 1195 1196#include "SkColorPriv.h" 1197 1198// taken from jcolor.c in libjpeg 1199#if 0 // 16bit - precise but slow 1200 #define CYR 19595 // 0.299 1201 #define CYG 38470 // 0.587 1202 #define CYB 7471 // 0.114 1203 1204 #define CUR -11059 // -0.16874 1205 #define CUG -21709 // -0.33126 1206 #define CUB 32768 // 0.5 1207 1208 #define CVR 32768 // 0.5 1209 #define CVG -27439 // -0.41869 1210 #define CVB -5329 // -0.08131 1211 1212 #define CSHIFT 16 1213#else // 8bit - fast, slightly less precise 1214 #define CYR 77 // 0.299 1215 #define CYG 150 // 0.587 1216 #define CYB 29 // 0.114 1217 1218 #define CUR -43 // -0.16874 1219 #define CUG -85 // -0.33126 1220 #define CUB 128 // 0.5 1221 1222 #define CVR 128 // 0.5 1223 #define CVG -107 // -0.41869 1224 #define CVB -21 // -0.08131 1225 1226 #define CSHIFT 8 1227#endif 1228 1229static void rgb2yuv_32(uint8_t dst[], SkPMColor c) { 1230 int r = SkGetPackedR32(c); 1231 int g = SkGetPackedG32(c); 1232 int b = SkGetPackedB32(c); 1233 1234 int y = ( CYR*r + CYG*g + CYB*b ) >> CSHIFT; 1235 int u = ( CUR*r + CUG*g + CUB*b ) >> CSHIFT; 1236 int v = ( CVR*r + CVG*g + CVB*b ) >> CSHIFT; 1237 1238 dst[0] = SkToU8(y); 1239 dst[1] = SkToU8(u + 128); 1240 dst[2] = SkToU8(v + 128); 1241} 1242 1243static void rgb2yuv_4444(uint8_t dst[], U16CPU c) { 1244 int r = SkGetPackedR4444(c); 1245 int g = SkGetPackedG4444(c); 1246 int b = SkGetPackedB4444(c); 1247 1248 int y = ( CYR*r + CYG*g + CYB*b ) >> (CSHIFT - 4); 1249 int u = ( CUR*r + CUG*g + CUB*b ) >> (CSHIFT - 4); 1250 int v = ( CVR*r + CVG*g + CVB*b ) >> (CSHIFT - 4); 1251 1252 dst[0] = SkToU8(y); 1253 dst[1] = SkToU8(u + 128); 1254 dst[2] = SkToU8(v + 128); 1255} 1256 1257static void rgb2yuv_16(uint8_t dst[], U16CPU c) { 1258 int r = SkGetPackedR16(c); 1259 int g = SkGetPackedG16(c); 1260 int b = SkGetPackedB16(c); 1261 1262 int y = ( 2*CYR*r + CYG*g + 2*CYB*b ) >> (CSHIFT - 2); 1263 int u = ( 2*CUR*r + CUG*g + 2*CUB*b ) >> (CSHIFT - 2); 1264 int v = ( 2*CVR*r + CVG*g + 2*CVB*b ) >> (CSHIFT - 2); 1265 1266 dst[0] = SkToU8(y); 1267 dst[1] = SkToU8(u + 128); 1268 dst[2] = SkToU8(v + 128); 1269} 1270 1271/////////////////////////////////////////////////////////////////////////////// 1272 1273typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst, 1274 const void* SK_RESTRICT src, int width, 1275 const SkPMColor* SK_RESTRICT ctable); 1276 1277static void Write_32_YUV(uint8_t* SK_RESTRICT dst, 1278 const void* SK_RESTRICT srcRow, int width, 1279 const SkPMColor*) { 1280 const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow; 1281 while (--width >= 0) { 1282#ifdef WE_CONVERT_TO_YUV 1283 rgb2yuv_32(dst, *src++); 1284#else 1285 uint32_t c = *src++; 1286 dst[0] = SkGetPackedR32(c); 1287 dst[1] = SkGetPackedG32(c); 1288 dst[2] = SkGetPackedB32(c); 1289#endif 1290 dst += 3; 1291 } 1292} 1293 1294static void Write_4444_YUV(uint8_t* SK_RESTRICT dst, 1295 const void* SK_RESTRICT srcRow, int width, 1296 const SkPMColor*) { 1297 const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow; 1298 while (--width >= 0) { 1299#ifdef WE_CONVERT_TO_YUV 1300 rgb2yuv_4444(dst, *src++); 1301#else 1302 SkPMColor16 c = *src++; 1303 dst[0] = SkPacked4444ToR32(c); 1304 dst[1] = SkPacked4444ToG32(c); 1305 dst[2] = SkPacked4444ToB32(c); 1306#endif 1307 dst += 3; 1308 } 1309} 1310 1311static void Write_16_YUV(uint8_t* SK_RESTRICT dst, 1312 const void* SK_RESTRICT srcRow, int width, 1313 const SkPMColor*) { 1314 const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow; 1315 while (--width >= 0) { 1316#ifdef WE_CONVERT_TO_YUV 1317 rgb2yuv_16(dst, *src++); 1318#else 1319 uint16_t c = *src++; 1320 dst[0] = SkPacked16ToR32(c); 1321 dst[1] = SkPacked16ToG32(c); 1322 dst[2] = SkPacked16ToB32(c); 1323#endif 1324 dst += 3; 1325 } 1326} 1327 1328static void Write_Index_YUV(uint8_t* SK_RESTRICT dst, 1329 const void* SK_RESTRICT srcRow, int width, 1330 const SkPMColor* SK_RESTRICT ctable) { 1331 const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow; 1332 while (--width >= 0) { 1333#ifdef WE_CONVERT_TO_YUV 1334 rgb2yuv_32(dst, ctable[*src++]); 1335#else 1336 uint32_t c = ctable[*src++]; 1337 dst[0] = SkGetPackedR32(c); 1338 dst[1] = SkGetPackedG32(c); 1339 dst[2] = SkGetPackedB32(c); 1340#endif 1341 dst += 3; 1342 } 1343} 1344 1345static WriteScanline ChooseWriter(const SkBitmap& bm) { 1346 switch (bm.colorType()) { 1347 case kN32_SkColorType: 1348 return Write_32_YUV; 1349 case kRGB_565_SkColorType: 1350 return Write_16_YUV; 1351 case kARGB_4444_SkColorType: 1352 return Write_4444_YUV; 1353 case kIndex_8_SkColorType: 1354 return Write_Index_YUV; 1355 default: 1356 return NULL; 1357 } 1358} 1359 1360class SkJPEGImageEncoder : public SkImageEncoder { 1361protected: 1362 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) { 1363#ifdef TIME_ENCODE 1364 SkAutoTime atm("JPEG Encode"); 1365#endif 1366 1367 SkAutoLockPixels alp(bm); 1368 if (NULL == bm.getPixels()) { 1369 return false; 1370 } 1371 1372 jpeg_compress_struct cinfo; 1373 skjpeg_error_mgr sk_err; 1374 skjpeg_destination_mgr sk_wstream(stream); 1375 1376 // allocate these before set call setjmp 1377 SkAutoMalloc oneRow; 1378 1379 cinfo.err = jpeg_std_error(&sk_err); 1380 sk_err.error_exit = skjpeg_error_exit; 1381 if (setjmp(sk_err.fJmpBuf)) { 1382 return false; 1383 } 1384 1385 // Keep after setjmp or mark volatile. 1386 const WriteScanline writer = ChooseWriter(bm); 1387 if (NULL == writer) { 1388 return false; 1389 } 1390 1391 jpeg_create_compress(&cinfo); 1392 cinfo.dest = &sk_wstream; 1393 cinfo.image_width = bm.width(); 1394 cinfo.image_height = bm.height(); 1395 cinfo.input_components = 3; 1396#ifdef WE_CONVERT_TO_YUV 1397 cinfo.in_color_space = JCS_YCbCr; 1398#else 1399 cinfo.in_color_space = JCS_RGB; 1400#endif 1401 cinfo.input_gamma = 1; 1402 1403 jpeg_set_defaults(&cinfo); 1404 jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); 1405#ifdef DCT_IFAST_SUPPORTED 1406 cinfo.dct_method = JDCT_IFAST; 1407#endif 1408 1409 jpeg_start_compress(&cinfo, TRUE); 1410 1411 const int width = bm.width(); 1412 uint8_t* oneRowP = (uint8_t*)oneRow.reset(width * 3); 1413 1414 const SkPMColor* colors = bm.getColorTable() ? bm.getColorTable()->readColors() : NULL; 1415 const void* srcRow = bm.getPixels(); 1416 1417 while (cinfo.next_scanline < cinfo.image_height) { 1418 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ 1419 1420 writer(oneRowP, srcRow, width, colors); 1421 row_pointer[0] = oneRowP; 1422 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); 1423 srcRow = (const void*)((const char*)srcRow + bm.rowBytes()); 1424 } 1425 1426 jpeg_finish_compress(&cinfo); 1427 jpeg_destroy_compress(&cinfo); 1428 1429 return true; 1430 } 1431}; 1432 1433/////////////////////////////////////////////////////////////////////////////// 1434DEFINE_DECODER_CREATOR(JPEGImageDecoder); 1435DEFINE_ENCODER_CREATOR(JPEGImageEncoder); 1436/////////////////////////////////////////////////////////////////////////////// 1437 1438static bool is_jpeg(SkStreamRewindable* stream) { 1439 static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF }; 1440 static const size_t HEADER_SIZE = sizeof(gHeader); 1441 1442 char buffer[HEADER_SIZE]; 1443 size_t len = stream->read(buffer, HEADER_SIZE); 1444 1445 if (len != HEADER_SIZE) { 1446 return false; // can't read enough 1447 } 1448 if (memcmp(buffer, gHeader, HEADER_SIZE)) { 1449 return false; 1450 } 1451 return true; 1452} 1453 1454 1455static SkImageDecoder* sk_libjpeg_dfactory(SkStreamRewindable* stream) { 1456 if (is_jpeg(stream)) { 1457 return SkNEW(SkJPEGImageDecoder); 1458 } 1459 return NULL; 1460} 1461 1462static SkImageDecoder::Format get_format_jpeg(SkStreamRewindable* stream) { 1463 if (is_jpeg(stream)) { 1464 return SkImageDecoder::kJPEG_Format; 1465 } 1466 return SkImageDecoder::kUnknown_Format; 1467} 1468 1469static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { 1470 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; 1471} 1472 1473static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); 1474static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); 1475static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); 1476