Browse Source

PixelPaint: Display an error message if exporting to PNG/BMP fails

Andreas Kling 4 năm trước cách đây
mục cha
commit
91100f2f94

+ 37 - 15
Userland/Applications/PixelPaint/Image.cpp

@@ -55,7 +55,7 @@ Image::Image(Gfx::IntSize const& size)
 {
 }
 
-void Image::paint_into(GUI::Painter& painter, Gfx::IntRect const& dest_rect)
+void Image::paint_into(GUI::Painter& painter, Gfx::IntRect const& dest_rect) const
 {
     float scale = (float)dest_rect.width() / (float)rect().width();
     Gfx::PainterStateSaver saver(painter);
@@ -188,30 +188,52 @@ Result<void, String> Image::write_to_file(const String& file_path) const
     return {};
 }
 
-void Image::export_bmp(String const& file_path)
+RefPtr<Gfx::Bitmap> Image::try_compose_bitmap() const
 {
     auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, m_size);
+    if (!bitmap)
+        return nullptr;
     GUI::Painter painter(*bitmap);
     paint_into(painter, { 0, 0, m_size.width(), m_size.height() });
+    return bitmap;
+}
+
+Result<void, String> Image::export_bmp_to_file(String const& file_path)
+{
+    auto file_or_error = Core::File::open(file_path, (Core::OpenMode)(Core::OpenMode::WriteOnly | Core::OpenMode::Truncate));
+    if (file_or_error.is_error())
+        return file_or_error.error();
+
+    auto bitmap = try_compose_bitmap();
+    if (!bitmap)
+        return String { "Failed to allocate bitmap for encoding"sv };
 
     Gfx::BMPWriter dumper;
-    auto bmp = dumper.dump(bitmap);
-    auto file = fopen(file_path.characters(), "wb");
-    fwrite(bmp.data(), sizeof(u8), bmp.size(), file);
-    fclose(file);
+    auto encoded_data = dumper.dump(bitmap);
+
+    auto& file = *file_or_error.value();
+    if (!file.write(encoded_data.data(), encoded_data.size()))
+        return String { "Failed to write encoded BMP data to file"sv };
+
+    return {};
 }
 
-void Image::export_png(String const& file_path)
+Result<void, String> Image::export_png_to_file(String const& file_path)
 {
-    auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, m_size);
-    VERIFY(bitmap);
-    GUI::Painter painter(*bitmap);
-    paint_into(painter, { 0, 0, m_size.width(), m_size.height() });
+    auto file_or_error = Core::File::open(file_path, (Core::OpenMode)(Core::OpenMode::WriteOnly | Core::OpenMode::Truncate));
+    if (file_or_error.is_error())
+        return file_or_error.error();
+
+    auto bitmap = try_compose_bitmap();
+    if (!bitmap)
+        return String { "Failed to allocate bitmap for encoding"sv };
 
-    auto png = Gfx::PNGWriter::encode(*bitmap);
-    auto file = fopen(file_path.characters(), "wb");
-    fwrite(png.data(), sizeof(u8), png.size(), file);
-    fclose(file);
+    auto encoded_data = Gfx::PNGWriter::encode(*bitmap);
+    auto& file = *file_or_error.value();
+    if (!file.write(encoded_data.data(), encoded_data.size()))
+        return String { "Failed to write encoded PNG data to file"sv };
+
+    return {};
 }
 
 void Image::add_layer(NonnullRefPtr<Layer> layer)

+ 6 - 3
Userland/Applications/PixelPaint/Image.h

@@ -41,6 +41,9 @@ public:
     static Result<NonnullRefPtr<Image>, String> try_create_from_file(String const& file_path);
     static RefPtr<Image> try_create_from_bitmap(NonnullRefPtr<Gfx::Bitmap>);
 
+    // This generates a new Bitmap with the final image (all layers composed according to their attributes.)
+    RefPtr<Gfx::Bitmap> try_compose_bitmap() const;
+
     size_t layer_count() const { return m_layers.size(); }
     Layer const& layer(size_t index) const { return m_layers.at(index); }
     Layer& layer(size_t index) { return m_layers.at(index); }
@@ -52,10 +55,10 @@ public:
     RefPtr<Image> take_snapshot() const;
     void restore_snapshot(Image const&);
 
-    void paint_into(GUI::Painter&, Gfx::IntRect const& dest_rect);
+    void paint_into(GUI::Painter&, Gfx::IntRect const& dest_rect) const;
     Result<void, String> write_to_file(String const& file_path) const;
-    void export_bmp(String const& file_path);
-    void export_png(String const& file_path);
+    Result<void, String> export_bmp_to_file(String const& file_path);
+    Result<void, String> export_png_to_file(String const& file_path);
 
     void move_layer_to_front(Layer&);
     void move_layer_to_back(Layer&);

+ 8 - 7
Userland/Applications/PixelPaint/main.cpp

@@ -138,10 +138,12 @@ int main(int argc, char** argv)
             "As &BMP", [&](auto&) {
                 if (!image_editor.image())
                     return;
-                Optional<String> save_path = GUI::FilePicker::get_save_filepath(window, "untitled", "bmp");
+                auto save_path = GUI::FilePicker::get_save_filepath(window, "untitled", "bmp");
                 if (!save_path.has_value())
                     return;
-                image_editor.image()->export_bmp(save_path.value());
+                auto result = image_editor.image()->export_bmp_to_file(save_path.value());
+                if (result.is_error())
+                    GUI::MessageBox::show_error(window, String::formatted("Export to BMP failed: {}", result.error()));
             },
             window));
     export_submenu.add_action(
@@ -149,13 +151,12 @@ int main(int argc, char** argv)
             "As &PNG", [&](auto&) {
                 if (!image_editor.image())
                     return;
-
-                Optional<String> save_path = GUI::FilePicker::get_save_filepath(window, "untitled", "png");
-
+                auto save_path = GUI::FilePicker::get_save_filepath(window, "untitled", "png");
                 if (!save_path.has_value())
                     return;
-
-                image_editor.image()->export_png(save_path.value());
+                auto result = image_editor.image()->export_bmp_to_file(save_path.value());
+                if (result.is_error())
+                    GUI::MessageBox::show_error(window, String::formatted("Export to PNG failed: {}", result.error()));
             },
             window));