blob: 271a60a4dd0547af0d56a047c731f4b1d6fa87fe [file] [log] [blame]
// 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.
#ifndef FLUTTER_LIB_UI_PAINTING_IMAGE_DESCRIPTOR_H_
#define FLUTTER_LIB_UI_PAINTING_IMAGE_DESCRIPTOR_H_
#include <cstdint>
#include <memory>
#include <optional>
#include "flutter/fml/macros.h"
#include "flutter/lib/ui/dart_wrapper.h"
#include "flutter/lib/ui/painting/image_generator_registry.h"
#include "flutter/lib/ui/painting/immutable_buffer.h"
#include "third_party/skia/include/codec/SkCodec.h"
#include "third_party/skia/include/core/SkImageGenerator.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/src/codec/SkCodecImageGenerator.h"
#include "third_party/tonic/dart_library_natives.h"
namespace flutter {
/// @brief Creates an image descriptor for encoded or decoded image data,
/// describing the width, height, and bytes per pixel for that image.
/// This class will hold a reference on the underlying image data, and
/// in the case of compressed data, an `ImageGenerator` for the data.
/// The Codec initialization actually happens in initEncoded, making
/// `initstantiateCodec` a lightweight operation.
/// @see `ImageGenerator`
class ImageDescriptor : public RefCountedDartWrappable<ImageDescriptor> {
public:
~ImageDescriptor() override = default;
// This must be kept in sync with the enum in painting.dart
enum PixelFormat {
kRGBA8888,
kBGRA8888,
};
/// @brief Asynchronously initlializes an ImageDescriptor for an encoded
/// image, as long as the format is recognized by an encoder installed
/// in the `ImageGeneratorRegistry`. Calling this method will create
/// an `ImageGenerator` and read EXIF corrected dimensions from the
/// image data.
/// @see `ImageGeneratorRegistry`
static Dart_Handle initEncoded(Dart_Handle descriptor_handle,
ImmutableBuffer* immutable_buffer,
Dart_Handle callback_handle);
/// @brief Synchronously initializes an `ImageDescriptor` for decompressed
/// image data as specified by the `PixelFormat`.
static void initRaw(Dart_Handle descriptor_handle,
fml::RefPtr<ImmutableBuffer> data,
int width,
int height,
int row_bytes,
PixelFormat pixel_format);
/// @brief Associates a flutter::Codec object with the dart.ui Codec handle.
void instantiateCodec(Dart_Handle codec, int target_width, int target_height);
/// @brief The width of this image, EXIF oriented if applicable.
int width() const { return image_info_.width(); }
/// @brief The height of this image. EXIF oriented if applicable.
int height() const { return image_info_.height(); }
/// @brief The bytes per pixel of the image.
int bytesPerPixel() const { return image_info_.bytesPerPixel(); }
/// @brief The byte length of the first row of the image.
/// Defaults to width() * 4.
int row_bytes() const {
return row_bytes_.value_or(
static_cast<size_t>(image_info_.width() * image_info_.bytesPerPixel()));
}
/// @brief Whether the given `target_width` or `target_height` differ from
/// `width()` and `height()` respectively.
bool should_resize(int target_width, int target_height) const {
return target_width != width() || target_height != height();
}
/// @brief The underlying buffer for this image.
sk_sp<SkData> data() const { return buffer_; }
sk_sp<SkImage> image() const;
/// @brief Whether this descriptor represents compressed (encoded) data or
/// not.
bool is_compressed() const { return !!generator_; }
/// @brief The orientation corrected image info for this image.
const SkImageInfo& image_info() const { return image_info_; }
/// @brief Gets the scaled dimensions of this image, if backed by an
/// `ImageGenerator` that can perform efficient subpixel scaling.
/// @see `ImageGenerator::GetScaledDimensions`
SkISize get_scaled_dimensions(float scale) {
if (generator_) {
return generator_->GetScaledDimensions(scale);
}
return image_info_.dimensions();
}
/// @brief Gets pixels for this image transformed based on the EXIF
/// orientation tag, if applicable.
bool get_pixels(const SkPixmap& pixmap) const;
void dispose() {
buffer_.reset();
generator_.reset();
ClearDartWrapper();
}
size_t GetAllocationSize() const override {
return sizeof(ImageDescriptor) + sizeof(SkImageInfo) + buffer_->size();
}
private:
ImageDescriptor(sk_sp<SkData> buffer,
const SkImageInfo& image_info,
std::optional<size_t> row_bytes);
ImageDescriptor(sk_sp<SkData> buffer,
std::shared_ptr<ImageGenerator> generator);
sk_sp<SkData> buffer_;
std::shared_ptr<ImageGenerator> generator_;
const SkImageInfo image_info_;
std::optional<size_t> row_bytes_;
const SkImageInfo CreateImageInfo() const;
DEFINE_WRAPPERTYPEINFO();
FML_FRIEND_MAKE_REF_COUNTED(ImageDescriptor);
FML_DISALLOW_COPY_AND_ASSIGN(ImageDescriptor);
friend class ImageDecoderFixtureTest;
};
} // namespace flutter
#endif // FLUTTER_LIB_UI_PAINTING_IMAGE_DESCRIPTOR_H_