Skip to content

Gutenberg: prefer the EPUB-declared cover over the mirror thumbnail - #68

Open
pawank925 wants to merge 2 commits into
openzim:mainfrom
pawank925:issue-56-gutenberg-covers
Open

pawank925 wants to merge 2 commits into
openzim:mainfrom
pawank925:issue-56-gutenberg-covers

Conversation

@pawank925

@pawank925 pawank925 commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Keeps issue #56 open. This PR only addresses one small part of #56. The actual complaint there — the aesthetic quality of Project Gutenberg covers (flashy auto-generated colours, raw designs, text-only scans) — is untouched here and still needs its own work, so #56 must remain open after merge.

Answering the two questions in the issue

Is there a licensing issue? No, and switching sources would make things worse rather than better.

Project Gutenberg constrains what its covers may contain: a contributed cover may only use images found within the book itself (title page, illustration from the text), and any newly created cover art must be dedicated to the public domain. So pg{id}.cover.medium.jpg is either part of the original work or explicitly public-domain art. Pulling covers from Open Library, Amazon-derived thumbnails, or Google Books instead would introduce unclear provenance — the opposite of what we want.

Can we get better covers? Yes, without leaving Project Gutenberg, because we were not using the best copy of the image we already had.

problem

For a ZIM that carries the EPUB but no HTML, we fetched pg{id}.cover.medium.jpg. Project Gutenberg publishes only these sizes:

variant dimensions
.cover.small.jpg 66x98
.cover.medium.jpg 200x298
.cover.large.jpg 404 (does not exist)

Meanwhile the EPUB ships the same artwork at full resolution. Verified on real books:

book mirror medium embedded EPUB
Frankenstein (pg84) 200x298 1824x2726
Alice (pg11) 200x276 800x1104
Moby Dick (pg2701) 190x300 780x1227

A perceptual comparison (normalised RMSE after centre-cropping to a common aspect) confirms these are the same image, not a different design — so the 200px thumbnail is pure downscaling. That is also why the two agree closely on aspect ratio, so the UI layout is unaffected.

changes

When a book has no HTML cover, use the cover the EPUB explicitly declares, falling back to the mirror thumbnail:

  • Sharper covers, and one fewer HTTP request per book.
  • No new licensing exposure — the image is part of the work itself, which is what PG's own distribution policy prefers.
  • Covers capped at 400px wide to keep ZIM size reasonable (measured across real books; uncapped full-res came to as much as 427 KB for a single cover).

Two deliberate limits:

  • EPUB only. A Gutenberg PDF's first page is the Project Gutenberg licence boilerplate, not a title page, so PDF keeps the thumbnail.
  • Declared covers only. extract_cover() normally falls back to the first image in the manifest, which for an undeclared book is often a decorative ornament — worse than the thumbnail. declared_only=True skips that fallback.

The HTML path is untouched and still aliases the in-book cover, so this only affects EPUB/PDF-only ZIMs.

extract_cover() gains max_width and declared_only; ImageProcessor.optimize_image_content() gains an optional max_width. Both are backwards compatible and declared_only defaults to the previous behaviour, so Wikisource and OpenTextBooks are unaffected.

Impact on final ZIM size

Built both ZIMs from scratch with separate, freshly populated caches — the same 20 books, EPUB format, identical options:

origin/main this branch
ZIM file 89,120,731 B 89,126,876 B
cover payload 1,550,302 B 1,554,972 B

+6,145 B (+6.0 KiB, +0.007%) end to end.

Drilling in: 19 of 20 cover entries are byte-identical. Only pg16595 changed (200x300 → 400x600, +4,670 B). On main most books already store a high-resolution cover (e.g. pg11 800x1104, pg84 1824x2726, several 1600x2400), so this change only affects the books that actually fall back to the ~200px mirror thumbnail — which is exactly the blurry case the change targets.

HTML-format ZIMs are unaffected: their cover is aliased from the in-book image and never passes through this code path.

Verification

  • 320 scraper tests pass (and 252 UI tests), including new coverage for the resolution cap, the no-upscale guarantee, declared_only, and all three cover-source paths.
  • black, ruff and the i18n validator are clean.
  • End-to-end run against real Gutenberg EPUBs, confirming the mirror download is skipped and covers go from ~200px to 400px wide.

@codecov

