Fix/23953 transparency group blank conversion#17
Open
antobinary wants to merge 1 commit into
Open
Conversation
…gbluebutton#23953) Some PDFs embed a figure inside a transparency group whose image uses a soft mask (SMask) with an ICCBased colorspace. poppler's cairo backend fails to composite this construct, so both the primary `pdftocairo -svg` conversion and the existing `pdftocairo -png` raster fallback produce a blank result. The client reports the conversion as successful, so the slide silently shows nothing (e.g. a black rectangle that never appears). Fix, in bbb-common-web: - Trigger the raster fallback when the generated SVG contains a cairo transparency-group soft mask. The blank SVG otherwise passes all existing thresholds (image/path/use counts). We gate on the <filter> count rather than <mask>: cairo emits a <filter> (alpha->luminance feColorMatrix) only for the blanking transparency-group construct, whereas plain alpha images emit <mask> with no <filter> and render fine -- so gating on <mask> would needlessly rasterize normal images. - Rasterize the fallback with pdftoppm (poppler splash backend) instead of pdftocairo -png (cairo backend); splash composites the construct correctly. `-singlefile` writes "<root>.png", matching the existing temp-file handling. Adds a configurable `filterTagThreshold` (default 0) wired in doc-conversion.xml / bigbluebutton.properties. Also adds a Playwright regression test that uploads the reported PDF and asserts the rendered slide is not blank (dark-pixel ratio of the slide image rasterized onto a canvas). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
antobinary
force-pushed
the
fix/23953-transparency-group-blank-conversion
branch
from
July 18, 2026 01:59
e86d741 to
ebb462f
Compare
antobinary
force-pushed
the
v3.0.x-develop
branch
from
July 18, 2026 02:02
e67e67b to
a0e203a
Compare
🚨 Automated tests failed |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix(presentation): render PDF transparency-group soft-mask images (bigbluebutton#23953)
Fixes #23953 — "[3.0] some specific embedded images in PDF are not converted".
What
Certain PDFs contain a figure (in the report: a black rectangle with a blurred/feathered edge, taken from
default.pdf's icon-shadow artwork) that is silently dropped during presentation conversion. The slide uploads "successfully" but renders completely blank. Reproduces across browsers and BBB versions.Why (root cause)
The figure lives inside a PDF transparency group (
/Group /S /Transparency) as an image with a soft mask (/SMask) + an ICCBased colorspace. poppler's cairo backend fails to composite this construct and emits nothing for it.BBB uses
pdftocairo(cairo backend) for both conversion paths, so both fail:pdftocairo -svg: produces a well-formed SVG that renders blank in the browser (cairo represents the group as a nested<mask>+<filter>alpha→luminance construct that browsers evaluate to fully transparent).pdftocairo -png: also blank — and it never even triggers here, because the blank SVG passes every existing threshold (image=3, path=5, use=5).Verified with the exact file from the report:
pdftocairo -svg(BBB primary)pdftocairo -png(BBB raster fallback)pdftoppm(poppler splash backend)gs(Ghostscript)So the bug is specific to poppler's cairo backend; the splash backend renders it correctly.
How (the fix)
Two-part fix in
bbb-common-web:Trigger the raster fallback when the generated SVG contains a cairo transparency-group soft mask. We gate on the
<filter>count, not<mask>:<filter>(feColorMatrixalpha→luminance) only for the blanking transparency-group construct.<mask>with zero<filter>and render fine — gating on<mask>would needlessly rasterize them (measured: it broke themoderator-new-presentationsnapshot; the<filter>gate does not).<mask><filter>uploadTest.png(alpha PNG)blurimage2.pdf(the bug)Rasterize the fallback with
pdftoppm(splash backend) instead ofpdftocairo -png(cairo).-singlefilewrites<root>.png, matching the existing temp-file handling — no other caller changes needed.A configurable
filterTagThreshold(default0= rasterize any slide with such a group) is wired throughdoc-conversion.xml/bigbluebutton.properties; the Java field defaults to0so behaviour is correct even without the XML wiring.History / how it was found & verified
blurimage2.pdffrom the issue;pdfimagesshowed animage+smask+ ICCBased colorspace.pdftocairo -svgand-pngboth blank;gsandpdftoppmcorrect.createAPI (base64-embedded doc) and confirmed inbbb-web.log: conversion reported "1 of 1 pages successfully converted" while the generatedslide1.svgrendered blank.0dark pixels; blank Slide 1 screenshot).tsc+eslintclean.Test
bigbluebutton-tests/playwright/presentation/presentation.spec.ts→ "Upload PDF with embedded soft-masked image renders (not blank)"bigbluebutton-tests/playwright/core/media/blurImage.pdf(the file from the report)getCurrentSlideDarkPixelRatio()fetches the slide SVG through the authenticated context, rasterizes it in-page via a same-origin blob URL onto a canvas (avoids canvas tainting), and asserts the near-black-pixel ratio > 0.02. Blank slide →0(fail); fixed → ~0.1 (pass).Files changed
bbb-common-web/.../presentation/imp/SvgImageCreatorImp.java—<filter>trigger +createRasterizationProcess()(pdftoppm)bbb-common-web/.../presentation/handlers/SvgConversionHandler.java—numberOfFilterTags()bigbluebutton-web/grails-app/conf/spring/doc-conversion.xml— wirefilterTagThresholdbigbluebutton-web/grails-app/conf/bigbluebutton.properties—filterTagThreshold=0(documented)bigbluebutton-tests/playwright/presentation/{presentation.spec.ts,presentation.ts,util.ts}— regression test + helperbigbluebutton-tests/playwright/core/elements.ts— fixture filename constantbigbluebutton-tests/playwright/core/media/blurImage.pdf— test fixture (new)Notes for reviewers
filterTagThreshold=0converts affected slides from vector to raster (only those containing the transparency-group soft mask). This is intended and safe (BBB already rasterizes for Type-3 fonts / high tag counts) and tunable.default.pdfpage 1 (the icon-shadow group) was also affected by this bug and now renders correctly.TODO — remaining (same root cause, out of scope of this commit)
The identical cairo-blank bug affects two other call sites that still use
pdftocairo -png. They produce a blank image for this PDF too and should be switched topdftoppm:bbb-common-web/.../presentation/imp/PngCreatorImp.java— the downloadable slide PNGbbb-common-web/.../presentation/imp/ThumbnailCreatorImp.java— the slide thumbnail