mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-06-05 17:51:03 +02:00
Merge pull request #21372 from calixteman/issue7998
Render gray transparency groups in grayscale
This commit is contained in:
commit
744c1e6d7a
@ -523,6 +523,7 @@ class PartialEvaluator {
|
||||
isolated: false,
|
||||
knockout: false,
|
||||
needsIsolation: false,
|
||||
isGray: false,
|
||||
};
|
||||
|
||||
const groupSubtype = group.get("S");
|
||||
@ -541,6 +542,10 @@ class PartialEvaluator {
|
||||
}
|
||||
}
|
||||
|
||||
// When the group color space is gray (a single component) the group's
|
||||
// content must be rendered in grayscale, see issue 7998.
|
||||
groupOptions.isGray = colorSpace?.numComps === 1;
|
||||
|
||||
if (smask?.backdrop) {
|
||||
colorSpace ||= ColorSpaceUtils.rgb;
|
||||
smask.backdrop = colorSpace.getRgbHex(smask.backdrop, 0);
|
||||
|
||||
@ -3262,6 +3262,7 @@ class CanvasGraphics {
|
||||
if (
|
||||
!group.needsIsolation &&
|
||||
!group.knockout &&
|
||||
!group.isGray &&
|
||||
this.#knockoutGroupLevel === 0 &&
|
||||
currentCtx.globalAlpha === 1 &&
|
||||
currentCtx.globalCompositeOperation === "source-over" &&
|
||||
@ -3473,6 +3474,13 @@ class CanvasGraphics {
|
||||
return;
|
||||
}
|
||||
|
||||
if (group.isGray) {
|
||||
// The group color space is gray (a single component), so its rendered
|
||||
// content must be converted to grayscale before being composited onto
|
||||
// the parent canvas, see issue 7998.
|
||||
this.#convertGroupToGray(groupCtx);
|
||||
}
|
||||
|
||||
this.ctx = ctx;
|
||||
// Turn off image smoothing to avoid sub pixel interpolation which can
|
||||
// look kind of blurry for some pdfs.
|
||||
@ -3604,6 +3612,38 @@ class CanvasGraphics {
|
||||
}
|
||||
}
|
||||
|
||||
#convertGroupToGray(groupCtx) {
|
||||
const { canvas } = groupCtx;
|
||||
const { width, height } = canvas;
|
||||
|
||||
if (FeatureTest.isCanvasFilterSupported) {
|
||||
// Draw the canvas onto itself with the grayscale filter applied (which
|
||||
// preserves the alpha channel), using the "copy" composite operation so
|
||||
// the filtered content fully replaces the original.
|
||||
groupCtx.save();
|
||||
groupCtx.setTransform(1, 0, 0, 1, 0, 0);
|
||||
groupCtx.filter = "grayscale(1)";
|
||||
groupCtx.globalAlpha = 1;
|
||||
groupCtx.globalCompositeOperation = "copy";
|
||||
groupCtx.drawImage(canvas, 0, 0);
|
||||
groupCtx.restore();
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback when canvas filters aren't supported: convert each pixel to
|
||||
// grayscale by hand, using the same luminance coefficients as the
|
||||
// "grayscale(1)" filter while leaving the alpha channel untouched.
|
||||
const imageData = groupCtx.getImageData(0, 0, width, height);
|
||||
const { data } = imageData;
|
||||
for (let i = 0, ii = data.length; i < ii; i += 4) {
|
||||
const gray =
|
||||
(data[i] * 0.2126 + data[i + 1] * 0.7152 + data[i + 2] * 0.0722 + 0.5) |
|
||||
0;
|
||||
data[i] = data[i + 1] = data[i + 2] = gray;
|
||||
}
|
||||
groupCtx.putImageData(imageData, 0, 0);
|
||||
}
|
||||
|
||||
#destroyKnockoutPools(groupMeta) {
|
||||
if (!groupMeta) {
|
||||
return;
|
||||
|
||||
1
test/pdfs/issue7998.pdf.link
Normal file
1
test/pdfs/issue7998.pdf.link
Normal file
@ -0,0 +1 @@
|
||||
https://bugs.ghostscript.com/attachment.cgi?id=13156
|
||||
@ -3822,6 +3822,14 @@
|
||||
"link": false,
|
||||
"type": "eq"
|
||||
},
|
||||
{
|
||||
"id": "issue7998",
|
||||
"file": "pdfs/issue7998.pdf",
|
||||
"md5": "6cf4622cbcb61fb07525dfb0ab23f9c3",
|
||||
"rounds": 1,
|
||||
"link": true,
|
||||
"type": "eq"
|
||||
},
|
||||
{
|
||||
"id": "issue11279",
|
||||
"file": "pdfs/issue11279.pdf",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user