# gifa
**Repository Path**: devoink/gifa
## Basic Information
- **Project Name**: gifa
- **Description**: A GIF toolkit focused on frame decoding and composition, with extensible playback, frame extraction, and compression utilities.
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-01-19
- **Last Updated**: 2026-01-20
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# gifa
gifa:一个 GIF 工具箱,核心是 GIF 帧解析与合成,并在此基础上扩展播放、抽帧与压缩等能力。
## 功能特性
- ✅ 完整的 GIF 格式解析(GIF87a 和 GIF89a)
- ✅ 支持单帧和多帧 GIF
- ✅ LZW 解压算法实现
- ✅ 交错图像处理
- ✅ 透明色支持
- ✅ 动画帧提取(延迟时间、循环次数、处置方式)
- ✅ 全局和局部调色板支持
- ✅ 注释和扩展数据提取
- ✅ 输出每一帧的“完整画面” RGBA(`fullRgbaData`,可直接渲染/导出)
## 环境支持
- ✅ Node.js
- ✅ 浏览器(ESM / `
```
### Demo
项目内置了一个最小 demo:`demo/index.html`(上传 GIF、`GifPlayer` 播放控制、滑块切帧、渲染 `fullRgbaData`)。
### 播放控制(跨端)
`GifPlayer` 只依赖 `setTimeout`,可以在浏览器 / uniapp / 小程序 / Node 端使用。你只需要提供 `onRender` 回调决定“如何渲染一帧”。
```ts
import { GifParser, GifPlayer } from 'gifa';
const parser = new GifParser(uint8Array);
const frames = parser.getFrames();
const player = new GifPlayer(frames, {
loop: 'infinite',
speed: 1,
onRender: (frame, index) => {
// 在这里把 frame.fullRgbaData 画到 canvas / 推给 WebGL / 导出等
// console.log('render', index, frame.fullRgbaData.length);
}
});
player.play();
// player.pause();
// player.seek(10);
```
## Roadmap(计划开发)
以“帧级解码/合成”为核心,逐步补齐常见 GIF 工具能力:
- [ ] **浏览器播放器**:绑定 `canvas`,支持 `play/pause/seek/speed/loop`,并支持事件回调
- [ ] **抽帧**:导出指定帧为 PNG(浏览器 Blob / Node Buffer)
- [ ] **压缩**:尺寸缩放、降帧率、调色板量化(质量/体积权衡可配置)
- [ ] **裁剪/缩放**:按 ROI 裁剪、按目标尺寸缩放
- [ ] **信息分析**:统计透明像素比例、变化区域、帧矩形分布等
- [ ] **流式/增量 API**:大 GIF 逐帧产出,降低内存占用
## `rgbaData` vs `fullRgbaData`
- **`fullRgbaData`(必有,推荐)**:每帧“完整画布”的 RGBA,尺寸恒为 `screen.width * screen.height * 4`,已按透明索引与处置方式完成帧合成,可直接渲染/导出。
- **`rgbaData`(可选)**:帧自身图像块(可能是局部矩形)的 RGBA,尺寸为 `descriptor.width * descriptor.height * 4`,不包含画布位置信息的展开,也不包含与前一帧的合成结果;适合做增量渲染或自行实现合成器。
## API(核心)
### GifParser
主解析器类。
#### 构造函数
```typescript
constructor(data: Uint8Array, options?: { onWarning?: (message: string) => void })
```
- `data`: GIF 文件的二进制数据(Uint8Array)
- `options.onWarning`: 非致命问题回调(默认静默)
#### 方法
##### `parse(): GifData`
解析整个 GIF 文件,返回完整的 GIF 数据结构。
##### `getFrames(): Frame[]`
获取所有帧的数组。
##### `getFrameFullRgbaData(frameIndex: number): Uint8Array`
获取指定帧的“整帧画面” RGBA 数据(与 `frames[frameIndex].fullRgbaData` 等价)。
##### `getMetadata()`
获取 GIF 的元数据:
- `width`: 画布宽度
- `height`: 画布高度
- `frameCount`: 帧数
- `loopCount`: 循环次数(undefined 表示无限循环)
- `hasGlobalColorTable`: 是否有全局调色板
- `globalColorTableSize`: 全局调色板大小
### 类型定义
#### GifData
完整的 GIF 数据结构:
```typescript
interface GifData {
header: GifHeader;
screenDescriptor: LogicalScreenDescriptor;
globalColorTable?: ColorTable;
frames: Frame[];
loopCount?: number;
comments?: string[];
}
```
#### Frame
帧数据:
```typescript
interface Frame {
descriptor: ImageDescriptor;
graphicControl?: GraphicControlExtension;
pixels: number[][]; // 像素索引数组(二维)
rgbaData?: Uint8Array; // 帧自身图像块(可能为局部矩形)的 RGBA
fullRgbaData: Uint8Array; // 每帧完整画布的 RGBA(推荐用于渲染/导出)
}
```
## 开发
```bash
# 安装依赖
npm install
# 编译
npm run build
# 开发模式(监听文件变化)
npm run dev
```
## 许可证
MIT