Avoid re-calculating the xScaleBlockOffset when not necessary in JpegImage._getLinearizedBlockData

As can be seen in the code, the `xScaleBlockOffset` typed array doesn't depend on the actual image data but only on the width and x-scale. The width is obviously consistent for an image, and it turns out that in practice the `componentScaleX` is quite often identical between two (or more) adjacent image components.
All-in-all it's thus not necessary to *unconditionally* re-compute the `xScaleBlockOffset` when getting the JPEG image data.

While avoiding, in many cases, one or more loops can never be a bad thing these changes are unfortunately completely dominated by the rest of the JpegImage code and consequently doesn't really show up in benchmark results. *Hence I'd understand if this patch is ultimately deemed not necessary.*
This commit is contained in:
Jonas Jenwald 2020-02-01 11:42:22 +01:00
parent 517ccb7a39
commit a4440a1c6b

View File

@ -1105,6 +1105,7 @@ var JpegImage = (function JpegImageClosure() {
var data = new Uint8ClampedArray(dataLength);
var xScaleBlockOffset = new Uint32Array(width);
var mask3LSB = 0xfffffff8; // used to clear the 3 LSBs
let lastComponentScaleX;
for (i = 0; i < numComponents; i++) {
component = this.components[i];
@ -1113,10 +1114,14 @@ var JpegImage = (function JpegImageClosure() {
offset = i;
output = component.output;
blocksPerScanline = (component.blocksPerLine + 1) << 3;
// precalculate the xScaleBlockOffset
for (x = 0; x < width; x++) {
j = 0 | (x * componentScaleX);
xScaleBlockOffset[x] = ((j & mask3LSB) << 3) | (j & 7);
// Precalculate the `xScaleBlockOffset`. Since it doesn't depend on the
// component data, that's only necessary when `componentScaleX` changes.
if (componentScaleX !== lastComponentScaleX) {
for (x = 0; x < width; x++) {
j = 0 | (x * componentScaleX);
xScaleBlockOffset[x] = ((j & mask3LSB) << 3) | (j & 7);
}
lastComponentScaleX = componentScaleX;
}
// linearize the blocks of the component
for (y = 0; y < height; y++) {