gifwrap – FRAME 0 USES MORE THAN 256 COLOR INDEXES

I’ve built an algorithm that:

  • Reads an image from a file using jimp.
  • Prints some text in that image and overlays another image, both using jimp too.
  • Then, using gifwrap, it decodes an existing GIF into all of its images, converts them to Jimp objects, and then resizes them. Afterwards, it overlays them into the previously created image (also using jimp).
  • I then try to encode all of these images into one GIF using gifwrap but I get the following error: FRAME 0 USES MORE THAN 256 COLOR INDEXES
    public async generate() {
        await this._createBaseLayer();
        const frames: GifFrame[] = [];

        const nftGIF = await GifUtil.read(path.join(__dirname, '../gifs/monkey.gif')).catch(reason => {
            throw {
                message: reason,
                extraInfo: 'COULD NOT READ MONKEY GIF FILE',
            };
        });


        for (const frame of nftGIF.frames) {
            const baseLayer = this._baseLayer.clone();
            const jimpCopy: Jimp = GifUtil.copyAsJimp(Jimp, frame);
            jimpCopy.contain(this._measurements.nftGIF.width, this._measurements.nftGIF.height);

            baseLayer.blit(jimpCopy, (this._measurements.base.width - this._measurements.nftGIF.width) / 2, (this._measurements.base.height - this._measurements.nftGIF.height - 50) / 2);

            const gifFrame = new GifFrame(jimpCopy.bitmap);
            GifUtil.quantizeDekker(gifFrame, 256); //THIS TAKES FOREVER
            frames.push(gifFrame);
        }

        const codec = new GifCodec();

        const gif = await codec.encodeGif(frames, {
            loops: 0,
        });

        this._buffer = gif.buffer;
    }
    private async _createBaseLayer() {
        const baseImage = await Jimp.read(path.join(__dirname, '../shapes/speech.png')).catch(reason => {
            throw {
                message: reason,
                extraInfo: 'COULD NOT READ SPEECH SHAPE FILE',
            };
        });

        const profileImage = await Jimp.read(this._user.profileImageURL).catch(reason => {
            throw {
                message: reason,
                extraInfo: 'COULD NOT READ PROFILE IMAGE FILE',
            };
        });

        baseImage.blit(
            profileImage,
            this._measurements.userIdentification.margins.left,
            this._measurements.base.height - this._measurements.userIdentification.profileImage.height - this._measurements.userIdentification.margins.bot,
        );

        const font = await Jimp.loadFont(Jimp.FONT_SANS_32_WHITE).catch(reason => {
            throw {
                message: reason,
                extraInfo: 'COULD NOT LOAD FONT',
            };
        });

        baseImage.print(
            font,
            this._measurements.userIdentification.margins.left + this._measurements.userIdentification.profileImage.width + this._measurements.userIdentification.profileImage.margins.right,
            this._measurements.base.height - this._measurements.userIdentification.profileImage.height - this._measurements.userIdentification.margins.bot,
            this._user.username,
        );

        this._baseLayer = baseImage;
    }

I have found a couple of users on the GitHub repository with the same issue:

The only “solution” I’ve found is to call quantizeDekker on each of the GifFrames created from the Jimp objects (for each frame of the GIF), but it is extremely slow.