// 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/decompressed_image.h" #include #include "flutter/fml/mapping.h" #include "impeller/base/allocation.h" namespace impeller { DecompressedImage::DecompressedImage() = default; DecompressedImage::DecompressedImage( ISize size, Format format, std::shared_ptr allocation) : size_(size), format_(format), allocation_(std::move(allocation)) { if (!allocation_ || !size.IsPositive() || format_ == Format::kInvalid) { return; } is_valid_ = true; } DecompressedImage::~DecompressedImage() = default; bool DecompressedImage::IsValid() const { return is_valid_; } const ISize& DecompressedImage::GetSize() const { return size_; } DecompressedImage::Format DecompressedImage::GetFormat() const { return format_; } const std::shared_ptr& DecompressedImage::GetAllocation() const { return allocation_; } static size_t GetBytesPerPixel(DecompressedImage::Format format) { switch (format) { case DecompressedImage::Format::kInvalid: return 0u; case DecompressedImage::Format::kGrey: return 1u; case DecompressedImage::Format::kGreyAlpha: return 1u; case DecompressedImage::Format::kRGB: return 3u; case DecompressedImage::Format::kRGBA: return 4; } return 0u; } DecompressedImage DecompressedImage::ConvertToRGBA() const { if (!is_valid_) { return {}; } if (format_ == Format::kRGBA) { return DecompressedImage{size_, format_, allocation_}; } const auto bpp = GetBytesPerPixel(format_); const auto source_byte_size = size_.Area() * bpp; if (allocation_->GetSize() < source_byte_size) { return {}; } auto rgba_allocation = std::make_shared(); if (!rgba_allocation->Truncate(size_.Area() * 4u, false)) { return {}; } const uint8_t* source = allocation_->GetMapping(); uint8_t* dest = rgba_allocation->GetBuffer(); for (size_t i = 0, j = 0; i < source_byte_size; i += bpp, j += 4u) { switch (format_) { case DecompressedImage::Format::kGrey: dest[j + 0] = source[i]; dest[j + 1] = source[i]; dest[j + 2] = source[i]; dest[j + 3] = std::numeric_limits::max(); break; case DecompressedImage::Format::kGreyAlpha: dest[j + 0] = std::numeric_limits::max(); dest[j + 1] = std::numeric_limits::max(); dest[j + 2] = std::numeric_limits::max(); dest[j + 3] = source[i]; break; case DecompressedImage::Format::kRGB: dest[j + 0] = source[i + 0]; dest[j + 1] = source[i + 1]; dest[j + 2] = source[i + 2]; dest[j + 3] = std::numeric_limits::max(); break; case DecompressedImage::Format::kInvalid: case DecompressedImage::Format::kRGBA: // Should never happen. The necessary checks have already been // performed. FML_CHECK(false); break; } } return DecompressedImage{ size_, Format::kRGBA, std::make_shared( rgba_allocation->GetBuffer(), // rgba_allocation->GetLength(), // [rgba_allocation](auto, auto) {}) // }; } } // namespace impeller