javascript - Hafif bir tarayıcı JS kütüphanesi (omggif gibi) kullanarak gif'ten kareler çıkarma


Bir gif dosyasından tarayıcıda kareler çıkarmak istiyorum. Daha spesifik olarak, bir gif'in url'si verildiğinde gifUrl: string, onu indirip kareler dizisi olarak elde etmek istiyorum imageList: ImageData[]). Bunları bir kanvasın çeşitli koordinatlarında putImageData ile kullanacağım. Çözümün ayrıca hafif olmasını da istiyorum.

BundlePhobia'da, omggif emerging-3G üzerinden indirilmesi 50ms sürüyor. Şimdiye kadar gördüğüm tüm alternatifler ise yaklaşık 700ms civarında. Ancak, omggif sadece temel düzeyde etkileşimler sunuyor ve bir GIF'i ImageData dizisi olarak alma gibi yaygın tarifler eksik.

Şimdiye kadar omggif için bulduğum en iyi dokümantasyon, DefinitelyTyped projesindeki omggif türleridir.

Ayrıca movableink'in örneği de var (Ocak 2019'dan beri bir PR'da bekliyor).

TypeScript kullanıyorum ve bu nedenle mümkünse tipli tariflerle ilgileniyorum.

İlgili sorular:

  • JavaScript kullanarak animasyonlu bir GIF'ten kareler nasıl çıkarılır? [kapalı]
  • Kare kontrolü ile tuval üzerinde GIF animasyonu

Cevap #1

İşte bunu yapma şekli:

import { GifReader } from 'omggif';

export const loadGifFrameList = async (
    gifUrl: string,
): Promise<ImageData[]> => {
    const response = await fetch(gifUrl);
    const blob = await response.blob();
    const arrayBuffer = await blob.arrayBuffer();
    const intArray = new Uint8Array(arrayBuffer);

    const reader = new GifReader(intArray as Buffer);

    const info = reader.frameInfo(0);

    return new Array(reader.numFrames()).fill(0).map((_, k) => {
        const image = new ImageData(info.width, info.height);

        reader.decodeAndBlitFrameRGBA(k, image.data as any);

        return image;
    });
};

Şeffaflığa ihtiyacınız varsa, daha sonra ctx.drawImage(canvas, x, y) ile ara yüz oluşturulabileceğinden canvas kullanmak isteyebilirsiniz:

import { GifReader } from 'omggif';

export const loadGifFrameList = async (
    gifUrl: string,
): Promise<HTMLCanvasElement[]> => {
    const response = await fetch(gifUrl);
    const blob = await response.blob();
    const arrayBuffer = await blob.arrayBuffer();
    const intArray = new Uint8Array(arrayBuffer);

    const reader = new GifReader(intArray as Buffer);

    const info = reader.frameInfo(0);

    return new Array(reader.numFrames()).fill(0).map((_, k) => {
        const image = new ImageData(info.width, info.height);

        reader.decodeAndBlitFrameRGBA(k, image.data as any);

        let canvas = document.createElement('canvas');

        canvas.width = info.width;
        canvas.height = info.height;

        canvas.getContext('2d')!.putImageData(image, 0, 0);

        return canvas;
    });
};