image-in-browser
Version:
Package for encoding / decoding images, transforming images, applying filters, drawing primitives on images on the client side (no need for server Node.js)
186 lines • 5.83 kB
JavaScript
import { Format } from '../color/format.js';
import { InputBuffer } from '../common/input-buffer.js';
import { MemoryImage } from '../image/image.js';
import { ImageFormat } from './image-format.js';
import { PnmFormat } from './pnm/pnm-format.js';
import { PnmInfo } from './pnm/pnm-info.js';
export class PnmDecoder {
constructor() {
this._tokens = [];
}
get input() {
return this._input;
}
get info() {
return this._info;
}
get format() {
return ImageFormat.pnm;
}
get numFrames() {
return this._info !== undefined ? 1 : 0;
}
getNextToken() {
var _a;
if (this._input === undefined) {
return '';
}
if (this._tokens.length > 0) {
return this._tokens.shift();
}
let line = this._input.readStringLine().trim();
if (line.length === 0) {
return '';
}
while (line.startsWith('#')) {
line = this._input.readStringLine(70).trim();
}
const tk = line.split(' ').filter((l) => l.length > 0);
for (let i = 0; i < tk.length; ++i) {
if (tk[i].startsWith('#')) {
tk.length = i;
break;
}
}
this._tokens.push(...tk);
return (_a = this._tokens.shift()) !== null && _a !== void 0 ? _a : '';
}
parseNextInt() {
const tk = this.getNextToken();
if (tk.length === 0) {
return 0;
}
const res = parseInt(tk);
return isNaN(res) ? 0 : res;
}
formatFromMaxValue(maxValue) {
if (maxValue > 255) {
return Format.uint16;
}
if (maxValue > 15) {
return Format.uint8;
}
if (maxValue > 3) {
return Format.uint4;
}
if (maxValue > 1) {
return Format.uint2;
}
return Format.uint1;
}
readValue(format, _maxValue) {
if (format === PnmFormat.pgm5 || format === PnmFormat.ppm6) {
return this.input.read();
}
return this.parseNextInt();
}
isValidFile(bytes) {
this._input = new InputBuffer({
buffer: bytes,
});
const tk = this.getNextToken();
return (tk === 'P1' || tk === 'P2' || tk === 'P5' || tk === 'P3' || tk === 'P6');
}
startDecode(bytes) {
this._input = new InputBuffer({
buffer: bytes,
});
const tk = this.getNextToken();
if (tk === 'P1') {
this._info = new PnmInfo(PnmFormat.pbm);
}
else if (tk === 'P2') {
this._info = new PnmInfo(PnmFormat.pgm2);
}
else if (tk === 'P5') {
this._info = new PnmInfo(PnmFormat.pgm5);
}
else if (tk === 'P3') {
this._info = new PnmInfo(PnmFormat.ppm3);
}
else if (tk === 'P6') {
this._info = new PnmInfo(PnmFormat.ppm6);
}
else {
this._input = undefined;
return undefined;
}
this._info.width = this.parseNextInt();
this._info.height = this.parseNextInt();
if (this._info.width === 0 || this._info.height === 0) {
this._input = undefined;
this._info = undefined;
return undefined;
}
return this._info;
}
decode(opt) {
var _a;
if (this.startDecode(opt.bytes) === undefined) {
return undefined;
}
return this.decodeFrame((_a = opt.frameIndex) !== null && _a !== void 0 ? _a : 0);
}
decodeFrame(_frameIndex) {
if (this._info === undefined) {
return undefined;
}
if (this._info.format === PnmFormat.pbm) {
const image = new MemoryImage({
width: this._info.width,
height: this._info.height,
numChannels: 1,
format: Format.uint1,
});
for (const p of image) {
const tk = this.getNextToken();
if (tk === '1') {
p.setRgb(1, 1, 1);
}
else {
p.setRgb(0, 0, 0);
}
}
return image;
}
else if (this._info.format === PnmFormat.pgm2 ||
this._info.format === PnmFormat.pgm5) {
const maxValue = this.parseNextInt();
if (maxValue === 0) {
return undefined;
}
const image = new MemoryImage({
width: this._info.width,
height: this._info.height,
numChannels: 1,
format: this.formatFromMaxValue(maxValue),
});
for (const p of image) {
const g = this.readValue(this._info.format, maxValue);
p.setRgb(g, g, g);
}
return image;
}
else if (this._info.format === PnmFormat.ppm3 ||
this._info.format === PnmFormat.ppm6) {
const maxValue = this.parseNextInt();
if (maxValue === 0) {
return undefined;
}
const image = new MemoryImage({
width: this._info.width,
height: this._info.height,
format: this.formatFromMaxValue(maxValue),
});
for (const p of image) {
const r = this.readValue(this._info.format, maxValue);
const g = this.readValue(this._info.format, maxValue);
const b = this.readValue(this._info.format, maxValue);
p.setRgb(r, g, b);
}
return image;
}
return undefined;
}
}
//# sourceMappingURL=pnm-decoder.js.map