Add fart.png to write RGBA PNG images
This commit is contained in:
parent
5b449506cb
commit
e6c943aab4
@ -1,4 +1,7 @@
|
|||||||
|
import fart.png;
|
||||||
|
|
||||||
int main(string[] args)
|
int main(string[] args)
|
||||||
{
|
{
|
||||||
|
png_test();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
121
src/fart/png.d
Normal file
121
src/fart/png.d
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
module fart.png;
|
||||||
|
|
||||||
|
import std.zlib;
|
||||||
|
import std.math;
|
||||||
|
import std.digest;
|
||||||
|
|
||||||
|
import fart.bfile;
|
||||||
|
import fart.crc32;
|
||||||
|
import fart.hton;
|
||||||
|
|
||||||
|
private immutable ubyte[] HEADER = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
|
||||||
|
|
||||||
|
struct IHDR
|
||||||
|
{
|
||||||
|
uint width;
|
||||||
|
uint height;
|
||||||
|
ubyte bit_depth;
|
||||||
|
ubyte color_type;
|
||||||
|
ubyte compression;
|
||||||
|
ubyte filter;
|
||||||
|
ubyte interlace;
|
||||||
|
ubyte[0] end;
|
||||||
|
|
||||||
|
this(uint width, uint height)
|
||||||
|
{
|
||||||
|
this.width = htonl(width);
|
||||||
|
this.height = htonl(height);
|
||||||
|
this.bit_depth = 8;
|
||||||
|
this.color_type = 6;
|
||||||
|
this.compression = 0;
|
||||||
|
this.filter = 0;
|
||||||
|
this.interlace = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public const(void) * data()
|
||||||
|
{
|
||||||
|
return &this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public size_t data_length()
|
||||||
|
{
|
||||||
|
return end.offsetof;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IDAT
|
||||||
|
{
|
||||||
|
private const(ubyte)[] m_data;
|
||||||
|
|
||||||
|
this(ubyte[] data)
|
||||||
|
{
|
||||||
|
m_data = compress(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public const(void) * data()
|
||||||
|
{
|
||||||
|
return m_data.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public size_t data_length()
|
||||||
|
{
|
||||||
|
return m_data.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IEND
|
||||||
|
{
|
||||||
|
public const(void) * data()
|
||||||
|
{
|
||||||
|
return &this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public size_t data_length()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void write_chunk(Chunk)(BFile file, string chunk_type, Chunk chunk)
|
||||||
|
{
|
||||||
|
size_t chunk_data_length = chunk.data_length();
|
||||||
|
uint chunk_length_be32 = htonl(cast(uint)chunk_data_length);
|
||||||
|
file.writeObject(chunk_length_be32);
|
||||||
|
file.write(chunk_type);
|
||||||
|
const(ubyte)[] chunk_data = (cast(const(ubyte) *)chunk.data())[0..chunk_data_length];
|
||||||
|
file.write(chunk_data);
|
||||||
|
uint crc_be32 = htonl(crc32(chunk_type, chunk_data));
|
||||||
|
file.writeObject(crc_be32);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write_png(string filename, uint width, uint height, ubyte[] data)
|
||||||
|
{
|
||||||
|
BFile file = BFile(filename);
|
||||||
|
file.write(HEADER);
|
||||||
|
IHDR ihdr = IHDR(width, height);
|
||||||
|
write_chunk(file, "IHDR", ihdr);
|
||||||
|
IDAT idat = IDAT(data);
|
||||||
|
write_chunk(file, "IDAT", idat);
|
||||||
|
IEND iend;
|
||||||
|
write_chunk(file, "IEND", iend);
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void png_test()
|
||||||
|
{
|
||||||
|
ubyte[] pixel_data = [];
|
||||||
|
for (size_t y = 0; y < 500; y++)
|
||||||
|
{
|
||||||
|
/* Filter method 0 (None) */
|
||||||
|
pixel_data ~= [0];
|
||||||
|
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 ~= [r, g, b, a];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write_png("out.png", 500, 500, pixel_data);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user