Shrink the oversized auto avatars into the box instead of cropping them

96x96 is the games' own sprite size and most of the pool is drawn inside it,
but 40 of the 702 slots are not: the animation's own canvas is wider or
taller, up to Lugia's 153x97, and -extent trimmed those to the box. That
does not frame a picture, it cuts one -- Thundurus-Therian lost 16px off
each side, Venomoth both wingtips, sliced flat at the frame edge.

The claim that the set the forum used to carry did the same holds for 39 of
the 40, which were clipped there too, but not for Venomoth: its animation
sat in 71x71 with margin on both sides and publishes at 96x74 today. Samurott
and Lugia were clipped in 2019 and are clipped harder now.

So -resize "96x96>" ahead of the extent. It only ever shrinks, so the 660
files already inside the box come out byte for byte what they were, and the
40 that don't arrive whole instead of trimmed. Resampling a 16-color picture
invents shades and the frames leave the resize carrying thousands of them,
which doubles what those 40 weigh (Thundurus-Therian 215KB -> 474KB);
-dither None -colors 64 puts them back on a palette at 298KB. 64 is above
every source palette in the pool, so it is a no-op on everything the resize
doesn't touch, bar Tomohawk, which the old pipeline quietly wrote two colors
short of its 28 and which now keeps them.

Checked over every source in the pool: 40 files change, no animation's union
leaves the box any more, and gifsicle -O3 alters no pixel of any of them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Christopher Monsanto
2026-08-23 20:15:16 -04:00
parent 8c3bdd0453
commit 71a062cbb0

View File

@@ -247,8 +247,15 @@ deploy(async ctx => {
// Forum auto avatars: the gen 5 animations on a uniform 96x96 box, which is
// what XenForo's avatar container is. It scales an <img> to fill, so a sprite
// published at its own aspect would arrive stretched; the box is the games' own
// sprite size, so nothing is scaled up, and the few animations that overflow it
// are cropped to it, which is what the set the forum used to carry did too.
// sprite size, so nothing is scaled up.
//
// The 40 slots whose animation is drawn wider or taller than the box -- a
// wingspan, mostly, and Lugia's is 153px of it -- are shrunk into it rather
// than cropped to it. The box is there to hold the picture, and an extent that
// trims one cuts the wings off flat at the frame edge. Resampling a 16-color
// picture invents shades, so the frames are requantized afterwards, which is
// what keeps those 40 from doubling in bytes; 64 is above every source palette
// here, so the slots that fit the box are untouched by it.
// The pool with its two second slots resolved, which is the set of pictures to
// build. See rules/avatars.ts for why it is a list and not a glob.
@@ -271,7 +278,7 @@ for (let f of spriteglob(['src/sprites/gen5/*.gif', 'src/sprites/gen5/xsubstitut
avatarArt.set(name, rule(f, {
display: 'avatar %f',
cmds: [
'magick convert %f -coalesce -background none -gravity center -extent 96x96 %o',
'magick convert %f -coalesce -background none -resize "96x96>" -dither None -colors 64 -gravity center -extent 96x96 %o',
'gifsicle -O3 -b %o',
],
}, `${name}.gif`));