Ver código fonte

LibGfx: Improve PNG encoder API somewhat

This is still far from ideal, but let's at least make it take a
Gfx::Bitmap const&.
Andreas Kling 4 anos atrás
pai
commit
6793574003

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

@@ -155,11 +155,11 @@ void Image::export_bmp(const String& file_path)
 void Image::export_png(const String& 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() });
 
-    Gfx::PNGWriter png_writer;
-    auto png = png_writer.write(bitmap);
+    auto png = Gfx::PNGWriter::encode(*bitmap);
     auto file = fopen(file_path.characters(), "wb");
     fwrite(png.data(), sizeof(u8), png.size(), file);
     fclose(file);

+ 21 - 21
Userland/Libraries/LibGfx/PNGWriter.cpp

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2021, Pierre Hoffmeister
+ * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -24,17 +25,18 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "PNGWriter.h"
 #include <AK/String.h>
 #include <LibCrypto/Checksum/CRC32.h>
+#include <LibGfx/Bitmap.h>
+#include <LibGfx/PNGWriter.h>
 
 namespace Gfx {
 
 class PNGChunk {
 public:
-    PNGChunk(const String&);
-    const Vector<u8>& data() const { return m_data; };
-    const String& type() const { return m_type; };
+    explicit PNGChunk(String);
+    Vector<u8> const& data() const { return m_data; };
+    String const& type() const { return m_type; };
     void add_u8(u8);
     void add_u16_big(u16);
     void add_u32_big(u32);
@@ -51,8 +53,8 @@ public:
     void finalize(PNGChunk&);
     void add_byte_to_block(u8 data, PNGChunk&);
 
-    u32 adler_s1() { return m_adler_s1; }
-    u32 adler_s2() { return m_adler_s2; }
+    u32 adler_s1() const { return m_adler_s1; }
+    u32 adler_s2() const { return m_adler_s2; }
 
 private:
     void add_block_to_chunk(PNGChunk&, bool);
@@ -63,7 +65,7 @@ private:
     u32 m_adler_s2 { 0 };
 };
 
-PNGChunk::PNGChunk(const String& type)
+PNGChunk::PNGChunk(String type)
     : m_type(move(type))
 {
 }
@@ -141,7 +143,7 @@ void NonCompressibleBlock::update_adler(u8 data)
     m_adler_s2 = (m_adler_s2 + m_adler_s1) % 65521;
 }
 
-void PNGWriter::add_chunk(const PNGChunk& png_chunk)
+void PNGWriter::add_chunk(PNGChunk const& png_chunk)
 {
     Vector<u8> combined;
     for (auto character : png_chunk.type()) {
@@ -185,7 +187,7 @@ void PNGWriter::add_IEND_chunk()
     add_chunk(png_chunk);
 }
 
-void PNGWriter::add_IDAT_chunk(const RefPtr<Bitmap> bitmap)
+void PNGWriter::add_IDAT_chunk(Gfx::Bitmap const& bitmap)
 {
     PNGChunk png_chunk { "IDAT" };
 
@@ -194,11 +196,11 @@ void PNGWriter::add_IDAT_chunk(const RefPtr<Bitmap> bitmap)
 
     NonCompressibleBlock non_compressible_block;
 
-    for (int y = 0; y < bitmap->height(); ++y) {
+    for (int y = 0; y < bitmap.height(); ++y) {
         non_compressible_block.add_byte_to_block(0, png_chunk);
 
-        for (int x = 0; x < bitmap->width(); ++x) {
-            auto pixel = bitmap->get_pixel(x, y);
+        for (int x = 0; x < bitmap.width(); ++x) {
+            auto pixel = bitmap.get_pixel(x, y);
             non_compressible_block.add_byte_to_block(pixel.red(), png_chunk);
             non_compressible_block.add_byte_to_block(pixel.green(), png_chunk);
             non_compressible_block.add_byte_to_block(pixel.blue(), png_chunk);
@@ -213,16 +215,14 @@ void PNGWriter::add_IDAT_chunk(const RefPtr<Bitmap> bitmap)
     add_chunk(png_chunk);
 }
 
-ByteBuffer PNGWriter::write(const RefPtr<Bitmap> bitmap)
+ByteBuffer PNGWriter::encode(Gfx::Bitmap const& bitmap)
 {
-    add_png_header();
-    add_IHDR_chunk(bitmap->width(), bitmap->height(), 8, 6, 0, 0, 0);
-    add_IDAT_chunk(bitmap);
-    add_IEND_chunk();
-
-    ByteBuffer buf;
-    buf.append(m_data.data(), m_data.size());
-    return buf;
+    PNGWriter writer;
+    writer.add_png_header();
+    writer.add_IHDR_chunk(bitmap.width(), bitmap.height(), 8, 6, 0, 0, 0);
+    writer.add_IDAT_chunk(bitmap);
+    writer.add_IEND_chunk();
+    return ByteBuffer::copy(writer.m_data);
 }
 
 }

+ 7 - 5
Userland/Libraries/LibGfx/PNGWriter.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2021, Pierre Hoffmeister
+ * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,9 +27,8 @@
 
 #pragma once
 
-#include <AK/String.h>
 #include <AK/Vector.h>
-#include <LibGfx/Bitmap.h>
+#include <LibGfx/Forward.h>
 
 namespace Gfx {
 
@@ -36,14 +36,16 @@ class PNGChunk;
 
 class PNGWriter {
 public:
-    ByteBuffer write(const RefPtr<Bitmap>);
+    static ByteBuffer encode(Gfx::Bitmap const&);
 
 private:
+    PNGWriter() { }
+
     Vector<u8> m_data;
-    void add_chunk(const PNGChunk&);
+    void add_chunk(PNGChunk const&);
     void add_png_header();
     void add_IHDR_chunk(u32 width, u32 height, u8 bit_depth, u8 color_type, u8 compression_method, u8 filter_method, u8 interlace_method);
-    void add_IDAT_chunk(const RefPtr<Bitmap>);
+    void add_IDAT_chunk(Gfx::Bitmap const&);
     void add_IEND_chunk();
 };
 

+ 1 - 2
Userland/Utilities/shot.cpp

@@ -67,8 +67,7 @@ int main(int argc, char** argv)
         return 0;
     }
 
-    Gfx::PNGWriter writer;
-    auto encoded_bitmap = writer.write(bitmap);
+    auto encoded_bitmap = Gfx::PNGWriter::encode(*bitmap);
     if (encoded_bitmap.is_empty()) {
         warnln("Failed to encode PNG");
         return 1;