1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-26 01:25:08 +00:00
serenity/Userland/Libraries/LibGfx/PNGShared.h
Karol Kosek b5420b8a9a LibGfx: Implement PNG filtering on write
Is it another great upgrade to our PNG encoder like in 9aafaec259?
Well, not really - it's not a 2x or 55x improvement like you saw there,
but still it saves something:

- a screenshot of a blank Serenity desktop dropped from about 45 KiB
  to 40 KiB.
- re-encoding NASA photo of the Earth to PNG again saves about 25%
  (16.5 MiB -> 12.3 MiB), compared to not using filters.

[1]: https://commons.wikimedia.org/wiki/File:The_Blue_Marble_(remastered).jpg
2022-07-10 15:01:07 +02:00

56 lines
1.2 KiB
C++

/*
* Copyright (c) 2022, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
namespace Gfx::PNG {
// https://www.w3.org/TR/PNG/#5PNG-file-signature
static constexpr Array<u8, 8> header = { 0x89, 'P', 'N', 'G', 13, 10, 26, 10 };
// https://www.w3.org/TR/PNG/#6Colour-values
enum class ColorType : u8 {
Greyscale = 0,
Truecolor = 2, // RGB
IndexedColor = 3,
GreyscaleWithAlpha = 4,
TruecolorWithAlpha = 6,
};
// https://www.w3.org/TR/PNG/#9Filter-types
enum class FilterType : u8 {
None,
Sub,
Up,
Average,
Paeth,
};
// https://www.w3.org/TR/PNG/#9Filter-type-4-Paeth
ALWAYS_INLINE u8 paeth_predictor(u8 a, u8 b, u8 c)
{
int p = a + b - c;
int pa = abs(p - a);
int pb = abs(p - b);
int pc = abs(p - c);
if (pa <= pb && pa <= pc)
return a;
if (pb <= pc)
return b;
return c;
}
ALWAYS_INLINE AK::SIMD::u8x4 paeth_predictor(AK::SIMD::u8x4 a, AK::SIMD::u8x4 b, AK::SIMD::u8x4 c)
{
return AK::SIMD::u8x4 {
paeth_predictor(a[0], b[0], c[0]),
paeth_predictor(a[1], b[1], c[1]),
paeth_predictor(a[2], b[2], c[2]),
paeth_predictor(a[3], b[3], c[3]),
};
}
};