PNG colour-key transparency (tRNS for greyscale and truecolour) gives a wrong /Mask
Los mantenedores suelen responder en 1 día
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 78/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- javascript, node.js
Línea de trabajo
Start with lib/image/png.js and trace how it reads the tRNS bytes and builds the image XObject /Mask; the report also identifies png-js as the source of the raw grayscale and RGB values. Use the included grayscale, RGB, and 16-bit examples to check the generated mask. Done means each component has the expected min/max pair and the affected viewers handle the resulting transparency correctly.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Bug Report
Description of the problem
For greyscale (colour type 0) and truecolour (colour type 2) PNGs with a tRNS colour key, the image XObject gets a wrong /Mask array. For 8-bit greyscale the key is always written as 0, so black pixels become transparent and the keyed grey stays. For RGB the array has 12 entries instead of 6, which viewers ignore (pdf.js, MuPDF, PDFium) or misread.
tRNS stores 2-byte big-endian samples for these colour types (one for grey, three for RGB, regardless of bit depth), and /Mask needs one min max pair per component (ISO 32000-1, 8.9.6.4). png-js keeps the chunk as raw bytes (for grey only read(chunkSize)[0], the high byte; for RGB all six bytes), and lib/image/png.js then pushes every byte as a pair (for (let x of rgb) mask.push(x, x)).
Expected output:
key-gray /Mask [128 128]
key-rgb /Mask [255 255 0 0 0 0]
key-rgb16 /Mask [65535 65535 0 0 0 0]
Actual output:
key-gray /Mask [0 0]
key-rgb /Mask [0 0 255 255 0 0 0 0 0 0 0 0]
key-rgb16 /Mask [255 255 255 255 0 0 0 0 0 0 0 0]
#1274 lists PngSuite transparency files among unsupported PNGs; this may be part of it.
Code sample
import zlib from "node:zlib";
import PDFDocument from "pdfkit";
const crc = (b) => {
let c = 0xffffffff;
for (const x of b) {
c ^= x;
for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
}
return (c ^ 0xffffffff) >>> 0;
};
const chunk = (type, data) => {
const l = Buffer.alloc(4), td = Buffer.concat([Buffer.from(type), data]), c = Buffer.alloc(4);
l.writeUInt32BE(data.length);
c.writeUInt32BE(crc(td));
return Buffer.concat([l, td, c]);
};
const png = (w, h, depth, ctype, rows, trns) => {
const ih = Buffer.alloc(13);
ih.writeUInt32BE(w, 0); ih.writeUInt32BE(h, 4); ih[8] = depth; ih[9] = ctype;
return Buffer.concat([
Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]),
chunk("IHDR", ih),
chunk("tRNS", Buffer.from(trns)),
chunk("IDAT", zlib.deflateSync(Buffer.concat(rows.map((r) => Buffer.from([0, ...r]))))),
chunk("IEND", Buffer.alloc(0)),
]);
};
const cases = {
"key-gray": png(2, 1, 8, 0, [[128, 0]], [0, 128]),
"key-rgb": png(2, 1, 8, 2, [[255, 0, 0, 0, 0, 255]], [0, 255, 0, 0, 0, 0]),
"key-rgb16": png(2, 1, 16, 2, [[255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255]], [255, 255, 0, 0, 0, 0]),
};
for (const [name, buf] of Object.entries(cases)) {
const doc = new PDFDocument({ size: [200, 100], margin: 0, compress: false });
const out = [];
doc.on("data", (d) => out.push(d));
doc.image(buf, 0, 0, { width: 200, height: 100 });
doc.end();
await new Promise((r) => doc.on("end", r));
console.log(name, Buffer.concat(out).toString("latin1").match(/\/Mask \[[^\]]*\]/)[0]);
}
Your environment
- pdfkit version: 0.20.2 (with png-js 2.0.0), also a build of
masterat 91c54ef - Node version: 26.13.0
- Browser version (if applicable): n/a
- Operating System: Ubuntu Linux x86_64
Credit: https://ucsbplse.github.io/
- Lenguaje dominante
- JavaScript
- Estrellas
- 10.7k
- Forks
- 1.2k
- Merge medio
- 19 h 16 min
- PR fusionados (30 d)
- 25
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de foliojs/pdfkit
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
foliojs/pdfkit#1804 · 5 comentarios ·
Los mantenedores suelen responder en 1 día
-
PDFKit crashes when providing fonts as Buffer in tablePosiblemente ocupada @ykw9263 la tomó hace 135 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
foliojs/pdfkit#1743 · 13 comentarios ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
foliojs/pdfkit#1635 · 4 comentarios ·
Los mantenedores suelen responder en 1 día
-
Get detailed font metricsAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
foliojs/pdfkit#1512 · 1 comentario · 2 reacciones ·
Los mantenedores suelen responder en 1 día
-
Upgrade codemirrorAbierto
Dificultad 3/5 1-2 días Aptitud para principiantes 45/100
Los mantenedores suelen responder en 1 día
Todos los issues de foliojs/pdfkit
Issues similares
-
Add: ESP 2 RSAbiertoapproved check:passed feeds:add
Dificultad 1/5 Menos de una hora Aptitud para principiantes 67/100
-
xsd:integer cast from a string rejects negative numbers, a leading + and surrounding whitespaceAbiertobug 🐛
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
comunica/comunica#1960 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Waiting for: Product Owner
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
getsentry/sentry-javascript#26203 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
Los mantenedores suelen responder en 1 día