Selaa lähdekoodia

LibGfx+Userland: Make PNGWriter::encode() return ErrorOr<ByteBuffer>

This is a first step towards handling PNG encoding failures instead of
just falling over and crashing the program.

This initial step will cause encode() to return an error if the final
ByteBuffer copy fails to allocate. There are more potential failures
that will be surfaced by subsequent commits.

Two FIXMEs were killed in the making of this patch. :^)
Andreas Kling 2 vuotta sitten
vanhempi
commit
d88c7fee32

+ 1 - 1
Userland/Applications/Browser/BrowserWindow.cpp

@@ -744,7 +744,7 @@ ErrorOr<void> BrowserWindow::take_screenshot(ScreenshotType type)
     LexicalPath path { Core::StandardPaths::downloads_directory() };
     path = path.append(Core::DateTime::now().to_deprecated_string("screenshot-%Y-%m-%d-%H-%M-%S.png"sv));
 
-    auto encoded = Gfx::PNGWriter::encode(*bitmap.bitmap());
+    auto encoded = TRY(Gfx::PNGWriter::encode(*bitmap.bitmap()));
 
     auto screenshot_file = TRY(Core::Stream::File::open(path.string(), Core::Stream::OpenMode::Write));
     TRY(screenshot_file->write(encoded));

+ 1 - 1
Userland/Applications/PixelPaint/Image.cpp

@@ -193,7 +193,7 @@ ErrorOr<void> Image::export_png_to_file(Core::File& file, bool preserve_alpha_ch
     auto bitmap_format = preserve_alpha_channel ? Gfx::BitmapFormat::BGRA8888 : Gfx::BitmapFormat::BGRx8888;
     auto bitmap = TRY(try_compose_bitmap(bitmap_format));
 
-    auto encoded_data = Gfx::PNGWriter::encode(*bitmap);
+    auto encoded_data = TRY(Gfx::PNGWriter::encode(*bitmap));
     if (!file.write(encoded_data.data(), encoded_data.size()))
         return Error::from_errno(file.error());
 

+ 1 - 1
Userland/Demos/Mandelbrot/Mandelbrot.cpp

@@ -377,7 +377,7 @@ ErrorOr<void> Mandelbrot::export_image(DeprecatedString const& export_path, Imag
         break;
     }
     case ImageType::PNG:
-        encoded_data = Gfx::PNGWriter::encode(m_set.bitmap());
+        encoded_data = TRY(Gfx::PNGWriter::encode(m_set.bitmap()));
         break;
     case ImageType::QOI:
         encoded_data = Gfx::QOIWriter::encode(m_set.bitmap());

+ 2 - 3
Userland/Libraries/LibGfx/PNGWriter.cpp

@@ -261,15 +261,14 @@ void PNGWriter::add_IDAT_chunk(Gfx::Bitmap const& bitmap)
     add_chunk(png_chunk);
 }
 
-ByteBuffer PNGWriter::encode(Gfx::Bitmap const& bitmap)
+ErrorOr<ByteBuffer> PNGWriter::encode(Gfx::Bitmap const& bitmap)
 {
     PNGWriter writer;
     writer.add_png_header();
     writer.add_IHDR_chunk(bitmap.width(), bitmap.height(), 8, PNG::ColorType::TruecolorWithAlpha, 0, 0, 0);
     writer.add_IDAT_chunk(bitmap);
     writer.add_IEND_chunk();
-    // FIXME: Handle OOM failure.
-    return ByteBuffer::copy(writer.m_data).release_value_but_fixme_should_propagate_errors();
+    return ByteBuffer::copy(writer.m_data);
 }
 
 }

+ 1 - 1
Userland/Libraries/LibGfx/PNGWriter.h

@@ -17,7 +17,7 @@ class PNGChunk;
 
 class PNGWriter {
 public:
-    static ByteBuffer encode(Gfx::Bitmap const&);
+    static ErrorOr<ByteBuffer> encode(Gfx::Bitmap const&);
 
 private:
     PNGWriter() = default;

+ 6 - 2
Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp

@@ -176,8 +176,12 @@ DeprecatedString HTMLCanvasElement::to_data_url(DeprecatedString const& type, [[
         return {};
     if (type != "image/png")
         return {};
-    auto encoded_bitmap = Gfx::PNGWriter::encode(*m_bitmap);
-    return AK::URL::create_with_data(type, encode_base64(encoded_bitmap), true).to_deprecated_string();
+    auto encoded_bitmap_or_error = Gfx::PNGWriter::encode(*m_bitmap);
+    if (encoded_bitmap_or_error.is_error()) {
+        dbgln("Gfx::PNGWriter failed to encode the HTMLCanvasElement: {}", encoded_bitmap_or_error.error());
+        return {};
+    }
+    return AK::URL::create_with_data(type, encode_base64(encoded_bitmap_or_error.value()), true).to_deprecated_string();
 }
 
 void HTMLCanvasElement::present()

+ 1 - 1
Userland/Services/SpiceAgent/SpiceAgent.cpp

@@ -79,7 +79,7 @@ void SpiceAgent::on_message_received()
         ReadonlyBytes bytes;
         if (mime == "image/x-serenityos") {
             auto bitmap = m_clipboard_connection.get_bitmap();
-            backing_byte_buffer = Gfx::PNGWriter::encode(*bitmap);
+            backing_byte_buffer = MUST(Gfx::PNGWriter::encode(*bitmap));
             bytes = backing_byte_buffer;
         } else {
             auto data = clipboard.data();

+ 1 - 1
Userland/Utilities/headless-browser.cpp

@@ -703,7 +703,7 @@ static void load_page_for_screenshot_and_exit(HeadlessBrowserPageClient& page_cl
 
             page_client.paint(output_rect, output_bitmap);
 
-            auto image_buffer = Gfx::PNGWriter::encode(output_bitmap);
+            auto image_buffer = MUST(Gfx::PNGWriter::encode(output_bitmap));
             MUST(output_file->write(image_buffer.bytes()));
 
             exit(0);

+ 4 - 2
Userland/Utilities/shot.cpp

@@ -151,11 +151,13 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
         return 0;
     }
 
-    auto encoded_bitmap = Gfx::PNGWriter::encode(*bitmap);
-    if (encoded_bitmap.is_empty()) {
+    auto encoded_bitmap_or_error = Gfx::PNGWriter::encode(*bitmap);
+    if (encoded_bitmap_or_error.is_error()) {
         warnln("Failed to encode PNG");
         return 1;
     }
+    auto encoded_bitmap = encoded_bitmap_or_error.release_value();
+
     if (edit_image)
         output_path = Core::DateTime::now().to_deprecated_string("/tmp/screenshot-%Y-%m-%d-%H-%M-%S.png"sv);