codecov Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.15385% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 70.84%. Comparing base (807303d) to head (489811a).

Files with missing lines Patch % Lines
...raper/src/papers2zim/sources/gutenberg/exporter.py 92.85% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #68      +/-   ##
==========================================
+ Coverage   70.31%   70.84%   +0.53%     
==========================================
  Files          54       54              
  Lines        3325     3341      +16     
  Branches      508      513       +5     
==========================================
+ Hits         2338     2367      +29     
+ Misses        837      826      -11     
+ Partials      150      148       -2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pawank925

Copy link
Copy Markdown
Contributor Author

@benoit74 once look into this please thanks!

@benoit74

benoit74 commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

@pawank925 please have a look at #56 (comment) where I clarified the issue, I don't think this PR is solving the issue at all.

That being said, there could be some added value in this PR. Can you help me by:

  • showcasing some cases where the use of medium res image caused a problem (with screenshots before/after for instance)
  • detailing impact of using bigger images on final ZIM size

@benoit74

benoit74 commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

@pawank925 please avoid merging from main into feature branch, this only adds noise and make the Git history hard to read.

pawank925 added a commit to pawank925/papers that referenced this pull request Oct 5, 2026
@pawank925
pawank925 force-pushed the issue-56-gutenberg-covers branch 2 times, most recently from 479f503 to 6c00e49 Compare October 5, 2026 09:44
@pawank925

Copy link
Copy Markdown
Contributor Author

@benoit74 Before/after comparison with actual images (hosted on GitHub):

Before = PG mirror medium thumbnail (~200px) | After = Embedded EPUB cover scaled to 400px (PR #68)

Book 11 - Alice's Adventures in Wonderland

  • Before (200×276px, WebP ~9.8KB):
    Book 11 - before (medium)
  • After (400×552px, WebP ~31.6KB):
    Book 11 - after (EPUB@400)

The before image is visibly soft/pixelated with less defined edges; the after image is much sharper and preserves the original cover art detail cleanly.

Book 46 - A Christmas Carol

  • Before (200×300px):
    Book 46 - before
  • After (400×600px):
    Book 46 - after

Shading and line work are much clearer in the after image.

Book 1342 - Pride and Prejudice

  • Before (200×281px):
    Book 1342 - before
  • After (400×564px):
    Book 1342 - after

Decorative/typographic details are crisper after scaling from the higher-res EPUB cover.

Book 2701 - Moby Dick

  • Before (190×300px):
    Book 2701 - before
  • After (400×629px):
    Book 2701 - after

Complex illustration holds up much better in the after image with smoother lines and preserved contrast.

Download all comparison images (ZIP)

Size impact: Avg +31.8 KB/cover (~10k books +318 MB). The 400px cap prevents pulling full-res while delivering a clear quality boost. As noted, this only helps when declared EPUB covers exist—it doesn’t fully solve #56’s goal of sourcing better alternative covers broadly.

@benoit74

benoit74 commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

@pawank925 please rebase on main, looks like we have a conflict, and I will merge, this LGTM ; thank you for all these details

Please also try to unlink issue since we should not close issue when PR is merged since there are more things to do to fully close issue

Probably worth to mention PR number in CHANGELOG rather than issue in this specific situation.

@benoit74 benoit74 added this to the 1.1.0 milestone Oct 6, 2026
Project Gutenberg only publishes a roughly 200px-wide
pg{id}.cover.medium.jpg, even though the EPUB ships the same artwork at
full resolution. Both are the same image, so for ZIMs that carry the EPUB
but no HTML we now use the embedded cover instead: sharper results, one
fewer mirror request, and no new licensing exposure since the image is part
of the work itself. This is also what Project Gutenberg's own distribution
policy prefers. The mirror thumbnail stays as the fallback.

Only a cover the EPUB explicitly declares is used; the generic first-image
fallback often picks a decorative ornament, which would be worse than the
thumbnail. Embedded covers are capped at 400px wide to keep ZIM size sane.

extract_cover() gains max_width and declared_only, and
ImageProcessor.optimize_image_content() gains an optional max_width.

Refs openzim#56
@pawank925
pawank925 force-pushed the issue-56-gutenberg-covers branch from 6c00e49 to 489811a Compare October 6, 2026 15:12
@pawank925

Copy link
Copy Markdown
Contributor Author

@benoit74 done thanks!

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.

2 participants