Compare commits

..

No commits in common. "5089cceec708cb36d8d4ea369f97e1449c1df475" and "81c9a34fd30f64404738fbdf567a8d429f051be8" have entirely different histories.

View File

@ -17,6 +17,7 @@ import { assert, BaseException, warn } from "../shared/util.js";
import { ColorSpaceUtils } from "./colorspace_utils.js";
import { DeviceCmykCS } from "./colorspace.js";
import { grayToRGBA } from "../shared/image_utils.js";
import { readUint16 } from "./core_utils.js";
class JpegError extends BaseException {
constructor(msg) {
@ -121,7 +122,6 @@ function getBlockBufferOffset(component, row, col) {
function decodeScan(
data,
view,
offset,
frame,
components,
@ -151,7 +151,7 @@ function decodeScan(
if (nextByte === /* DNL = */ 0xdc && parseDNLMarker) {
offset += 2; // Skip marker length.
const scanLines = view.getUint16(offset);
const scanLines = readUint16(data, offset);
offset += 2;
if (scanLines > 0 && scanLines !== frame.scanLines) {
throw new DNLMarkerError(
@ -434,7 +434,7 @@ function decodeScan(
// find marker
bitsCount = 0;
fileMarker = findNextFileMarker(data, view, offset);
fileMarker = findNextFileMarker(data, offset);
if (!fileMarker) {
break; // Reached the end of the image data without finding any marker.
}
@ -717,14 +717,14 @@ function buildComponentData(frame, component) {
return component.blockData;
}
function findNextFileMarker(data, view, currentPos, startPos = currentPos) {
function findNextFileMarker(data, currentPos, startPos = currentPos) {
const maxPos = data.length - 1;
let newPos = startPos < currentPos ? startPos : currentPos;
if (currentPos >= maxPos) {
return null; // Don't attempt to read non-existent data and just return.
}
const currentMarker = view.getUint16(currentPos);
const currentMarker = readUint16(data, currentPos);
if (currentMarker >= 0xffc0 && currentMarker <= 0xfffe) {
return {
invalid: null,
@ -732,12 +732,12 @@ function findNextFileMarker(data, view, currentPos, startPos = currentPos) {
offset: currentPos,
};
}
let newMarker = view.getUint16(newPos);
let newMarker = readUint16(data, newPos);
while (!(newMarker >= 0xffc0 && newMarker <= 0xfffe)) {
if (++newPos >= maxPos) {
return null; // Don't attempt to read non-existent data and just return.
}
newMarker = view.getUint16(newPos);
newMarker = readUint16(data, newPos);
}
return {
invalid: currentMarker.toString(16),
@ -769,12 +769,12 @@ function prepareComponents(frame) {
frame.mcusPerColumn = mcusPerColumn;
}
function readDataBlock(data, view, offset) {
const length = view.getUint16(offset);
function readDataBlock(data, offset) {
const length = readUint16(data, offset);
offset += 2;
let endOffset = offset + length - 2;
const fileMarker = findNextFileMarker(data, view, endOffset, offset);
const fileMarker = findNextFileMarker(data, endOffset, offset);
if (fileMarker?.invalid) {
warn(
"readDataBlock - incorrect length, current marker is: " +
@ -791,12 +791,12 @@ function readDataBlock(data, view, offset) {
};
}
function skipData(data, view, offset) {
const length = view.getUint16(offset);
function skipData(data, offset) {
const length = readUint16(data, offset);
offset += 2;
const endOffset = offset + length - 2;
const fileMarker = findNextFileMarker(data, view, endOffset, offset);
const fileMarker = findNextFileMarker(data, endOffset, offset);
if (fileMarker?.invalid) {
return fileMarker.offset;
}
@ -810,16 +810,15 @@ class JpegImage {
}
static canUseImageDecoder(data, colorTransform = -1) {
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
let exifOffsets = null;
let offset = 0;
let numComponents = null;
let fileMarker = view.getUint16(offset);
let fileMarker = readUint16(data, offset);
offset += 2;
if (fileMarker !== /* SOI (Start of Image) = */ 0xffd8) {
throw new JpegError("SOI not found");
}
fileMarker = view.getUint16(offset);
fileMarker = readUint16(data, offset);
offset += 2;
markerLoop: while (fileMarker !== /* EOI (End of Image) = */ 0xffd9) {
@ -827,11 +826,7 @@ class JpegImage {
case 0xffe1: // APP1 - Exif
// TODO: Remove this once https://github.com/w3c/webcodecs/issues/870
// is fixed.
const { appData, oldOffset, newOffset } = readDataBlock(
data,
view,
offset
);
const { appData, oldOffset, newOffset } = readDataBlock(data, offset);
offset = newOffset;
// 'Exif\x00\x00'
@ -850,7 +845,7 @@ class JpegImage {
// since that can modify the original PDF document.
exifOffsets = { exifStart: oldOffset + 6, exifEnd: newOffset };
}
fileMarker = view.getUint16(offset);
fileMarker = readUint16(data, offset);
offset += 2;
continue;
case 0xffc0: // SOF0 (Start of Frame, Baseline DCT)
@ -869,8 +864,8 @@ class JpegImage {
}
break;
}
offset = skipData(data, view, offset);
fileMarker = view.getUint16(offset);
offset = skipData(data, offset);
fileMarker = readUint16(data, offset);
offset += 2;
}
if (numComponents === 4) {
@ -883,8 +878,6 @@ class JpegImage {
}
parse(data, { dnlScanLines = null } = {}) {
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
const maxOffset = data.length - 1;
let offset = 0;
let jfif = null;
let adobe = null;
@ -894,12 +887,12 @@ class JpegImage {
const huffmanTablesAC = [],
huffmanTablesDC = [];
let fileMarker = view.getUint16(offset);
let fileMarker = readUint16(data, offset);
offset += 2;
if (fileMarker !== /* SOI (Start of Image) = */ 0xffd8) {
throw new JpegError("SOI not found");
}
fileMarker = view.getUint16(offset);
fileMarker = readUint16(data, offset);
offset += 2;
markerLoop: while (fileMarker !== /* EOI (End of Image) = */ 0xffd9) {
@ -922,7 +915,7 @@ class JpegImage {
case 0xffee: // APP14
case 0xffef: // APP15
case 0xfffe: // COM (Comment)
const { appData, newOffset } = readDataBlock(data, view, offset);
const { appData, newOffset } = readDataBlock(data, offset);
offset = newOffset;
if (fileMarker === 0xffe0) {
@ -969,7 +962,7 @@ class JpegImage {
break;
case 0xffdb: // DQT (Define Quantization Tables)
const quantizationTablesLength = view.getUint16(offset);
const quantizationTablesLength = readUint16(data, offset);
offset += 2;
const quantizationTablesEnd = quantizationTablesLength + offset - 2;
let z;
@ -986,7 +979,7 @@ class JpegImage {
// 16 bit values
for (j = 0; j < 64; j++) {
z = dctZigZag[j];
tableData[z] = view.getUint16(offset);
tableData[z] = readUint16(data, offset);
offset += 2;
}
} else {
@ -1008,10 +1001,10 @@ class JpegImage {
frame.extended = fileMarker === 0xffc1;
frame.progressive = fileMarker === 0xffc2;
frame.precision = data[offset++];
const sofScanLines = view.getUint16(offset);
const sofScanLines = readUint16(data, offset);
offset += 2;
frame.scanLines = dnlScanLines || sofScanLines;
frame.samplesPerLine = view.getUint16(offset);
frame.samplesPerLine = readUint16(data, offset);
offset += 2;
frame.components = [];
frame.componentIds = {};
@ -1044,7 +1037,7 @@ class JpegImage {
break;
case 0xffc4: // DHT (Define Huffman Tables)
const huffmanLength = view.getUint16(offset);
const huffmanLength = readUint16(data, offset);
offset += 2;
for (i = 2; i < huffmanLength; ) {
const huffmanTableSpec = data[offset++];
@ -1068,7 +1061,7 @@ class JpegImage {
case 0xffdd: // DRI (Define Restart Interval)
offset += 2; // Skip marker length.
resetInterval = view.getUint16(offset);
resetInterval = readUint16(data, offset);
offset += 2;
break;
@ -1099,7 +1092,6 @@ class JpegImage {
try {
const processed = decodeScan(
data,
view,
offset,
frame,
components,
@ -1141,7 +1133,6 @@ class JpegImage {
// `startPos = offset - 3` when looking for the next valid marker.
const nextFileMarker = findNextFileMarker(
data,
view,
/* currentPos = */ offset - 2,
/* startPos = */ offset - 3
);
@ -1153,7 +1144,7 @@ class JpegImage {
offset = nextFileMarker.offset;
break;
}
if (!nextFileMarker || offset >= maxOffset) {
if (!nextFileMarker || offset >= data.length - 1) {
warn(
"JpegImage.parse - reached the end of the image data " +
"without finding an EOI marker (0xFFD9)."
@ -1164,13 +1155,8 @@ class JpegImage {
"JpegImage.parse - unknown marker: " + fileMarker.toString(16)
);
}
if (offset < maxOffset) {
fileMarker = view.getUint16(offset);
offset += 2;
} else {
fileMarker = 0;
}
fileMarker = readUint16(data, offset);
offset += 2;
}
if (!frame) {