Skip to content

Commit 98c771e

Browse files
authored
feat: add hasPngSignature method (#36)
Closes: #30
1 parent fdb2289 commit 98c771e

File tree

6 files changed

+46
-31
lines changed

6 files changed

+46
-31
lines changed

‎src/PngDecoder.ts

+6-16
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { IOBuffer } from 'iobuffer';
22
import { inflate, Inflate as Inflator } from 'pako';
33

4-
import { pngSignature, crc } from './common';
4+
import { crc } from './common';
5+
import { checkSignature } from './helpers/signature';
56
import {
67
ColorType,
78
CompressionMethod,
@@ -25,9 +26,9 @@ const uint8 = new Uint8Array(uint16.buffer);
2526
const osIsLittleEndian = uint8[0] === 0xff;
2627

2728
export default class PngDecoder extends IOBuffer {
28-
private _checkCrc: boolean;
29-
private _inflator: Inflator;
30-
private _png: DecodedPng;
29+
private readonly _checkCrc: boolean;
30+
private readonly _inflator: Inflator;
31+
private readonly _png: DecodedPng;
3132
private _end: boolean;
3233
private _hasPalette: boolean;
3334
private _palette: IndexedColors;
@@ -66,25 +67,14 @@ export default class PngDecoder extends IOBuffer {
6667
}
6768

6869
public decode(): DecodedPng {
69-
this.decodeSignature();
70+
checkSignature(this);
7071
while (!this._end) {
7172
this.decodeChunk();
7273
}
7374
this.decodeImage();
7475
return this._png;
7576
}
7677

77-
// https://www.w3.org/TR/PNG/#5PNG-file-signature
78-
private decodeSignature(): void {
79-
for (let i = 0; i < pngSignature.length; i++) {
80-
if (this.readUint8() !== pngSignature[i]) {
81-
throw new Error(
82-
`wrong PNG signature. Byte at ${i} should be ${pngSignature[i]}.`,
83-
);
84-
}
85-
}
86-
}
87-
8878
// https://www.w3.org/TR/PNG/#5Chunk-layout
8979
private decodeChunk(): void {
9080
const length = this.readUint32();

‎src/PngEncoder.ts

+5-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { IOBuffer } from 'iobuffer';
22
import { deflate } from 'pako';
33

4-
import { pngSignature, crc } from './common';
4+
import { crc } from './common';
5+
import { writeSignature } from './helpers/signature';
56
import {
67
ColorType,
78
CompressionMethod,
@@ -22,8 +23,8 @@ const defaultZlibOptions: DeflateFunctionOptions = {
2223
};
2324

2425
export default class PngEncoder extends IOBuffer {
25-
private _png: DecodedPng;
26-
private _zlibOptions: DeflateFunctionOptions;
26+
private readonly _png: DecodedPng;
27+
private readonly _zlibOptions: DeflateFunctionOptions;
2728
private _colorType: ColorType;
2829

2930
public constructor(data: ImageData, options: PngEncoderOptions = {}) {
@@ -35,18 +36,13 @@ export default class PngEncoder extends IOBuffer {
3536
}
3637

3738
public encode(): Uint8Array {
38-
this.encodeSignature();
39+
writeSignature(this);
3940
this.encodeIHDR();
4041
this.encodeData();
4142
this.encodeIEND();
4243
return this.toArray();
4344
}
4445

45-
// https://www.w3.org/TR/PNG/#5PNG-file-signature
46-
private encodeSignature(): void {
47-
this.writeBytes(pngSignature);
48-
}
49-
5046
// https://www.w3.org/TR/PNG/#11IHDR
5147
private encodeIHDR(): void {
5248
this.writeUint32(13);

‎src/__tests__/decode.test.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,13 @@ describe('decode', () => {
8888
loadAndDecode('palette.png', { checkCrc: true });
8989
});
9090

91-
it('should throw with a non-png', () => {
92-
expect(() => decode(new Uint8Array(20))).toThrow(
93-
'wrong PNG signature. Byte at 0 should be 137.',
94-
);
91+
it.each([
92+
// Enough values, last one is wrong.
93+
Uint8Array.of(137, 80, 78, 71, 13, 10, 26, 9, 0, 0, 0),
94+
// Not enough values.
95+
Uint8Array.of(137, 80),
96+
])('should throw with a non-png', (value) => {
97+
expect(() => decode(value)).toThrow('wrong PNG signature');
9598
});
9699

97100
it('ICC Embeded Profile', () => {

‎src/common.ts

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
export const pngSignature = [137, 80, 78, 71, 13, 10, 26, 10];
2-
31
const crcTable: number[] = [];
42
for (let n = 0; n < 256; n++) {
53
let c = n;

‎src/helpers/signature.ts

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import type { IOBuffer } from 'iobuffer';
2+
3+
// https://www.w3.org/TR/PNG/#5PNG-file-signature
4+
5+
const pngSignature = Uint8Array.of(137, 80, 78, 71, 13, 10, 26, 10);
6+
7+
export function writeSignature(buffer: IOBuffer) {
8+
buffer.writeBytes(pngSignature);
9+
}
10+
11+
export function checkSignature(buffer: IOBuffer) {
12+
if (!hasPngSignature(buffer.readBytes(pngSignature.length))) {
13+
throw new Error('wrong PNG signature');
14+
}
15+
}
16+
17+
export function hasPngSignature(array: ArrayLike<number>) {
18+
if (array.length < pngSignature.length) {
19+
return false;
20+
}
21+
for (let i = 0; i < pngSignature.length; i++) {
22+
if (array[i] !== pngSignature[i]) {
23+
return false;
24+
}
25+
}
26+
return true;
27+
}

‎src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
PngEncoderOptions,
99
} from './types';
1010

11+
export { hasPngSignature } from './helpers/signature';
1112
export * from './types';
1213

1314
function decodePng(

0 commit comments

Comments
 (0)