| 
									
										
										
										
											2022-03-12 11:16:30 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2020, Hüseyin ASLITÜRK <asliturk@hotmail.com> | 
					
						
							|  |  |  |  * Copyright (c) 2022, the SerenityOS developers. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  | #include <AK/BufferedStream.h>
 | 
					
						
							|  |  |  | #include <AK/MemoryStream.h>
 | 
					
						
							| 
									
										
										
										
											2022-03-12 11:16:30 -07:00
										 |  |  | #include <AK/RefPtr.h>
 | 
					
						
							|  |  |  | #include <AK/StringView.h>
 | 
					
						
							|  |  |  | #include <AK/Types.h>
 | 
					
						
							|  |  |  | #include <LibGfx/Bitmap.h>
 | 
					
						
							| 
									
										
										
										
											2023-03-21 14:58:06 -04:00
										 |  |  | #include <LibGfx/ImageFormats/PortableImageLoaderCommon.h>
 | 
					
						
							| 
									
										
										
										
											2022-03-12 11:16:30 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace Gfx { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<class TFormatDetails> | 
					
						
							|  |  |  | struct PortableImageMapLoadingContext { | 
					
						
							|  |  |  |     using FormatDetails = TFormatDetails; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     enum class Type { | 
					
						
							|  |  |  |         Unknown, | 
					
						
							|  |  |  |         ASCII, | 
					
						
							|  |  |  |         RAWBITS | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     enum class State { | 
					
						
							|  |  |  |         NotDecoded = 0, | 
					
						
							|  |  |  |         Error, | 
					
						
							|  |  |  |         MagicNumber, | 
					
						
							|  |  |  |         Width, | 
					
						
							|  |  |  |         Height, | 
					
						
							|  |  |  |         Maxval, | 
					
						
							|  |  |  |         Bitmap, | 
					
						
							|  |  |  |         Decoded | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Type type { Type::Unknown }; | 
					
						
							|  |  |  |     State state { State::NotDecoded }; | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-12 11:16:30 -07:00
										 |  |  |     size_t width { 0 }; | 
					
						
							|  |  |  |     size_t height { 0 }; | 
					
						
							|  |  |  |     FormatDetails format_details {}; | 
					
						
							|  |  |  |     RefPtr<Gfx::Bitmap> bitmap; | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     NonnullOwnPtr<SeekableStream> stream; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PortableImageMapLoadingContext(NonnullOwnPtr<SeekableStream> stream) | 
					
						
							|  |  |  |         : stream(move(stream)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-03-12 11:16:30 -07:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-13 11:58:58 -06:00
										 |  |  | template<typename TContext> | 
					
						
							|  |  |  | class PortableImageDecoderPlugin final : public ImageDecoderPlugin { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2023-02-26 18:02:50 +00:00
										 |  |  |     static bool sniff(ReadonlyBytes); | 
					
						
							| 
									
										
										
										
											2023-01-20 10:13:14 +02:00
										 |  |  |     static ErrorOr<NonnullOwnPtr<ImageDecoderPlugin>> create(ReadonlyBytes); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-13 11:58:58 -06:00
										 |  |  |     virtual ~PortableImageDecoderPlugin() override = default; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual IntSize size() override; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-07 19:27:07 +02:00
										 |  |  |     virtual ErrorOr<void> initialize() override { return {}; } | 
					
						
							| 
									
										
										
										
											2022-03-13 11:58:58 -06:00
										 |  |  |     virtual bool is_animated() override; | 
					
						
							|  |  |  |     virtual size_t loop_count() override; | 
					
						
							|  |  |  |     virtual size_t frame_count() override; | 
					
						
							| 
									
										
										
										
											2023-04-07 20:41:22 -06:00
										 |  |  |     virtual size_t first_animated_frame_index() override; | 
					
						
							| 
									
										
										
										
											2023-07-02 22:20:06 +01:00
										 |  |  |     virtual ErrorOr<ImageFrameDescriptor> frame(size_t index, Optional<IntSize> ideal_size = {}) override; | 
					
						
							| 
									
										
										
										
											2023-01-26 07:23:59 -05:00
										 |  |  |     virtual ErrorOr<Optional<ReadonlyBytes>> icc_data() override; | 
					
						
							| 
									
										
										
										
											2022-03-13 11:58:58 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |     PortableImageDecoderPlugin(NonnullOwnPtr<SeekableStream> stream); | 
					
						
							| 
									
										
										
										
											2023-03-12 13:52:14 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-13 11:58:58 -06:00
										 |  |  |     OwnPtr<TContext> m_context; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<typename TContext> | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  | PortableImageDecoderPlugin<TContext>::PortableImageDecoderPlugin(NonnullOwnPtr<SeekableStream> stream) | 
					
						
							| 
									
										
										
										
											2022-03-13 11:58:58 -06:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |     m_context = make<TContext>(move(stream)); | 
					
						
							| 
									
										
										
										
											2022-03-13 11:58:58 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<typename TContext> | 
					
						
							|  |  |  | IntSize PortableImageDecoderPlugin<TContext>::size() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_context->state == TContext::State::Error) | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_context->state < TContext::State::Decoded) { | 
					
						
							| 
									
										
										
										
											2023-03-12 23:03:08 -04:00
										 |  |  |         if (decode(*m_context).is_error()) { | 
					
						
							|  |  |  |             m_context->state = TContext::State::Error; | 
					
						
							|  |  |  |             // FIXME: We should propagate errors
 | 
					
						
							| 
									
										
										
										
											2022-03-13 11:58:58 -06:00
										 |  |  |             return {}; | 
					
						
							| 
									
										
										
										
											2023-03-12 23:03:08 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-03-13 11:58:58 -06:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return { m_context->width, m_context->height }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<typename TContext> | 
					
						
							| 
									
										
										
										
											2023-01-20 10:13:14 +02:00
										 |  |  | ErrorOr<NonnullOwnPtr<ImageDecoderPlugin>> PortableImageDecoderPlugin<TContext>::create(ReadonlyBytes data) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |     auto stream = TRY(try_make<FixedMemoryStream>(data)); | 
					
						
							|  |  |  |     return adopt_nonnull_own_or_enomem(new (nothrow) PortableImageDecoderPlugin<TContext>(move(stream))); | 
					
						
							| 
									
										
										
										
											2023-01-20 10:13:14 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<typename TContext> | 
					
						
							| 
									
										
										
										
											2023-02-26 18:02:50 +00:00
										 |  |  | bool PortableImageDecoderPlugin<TContext>::sniff(ReadonlyBytes data) | 
					
						
							| 
									
										
										
										
											2023-01-20 10:13:14 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     using Context = TContext; | 
					
						
							|  |  |  |     if (data.size() < 2) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (data.data()[0] == 'P' && data.data()[1] == Context::FormatDetails::ascii_magic_number) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (data.data()[0] == 'P' && data.data()[1] == Context::FormatDetails::binary_magic_number) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2022-03-13 11:58:58 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<typename TContext> | 
					
						
							|  |  |  | bool PortableImageDecoderPlugin<TContext>::is_animated() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<typename TContext> | 
					
						
							|  |  |  | size_t PortableImageDecoderPlugin<TContext>::loop_count() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<typename TContext> | 
					
						
							|  |  |  | size_t PortableImageDecoderPlugin<TContext>::frame_count() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-07 20:41:22 -06:00
										 |  |  | template<typename TContext> | 
					
						
							|  |  |  | size_t PortableImageDecoderPlugin<TContext>::first_animated_frame_index() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-13 11:58:58 -06:00
										 |  |  | template<typename TContext> | 
					
						
							| 
									
										
										
										
											2023-07-02 22:20:06 +01:00
										 |  |  | ErrorOr<ImageFrameDescriptor> PortableImageDecoderPlugin<TContext>::frame(size_t index, Optional<IntSize>) | 
					
						
							| 
									
										
										
										
											2022-03-13 11:58:58 -06:00
										 |  |  | { | 
					
						
							|  |  |  |     if (index > 0) | 
					
						
							| 
									
										
										
										
											2022-07-11 17:57:32 +00:00
										 |  |  |         return Error::from_string_literal("PortableImageDecoderPlugin: Invalid frame index"); | 
					
						
							| 
									
										
										
										
											2022-03-13 11:58:58 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (m_context->state == TContext::State::Error) | 
					
						
							| 
									
										
										
										
											2022-07-11 17:57:32 +00:00
										 |  |  |         return Error::from_string_literal("PortableImageDecoderPlugin: Decoding failed"); | 
					
						
							| 
									
										
										
										
											2022-03-13 11:58:58 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (m_context->state < TContext::State::Decoded) { | 
					
						
							| 
									
										
										
										
											2023-03-12 23:03:08 -04:00
										 |  |  |         if (decode(*m_context).is_error()) { | 
					
						
							|  |  |  |             m_context->state = TContext::State::Error; | 
					
						
							| 
									
										
										
										
											2022-07-11 17:57:32 +00:00
										 |  |  |             return Error::from_string_literal("PortableImageDecoderPlugin: Decoding failed"); | 
					
						
							| 
									
										
										
										
											2023-03-12 23:03:08 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-03-13 11:58:58 -06:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     VERIFY(m_context->bitmap); | 
					
						
							|  |  |  |     return ImageFrameDescriptor { m_context->bitmap, 0 }; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-01-26 07:23:59 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | template<typename TContext> | 
					
						
							|  |  |  | ErrorOr<Optional<ReadonlyBytes>> PortableImageDecoderPlugin<TContext>::icc_data() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return OptionalNone {}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-12 11:16:30 -07:00
										 |  |  | } |