Display image only when it's completely decoded not working

I’m running a Raspberry Pi 3 in Chromium for a custom Spotify interface which displays the current song that’s played. While that works in itself, the transition between one song to another is extremely choppy and I just don’t know what to do anymore. What’s supposed to happen is that the image and background do not fade-in until the image is completely loaded, as in, it should not be cut in half.

But as you can see here, that is not the case (it’s only for a few frames, but you can clearly see how it first only shows a fifth of the cover art and then jumps to the full image): https://i.imgur.com/pQsQ26r.mp4

For reference, this is what is should look like: https://i.imgur.com/QWY1J38.gif

On a regular PC this is already super smooth, but I assume the RP3 is just too slow to get it all decoded in time. So, naturally, I thought my problem would be solved like this, but the results are still what you can see in the first video:

function changeImage(newImage) {
    var preloadImg = new Image();
    preloadImg.src = newImage;
    preloadImg.decode().then(() => {
        let artworkUrl = makeUrl(preloadImg.src);
        document.getElementById("artwork-img").style.backgroundImage = artworkUrl;
        document.getElementById("background-img").style.backgroundImage = artworkUrl;

function setArtworkOpacity(value) {
    // the smooth fade itself is done via CSS "transition: opacity 1s;"
    document.getElementById("artwork-img").style.opacity = value;
    document.getElementById("background-img").style.opacity = value;

I’ve also tried img.onload, same result.

Is this the wrong approach? Ideally there would be a function that goes "do not execute until image has been fully painted" in which case I’d move the setArtworkOpacity("1") into its callback, but I couldn’t find anything like that.

Leave a Comment