mirror of
https://github.com/danbulant/pngjs
synced 2026-09-18 05:43:53 +00:00
Speed up mapImage8Bit and mapImageCustomBit (#123)
Inner loop with `if()` comparison is eliminated and replaced with function call. Synthetic benchmark shows 1.5x increase in speed of mapImage8Bit for big PNG images (e.g. 4064 x 2338, 8-bit/color RGBA, non-interlaced screenshots).
This commit is contained in:
parent
ae7b0a1534
commit
2d78949365
1 changed files with 99 additions and 40 deletions
139
lib/bitmapper.js
139
lib/bitmapper.js
|
|
@ -2,32 +2,107 @@
|
|||
|
||||
var interlaceUtils = require('./interlace');
|
||||
|
||||
var pixelBppMap = {
|
||||
1: { // L
|
||||
0: 0,
|
||||
1: 0,
|
||||
2: 0,
|
||||
3: 0xff
|
||||
var pixelBppMapper = [
|
||||
// 0 - dummy entry
|
||||
function() {},
|
||||
|
||||
// 1 - L
|
||||
// 0: 0, 1: 0, 2: 0, 3: 0xff
|
||||
function(pxData, data, pxPos, rawPos) {
|
||||
if (rawPos === data.length) {
|
||||
throw new Error('Ran out of data');
|
||||
}
|
||||
|
||||
var pixel = data[rawPos];
|
||||
pxData[pxPos] = pixel;
|
||||
pxData[pxPos + 1] = pixel;
|
||||
pxData[pxPos + 2] = pixel;
|
||||
pxData[pxPos + 3] = 0xff;
|
||||
},
|
||||
2: { // LA
|
||||
0: 0,
|
||||
1: 0,
|
||||
2: 0,
|
||||
3: 1
|
||||
|
||||
// 2 - LA
|
||||
// 0: 0, 1: 0, 2: 0, 3: 1
|
||||
function(pxData, data, pxPos, rawPos) {
|
||||
if (rawPos + 1 >= data.length) {
|
||||
throw new Error('Ran out of data');
|
||||
}
|
||||
|
||||
var pixel = data[rawPos];
|
||||
pxData[pxPos] = pixel;
|
||||
pxData[pxPos + 1] = pixel;
|
||||
pxData[pxPos + 2] = pixel;
|
||||
pxData[pxPos + 3] = data[rawPos + 1];
|
||||
},
|
||||
3: { // RGB
|
||||
0: 0,
|
||||
1: 1,
|
||||
2: 2,
|
||||
3: 0xff
|
||||
|
||||
// 3 - RGB
|
||||
// 0: 0, 1: 1, 2: 2, 3: 0xff
|
||||
function(pxData, data, pxPos, rawPos) {
|
||||
if (rawPos + 2 >= data.length) {
|
||||
throw new Error('Ran out of data');
|
||||
}
|
||||
|
||||
pxData[pxPos] = data[rawPos];
|
||||
pxData[pxPos + 1] = data[rawPos + 1];
|
||||
pxData[pxPos + 2] = data[rawPos + 2];
|
||||
pxData[pxPos + 3] = 0xff;
|
||||
},
|
||||
4: { // RGBA
|
||||
0: 0,
|
||||
1: 1,
|
||||
2: 2,
|
||||
3: 3
|
||||
|
||||
// 4 - RGBA
|
||||
// 0: 0, 1: 1, 2: 2, 3: 3
|
||||
function(pxData, data, pxPos, rawPos) {
|
||||
if (rawPos + 3 >= data.length) {
|
||||
throw new Error('Ran out of data');
|
||||
}
|
||||
|
||||
pxData[pxPos] = data[rawPos];
|
||||
pxData[pxPos + 1] = data[rawPos + 1];
|
||||
pxData[pxPos + 2] = data[rawPos + 2];
|
||||
pxData[pxPos + 3] = data[rawPos + 3];
|
||||
}
|
||||
};
|
||||
];
|
||||
|
||||
var pixelBppCustomMapper = [
|
||||
// 0 - dummy entry
|
||||
function() {},
|
||||
|
||||
// 1 - L
|
||||
// 0: 0, 1: 0, 2: 0, 3: 0xff
|
||||
function(pxData, pixelData, pxPos, maxBit) {
|
||||
var pixel = pixelData[0];
|
||||
pxData[pxPos] = pixel;
|
||||
pxData[pxPos + 1] = pixel;
|
||||
pxData[pxPos + 2] = pixel;
|
||||
pxData[pxPos + 3] = maxBit;
|
||||
},
|
||||
|
||||
// 2 - LA
|
||||
// 0: 0, 1: 0, 2: 0, 3: 1
|
||||
function(pxData, pixelData, pxPos) {
|
||||
var pixel = pixelData[0];
|
||||
pxData[pxPos] = pixel;
|
||||
pxData[pxPos + 1] = pixel;
|
||||
pxData[pxPos + 2] = pixel;
|
||||
pxData[pxPos + 3] = pixelData[1];
|
||||
},
|
||||
|
||||
// 3 - RGB
|
||||
// 0: 0, 1: 1, 2: 2, 3: 0xff
|
||||
function(pxData, pixelData, pxPos, maxBit) {
|
||||
pxData[pxPos] = pixelData[0];
|
||||
pxData[pxPos + 1] = pixelData[1];
|
||||
pxData[pxPos + 2] = pixelData[2];
|
||||
pxData[pxPos + 3] = maxBit;
|
||||
},
|
||||
|
||||
// 4 - RGBA
|
||||
// 0: 0, 1: 1, 2: 2, 3: 3
|
||||
function(pxData, pixelData, pxPos) {
|
||||
pxData[pxPos] = pixelData[0];
|
||||
pxData[pxPos + 1] = pixelData[1];
|
||||
pxData[pxPos + 2] = pixelData[2];
|
||||
pxData[pxPos + 3] = pixelData[3];
|
||||
}
|
||||
];
|
||||
|
||||
function bitRetriever(data, depth) {
|
||||
|
||||
|
|
@ -102,19 +177,7 @@ function mapImage8Bit(image, pxData, getPxPos, bpp, data, rawPos) { // eslint-di
|
|||
for (var y = 0; y < imageHeight; y++) {
|
||||
for (var x = 0; x < imageWidth; x++) {
|
||||
var pxPos = getPxPos(x, y, imagePass);
|
||||
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var idx = pixelBppMap[bpp][i];
|
||||
if (idx === 0xff) {
|
||||
pxData[pxPos + i] = 0xff;
|
||||
} else {
|
||||
var dataPos = idx + rawPos;
|
||||
if (dataPos === data.length) {
|
||||
throw new Error('Ran out of data');
|
||||
}
|
||||
pxData[pxPos + i] = data[dataPos];
|
||||
}
|
||||
}
|
||||
pixelBppMapper[bpp](pxData, data, pxPos, rawPos);
|
||||
rawPos += bpp; //eslint-disable-line no-param-reassign
|
||||
}
|
||||
}
|
||||
|
|
@ -129,11 +192,7 @@ function mapImageCustomBit(image, pxData, getPxPos, bpp, bits, maxBit) { // esli
|
|||
for (var x = 0; x < imageWidth; x++) {
|
||||
var pixelData = bits.get(bpp);
|
||||
var pxPos = getPxPos(x, y, imagePass);
|
||||
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var idx = pixelBppMap[bpp][i];
|
||||
pxData[pxPos + i] = idx !== 0xff ? pixelData[idx] : maxBit;
|
||||
}
|
||||
pixelBppCustomMapper[bpp](pxData, pixelData, pxPos, maxBit);
|
||||
}
|
||||
bits.resetAfterLine();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue