mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 01:57:45 +00:00
LibGfx: Use ByteBuffer instead of Vector<u8> in PNGWriter
This is the first step towards reducing the number of copies in PNGWriter by switching to ByteBuffer as underlying storage.
This commit is contained in:
parent
d78a007b5d
commit
97859aaff1
1 changed files with 50 additions and 54 deletions
|
@ -5,6 +5,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/Concepts.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <LibCrypto/Checksum/CRC32.h>
|
#include <LibCrypto/Checksum/CRC32.h>
|
||||||
#include <LibGfx/Bitmap.h>
|
#include <LibGfx/Bitmap.h>
|
||||||
|
@ -15,16 +16,22 @@ namespace Gfx {
|
||||||
class PNGChunk {
|
class PNGChunk {
|
||||||
public:
|
public:
|
||||||
explicit PNGChunk(String);
|
explicit PNGChunk(String);
|
||||||
Vector<u8> const& data() const { return m_data; };
|
auto const& data() const { return m_data; };
|
||||||
String const& type() const { return m_type; };
|
String const& type() const { return m_type; };
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void add_as_big_endian(T);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void add_as_little_endian(T);
|
||||||
|
|
||||||
void add_u8(u8);
|
void add_u8(u8);
|
||||||
void add_u16_big(u16);
|
|
||||||
void add_u32_big(u32);
|
|
||||||
void add_u16_little(u16);
|
|
||||||
void add_u32_little(u32);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector<u8> m_data;
|
template<typename T>
|
||||||
|
requires(IsUnsigned<T>) void add(T);
|
||||||
|
|
||||||
|
ByteBuffer m_data;
|
||||||
String m_type;
|
String m_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,8 +48,8 @@ private:
|
||||||
void update_adler(u8);
|
void update_adler(u8);
|
||||||
bool full() { return m_non_compressible_data.size() == 65535; }
|
bool full() { return m_non_compressible_data.size() == 65535; }
|
||||||
Vector<u8> m_non_compressible_data;
|
Vector<u8> m_non_compressible_data;
|
||||||
u32 m_adler_s1 { 1 };
|
u16 m_adler_s1 { 1 };
|
||||||
u32 m_adler_s2 { 0 };
|
u16 m_adler_s2 { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
PNGChunk::PNGChunk(String type)
|
PNGChunk::PNGChunk(String type)
|
||||||
|
@ -50,37 +57,29 @@ PNGChunk::PNGChunk(String type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
requires(IsUnsigned<T>) void PNGChunk::add(T data)
|
||||||
|
{
|
||||||
|
m_data.append(&data, sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void PNGChunk::add_as_little_endian(T data)
|
||||||
|
{
|
||||||
|
auto data_out = AK::convert_between_host_and_little_endian(data);
|
||||||
|
add(data_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void PNGChunk::add_as_big_endian(T data)
|
||||||
|
{
|
||||||
|
auto data_out = AK::convert_between_host_and_big_endian(data);
|
||||||
|
add(data_out);
|
||||||
|
}
|
||||||
|
|
||||||
void PNGChunk::add_u8(u8 data)
|
void PNGChunk::add_u8(u8 data)
|
||||||
{
|
{
|
||||||
m_data.append(data);
|
add(data);
|
||||||
}
|
|
||||||
|
|
||||||
void PNGChunk::add_u16_little(u16 data)
|
|
||||||
{
|
|
||||||
m_data.append(data & 0xff);
|
|
||||||
m_data.append((data >> 8) & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PNGChunk::add_u32_little(u32 data)
|
|
||||||
{
|
|
||||||
m_data.append(data & 0xff);
|
|
||||||
m_data.append((data >> 8) & 0xff);
|
|
||||||
m_data.append((data >> 16) & 0xff);
|
|
||||||
m_data.append((data >> 24) & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PNGChunk::add_u32_big(u32 data)
|
|
||||||
{
|
|
||||||
m_data.append((data >> 24) & 0xff);
|
|
||||||
m_data.append((data >> 16) & 0xff);
|
|
||||||
m_data.append((data >> 8) & 0xff);
|
|
||||||
m_data.append(data & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PNGChunk::add_u16_big(u16 data)
|
|
||||||
{
|
|
||||||
m_data.append((data >> 8) & 0xff);
|
|
||||||
m_data.append(data & 0xff);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NonCompressibleBlock::add_byte_to_block(u8 data, PNGChunk& chunk)
|
void NonCompressibleBlock::add_byte_to_block(u8 data, PNGChunk& chunk)
|
||||||
|
@ -95,17 +94,13 @@ void NonCompressibleBlock::add_byte_to_block(u8 data, PNGChunk& chunk)
|
||||||
|
|
||||||
void NonCompressibleBlock::add_block_to_chunk(PNGChunk& png_chunk, bool last)
|
void NonCompressibleBlock::add_block_to_chunk(PNGChunk& png_chunk, bool last)
|
||||||
{
|
{
|
||||||
if (last) {
|
png_chunk.add_u8(last);
|
||||||
png_chunk.add_u8(1);
|
|
||||||
} else {
|
|
||||||
png_chunk.add_u8(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto len = m_non_compressible_data.size();
|
u16 len = m_non_compressible_data.size();
|
||||||
auto nlen = ~len;
|
u16 nlen = ~len;
|
||||||
|
|
||||||
png_chunk.add_u16_little(len);
|
png_chunk.add_as_little_endian(len);
|
||||||
png_chunk.add_u16_little(nlen);
|
png_chunk.add_as_little_endian(nlen);
|
||||||
|
|
||||||
for (auto non_compressed_byte : m_non_compressible_data) {
|
for (auto non_compressed_byte : m_non_compressible_data) {
|
||||||
png_chunk.add_u8(non_compressed_byte);
|
png_chunk.add_u8(non_compressed_byte);
|
||||||
|
@ -125,11 +120,12 @@ void NonCompressibleBlock::update_adler(u8 data)
|
||||||
|
|
||||||
void PNGWriter::add_chunk(PNGChunk const& png_chunk)
|
void PNGWriter::add_chunk(PNGChunk const& png_chunk)
|
||||||
{
|
{
|
||||||
Vector<u8> combined;
|
ByteBuffer combined;
|
||||||
for (auto character : png_chunk.type()) {
|
for (auto character : png_chunk.type()) {
|
||||||
combined.append(character);
|
combined.append(&character, sizeof(character));
|
||||||
}
|
}
|
||||||
combined.extend(png_chunk.data());
|
|
||||||
|
combined.append(png_chunk.data().data(), png_chunk.data().size());
|
||||||
|
|
||||||
auto crc = BigEndian(Crypto::Checksum::CRC32({ (const u8*)combined.data(), combined.size() }).digest());
|
auto crc = BigEndian(Crypto::Checksum::CRC32({ (const u8*)combined.data(), combined.size() }).digest());
|
||||||
auto data_len = BigEndian(png_chunk.data().size());
|
auto data_len = BigEndian(png_chunk.data().size());
|
||||||
|
@ -151,8 +147,8 @@ void PNGWriter::add_png_header()
|
||||||
void PNGWriter::add_IHDR_chunk(u32 width, u32 height, u8 bit_depth, u8 color_type, u8 compression_method, u8 filter_method, u8 interlace_method)
|
void PNGWriter::add_IHDR_chunk(u32 width, u32 height, u8 bit_depth, u8 color_type, u8 compression_method, u8 filter_method, u8 interlace_method)
|
||||||
{
|
{
|
||||||
PNGChunk png_chunk { "IHDR" };
|
PNGChunk png_chunk { "IHDR" };
|
||||||
png_chunk.add_u32_big(width);
|
png_chunk.add_as_big_endian(width);
|
||||||
png_chunk.add_u32_big(height);
|
png_chunk.add_as_big_endian(height);
|
||||||
png_chunk.add_u8(bit_depth);
|
png_chunk.add_u8(bit_depth);
|
||||||
png_chunk.add_u8(color_type);
|
png_chunk.add_u8(color_type);
|
||||||
png_chunk.add_u8(compression_method);
|
png_chunk.add_u8(compression_method);
|
||||||
|
@ -172,7 +168,7 @@ void PNGWriter::add_IDAT_chunk(Gfx::Bitmap const& bitmap)
|
||||||
PNGChunk png_chunk { "IDAT" };
|
PNGChunk png_chunk { "IDAT" };
|
||||||
|
|
||||||
u16 CMF_FLG = 0x81d;
|
u16 CMF_FLG = 0x81d;
|
||||||
png_chunk.add_u16_big(CMF_FLG);
|
png_chunk.add_as_big_endian(CMF_FLG);
|
||||||
|
|
||||||
NonCompressibleBlock non_compressible_block;
|
NonCompressibleBlock non_compressible_block;
|
||||||
|
|
||||||
|
@ -189,8 +185,8 @@ void PNGWriter::add_IDAT_chunk(Gfx::Bitmap const& bitmap)
|
||||||
}
|
}
|
||||||
non_compressible_block.finalize(png_chunk);
|
non_compressible_block.finalize(png_chunk);
|
||||||
|
|
||||||
png_chunk.add_u16_big(non_compressible_block.adler_s2());
|
png_chunk.add_as_big_endian(non_compressible_block.adler_s2());
|
||||||
png_chunk.add_u16_big(non_compressible_block.adler_s1());
|
png_chunk.add_as_big_endian(non_compressible_block.adler_s1());
|
||||||
|
|
||||||
add_chunk(png_chunk);
|
add_chunk(png_chunk);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue