1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 22:57:44 +00:00

LibGfx: Improve PNG encoder API somewhat

This is still far from ideal, but let's at least make it take a
Gfx::Bitmap const&.
This commit is contained in:
Andreas Kling 2021-04-19 23:43:04 +02:00
parent 51fe25fdbb
commit 6793574003
4 changed files with 31 additions and 30 deletions

View file

@ -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);

View file

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

View file

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

View file

@ -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;