Skip to content

Commit

Permalink
Some jpx images can have a mask
Browse files Browse the repository at this point in the history
It fixes mozilla#18896.
  • Loading branch information
calixteman committed Oct 14, 2024
1 parent e1f9fa4 commit 8b7b39f
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 1 deletion.
88 changes: 88 additions & 0 deletions src/core/colorspace.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import {
assert,
FeatureTest,
FormatError,
info,
shadow,
Expand Down Expand Up @@ -60,6 +61,61 @@ function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
}
}

function resizeRgbaImage(src, dest, w1, h1, w2, h2, alpha01) {
const xRatio = w1 / w2;
const yRatio = h1 / h2;
let newIndex = 0;
const xScaled = new Uint16Array(w2);

if (alpha01 === 1) {
for (let i = 0; i < w2; i++) {
xScaled[i] = Math.floor(i * xRatio);
}
const src32 = new Uint32Array(src.buffer);
const dest32 = new Uint32Array(dest.buffer);
const rgbMask = FeatureTest.isLittleEndian ? 0x00ffffff : 0xffffff00;
for (let i = 0; i < h2; i++) {
const buf = src32.subarray(Math.floor(i * yRatio) * w1);
for (let j = 0; j < w2; j++) {
dest32[newIndex++] |= buf[xScaled[j]] & rgbMask;
}
}
} else {
const COMPONENTS = 4;
const w1Scanline = w1 * COMPONENTS;
for (let i = 0; i < w2; i++) {
xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
}
for (let i = 0; i < h2; i++) {
const buf = src.subarray(Math.floor(i * yRatio) * w1Scanline);
for (let j = 0; j < w2; j++) {
const oldIndex = xScaled[j];
dest[newIndex++] = buf[oldIndex];
dest[newIndex++] = buf[oldIndex + 1];
dest[newIndex++] = buf[oldIndex + 2];
}
}
}
}

function copyRgbaImage(src, dest, alpha01) {
if (alpha01 === 1) {
const src32 = new Uint32Array(src.buffer);
const dest32 = new Uint32Array(dest.buffer);
const rgbMask = FeatureTest.isLittleEndian ? 0x00ffffff : 0xffffff00;
for (let i = 0, ii = src32.length; i < ii; i++) {
dest32[i] |= src32[i] & rgbMask;
}
} else {
let j = 0;
for (let i = 0, ii = src.length; i < ii; i += 4) {
dest[j++] = src[i];
dest[j++] = src[i + 1];
dest[j++] = src[i + 2];
}
}
}

class ColorSpace {
constructor(name, numComps) {
if (
Expand Down Expand Up @@ -806,6 +862,38 @@ class DeviceRgbaCS extends ColorSpace {
isPassthrough(bits) {
return bits === 8;
}

fillRgb(
dest,
originalWidth,
originalHeight,
width,
height,
actualHeight,
bpc,
comps,
alpha01
) {
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
assert(
dest instanceof Uint8ClampedArray,
'DeviceRgbaCS.fillRgb: Unsupported "dest" type.'
);
}
if (originalHeight !== height || originalWidth !== width) {
resizeRgbaImage(
comps,
dest,
originalWidth,
originalHeight,
width,
height,
alpha01
);
} else {
copyRgbaImage(comps, dest, alpha01);
}
}
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/core/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ class PDFImage {
isOffscreenCanvasSupported &&
ImageResizer.needsToBeResized(drawWidth, drawHeight);

if (this.colorSpace.name === "DeviceRGBA") {
if (!this.smask && !this.mask && this.colorSpace.name === "DeviceRGBA") {
imgData.kind = ImageKind.RGBA_32BPP;
const imgArray = (imgData.data = await this.getImageBytes(
originalHeight * originalWidth * 4,
Expand Down
1 change: 1 addition & 0 deletions test/pdfs/issue18896.pdf.link
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://github.com/user-attachments/files/17365176/issue18896.pdf
9 changes: 9 additions & 0 deletions test/test_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -10700,5 +10700,14 @@
"rounds": 1,
"type": "eq",
"talos": false
},
{
"id": "issue18896",
"file": "pdfs/issue18896.pdf",
"md5": "4acb4df0f38c976dce5e841e6de1f875",
"rounds": 1,
"type": "eq",
"link": true,
"talos": false
}
]

0 comments on commit 8b7b39f

Please sign in to comment.