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:
parent
cb65b762eb
commit
ce14171cf0
333
src/core/jpx.js
333
src/core/jpx.js
@ -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 };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user