diff options
author | Nico Weber <thakis@chromium.org> | 2023-03-12 09:05:25 -0400 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2023-03-12 13:23:34 +0000 |
commit | 9b297c634f82479f3b6851b77f9af9e1486c4546 (patch) | |
tree | cb566f3d3fcb592a496ab562c3df4bd11165dbc9 /Userland | |
parent | b698d64ee9161ae107d2f8fd783b04efe0bb1f59 (diff) | |
download | serenity-9b297c634f82479f3b6851b77f9af9e1486c4546.zip |
LibGfx: Make QOIWriter use ErrorOr
In addition to it now handling allocation failures, the encode() API is
now consistent with PNGWriter.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Applications/PixelPaint/Image.cpp | 2 | ||||
-rw-r--r-- | Userland/Demos/Mandelbrot/Mandelbrot.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/QOIWriter.cpp | 87 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/QOIWriter.h | 19 | ||||
-rw-r--r-- | Userland/Utilities/image.cpp | 2 |
5 files changed, 61 insertions, 51 deletions
diff --git a/Userland/Applications/PixelPaint/Image.cpp b/Userland/Applications/PixelPaint/Image.cpp index ab53535f73..c6beb8f60f 100644 --- a/Userland/Applications/PixelPaint/Image.cpp +++ b/Userland/Applications/PixelPaint/Image.cpp @@ -196,7 +196,7 @@ ErrorOr<void> Image::export_qoi_to_file(NonnullOwnPtr<Stream> stream) const { auto bitmap = TRY(compose_bitmap(Gfx::BitmapFormat::BGRA8888)); - auto encoded_data = Gfx::QOIWriter::encode(bitmap); + auto encoded_data = TRY(Gfx::QOIWriter::encode(bitmap)); TRY(stream->write_entire_buffer(encoded_data)); return {}; } diff --git a/Userland/Demos/Mandelbrot/Mandelbrot.cpp b/Userland/Demos/Mandelbrot/Mandelbrot.cpp index cf65d28df6..c975bbaf9c 100644 --- a/Userland/Demos/Mandelbrot/Mandelbrot.cpp +++ b/Userland/Demos/Mandelbrot/Mandelbrot.cpp @@ -380,7 +380,7 @@ ErrorOr<void> Mandelbrot::export_image(DeprecatedString const& export_path, Imag encoded_data = TRY(Gfx::PNGWriter::encode(m_set.bitmap())); break; case ImageType::QOI: - encoded_data = Gfx::QOIWriter::encode(m_set.bitmap()); + encoded_data = TRY(Gfx::QOIWriter::encode(m_set.bitmap())); break; default: VERIFY_NOT_REACHED(); diff --git a/Userland/Libraries/LibGfx/QOIWriter.cpp b/Userland/Libraries/LibGfx/QOIWriter.cpp index 6bedd443c2..4abd119dd4 100644 --- a/Userland/Libraries/LibGfx/QOIWriter.cpp +++ b/Userland/Libraries/LibGfx/QOIWriter.cpp @@ -23,10 +23,10 @@ enum class Channels { RGBA, }; -ByteBuffer QOIWriter::encode(Bitmap const& bitmap) +ErrorOr<ByteBuffer> QOIWriter::encode(Bitmap const& bitmap) { QOIWriter writer; - writer.add_header(bitmap.width(), bitmap.height(), Channels::RGBA, Colorspace::sRGB); + TRY(writer.add_header(bitmap.width(), bitmap.height(), Channels::RGBA, Colorspace::sRGB)); Color previous_pixel = { 0, 0, 0, 255 }; @@ -49,7 +49,7 @@ ByteBuffer QOIWriter::encode(Bitmap const& bitmap) // If the run reaches a maximum length of 62 or if this is the last pixel then create the chunk. if (run_length == 62 || (y == bitmap.height() - 1 && x == bitmap.width() - 1)) { - writer.add_run_chunk(run_length); + TRY(writer.add_run_chunk(run_length)); creating_run = false; } @@ -58,7 +58,7 @@ ByteBuffer QOIWriter::encode(Bitmap const& bitmap) // Run ended with the previous pixel. Create a chunk for it and continue processing this pixel. if (creating_run) { - writer.add_run_chunk(run_length); + TRY(writer.add_run_chunk(run_length)); creating_run = false; } @@ -66,7 +66,7 @@ ByteBuffer QOIWriter::encode(Bitmap const& bitmap) auto index = pixel_hash_function(pixel); auto& array_pixel = writer.running_array[index]; if (array_pixel == pixel) { - writer.add_index_chunk(index); + TRY(writer.add_index_chunk(index)); previous_pixel = pixel; continue; } @@ -84,19 +84,19 @@ ByteBuffer QOIWriter::encode(Bitmap const& bitmap) if (red_difference > -3 && red_difference < 2 && green_difference > -3 && green_difference < 2 && blue_difference > -3 && blue_difference < 2) { - writer.add_diff_chunk(red_difference, green_difference, blue_difference); + TRY(writer.add_diff_chunk(red_difference, green_difference, blue_difference)); previous_pixel = pixel; continue; } if (relative_red_difference > -9 && relative_red_difference < 8 && green_difference > -33 && green_difference < 32 && relative_blue_difference > -9 && relative_blue_difference < 8) { - writer.add_luma_chunk(relative_red_difference, green_difference, relative_blue_difference); + TRY(writer.add_luma_chunk(relative_red_difference, green_difference, relative_blue_difference)); previous_pixel = pixel; continue; } - writer.add_rgb_chunk(pixel.red(), pixel.green(), pixel.blue()); + TRY(writer.add_rgb_chunk(pixel.red(), pixel.green(), pixel.blue())); previous_pixel = pixel; continue; } @@ -104,66 +104,71 @@ ByteBuffer QOIWriter::encode(Bitmap const& bitmap) previous_pixel = pixel; // Write full color values. - writer.add_rgba_chunk(pixel.red(), pixel.green(), pixel.blue(), pixel.alpha()); + TRY(writer.add_rgba_chunk(pixel.red(), pixel.green(), pixel.blue(), pixel.alpha())); } } - writer.add_end_marker(); + TRY(writer.add_end_marker()); - return ByteBuffer::copy(writer.m_data).release_value_but_fixme_should_propagate_errors(); + return ByteBuffer::copy(writer.m_data); } -void QOIWriter::add_header(u32 width, u32 height, Channels channels = Channels::RGBA, Colorspace color_space = Colorspace::sRGB) +ErrorOr<void> QOIWriter::add_header(u32 width, u32 height, Channels channels = Channels::RGBA, Colorspace color_space = Colorspace::sRGB) { // FIXME: Handle RGB and all linear channels. if (channels == Channels::RGB || color_space == Colorspace::Linear) TODO(); - m_data.append(qoi_magic_bytes.data(), sizeof(qoi_magic_bytes)); + TRY(m_data.try_append(qoi_magic_bytes.data(), sizeof(qoi_magic_bytes))); auto big_endian_width = AK::convert_between_host_and_big_endian(width); - m_data.append(bit_cast<u8*>(&big_endian_width), sizeof(width)); + TRY(m_data.try_append(bit_cast<u8*>(&big_endian_width), sizeof(width))); auto big_endian_height = AK::convert_between_host_and_big_endian(height); - m_data.append(bit_cast<u8*>(&big_endian_height), sizeof(height)); + TRY(m_data.try_append(bit_cast<u8*>(&big_endian_height), sizeof(height))); // Number of channels: 3 = RGB, 4 = RGBA. - m_data.append(4); + TRY(m_data.try_append(4)); // Colorspace: 0 = sRGB, 1 = all linear channels. - m_data.append(color_space == Colorspace::sRGB ? 0 : 1); + TRY(m_data.try_append(color_space == Colorspace::sRGB ? 0 : 1)); + + return {}; } -void QOIWriter::add_rgb_chunk(u8 r, u8 g, u8 b) +ErrorOr<void> QOIWriter::add_rgb_chunk(u8 r, u8 g, u8 b) { constexpr static u8 rgb_tag = 0b1111'1110; - m_data.append(rgb_tag); - m_data.append(r); - m_data.append(g); - m_data.append(b); + TRY(m_data.try_append(rgb_tag)); + TRY(m_data.try_append(r)); + TRY(m_data.try_append(g)); + TRY(m_data.try_append(b)); + return {}; } -void QOIWriter::add_rgba_chunk(u8 r, u8 g, u8 b, u8 a) +ErrorOr<void> QOIWriter::add_rgba_chunk(u8 r, u8 g, u8 b, u8 a) { constexpr static u8 rgba_tag = 0b1111'1111; - m_data.append(rgba_tag); - m_data.append(r); - m_data.append(g); - m_data.append(b); - m_data.append(a); + TRY(m_data.try_append(rgba_tag)); + TRY(m_data.try_append(r)); + TRY(m_data.try_append(g)); + TRY(m_data.try_append(b)); + TRY(m_data.try_append(a)); + return {}; } -void QOIWriter::add_index_chunk(unsigned int index) +ErrorOr<void> QOIWriter::add_index_chunk(unsigned int index) { constexpr static u8 index_tag = 0b0000'0000; u8 chunk = index_tag | index; - m_data.append(chunk); + TRY(m_data.try_append(chunk)); + return {}; } -void QOIWriter::add_diff_chunk(i8 red_difference, i8 green_difference, i8 blue_difference) +ErrorOr<void> QOIWriter::add_diff_chunk(i8 red_difference, i8 green_difference, i8 blue_difference) { constexpr static u8 diff_tag = 0b0100'0000; @@ -173,10 +178,11 @@ void QOIWriter::add_diff_chunk(i8 red_difference, i8 green_difference, i8 blue_d u8 blue = blue_difference + bias; u8 chunk = diff_tag | (red << 4) | (green << 2) | blue; - m_data.append(chunk); + TRY(m_data.try_append(chunk)); + return {}; } -void QOIWriter::add_luma_chunk(i8 relative_red_difference, i8 green_difference, i8 relative_blue_difference) +ErrorOr<void> QOIWriter::add_luma_chunk(i8 relative_red_difference, i8 green_difference, i8 relative_blue_difference) { constexpr static u8 luma_tag = 0b1000'0000; u8 green_bias = 32; @@ -184,22 +190,25 @@ void QOIWriter::add_luma_chunk(i8 relative_red_difference, i8 green_difference, u8 chunk1 = luma_tag | (green_difference + green_bias); u8 chunk2 = ((relative_red_difference + red_blue_bias) << 4) | (relative_blue_difference + red_blue_bias); - m_data.append(chunk1); - m_data.append(chunk2); + TRY(m_data.try_append(chunk1)); + TRY(m_data.try_append(chunk2)); + return {}; } -void QOIWriter::add_run_chunk(unsigned run_length) +ErrorOr<void> QOIWriter::add_run_chunk(unsigned run_length) { constexpr static u8 run_tag = 0b1100'0000; int bias = -1; u8 chunk = run_tag | (run_length + bias); - m_data.append(chunk); + TRY(m_data.try_append(chunk)); + return {}; } -void QOIWriter::add_end_marker() +ErrorOr<void> QOIWriter::add_end_marker() { - m_data.append(qoi_end_marker.data(), sizeof(qoi_end_marker)); + TRY(m_data.try_append(qoi_end_marker.data(), sizeof(qoi_end_marker))); + return {}; } u32 QOIWriter::pixel_hash_function(Color pixel) diff --git a/Userland/Libraries/LibGfx/QOIWriter.h b/Userland/Libraries/LibGfx/QOIWriter.h index 3bb8b998f1..232aad5cd1 100644 --- a/Userland/Libraries/LibGfx/QOIWriter.h +++ b/Userland/Libraries/LibGfx/QOIWriter.h @@ -6,6 +6,7 @@ #pragma once +#include <AK/Error.h> #include <AK/Vector.h> #include <LibGfx/Bitmap.h> @@ -16,20 +17,20 @@ enum class Channels; class QOIWriter { public: - static ByteBuffer encode(Gfx::Bitmap const&); + static ErrorOr<ByteBuffer> encode(Gfx::Bitmap const&); private: QOIWriter() = default; Vector<u8> m_data; - void add_header(u32 width, u32 height, Channels, Colorspace); - void add_rgb_chunk(u8, u8, u8); - void add_rgba_chunk(u8, u8, u8, u8); - void add_index_chunk(u32 index); - void add_diff_chunk(i8 red_difference, i8 green_difference, i8 blue_difference); - void add_luma_chunk(i8 relative_red_difference, i8 green_difference, i8 relative_blue_difference); - void add_run_chunk(u32 run_length); - void add_end_marker(); + ErrorOr<void> add_header(u32 width, u32 height, Channels, Colorspace); + ErrorOr<void> add_rgb_chunk(u8, u8, u8); + ErrorOr<void> add_rgba_chunk(u8, u8, u8, u8); + ErrorOr<void> add_index_chunk(u32 index); + ErrorOr<void> add_diff_chunk(i8 red_difference, i8 green_difference, i8 blue_difference); + ErrorOr<void> add_luma_chunk(i8 relative_red_difference, i8 green_difference, i8 relative_blue_difference); + ErrorOr<void> add_run_chunk(u32 run_length); + ErrorOr<void> add_end_marker(); Array<Color, 64> running_array; static u32 pixel_hash_function(Color pixel); diff --git a/Userland/Utilities/image.cpp b/Userland/Utilities/image.cpp index fa105303b9..e53814f992 100644 --- a/Userland/Utilities/image.cpp +++ b/Userland/Utilities/image.cpp @@ -42,7 +42,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) } else if (out_path.ends_with(".png"sv, CaseSensitivity::CaseInsensitive)) { bytes = TRY(Gfx::PNGWriter::encode(*frame)); } else if (out_path.ends_with(".qoi"sv, CaseSensitivity::CaseInsensitive)) { - bytes = Gfx::QOIWriter::encode(*frame); + bytes = TRY(Gfx::QOIWriter::encode(*frame)); } else { warnln("can only write .bmp, .png, and .qoi"); return 1; |