How to Reverse a Firefox Logo Animation by Manipulating APNG Files
This article explains how to reverse a clockwise‑rotating Firefox logo animation by understanding the APNG file format, identifying frame chunks, and rewriting the binary data with JavaScript to play the frames in reverse order.
Reverse a Firefox Logo Animation Using APNG
APNG is a widely supported web animation format, but its interactivity is limited. To reverse a Firefox logo that rotates clockwise, we first need to understand the APNG file structure.
Animation Principle
Frame animation works by preparing a series of static images (key frames) with slight differences and displaying them quickly; the eye perceives motion due to persistence of vision. The Firefox logo consists of 25 key frames, each shown for 50 ms.
APNG File Structure
A PNG file is a binary bitmap composed of a signature followed by a series of chunks. The basic layout is:
<code>|-- PNG Signature --|-- IHDR --|-- IDAT --|-- IEND --|</code>Each chunk has the format:
<code>|-4: length --|-4: type identifier --|N: data (length bytes) --|-4: CRC32 --|</code>APNG adds animation control chunks such as
acTL(animation control) and
fcTL(frame control) on top of the standard PNG structure.
acTL Chunk
The
acTLchunk specifies the total number of frames and the number of loops. For the Firefox logo the hex dump shows:
00 00 00 08– length (8 bytes)
61 63 54 4C– "acTL" identifier
00 00 00 19– 25 frames
00 00 00 00– infinite loops
fcTL Chunk
Each
fcTLchunk describes a single frame (width, height, offsets, delay, dispose and blend operations). The first frame looks like:
<code>(0) |----4: length----|----4: fcTL----|
(8) |----4: sequence----|----4: width----|
(16)|----4: height----|----4: x offset----|
(24)|----4: y offset----|--2: delay numerator--|--2: delay denominator--|
(32)|-1: dispose op-| -1: blend op-|----4: CRC32----|</code>Key fields are the sequence number (frame index) and the delay (e.g.,
00 32 03 E8= 50 ms).
Reversal Strategy
Identify each frame by its
fcTLchunk and the following data chunks (
IDATfor the first frame,
fdATfor subsequent frames).
Reverse the order of the frame data while keeping the
acTLframe count unchanged.
Adjust sequence numbers and recompute CRC32 for every modified chunk.
Implementation Overview (JavaScript)
The code traverses the PNG byte array, extracts each chunk, and builds a new byte array with the frames in reverse order.
<code>// Iterate over each chunk
eachChunk(bytes, (type, bytes, off, length) => {
const dv = new DataView(bytes.buffer);
const obj = {};
switch (type) {
case 'fdAT':
obj.sequence_number = dv.getUint32(off + 8);
obj.crc = dv.getUint32(off + 8 + length);
break;
case 'fcTL':
obj.sequence_number = dv.getUint32(off + 8);
obj.width = dv.getUint32(off + 8 + 4);
obj.height = dv.getUint32(off + 8 + 8);
obj.x_offset = dv.getUint32(off + 8 + 12);
obj.y_offset = dv.getUint32(off + 8 + 16);
obj.delay = (dv.getUint16(off + 8 + 20) / (dv.getUint16(off + 8 + 22) || 100)) * 1000;
obj.dispose_op = dv.getUint8(off + 8 + 24);
obj.blend_op = dv.getUint8(off + 8 + 25);
obj.crc = dv.getUint32(off + 8 + 26);
break;
default:
break;
}
// store or log obj as needed
});</code>Two passes are required: the first records the positions of all frames and non‑frame chunks; the second rebuilds the PNG, swapping the frame order, converting the first
fdATto
IDAT, and updating sequence numbers and CRC32.
<code>// Example of creating a new chunk with updated CRC
var makeChunkBytes = function (type, dataBytes) {
const crcLen = type.length + dataBytes.length;
const bytes = new Uint8Array(crcLen + 8);
const dv = new DataView(bytes.buffer);
dv.setUint32(0, dataBytes.length);
bytes.set(makeStringArray(type), 4);
bytes.set(dataBytes, 8);
var crc = CRC32.byte(bytes, 4, crcLen);
dv.setUint32(crcLen + 4, crc);
return bytes;
};
</code>After processing, the resulting PNG contains the same number of frames but plays them backward, producing a counter‑clockwise rotation of the Firefox logo.
Final Result
The reversed animation is displayed correctly, confirming that the frame order, sequence numbers, and CRC values were updated properly.
Tencent IMWeb Frontend Team
IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.