| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2007 The Android Open Source Project | 2 * Copyright 2007 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 | 8 |
| 9 #include "SkImageDecoder.h" | 9 #include "SkImageDecoder.h" |
| 10 #include "SkImageEncoder.h" | 10 #include "SkImageEncoder.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 ////////////////////////////////////////////////////////////////////////// | 58 ////////////////////////////////////////////////////////////////////////// |
| 59 | 59 |
| 60 static void do_nothing_emit_message(jpeg_common_struct*, int) { | 60 static void do_nothing_emit_message(jpeg_common_struct*, int) { |
| 61 /* do nothing */ | 61 /* do nothing */ |
| 62 } | 62 } |
| 63 static void do_nothing_output_message(j_common_ptr) { | 63 static void do_nothing_output_message(j_common_ptr) { |
| 64 /* do nothing */ | 64 /* do nothing */ |
| 65 } | 65 } |
| 66 | 66 |
| 67 static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* sr
c_mgr) { | 67 static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* sr
c_mgr) { |
| 68 SkASSERT(cinfo != NULL); | 68 SkASSERT(cinfo != nullptr); |
| 69 SkASSERT(src_mgr != NULL); | 69 SkASSERT(src_mgr != nullptr); |
| 70 jpeg_create_decompress(cinfo); | 70 jpeg_create_decompress(cinfo); |
| 71 cinfo->src = src_mgr; | 71 cinfo->src = src_mgr; |
| 72 /* To suppress warnings with a SK_DEBUG binary, set the | 72 /* To suppress warnings with a SK_DEBUG binary, set the |
| 73 * environment variable "skia_images_jpeg_suppressDecoderWarnings" | 73 * environment variable "skia_images_jpeg_suppressDecoderWarnings" |
| 74 * to "true". Inside a program that links to skia: | 74 * to "true". Inside a program that links to skia: |
| 75 * SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); */ | 75 * SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); */ |
| 76 if (c_suppressJPEGImageDecoderWarnings) { | 76 if (c_suppressJPEGImageDecoderWarnings) { |
| 77 cinfo->err->emit_message = &do_nothing_emit_message; | 77 cinfo->err->emit_message = &do_nothing_emit_message; |
| 78 } | 78 } |
| 79 /* To suppress error messages with a SK_DEBUG binary, set the | 79 /* To suppress error messages with a SK_DEBUG binary, set the |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 bool fHuffmanCreated; | 198 bool fHuffmanCreated; |
| 199 bool fDecompressStarted; | 199 bool fDecompressStarted; |
| 200 SkDEBUGCODE(bool fReadHeaderSucceeded;) | 200 SkDEBUGCODE(bool fReadHeaderSucceeded;) |
| 201 }; | 201 }; |
| 202 #endif | 202 #endif |
| 203 | 203 |
| 204 class SkJPEGImageDecoder : public SkImageDecoder { | 204 class SkJPEGImageDecoder : public SkImageDecoder { |
| 205 public: | 205 public: |
| 206 #ifdef SK_BUILD_FOR_ANDROID | 206 #ifdef SK_BUILD_FOR_ANDROID |
| 207 SkJPEGImageDecoder() { | 207 SkJPEGImageDecoder() { |
| 208 fImageIndex = NULL; | 208 fImageIndex = nullptr; |
| 209 fImageWidth = 0; | 209 fImageWidth = 0; |
| 210 fImageHeight = 0; | 210 fImageHeight = 0; |
| 211 } | 211 } |
| 212 | 212 |
| 213 virtual ~SkJPEGImageDecoder() { delete fImageIndex; } | 213 virtual ~SkJPEGImageDecoder() { delete fImageIndex; } |
| 214 #endif | 214 #endif |
| 215 | 215 |
| 216 Format getFormat() const override { | 216 Format getFormat() const override { |
| 217 return kJPEG_Format; | 217 return kJPEG_Format; |
| 218 } | 218 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 243 SkColorType getBitmapColorType(jpeg_decompress_struct*); | 243 SkColorType getBitmapColorType(jpeg_decompress_struct*); |
| 244 | 244 |
| 245 typedef SkImageDecoder INHERITED; | 245 typedef SkImageDecoder INHERITED; |
| 246 }; | 246 }; |
| 247 | 247 |
| 248 ////////////////////////////////////////////////////////////////////////// | 248 ////////////////////////////////////////////////////////////////////////// |
| 249 | 249 |
| 250 /* Automatically clean up after throwing an exception */ | 250 /* Automatically clean up after throwing an exception */ |
| 251 class JPEGAutoClean { | 251 class JPEGAutoClean { |
| 252 public: | 252 public: |
| 253 JPEGAutoClean(): cinfo_ptr(NULL) {} | 253 JPEGAutoClean(): cinfo_ptr(nullptr) {} |
| 254 ~JPEGAutoClean() { | 254 ~JPEGAutoClean() { |
| 255 if (cinfo_ptr) { | 255 if (cinfo_ptr) { |
| 256 jpeg_destroy_decompress(cinfo_ptr); | 256 jpeg_destroy_decompress(cinfo_ptr); |
| 257 } | 257 } |
| 258 } | 258 } |
| 259 void set(jpeg_decompress_struct* info) { | 259 void set(jpeg_decompress_struct* info) { |
| 260 cinfo_ptr = info; | 260 cinfo_ptr = info; |
| 261 } | 261 } |
| 262 private: | 262 private: |
| 263 jpeg_decompress_struct* cinfo_ptr; | 263 jpeg_decompress_struct* cinfo_ptr; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]); | 365 scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]); |
| 366 scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]); | 366 scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]); |
| 367 scanline[3] = 255; | 367 scanline[3] = 255; |
| 368 } | 368 } |
| 369 } | 369 } |
| 370 | 370 |
| 371 /** | 371 /** |
| 372 * Common code for setting the error manager. | 372 * Common code for setting the error manager. |
| 373 */ | 373 */ |
| 374 static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* error
Manager) { | 374 static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* error
Manager) { |
| 375 SkASSERT(cinfo != NULL); | 375 SkASSERT(cinfo != nullptr); |
| 376 SkASSERT(errorManager != NULL); | 376 SkASSERT(errorManager != nullptr); |
| 377 cinfo->err = jpeg_std_error(errorManager); | 377 cinfo->err = jpeg_std_error(errorManager); |
| 378 errorManager->error_exit = skjpeg_error_exit; | 378 errorManager->error_exit = skjpeg_error_exit; |
| 379 } | 379 } |
| 380 | 380 |
| 381 /** | 381 /** |
| 382 * Common code for turning off upsampling and smoothing. Turning these | 382 * Common code for turning off upsampling and smoothing. Turning these |
| 383 * off helps performance without showing noticable differences in the | 383 * off helps performance without showing noticable differences in the |
| 384 * resulting bitmap. | 384 * resulting bitmap. |
| 385 */ | 385 */ |
| 386 static void turn_off_visual_optimizations(jpeg_decompress_struct* cinfo) { | 386 static void turn_off_visual_optimizations(jpeg_decompress_struct* cinfo) { |
| 387 SkASSERT(cinfo != NULL); | 387 SkASSERT(cinfo != nullptr); |
| 388 /* this gives about 30% performance improvement. In theory it may | 388 /* this gives about 30% performance improvement. In theory it may |
| 389 reduce the visual quality, in practice I'm not seeing a difference | 389 reduce the visual quality, in practice I'm not seeing a difference |
| 390 */ | 390 */ |
| 391 cinfo->do_fancy_upsampling = 0; | 391 cinfo->do_fancy_upsampling = 0; |
| 392 | 392 |
| 393 /* this gives another few percents */ | 393 /* this gives another few percents */ |
| 394 cinfo->do_block_smoothing = 0; | 394 cinfo->do_block_smoothing = 0; |
| 395 } | 395 } |
| 396 | 396 |
| 397 /** | 397 /** |
| 398 * Common code for setting the dct method. | 398 * Common code for setting the dct method. |
| 399 */ | 399 */ |
| 400 static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct
* cinfo) { | 400 static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct
* cinfo) { |
| 401 SkASSERT(cinfo != NULL); | 401 SkASSERT(cinfo != nullptr); |
| 402 #ifdef DCT_IFAST_SUPPORTED | 402 #ifdef DCT_IFAST_SUPPORTED |
| 403 if (decoder.getPreferQualityOverSpeed()) { | 403 if (decoder.getPreferQualityOverSpeed()) { |
| 404 cinfo->dct_method = JDCT_ISLOW; | 404 cinfo->dct_method = JDCT_ISLOW; |
| 405 } else { | 405 } else { |
| 406 cinfo->dct_method = JDCT_IFAST; | 406 cinfo->dct_method = JDCT_IFAST; |
| 407 } | 407 } |
| 408 #else | 408 #else |
| 409 cinfo->dct_method = JDCT_ISLOW; | 409 cinfo->dct_method = JDCT_ISLOW; |
| 410 #endif | 410 #endif |
| 411 } | 411 } |
| 412 | 412 |
| 413 SkColorType SkJPEGImageDecoder::getBitmapColorType(jpeg_decompress_struct* cinfo
) { | 413 SkColorType SkJPEGImageDecoder::getBitmapColorType(jpeg_decompress_struct* cinfo
) { |
| 414 SkASSERT(cinfo != NULL); | 414 SkASSERT(cinfo != nullptr); |
| 415 | 415 |
| 416 SrcDepth srcDepth = k32Bit_SrcDepth; | 416 SrcDepth srcDepth = k32Bit_SrcDepth; |
| 417 if (JCS_GRAYSCALE == cinfo->jpeg_color_space) { | 417 if (JCS_GRAYSCALE == cinfo->jpeg_color_space) { |
| 418 srcDepth = k8BitGray_SrcDepth; | 418 srcDepth = k8BitGray_SrcDepth; |
| 419 } | 419 } |
| 420 | 420 |
| 421 SkColorType colorType = this->getPrefColorType(srcDepth, /*hasAlpha*/ false)
; | 421 SkColorType colorType = this->getPrefColorType(srcDepth, /*hasAlpha*/ false)
; |
| 422 switch (colorType) { | 422 switch (colorType) { |
| 423 case kAlpha_8_SkColorType: | 423 case kAlpha_8_SkColorType: |
| 424 // Only respect A8 colortype if the original is grayscale, | 424 // Only respect A8 colortype if the original is grayscale, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 return colorType; | 464 return colorType; |
| 465 } | 465 } |
| 466 | 466 |
| 467 /** | 467 /** |
| 468 * Based on the colortype and dither mode, adjust out_color_space and | 468 * Based on the colortype and dither mode, adjust out_color_space and |
| 469 * dither_mode of cinfo. Only does work in ANDROID_RGB | 469 * dither_mode of cinfo. Only does work in ANDROID_RGB |
| 470 */ | 470 */ |
| 471 static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo, | 471 static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo, |
| 472 SkColorType colorType, | 472 SkColorType colorType, |
| 473 const SkImageDecoder& decoder) { | 473 const SkImageDecoder& decoder) { |
| 474 SkASSERT(cinfo != NULL); | 474 SkASSERT(cinfo != nullptr); |
| 475 #ifdef ANDROID_RGB | 475 #ifdef ANDROID_RGB |
| 476 cinfo->dither_mode = JDITHER_NONE; | 476 cinfo->dither_mode = JDITHER_NONE; |
| 477 if (JCS_CMYK == cinfo->out_color_space) { | 477 if (JCS_CMYK == cinfo->out_color_space) { |
| 478 return; | 478 return; |
| 479 } | 479 } |
| 480 switch (colorType) { | 480 switch (colorType) { |
| 481 case kN32_SkColorType: | 481 case kN32_SkColorType: |
| 482 cinfo->out_color_space = JCS_RGBA_8888; | 482 cinfo->out_color_space = JCS_RGBA_8888; |
| 483 break; | 483 break; |
| 484 case kRGB_565_SkColorType: | 484 case kRGB_565_SkColorType: |
| (...skipping 19 matching lines...) Expand all Loading... |
| 504 canvas.drawColor(SK_ColorWHITE); | 504 canvas.drawColor(SK_ColorWHITE); |
| 505 } | 505 } |
| 506 | 506 |
| 507 /** | 507 /** |
| 508 * Get the config and bytes per pixel of the source data. Return | 508 * Get the config and bytes per pixel of the source data. Return |
| 509 * whether the data is supported. | 509 * whether the data is supported. |
| 510 */ | 510 */ |
| 511 static bool get_src_config(const jpeg_decompress_struct& cinfo, | 511 static bool get_src_config(const jpeg_decompress_struct& cinfo, |
| 512 SkScaledBitmapSampler::SrcConfig* sc, | 512 SkScaledBitmapSampler::SrcConfig* sc, |
| 513 int* srcBytesPerPixel) { | 513 int* srcBytesPerPixel) { |
| 514 SkASSERT(sc != NULL && srcBytesPerPixel != NULL); | 514 SkASSERT(sc != nullptr && srcBytesPerPixel != nullptr); |
| 515 if (JCS_CMYK == cinfo.out_color_space) { | 515 if (JCS_CMYK == cinfo.out_color_space) { |
| 516 // In this case we will manually convert the CMYK values to RGB | 516 // In this case we will manually convert the CMYK values to RGB |
| 517 *sc = SkScaledBitmapSampler::kRGBX; | 517 *sc = SkScaledBitmapSampler::kRGBX; |
| 518 // The CMYK work-around relies on 4 components per pixel here | 518 // The CMYK work-around relies on 4 components per pixel here |
| 519 *srcBytesPerPixel = 4; | 519 *srcBytesPerPixel = 4; |
| 520 } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_spa
ce) { | 520 } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_spa
ce) { |
| 521 *sc = SkScaledBitmapSampler::kRGB; | 521 *sc = SkScaledBitmapSampler::kRGB; |
| 522 *srcBytesPerPixel = 3; | 522 *srcBytesPerPixel = 3; |
| 523 #ifdef ANDROID_RGB | 523 #ifdef ANDROID_RGB |
| 524 } else if (JCS_RGBA_8888 == cinfo.out_color_space) { | 524 } else if (JCS_RGBA_8888 == cinfo.out_color_space) { |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 627 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampl
eSize); | 627 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampl
eSize); |
| 628 // Assume an A8 bitmap is not opaque to avoid the check of each | 628 // Assume an A8 bitmap is not opaque to avoid the check of each |
| 629 // individual pixel. It is very unlikely to be opaque, since | 629 // individual pixel. It is very unlikely to be opaque, since |
| 630 // an opaque A8 bitmap would not be very interesting. | 630 // an opaque A8 bitmap would not be very interesting. |
| 631 // Otherwise, a jpeg image is opaque. | 631 // Otherwise, a jpeg image is opaque. |
| 632 bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), | 632 bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), |
| 633 colorType, alphaType)); | 633 colorType, alphaType)); |
| 634 if (SkImageDecoder::kDecodeBounds_Mode == mode) { | 634 if (SkImageDecoder::kDecodeBounds_Mode == mode) { |
| 635 return kSuccess; | 635 return kSuccess; |
| 636 } | 636 } |
| 637 if (!this->allocPixelRef(bm, NULL)) { | 637 if (!this->allocPixelRef(bm, nullptr)) { |
| 638 return return_failure(cinfo, *bm, "allocPixelRef"); | 638 return return_failure(cinfo, *bm, "allocPixelRef"); |
| 639 } | 639 } |
| 640 | 640 |
| 641 SkAutoLockPixels alp(*bm); | 641 SkAutoLockPixels alp(*bm); |
| 642 | 642 |
| 643 #ifdef ANDROID_RGB | 643 #ifdef ANDROID_RGB |
| 644 /* short-circuit the SkScaledBitmapSampler when possible, as this gives | 644 /* short-circuit the SkScaledBitmapSampler when possible, as this gives |
| 645 a significant performance boost. | 645 a significant performance boost. |
| 646 */ | 646 */ |
| 647 if (sampleSize == 1 && | 647 if (sampleSize == 1 && |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 923 return false; | 923 return false; |
| 924 } | 924 } |
| 925 | 925 |
| 926 if (!output_raw_data(cinfo, planes, rowBytes)) { | 926 if (!output_raw_data(cinfo, planes, rowBytes)) { |
| 927 return return_false(cinfo, "output_raw_data"); | 927 return return_false(cinfo, "output_raw_data"); |
| 928 } | 928 } |
| 929 | 929 |
| 930 update_components_sizes(cinfo, componentSizes, kActualSize_SizeType); | 930 update_components_sizes(cinfo, componentSizes, kActualSize_SizeType); |
| 931 jpeg_finish_decompress(&cinfo); | 931 jpeg_finish_decompress(&cinfo); |
| 932 | 932 |
| 933 if (NULL != colorSpace) { | 933 if (nullptr != colorSpace) { |
| 934 *colorSpace = kJPEG_SkYUVColorSpace; | 934 *colorSpace = kJPEG_SkYUVColorSpace; |
| 935 } | 935 } |
| 936 | 936 |
| 937 return true; | 937 return true; |
| 938 } | 938 } |
| 939 | 939 |
| 940 /////////////////////////////////////////////////////////////////////////////// | 940 /////////////////////////////////////////////////////////////////////////////// |
| 941 | 941 |
| 942 #ifdef SK_BUILD_FOR_ANDROID | 942 #ifdef SK_BUILD_FOR_ANDROID |
| 943 bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width
, int *height) { | 943 bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width
, int *height) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 997 *height = fImageHeight; | 997 *height = fImageHeight; |
| 998 } | 998 } |
| 999 | 999 |
| 1000 delete fImageIndex; | 1000 delete fImageIndex; |
| 1001 fImageIndex = imageIndex.detach(); | 1001 fImageIndex = imageIndex.detach(); |
| 1002 | 1002 |
| 1003 return true; | 1003 return true; |
| 1004 } | 1004 } |
| 1005 | 1005 |
| 1006 bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { | 1006 bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { |
| 1007 if (NULL == fImageIndex) { | 1007 if (nullptr == fImageIndex) { |
| 1008 return false; | 1008 return false; |
| 1009 } | 1009 } |
| 1010 jpeg_decompress_struct* cinfo = fImageIndex->cinfo(); | 1010 jpeg_decompress_struct* cinfo = fImageIndex->cinfo(); |
| 1011 | 1011 |
| 1012 SkIRect rect = SkIRect::MakeWH(fImageWidth, fImageHeight); | 1012 SkIRect rect = SkIRect::MakeWH(fImageWidth, fImageHeight); |
| 1013 if (!rect.intersect(region)) { | 1013 if (!rect.intersect(region)) { |
| 1014 // If the requested region is entirely outside the image return false | 1014 // If the requested region is entirely outside the image return false |
| 1015 return false; | 1015 return false; |
| 1016 } | 1016 } |
| 1017 | 1017 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1056 // If yes, then we will stick to AllocPixelRef since it's cheaper with the | 1056 // If yes, then we will stick to AllocPixelRef since it's cheaper with the |
| 1057 // swap happening. If no, then we will use alloc to allocate pixels to | 1057 // swap happening. If no, then we will use alloc to allocate pixels to |
| 1058 // prevent garbage collection. | 1058 // prevent garbage collection. |
| 1059 int w = rect.width() / actualSampleSize; | 1059 int w = rect.width() / actualSampleSize; |
| 1060 int h = rect.height() / actualSampleSize; | 1060 int h = rect.height() / actualSampleSize; |
| 1061 bool swapOnly = (rect == region) && bm->isNull() && | 1061 bool swapOnly = (rect == region) && bm->isNull() && |
| 1062 (w == bitmap.width()) && (h == bitmap.height()) && | 1062 (w == bitmap.width()) && (h == bitmap.height()) && |
| 1063 ((startX - rect.x()) / actualSampleSize == 0) && | 1063 ((startX - rect.x()) / actualSampleSize == 0) && |
| 1064 ((startY - rect.y()) / actualSampleSize == 0); | 1064 ((startY - rect.y()) / actualSampleSize == 0); |
| 1065 if (swapOnly) { | 1065 if (swapOnly) { |
| 1066 if (!this->allocPixelRef(&bitmap, NULL)) { | 1066 if (!this->allocPixelRef(&bitmap, nullptr)) { |
| 1067 return return_false(*cinfo, bitmap, "allocPixelRef"); | 1067 return return_false(*cinfo, bitmap, "allocPixelRef"); |
| 1068 } | 1068 } |
| 1069 } else { | 1069 } else { |
| 1070 if (!bitmap.tryAllocPixels()) { | 1070 if (!bitmap.tryAllocPixels()) { |
| 1071 return return_false(*cinfo, bitmap, "allocPixels"); | 1071 return return_false(*cinfo, bitmap, "allocPixels"); |
| 1072 } | 1072 } |
| 1073 } | 1073 } |
| 1074 | 1074 |
| 1075 SkAutoLockPixels alp(bitmap); | 1075 SkAutoLockPixels alp(bitmap); |
| 1076 | 1076 |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1326 switch (bm.colorType()) { | 1326 switch (bm.colorType()) { |
| 1327 case kN32_SkColorType: | 1327 case kN32_SkColorType: |
| 1328 return Write_32_YUV; | 1328 return Write_32_YUV; |
| 1329 case kRGB_565_SkColorType: | 1329 case kRGB_565_SkColorType: |
| 1330 return Write_16_YUV; | 1330 return Write_16_YUV; |
| 1331 case kARGB_4444_SkColorType: | 1331 case kARGB_4444_SkColorType: |
| 1332 return Write_4444_YUV; | 1332 return Write_4444_YUV; |
| 1333 case kIndex_8_SkColorType: | 1333 case kIndex_8_SkColorType: |
| 1334 return Write_Index_YUV; | 1334 return Write_Index_YUV; |
| 1335 default: | 1335 default: |
| 1336 return NULL; | 1336 return nullptr; |
| 1337 } | 1337 } |
| 1338 } | 1338 } |
| 1339 | 1339 |
| 1340 class SkJPEGImageEncoder : public SkImageEncoder { | 1340 class SkJPEGImageEncoder : public SkImageEncoder { |
| 1341 protected: | 1341 protected: |
| 1342 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) { | 1342 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) { |
| 1343 #ifdef TIME_ENCODE | 1343 #ifdef TIME_ENCODE |
| 1344 SkAutoTime atm("JPEG Encode"); | 1344 SkAutoTime atm("JPEG Encode"); |
| 1345 #endif | 1345 #endif |
| 1346 | 1346 |
| 1347 SkAutoLockPixels alp(bm); | 1347 SkAutoLockPixels alp(bm); |
| 1348 if (NULL == bm.getPixels()) { | 1348 if (nullptr == bm.getPixels()) { |
| 1349 return false; | 1349 return false; |
| 1350 } | 1350 } |
| 1351 | 1351 |
| 1352 jpeg_compress_struct cinfo; | 1352 jpeg_compress_struct cinfo; |
| 1353 skjpeg_error_mgr sk_err; | 1353 skjpeg_error_mgr sk_err; |
| 1354 skjpeg_destination_mgr sk_wstream(stream); | 1354 skjpeg_destination_mgr sk_wstream(stream); |
| 1355 | 1355 |
| 1356 // allocate these before set call setjmp | 1356 // allocate these before set call setjmp |
| 1357 SkAutoMalloc oneRow; | 1357 SkAutoMalloc oneRow; |
| 1358 | 1358 |
| 1359 cinfo.err = jpeg_std_error(&sk_err); | 1359 cinfo.err = jpeg_std_error(&sk_err); |
| 1360 sk_err.error_exit = skjpeg_error_exit; | 1360 sk_err.error_exit = skjpeg_error_exit; |
| 1361 if (setjmp(sk_err.fJmpBuf)) { | 1361 if (setjmp(sk_err.fJmpBuf)) { |
| 1362 return false; | 1362 return false; |
| 1363 } | 1363 } |
| 1364 | 1364 |
| 1365 // Keep after setjmp or mark volatile. | 1365 // Keep after setjmp or mark volatile. |
| 1366 const WriteScanline writer = ChooseWriter(bm); | 1366 const WriteScanline writer = ChooseWriter(bm); |
| 1367 if (NULL == writer) { | 1367 if (nullptr == writer) { |
| 1368 return false; | 1368 return false; |
| 1369 } | 1369 } |
| 1370 | 1370 |
| 1371 jpeg_create_compress(&cinfo); | 1371 jpeg_create_compress(&cinfo); |
| 1372 cinfo.dest = &sk_wstream; | 1372 cinfo.dest = &sk_wstream; |
| 1373 cinfo.image_width = bm.width(); | 1373 cinfo.image_width = bm.width(); |
| 1374 cinfo.image_height = bm.height(); | 1374 cinfo.image_height = bm.height(); |
| 1375 cinfo.input_components = 3; | 1375 cinfo.input_components = 3; |
| 1376 #ifdef WE_CONVERT_TO_YUV | 1376 #ifdef WE_CONVERT_TO_YUV |
| 1377 cinfo.in_color_space = JCS_YCbCr; | 1377 cinfo.in_color_space = JCS_YCbCr; |
| 1378 #else | 1378 #else |
| 1379 cinfo.in_color_space = JCS_RGB; | 1379 cinfo.in_color_space = JCS_RGB; |
| 1380 #endif | 1380 #endif |
| 1381 cinfo.input_gamma = 1; | 1381 cinfo.input_gamma = 1; |
| 1382 | 1382 |
| 1383 jpeg_set_defaults(&cinfo); | 1383 jpeg_set_defaults(&cinfo); |
| 1384 jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values
*/); | 1384 jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values
*/); |
| 1385 #ifdef DCT_IFAST_SUPPORTED | 1385 #ifdef DCT_IFAST_SUPPORTED |
| 1386 cinfo.dct_method = JDCT_IFAST; | 1386 cinfo.dct_method = JDCT_IFAST; |
| 1387 #endif | 1387 #endif |
| 1388 | 1388 |
| 1389 jpeg_start_compress(&cinfo, TRUE); | 1389 jpeg_start_compress(&cinfo, TRUE); |
| 1390 | 1390 |
| 1391 const int width = bm.width(); | 1391 const int width = bm.width(); |
| 1392 uint8_t* oneRowP = (uint8_t*)oneRow.reset(width * 3); | 1392 uint8_t* oneRowP = (uint8_t*)oneRow.reset(width * 3); |
| 1393 | 1393 |
| 1394 const SkPMColor* colors = bm.getColorTable() ? bm.getColorTable()->readC
olors() : NULL; | 1394 const SkPMColor* colors = bm.getColorTable() ? bm.getColorTable()->readC
olors() : nullptr; |
| 1395 const void* srcRow = bm.getPixels(); | 1395 const void* srcRow = bm.getPixels(); |
| 1396 | 1396 |
| 1397 while (cinfo.next_scanline < cinfo.image_height) { | 1397 while (cinfo.next_scanline < cinfo.image_height) { |
| 1398 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ | 1398 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ |
| 1399 | 1399 |
| 1400 writer(oneRowP, srcRow, width, colors); | 1400 writer(oneRowP, srcRow, width, colors); |
| 1401 row_pointer[0] = oneRowP; | 1401 row_pointer[0] = oneRowP; |
| 1402 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); | 1402 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); |
| 1403 srcRow = (const void*)((const char*)srcRow + bm.rowBytes()); | 1403 srcRow = (const void*)((const char*)srcRow + bm.rowBytes()); |
| 1404 } | 1404 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1429 return false; | 1429 return false; |
| 1430 } | 1430 } |
| 1431 return true; | 1431 return true; |
| 1432 } | 1432 } |
| 1433 | 1433 |
| 1434 | 1434 |
| 1435 static SkImageDecoder* sk_libjpeg_dfactory(SkStreamRewindable* stream) { | 1435 static SkImageDecoder* sk_libjpeg_dfactory(SkStreamRewindable* stream) { |
| 1436 if (is_jpeg(stream)) { | 1436 if (is_jpeg(stream)) { |
| 1437 return new SkJPEGImageDecoder; | 1437 return new SkJPEGImageDecoder; |
| 1438 } | 1438 } |
| 1439 return NULL; | 1439 return nullptr; |
| 1440 } | 1440 } |
| 1441 | 1441 |
| 1442 static SkImageDecoder::Format get_format_jpeg(SkStreamRewindable* stream) { | 1442 static SkImageDecoder::Format get_format_jpeg(SkStreamRewindable* stream) { |
| 1443 if (is_jpeg(stream)) { | 1443 if (is_jpeg(stream)) { |
| 1444 return SkImageDecoder::kJPEG_Format; | 1444 return SkImageDecoder::kJPEG_Format; |
| 1445 } | 1445 } |
| 1446 return SkImageDecoder::kUnknown_Format; | 1446 return SkImageDecoder::kUnknown_Format; |
| 1447 } | 1447 } |
| 1448 | 1448 |
| 1449 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { | 1449 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { |
| 1450 return (SkImageEncoder::kJPEG_Type == t) ? new SkJPEGImageEncoder : NULL; | 1450 return (SkImageEncoder::kJPEG_Type == t) ? new SkJPEGImageEncoder : nullptr; |
| 1451 } | 1451 } |
| 1452 | 1452 |
| 1453 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); | 1453 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); |
| 1454 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); | 1454 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); |
| 1455 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); | 1455 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); |
| OLD | NEW |