| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2020-12-25 00:19:06 +01:00
										 |  |  |  |  * Copyright (c) 2020, Hüseyin Aslıtürk <asliturk@hotmail.com> | 
					
						
							| 
									
										
										
										
											2022-03-12 11:16:30 -07:00
										 |  |  |  |  * Copyright (c) 2020-2022, the SerenityOS developers. | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |  */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #pragma once
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-16 15:51:56 +01:00
										 |  |  |  | #include <AK/Debug.h>
 | 
					
						
							| 
									
										
										
										
											2022-12-04 18:02:33 +00:00
										 |  |  |  | #include <AK/DeprecatedString.h>
 | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | #include <AK/Endian.h>
 | 
					
						
							|  |  |  |  | #include <AK/ScopeGuard.h>
 | 
					
						
							| 
									
										
										
										
											2023-03-12 15:02:03 -04:00
										 |  |  |  | #include <AK/String.h>
 | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | #include <AK/StringBuilder.h>
 | 
					
						
							|  |  |  |  | #include <AK/Types.h>
 | 
					
						
							|  |  |  |  | #include <AK/Vector.h>
 | 
					
						
							| 
									
										
										
										
											2020-12-25 00:19:06 +01:00
										 |  |  |  | #include <LibGfx/Bitmap.h>
 | 
					
						
							|  |  |  |  | #include <LibGfx/Color.h>
 | 
					
						
							| 
									
										
										
										
											2023-03-21 14:58:06 -04:00
										 |  |  |  | #include <LibGfx/ImageFormats/ImageDecoder.h>
 | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | namespace Gfx { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static constexpr Color adjust_color(u16 max_val, Color color) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     color.set_red((color.red() * 255) / max_val); | 
					
						
							|  |  |  |  |     color.set_green((color.green() * 255) / max_val); | 
					
						
							|  |  |  |  |     color.set_blue((color.blue() * 255) / max_val); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     return color; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  | static inline ErrorOr<u16> read_number(SeekableStream& stream) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | { | 
					
						
							|  |  |  |  |     StringBuilder sb {}; | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |     u8 byte {}; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |     for (auto buffer = TRY(stream.read_some({ &byte, 1 })); !buffer.is_empty(); buffer = TRY(stream.read_some({ &byte, 1 }))) { | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |         if (byte == ' ' || byte == '\t' || byte == '\n' || byte == '\r') { | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |             TRY(stream.seek(-1, SeekMode::FromCurrentPosition)); | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |             break; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         sb.append(byte); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 15:02:03 -04:00
										 |  |  |  |     auto const maybe_value = TRY(sb.to_string()).to_number<u16>(); | 
					
						
							|  |  |  |  |     if (!maybe_value.has_value()) | 
					
						
							|  |  |  |  |         return Error::from_string_literal("Can't convert bytes to a number"); | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 15:02:03 -04:00
										 |  |  |  |     return *maybe_value; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | template<typename TContext> | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  | static ErrorOr<void> read_comment(TContext& context) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |     auto& stream = *context.stream; | 
					
						
							| 
									
										
										
										
											2023-03-12 20:58:55 -04:00
										 |  |  |  |     bool is_first_char = true; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |     u8 byte {}; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |     while ((byte = TRY(stream.template read_value<u8>()))) { | 
					
						
							| 
									
										
										
										
											2023-03-12 20:58:55 -04:00
										 |  |  |  |         if (is_first_char) { | 
					
						
							|  |  |  |  |             if (byte != '#') | 
					
						
							| 
									
										
										
										
											2023-03-12 20:59:42 -04:00
										 |  |  |  |                 return Error::from_string_literal("Can't read comment from stream"); | 
					
						
							| 
									
										
										
										
											2023-03-12 20:58:55 -04:00
										 |  |  |  |             is_first_char = false; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |         } else if (byte == '\t' || byte == '\n') { | 
					
						
							| 
									
										
										
										
											2023-03-12 20:58:55 -04:00
										 |  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |         } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 20:59:42 -04:00
										 |  |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | template<typename TContext> | 
					
						
							| 
									
										
										
										
											2023-03-12 22:48:24 -04:00
										 |  |  |  | static ErrorOr<void> read_magic_number(TContext& context) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-12 22:48:24 -04:00
										 |  |  |  |     if (context.state >= TContext::State::MagicNumber) | 
					
						
							|  |  |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 22:48:24 -04:00
										 |  |  |  |     if (TRY(context.stream->size()) < 2) { | 
					
						
							| 
									
										
										
										
											2022-03-12 11:16:30 -07:00
										 |  |  |  |         dbgln_if(PORTABLE_IMAGE_LOADER_DEBUG, "There is no enough data for {}", TContext::FormatDetails::image_type); | 
					
						
							| 
									
										
										
										
											2023-03-12 22:48:24 -04:00
										 |  |  |  |         return Error::from_string_literal("There is no enough data to read magic number."); | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |     Array<u8, 2> magic_number {}; | 
					
						
							| 
									
										
										
										
											2023-03-12 22:48:24 -04:00
										 |  |  |  |     TRY(context.stream->read_until_filled(Bytes { magic_number })); | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-12 11:16:30 -07:00
										 |  |  |  |     if (magic_number[0] == 'P' && magic_number[1] == TContext::FormatDetails::ascii_magic_number) { | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |         context.type = TContext::Type::ASCII; | 
					
						
							|  |  |  |  |         context.state = TContext::State::MagicNumber; | 
					
						
							| 
									
										
										
										
											2023-03-12 22:48:24 -04:00
										 |  |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-12 11:16:30 -07:00
										 |  |  |  |     if (magic_number[0] == 'P' && magic_number[1] == TContext::FormatDetails::binary_magic_number) { | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |         context.type = TContext::Type::RAWBITS; | 
					
						
							|  |  |  |  |         context.state = TContext::State::MagicNumber; | 
					
						
							| 
									
										
										
										
											2023-03-12 22:48:24 -04:00
										 |  |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-12 11:16:30 -07:00
										 |  |  |  |     dbgln_if(PORTABLE_IMAGE_LOADER_DEBUG, "Magic number is not valid for {}{}{}", magic_number[0], magic_number[1], TContext::FormatDetails::image_type); | 
					
						
							| 
									
										
										
										
											2023-03-12 22:48:24 -04:00
										 |  |  |  |     return Error::from_string_literal("Unable to recognize magic bytes"); | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | template<typename TContext> | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  | static ErrorOr<void> read_whitespace(TContext& context) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |     auto& stream = *context.stream; | 
					
						
							| 
									
										
										
										
											2023-03-12 16:05:12 -04:00
										 |  |  |  |     bool is_first_char = true; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |     while (true) { | 
					
						
							|  |  |  |  |         auto byte_or_error = stream.template read_value<u8>(); | 
					
						
							|  |  |  |  |         // Nothing went wrong if we reached eof while reading a comment.
 | 
					
						
							|  |  |  |  |         if (byte_or_error.is_error()) | 
					
						
							|  |  |  |  |             return {}; | 
					
						
							|  |  |  |  |         auto const byte = byte_or_error.value(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 16:05:12 -04:00
										 |  |  |  |         if (byte == '#') { | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |             stream.seek(-1, SeekMode::FromCurrentPosition).release_value_but_fixme_should_propagate_errors(); | 
					
						
							|  |  |  |  |             TRY(read_comment(context)); | 
					
						
							| 
									
										
										
										
											2023-03-12 16:05:12 -04:00
										 |  |  |  |             continue; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |         if (byte != ' ' && byte != '\t' && byte != '\n' && byte != '\r') { | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |             stream.seek(-1, SeekMode::FromCurrentPosition).release_value_but_fixme_should_propagate_errors(); | 
					
						
							| 
									
										
										
										
											2023-03-12 16:05:12 -04:00
										 |  |  |  |             if (is_first_char) | 
					
						
							|  |  |  |  |                 return Error::from_string_literal("Can't read whitespace from stream"); | 
					
						
							|  |  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-03-12 16:05:12 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |         if (is_first_char) | 
					
						
							|  |  |  |  |             is_first_char = false; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 16:05:12 -04:00
										 |  |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | template<typename TContext> | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  | static ErrorOr<void> read_width(TContext& context) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |     context.width = TRY(read_number(*context.stream)); | 
					
						
							| 
									
										
										
										
											2022-03-12 11:16:30 -07:00
										 |  |  |  |     context.state = TContext::State::Width; | 
					
						
							| 
									
										
										
										
											2023-03-12 16:08:46 -04:00
										 |  |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | template<typename TContext> | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  | static ErrorOr<void> read_height(TContext& context) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |     context.height = TRY(read_number(*context.stream)); | 
					
						
							| 
									
										
										
										
											2022-03-12 11:16:30 -07:00
										 |  |  |  |     context.state = TContext::State::Height; | 
					
						
							| 
									
										
										
										
											2023-03-12 16:08:46 -04:00
										 |  |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | template<typename TContext> | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  | static ErrorOr<void> read_max_val(TContext& context) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |     context.format_details.max_val = TRY(read_number(*context.stream)); | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-12 11:16:30 -07:00
										 |  |  |  |     if (context.format_details.max_val > 255) { | 
					
						
							|  |  |  |  |         dbgln_if(PORTABLE_IMAGE_LOADER_DEBUG, "We can't parse 2 byte color for {}", TContext::FormatDetails::image_type); | 
					
						
							|  |  |  |  |         context.state = TContext::State::Error; | 
					
						
							| 
									
										
										
										
											2023-03-12 16:08:46 -04:00
										 |  |  |  |         return Error::from_string_literal("Can't parse 2 byte color"); | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-12 11:16:30 -07:00
										 |  |  |  |     context.state = TContext::State::Maxval; | 
					
						
							| 
									
										
										
										
											2023-03-12 16:08:46 -04:00
										 |  |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | template<typename TContext> | 
					
						
							| 
									
										
										
										
											2023-03-12 22:55:47 -04:00
										 |  |  |  | static ErrorOr<void> create_bitmap(TContext& context) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-12 22:55:47 -04:00
										 |  |  |  |     context.bitmap = TRY(Bitmap::create(BitmapFormat::BGRx8888, { context.width, context.height })); | 
					
						
							|  |  |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | template<typename TContext> | 
					
						
							| 
									
										
										
										
											2022-04-01 20:58:27 +03:00
										 |  |  |  | static void set_pixels(TContext& context, Vector<Gfx::Color> const& color_data) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  | { | 
					
						
							|  |  |  |  |     size_t index = 0; | 
					
						
							| 
									
										
										
										
											2020-12-25 00:19:06 +01:00
										 |  |  |  |     for (size_t y = 0; y < context.height; ++y) { | 
					
						
							|  |  |  |  |         for (size_t x = 0; x < context.width; ++x) { | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |             context.bitmap->set_pixel(x, y, color_data.at(index)); | 
					
						
							|  |  |  |  |             index++; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | template<typename TContext> | 
					
						
							|  |  |  |  | static bool decode(TContext& context) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     if (context.state >= TContext::State::Decoded) | 
					
						
							|  |  |  |  |         return true; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     auto error_guard = ArmedScopeGuard([&] { | 
					
						
							|  |  |  |  |         context.state = TContext::State::Error; | 
					
						
							|  |  |  |  |     }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 22:48:24 -04:00
										 |  |  |  |     if (read_magic_number(context).is_error()) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |         return false; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |     if (read_whitespace(context).is_error()) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |         return false; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |     if (read_width(context).is_error()) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |         return false; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |     if (read_whitespace(context).is_error()) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |         return false; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |     if (read_height(context).is_error()) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |         return false; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-25 00:19:06 +01:00
										 |  |  |  |     if (context.width > maximum_width_for_decoded_images || context.height > maximum_height_for_decoded_images) { | 
					
						
							|  |  |  |  |         dbgln("This portable network image is too large for comfort: {}x{}", context.width, context.height); | 
					
						
							|  |  |  |  |         return false; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |     if (read_whitespace(context).is_error()) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |         return false; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-12 11:16:30 -07:00
										 |  |  |  |     if constexpr (requires { context.format_details.max_val; }) { | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |         if (read_max_val(context).is_error()) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |             return false; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 20:08:29 -04:00
										 |  |  |  |         if (read_whitespace(context).is_error()) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |             return false; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 22:55:47 -04:00
										 |  |  |  |     if (read_image_data(context).is_error()) | 
					
						
							| 
									
										
										
										
											2020-12-20 10:19:03 -07:00
										 |  |  |  |         return false; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     error_guard.disarm(); | 
					
						
							|  |  |  |  |     context.state = TContext::State::Decoded; | 
					
						
							|  |  |  |  |     return true; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | } |