Skip to content

WASM backend applies premultipliedAlpha twice (worker + Dart client) #678

Description

@espresso3389

Found while porting the WASM client to TypeScript (pdfrx_web project), by code inspection.

When PdfPageRenderFlags.premultipliedAlpha (0x80000000) is set, the alpha premultiplication is performed twice on the WASM backend:

  1. packages/pdfrx/assets/pdfium_worker.js, renderPage(): the copy loop premultiplies BGRA when flags & premultipliedAlpha:
if (flags & premultipliedAlpha) {
  for (let i = 0; i < src.length; i += 4) {
    const a = src[i + 3];
    dest[i] = (src[i] * a + 128) >> 8;
    ...
  1. packages/pdfrx/lib/src/wasm/pdfrx_wasm.dart, _PdfPageWasm.render(): the received pixels are premultiplied again:
if ((flags & PdfPageRenderFlags.premultipliedAlpha) != 0) {
  final count = width * height;
  for (var i = 0; i < count; i++) {
    ...
    pixels[i * 4] = b * a ~/ 255;

Since both sides test the same bit on the same flags value, semi-transparent pixels end up with alpha applied twice (RGB gets darker than intended). One of the two loops should be removed (keeping it in the worker avoids the extra pass over the transferred buffer).

Related nit in the same worker function: FPDF_RenderPageBitmap receives masked flags ((flags & 0xffff) | FPDF_ANNOT), but FPDF_FFLDraw receives the raw flags including the non-PDFium 0x80000000 bit (negative as int32). It should probably receive the same masked value.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions