Created
April 4, 2021 09:12
-
-
Save disgusting-dev/899774a89f9cefa55e0add0c79930dac to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = { | |
//First 8 bites of any original PNG Image | |
PNG_SIGNATURE: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], | |
RGBA_DIMENSIONS_AMOUNT: 4, //1 for each letter in RGBA; | |
TYPE_IHDR: 0x49484452, | |
TYPE_IEND: 0x49454e44, | |
TYPE_IDAT: 0x49444154, | |
TYPE_PLTE: 0x504c5445, | |
TYPE_tRNS: 0x74524e53, // eslint-disable-line camelcase | |
TYPE_gAMA: 0x67414d41, // eslint-disable-line camelcase | |
// color-type bits | |
COLORTYPE_GRAYSCALE: 0, | |
COLORTYPE_PALETTE: 1, | |
COLORTYPE_COLOR: 2, | |
COLORTYPE_ALPHA: 4, // e.g. grayscale and alpha | |
// color-type combinations | |
COLORTYPE_PALETTE_COLOR: 3, | |
COLORTYPE_COLOR_ALPHA: 6, | |
COLORTYPE_TO_BPP_MAP: { | |
0: 1, | |
2: 3, | |
3: 1, | |
4: 2, | |
6: 4, | |
}, | |
GAMMA_DIVISION: 100000, | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// var fs = require("fs"), | |
// PNG = require("pngjs").PNG; | |
// fs.createReadStream("art.png") | |
// .pipe( | |
// new PNG({ | |
// filterType: 4, | |
// }) | |
// ) | |
// .on("parsed", function () { | |
// for (var y = 0; y < this.height; y++) { | |
// for (var x = 0; x < this.width; x++) { | |
// var idx = (this.width * y + x) << 2; | |
// // invert color | |
// this.data[idx] = 255 - this.data[idx]; | |
// this.data[idx + 1] = 255 - this.data[idx + 1]; | |
// this.data[idx + 2] = 255 - this.data[idx + 2]; | |
// } | |
// } | |
// this.pack().pipe(fs.createWriteStream("out.png")); | |
// }); | |
const Stream = require('stream'); | |
const { RGBA_DIMENSIONS_AMOUNT } = require('./constants'); | |
class PNG extends Stream { | |
constructor( | |
options = {}, | |
) { | |
super(); | |
// if create picture from scratch, user may define width/heigth in options | |
// we will use automatical data from parsed picture | |
const { width = 0, height = 0 } = options; | |
this.gamma = 0; | |
this.options = options; | |
this.data = null; | |
//Stream should be both readable and writable | |
this.readable = this.writable = true; | |
// Cutting of floating point parts in case of such existance; | |
[this.width, this.height] = [width, height].map(Math.trunc); | |
this._initializeDataBuffer(); | |
// this._parser = new Parser(this.options); | |
} | |
_initializeDataBuffer() { | |
//check typeof to be sure we work with number-like structures | |
if ( | |
this.width | |
&& this.height | |
&& !isNaN(this.width) | |
&& !isNaN(this.height) | |
) { | |
//Buffer is array of integers, 1 dimensional by default. | |
// So, for our needs we have to take width + height and multiplied by dimensions amount, | |
// Cause each pixel is representation of 4 rgba values; | |
//So we already allocate needed amount of memory for this; | |
this.data = Buffer.alloc(RGBA_DIMENSIONS_AMOUNT * this.width * this.height); | |
} else { | |
throw new Error('Width and Height should be numbers'); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { | |
PNG_SIGNATURE, | |
RGBA_DIMENSIONS_AMOUNT | |
} = require('./constants'); | |
class Parser { | |
constructor( | |
options, | |
{ | |
read, | |
} = {} | |
) { | |
this._options = options; | |
this._hasIHDR = false; | |
this._emittedHeadersFinished = false; | |
this._colorType = 0; | |
this._palette = []; | |
this._chunks = {}; | |
this.read = read; | |
} | |
start = () => { | |
this.read(PNG_SIGNATURE.length, this._parseSignature()); | |
} | |
_parseSignature = (data) => { | |
// To be sure we work with correct format of file by signature | |
if (JSON.stringify( | |
this.data.slice(0, PNG_SIGNATURE.length) | |
) === JSON.stringify(PNG_SIGNATURE)) { | |
return this.read(8, this._parseChunkBegin); | |
} | |
throw new Error('Invalid file signature'); | |
} | |
_parseChunkBegin = () => { | |
const data = Buffer.from([0x21, 0x09, 0x19, 0x98, | |
0x34, 0xae, 0xe8, 0xff]); | |
console.log(data); | |
const length = data.readUInt32BE(); | |
console.log(length); | |
const type = data.readUInt32BE(4); | |
console.log(type); | |
let name = ''; | |
for (let i = RGBA_DIMENSIONS_AMOUNT; i < PNG_SIGNATURE.length; i++) { | |
name += String.fromCharCode(data[i]); | |
} | |
console.log(name); | |
let ancillary = Boolean(data[4] & 0x20); | |
} | |
} | |
const parser = new Parser(); | |
parser._parseChunkBegin(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment