| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "impeller/image/backends/skia/compressed_image_skia.h" |
| |
| #include <memory> |
| |
| #include "impeller/base/validation.h" |
| #include "third_party/skia/include/core/SkBitmap.h" |
| #include "third_party/skia/include/core/SkData.h" |
| #include "third_party/skia/include/core/SkImage.h" |
| #include "third_party/skia/include/core/SkPixmap.h" |
| #include "third_party/skia/include/core/SkRefCnt.h" |
| |
| namespace impeller { |
| |
| std::shared_ptr<CompressedImage> CompressedImageSkia::Create( |
| std::shared_ptr<const fml::Mapping> allocation) { |
| // There is only one backend today. |
| if (!allocation) { |
| return nullptr; |
| } |
| return std::make_shared<CompressedImageSkia>(std::move(allocation)); |
| } |
| |
| CompressedImageSkia::CompressedImageSkia( |
| std::shared_ptr<const fml::Mapping> allocation) |
| : CompressedImage(std::move(allocation)) {} |
| |
| CompressedImageSkia::~CompressedImageSkia() = default; |
| |
| // |CompressedImage| |
| DecompressedImage CompressedImageSkia::Decode() const { |
| if (!IsValid()) { |
| return {}; |
| } |
| if (source_->GetSize() == 0u) { |
| return {}; |
| } |
| |
| auto src = new std::shared_ptr<const fml::Mapping>(source_); |
| auto sk_data = SkData::MakeWithProc( |
| source_->GetMapping(), source_->GetSize(), |
| [](const void* ptr, void* context) { |
| delete reinterpret_cast<decltype(src)>(context); |
| }, |
| src); |
| |
| auto image = SkImages::DeferredFromEncodedData(sk_data); |
| if (!image) { |
| return {}; |
| } |
| |
| const auto dims = image->imageInfo().dimensions(); |
| auto info = SkImageInfo::Make(dims.width(), dims.height(), |
| kRGBA_8888_SkColorType, kPremul_SkAlphaType); |
| |
| auto bitmap = std::make_shared<SkBitmap>(); |
| if (!bitmap->tryAllocPixels(info)) { |
| VALIDATION_LOG << "Could not allocate arena for decompressing image."; |
| return {}; |
| } |
| |
| if (!image->readPixels(nullptr, bitmap->pixmap(), 0, 0)) { |
| VALIDATION_LOG << "Could not decompress image into arena."; |
| return {}; |
| } |
| |
| auto mapping = std::make_shared<fml::NonOwnedMapping>( |
| reinterpret_cast<const uint8_t*>(bitmap->pixmap().addr()), // data |
| bitmap->pixmap().rowBytes() * bitmap->pixmap().height(), // size |
| [bitmap](const uint8_t* data, size_t size) mutable { |
| bitmap.reset(); |
| } // proc |
| ); |
| |
| return { |
| {bitmap->pixmap().dimensions().fWidth, |
| bitmap->pixmap().dimensions().fHeight}, // size |
| DecompressedImage::Format::kRGBA, // format |
| mapping // allocation |
| }; |
| } |
| |
| } // namespace impeller |