arsd.apng

Support for animated png files.

Please note this interface is not exactly stable and may break with minimum notice.

Members

Classes

ApngAnimation
class ApngAnimation
Undocumented in source.
ApngFrame
class ApngFrame

Represents a single frame from the file, directly corresponding to the fcTL and fdAT data from the file.

Enums

APNG_BLEND_OP
enum APNG_BLEND_OP
APNG_DISPOSE_OP
enum APNG_DISPOSE_OP

Functions

getApngBytes
ubyte[] getApngBytes(ApngAnimation apng)
readApng
ApngAnimation readApng(ubyte[] data, bool strictApng)

Loads an apng file.

writeApngToData
void writeApngToData(ApngAnimation apng, void delegate(in ubyte[] data) sink)
writeApngToFile
void writeApngToFile(ApngAnimation apng, string filename)

Structs

AnimationControlChunk
struct AnimationControlChunk

acTL chunk direct representation

ApngRenderBuffer
struct ApngRenderBuffer
FrameControlChunk
struct FrameControlChunk

fcTL chunk direct representation

Examples

Demo creating one from scratch

import arsd.apng;

void main() {
	auto apng = new ApngAnimation(50, 50);

	auto frame = apng.addFrame(25, 25);
	frame.data[] = 255;

	frame = apng.addFrame(25, 25);
	frame.data[] = 255;
	frame.frameControlChunk.delay_num = 10;

	frame = apng.addFrame(25, 25);
	frame.data[] = 255;
	frame.frameControlChunk.x_offset = 25;
	frame.frameControlChunk.delay_num = 10;

	frame = apng.addFrame(25, 25);
	frame.data[] = 255;
	frame.frameControlChunk.y_offset = 25;
	frame.frameControlChunk.delay_num = 10;

	frame = apng.addFrame(25, 25);
	frame.data[] = 255;
	frame.frameControlChunk.x_offset = 25;
	frame.frameControlChunk.y_offset = 25;
	frame.frameControlChunk.delay_num = 10;


	writeApngToFile(apng, "/home/me/test.apng");
}

Demo reading and rendering

import arsd.simpledisplay;
import arsd.game;
import arsd.apng;

void main(string[] args) {
	import std.file;
	auto a = readApng(cast(ubyte[]) std.file.read(args[1]));

	auto window = create2dWindow("Animated PNG viewer", a.header.width, a.header.height);

	auto render = a.renderer();
	OpenGlTexture[] frames;
	int[] waits;
	foreach(frame; a.frames) {
		waits ~= render.nextFrame();
		// this would be the raw data for the frame
		//frames ~= new OpenGlTexture(frame.frameData.getAsTrueColorImage);
		// or the current rendered ersion
		frames ~= new OpenGlTexture(render.buffer);
	}

	int pos;
	int currentWait;

	void update() {
		currentWait += waits[pos];
		pos++;
		if(pos == frames.length)
			pos = 0;
	}

	window.redrawOpenGlScene = () {
		glClear(GL_COLOR_BUFFER_BIT);
		frames[pos].draw(0, 0);
	};

	auto tick = 50;
	window.eventLoop(tick, delegate() {
		currentWait -= tick;
		auto updateNeeded = currentWait <= 0;
		while(currentWait <= 0)
			update();
		if(updateNeeded)
			window.redrawOpenGlSceneNow();
	//},
	//(KeyEvent ev) {
	//if(ev.pressed)
	});

	// writeApngToFile(a, "/home/me/test.apng");
}

Meta

History

Originally written March 2019 with read support.

Render support added December 28, 2020.

Write support added February 27, 2021.

Suggestion Box / Bug Report