mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 21:57:43 +00:00
LibGfx: BMPLoader: Propagate errors properly
Use our normal error propagation mechanism instead of returning booleans
This commit is contained in:
parent
8455d58a44
commit
a6d710612f
1 changed files with 91 additions and 110 deletions
|
@ -8,7 +8,9 @@
|
|||
#include <AK/BuiltinWrappers.h>
|
||||
#include <AK/Debug.h>
|
||||
#include <AK/DeprecatedString.h>
|
||||
#include <AK/Error.h>
|
||||
#include <AK/Function.h>
|
||||
#include <AK/Try.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibGfx/BMPLoader.h>
|
||||
|
||||
|
@ -425,18 +427,18 @@ static bool set_dib_bitmasks(BMPLoadingContext& context, InputStreamer& streamer
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool decode_bmp_header(BMPLoadingContext& context)
|
||||
static ErrorOr<void> decode_bmp_header(BMPLoadingContext& context)
|
||||
{
|
||||
if (context.state == BMPLoadingContext::State::Error)
|
||||
return false;
|
||||
return Error::from_string_literal("Error before starting decode_bmp_header");
|
||||
|
||||
if (context.state >= BMPLoadingContext::State::HeaderDecoded)
|
||||
return true;
|
||||
return {};
|
||||
|
||||
if (!context.file_bytes || context.file_size < bmp_header_size) {
|
||||
dbgln_if(BMP_DEBUG, "Missing BMP header");
|
||||
context.state = BMPLoadingContext::State::Error;
|
||||
return false;
|
||||
return Error::from_string_literal("Missing BMP header");
|
||||
}
|
||||
|
||||
InputStreamer streamer(context.file_bytes, bmp_header_size);
|
||||
|
@ -445,7 +447,7 @@ static bool decode_bmp_header(BMPLoadingContext& context)
|
|||
if (header != 0x4d42) {
|
||||
dbgln_if(BMP_DEBUG, "BMP has invalid magic header number: {:#04x}", header);
|
||||
context.state = BMPLoadingContext::State::Error;
|
||||
return false;
|
||||
return Error::from_string_literal("BMP has invalid magic header number");
|
||||
}
|
||||
|
||||
// The reported size of the file in the header is actually not important
|
||||
|
@ -466,11 +468,11 @@ static bool decode_bmp_header(BMPLoadingContext& context)
|
|||
|
||||
if (context.data_offset >= context.file_size) {
|
||||
dbgln_if(BMP_DEBUG, "BMP data offset is beyond file end?!");
|
||||
return false;
|
||||
return Error::from_string_literal("BMP data offset is beyond file end");
|
||||
}
|
||||
|
||||
context.state = BMPLoadingContext::State::HeaderDecoded;
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
static bool decode_bmp_core_dib(BMPLoadingContext& context, InputStreamer& streamer)
|
||||
|
@ -744,35 +746,35 @@ static bool decode_bmp_v5_dib(BMPLoadingContext& context, InputStreamer& streame
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool decode_bmp_dib(BMPLoadingContext& context)
|
||||
static ErrorOr<void> decode_bmp_dib(BMPLoadingContext& context)
|
||||
{
|
||||
if (context.state == BMPLoadingContext::State::Error)
|
||||
return false;
|
||||
return Error::from_string_literal("Error before starting decode_bmp_dib");
|
||||
|
||||
if (context.state >= BMPLoadingContext::State::DIBDecoded)
|
||||
return true;
|
||||
return {};
|
||||
|
||||
if (!context.is_included_in_ico && context.state < BMPLoadingContext::State::HeaderDecoded && !decode_bmp_header(context))
|
||||
return false;
|
||||
if (!context.is_included_in_ico && context.state < BMPLoadingContext::State::HeaderDecoded)
|
||||
TRY(decode_bmp_header(context));
|
||||
|
||||
u8 header_size = context.is_included_in_ico ? 0 : bmp_header_size;
|
||||
|
||||
if (!context.is_included_in_ico && context.file_size < (u8)(header_size + 4))
|
||||
return false;
|
||||
return Error::from_string_literal("File size too short");
|
||||
|
||||
if (context.is_included_in_ico && context.file_size < 4)
|
||||
return false;
|
||||
return Error::from_string_literal("File size too short");
|
||||
|
||||
InputStreamer streamer(context.file_bytes + (context.is_included_in_ico ? 0 : header_size), 4);
|
||||
|
||||
u32 dib_size = streamer.read_u32();
|
||||
|
||||
if (context.file_size < header_size + dib_size)
|
||||
return false;
|
||||
return Error::from_string_literal("File size too short");
|
||||
|
||||
if (!context.is_included_in_ico && (context.data_offset < header_size + dib_size)) {
|
||||
dbgln("Shenanigans! BMP pixel data and header usually don't overlap.");
|
||||
return false;
|
||||
return Error::from_string_literal("BMP pixel data and header usually don't overlap");
|
||||
}
|
||||
|
||||
// NOTE: If this is a headless BMP (embedded on ICO files), then we can only infer the data_offset after we know the data table size.
|
||||
|
@ -843,7 +845,7 @@ static bool decode_bmp_dib(BMPLoadingContext& context)
|
|||
if (error) {
|
||||
dbgln("BMP has an invalid DIB");
|
||||
context.state = BMPLoadingContext::State::Error;
|
||||
return false;
|
||||
return Error::from_string_literal("BMP has an invalid DIB");
|
||||
}
|
||||
|
||||
// NOTE: If this is a headless BMP (included on ICOns), the data_offset is set based on the number_of_palette_colors found on the DIB header
|
||||
|
@ -860,23 +862,23 @@ static bool decode_bmp_dib(BMPLoadingContext& context)
|
|||
|
||||
context.state = BMPLoadingContext::State::DIBDecoded;
|
||||
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
static bool decode_bmp_color_table(BMPLoadingContext& context)
|
||||
static ErrorOr<void> decode_bmp_color_table(BMPLoadingContext& context)
|
||||
{
|
||||
if (context.state == BMPLoadingContext::State::Error)
|
||||
return false;
|
||||
return Error::from_string_literal("Error before starting decode_bmp_color_table");
|
||||
|
||||
if (context.state < BMPLoadingContext::State::DIBDecoded && !decode_bmp_dib(context))
|
||||
return false;
|
||||
if (context.state < BMPLoadingContext::State::DIBDecoded)
|
||||
TRY(decode_bmp_dib(context));
|
||||
|
||||
if (context.state >= BMPLoadingContext::State::ColorTableDecoded)
|
||||
return true;
|
||||
return {};
|
||||
|
||||
if (context.dib.core.bpp > 8) {
|
||||
context.state = BMPLoadingContext::State::ColorTableDecoded;
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto bytes_per_color = context.dib_type == DIBType::Core ? 3 : 4;
|
||||
|
@ -905,18 +907,18 @@ static bool decode_bmp_color_table(BMPLoadingContext& context)
|
|||
for (u32 i = 0; !streamer.at_end() && i < max_colors; ++i) {
|
||||
if (bytes_per_color == 4) {
|
||||
if (!streamer.has_u32())
|
||||
return false;
|
||||
return Error::from_string_literal("Cannot read 32 bits");
|
||||
context.color_table.append(streamer.read_u32());
|
||||
} else {
|
||||
if (!streamer.has_u24())
|
||||
return false;
|
||||
return Error::from_string_literal("Cannot read 24 bits");
|
||||
context.color_table.append(streamer.read_u24());
|
||||
}
|
||||
}
|
||||
|
||||
context.state = BMPLoadingContext::State::ColorTableDecoded;
|
||||
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
struct RLEState {
|
||||
|
@ -927,13 +929,13 @@ struct RLEState {
|
|||
};
|
||||
};
|
||||
|
||||
static bool uncompress_bmp_rle_data(BMPLoadingContext& context, ByteBuffer& buffer)
|
||||
static ErrorOr<void> uncompress_bmp_rle_data(BMPLoadingContext& context, ByteBuffer& buffer)
|
||||
{
|
||||
// RLE-compressed images cannot be stored top-down
|
||||
if (context.dib.core.height < 0) {
|
||||
dbgln_if(BMP_DEBUG, "BMP is top-down and RLE compressed");
|
||||
context.state = BMPLoadingContext::State::Error;
|
||||
return false;
|
||||
return Error::from_string_literal("BMP is top-down and RLE compressed");
|
||||
}
|
||||
|
||||
InputStreamer streamer(context.file_bytes + context.data_offset, context.file_size - context.data_offset);
|
||||
|
@ -958,20 +960,20 @@ static bool uncompress_bmp_rle_data(BMPLoadingContext& context, ByteBuffer& buff
|
|||
}
|
||||
if (buffer_size > 300 * MiB) {
|
||||
dbgln("Suspiciously large amount of RLE data");
|
||||
return false;
|
||||
return Error::from_string_literal("Suspiciously large amount of RLE data");
|
||||
}
|
||||
auto buffer_result = ByteBuffer::create_zeroed(buffer_size);
|
||||
if (buffer_result.is_error()) {
|
||||
dbgln("Not enough memory for buffer allocation");
|
||||
return false;
|
||||
return buffer_result.release_error();
|
||||
}
|
||||
buffer = buffer_result.release_value();
|
||||
|
||||
// Avoid as many if statements as possible by pulling out
|
||||
// compression-dependent actions into separate lambdas
|
||||
Function<u32()> get_buffer_index;
|
||||
Function<bool(u32, bool)> set_byte;
|
||||
Function<Optional<u32>()> read_byte;
|
||||
Function<ErrorOr<void>(u32, bool)> set_byte;
|
||||
Function<ErrorOr<u32>()> read_byte;
|
||||
|
||||
if (compression == Compression::RLE8) {
|
||||
get_buffer_index = [&]() -> u32 { return row * total_columns + column; };
|
||||
|
@ -982,7 +984,7 @@ static bool uncompress_bmp_rle_data(BMPLoadingContext& context, ByteBuffer& buff
|
|||
}
|
||||
|
||||
if (compression == Compression::RLE8) {
|
||||
set_byte = [&](u32 color, bool) -> bool {
|
||||
set_byte = [&](u32 color, bool) -> ErrorOr<void> {
|
||||
if (column >= total_columns) {
|
||||
column = 0;
|
||||
row++;
|
||||
|
@ -990,14 +992,14 @@ static bool uncompress_bmp_rle_data(BMPLoadingContext& context, ByteBuffer& buff
|
|||
auto index = get_buffer_index();
|
||||
if (index >= buffer.size()) {
|
||||
dbgln("BMP has badly-formatted RLE data");
|
||||
return false;
|
||||
return Error::from_string_literal("BMP has badly-formatted RLE data");
|
||||
}
|
||||
buffer[index] = color;
|
||||
column++;
|
||||
return true;
|
||||
return {};
|
||||
};
|
||||
} else if (compression == Compression::RLE24) {
|
||||
set_byte = [&](u32 color, bool) -> bool {
|
||||
set_byte = [&](u32 color, bool) -> ErrorOr<void> {
|
||||
if (column >= total_columns) {
|
||||
column = 0;
|
||||
row++;
|
||||
|
@ -1005,14 +1007,14 @@ static bool uncompress_bmp_rle_data(BMPLoadingContext& context, ByteBuffer& buff
|
|||
auto index = get_buffer_index();
|
||||
if (index + 3 >= buffer.size()) {
|
||||
dbgln("BMP has badly-formatted RLE data");
|
||||
return false;
|
||||
return Error::from_string_literal("BMP has badly-formatted RLE data");
|
||||
}
|
||||
((u32&)buffer[index]) = color;
|
||||
column++;
|
||||
return true;
|
||||
return {};
|
||||
};
|
||||
} else {
|
||||
set_byte = [&](u32 byte, bool rle4_set_second_nibble) -> bool {
|
||||
set_byte = [&](u32 byte, bool rle4_set_second_nibble) -> ErrorOr<void> {
|
||||
if (column >= total_columns) {
|
||||
column = 0;
|
||||
row++;
|
||||
|
@ -1021,7 +1023,7 @@ static bool uncompress_bmp_rle_data(BMPLoadingContext& context, ByteBuffer& buff
|
|||
u32 index = get_buffer_index();
|
||||
if (index >= buffer.size() || (rle4_set_second_nibble && index + 1 >= buffer.size())) {
|
||||
dbgln("BMP has badly-formatted RLE data");
|
||||
return false;
|
||||
return Error::from_string_literal("BMP has badly-formatted RLE data");
|
||||
}
|
||||
|
||||
if (column % 2) {
|
||||
|
@ -1040,23 +1042,23 @@ static bool uncompress_bmp_rle_data(BMPLoadingContext& context, ByteBuffer& buff
|
|||
}
|
||||
|
||||
column++;
|
||||
return true;
|
||||
return {};
|
||||
};
|
||||
}
|
||||
|
||||
if (compression == Compression::RLE24) {
|
||||
read_byte = [&]() -> Optional<u32> {
|
||||
read_byte = [&]() -> ErrorOr<u32> {
|
||||
if (!streamer.has_u24()) {
|
||||
dbgln("BMP has badly-formatted RLE data");
|
||||
return {};
|
||||
return Error::from_string_literal("BMP has badly-formatted RLE data");
|
||||
}
|
||||
return streamer.read_u24();
|
||||
};
|
||||
} else {
|
||||
read_byte = [&]() -> Optional<u32> {
|
||||
read_byte = [&]() -> ErrorOr<u32> {
|
||||
if (!streamer.has_u8()) {
|
||||
dbgln("BMP has badly-formatted RLE data");
|
||||
return {};
|
||||
return Error::from_string_literal("BMP has badly-formatted RLE data");
|
||||
}
|
||||
return streamer.read_u8();
|
||||
};
|
||||
|
@ -1068,7 +1070,7 @@ static bool uncompress_bmp_rle_data(BMPLoadingContext& context, ByteBuffer& buff
|
|||
switch (currently_consuming) {
|
||||
case RLEState::PixelCount:
|
||||
if (!streamer.has_u8())
|
||||
return false;
|
||||
return Error::from_string_literal("Cannot read 8 bits");
|
||||
byte = streamer.read_u8();
|
||||
if (!byte) {
|
||||
currently_consuming = RLEState::Meta;
|
||||
|
@ -1077,28 +1079,22 @@ static bool uncompress_bmp_rle_data(BMPLoadingContext& context, ByteBuffer& buff
|
|||
currently_consuming = RLEState::PixelValue;
|
||||
}
|
||||
break;
|
||||
case RLEState::PixelValue: {
|
||||
auto result = read_byte();
|
||||
if (!result.has_value())
|
||||
return false;
|
||||
byte = result.value();
|
||||
case RLEState::PixelValue:
|
||||
byte = TRY(read_byte());
|
||||
for (u16 i = 0; i < pixel_count; ++i) {
|
||||
if (compression != Compression::RLE4) {
|
||||
if (!set_byte(byte, true))
|
||||
return false;
|
||||
TRY(set_byte(byte, true));
|
||||
} else {
|
||||
if (!set_byte(byte, i != pixel_count - 1))
|
||||
return false;
|
||||
TRY(set_byte(byte, i != pixel_count - 1));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
currently_consuming = RLEState::PixelCount;
|
||||
break;
|
||||
}
|
||||
case RLEState::Meta:
|
||||
if (!streamer.has_u8())
|
||||
return false;
|
||||
return Error::from_string_literal("Cannot read 8 bits");
|
||||
byte = streamer.read_u8();
|
||||
if (!byte) {
|
||||
column = 0;
|
||||
|
@ -1107,13 +1103,13 @@ static bool uncompress_bmp_rle_data(BMPLoadingContext& context, ByteBuffer& buff
|
|||
continue;
|
||||
}
|
||||
if (byte == 1)
|
||||
return true;
|
||||
return {};
|
||||
if (byte == 2) {
|
||||
if (!streamer.has_u8())
|
||||
return false;
|
||||
return Error::from_string_literal("Cannot read 8 bits");
|
||||
u8 offset_x = streamer.read_u8();
|
||||
if (!streamer.has_u8())
|
||||
return false;
|
||||
return Error::from_string_literal("Cannot read 8 bits");
|
||||
u8 offset_y = streamer.read_u8();
|
||||
column += offset_x;
|
||||
if (column >= total_columns) {
|
||||
|
@ -1130,12 +1126,8 @@ static bool uncompress_bmp_rle_data(BMPLoadingContext& context, ByteBuffer& buff
|
|||
i16 i = byte;
|
||||
|
||||
while (i >= 1) {
|
||||
auto result = read_byte();
|
||||
if (!result.has_value())
|
||||
return false;
|
||||
byte = result.value();
|
||||
if (!set_byte(byte, i != 1))
|
||||
return false;
|
||||
byte = TRY(read_byte());
|
||||
TRY(set_byte(byte, i != 1));
|
||||
i--;
|
||||
if (compression == Compression::RLE4)
|
||||
i--;
|
||||
|
@ -1145,13 +1137,13 @@ static bool uncompress_bmp_rle_data(BMPLoadingContext& context, ByteBuffer& buff
|
|||
if (compression != Compression::RLE4) {
|
||||
if (pixel_count % 2) {
|
||||
if (!streamer.has_u8())
|
||||
return false;
|
||||
return Error::from_string_literal("Cannot read 8 bits");
|
||||
byte = streamer.read_u8();
|
||||
}
|
||||
} else {
|
||||
if (((pixel_count + 1) / 2) % 2) {
|
||||
if (!streamer.has_u8())
|
||||
return false;
|
||||
return Error::from_string_literal("Cannot read 8 bits");
|
||||
byte = streamer.read_u8();
|
||||
}
|
||||
}
|
||||
|
@ -1163,13 +1155,13 @@ static bool uncompress_bmp_rle_data(BMPLoadingContext& context, ByteBuffer& buff
|
|||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
static bool decode_bmp_pixel_data(BMPLoadingContext& context)
|
||||
static ErrorOr<void> decode_bmp_pixel_data(BMPLoadingContext& context)
|
||||
{
|
||||
if (context.state == BMPLoadingContext::State::Error)
|
||||
return false;
|
||||
return Error::from_string_literal("Error before starting decode_bmp_pixel_data");
|
||||
|
||||
if (context.state <= BMPLoadingContext::State::ColorTableDecoded && !decode_bmp_color_table(context))
|
||||
return false;
|
||||
if (context.state <= BMPLoadingContext::State::ColorTableDecoded)
|
||||
TRY(decode_bmp_color_table(context));
|
||||
|
||||
const u16 bits_per_pixel = context.dib.core.bpp;
|
||||
|
||||
|
@ -1207,52 +1199,45 @@ static bool decode_bmp_pixel_data(BMPLoadingContext& context)
|
|||
if (format == BitmapFormat::Invalid) {
|
||||
dbgln("BMP has invalid bpp of {}", bits_per_pixel);
|
||||
context.state = BMPLoadingContext::State::Error;
|
||||
return false;
|
||||
return Error::from_string_literal("BMP has invalid bpp");
|
||||
}
|
||||
|
||||
const u32 width = abs(context.dib.core.width);
|
||||
const u32 height = !context.is_included_in_ico ? context.dib.core.height : (context.dib.core.height / 2);
|
||||
|
||||
auto bitmap_or_error = Bitmap::try_create(format, { static_cast<int>(width), static_cast<int>(height) });
|
||||
if (bitmap_or_error.is_error()) {
|
||||
// FIXME: Propagate the *real* error.
|
||||
return false;
|
||||
}
|
||||
|
||||
context.bitmap = bitmap_or_error.release_value_but_fixme_should_propagate_errors();
|
||||
context.bitmap = TRY(Bitmap::try_create(format, { static_cast<int>(width), static_cast<int>(height) }));
|
||||
|
||||
ByteBuffer rle_buffer;
|
||||
ReadonlyBytes bytes { context.file_bytes + context.data_offset, context.file_size - context.data_offset };
|
||||
|
||||
if (context.dib.info.compression == Compression::RLE4 || context.dib.info.compression == Compression::RLE8
|
||||
|| context.dib.info.compression == Compression::RLE24) {
|
||||
if (!uncompress_bmp_rle_data(context, rle_buffer))
|
||||
return false;
|
||||
TRY(uncompress_bmp_rle_data(context, rle_buffer));
|
||||
bytes = rle_buffer.bytes();
|
||||
}
|
||||
|
||||
InputStreamer streamer(bytes.data(), bytes.size());
|
||||
|
||||
auto process_row_padding = [&](const u8 consumed) -> bool {
|
||||
auto process_row_padding = [&](const u8 consumed) -> ErrorOr<void> {
|
||||
// Calculate padding
|
||||
u8 remaining = consumed % 4;
|
||||
u8 bytes_to_drop = remaining == 0 ? 0 : 4 - remaining;
|
||||
|
||||
if (streamer.remaining() < bytes_to_drop)
|
||||
return false;
|
||||
return Error::from_string_literal("Not enough bytes available to drop");
|
||||
streamer.drop_bytes(bytes_to_drop);
|
||||
|
||||
return true;
|
||||
return {};
|
||||
};
|
||||
|
||||
auto process_row = [&](u32 row) -> bool {
|
||||
auto process_row = [&](u32 row) -> ErrorOr<void> {
|
||||
u32 space_remaining_before_consuming_row = streamer.remaining();
|
||||
|
||||
for (u32 column = 0; column < width;) {
|
||||
switch (bits_per_pixel) {
|
||||
case 1: {
|
||||
if (!streamer.has_u8())
|
||||
return false;
|
||||
return Error::from_string_literal("Cannot read 8 bits");
|
||||
u8 byte = streamer.read_u8();
|
||||
u8 mask = 8;
|
||||
while (column < width && mask > 0) {
|
||||
|
@ -1269,7 +1254,7 @@ static bool decode_bmp_pixel_data(BMPLoadingContext& context)
|
|||
}
|
||||
case 2: {
|
||||
if (!streamer.has_u8())
|
||||
return false;
|
||||
return Error::from_string_literal("Cannot read 8 bits");
|
||||
u8 byte = streamer.read_u8();
|
||||
u8 mask = 8;
|
||||
while (column < width && mask > 0) {
|
||||
|
@ -1286,7 +1271,7 @@ static bool decode_bmp_pixel_data(BMPLoadingContext& context)
|
|||
}
|
||||
case 4: {
|
||||
if (!streamer.has_u8()) {
|
||||
return false;
|
||||
return Error::from_string_literal("Cannot read 8 bits");
|
||||
}
|
||||
u8 byte = streamer.read_u8();
|
||||
|
||||
|
@ -1309,7 +1294,7 @@ static bool decode_bmp_pixel_data(BMPLoadingContext& context)
|
|||
}
|
||||
case 8: {
|
||||
if (!streamer.has_u8())
|
||||
return false;
|
||||
return Error::from_string_literal("Cannot read 8 bits");
|
||||
|
||||
u8 byte = streamer.read_u8();
|
||||
if (context.is_included_in_ico) {
|
||||
|
@ -1322,19 +1307,19 @@ static bool decode_bmp_pixel_data(BMPLoadingContext& context)
|
|||
}
|
||||
case 16: {
|
||||
if (!streamer.has_u16())
|
||||
return false;
|
||||
return Error::from_string_literal("Cannot read 16 bits");
|
||||
context.bitmap->scanline(row)[column++] = int_to_scaled_rgb(context, streamer.read_u16());
|
||||
break;
|
||||
}
|
||||
case 24: {
|
||||
if (!streamer.has_u24())
|
||||
return false;
|
||||
return Error::from_string_literal("Cannot read 24 bits");
|
||||
context.bitmap->scanline(row)[column++] = streamer.read_u24();
|
||||
break;
|
||||
}
|
||||
case 32:
|
||||
if (!streamer.has_u32())
|
||||
return false;
|
||||
return Error::from_string_literal("Cannot read 32 bits");
|
||||
if (context.dib.info.masks.is_empty()) {
|
||||
context.bitmap->scanline(row)[column++] = streamer.read_u32();
|
||||
} else {
|
||||
|
@ -1349,12 +1334,12 @@ static bool decode_bmp_pixel_data(BMPLoadingContext& context)
|
|||
return process_row_padding(consumed);
|
||||
};
|
||||
|
||||
auto process_mask_row = [&](u32 row) -> bool {
|
||||
auto process_mask_row = [&](u32 row) -> ErrorOr<void> {
|
||||
u32 space_remaining_before_consuming_row = streamer.remaining();
|
||||
|
||||
for (u32 column = 0; column < width;) {
|
||||
if (!streamer.has_u8())
|
||||
return false;
|
||||
return Error::from_string_literal("Cannot read 8 bits");
|
||||
|
||||
u8 byte = streamer.read_u8();
|
||||
u8 mask = 8;
|
||||
|
@ -1383,27 +1368,23 @@ static bool decode_bmp_pixel_data(BMPLoadingContext& context)
|
|||
if (context.dib.core.height < 0) {
|
||||
// BMP is stored top-down
|
||||
for (u32 row = 0; row < height; ++row) {
|
||||
if (!process_row(row))
|
||||
return false;
|
||||
TRY(process_row(row));
|
||||
}
|
||||
|
||||
if (context.is_included_in_ico) {
|
||||
for (u32 row = 0; row < height; ++row) {
|
||||
if (!process_mask_row(row))
|
||||
return false;
|
||||
TRY(process_mask_row(row));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// BMP is stored bottom-up
|
||||
for (i32 row = height - 1; row >= 0; --row) {
|
||||
if (!process_row(row))
|
||||
return false;
|
||||
TRY(process_row(row));
|
||||
}
|
||||
|
||||
if (context.is_included_in_ico) {
|
||||
for (i32 row = height - 1; row >= 0; --row) {
|
||||
if (!process_mask_row(row))
|
||||
return false;
|
||||
TRY(process_mask_row(row));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1416,7 +1397,7 @@ static bool decode_bmp_pixel_data(BMPLoadingContext& context)
|
|||
|
||||
context.state = BMPLoadingContext::State::PixelDataDecoded;
|
||||
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
BMPImageDecoderPlugin::BMPImageDecoderPlugin(u8 const* data, size_t data_size, bool is_included_in_ico)
|
||||
|
@ -1434,7 +1415,7 @@ IntSize BMPImageDecoderPlugin::size()
|
|||
if (m_context->state == BMPLoadingContext::State::Error)
|
||||
return {};
|
||||
|
||||
if (m_context->state < BMPLoadingContext::State::DIBDecoded && !decode_bmp_dib(*m_context))
|
||||
if (m_context->state < BMPLoadingContext::State::DIBDecoded && decode_bmp_dib(*m_context).is_error())
|
||||
return {};
|
||||
|
||||
return { m_context->dib.core.width, abs(m_context->dib.core.height) };
|
||||
|
@ -1455,12 +1436,12 @@ bool BMPImageDecoderPlugin::set_nonvolatile(bool& was_purged)
|
|||
|
||||
bool BMPImageDecoderPlugin::sniff()
|
||||
{
|
||||
return decode_bmp_header(*m_context);
|
||||
return !decode_bmp_header(*m_context).is_error();
|
||||
}
|
||||
|
||||
bool BMPImageDecoderPlugin::sniff_dib()
|
||||
{
|
||||
return decode_bmp_dib(*m_context);
|
||||
return !decode_bmp_dib(*m_context).is_error();
|
||||
}
|
||||
|
||||
bool BMPImageDecoderPlugin::is_animated()
|
||||
|
@ -1486,8 +1467,8 @@ ErrorOr<ImageFrameDescriptor> BMPImageDecoderPlugin::frame(size_t index)
|
|||
if (m_context->state == BMPLoadingContext::State::Error)
|
||||
return Error::from_string_literal("BMPImageDecoderPlugin: Decoding failed");
|
||||
|
||||
if (m_context->state < BMPLoadingContext::State::PixelDataDecoded && !decode_bmp_pixel_data(*m_context))
|
||||
return Error::from_string_literal("BMPImageDecoderPlugin: Decoding failed");
|
||||
if (m_context->state < BMPLoadingContext::State::PixelDataDecoded)
|
||||
TRY(decode_bmp_pixel_data(*m_context));
|
||||
|
||||
VERIFY(m_context->bitmap);
|
||||
return ImageFrameDescriptor { m_context->bitmap, 0 };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue