using System.IO.Compression; namespace AgentWikiUi.Tests; /// Scrive PNG minimali (colore pieno) senza dipendere da Avalonia. static class PngFactory { public static byte[] Create(int width, int height) { var raw = new byte[height * (1 + width * 3)]; for (var y = 0; y < height; y++) for (var x = 0; x < width; x++) raw[y * (1 + width * 3) + 1 + x * 3] = 200; // filtro 0 per riga, canale rosso using var ms = new MemoryStream(); ms.Write([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]); var ihdr = new byte[13]; WriteInt(ihdr, 0, width); WriteInt(ihdr, 4, height); ihdr[8] = 8; ihdr[9] = 2; // 8 bit, RGB Chunk(ms, "IHDR", ihdr); using (var z = new MemoryStream()) { using (var zs = new ZLibStream(z, CompressionLevel.Fastest, leaveOpen: true)) zs.Write(raw); Chunk(ms, "IDAT", z.ToArray()); } Chunk(ms, "IEND", []); return ms.ToArray(); } static void WriteInt(byte[] b, int at, int v) { b[at] = (byte)(v >> 24); b[at + 1] = (byte)(v >> 16); b[at + 2] = (byte)(v >> 8); b[at + 3] = (byte)v; } static void Chunk(Stream s, string type, byte[] data) { var len = new byte[4]; WriteInt(len, 0, data.Length); s.Write(len); var body = new byte[4 + data.Length]; for (var i = 0; i < 4; i++) body[i] = (byte)type[i]; data.CopyTo(body, 4); s.Write(body); var crc = new byte[4]; WriteInt(crc, 0, (int)Crc32(body)); s.Write(crc); } static uint Crc32(byte[] data) { var crc = 0xFFFFFFFFu; foreach (var b in data) { crc ^= b; for (var k = 0; k < 8; k++) crc = (crc & 1) != 0 ? (crc >> 1) ^ 0xEDB88320u : crc >> 1; } return ~crc; } }