From 6e04286cc21a0b7d56b8c32bbc6e4dd8b3fe2a90 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Wed, 11 Oct 2023 09:58:21 -0400 Subject: [PATCH] Default to 800x600 transparent image output --- src/fart/color.d | 2 ++ src/fart/main.d | 24 +++++++++++++++-- src/fart/png.d | 68 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/src/fart/color.d b/src/fart/color.d index 822e3c4..2a5c2a9 100644 --- a/src/fart/color.d +++ b/src/fart/color.d @@ -40,4 +40,6 @@ struct Color { return cast(ubyte)(0xFF * v); } + + public static immutable Color TRANSPARENT = Color(0, 0, 0, 0); } diff --git a/src/fart/main.d b/src/fart/main.d index 704b885..e3193da 100644 --- a/src/fart/main.d +++ b/src/fart/main.d @@ -1,7 +1,27 @@ -import fart.png; +module fart.main; +import fart.png; +import fart.color; + +/** + * Main program entry point. + * + * @param args + * Program arguments. + */ int main(string[] args) { - png_test(); + size_t width = 800; + size_t height = 600; + string output_filename = "out.png"; + Color[] pixels = []; + for (size_t y = 0; y < height; y++) + { + for (size_t x = 0; x < width; x++) + { + pixels ~= Color.TRANSPARENT; + } + } + write_png(output_filename, width, height, pixels); return 0; } diff --git a/src/fart/png.d b/src/fart/png.d index fd9f6a4..49c39ed 100644 --- a/src/fart/png.d +++ b/src/fart/png.d @@ -1,7 +1,6 @@ module fart.png; import std.zlib; -import std.math; import std.digest; import fart.bfile; @@ -9,8 +8,14 @@ import fart.crc32; import fart.hton; import fart.color; +/** + * PNG file header. + */ private immutable ubyte[] HEADER = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]; +/** + * PNG IHDR chunk. + */ struct IHDR { uint width; @@ -22,10 +27,10 @@ struct IHDR ubyte interlace; ubyte[0] end; - this(uint width, uint height) + this(size_t width, size_t height) { - this.width = htonl(width); - this.height = htonl(height); + this.width = htonl(cast(uint)width); + this.height = htonl(cast(uint)height); this.bit_depth = 8; this.color_type = 6; this.compression = 0; @@ -44,6 +49,9 @@ struct IHDR } } +/** + * PNG IDAT chunk. + */ struct IDAT { private const(ubyte)[] m_data; @@ -64,6 +72,9 @@ struct IDAT } } +/** + * PNG IEND chunk. + */ struct IEND { public const(void) * data() @@ -77,6 +88,16 @@ struct IEND } } +/** + * Write a PNG chunk to the output file. + * + * @param file + * Output file + * @param chunk_type + * Chunk type. + * @param chunk + * Chunk to write. + */ private void write_chunk(Chunk)(BFile file, string chunk_type, Chunk chunk) { size_t chunk_data_length = chunk.data_length(); @@ -89,11 +110,24 @@ private void write_chunk(Chunk)(BFile file, string chunk_type, Chunk chunk) file.writeObject(crc_be32); } -public void write_png(string filename, uint width, uint height, const(Color)[] data) +/** + * Write a PNG image from the given metadata and pixel data. + * + * @param filename + * Name of file to write. + * @param width + * Width of image. + * @param height + * Height of image. + * @param data + * Pixel color data. + */ +public void write_png(string filename, size_t width, size_t height, const(Color)[] data) { if (data.length != width * height) return; + /* Convert Color values to 32-bit RGBA values. */ ubyte[] pixel_data; size_t data_index; for (size_t y = 0; y < height; y++) @@ -105,30 +139,20 @@ public void write_png(string filename, uint width, uint height, const(Color)[] d pixel_data ~= data[data_index++].rgba32(); } } + + /* Open output file. */ BFile file = BFile(filename); + /* Write PNG header. */ file.write(HEADER); + /* Write IHDR chunk. */ IHDR ihdr = IHDR(width, height); write_chunk(file, "IHDR", ihdr); + /* Write IDAT chunk. */ IDAT idat = IDAT(pixel_data); write_chunk(file, "IDAT", idat); + /* Write IEND chunk. */ IEND iend; write_chunk(file, "IEND", iend); + /* Close output file. */ file.close(); } - -void png_test() -{ - Color[] pixel_data = []; - for (size_t y = 0; y < 500; y++) - { - for (size_t x = 0; x < 500; x++) - { - ubyte r = cast(ubyte)(x / 2); - ubyte g = 0x80; - ubyte b = cast(ubyte)((500 - y) / 2); - ubyte a = cast(ubyte)((abs(cast(int)x - 250) + abs(cast(int)y - 250)) / 2); - pixel_data ~= Color(r / 255.0, g / 255.0, b / 255.0, a / 255.0); - } - } - write_png("out.png", 500, 500, pixel_data); -}