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 |