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 "SkMSAN.h" 15 #include "SkScaledBitmapSampler.h" 16 #include "SkStream.h" 17 #include "SkTemplates.h" 18 #include "SkTime.h" 19 #include "SkUtils.h" 20 #include "SkRTConf.h" 21 #include "SkRect.h" 22 #include "SkCanvas.h" 23 24 25 #include <stdio.h> 26 extern "C" { 27 #include "jpeglib.h" 28 #include "jerror.h" 29 } 30 31 // These enable timing code that report milliseconds for an encoding/decoding 32 //#define TIME_ENCODE 33 //#define TIME_DECODE 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 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS true 39 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS true 40 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderWarnings, 41 "images.jpeg.suppressDecoderWarnings", 42 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS, 43 "Suppress most JPG warnings when calling decode functions."); 44 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderErrors, 45 "images.jpeg.suppressDecoderErrors", 46 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS, 47 "Suppress most JPG error messages when decode " 48 "function fails."); 49 50 ////////////////////////////////////////////////////////////////////////// 51 ////////////////////////////////////////////////////////////////////////// 52 53 static void do_nothing_emit_message(jpeg_common_struct*, int) { 54 /* do nothing */ 55 } 56 static void do_nothing_output_message(j_common_ptr) { 57 /* do nothing */ 58 } 59 60 static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* src_mgr) { 61 SkASSERT(cinfo != nullptr); 62 SkASSERT(src_mgr != nullptr); 63 jpeg_create_decompress(cinfo); 64 cinfo->src = src_mgr; 65 /* To suppress warnings with a SK_DEBUG binary, set the 66 * environment variable "skia_images_jpeg_suppressDecoderWarnings" 67 * to "true". Inside a program that links to skia: 68 * SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); */ 69 if (c_suppressJPEGImageDecoderWarnings) { 70 cinfo->err->emit_message = &do_nothing_emit_message; 71 } 72 /* To suppress error messages with a SK_DEBUG binary, set the 73 * environment variable "skia_images_jpeg_suppressDecoderErrors" 74 * to "true". Inside a program that links to skia: 75 * SK_CONF_SET("images.jpeg.suppressDecoderErrors", true); */ 76 if (c_suppressJPEGImageDecoderErrors) { 77 cinfo->err->output_message = &do_nothing_output_message; 78 } 79 } 80 81 class SkJPEGImageDecoder : public SkImageDecoder { 82 public: 83 84 Format getFormat() const override { 85 return kJPEG_Format; 86 } 87 88 protected: 89 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override; 90 bool onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3], 91 void* planes[3], size_t rowBytes[3], 92 SkYUVColorSpace* colorSpace) override; 93 94 private: 95 96 /** 97 * Determine the appropriate bitmap colortype and out_color_space based on 98 * both the preference of the caller and the jpeg_color_space on the 99 * jpeg_decompress_struct passed in. 100 * Must be called after jpeg_read_header. 101 */ 102 SkColorType getBitmapColorType(jpeg_decompress_struct*); 103 104 typedef SkImageDecoder INHERITED; 105 }; 106 107 ////////////////////////////////////////////////////////////////////////// 108 109 /* Automatically clean up after throwing an exception */ 110 class JPEGAutoClean { 111 public: 112 JPEGAutoClean(): cinfo_ptr(nullptr) {} 113 ~JPEGAutoClean() { 114 if (cinfo_ptr) { 115 jpeg_destroy_decompress(cinfo_ptr); 116 } 117 } 118 void set(jpeg_decompress_struct* info) { 119 cinfo_ptr = info; 120 } 121 private: 122 jpeg_decompress_struct* cinfo_ptr; 123 }; 124 125 /////////////////////////////////////////////////////////////////////////////// 126 127 /* If we need to better match the request, we might examine the image and 128 output dimensions, and determine if the downsampling jpeg provided is 129 not sufficient. If so, we can recompute a modified sampleSize value to 130 make up the difference. 131 132 To skip this additional scaling, just set sampleSize = 1; below. 133 */ 134 static int recompute_sampleSize(int sampleSize, 135 const jpeg_decompress_struct& cinfo) { 136 return sampleSize * cinfo.output_width / cinfo.image_width; 137 } 138 139 static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) { 140 /* These are initialized to 0, so if they have non-zero values, we assume 141 they are "valid" (i.e. have been computed by libjpeg) 142 */ 143 return 0 != cinfo.output_width && 0 != cinfo.output_height; 144 } 145 146 static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count) { 147 for (int i = 0; i < count; i++) { 148 JSAMPLE* rowptr = (JSAMPLE*)buffer; 149 int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1); 150 if (1 != row_count) { 151 return false; 152 } 153 } 154 return true; 155 } 156 157 /////////////////////////////////////////////////////////////////////////////// 158 159 // This guy exists just to aid in debugging, as it allows debuggers to just 160 // set a break-point in one place to see all error exists. 161 static void print_jpeg_decoder_errors(const jpeg_decompress_struct& cinfo, 162 int width, int height, const char caller[]) { 163 if (!(c_suppressJPEGImageDecoderErrors)) { 164 char buffer[JMSG_LENGTH_MAX]; 165 cinfo.err->format_message((const j_common_ptr)&cinfo, buffer); 166 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n", 167 cinfo.err->msg_code, buffer, caller, width, height); 168 } 169 } 170 171 static bool return_false(const jpeg_decompress_struct& cinfo, 172 const char caller[]) { 173 print_jpeg_decoder_errors(cinfo, 0, 0, caller); 174 return false; 175 } 176 177 static SkImageDecoder::Result return_failure(const jpeg_decompress_struct& cinfo, 178 const SkBitmap& bm, const char caller[]) { 179 print_jpeg_decoder_errors(cinfo, bm.width(), bm.height(), caller); 180 return SkImageDecoder::kFailure; 181 } 182 183 /////////////////////////////////////////////////////////////////////////////// 184 185 // Convert a scanline of CMYK samples to RGBX in place. Note that this 186 // method moves the "scanline" pointer in its processing 187 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) { 188 // At this point we've received CMYK pixels from libjpeg. We 189 // perform a crude conversion to RGB (based on the formulae 190 // from easyrgb.com): 191 // CMYK -> CMY 192 // C = ( C * (1 - K) + K ) // for each CMY component 193 // CMY -> RGB 194 // R = ( 1 - C ) * 255 // for each RGB component 195 // Unfortunately we are seeing inverted CMYK so all the original terms 196 // are 1-. This yields: 197 // CMYK -> CMY 198 // C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K 199 // The conversion from CMY->RGB remains the same 200 for (unsigned int x = 0; x < width; ++x, scanline += 4) { 201 scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]); 202 scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]); 203 scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]); 204 scanline[3] = 255; 205 } 206 } 207 208 /** 209 * Common code for setting the error manager. 210 */ 211 static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* errorManager) { 212 SkASSERT(cinfo != nullptr); 213 SkASSERT(errorManager != nullptr); 214 cinfo->err = jpeg_std_error(errorManager); 215 errorManager->error_exit = skjpeg_error_exit; 216 } 217 218 /** 219 * Common code for setting the dct method. 220 */ 221 static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct* cinfo) { 222 SkASSERT(cinfo != nullptr); 223 cinfo->dct_method = JDCT_ISLOW; 224 } 225 226 SkColorType SkJPEGImageDecoder::getBitmapColorType(jpeg_decompress_struct* cinfo) { 227 SkASSERT(cinfo != nullptr); 228 229 SrcDepth srcDepth = k32Bit_SrcDepth; 230 if (JCS_GRAYSCALE == cinfo->jpeg_color_space) { 231 srcDepth = k8BitGray_SrcDepth; 232 } 233 234 SkColorType colorType = this->getPrefColorType(srcDepth, /*hasAlpha*/ false); 235 switch (colorType) { 236 case kAlpha_8_SkColorType: 237 // Only respect A8 colortype if the original is grayscale, 238 // in which case we will treat the grayscale as alpha 239 // values. 240 if (cinfo->jpeg_color_space != JCS_GRAYSCALE) { 241 colorType = kN32_SkColorType; 242 } 243 break; 244 case kN32_SkColorType: 245 // Fall through. 246 case kARGB_4444_SkColorType: 247 // Fall through. 248 case kRGB_565_SkColorType: 249 // These are acceptable destination colortypes. 250 break; 251 default: 252 // Force all other colortypes to 8888. 253 colorType = kN32_SkColorType; 254 break; 255 } 256 257 switch (cinfo->jpeg_color_space) { 258 case JCS_CMYK: 259 // Fall through. 260 case JCS_YCCK: 261 // libjpeg cannot convert from CMYK or YCCK to RGB - here we set up 262 // so libjpeg will give us CMYK samples back and we will later 263 // manually convert them to RGB 264 cinfo->out_color_space = JCS_CMYK; 265 break; 266 case JCS_GRAYSCALE: 267 if (kAlpha_8_SkColorType == colorType) { 268 cinfo->out_color_space = JCS_GRAYSCALE; 269 break; 270 } 271 // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB 272 // colortype. Fall through to set to the default. 273 default: 274 cinfo->out_color_space = JCS_RGB; 275 break; 276 } 277 return colorType; 278 } 279 280 /** 281 * Based on the colortype and dither mode, adjust out_color_space and 282 * dither_mode of cinfo. Only does work in ANDROID_RGB 283 */ 284 static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo, 285 SkColorType colorType, 286 const SkImageDecoder& decoder) { 287 SkASSERT(cinfo != nullptr); 288 #ifdef ANDROID_RGB 289 cinfo->dither_mode = JDITHER_NONE; 290 if (JCS_CMYK == cinfo->out_color_space) { 291 return; 292 } 293 switch (colorType) { 294 case kN32_SkColorType: 295 cinfo->out_color_space = JCS_RGBA_8888; 296 break; 297 case kRGB_565_SkColorType: 298 cinfo->out_color_space = JCS_RGB_565; 299 if (decoder.getDitherImage()) { 300 cinfo->dither_mode = JDITHER_ORDERED; 301 } 302 break; 303 default: 304 break; 305 } 306 #endif 307 } 308 309 /** 310 Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y. 311 Used when decoding fails partway through reading scanlines to fill 312 remaining lines. */ 313 static void fill_below_level(int y, SkBitmap* bitmap) { 314 SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height()); 315 SkCanvas canvas(*bitmap); 316 canvas.clipRect(SkRect::Make(rect)); 317 canvas.drawColor(SK_ColorWHITE); 318 } 319 320 /** 321 * Get the config and bytes per pixel of the source data. Return 322 * whether the data is supported. 323 */ 324 static bool get_src_config(const jpeg_decompress_struct& cinfo, 325 SkScaledBitmapSampler::SrcConfig* sc, 326 int* srcBytesPerPixel) { 327 SkASSERT(sc != nullptr && srcBytesPerPixel != nullptr); 328 if (JCS_CMYK == cinfo.out_color_space) { 329 // In this case we will manually convert the CMYK values to RGB 330 *sc = SkScaledBitmapSampler::kRGBX; 331 // The CMYK work-around relies on 4 components per pixel here 332 *srcBytesPerPixel = 4; 333 } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) { 334 *sc = SkScaledBitmapSampler::kRGB; 335 *srcBytesPerPixel = 3; 336 #ifdef ANDROID_RGB 337 } else if (JCS_RGBA_8888 == cinfo.out_color_space) { 338 *sc = SkScaledBitmapSampler::kRGBX; 339 *srcBytesPerPixel = 4; 340 } else if (JCS_RGB_565 == cinfo.out_color_space) { 341 *sc = SkScaledBitmapSampler::kRGB_565; 342 *srcBytesPerPixel = 2; 343 #endif 344 } else if (1 == cinfo.out_color_components && 345 JCS_GRAYSCALE == cinfo.out_color_space) { 346 *sc = SkScaledBitmapSampler::kGray; 347 *srcBytesPerPixel = 1; 348 } else { 349 return false; 350 } 351 return true; 352 } 353 354 SkImageDecoder::Result SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { 355 #ifdef TIME_DECODE 356 SkAutoTime atm("JPEG Decode"); 357 #endif 358 359 JPEGAutoClean autoClean; 360 361 jpeg_decompress_struct cinfo; 362 skjpeg_source_mgr srcManager(stream, this); 363 364 skjpeg_error_mgr errorManager; 365 set_error_mgr(&cinfo, &errorManager); 366 367 // All objects need to be instantiated before this setjmp call so that 368 // they will be cleaned up properly if an error occurs. 369 if (setjmp(errorManager.fJmpBuf)) { 370 return return_failure(cinfo, *bm, "setjmp"); 371 } 372 373 initialize_info(&cinfo, &srcManager); 374 autoClean.set(&cinfo); 375 376 int status = jpeg_read_header(&cinfo, true); 377 if (status != JPEG_HEADER_OK) { 378 return return_failure(cinfo, *bm, "read_header"); 379 } 380 381 /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it 382 can) much faster that we, just use their num/denom api to approximate 383 the size. 384 */ 385 int sampleSize = this->getSampleSize(); 386 387 set_dct_method(*this, &cinfo); 388 389 SkASSERT(1 == cinfo.scale_num); 390 cinfo.scale_denom = sampleSize; 391 392 const SkColorType colorType = this->getBitmapColorType(&cinfo); 393 const SkAlphaType alphaType = kAlpha_8_SkColorType == colorType ? 394 kPremul_SkAlphaType : kOpaque_SkAlphaType; 395 396 adjust_out_color_space_and_dither(&cinfo, colorType, *this); 397 398 if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) { 399 // Assume an A8 bitmap is not opaque to avoid the check of each 400 // individual pixel. It is very unlikely to be opaque, since 401 // an opaque A8 bitmap would not be very interesting. 402 // Otherwise, a jpeg image is opaque. 403 bool success = bm->setInfo(SkImageInfo::Make(cinfo.image_width, cinfo.image_height, 404 colorType, alphaType)); 405 return success ? kSuccess : kFailure; 406 } 407 408 /* image_width and image_height are the original dimensions, available 409 after jpeg_read_header(). To see the scaled dimensions, we have to call 410 jpeg_start_decompress(), and then read output_width and output_height. 411 */ 412 if (!jpeg_start_decompress(&cinfo)) { 413 /* If we failed here, we may still have enough information to return 414 to the caller if they just wanted (subsampled bounds). If sampleSize 415 was 1, then we would have already returned. Thus we just check if 416 we're in kDecodeBounds_Mode, and that we have valid output sizes. 417 418 One reason to fail here is that we have insufficient stream data 419 to complete the setup. However, output dimensions seem to get 420 computed very early, which is why this special check can pay off. 421 */ 422 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimensions(cinfo)) { 423 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height, 424 recompute_sampleSize(sampleSize, cinfo)); 425 // Assume an A8 bitmap is not opaque to avoid the check of each 426 // individual pixel. It is very unlikely to be opaque, since 427 // an opaque A8 bitmap would not be very interesting. 428 // Otherwise, a jpeg image is opaque. 429 bool success = bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaledHeight(), 430 colorType, alphaType)); 431 return success ? kSuccess : kFailure; 432 } else { 433 return return_failure(cinfo, *bm, "start_decompress"); 434 } 435 } 436 sampleSize = recompute_sampleSize(sampleSize, cinfo); 437 438 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize); 439 // Assume an A8 bitmap is not opaque to avoid the check of each 440 // individual pixel. It is very unlikely to be opaque, since 441 // an opaque A8 bitmap would not be very interesting. 442 // Otherwise, a jpeg image is opaque. 443 bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), 444 colorType, alphaType)); 445 if (SkImageDecoder::kDecodeBounds_Mode == mode) { 446 return kSuccess; 447 } 448 if (!this->allocPixelRef(bm, nullptr)) { 449 return return_failure(cinfo, *bm, "allocPixelRef"); 450 } 451 452 SkAutoLockPixels alp(*bm); 453 454 #ifdef ANDROID_RGB 455 /* short-circuit the SkScaledBitmapSampler when possible, as this gives 456 a significant performance boost. 457 */ 458 if (sampleSize == 1 && 459 ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_8888) || 460 (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_565))) 461 { 462 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); 463 INT32 const bpr = bm->rowBytes(); 464 465 while (cinfo.output_scanline < cinfo.output_height) { 466 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 467 if (0 == row_count) { 468 // if row_count == 0, then we didn't get a scanline, 469 // so return early. We will return a partial image. 470 fill_below_level(cinfo.output_scanline, bm); 471 cinfo.output_scanline = cinfo.output_height; 472 jpeg_finish_decompress(&cinfo); 473 return kPartialSuccess; 474 } 475 if (this->shouldCancelDecode()) { 476 return return_failure(cinfo, *bm, "shouldCancelDecode"); 477 } 478 rowptr += bpr; 479 } 480 jpeg_finish_decompress(&cinfo); 481 return kSuccess; 482 } 483 #endif 484 485 // check for supported formats 486 SkScaledBitmapSampler::SrcConfig sc; 487 int srcBytesPerPixel; 488 489 if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) { 490 return return_failure(cinfo, *bm, "jpeg colorspace"); 491 } 492 493 if (!sampler.begin(bm, sc, *this)) { 494 return return_failure(cinfo, *bm, "sampler.begin"); 495 } 496 497 SkAutoTMalloc<uint8_t> srcStorage(cinfo.output_width * srcBytesPerPixel); 498 uint8_t* srcRow = srcStorage.get(); 499 500 // Possibly skip initial rows [sampler.srcY0] 501 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) { 502 return return_failure(cinfo, *bm, "skip rows"); 503 } 504 505 // now loop through scanlines until y == bm->height() - 1 506 for (int y = 0;; y++) { 507 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 508 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 509 sk_msan_mark_initialized(srcRow, srcRow + cinfo.output_width * srcBytesPerPixel, 510 "skbug.com/4550"); 511 if (0 == row_count) { 512 // if row_count == 0, then we didn't get a scanline, 513 // so return early. We will return a partial image. 514 fill_below_level(y, bm); 515 cinfo.output_scanline = cinfo.output_height; 516 jpeg_finish_decompress(&cinfo); 517 return kPartialSuccess; 518 } 519 if (this->shouldCancelDecode()) { 520 return return_failure(cinfo, *bm, "shouldCancelDecode"); 521 } 522 523 if (JCS_CMYK == cinfo.out_color_space) { 524 convert_CMYK_to_RGB(srcRow, cinfo.output_width); 525 } 526 527 528 sampler.next(srcRow); 529 if (bm->height() - 1 == y) { 530 // we're done 531 break; 532 } 533 534 if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) { 535 return return_failure(cinfo, *bm, "skip rows"); 536 } 537 } 538 539 // we formally skip the rest, so we don't get a complaint from libjpeg 540 if (!skip_src_rows(&cinfo, srcRow, 541 cinfo.output_height - cinfo.output_scanline)) { 542 return return_failure(cinfo, *bm, "skip rows"); 543 } 544 jpeg_finish_decompress(&cinfo); 545 546 return kSuccess; 547 } 548 549 /////////////////////////////////////////////////////////////////////////////// 550 551 enum SizeType { 552 kSizeForMemoryAllocation_SizeType, 553 kActualSize_SizeType 554 }; 555 556 static SkISize compute_yuv_size(const jpeg_decompress_struct& info, int component, 557 SizeType sizeType) { 558 if (sizeType == kSizeForMemoryAllocation_SizeType) { 559 return SkISize::Make(info.cur_comp_info[component]->width_in_blocks * DCTSIZE, 560 info.cur_comp_info[component]->height_in_blocks * DCTSIZE); 561 } 562 return SkISize::Make(info.cur_comp_info[component]->downsampled_width, 563 info.cur_comp_info[component]->downsampled_height); 564 } 565 566 static bool appears_to_be_yuv(const jpeg_decompress_struct& info) { 567 return (info.jpeg_color_space == JCS_YCbCr) 568 && (DCTSIZE == 8) 569 && (info.num_components == 3) 570 && (info.comps_in_scan >= info.num_components) 571 && (info.scale_denom <= 8) 572 && (info.cur_comp_info[0]) 573 && (info.cur_comp_info[1]) 574 && (info.cur_comp_info[2]) 575 && (info.cur_comp_info[1]->h_samp_factor == 1) 576 && (info.cur_comp_info[1]->v_samp_factor == 1) 577 && (info.cur_comp_info[2]->h_samp_factor == 1) 578 && (info.cur_comp_info[2]->v_samp_factor == 1); 579 } 580 581 static void update_components_sizes(const jpeg_decompress_struct& cinfo, SkISize componentSizes[3], 582 SizeType sizeType) { 583 SkASSERT(appears_to_be_yuv(cinfo)); 584 for (int i = 0; i < 3; ++i) { 585 componentSizes[i] = compute_yuv_size(cinfo, i, sizeType); 586 } 587 } 588 589 static bool output_raw_data(jpeg_decompress_struct& cinfo, void* planes[3], size_t rowBytes[3]) { 590 SkASSERT(appears_to_be_yuv(cinfo)); 591 // U size and V size have to be the same if we're calling output_raw_data() 592 SkISize uvSize = compute_yuv_size(cinfo, 1, kSizeForMemoryAllocation_SizeType); 593 SkASSERT(uvSize == compute_yuv_size(cinfo, 2, kSizeForMemoryAllocation_SizeType)); 594 595 JSAMPARRAY bufferraw[3]; 596 JSAMPROW bufferraw2[32]; 597 bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16) 598 bufferraw[1] = &bufferraw2[16]; // U channel rows (8) 599 bufferraw[2] = &bufferraw2[24]; // V channel rows (8) 600 int yWidth = cinfo.output_width; 601 int yHeight = cinfo.output_height; 602 int yMaxH = yHeight - 1; 603 int v = cinfo.cur_comp_info[0]->v_samp_factor; 604 int uvMaxH = uvSize.height() - 1; 605 JSAMPROW outputY = static_cast<JSAMPROW>(planes[0]); 606 JSAMPROW outputU = static_cast<JSAMPROW>(planes[1]); 607 JSAMPROW outputV = static_cast<JSAMPROW>(planes[2]); 608 size_t rowBytesY = rowBytes[0]; 609 size_t rowBytesU = rowBytes[1]; 610 size_t rowBytesV = rowBytes[2]; 611 612 int yScanlinesToRead = DCTSIZE * v; 613 SkAutoMalloc lastRowStorage(rowBytesY * 4); 614 JSAMPROW yLastRow = (JSAMPROW)lastRowStorage.get(); 615 JSAMPROW uLastRow = yLastRow + rowBytesY; 616 JSAMPROW vLastRow = uLastRow + rowBytesY; 617 JSAMPROW dummyRow = vLastRow + rowBytesY; 618 619 while (cinfo.output_scanline < cinfo.output_height) { 620 // Request 8 or 16 scanlines: returns 0 or more scanlines. 621 bool hasYLastRow(false), hasUVLastRow(false); 622 // Assign 8 or 16 rows of memory to read the Y channel. 623 for (int i = 0; i < yScanlinesToRead; ++i) { 624 int scanline = (cinfo.output_scanline + i); 625 if (scanline < yMaxH) { 626 bufferraw2[i] = &outputY[scanline * rowBytesY]; 627 } else if (scanline == yMaxH) { 628 bufferraw2[i] = yLastRow; 629 hasYLastRow = true; 630 } else { 631 bufferraw2[i] = dummyRow; 632 } 633 } 634 int scaledScanline = cinfo.output_scanline / v; 635 // Assign 8 rows of memory to read the U and V channels. 636 for (int i = 0; i < 8; ++i) { 637 int scanline = (scaledScanline + i); 638 if (scanline < uvMaxH) { 639 bufferraw2[16 + i] = &outputU[scanline * rowBytesU]; 640 bufferraw2[24 + i] = &outputV[scanline * rowBytesV]; 641 } else if (scanline == uvMaxH) { 642 bufferraw2[16 + i] = uLastRow; 643 bufferraw2[24 + i] = vLastRow; 644 hasUVLastRow = true; 645 } else { 646 bufferraw2[16 + i] = dummyRow; 647 bufferraw2[24 + i] = dummyRow; 648 } 649 } 650 JDIMENSION scanlinesRead = jpeg_read_raw_data(&cinfo, bufferraw, yScanlinesToRead); 651 652 if (scanlinesRead == 0) { 653 return false; 654 } 655 656 if (hasYLastRow) { 657 memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth); 658 } 659 if (hasUVLastRow) { 660 memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width()); 661 memcpy(&outputV[uvMaxH * rowBytesV], vLastRow, uvSize.width()); 662 } 663 } 664 665 cinfo.output_scanline = SkMin32(cinfo.output_scanline, cinfo.output_height); 666 667 return true; 668 } 669 670 bool SkJPEGImageDecoder::onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3], 671 void* planes[3], size_t rowBytes[3], 672 SkYUVColorSpace* colorSpace) { 673 #ifdef TIME_DECODE 674 SkAutoTime atm("JPEG YUV8 Decode"); 675 #endif 676 if (this->getSampleSize() != 1) { 677 return false; // Resizing not supported 678 } 679 680 JPEGAutoClean autoClean; 681 682 jpeg_decompress_struct cinfo; 683 skjpeg_source_mgr srcManager(stream, this); 684 685 skjpeg_error_mgr errorManager; 686 set_error_mgr(&cinfo, &errorManager); 687 688 // All objects need to be instantiated before this setjmp call so that 689 // they will be cleaned up properly if an error occurs. 690 if (setjmp(errorManager.fJmpBuf)) { 691 return return_false(cinfo, "setjmp YUV8"); 692 } 693 694 initialize_info(&cinfo, &srcManager); 695 autoClean.set(&cinfo); 696 697 int status = jpeg_read_header(&cinfo, true); 698 if (status != JPEG_HEADER_OK) { 699 return return_false(cinfo, "read_header YUV8"); 700 } 701 702 if (!appears_to_be_yuv(cinfo)) { 703 // It's not an error to not be encoded in YUV, so no need to use return_false() 704 return false; 705 } 706 707 cinfo.out_color_space = JCS_YCbCr; 708 cinfo.raw_data_out = TRUE; 709 710 if (!planes || !planes[0] || !rowBytes || !rowBytes[0]) { // Compute size only 711 update_components_sizes(cinfo, componentSizes, kSizeForMemoryAllocation_SizeType); 712 return true; 713 } 714 715 set_dct_method(*this, &cinfo); 716 717 SkASSERT(1 == cinfo.scale_num); 718 cinfo.scale_denom = 1; 719 720 #ifdef ANDROID_RGB 721 cinfo.dither_mode = JDITHER_NONE; 722 #endif 723 724 /* image_width and image_height are the original dimensions, available 725 after jpeg_read_header(). To see the scaled dimensions, we have to call 726 jpeg_start_decompress(), and then read output_width and output_height. 727 */ 728 if (!jpeg_start_decompress(&cinfo)) { 729 return return_false(cinfo, "start_decompress YUV8"); 730 } 731 732 // Seems like jpeg_start_decompress is updating our opinion of whether cinfo represents YUV. 733 // Again, not really an error. 734 if (!appears_to_be_yuv(cinfo)) { 735 return false; 736 } 737 738 if (!output_raw_data(cinfo, planes, rowBytes)) { 739 return return_false(cinfo, "output_raw_data"); 740 } 741 742 update_components_sizes(cinfo, componentSizes, kActualSize_SizeType); 743 jpeg_finish_decompress(&cinfo); 744 745 if (nullptr != colorSpace) { 746 *colorSpace = kJPEG_SkYUVColorSpace; 747 } 748 749 return true; 750 } 751 752 /////////////////////////////////////////////////////////////////////////////// 753 754 typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst, 755 const void* SK_RESTRICT src, int width, 756 const SkPMColor* SK_RESTRICT ctable); 757 758 static void Write_32_RGB(uint8_t* SK_RESTRICT dst, 759 const void* SK_RESTRICT srcRow, int width, 760 const SkPMColor*) { 761 const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow; 762 while (--width >= 0) { 763 uint32_t c = *src++; 764 dst[0] = SkGetPackedR32(c); 765 dst[1] = SkGetPackedG32(c); 766 dst[2] = SkGetPackedB32(c); 767 dst += 3; 768 } 769 } 770 771 static void Write_4444_RGB(uint8_t* SK_RESTRICT dst, 772 const void* SK_RESTRICT srcRow, int width, 773 const SkPMColor*) { 774 const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow; 775 while (--width >= 0) { 776 SkPMColor16 c = *src++; 777 dst[0] = SkPacked4444ToR32(c); 778 dst[1] = SkPacked4444ToG32(c); 779 dst[2] = SkPacked4444ToB32(c); 780 dst += 3; 781 } 782 } 783 784 static void Write_16_RGB(uint8_t* SK_RESTRICT dst, 785 const void* SK_RESTRICT srcRow, int width, 786 const SkPMColor*) { 787 const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow; 788 while (--width >= 0) { 789 uint16_t c = *src++; 790 dst[0] = SkPacked16ToR32(c); 791 dst[1] = SkPacked16ToG32(c); 792 dst[2] = SkPacked16ToB32(c); 793 dst += 3; 794 } 795 } 796 797 static void Write_Index_RGB(uint8_t* SK_RESTRICT dst, 798 const void* SK_RESTRICT srcRow, int width, 799 const SkPMColor* SK_RESTRICT ctable) { 800 const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow; 801 while (--width >= 0) { 802 uint32_t c = ctable[*src++]; 803 dst[0] = SkGetPackedR32(c); 804 dst[1] = SkGetPackedG32(c); 805 dst[2] = SkGetPackedB32(c); 806 dst += 3; 807 } 808 } 809 810 static WriteScanline ChooseWriter(const SkBitmap& bm) { 811 switch (bm.colorType()) { 812 case kN32_SkColorType: 813 return Write_32_RGB; 814 case kRGB_565_SkColorType: 815 return Write_16_RGB; 816 case kARGB_4444_SkColorType: 817 return Write_4444_RGB; 818 case kIndex_8_SkColorType: 819 return Write_Index_RGB; 820 default: 821 return nullptr; 822 } 823 } 824 825 class SkJPEGImageEncoder : public SkImageEncoder { 826 protected: 827 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) { 828 #ifdef TIME_ENCODE 829 SkAutoTime atm("JPEG Encode"); 830 #endif 831 832 SkAutoLockPixels alp(bm); 833 if (nullptr == bm.getPixels()) { 834 return false; 835 } 836 837 jpeg_compress_struct cinfo; 838 skjpeg_error_mgr sk_err; 839 skjpeg_destination_mgr sk_wstream(stream); 840 841 // allocate these before set call setjmp 842 SkAutoTMalloc<uint8_t> oneRow; 843 844 cinfo.err = jpeg_std_error(&sk_err); 845 sk_err.error_exit = skjpeg_error_exit; 846 if (setjmp(sk_err.fJmpBuf)) { 847 return false; 848 } 849 850 // Keep after setjmp or mark volatile. 851 const WriteScanline writer = ChooseWriter(bm); 852 if (nullptr == writer) { 853 return false; 854 } 855 856 jpeg_create_compress(&cinfo); 857 cinfo.dest = &sk_wstream; 858 cinfo.image_width = bm.width(); 859 cinfo.image_height = bm.height(); 860 cinfo.input_components = 3; 861 // FIXME: Can we take advantage of other in_color_spaces in libjpeg-turbo? 862 cinfo.in_color_space = JCS_RGB; 863 864 // The gamma value is ignored by libjpeg-turbo. 865 cinfo.input_gamma = 1; 866 867 jpeg_set_defaults(&cinfo); 868 869 // Tells libjpeg-turbo to compute optimal Huffman coding tables 870 // for the image. This improves compression at the cost of 871 // slower encode performance. 872 cinfo.optimize_coding = TRUE; 873 jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); 874 875 jpeg_start_compress(&cinfo, TRUE); 876 877 const int width = bm.width(); 878 uint8_t* oneRowP = oneRow.reset(width * 3); 879 880 const SkPMColor* colors = bm.getColorTable() ? bm.getColorTable()->readColors() : nullptr; 881 const void* srcRow = bm.getPixels(); 882 883 while (cinfo.next_scanline < cinfo.image_height) { 884 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ 885 886 writer(oneRowP, srcRow, width, colors); 887 row_pointer[0] = oneRowP; 888 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); 889 srcRow = (const void*)((const char*)srcRow + bm.rowBytes()); 890 } 891 892 jpeg_finish_compress(&cinfo); 893 jpeg_destroy_compress(&cinfo); 894 895 return true; 896 } 897 }; 898 899 /////////////////////////////////////////////////////////////////////////////// 900 DEFINE_DECODER_CREATOR(JPEGImageDecoder); 901 DEFINE_ENCODER_CREATOR(JPEGImageEncoder); 902 /////////////////////////////////////////////////////////////////////////////// 903 904 static bool is_jpeg(SkStreamRewindable* stream) { 905 static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF }; 906 static const size_t HEADER_SIZE = sizeof(gHeader); 907 908 char buffer[HEADER_SIZE]; 909 size_t len = stream->read(buffer, HEADER_SIZE); 910 911 if (len != HEADER_SIZE) { 912 return false; // can't read enough 913 } 914 if (memcmp(buffer, gHeader, HEADER_SIZE)) { 915 return false; 916 } 917 return true; 918 } 919 920 921 static SkImageDecoder* sk_libjpeg_dfactory(SkStreamRewindable* stream) { 922 if (is_jpeg(stream)) { 923 return new SkJPEGImageDecoder; 924 } 925 return nullptr; 926 } 927 928 static SkImageDecoder::Format get_format_jpeg(SkStreamRewindable* stream) { 929 if (is_jpeg(stream)) { 930 return SkImageDecoder::kJPEG_Format; 931 } 932 return SkImageDecoder::kUnknown_Format; 933 } 934 935 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { 936 return (SkImageEncoder::kJPEG_Type == t) ? new SkJPEGImageEncoder : nullptr; 937 } 938 939 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); 940 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); 941 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); 942