Wikimedia Developer Support

Embedding Wikimedia Commons images in tools with multiple resolutions (srcset)

My tool Wikidata Image Positions embeds an image from Wikimedia Commons; as it’s sometimes used with rather large images, I also want to include a scrset attribute on the image so that users on smaller displays don’t have to load the full-size image.

Currently, it’s implemented like this:

<img src="{{ image_title_ }}"
     srcset="{{ image_title_ }}?width=320 320w,
   {{ image_title_ }}?width=640 640w,
   {{ image_title_ }}?width=1024 1024w,
   {{ image_title_ }}?width=1280 1280w,
   {{ image_title_ }}?width=1920 1920w,
   {{ image_title_ }}?width=3840 3840w,
   {{ image_title_ }}?width=4096 4096w">

(Where {{}} is Jinja syntax and image_title_ is the title with spaces converted to underscores.)

This works, but is somewhat inefficient – as @Tgr pointed out in an answer to another question, using Special:FilePath bypasses the cache and issues several redirects. The list of resolutions is also fairly arbitrary (I think I based it on enwiki’s list of common resolutions), and probably not server-friendly: if other places typically request thumbnails in other widths, then the thumbnails my tool requests probably don’t exist yet and will also take up extra disk space. And finally, going through Special:FilePath prevents me from using cropperjs (the library used by CropTool), because that wants to load the image via JS, and the redirect responses don’t include CORS headers (only the image response does).

What should I do instead? I think I have two related, but separate problems:

  1. I need a list of resolutions (widths) for which thumbnails are likely to exist, which is shared with other places.
  2. I need a way to go from a file path and a list of resolutions (widths) to a list of corresponding thumbnail URLs.

For the list of resolutions, I thought I saw some API a while ago, but the closest I can find now are the imagelimits in action=query&meta=siteinfo (corresponding to $wgImageLimits) – but those seem to be intended for something else, and don’t correspond to the “other resolutions” on an individual file’s page as far as I can tell.

For getting the URLs, I assume the canonical way to do it is action=query&prop=imageinfo&iiprop=url&iiurlwidth=PIXELS, but that would mean I would have to make one API request per resolution. Alternatively, I can try to compute the URL directly (it’s based on the MD5 hash of the file name), but as @Tgr points out in another reply this can be fragile. Or I could merge the two approaches, and ask the API for one thumbnail URL and then replace the pixel number inside it to get the other URLs? But that would still require a lot of assumptions about the URL format, so I’m not convinced this would be any better than just creating the URL from scratch.

  • The sizes in $wgUploadThumbnailRenderMap are guaranteed to exist. On Wikimedia wikis it is set to 320, 640, 800, 1024, 1280, 1920.
  • The default user option for $wgThumbLimits (that is, $wgThumbLimits[$wgDefaultUserOptions['thumbsize']]) is very likely to exist. This is the size in which the image will be rendered in articles if the article author has not specified an explicit size and the user has not changed their preferences. On Wikimedia wikis this is 220. (If you think that’s ridiculously small, you might be interested in T51357 and T71973.)
  • The default user option for $wgImageLimits is very likely to exist. That’s the size (bounding rectangle to be exact) in which images are shown on file description pages if the user has not changed their preferences. On Wikimedia wikis this is currently 800x600. The other sizes are somewhat likely to exist as well as they are shown as links on image pages and people tend to click them. (320x240, 640x480, 1024x768, 1280x1024.)
  • The sizes in $wgThumbnailBuckets are always going to exist, unless the full image size is not much larger. These are used as intermediaries to speed up image scaling. On Wikimedia wikis this is 1920, for images above 2020 px.
  • The sizes in the default MediaViewer buckets are mostly going to exist (less likely for larger sizes since those will only be rendered on huge screens). MediaViewer “snaps” images to these sizes and uses browser-side scaling to bridge the remaining gap.

In practice I would probably just go with $wgUploadThumbnailRenderMap; if it has been set reasonably, it will overlap with the others anyway. (Although $wgImageLimits might differ for tall images since it’s calculated differently.)

None of this is currently exposed in siteinfo ($wgImageLimits and $wgThumbLimits are, but you can’t tell which value is the default). Patches welcome!

Multiple sizes in a single imageinfo request is T56035 (should be fairly easy). Having a predictable thumb URL is T66214.

Deriving a thumb URL from another thumb URL is mostly safe (although complicated), you can see how MediaViewer does it. With two limitations: Wikimedia wikis only (in general there are very little limitations on what a media handler can do with the file URL, so you can only account for known handlers), and there is no way to guess the URL of a JPG thumbnail that has the exact same size as the original image (it might end up to be the original URL, or a thumbnail-like URL, depending on whether the image has an EXIF rotation).

1 Like

Well, I tried – I would appreciate some help with the blocker mentioned in the commit message (I can do the TODOs myself, I just didn’t want to spend more time on it before getting the blocker resolved).

Just as a note, the caching behaviour of Special:FilePath is a little bit better now (Once upon a time someone used it in a central notice which caused problems. Now its cached!). Of course a direct link to the file will still always be better.

1 Like