/* * Copyright (c) 2018-2021, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include namespace Gfx { class Bitmap; static constexpr size_t maximum_width_for_decoded_images = 16384; static constexpr size_t maximum_height_for_decoded_images = 16384; struct ImageFrameDescriptor { RefPtr image; int duration { 0 }; }; struct VectorImageFrameDescriptor { RefPtr image; int duration { 0 }; }; class ImageDecoderPlugin { public: virtual ~ImageDecoderPlugin() = default; // Each plugin should implement these static functions and register them in ImageDecoder.cpp // Implement sniff() if the file includes a magic number // static bool sniff(ReadonlyBytes); // Implement validate_before_create() otherwise // static ErrorOr validate_before_create(ReadonlyBytes); // This function should be used to both create the context and parse the image header. // static ErrorOr> create(ReadonlyBytes); // This should always be available as gathered in create() virtual IntSize size() = 0; virtual bool is_animated() = 0; virtual size_t loop_count() = 0; virtual size_t frame_count() = 0; virtual size_t first_animated_frame_index() = 0; virtual ErrorOr frame(size_t index, Optional ideal_size = {}) = 0; virtual ErrorOr> icc_data() = 0; virtual bool is_vector() { return false; } virtual ErrorOr vector_frame(size_t) { VERIFY_NOT_REACHED(); } protected: ImageDecoderPlugin() = default; }; class ImageDecoder : public RefCounted { public: static RefPtr try_create_for_raw_bytes(ReadonlyBytes, Optional mime_type = {}); ~ImageDecoder() = default; IntSize size() const { return m_plugin->size(); } int width() const { return size().width(); } int height() const { return size().height(); } bool is_animated() const { return m_plugin->is_animated(); } size_t loop_count() const { return m_plugin->loop_count(); } size_t frame_count() const { return m_plugin->frame_count(); } size_t first_animated_frame_index() const { return m_plugin->first_animated_frame_index(); } ErrorOr frame(size_t index, Optional ideal_size = {}) const { return m_plugin->frame(index, ideal_size); } ErrorOr> icc_data() const { return m_plugin->icc_data(); } bool is_vector() { return m_plugin->is_vector(); } ErrorOr vector_frame(size_t index) { return m_plugin->vector_frame(index); } private: explicit ImageDecoder(NonnullOwnPtr); NonnullOwnPtr mutable m_plugin; }; }