Blame Raw
· · · 68 lines (1.8 KB)
0 contributors
1import { crc32 } from 'crc';
2
3/**
4 * Encodes PNG chunks into a PNG file format buffer.
5 * @param {Array<{ name: string; data: Uint8Array }>} chunks Array of PNG chunks
6 * @returns {Uint8Array} Encoded PNG data
7 * @copyright Based on https://github.com/hughsk/png-chunks-encode (MIT)
8 */
9export default function encode(chunks) {
10 const uint8 = new Uint8Array(4);
11 const int32 = new Int32Array(uint8.buffer);
12 const uint32 = new Uint32Array(uint8.buffer);
13
14 let totalSize = 8;
15 let idx = totalSize;
16
17 for (let i = 0; i < chunks.length; i++) {
18 totalSize += chunks[i].data.length;
19 totalSize += 12;
20 }
21
22 const output = new Uint8Array(totalSize);
23
24 output[0] = 0x89;
25 output[1] = 0x50;
26 output[2] = 0x4E;
27 output[3] = 0x47;
28 output[4] = 0x0D;
29 output[5] = 0x0A;
30 output[6] = 0x1A;
31 output[7] = 0x0A;
32
33 for (let i = 0; i < chunks.length; i++) {
34 const { name, data } = chunks[i];
35 const size = data.length;
36 const nameChars = [
37 name.charCodeAt(0),
38 name.charCodeAt(1),
39 name.charCodeAt(2),
40 name.charCodeAt(3),
41 ];
42
43 uint32[0] = size;
44 output[idx++] = uint8[3];
45 output[idx++] = uint8[2];
46 output[idx++] = uint8[1];
47 output[idx++] = uint8[0];
48
49 output[idx++] = nameChars[0];
50 output[idx++] = nameChars[1];
51 output[idx++] = nameChars[2];
52 output[idx++] = nameChars[3];
53
54 for (let j = 0; j < size;) {
55 output[idx++] = data[j++];
56 }
57
58 const crc = crc32(data, crc32(new Uint8Array(nameChars)));
59
60 int32[0] = crc;
61 output[idx++] = uint8[3];
62 output[idx++] = uint8[2];
63 output[idx++] = uint8[1];
64 output[idx++] = uint8[0];
65 }
66
67 return output;
68}