Skip to content

Commit fe791ff

Browse files
authored
fix(browser): mask unused PNG transparency key bits (morluto#9890)
1 parent 4082375 commit fe791ff

2 files changed

Lines changed: 6 additions & 6 deletions

File tree

‎src/browser/PngVisualDiff.test.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,16 +127,16 @@ describe("PNG visual diff", () => {
127127
});
128128
});
129129

130-
it("keeps 8-bit samples opaque when a 16-bit transparency key exceeds 255", () => {
130+
it("masks unused transparency-key bits before comparing 8-bit samples", () => {
131131
const key = Buffer.alloc(6);
132132
key.writeUInt16BE(266, 0);
133-
key.writeUInt16BE(20, 2);
134-
key.writeUInt16BE(30, 4);
133+
key.writeUInt16BE(0xfe14, 2);
134+
key.writeUInt16BE(0xff1e, 4);
135135
const rgb = transparencyArtifact(2, key, [10, 20, 30]);
136136
const result = comparePngScreenshots(
137137
compareWebScreenshotsInputSchema.parse({
138138
before: rgb,
139-
after: artifact(1, 1, [10, 20, 30, 255]),
139+
after: artifact(1, 1, [10, 20, 30, 0]),
140140
}),
141141
);
142142
expect(result).toMatchObject({ status: "identical", changed_pixels: 0 });

‎src/browser/PngVisualDiff.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,12 @@ const parsePng = (
162162
throw new TypeError("Invalid PNG transparency order");
163163
sawTransparency = true;
164164
if (header.colorType === 2 && data.length === 6) {
165+
const sampleMask = (1 << header.bitDepth) - 1;
165166
transparentColor = [
166167
data.readUInt16BE(0),
167168
data.readUInt16BE(2),
168169
data.readUInt16BE(4),
169-
];
170+
].map((value) => value & sampleMask);
170171
} else if (
171172
(header.colorType === 0 && data.length === 2) ||
172173
(header.colorType === 3 &&
@@ -459,7 +460,6 @@ const expandRgba = (
459460
rgba[target] = decoded[source] ?? 0;
460461
rgba[target + 1] = decoded[source + 1] ?? 0;
461462
rgba[target + 2] = decoded[source + 2] ?? 0;
462-
// PNG tRNS keys are 16-bit values; values above 255 cannot match 8-bit samples.
463463
rgba[target + 3] =
464464
transparentColor !== undefined &&
465465
transparentColor.every(

0 commit comments

Comments
 (0)