/src/serenity/Userland/Libraries/LibGfx/ImageFormats/ImageDecoder.cpp
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 | | #include <AK/LexicalPath.h> |
8 | | #include <LibGfx/ImageFormats/BMPLoader.h> |
9 | | #include <LibGfx/ImageFormats/DDSLoader.h> |
10 | | #include <LibGfx/ImageFormats/DICOMLoader.h> |
11 | | #include <LibGfx/ImageFormats/GIFLoader.h> |
12 | | #include <LibGfx/ImageFormats/ICOLoader.h> |
13 | | #include <LibGfx/ImageFormats/ILBMLoader.h> |
14 | | #include <LibGfx/ImageFormats/ImageDecoder.h> |
15 | | #include <LibGfx/ImageFormats/JBIG2Loader.h> |
16 | | #include <LibGfx/ImageFormats/JPEG2000Loader.h> |
17 | | #include <LibGfx/ImageFormats/JPEGLoader.h> |
18 | | #include <LibGfx/ImageFormats/JPEGXLLoader.h> |
19 | | #include <LibGfx/ImageFormats/PAMLoader.h> |
20 | | #include <LibGfx/ImageFormats/PBMLoader.h> |
21 | | #include <LibGfx/ImageFormats/PGMLoader.h> |
22 | | #include <LibGfx/ImageFormats/PNGLoader.h> |
23 | | #include <LibGfx/ImageFormats/PPMLoader.h> |
24 | | #include <LibGfx/ImageFormats/QOILoader.h> |
25 | | #include <LibGfx/ImageFormats/TGALoader.h> |
26 | | #include <LibGfx/ImageFormats/TIFFLoader.h> |
27 | | #include <LibGfx/ImageFormats/TinyVGLoader.h> |
28 | | #include <LibGfx/ImageFormats/WebPLoader.h> |
29 | | |
30 | | namespace Gfx { |
31 | | |
32 | | static ErrorOr<OwnPtr<ImageDecoderPlugin>> probe_and_sniff_for_appropriate_plugin(ReadonlyBytes bytes) |
33 | 0 | { |
34 | 0 | struct ImagePluginInitializer { |
35 | 0 | bool (*sniff)(ReadonlyBytes) = nullptr; |
36 | 0 | ErrorOr<NonnullOwnPtr<ImageDecoderPlugin>> (*create)(ReadonlyBytes) = nullptr; |
37 | 0 | }; |
38 | |
|
39 | 0 | static constexpr ImagePluginInitializer s_initializers[] = { |
40 | 0 | { BMPImageDecoderPlugin::sniff, BMPImageDecoderPlugin::create }, |
41 | 0 | { DDSImageDecoderPlugin::sniff, DDSImageDecoderPlugin::create }, |
42 | 0 | { DICOMImageDecoderPlugin::sniff, DICOMImageDecoderPlugin::create }, |
43 | 0 | { GIFImageDecoderPlugin::sniff, GIFImageDecoderPlugin::create }, |
44 | 0 | { ICOImageDecoderPlugin::sniff, ICOImageDecoderPlugin::create }, |
45 | 0 | { ILBMImageDecoderPlugin::sniff, ILBMImageDecoderPlugin::create }, |
46 | 0 | { JBIG2ImageDecoderPlugin::sniff, JBIG2ImageDecoderPlugin::create }, |
47 | 0 | { JPEG2000ImageDecoderPlugin::sniff, JPEG2000ImageDecoderPlugin::create }, |
48 | 0 | { JPEGImageDecoderPlugin::sniff, JPEGImageDecoderPlugin::create }, |
49 | 0 | { JPEGXLImageDecoderPlugin::sniff, JPEGXLImageDecoderPlugin::create }, |
50 | 0 | { PAMImageDecoderPlugin::sniff, PAMImageDecoderPlugin::create }, |
51 | 0 | { PBMImageDecoderPlugin::sniff, PBMImageDecoderPlugin::create }, |
52 | 0 | { PGMImageDecoderPlugin::sniff, PGMImageDecoderPlugin::create }, |
53 | 0 | { PNGImageDecoderPlugin::sniff, PNGImageDecoderPlugin::create }, |
54 | 0 | { PPMImageDecoderPlugin::sniff, PPMImageDecoderPlugin::create }, |
55 | 0 | { QOIImageDecoderPlugin::sniff, QOIImageDecoderPlugin::create }, |
56 | 0 | { TIFFImageDecoderPlugin::sniff, TIFFImageDecoderPlugin::create }, |
57 | 0 | { TinyVGImageDecoderPlugin::sniff, TinyVGImageDecoderPlugin::create }, |
58 | 0 | { WebPImageDecoderPlugin::sniff, WebPImageDecoderPlugin::create }, |
59 | 0 | }; |
60 | |
|
61 | 0 | for (auto& plugin : s_initializers) { |
62 | 0 | auto sniff_result = plugin.sniff(bytes); |
63 | 0 | if (!sniff_result) |
64 | 0 | continue; |
65 | 0 | return TRY(plugin.create(bytes)); |
66 | 0 | } |
67 | 0 | return OwnPtr<ImageDecoderPlugin> {}; |
68 | 0 | } |
69 | | |
70 | | static ErrorOr<OwnPtr<ImageDecoderPlugin>> probe_and_sniff_for_appropriate_plugin_with_known_mime_type(StringView mime_type, ReadonlyBytes bytes) |
71 | 0 | { |
72 | 0 | struct ImagePluginWithMIMETypeInitializer { |
73 | 0 | bool (*validate_before_create)(ReadonlyBytes) = nullptr; |
74 | 0 | ErrorOr<NonnullOwnPtr<ImageDecoderPlugin>> (*create)(ReadonlyBytes) = nullptr; |
75 | 0 | StringView mime_type; |
76 | 0 | }; |
77 | |
|
78 | 0 | static constexpr ImagePluginWithMIMETypeInitializer s_initializers_with_mime_type[] = { |
79 | 0 | { TGAImageDecoderPlugin::validate_before_create, TGAImageDecoderPlugin::create, "image/x-targa"sv }, |
80 | 0 | }; |
81 | |
|
82 | 0 | for (auto& plugin : s_initializers_with_mime_type) { |
83 | 0 | if (plugin.mime_type != mime_type) |
84 | 0 | continue; |
85 | 0 | auto validation_result = plugin.validate_before_create(bytes); |
86 | 0 | if (!validation_result) |
87 | 0 | continue; |
88 | 0 | return TRY(plugin.create(bytes)); |
89 | 0 | } |
90 | 0 | return OwnPtr<ImageDecoderPlugin> {}; |
91 | 0 | } |
92 | | |
93 | | ErrorOr<RefPtr<ImageDecoder>> ImageDecoder::try_create_for_raw_bytes(ReadonlyBytes bytes, Optional<ByteString> mime_type) |
94 | 0 | { |
95 | 0 | if (auto plugin = TRY(probe_and_sniff_for_appropriate_plugin(bytes)); plugin) |
96 | 0 | return adopt_ref_if_nonnull(new (nothrow) ImageDecoder(plugin.release_nonnull())); |
97 | | |
98 | 0 | if (mime_type.has_value()) { |
99 | 0 | if (OwnPtr<ImageDecoderPlugin> plugin = TRY(probe_and_sniff_for_appropriate_plugin_with_known_mime_type(mime_type.value(), bytes)); plugin) |
100 | 0 | return adopt_ref_if_nonnull(new (nothrow) ImageDecoder(plugin.release_nonnull())); |
101 | 0 | } |
102 | | |
103 | 0 | return RefPtr<ImageDecoder> {}; |
104 | 0 | } |
105 | | |
106 | | ImageDecoder::ImageDecoder(NonnullOwnPtr<ImageDecoderPlugin> plugin) |
107 | 0 | : m_plugin(move(plugin)) |
108 | 0 | { |
109 | 0 | } |
110 | | |
111 | | } |