From ecf7db176b073842aedfb5f70226021d1b88f2f2 Mon Sep 17 00:00:00 2001 From: Francesc Leveque Date: Sun, 17 May 2026 01:01:57 +0200 Subject: [PATCH] Ask Wikimedia for a rasterized PNG instead of raw SVG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After yesterday's librsvg install (#21), the next REP.MC request still hung at processing — turns out the Alpine `vips` package is compiled WITHOUT rsvg support (verified via `vips --vips-config`), so installing librsvg as a runtime lib does nothing. libvips can't load it. Fortunately Wikimedia exposes server-side rasterization via the `Special:FilePath/?width=N` endpoint: when the source is SVG it redirects to a thumbnail-server PNG; when it's already a raster the query param is ignored. Either way, our downstream libvips pipeline only sees PNG bytes — which it handles fine without librsvg. Sandbox-verified: hit Special:FilePath/Repsol_logo.svg?width=512 → HTTP 301 → upload.wikimedia.org/...//960px-Repsol_logo.svg.png → real PNG (960×240, 8-bit RGBA). 512 chosen so the largest output size (xl=256px) downsamples cleanly with headroom. Co-Authored-By: Claude Opus 4.7 (1M context) --- internal/provider/wikidata_provider.go | 11 ++++++++++- internal/provider/wikidata_provider_test.go | 3 +++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/internal/provider/wikidata_provider.go b/internal/provider/wikidata_provider.go index 94ffeef..d3f7187 100644 --- a/internal/provider/wikidata_provider.go +++ b/internal/provider/wikidata_provider.go @@ -34,6 +34,12 @@ type WikidataProvider struct { const ( wikidataAPI = "https://www.wikidata.org/w/api.php" commonsFile = "https://commons.wikimedia.org/wiki/Special:FilePath/" + // Wikimedia rasterizes SVGs server-side when you append `?width=`. Asking + // for ~512px gives us a PNG large enough to downsize to our biggest output + // (xl=256px) without quality loss, but small enough to download fast. This + // means our image processor (libvips, compiled without rsvg on Alpine) + // only ever sees PNGs from this provider. + commonsThumbWidth = 512 ) func NewWikidataProvider(logger *zap.Logger) *WikidataProvider { @@ -63,7 +69,10 @@ func (w *WikidataProvider) GetLogo(ctx context.Context, symbol, companyName stri return nil, fmt.Errorf("wikidata P154 for %s: %w", entityID, err) } - logoURL := commonsFile + url.PathEscape(filename) + // Wikimedia gives us a server-rasterized PNG when the file is an SVG and we + // append `?width=`. For non-SVG files the query param is ignored and we get + // the original. Either way, libvips downstream just sees a raster image. + logoURL := fmt.Sprintf("%s%s?width=%d", commonsFile, url.PathEscape(filename), commonsThumbWidth) data, err := w.downloadImage(ctx, logoURL) if err != nil { return nil, fmt.Errorf("downloading %s: %w", logoURL, err) diff --git a/internal/provider/wikidata_provider_test.go b/internal/provider/wikidata_provider_test.go index 4ec7d6d..023abd3 100644 --- a/internal/provider/wikidata_provider_test.go +++ b/internal/provider/wikidata_provider_test.go @@ -67,6 +67,9 @@ func TestWikidataProvider_GetLogo_Success(t *testing.T) { if !strings.Contains(result.OriginalURL, "Diageo") { t.Errorf("OriginalURL should contain the filename: %q", result.OriginalURL) } + if !strings.Contains(result.OriginalURL, "width=") { + t.Errorf("OriginalURL should ask Wikimedia to rasterize SVG → PNG via width=: %q", result.OriginalURL) + } if result.Source != "wikidata:Q161140" { t.Errorf("Source = %q", result.Source) }