Skip to content

Stop white lines along the edges of full-page pictures (BL-17009) - #8459

Open
hatton wants to merge 1 commit into
masterfrom
BL-17009-image-white-lines
Open

hatton wants to merge 1 commit into
masterfrom
BL-17009-image-white-lines

Conversation

@hatton

@hatton hatton commented Oct 9, 2026 •

Copy link
Copy Markdown
Member

[Claude Sonnet 5.5 from Hatton's machine during preflight]

Problem

When a picture is meant to fill its area, a thin white line often shows along one or more of its edges. It happens most after the author drags the origami splitter until the picture looks like it fills its pane, and with Fit Space / Expand to Fill Space. The line is most noticeable where the picture runs to the edge of the page.

Cause

Bloom fits a background picture inside its picture area (the bloom-canvas) without cropping. Origami split positions are percentages, so the area is almost never exactly the picture's shape, and a sliver of 0.02–0.3px is left over. Fit Space had the same problem, because it sized to the whole-pixel clientWidth/clientHeight. On top of that, Chrome snaps an img to whole pixels in the page's own coordinates before it applies the Edit tab's zoom, so the drawn picture can stop up to another half pixel short of its box. Either way, the white page shows through.

Magnified top edge of a picture, before and after this change

Fix

  • adjustBackgroundImageSizeToFit now makes the picture overhang each edge of the bloom-canvas that it reaches (or comes within 2px in total of filling) by 1px. The bloom-canvas already clips its contents (overflow: hidden), so the overhang is never seen. This applies in both fit modes (contain, and cover from Expand to Fill Space). The picture keeps its aspect ratio, and a cropped picture keeps its crop.
  • Pages fitted before this change re-fit once when they are opened, so existing books get the fix without anyone touching the splitter.
  • When the origami splitter resizes a pane, overlays on the picture (bubbles, text boxes) keep their place: the code that repositions them now works out the size the picture was fitted to from its size and centred position, so the overhang isn't mistaken for a stale size record.
  • Fit Space counts as already done when the drawn picture covers the whole picture area, is centred, and is enlarged no more than the overhang explains. Otherwise the overhang would keep the command enabled after it has run.

Does every picture now lose a pixel on every side?

No.

  • Only the background picture of a picture area (the picture an origami pane holds). Pictures in canvas elements on top of it are not touched.
  • Only on the edges it reaches. That means edges that touch the edge of the picture area, or come within 2px of it. A picture that is letterboxed, say with white above and below, keeps those edges whole. It gets about 2px wider and stays centred.
  • About 1 CSS px is hidden on each edge it reaches. For a 400px-wide picture that is a quarter of one percent. A picture set to Expand to Fill Space is already cropped, and loses 1px more on each side.
  • It is applied in every theme, but the line it fixes only showed in some places. A white sliver is only visible where what lies beyond the picture's edge isn't white: at a page edge with no white padding (the edge-to-edge theme, against the dark Edit-tab background or a device's black surround), or next to a page or pane with a background color, such as a cover color. In themes with white padding, the sliver was white against white. The overhang is stored in the page as the picture's size and position, not added by a stylesheet, so the 1px cost is paid there too, and in published output.

Not addressed: where a picture runs to the edge of the page and that edge falls partway through a screen pixel, the last pixel column still comes out light gray. Chrome anti-aliases the white page background and the clipped picture separately at the same edge. Fixing it would mean changing the Edit tab's zoom or how the page clips its contents.

Risk Evaluation

The change runs through adjustBackgroundImageSizeToFit, which every background picture passes through: page load (for pages that need the one-time re-fit), origami resizes, image changes, Fit Space and Expand to Fill Space. It changes the background element's stored geometry: left/top become about -1px on edges it fills, and width/height grow by about 2px. Code that compares the background element's size with the bloom-canvas is where to look hardest: Fit Space's "already done" check and the overlay repositioning on an origami resize (CanvasElementResizeAdjustments.ts) are both updated for it. Rotation (imageContentTransform.ts) and the origami auto-fit (autoFitImageOverTextSplits.ts) use the element's aspect ratio, and the overhang doesn't change it.

The one-time re-fit on load means each existing page with a fill-to-edge picture gets one saved change the first time it is opened in the Edit tab. After that, nothing changes on later visits.

Ecosystem Impact

  • Published output (Bloom Player, BloomPUB, ePUB, PDF): these render the stored geometry with the book's own CSS, and basePage.less gives every .bloom-canvas overflow: hidden, so the overhang is clipped there too. I didn't view a published book.
  • Older Bloom versions opening a book saved by this version see ordinary px geometry; the picture is about 1px larger and offset by -1px, which they clip the same way. Not tested.
  • No new dependencies, strings, or C# changes.

E2E Coverage

No e2e test covers this. The change is sub-pixel geometry, and the existing canvas e2e specs neither assert background-image geometry nor look at screenshots that fine. New unit tests cover the sizing rule, Fit Space's "already done" check (wide canvases, near misses, author crops, off-centre crops), and overlays keeping their place when an overhanging background's pane is widened. The behavior was checked by screenshotting every page of an affected book in a running Bloom before and after, and measuring each picture edge.

Notion Test Suite

None.

Preflight report: https://bloombooks.github.io/dev-process-artifacts/deciders/bloomdesktop-bl-17009-image-white-lines.html

Ref: https://issues.bloomlibrary.org/youtrack/issue/BL-17009

🤖 Generated with Claude Code

Devin review


This change is Reviewable

@hatton

hatton commented Oct 9, 2026

Copy link
Copy Markdown
Member Author

[Claude Opus 5.5 from Hatton's machine during preflight] Consulted Devin on 2026-10-09 19:36 UTC up to commit c2627f872f. The first round (9ba6ab17a6) raised two bugs: overlays pinned to the left after an origami resize, and Fit Space unable to re-centre an off-centre crop. Both were fixed in c2627f872f, and Devin's re-review marks both resolved, with no new findings and no flags. See the two resolved review threads.

A background picture meant to fill its picture area (bloom-canvas) showed a
thin white line along one or more edges. The fit is "contain", and origami
split positions are percentages, so a picture lined up with its pane is
almost never an exact fit and the sliver left over shows the white page.
Chrome also snaps an img to whole pixels before applying the editor's zoom,
so the drawn picture can stop up to half a pixel short of its box.

- adjustBackgroundImageSizeToFit makes the picture overhang each edge it
  reaches (or comes within 2px of filling) by kBackgroundImageBleedPx (1px),
  in both contain and cover modes; the bloom-canvas clips the overhang.
  Aspect ratio and crops are kept.
- Pages fitted before this re-fit once when opened.
- Fit Space counts as already done when the picture covers the whole
  bloom-canvas, is centred, and is enlarged no more than the bleed explains.
- Overlay repositioning on an origami resize derives the size the picture
  was fitted to from its size and centred offset, so the overhang isn't
  taken for a stale size record.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@hatton
hatton force-pushed the BL-17009-image-white-lines branch from c2627f8 to b4024cc Compare October 9, 2026 19:47
@hatton
hatton marked this pull request as ready for review October 9, 2026 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant