Skip to content

Commit

Permalink
LibGfx: Improve PNG encoder API somewhat
Browse files Browse the repository at this point in the history
This is still far from ideal, but let's at least make it take a
Gfx::Bitmap const&.
  • Loading branch information
awesomekling committed Apr 19, 2021
1 parent 51fe25f commit 6793574
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 30 deletions.
4 changes: 2 additions & 2 deletions Userland/Applications/PixelPaint/Image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
42 changes: 21 additions & 21 deletions Userland/Libraries/LibGfx/PNGWriter.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2021, Pierre Hoffmeister
* Copyright (c) 2021, Andreas Kling <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand All @@ -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);
Expand All @@ -51,8 +53,8 @@ class NonCompressibleBlock {
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);
Expand All @@ -63,7 +65,7 @@ class NonCompressibleBlock {
u32 m_adler_s2 { 0 };
};

PNGChunk::PNGChunk(const String& type)
PNGChunk::PNGChunk(String type)
: m_type(move(type))
{
}
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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" };

Expand All @@ -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);
Expand All @@ -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);
}

}
12 changes: 7 additions & 5 deletions Userland/Libraries/LibGfx/PNGWriter.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2021, Pierre Hoffmeister
* Copyright (c) 2021, Andreas Kling <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand All @@ -26,24 +27,25 @@

#pragma once

#include <AK/String.h>
#include <AK/Vector.h>
#include <LibGfx/Bitmap.h>
#include <LibGfx/Forward.h>

namespace Gfx {

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();
};

Expand Down
3 changes: 1 addition & 2 deletions Userland/Utilities/shot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 6793574

Please sign in to comment.