Summary
detect_columns never runs its geometry on pages with fewer than 20 text items, and every fallback path has an equal or higher floor — so sparse two-column pages (large-print children's books: one PDF page = two book pages, ~7 lines per column) are always reported single-column, and the extracted markdown interleaves the two columns line-by-line.
Details
In extractor/layout.rs (v1.17.0):
detect_columns early-returns a single region when page_items.len() < 20 (line ~151).
- The relative-valley fallback needs
page_items.len() >= 30.
- The XY-cut fallback (
try_xy_cut_split) needs page_items.len() >= 20, plus MIN_ITEMS_MAJOR = 10 on the major side.
- The prose gate (
columns_have_prose) needs MIN_LINES = 8 per column.
A large-print book spread has ~7 lines per column — it falls under every floor, no matter how obvious the gutter.
Real-world example
A Catalan children's book PDF (5 pages, Mixed type). Page geometry from extract_text_with_positions_mem (text items only; one image placeholder per page filtered out):
page 3: 15 items
x= 65.2.. 271.8 y=492.7 "de mans senzills, com el de fer "
x= 65.2.. 280.8 y=470.7 "desaparéixer una moneda entre "
x= 83.6.. 266.7 y=514.7 "Va començar aprenent jocs "
x= 208.6.. 320.3 y=275.2 "...ara no la veieu!"
x= 416.7.. 573.8 y=492.7 "on ningú s'ho esperava:"
x= 435.1.. 636.7 y=514.7 "I, en acabant, fer-la aparéixer "
x= 435.1.. 648.0 y=470.7 "—Atenció! Què tens ací, darrere "
...
Left cluster x≈65–320, right cluster x≈415–710 — a ~95pt gutter, line-scale items, 8–17 items per page. Trivially separable by a largest-gap sweep, but below every item-count floor. The two columns share y-coordinates, so single-column grouping merges them line-by-line into mid-word interleaved text ("Va començar aprenent jocs I, en acabant, fer-la aparéixer…").
Suggestion
The floors exist to keep sparse single-column pages (covers, title pages) from false-splitting — that concern is real, but it could be preserved while admitting this class, e.g.:
- Let
try_xy_cut_split run at lower item counts (it needs no histogram density) with scaled floors — e.g. MIN_ITEMS_MAJOR/MINOR ≈ 3, but require a wider gap for sparse pages (absolute ≥ ~24pt or ≥ ~4% of page width) so only unambiguous gutters qualify.
- Or gate a sparse-page path on the gap being large relative to both column widths, keeping dense-page behavior unchanged.
Happy to provide the sample PDF privately if useful for a regression test.
Summary
detect_columnsnever runs its geometry on pages with fewer than 20 text items, and every fallback path has an equal or higher floor — so sparse two-column pages (large-print children's books: one PDF page = two book pages, ~7 lines per column) are always reported single-column, and the extracted markdown interleaves the two columns line-by-line.Details
In
extractor/layout.rs(v1.17.0):detect_columnsearly-returns a single region whenpage_items.len() < 20(line ~151).page_items.len() >= 30.try_xy_cut_split) needspage_items.len() >= 20, plusMIN_ITEMS_MAJOR = 10on the major side.columns_have_prose) needsMIN_LINES = 8per column.A large-print book spread has ~7 lines per column — it falls under every floor, no matter how obvious the gutter.
Real-world example
A Catalan children's book PDF (5 pages, Mixed type). Page geometry from
extract_text_with_positions_mem(text items only; one image placeholder per page filtered out):Left cluster x≈65–320, right cluster x≈415–710 — a ~95pt gutter, line-scale items, 8–17 items per page. Trivially separable by a largest-gap sweep, but below every item-count floor. The two columns share y-coordinates, so single-column grouping merges them line-by-line into mid-word interleaved text ("Va començar aprenent jocs I, en acabant, fer-la aparéixer…").
Suggestion
The floors exist to keep sparse single-column pages (covers, title pages) from false-splitting — that concern is real, but it could be preserved while admitting this class, e.g.:
try_xy_cut_splitrun at lower item counts (it needs no histogram density) with scaled floors — e.g.MIN_ITEMS_MAJOR/MINOR ≈ 3, but require a wider gap for sparse pages (absolute ≥ ~24pt or ≥ ~4% of page width) so only unambiguous gutters qualify.Happy to provide the sample PDF privately if useful for a regression test.