Por sugestão do sthysel, eu converti meu jpeg corrompido em um png, que revelou o problema e também me forneceu um png funcional que poderia ser carregado no lugar do jpeg.
$ convert bad.jpg okay.png
convert: Premature end of JPEG file 'bad.jpg' @ warning/jpeg.c/EmitMessage/228.
convert: Corrupt JPEG data: premature end of data segment 'bad.jpg' @ warning/jpeg.c/EmitMessage/228.
Olhando dentro do conteúdo real de bad.jpg, aparentemente faltavam os bytes EOF:
000d330: 8cbd e32f f164 95a4 4827 54e0 1264 8807 .../.d..H'T..d..
000d340: 8436 479f cd1e afa4 d9e3 0a .6G........
Então eu preenchi o arquivo com os bytes necessários, o que também funcionou para corrigir o jpeg.
000d330: 8cbd e32f f164 95a4 4827 54e0 1264 8807 .../.d..H'T..d..
000d340: 8436 479f cd1e afa4 d9e3 3fff d90a .6G.......?...