Convert src/core/jpx.js to use standard classes

*Please note:* Ignoring whitespace-only changes is probably necessary in order to review this.
This commit is contained in:
Jonas Jenwald 2021-05-05 13:02:58 +02:00
parent cb65b762eb
commit ce14171cf0

View File

@ -13,7 +13,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { BaseException, info, warn } from "../shared/util.js"; import { BaseException, info, unreachable, warn } from "../shared/util.js";
import { log2, readUint16, readUint32 } from "./core_utils.js"; import { log2, readUint16, readUint32 } from "./core_utils.js";
import { ArithmeticDecoder } from "./arithmetic_decoder.js"; import { ArithmeticDecoder } from "./arithmetic_decoder.js";
@ -23,21 +23,20 @@ class JpxError extends BaseException {
} }
} }
const JpxImage = (function JpxImageClosure() { // Table E.1
// Table E.1 const SubbandsGainLog2 = {
const SubbandsGainLog2 = {
LL: 0, LL: 0,
LH: 1, LH: 1,
HL: 1, HL: 1,
HH: 2, HH: 2,
}; };
// eslint-disable-next-line no-shadow class JpxImage {
function JpxImage() { constructor() {
this.failOnCorruptedImage = false; this.failOnCorruptedImage = false;
} }
JpxImage.prototype = {
parse: function JpxImage_parse(data) { parse(data) {
const head = readUint16(data, 0); const head = readUint16(data, 0);
// No box header, immediate start of codestream (SOC) // No box header, immediate start of codestream (SOC)
if (head === 0xff4f) { if (head === 0xff4f) {
@ -114,15 +113,16 @@ const JpxImage = (function JpxImageClosure() {
(tbox >> 8) & 0xff, (tbox >> 8) & 0xff,
tbox & 0xff tbox & 0xff
); );
warn("Unsupported header type " + tbox + " (" + headerType + ")"); warn(`Unsupported header type ${tbox} (${headerType}).`);
break; break;
} }
if (jumpDataLength) { if (jumpDataLength) {
position += dataLength; position += dataLength;
} }
} }
}, }
parseImageProperties: function JpxImage_parseImageProperties(stream) {
parseImageProperties(stream) {
let newByte = stream.getByte(); let newByte = stream.getByte();
while (newByte >= 0) { while (newByte >= 0) {
const oldByte = newByte; const oldByte = newByte;
@ -146,8 +146,9 @@ const JpxImage = (function JpxImageClosure() {
} }
} }
throw new JpxError("No size marker found in JPX stream"); throw new JpxError("No size marker found in JPX stream");
}, }
parseCodestream: function JpxImage_parseCodestream(data, start, end) {
parseCodestream(data, start, end) {
const context = {}; const context = {};
let doNotRecover = false; let doNotRecover = false;
try { try {
@ -350,9 +351,7 @@ const JpxImage = (function JpxImageClosure() {
} }
if (unsupported.length > 0) { if (unsupported.length > 0) {
doNotRecover = true; doNotRecover = true;
warn( warn(`JPX: Unsupported COD options (${unsupported.join(", ")}).`);
`JPX: Unsupported COD options (${unsupported.join(", ")}).`
);
} }
if (context.mainHeader) { if (context.mainHeader) {
context.COD = cod; context.COD = cod;
@ -417,9 +416,10 @@ const JpxImage = (function JpxImageClosure() {
this.width = context.SIZ.Xsiz - context.SIZ.XOsiz; this.width = context.SIZ.Xsiz - context.SIZ.XOsiz;
this.height = context.SIZ.Ysiz - context.SIZ.YOsiz; this.height = context.SIZ.Ysiz - context.SIZ.YOsiz;
this.componentsCount = context.SIZ.Csiz; this.componentsCount = context.SIZ.Csiz;
}, }
}; }
function calculateComponentDimensions(component, siz) {
function calculateComponentDimensions(component, siz) {
// Section B.2 Component mapping // Section B.2 Component mapping
component.x0 = Math.ceil(siz.XOsiz / component.XRsiz); component.x0 = Math.ceil(siz.XOsiz / component.XRsiz);
component.x1 = Math.ceil(siz.Xsiz / component.XRsiz); component.x1 = Math.ceil(siz.Xsiz / component.XRsiz);
@ -427,8 +427,8 @@ const JpxImage = (function JpxImageClosure() {
component.y1 = Math.ceil(siz.Ysiz / component.YRsiz); component.y1 = Math.ceil(siz.Ysiz / component.YRsiz);
component.width = component.x1 - component.x0; component.width = component.x1 - component.x0;
component.height = component.y1 - component.y0; component.height = component.y1 - component.y0;
} }
function calculateTileGrids(context, components) { function calculateTileGrids(context, components) {
const siz = context.SIZ; const siz = context.SIZ;
// Section B.3 Division into tile and tile-components // Section B.3 Division into tile and tile-components
const tiles = []; const tiles = [];
@ -465,8 +465,8 @@ const JpxImage = (function JpxImageClosure() {
tile.components[i] = tileComponent; tile.components[i] = tileComponent;
} }
} }
} }
function getBlocksDimensions(context, component, r) { function getBlocksDimensions(context, component, r) {
const codOrCoc = component.codingStyleParameters; const codOrCoc = component.codingStyleParameters;
const result = {}; const result = {};
if (!codOrCoc.entropyCoderWithCustomPrecincts) { if (!codOrCoc.entropyCoderWithCustomPrecincts) {
@ -486,8 +486,8 @@ const JpxImage = (function JpxImageClosure() {
? Math.min(codOrCoc.ycb, result.PPy - 1) ? Math.min(codOrCoc.ycb, result.PPy - 1)
: Math.min(codOrCoc.ycb, result.PPy); : Math.min(codOrCoc.ycb, result.PPy);
return result; return result;
} }
function buildPrecincts(context, resolution, dimensions) { function buildPrecincts(context, resolution, dimensions) {
// Section B.6 Division resolution to precincts // Section B.6 Division resolution to precincts
const precinctWidth = 1 << dimensions.PPx; const precinctWidth = 1 << dimensions.PPx;
const precinctHeight = 1 << dimensions.PPy; const precinctHeight = 1 << dimensions.PPy;
@ -507,8 +507,7 @@ const JpxImage = (function JpxImageClosure() {
// coordinates of a point in the LL band and child subband, respectively. // coordinates of a point in the LL band and child subband, respectively.
const isZeroRes = resolution.resLevel === 0; const isZeroRes = resolution.resLevel === 0;
const precinctWidthInSubband = 1 << (dimensions.PPx + (isZeroRes ? 0 : -1)); const precinctWidthInSubband = 1 << (dimensions.PPx + (isZeroRes ? 0 : -1));
const precinctHeightInSubband = const precinctHeightInSubband = 1 << (dimensions.PPy + (isZeroRes ? 0 : -1));
1 << (dimensions.PPy + (isZeroRes ? 0 : -1));
const numprecinctswide = const numprecinctswide =
resolution.trx1 > resolution.trx0 resolution.trx1 > resolution.trx0
? Math.ceil(resolution.trx1 / precinctWidth) - ? Math.ceil(resolution.trx1 / precinctWidth) -
@ -530,8 +529,8 @@ const JpxImage = (function JpxImageClosure() {
precinctWidthInSubband, precinctWidthInSubband,
precinctHeightInSubband, precinctHeightInSubband,
}; };
} }
function buildCodeblocks(context, subband, dimensions) { function buildCodeblocks(context, subband, dimensions) {
// Section B.7 Division sub-band into code-blocks // Section B.7 Division sub-band into code-blocks
const xcb_ = dimensions.xcb_; const xcb_ = dimensions.xcb_;
const ycb_ = dimensions.ycb_; const ycb_ = dimensions.ycb_;
@ -617,8 +616,8 @@ const JpxImage = (function JpxImageClosure() {
}; };
subband.codeblocks = codeblocks; subband.codeblocks = codeblocks;
subband.precincts = precincts; subband.precincts = precincts;
} }
function createPacket(resolution, precinctNumber, layerNumber) { function createPacket(resolution, precinctNumber, layerNumber) {
const precinctCodeblocks = []; const precinctCodeblocks = [];
// Section B.10.8 Order of info in packet // Section B.10.8 Order of info in packet
const subbands = resolution.subbands; const subbands = resolution.subbands;
@ -638,8 +637,8 @@ const JpxImage = (function JpxImageClosure() {
layerNumber, layerNumber,
codeblocks: precinctCodeblocks, codeblocks: precinctCodeblocks,
}; };
} }
function LayerResolutionComponentPositionIterator(context) { function LayerResolutionComponentPositionIterator(context) {
const siz = context.SIZ; const siz = context.SIZ;
const tileIndex = context.currentTile.index; const tileIndex = context.currentTile.index;
const tile = context.tiles[tileIndex]; const tile = context.tiles[tileIndex];
@ -683,8 +682,8 @@ const JpxImage = (function JpxImageClosure() {
} }
throw new JpxError("Out of packets"); throw new JpxError("Out of packets");
}; };
} }
function ResolutionLayerComponentPositionIterator(context) { function ResolutionLayerComponentPositionIterator(context) {
const siz = context.SIZ; const siz = context.SIZ;
const tileIndex = context.currentTile.index; const tileIndex = context.currentTile.index;
const tile = context.tiles[tileIndex]; const tile = context.tiles[tileIndex];
@ -728,8 +727,8 @@ const JpxImage = (function JpxImageClosure() {
} }
throw new JpxError("Out of packets"); throw new JpxError("Out of packets");
}; };
} }
function ResolutionPositionComponentLayerIterator(context) { function ResolutionPositionComponentLayerIterator(context) {
const siz = context.SIZ; const siz = context.SIZ;
const tileIndex = context.currentTile.index; const tileIndex = context.currentTile.index;
const tile = context.tiles[tileIndex]; const tile = context.tiles[tileIndex];
@ -792,8 +791,8 @@ const JpxImage = (function JpxImageClosure() {
} }
throw new JpxError("Out of packets"); throw new JpxError("Out of packets");
}; };
} }
function PositionComponentResolutionLayerIterator(context) { function PositionComponentResolutionLayerIterator(context) {
const siz = context.SIZ; const siz = context.SIZ;
const tileIndex = context.currentTile.index; const tileIndex = context.currentTile.index;
const tile = context.tiles[tileIndex]; const tile = context.tiles[tileIndex];
@ -844,8 +843,8 @@ const JpxImage = (function JpxImageClosure() {
} }
throw new JpxError("Out of packets"); throw new JpxError("Out of packets");
}; };
} }
function ComponentPositionResolutionLayerIterator(context) { function ComponentPositionResolutionLayerIterator(context) {
const siz = context.SIZ; const siz = context.SIZ;
const tileIndex = context.currentTile.index; const tileIndex = context.currentTile.index;
const tile = context.tiles[tileIndex]; const tile = context.tiles[tileIndex];
@ -895,14 +894,14 @@ const JpxImage = (function JpxImageClosure() {
} }
throw new JpxError("Out of packets"); throw new JpxError("Out of packets");
}; };
} }
function getPrecinctIndexIfExist( function getPrecinctIndexIfExist(
pxIndex, pxIndex,
pyIndex, pyIndex,
sizeInImageScale, sizeInImageScale,
precinctIterationSizes, precinctIterationSizes,
resolution resolution
) { ) {
const posX = pxIndex * precinctIterationSizes.minWidth; const posX = pxIndex * precinctIterationSizes.minWidth;
const posY = pyIndex * precinctIterationSizes.minHeight; const posY = pyIndex * precinctIterationSizes.minHeight;
if ( if (
@ -915,8 +914,8 @@ const JpxImage = (function JpxImageClosure() {
(posY / sizeInImageScale.width) * (posY / sizeInImageScale.width) *
resolution.precinctParameters.numprecinctswide; resolution.precinctParameters.numprecinctswide;
return posX / sizeInImageScale.height + startPrecinctRowIndex; return posX / sizeInImageScale.height + startPrecinctRowIndex;
} }
function getPrecinctSizesInImageScale(tile) { function getPrecinctSizesInImageScale(tile) {
const componentsCount = tile.components.length; const componentsCount = tile.components.length;
let minWidth = Number.MAX_VALUE; let minWidth = Number.MAX_VALUE;
let minHeight = Number.MAX_VALUE; let minHeight = Number.MAX_VALUE;
@ -980,8 +979,8 @@ const JpxImage = (function JpxImageClosure() {
maxNumWide, maxNumWide,
maxNumHigh, maxNumHigh,
}; };
} }
function buildPackets(context) { function buildPackets(context) {
const siz = context.SIZ; const siz = context.SIZ;
const tileIndex = context.currentTile.index; const tileIndex = context.currentTile.index;
const tile = context.tiles[tileIndex]; const tile = context.tiles[tileIndex];
@ -1093,8 +1092,8 @@ const JpxImage = (function JpxImageClosure() {
default: default:
throw new JpxError(`Unsupported progression order ${progressionOrder}`); throw new JpxError(`Unsupported progression order ${progressionOrder}`);
} }
} }
function parseTilePackets(context, data, offset, dataLength) { function parseTilePackets(context, data, offset, dataLength) {
let position = 0; let position = 0;
let buffer, let buffer,
bufferSize = 0, bufferSize = 0,
@ -1277,8 +1276,8 @@ const JpxImage = (function JpxImageClosure() {
} }
} }
return position; return position;
} }
function copyCoefficients( function copyCoefficients(
coefficients, coefficients,
levelWidth, levelWidth,
levelHeight, levelHeight,
@ -1287,7 +1286,7 @@ const JpxImage = (function JpxImageClosure() {
mb, mb,
reversible, reversible,
segmentationSymbolUsed segmentationSymbolUsed
) { ) {
const x0 = subband.tbx0; const x0 = subband.tbx0;
const y0 = subband.tby0; const y0 = subband.tby0;
const width = subband.tbx1 - subband.tbx0; const width = subband.tbx1 - subband.tbx0;
@ -1389,8 +1388,8 @@ const JpxImage = (function JpxImageClosure() {
offset += width - blockWidth; offset += width - blockWidth;
} }
} }
} }
function transformTile(context, tile, c) { function transformTile(context, tile, c) {
const component = tile.components[c]; const component = tile.components[c];
const codingStyleParameters = component.codingStyleParameters; const codingStyleParameters = component.codingStyleParameters;
const quantizationParameters = component.quantizationParameters; const quantizationParameters = component.quantizationParameters;
@ -1473,8 +1472,8 @@ const JpxImage = (function JpxImageClosure() {
height: result.height, height: result.height,
items: result.items, items: result.items,
}; };
} }
function transformComponents(context) { function transformComponents(context) {
const siz = context.SIZ; const siz = context.SIZ;
const components = context.components; const components = context.components;
const componentsCount = siz.Csiz; const componentsCount = siz.Csiz;
@ -1562,8 +1561,8 @@ const JpxImage = (function JpxImageClosure() {
resultImages.push(result); resultImages.push(result);
} }
return resultImages; return resultImages;
} }
function initializeTile(context, tileIndex) { function initializeTile(context, tileIndex) {
const siz = context.SIZ; const siz = context.SIZ;
const componentsCount = siz.Csiz; const componentsCount = siz.Csiz;
const tile = context.tiles[tileIndex]; const tile = context.tiles[tileIndex];
@ -1581,12 +1580,11 @@ const JpxImage = (function JpxImageClosure() {
component.codingStyleParameters = codOrCoc; component.codingStyleParameters = codOrCoc;
} }
tile.codingStyleDefaultParameters = context.currentTile.COD; tile.codingStyleDefaultParameters = context.currentTile.COD;
} }
// Section B.10.2 Tag trees // Section B.10.2 Tag trees
const TagTree = (function TagTreeClosure() { class TagTree {
// eslint-disable-next-line no-shadow constructor(width, height) {
function TagTree(width, height) {
const levelsLength = log2(Math.max(width, height)) + 1; const levelsLength = log2(Math.max(width, height)) + 1;
this.levels = []; this.levels = [];
for (let i = 0; i < levelsLength; i++) { for (let i = 0; i < levelsLength; i++) {
@ -1600,8 +1598,8 @@ const JpxImage = (function JpxImageClosure() {
height = Math.ceil(height / 2); height = Math.ceil(height / 2);
} }
} }
TagTree.prototype = {
reset: function TagTree_reset(i, j) { reset(i, j) {
let currentLevel = 0, let currentLevel = 0,
value = 0, value = 0,
level; level;
@ -1622,12 +1620,14 @@ const JpxImage = (function JpxImageClosure() {
level.items[level.index] = value; level.items[level.index] = value;
this.currentLevel = currentLevel; this.currentLevel = currentLevel;
delete this.value; delete this.value;
}, }
incrementValue: function TagTree_incrementValue() {
incrementValue() {
const level = this.levels[this.currentLevel]; const level = this.levels[this.currentLevel];
level.items[level.index]++; level.items[level.index]++;
}, }
nextLevel: function TagTree_nextLevel() {
nextLevel() {
let currentLevel = this.currentLevel; let currentLevel = this.currentLevel;
let level = this.levels[currentLevel]; let level = this.levels[currentLevel];
const value = level.items[level.index]; const value = level.items[level.index];
@ -1641,14 +1641,11 @@ const JpxImage = (function JpxImageClosure() {
level = this.levels[currentLevel]; level = this.levels[currentLevel];
level.items[level.index] = value; level.items[level.index] = value;
return true; return true;
}, }
}; }
return TagTree;
})();
const InclusionTree = (function InclusionTreeClosure() { class InclusionTree {
// eslint-disable-next-line no-shadow constructor(width, height, defaultValue) {
function InclusionTree(width, height, defaultValue) {
const levelsLength = log2(Math.max(width, height)) + 1; const levelsLength = log2(Math.max(width, height)) + 1;
this.levels = []; this.levels = [];
for (let i = 0; i < levelsLength; i++) { for (let i = 0; i < levelsLength; i++) {
@ -1668,8 +1665,8 @@ const JpxImage = (function JpxImageClosure() {
height = Math.ceil(height / 2); height = Math.ceil(height / 2);
} }
} }
InclusionTree.prototype = {
reset: function InclusionTree_reset(i, j, stopValue) { reset(i, j, stopValue) {
let currentLevel = 0; let currentLevel = 0;
while (currentLevel < this.levels.length) { while (currentLevel < this.levels.length) {
const level = this.levels[currentLevel]; const level = this.levels[currentLevel];
@ -1694,13 +1691,15 @@ const JpxImage = (function JpxImageClosure() {
} }
this.currentLevel = currentLevel - 1; this.currentLevel = currentLevel - 1;
return true; return true;
}, }
incrementValue: function InclusionTree_incrementValue(stopValue) {
incrementValue(stopValue) {
const level = this.levels[this.currentLevel]; const level = this.levels[this.currentLevel];
level.items[level.index] = stopValue + 1; level.items[level.index] = stopValue + 1;
this.propagateValues(); this.propagateValues();
}, }
propagateValues: function InclusionTree_propagateValues() {
propagateValues() {
let levelIndex = this.currentLevel; let levelIndex = this.currentLevel;
let level = this.levels[levelIndex]; let level = this.levels[levelIndex];
const currentValue = level.items[level.index]; const currentValue = level.items[level.index];
@ -1708,8 +1707,9 @@ const JpxImage = (function JpxImageClosure() {
level = this.levels[levelIndex]; level = this.levels[levelIndex];
level.items[level.index] = currentValue; level.items[level.index] = currentValue;
} }
}, }
nextLevel: function InclusionTree_nextLevel() {
nextLevel() {
let currentLevel = this.currentLevel; let currentLevel = this.currentLevel;
let level = this.levels[currentLevel]; let level = this.levels[currentLevel];
const value = level.items[level.index]; const value = level.items[level.index];
@ -1723,13 +1723,11 @@ const JpxImage = (function JpxImageClosure() {
level = this.levels[currentLevel]; level = this.levels[currentLevel];
level.items[level.index] = value; level.items[level.index] = value;
return true; return true;
}, }
}; }
return InclusionTree;
})();
// Section D. Coefficient bit modeling // Section D. Coefficient bit modeling
const BitModel = (function BitModelClosure() { const BitModel = (function BitModelClosure() {
const UNIFORM_CONTEXT = 17; const UNIFORM_CONTEXT = 17;
const RUNLENGTH_CONTEXT = 18; const RUNLENGTH_CONTEXT = 18;
// Table D-1 // Table D-1
@ -1755,7 +1753,8 @@ const JpxImage = (function JpxImageClosure() {
]); ]);
// eslint-disable-next-line no-shadow // eslint-disable-next-line no-shadow
function BitModel(width, height, subband, zeroBitPlanes, mb) { class BitModel {
constructor(width, height, subband, zeroBitPlanes, mb) {
this.width = width; this.width = width;
this.height = height; this.height = height;
@ -1797,11 +1796,11 @@ const JpxImage = (function JpxImageClosure() {
this.reset(); this.reset();
} }
BitModel.prototype = { setDecoder(decoder) {
setDecoder: function BitModel_setDecoder(decoder) {
this.decoder = decoder; this.decoder = decoder;
}, }
reset: function BitModel_reset() {
reset() {
// We have 17 contexts that are accessed via context labels, // We have 17 contexts that are accessed via context labels,
// plus the uniform and runlength context. // plus the uniform and runlength context.
this.contexts = new Int8Array(19); this.contexts = new Int8Array(19);
@ -1811,12 +1810,9 @@ const JpxImage = (function JpxImageClosure() {
this.contexts[0] = (4 << 1) | 0; this.contexts[0] = (4 << 1) | 0;
this.contexts[UNIFORM_CONTEXT] = (46 << 1) | 0; this.contexts[UNIFORM_CONTEXT] = (46 << 1) | 0;
this.contexts[RUNLENGTH_CONTEXT] = (3 << 1) | 0; this.contexts[RUNLENGTH_CONTEXT] = (3 << 1) | 0;
}, }
setNeighborsSignificance: function BitModel_setNeighborsSignificance(
row, setNeighborsSignificance(row, column, index) {
column,
index
) {
const neighborsSignificance = this.neighborsSignificance; const neighborsSignificance = this.neighborsSignificance;
const width = this.width, const width = this.width,
height = this.height; height = this.height;
@ -1853,8 +1849,9 @@ const JpxImage = (function JpxImageClosure() {
neighborsSignificance[index + 1] += 0x01; neighborsSignificance[index + 1] += 0x01;
} }
neighborsSignificance[index] |= 0x80; neighborsSignificance[index] |= 0x80;
}, }
runSignificancePropagationPass: function BitModel_runSignificancePropagationPass() {
runSignificancePropagationPass() {
const decoder = this.decoder; const decoder = this.decoder;
const width = this.width, const width = this.width,
height = this.height; height = this.height;
@ -1880,10 +1877,7 @@ const JpxImage = (function JpxImageClosure() {
// clear processed flag first // clear processed flag first
processingFlags[index] &= processedInverseMask; processingFlags[index] &= processedInverseMask;
if ( if (coefficentsMagnitude[index] || !neighborsSignificance[index]) {
coefficentsMagnitude[index] ||
!neighborsSignificance[index]
) {
continue; continue;
} }
@ -1901,8 +1895,9 @@ const JpxImage = (function JpxImageClosure() {
} }
} }
} }
}, }
decodeSignBit: function BitModel_decodeSignBit(row, column, index) {
decodeSignBit(row, column, index) {
const width = this.width, const width = this.width,
height = this.height; height = this.height;
const coefficentsMagnitude = this.coefficentsMagnitude; const coefficentsMagnitude = this.coefficentsMagnitude;
@ -1953,8 +1948,9 @@ const JpxImage = (function JpxImageClosure() {
decoded = this.decoder.readBit(this.contexts, contextLabel) ^ 1; decoded = this.decoder.readBit(this.contexts, contextLabel) ^ 1;
} }
return decoded; return decoded;
}, }
runMagnitudeRefinementPass: function BitModel_runMagnitudeRefinementPass() {
runMagnitudeRefinementPass() {
const decoder = this.decoder; const decoder = this.decoder;
const width = this.width, const width = this.width,
height = this.height; height = this.height;
@ -1996,8 +1992,9 @@ const JpxImage = (function JpxImageClosure() {
} }
} }
} }
}, }
runCleanupPass: function BitModel_runCleanupPass() {
runCleanupPass() {
const decoder = this.decoder; const decoder = this.decoder;
const width = this.width, const width = this.width,
height = this.height; height = this.height;
@ -2090,8 +2087,9 @@ const JpxImage = (function JpxImageClosure() {
} }
} }
} }
}, }
checkSegmentationSymbol: function BitModel_checkSegmentationSymbol() {
checkSegmentationSymbol() {
const decoder = this.decoder; const decoder = this.decoder;
const contexts = this.contexts; const contexts = this.contexts;
const symbol = const symbol =
@ -2102,29 +2100,29 @@ const JpxImage = (function JpxImageClosure() {
if (symbol !== 0xa) { if (symbol !== 0xa) {
throw new JpxError("Invalid segmentation symbol"); throw new JpxError("Invalid segmentation symbol");
} }
}, }
}; }
return BitModel; return BitModel;
})(); })();
// Section F, Discrete wavelet transformation // Section F, Discrete wavelet transformation
const Transform = (function TransformClosure() { class Transform {
// eslint-disable-next-line no-shadow constructor() {
function Transform() {} if (this.constructor === Transform) {
unreachable("Cannot initialize Transform.");
}
}
Transform.prototype.calculate = function transformCalculate( calculate(subbands, u0, v0) {
subbands,
u0,
v0
) {
let ll = subbands[0]; let ll = subbands[0];
for (let i = 1, ii = subbands.length; i < ii; i++) { for (let i = 1, ii = subbands.length; i < ii; i++) {
ll = this.iterate(ll, subbands[i], u0, v0); ll = this.iterate(ll, subbands[i], u0, v0);
} }
return ll; return ll;
}; }
Transform.prototype.extend = function extend(buffer, offset, size) {
extend(buffer, offset, size) {
// Section F.3.7 extending... using max extension of 4 // Section F.3.7 extending... using max extension of 4
let i1 = offset - 1, let i1 = offset - 1,
j1 = offset + 1; j1 = offset + 1;
@ -2138,13 +2136,13 @@ const JpxImage = (function JpxImageClosure() {
buffer[j2++] = buffer[i2--]; buffer[j2++] = buffer[i2--];
buffer[i1] = buffer[j1]; buffer[i1] = buffer[j1];
buffer[j2] = buffer[i2]; buffer[j2] = buffer[i2];
}; }
Transform.prototype.iterate = function Transform_iterate(
ll, filter(x, offset, length) {
hl_lh_hh, unreachable("Abstract method `filter` called");
u0, }
v0
) { iterate(ll, hl_lh_hh, u0, v0) {
const llWidth = ll.width, const llWidth = ll.width,
llHeight = ll.height; llHeight = ll.height;
let llItems = ll.items; let llItems = ll.items;
@ -2181,10 +2179,7 @@ const JpxImage = (function JpxImageClosure() {
this.extend(rowBuffer, bufferPadding, width); this.extend(rowBuffer, bufferPadding, width);
this.filter(rowBuffer, bufferPadding, width); this.filter(rowBuffer, bufferPadding, width);
items.set( items.set(rowBuffer.subarray(bufferPadding, bufferPadding + width), k);
rowBuffer.subarray(bufferPadding, bufferPadding + width),
k
);
} }
} }
@ -2241,28 +2236,13 @@ const JpxImage = (function JpxImageClosure() {
} }
} }
return { return { width, height, items };
width,
height,
items,
};
};
return Transform;
})();
// Section 3.8.2 Irreversible 9-7 filter
const IrreversibleTransform = (function IrreversibleTransformClosure() {
// eslint-disable-next-line no-shadow
function IrreversibleTransform() {
Transform.call(this);
} }
}
IrreversibleTransform.prototype = Object.create(Transform.prototype); // Section 3.8.2 Irreversible 9-7 filter
IrreversibleTransform.prototype.filter = function irreversibleTransformFilter( class IrreversibleTransform extends Transform {
x, filter(x, offset, length) {
offset,
length
) {
const len = length >> 1; const len = length >> 1;
offset = offset | 0; offset = offset | 0;
let j, n, current, next; let j, n, current, next;
@ -2343,24 +2323,12 @@ const JpxImage = (function JpxImageClosure() {
} }
} }
} }
};
return IrreversibleTransform;
})();
// Section 3.8.1 Reversible 5-3 filter
const ReversibleTransform = (function ReversibleTransformClosure() {
// eslint-disable-next-line no-shadow
function ReversibleTransform() {
Transform.call(this);
} }
}
ReversibleTransform.prototype = Object.create(Transform.prototype); // Section 3.8.1 Reversible 5-3 filter
ReversibleTransform.prototype.filter = function reversibleTransformFilter( class ReversibleTransform extends Transform {
x, filter(x, offset, length) {
offset,
length
) {
const len = length >> 1; const len = length >> 1;
offset = offset | 0; offset = offset | 0;
let j, n; let j, n;
@ -2372,12 +2340,7 @@ const JpxImage = (function JpxImageClosure() {
for (j = offset + 1, n = len; n--; j += 2) { for (j = offset + 1, n = len; n--; j += 2) {
x[j] += (x[j - 1] + x[j + 1]) >> 1; x[j] += (x[j - 1] + x[j + 1]) >> 1;
} }
}; }
}
return ReversibleTransform;
})();
return JpxImage;
})();
export { JpxImage }; export { JpxImage };