| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
| 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 #include "Resources.h" | 8 #include "Resources.h" |
| 9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
| 10 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 SkBitmap bm8888Unpremul; | 80 SkBitmap bm8888Unpremul; |
| 81 | 81 |
| 82 SkFILEStream stream(filename.c_str()); | 82 SkFILEStream stream(filename.c_str()); |
| 83 | 83 |
| 84 SkImageDecoder::Format format = SkImageDecoder::GetStreamFormat(&stream); | 84 SkImageDecoder::Format format = SkImageDecoder::GetStreamFormat(&stream); |
| 85 if (skip_image_format(format)) { | 85 if (skip_image_format(format)) { |
| 86 return; | 86 return; |
| 87 } | 87 } |
| 88 | 88 |
| 89 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream)); | 89 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream)); |
| 90 if (NULL == decoder.get()) { | 90 if (nullptr == decoder.get()) { |
| 91 SkDebugf("couldn't decode %s\n", filename.c_str()); | 91 SkDebugf("couldn't decode %s\n", filename.c_str()); |
| 92 return; | 92 return; |
| 93 } | 93 } |
| 94 | 94 |
| 95 bool success = decoder->decode(&stream, &bm8888, kN32_SkColorType, | 95 bool success = decoder->decode(&stream, &bm8888, kN32_SkColorType, |
| 96 SkImageDecoder::kDecodePixels_Mode) != SkImag
eDecoder::kFailure; | 96 SkImageDecoder::kDecodePixels_Mode) != SkImag
eDecoder::kFailure; |
| 97 if (!success) { | 97 if (!success) { |
| 98 return; | 98 return; |
| 99 } | 99 } |
| 100 | 100 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 169 } | 169 } |
| 170 | 170 |
| 171 #if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX) | 171 #if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX) |
| 172 // Test that the alpha type is what we expect. | 172 // Test that the alpha type is what we expect. |
| 173 static void test_alphaType(skiatest::Reporter* reporter, const SkString& filenam
e, | 173 static void test_alphaType(skiatest::Reporter* reporter, const SkString& filenam
e, |
| 174 bool requireUnpremul) { | 174 bool requireUnpremul) { |
| 175 SkBitmap bm; | 175 SkBitmap bm; |
| 176 SkFILEStream stream(filename.c_str()); | 176 SkFILEStream stream(filename.c_str()); |
| 177 | 177 |
| 178 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream)); | 178 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream)); |
| 179 if (NULL == decoder.get()) { | 179 if (nullptr == decoder.get()) { |
| 180 return; | 180 return; |
| 181 } | 181 } |
| 182 | 182 |
| 183 decoder->setRequireUnpremultipliedColors(requireUnpremul); | 183 decoder->setRequireUnpremultipliedColors(requireUnpremul); |
| 184 | 184 |
| 185 // Decode just the bounds. This should always succeed. | 185 // Decode just the bounds. This should always succeed. |
| 186 bool success = decoder->decode(&stream, &bm, kN32_SkColorType, | 186 bool success = decoder->decode(&stream, &bm, kN32_SkColorType, |
| 187 SkImageDecoder::kDecodeBounds_Mode); | 187 SkImageDecoder::kDecodeBounds_Mode); |
| 188 REPORTER_ASSERT(reporter, success); | 188 REPORTER_ASSERT(reporter, success); |
| 189 if (!success) { | 189 if (!success) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 | 274 |
| 275 if (!stream.isValid()) { | 275 if (!stream.isValid()) { |
| 276 SkDebugf("file %s missing from resource directoy %s\n", | 276 SkDebugf("file %s missing from resource directoy %s\n", |
| 277 basename.c_str(), resourcePath.c_str()); | 277 basename.c_str(), resourcePath.c_str()); |
| 278 continue; | 278 continue; |
| 279 } | 279 } |
| 280 | 280 |
| 281 // This should never fail since we know the images we're decoding. | 281 // This should never fail since we know the images we're decoding. |
| 282 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream)); | 282 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream)); |
| 283 REPORTER_ASSERT(reporter, decoder.get()); | 283 REPORTER_ASSERT(reporter, decoder.get()); |
| 284 if (NULL == decoder.get()) { | 284 if (nullptr == decoder.get()) { |
| 285 continue; | 285 continue; |
| 286 } | 286 } |
| 287 | 287 |
| 288 // Test unpremultiplied. We know what color this should result in. | 288 // Test unpremultiplied. We know what color this should result in. |
| 289 decoder->setRequireUnpremultipliedColors(true); | 289 decoder->setRequireUnpremultipliedColors(true); |
| 290 bool success = decoder->decode(&stream, &bm, kN32_SkColorType, | 290 bool success = decoder->decode(&stream, &bm, kN32_SkColorType, |
| 291 SkImageDecoder::kDecodePixels_Mode); | 291 SkImageDecoder::kDecodePixels_Mode); |
| 292 REPORTER_ASSERT(reporter, success); | 292 REPORTER_ASSERT(reporter, success); |
| 293 if (!success) { | 293 if (!success) { |
| 294 continue; | 294 continue; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 REPORTER_ASSERT(reporter, !error); | 417 REPORTER_ASSERT(reporter, !error); |
| 418 } | 418 } |
| 419 } | 419 } |
| 420 | 420 |
| 421 //////////////////////////////////////////////////////////////////////////////// | 421 //////////////////////////////////////////////////////////////////////////////// |
| 422 | 422 |
| 423 // example of how Android will do this inside their BitmapFactory | 423 // example of how Android will do this inside their BitmapFactory |
| 424 static SkPixelRef* install_pixel_ref(SkBitmap* bitmap, | 424 static SkPixelRef* install_pixel_ref(SkBitmap* bitmap, |
| 425 SkStreamRewindable* stream, | 425 SkStreamRewindable* stream, |
| 426 int sampleSize, bool ditherImage) { | 426 int sampleSize, bool ditherImage) { |
| 427 SkASSERT(bitmap != NULL); | 427 SkASSERT(bitmap != nullptr); |
| 428 SkASSERT(stream != NULL); | 428 SkASSERT(stream != nullptr); |
| 429 SkASSERT(stream->rewind()); | 429 SkASSERT(stream->rewind()); |
| 430 SkColorType colorType = bitmap->colorType(); | 430 SkColorType colorType = bitmap->colorType(); |
| 431 SkDecodingImageGenerator::Options opts(sampleSize, ditherImage, colorType); | 431 SkDecodingImageGenerator::Options opts(sampleSize, ditherImage, colorType); |
| 432 if (SkInstallDiscardablePixelRef( | 432 if (SkInstallDiscardablePixelRef( |
| 433 SkDecodingImageGenerator::Create(stream, opts), bitmap)) { | 433 SkDecodingImageGenerator::Create(stream, opts), bitmap)) { |
| 434 return bitmap->pixelRef(); | 434 return bitmap->pixelRef(); |
| 435 } | 435 } |
| 436 return NULL; | 436 return nullptr; |
| 437 } | 437 } |
| 438 /** | 438 /** |
| 439 * A test for the SkDecodingImageGenerator::Create and | 439 * A test for the SkDecodingImageGenerator::Create and |
| 440 * SkInstallDiscardablePixelRef functions. | 440 * SkInstallDiscardablePixelRef functions. |
| 441 */ | 441 */ |
| 442 DEF_TEST(ImprovedBitmapFactory, reporter) { | 442 DEF_TEST(ImprovedBitmapFactory, reporter) { |
| 443 SkString pngFilename = GetResourcePath("randPixels.png"); | 443 SkString pngFilename = GetResourcePath("randPixels.png"); |
| 444 SkAutoTDelete<SkStreamRewindable> stream(SkStream::NewFromFile(pngFilename.c
_str())); | 444 SkAutoTDelete<SkStreamRewindable> stream(SkStream::NewFromFile(pngFilename.c
_str())); |
| 445 if (sk_exists(pngFilename.c_str())) { | 445 if (sk_exists(pngFilename.c_str())) { |
| 446 SkBitmap bm; | 446 SkBitmap bm; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 */ | 508 */ |
| 509 static void test_options(skiatest::Reporter* reporter, | 509 static void test_options(skiatest::Reporter* reporter, |
| 510 const SkDecodingImageGenerator::Options& opts, | 510 const SkDecodingImageGenerator::Options& opts, |
| 511 SkStreamRewindable* encodedStream, | 511 SkStreamRewindable* encodedStream, |
| 512 SkData* encodedData, | 512 SkData* encodedData, |
| 513 bool useData, | 513 bool useData, |
| 514 const SkString& path) { | 514 const SkString& path) { |
| 515 SkBitmap bm; | 515 SkBitmap bm; |
| 516 bool success = false; | 516 bool success = false; |
| 517 if (useData) { | 517 if (useData) { |
| 518 if (NULL == encodedData) { | 518 if (nullptr == encodedData) { |
| 519 return; | 519 return; |
| 520 } | 520 } |
| 521 success = SkInstallDiscardablePixelRef( | 521 success = SkInstallDiscardablePixelRef( |
| 522 SkDecodingImageGenerator::Create(encodedData, opts), &bm); | 522 SkDecodingImageGenerator::Create(encodedData, opts), &bm); |
| 523 } else { | 523 } else { |
| 524 if (NULL == encodedStream) { | 524 if (nullptr == encodedStream) { |
| 525 return; | 525 return; |
| 526 } | 526 } |
| 527 success = SkInstallDiscardablePixelRef( | 527 success = SkInstallDiscardablePixelRef( |
| 528 SkDecodingImageGenerator::Create(encodedStream->duplicate(), opts),
&bm); | 528 SkDecodingImageGenerator::Create(encodedStream->duplicate(), opts),
&bm); |
| 529 } | 529 } |
| 530 if (!success) { | 530 if (!success) { |
| 531 if (opts.fUseRequestedColorType | 531 if (opts.fUseRequestedColorType |
| 532 && (kARGB_4444_SkColorType == opts.fRequestedColorType)) { | 532 && (kARGB_4444_SkColorType == opts.fRequestedColorType)) { |
| 533 return; // Ignore known conversion inabilities. | 533 return; // Ignore known conversion inabilities. |
| 534 } | 534 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 547 opts.fSampleSize)); | 547 opts.fSampleSize)); |
| 548 REPORTER_ASSERT(reporter, check_rounding(bm.width(), kExpectedWidth, | 548 REPORTER_ASSERT(reporter, check_rounding(bm.width(), kExpectedWidth, |
| 549 opts.fSampleSize)); | 549 opts.fSampleSize)); |
| 550 // The ImageDecoder API doesn't guarantee that SampleSize does | 550 // The ImageDecoder API doesn't guarantee that SampleSize does |
| 551 // anything at all, but the decoders that this test excercises all | 551 // anything at all, but the decoders that this test excercises all |
| 552 // produce an output size in the following range: | 552 // produce an output size in the following range: |
| 553 // (((sample_size * out_size) > (in_size - sample_size)) | 553 // (((sample_size * out_size) > (in_size - sample_size)) |
| 554 // && out_size <= SkNextPow2(((in_size - 1) / sample_size) + 1)); | 554 // && out_size <= SkNextPow2(((in_size - 1) / sample_size) + 1)); |
| 555 #endif // SK_BUILD_FOR_ANDROID || SK_BUILD_FOR_UNIX | 555 #endif // SK_BUILD_FOR_ANDROID || SK_BUILD_FOR_UNIX |
| 556 SkAutoLockPixels alp(bm); | 556 SkAutoLockPixels alp(bm); |
| 557 if (bm.getPixels() == NULL) { | 557 if (bm.getPixels() == nullptr) { |
| 558 ERRORF(reporter, "Pixel decode failed [sampleSize=%d dither=%s " | 558 ERRORF(reporter, "Pixel decode failed [sampleSize=%d dither=%s " |
| 559 "colorType=%s %s]", opts.fSampleSize, yn(opts.fDitherImage), | 559 "colorType=%s %s]", opts.fSampleSize, yn(opts.fDitherImage), |
| 560 options_colorType(opts), path.c_str()); | 560 options_colorType(opts), path.c_str()); |
| 561 return; | 561 return; |
| 562 } | 562 } |
| 563 | 563 |
| 564 SkColorType requestedColorType = opts.fRequestedColorType; | 564 SkColorType requestedColorType = opts.fRequestedColorType; |
| 565 REPORTER_ASSERT(reporter, | 565 REPORTER_ASSERT(reporter, |
| 566 (!opts.fUseRequestedColorType) | 566 (!opts.fUseRequestedColorType) |
| 567 || (bm.colorType() == requestedColorType)); | 567 || (bm.colorType() == requestedColorType)); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 }; | 628 }; |
| 629 const bool useDataList[] = {true, false}; | 629 const bool useDataList[] = {true, false}; |
| 630 | 630 |
| 631 for (size_t fidx = 0; fidx < SK_ARRAY_COUNT(files); ++fidx) { | 631 for (size_t fidx = 0; fidx < SK_ARRAY_COUNT(files); ++fidx) { |
| 632 SkString path = SkOSPath::Join(resourceDir.c_str(), files[fidx]); | 632 SkString path = SkOSPath::Join(resourceDir.c_str(), files[fidx]); |
| 633 if (!sk_exists(path.c_str())) { | 633 if (!sk_exists(path.c_str())) { |
| 634 continue; | 634 continue; |
| 635 } | 635 } |
| 636 | 636 |
| 637 SkAutoDataUnref encodedData(SkData::NewFromFileName(path.c_str())); | 637 SkAutoDataUnref encodedData(SkData::NewFromFileName(path.c_str())); |
| 638 REPORTER_ASSERT(reporter, encodedData.get() != NULL); | 638 REPORTER_ASSERT(reporter, encodedData.get() != nullptr); |
| 639 SkAutoTDelete<SkStreamRewindable> encodedStream( | 639 SkAutoTDelete<SkStreamRewindable> encodedStream( |
| 640 SkStream::NewFromFile(path.c_str())); | 640 SkStream::NewFromFile(path.c_str())); |
| 641 REPORTER_ASSERT(reporter, encodedStream.get() != NULL); | 641 REPORTER_ASSERT(reporter, encodedStream.get() != nullptr); |
| 642 | 642 |
| 643 for (size_t i = 0; i < SK_ARRAY_COUNT(scaleList); ++i) { | 643 for (size_t i = 0; i < SK_ARRAY_COUNT(scaleList); ++i) { |
| 644 for (size_t j = 0; j < SK_ARRAY_COUNT(ditherList); ++j) { | 644 for (size_t j = 0; j < SK_ARRAY_COUNT(ditherList); ++j) { |
| 645 for (size_t m = 0; m < SK_ARRAY_COUNT(useDataList); ++m) { | 645 for (size_t m = 0; m < SK_ARRAY_COUNT(useDataList); ++m) { |
| 646 for (size_t k = 0; k < SK_ARRAY_COUNT(colorList); ++k) { | 646 for (size_t k = 0; k < SK_ARRAY_COUNT(colorList); ++k) { |
| 647 SkDecodingImageGenerator::Options opts(scaleList[i], | 647 SkDecodingImageGenerator::Options opts(scaleList[i], |
| 648 ditherList[j], | 648 ditherList[j], |
| 649 colorList[k]); | 649 colorList[k]); |
| 650 test_options(reporter, opts, encodedStream, encodedData, | 650 test_options(reporter, opts, encodedStream, encodedData, |
| 651 useDataList[m], path); | 651 useDataList[m], path); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 695 namespace { | 695 namespace { |
| 696 class SingleAllocator : public SkBitmap::Allocator { | 696 class SingleAllocator : public SkBitmap::Allocator { |
| 697 public: | 697 public: |
| 698 SingleAllocator(void* p, size_t s) : fPixels(p), fSize(s) { } | 698 SingleAllocator(void* p, size_t s) : fPixels(p), fSize(s) { } |
| 699 ~SingleAllocator() {} | 699 ~SingleAllocator() {} |
| 700 // If the pixels in fPixels are big enough, use them. | 700 // If the pixels in fPixels are big enough, use them. |
| 701 bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) override { | 701 bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) override { |
| 702 SkASSERT(bm); | 702 SkASSERT(bm); |
| 703 if (bm->info().getSafeSize(bm->rowBytes()) <= fSize) { | 703 if (bm->info().getSafeSize(bm->rowBytes()) <= fSize) { |
| 704 bm->setPixels(fPixels, ct); | 704 bm->setPixels(fPixels, ct); |
| 705 fPixels = NULL; | 705 fPixels = nullptr; |
| 706 fSize = 0; | 706 fSize = 0; |
| 707 return true; | 707 return true; |
| 708 } | 708 } |
| 709 return bm->tryAllocPixels(NULL, ct); | 709 return bm->tryAllocPixels(nullptr, ct); |
| 710 } | 710 } |
| 711 bool ready() { return fPixels != NULL; } | 711 bool ready() { return fPixels != nullptr; } |
| 712 private: | 712 private: |
| 713 void* fPixels; | 713 void* fPixels; |
| 714 size_t fSize; | 714 size_t fSize; |
| 715 }; | 715 }; |
| 716 } // namespace | 716 } // namespace |
| 717 | 717 |
| 718 /* This tests for a bug in libjpeg where INT32 is typedefed to long | 718 /* This tests for a bug in libjpeg where INT32 is typedefed to long |
| 719 and memory can be written to outside of the array. */ | 719 and memory can be written to outside of the array. */ |
| 720 DEF_TEST(ImageDecoding_JpegOverwrite, r) { | 720 DEF_TEST(ImageDecoding_JpegOverwrite, r) { |
| 721 SkString resourceDir = GetResourcePath(); | 721 SkString resourceDir = GetResourcePath(); |
| 722 SkString path = SkOSPath::Join(resourceDir.c_str(), "randPixels.jpg"); | 722 SkString path = SkOSPath::Join(resourceDir.c_str(), "randPixels.jpg"); |
| 723 SkAutoTDelete<SkStreamAsset> stream( | 723 SkAutoTDelete<SkStreamAsset> stream( |
| 724 SkStream::NewFromFile(path.c_str())); | 724 SkStream::NewFromFile(path.c_str())); |
| 725 if (!stream.get()) { | 725 if (!stream.get()) { |
| 726 SkDebugf("\nPath '%s' missing.\n", path.c_str()); | 726 SkDebugf("\nPath '%s' missing.\n", path.c_str()); |
| 727 return; | 727 return; |
| 728 } | 728 } |
| 729 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream)); | 729 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream)); |
| 730 if (NULL == decoder.get()) { | 730 if (nullptr == decoder.get()) { |
| 731 ERRORF(r, "\nSkImageDecoder::Factory failed.\n"); | 731 ERRORF(r, "\nSkImageDecoder::Factory failed.\n"); |
| 732 return; | 732 return; |
| 733 } | 733 } |
| 734 SkAssertResult(stream->rewind()); | 734 SkAssertResult(stream->rewind()); |
| 735 | 735 |
| 736 static const uint16_t sentinal = 0xBEEF; | 736 static const uint16_t sentinal = 0xBEEF; |
| 737 static const int pixelCount = 16; | 737 static const int pixelCount = 16; |
| 738 SkAutoTMalloc<uint16_t> pixels(pixelCount + 1); | 738 SkAutoTMalloc<uint16_t> pixels(pixelCount + 1); |
| 739 // pixels.get() should be 4-byte aligned. | 739 // pixels.get() should be 4-byte aligned. |
| 740 // This is necessary to reproduce the bug. | 740 // This is necessary to reproduce the bug. |
| 741 | 741 |
| 742 pixels[pixelCount] = sentinal; // This value should not be changed. | 742 pixels[pixelCount] = sentinal; // This value should not be changed. |
| 743 | 743 |
| 744 SkAutoTUnref<SingleAllocator> allocator( | 744 SkAutoTUnref<SingleAllocator> allocator( |
| 745 new SingleAllocator((void*)pixels.get(), sizeof(uint16_t) * pixelCou
nt)); | 745 new SingleAllocator((void*)pixels.get(), sizeof(uint16_t) * pixelCou
nt)); |
| 746 decoder->setAllocator(allocator); | 746 decoder->setAllocator(allocator); |
| 747 decoder->setSampleSize(2); | 747 decoder->setSampleSize(2); |
| 748 SkBitmap bitmap; | 748 SkBitmap bitmap; |
| 749 bool success = decoder->decode(stream, &bitmap, kRGB_565_SkColorType, | 749 bool success = decoder->decode(stream, &bitmap, kRGB_565_SkColorType, |
| 750 SkImageDecoder::kDecodePixels_Mode) != SkImag
eDecoder::kFailure; | 750 SkImageDecoder::kDecodePixels_Mode) != SkImag
eDecoder::kFailure; |
| 751 REPORTER_ASSERT(r, success); | 751 REPORTER_ASSERT(r, success); |
| 752 REPORTER_ASSERT(r, !allocator->ready()); // Decoder used correct memory | 752 REPORTER_ASSERT(r, !allocator->ready()); // Decoder used correct memory |
| 753 REPORTER_ASSERT(r, sentinal == pixels[pixelCount]); | 753 REPORTER_ASSERT(r, sentinal == pixels[pixelCount]); |
| 754 } | 754 } |
| OLD | NEW |