/src/serenity/Userland/Libraries/LibGfx/ImageFormats/ImageDecoder.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #pragma once |
8 | | |
9 | | #include <AK/ByteBuffer.h> |
10 | | #include <AK/HashMap.h> |
11 | | #include <AK/OwnPtr.h> |
12 | | #include <AK/RefCounted.h> |
13 | | #include <AK/RefPtr.h> |
14 | | #include <AK/String.h> |
15 | | #include <LibGfx/Bitmap.h> |
16 | | #include <LibGfx/CMYKBitmap.h> |
17 | | #include <LibGfx/Size.h> |
18 | | #include <LibGfx/VectorGraphic.h> |
19 | | |
20 | | namespace Gfx { |
21 | | |
22 | | class Bitmap; |
23 | | |
24 | | struct ImageFrameDescriptor { |
25 | | RefPtr<Bitmap> image; |
26 | | int duration { 0 }; |
27 | | }; |
28 | | |
29 | | struct VectorImageFrameDescriptor { |
30 | | RefPtr<VectorGraphic> image; |
31 | | int duration { 0 }; |
32 | | }; |
33 | | |
34 | | class Metadata { |
35 | | public: |
36 | 21.0k | Metadata() = default; |
37 | 36.7k | virtual ~Metadata() = default; |
38 | | |
39 | | HashMap<StringView, String> const& main_tags() const |
40 | 0 | { |
41 | 0 | if (m_main_tags.is_empty()) |
42 | 0 | fill_main_tags(); |
43 | 0 |
|
44 | 0 | // This is designed to be used in a general GUI, don't include too much information here. |
45 | 0 | VERIFY(m_main_tags.size() < 8); |
46 | 0 |
|
47 | 0 | return m_main_tags; |
48 | 0 | } |
49 | | |
50 | | protected: |
51 | 0 | virtual void fill_main_tags() const { } |
52 | | |
53 | | mutable HashMap<StringView, String> m_main_tags; |
54 | | }; |
55 | | |
56 | | enum class NaturalFrameFormat { |
57 | | RGB, |
58 | | Grayscale, |
59 | | CMYK, |
60 | | Vector, |
61 | | }; |
62 | | |
63 | | class ImageDecoderPlugin { |
64 | | public: |
65 | 60.8k | virtual ~ImageDecoderPlugin() = default; |
66 | | |
67 | | // Each plugin should implement these static functions and register them in ImageDecoder.cpp |
68 | | // Implement sniff() if the file includes a magic number |
69 | | // static bool sniff(ReadonlyBytes); |
70 | | // Implement validate_before_create() otherwise |
71 | | // static ErrorOr<bool> validate_before_create(ReadonlyBytes); |
72 | | |
73 | | // This function should be used to both create the context and parse the image header. |
74 | | // static ErrorOr<NonnullOwnPtr<ImageDecoderPlugin>> create(ReadonlyBytes); |
75 | | |
76 | | // This should always be available as gathered in create() |
77 | | virtual IntSize size() = 0; |
78 | | |
79 | | // Override this if the format supports animated images |
80 | 0 | virtual bool is_animated() { return false; } |
81 | 0 | virtual size_t loop_count() { return 0; } |
82 | 0 | virtual size_t frame_count() { return 1; } |
83 | 0 | virtual size_t first_animated_frame_index() { return 0; } |
84 | | |
85 | | virtual ErrorOr<ImageFrameDescriptor> frame(size_t index, Optional<IntSize> ideal_size = {}) = 0; |
86 | | |
87 | 0 | virtual Optional<Metadata const&> metadata() { return OptionalNone {}; } |
88 | | |
89 | 0 | virtual ErrorOr<Optional<ReadonlyBytes>> icc_data() { return OptionalNone {}; } |
90 | | |
91 | 0 | virtual NaturalFrameFormat natural_frame_format() const { return NaturalFrameFormat::RGB; } |
92 | 0 | virtual ErrorOr<NonnullRefPtr<CMYKBitmap>> cmyk_frame() { VERIFY_NOT_REACHED(); } |
93 | 0 | virtual ErrorOr<VectorImageFrameDescriptor> vector_frame(size_t) { VERIFY_NOT_REACHED(); } |
94 | | |
95 | | protected: |
96 | 60.8k | ImageDecoderPlugin() = default; |
97 | | }; |
98 | | |
99 | | class ImageDecoder : public RefCounted<ImageDecoder> { |
100 | | public: |
101 | | static ErrorOr<RefPtr<ImageDecoder>> try_create_for_raw_bytes(ReadonlyBytes, Optional<ByteString> mime_type = {}); |
102 | 0 | ~ImageDecoder() = default; |
103 | | |
104 | 0 | IntSize size() const { return m_plugin->size(); } |
105 | 0 | int width() const { return size().width(); } |
106 | 0 | int height() const { return size().height(); } |
107 | 0 | bool is_animated() const { return m_plugin->is_animated(); } |
108 | 0 | size_t loop_count() const { return m_plugin->loop_count(); } |
109 | 0 | size_t frame_count() const { return m_plugin->frame_count(); } |
110 | 0 | size_t first_animated_frame_index() const { return m_plugin->first_animated_frame_index(); } |
111 | | |
112 | 0 | ErrorOr<ImageFrameDescriptor> frame(size_t index, Optional<IntSize> ideal_size = {}) const { return m_plugin->frame(index, ideal_size); } |
113 | | |
114 | 0 | Optional<Metadata const&> metadata() const { return m_plugin->metadata(); } |
115 | 0 | ErrorOr<Optional<ReadonlyBytes>> icc_data() const { return m_plugin->icc_data(); } |
116 | | |
117 | 0 | NaturalFrameFormat natural_frame_format() { return m_plugin->natural_frame_format(); } |
118 | | |
119 | | // Call only if natural_frame_format() == NaturalFrameFormat::CMYK. |
120 | 0 | ErrorOr<NonnullRefPtr<CMYKBitmap>> cmyk_frame() { return m_plugin->cmyk_frame(); } |
121 | | |
122 | | // Call only if natural_frame_format() == NaturalFrameFormat::Vector. |
123 | 0 | ErrorOr<VectorImageFrameDescriptor> vector_frame(size_t index) { return m_plugin->vector_frame(index); } |
124 | | |
125 | | private: |
126 | | explicit ImageDecoder(NonnullOwnPtr<ImageDecoderPlugin>); |
127 | | |
128 | | NonnullOwnPtr<ImageDecoderPlugin> mutable m_plugin; |
129 | | }; |
130 | | |
131 | | } |