#pragma once
#include <array>
#include <cstdint>
#include <cstring>
#include <whiteout/common_types.h>
#include <whiteout/textures/texture.h>
#include "../../common/checksum.h"
namespace whiteout::textures::png {
static constexpr std::array<u8, 8> PNG_SIGNATURE = {137, 80, 78, 71, 13, 10, 26, 10};
static constexpr u32 CHUNK_IHDR = 0x49484452; static constexpr u32 CHUNK_PLTE = 0x504C5445; static constexpr u32 CHUNK_IDAT = 0x49444154; static constexpr u32 CHUNK_IEND = 0x49454E44; static constexpr u32 CHUNK_tRNS = 0x74524E53; static constexpr u32 CHUNK_sRGB = 0x73524742; static constexpr u32 CHUNK_gAMA = 0x67414D41;
static constexpr u32 CHUNK_acTL = 0x6163544C; static constexpr u32 CHUNK_fcTL = 0x6663544C; static constexpr u32 CHUNK_fdAT = 0x66644154;
static constexpr u8 DISPOSE_NONE = 0; static constexpr u8 DISPOSE_BACKGROUND = 1; static constexpr u8 DISPOSE_PREVIOUS = 2;
static constexpr u8 BLEND_SOURCE = 0; static constexpr u8 BLEND_OVER = 1;
static constexpr u8 COLOR_GRAYSCALE = 0;
static constexpr u8 COLOR_TRUECOLOR = 2;
static constexpr u8 COLOR_INDEXED = 3;
static constexpr u8 COLOR_GRAYSCALE_ALPHA = 4;
static constexpr u8 COLOR_TRUECOLOR_ALPHA = 6;
static constexpr u8 FILTER_NONE = 0;
static constexpr u8 FILTER_SUB = 1;
static constexpr u8 FILTER_UP = 2;
static constexpr u8 FILTER_AVERAGE = 3;
static constexpr u8 FILTER_PAETH = 4;
using ::whiteout::crc32;
inline u32 readU32BE(const u8* p) {
return (static_cast<u32>(p[0]) << 24) | (static_cast<u32>(p[1]) << 16) |
(static_cast<u32>(p[2]) << 8) | static_cast<u32>(p[3]);
}
inline u16 readU16BE(const u8* p) {
return static_cast<u16>((static_cast<u16>(p[0]) << 8) | p[1]);
}
inline void writeU32BE(u8* p, u32 value) {
p[0] = static_cast<u8>((value >> 24) & 0xFF);
p[1] = static_cast<u8>((value >> 16) & 0xFF);
p[2] = static_cast<u8>((value >> 8) & 0xFF);
p[3] = static_cast<u8>(value & 0xFF);
}
inline void writeU16BE(u8* p, u16 value) {
p[0] = static_cast<u8>((value >> 8) & 0xFF);
p[1] = static_cast<u8>(value & 0xFF);
}
struct FcTL {
u32 sequenceNumber = 0;
u32 width = 0;
u32 height = 0;
u32 xOffset = 0;
u32 yOffset = 0;
u16 delayNum = 0; u16 delayDen = 0; u8 disposeOp = 0; u8 blendOp = 0; };
inline FcTL readFcTL(const u8* p) {
FcTL f;
f.sequenceNumber = readU32BE(p + 0);
f.width = readU32BE(p + 4);
f.height = readU32BE(p + 8);
f.xOffset = readU32BE(p + 12);
f.yOffset = readU32BE(p + 16);
f.delayNum = readU16BE(p + 20);
f.delayDen = readU16BE(p + 22);
f.disposeOp = p[24];
f.blendOp = p[25];
return f;
}
inline u8 paethPredictor(u8 a, u8 b, u8 c) {
i32 p = static_cast<i32>(a) + static_cast<i32>(b) - static_cast<i32>(c);
i32 pa = std::abs(p - static_cast<i32>(a));
i32 pb = std::abs(p - static_cast<i32>(b));
i32 pc = std::abs(p - static_cast<i32>(c));
if (pa <= pb && pa <= pc)
return a;
if (pb <= pc)
return b;
return c;
}
}