高效 GIF 帧提取:使用 omggif 库解析 GIF 动画并优化渲染性能
import {GifReader} from 'omggif';
const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); let imageData; let previousData;
export default (arrayBuffer, onFrame) => { const gifReader = new GifReader(new Uint8Array(arrayBuffer)); const numFrames = gifReader.numFrames(); canvas.width = gifReader.width; canvas.height = gifReader.height; imageData = new Uint8ClampedArray(canvas.width * canvas.height * 4); previousData = new Uint8ClampedArray(canvas.width * canvas.height * 4);
const loadFrame = i => {
const framePixels = new Uint8ClampedArray(canvas.width * canvas.height * 4);
gifReader.decodeAndBlitFrameRGBA(i, framePixels);
const {x, y, width, height, disposal} = gifReader.frameInfo(i);
const indexOffset = 4 * (x + (y * canvas.width));
for (let row = 0; row < height; row++) {
for (let column = 0; column < width; column++) {
const j = indexOffset + (4 * (column + (row * canvas.width)));
const alpha = framePixels[j + 3];
imageData[j + 0] = alpha ? framePixels[j + 0] : imageData[j + 0];
imageData[j + 1] = alpha ? framePixels[j + 1] : imageData[j + 1];
imageData[j + 2] = alpha ? framePixels[j + 2] : imageData[j + 2];
imageData[j + 3] = alpha ? framePixels[j + 3] : imageData[j + 3];
}
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.putImageData(new ImageData(imageData, canvas.width, canvas.height), 0, 0);
switch (disposal) {
case 2: // 'Return to background', blank out the current frame
ctx.clearRect(x, y, width, height);
imageData.set(previousData);
break;
case 3: // 'Restore to previous', copy previous data to current
imageData = previousData.slice();
break;
default: // 0 and 1, as well as 4+ modes = do-not-dispose, so cache frame
previousData.set(imageData);
break;
}
onFrame(i, canvas.toDataURL(), numFrames);
if (i < numFrames - 1) {
requestAnimationFrame(() => {
loadFrame(i + 1);
});
}
};
loadFrame(0);
};
原文地址: https://www.cveoy.top/t/topic/nHUI 著作权归作者所有。请勿转载和采集!