Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dispose 2 not working with transparent gifs #15

Open
nicolaschapeau opened this issue Jun 3, 2023 · 2 comments
Open

Dispose 2 not working with transparent gifs #15

nicolaschapeau opened this issue Jun 3, 2023 · 2 comments

Comments

@nicolaschapeau
Copy link

nicolaschapeau commented Jun 3, 2023

Hey!

Great work with the library it's really fast!

I stumbled on a problem recently which is transparent gifs seems to have each frame stack on each other.

I looked at the source code and found out I had to put dispose = 2 to fix that but it seems to not work.

Here is my code, it's a simple worker that take a gif as a data64 url and newDuration.
The goal is simple modify the duration of the gif by adding or removing delay between frames.

async function adjustGifDuration({ src, newDuration }: { src: string; newDuration: number }) {
    // Get frames from gif
    const frames = await gifFrames({
        url: src,
        frames: 'all',
        outputType: 'png',
        cumulative: true
    });

    // Get current duration
    const currentDuration =
        frames.reduce((total: any, frame: any) => total + frame.frameInfo.delay, 0) / 100;

    // Calculate ratio
    const ratio = newDuration / currentDuration;

    // Create encoder
    const encoder = new GIFEncoder();

    // Create palette rgba 256
    const rgbaData = frames[0].getImage().data;
    const palette = quantize(rgbaData, 256, {
        format: 'rgba4444'
    });

    for (let i = 0; i < frames.length; i++) {
        const frame = frames[i];

        // Get frame image
        const image = frame.getImage().data;

        // Apply palette to image
        const index = applyPalette(image, palette, 'rgba4444'); //rgba4444

        // Add frame to encoder
        encoder.writeFrame(index, frame.getImage().width, frame.getImage().height, {
            palette,
            delay: frame.frameInfo.delay * ratio,
            transparent: true,
            transparentIndex: 0,
            dispose: 2
        });

        // Update progress
        postMessage({ type: 'progress', progress: (i / frames.length) * 100 });
    }

    // Write end-of-stream character
    encoder.finish();

    // Get the Uint8Array output of the binary GIF file
    const output = encoder.bytes();

    // Convert the Uint8Array to a Buffer object
    const buffer = Buffer.from(output);

    return buffer;
}

Everything else seems to work fine, but this is a kind of a huge problem for me, would be glad to know if I did something wrong or if there is a problem with the library!

Regards, Nicolas.

Video.sans.titre.Realisee.avec.Clipchamp.5.mp4
@shankiflang
Copy link

I had the same problem and couldn't find a solution! Maybe here we'll have an answer! @mattdesl ?

@mattdesl
Copy link
Owner

I haven't attempted to run your code but in my own tests with the Looom exporter, transparency seems to have worked OK.

Here's how I've set it up:
https://github.com/mattdesl/looom-tools/blob/main/site/components/gifworker.js

If there is a reproducible test case showing the error I can dig into it a bit more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants