PNG colour-key transparency (tRNS for greyscale and truecolour) gives a wrong /Mask

Đang mở
#1,864 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

@1AbdullahButt đang làm issue này rồi.

Từ ngày 8/11/2026.

  • #1865 của @1AbdullahButt — đang mở

Đánh giá

Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức phù hợp với người mới
78/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
javascript, node.js
Lĩnh vực
api, backend

Hướng nghiên cứu

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.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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 master at 91c54ef
  • Node version: 26.13.0
  • Browser version (if applicable): n/a
  • Operating System: Ubuntu Linux x86_64

Credit: https://ucsbplse.github.io/

Ngôn ngữ chính
JavaScript
Star
10.7k
Fork
1.2k
Merge trung bình
19 giờ 16 phút
Pull request đã merge (30 ngày)
25

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của foliojs/pdfkit

Tất cả issue của foliojs/pdfkit

Issue tương tự

Thêm issue về JavaScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.