Skip to content

Commit

Permalink
feat: add hasPngSignature method (#36)
Browse files Browse the repository at this point in the history
Closes: #30
  • Loading branch information
targos authored Feb 10, 2024
1 parent fdb2289 commit 98c771e
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 31 deletions.
22 changes: 6 additions & 16 deletions src/PngDecoder.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { IOBuffer } from 'iobuffer';
import { inflate, Inflate as Inflator } from 'pako';

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

export default class PngDecoder extends IOBuffer {
private _checkCrc: boolean;
private _inflator: Inflator;
private _png: DecodedPng;
private readonly _checkCrc: boolean;
private readonly _inflator: Inflator;
private readonly _png: DecodedPng;
private _end: boolean;
private _hasPalette: boolean;
private _palette: IndexedColors;
Expand Down Expand Up @@ -66,25 +67,14 @@ export default class PngDecoder extends IOBuffer {
}

public decode(): DecodedPng {
this.decodeSignature();
checkSignature(this);
while (!this._end) {
this.decodeChunk();
}
this.decodeImage();
return this._png;
}

// https://www.w3.org/TR/PNG/#5PNG-file-signature
private decodeSignature(): void {
for (let i = 0; i < pngSignature.length; i++) {
if (this.readUint8() !== pngSignature[i]) {
throw new Error(
`wrong PNG signature. Byte at ${i} should be ${pngSignature[i]}.`,
);
}
}
}

// https://www.w3.org/TR/PNG/#5Chunk-layout
private decodeChunk(): void {
const length = this.readUint32();
Expand Down
14 changes: 5 additions & 9 deletions src/PngEncoder.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { IOBuffer } from 'iobuffer';
import { deflate } from 'pako';

import { pngSignature, crc } from './common';
import { crc } from './common';
import { writeSignature } from './helpers/signature';
import {
ColorType,
CompressionMethod,
Expand All @@ -22,8 +23,8 @@ const defaultZlibOptions: DeflateFunctionOptions = {
};

export default class PngEncoder extends IOBuffer {
private _png: DecodedPng;
private _zlibOptions: DeflateFunctionOptions;
private readonly _png: DecodedPng;
private readonly _zlibOptions: DeflateFunctionOptions;
private _colorType: ColorType;

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

public encode(): Uint8Array {
this.encodeSignature();
writeSignature(this);
this.encodeIHDR();
this.encodeData();
this.encodeIEND();
return this.toArray();
}

// https://www.w3.org/TR/PNG/#5PNG-file-signature
private encodeSignature(): void {
this.writeBytes(pngSignature);
}

// https://www.w3.org/TR/PNG/#11IHDR
private encodeIHDR(): void {
this.writeUint32(13);
Expand Down
11 changes: 7 additions & 4 deletions src/__tests__/decode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,13 @@ describe('decode', () => {
loadAndDecode('palette.png', { checkCrc: true });
});

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

it('ICC Embeded Profile', () => {
Expand Down
2 changes: 0 additions & 2 deletions src/common.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
export const pngSignature = [137, 80, 78, 71, 13, 10, 26, 10];

const crcTable: number[] = [];
for (let n = 0; n < 256; n++) {
let c = n;
Expand Down
27 changes: 27 additions & 0 deletions src/helpers/signature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { IOBuffer } from 'iobuffer';

// https://www.w3.org/TR/PNG/#5PNG-file-signature

const pngSignature = Uint8Array.of(137, 80, 78, 71, 13, 10, 26, 10);

export function writeSignature(buffer: IOBuffer) {
buffer.writeBytes(pngSignature);
}

export function checkSignature(buffer: IOBuffer) {
if (!hasPngSignature(buffer.readBytes(pngSignature.length))) {
throw new Error('wrong PNG signature');
}
}

export function hasPngSignature(array: ArrayLike<number>) {
if (array.length < pngSignature.length) {
return false;
}
for (let i = 0; i < pngSignature.length; i++) {
if (array[i] !== pngSignature[i]) {
return false;
}
}
return true;
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
PngEncoderOptions,
} from './types';

export { hasPngSignature } from './helpers/signature';
export * from './types';

function decodePng(
Expand Down

0 comments on commit 98c771e

Please sign in to comment.