gifencoder

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 24, 2025 License: MIT Imports: 5 Imported by: 0

README

NicoGIF Encoder

纯 Go 语言实现的 GIF 编码库,移植自 gif.js。使用 NeuQuant 神经网络算法进行高质量颜色量化。

Go Version License

安装
go get github.com/ManInM00N/nicogif/gifencoder
基础使用
package main

import (
    "image"
    "image/color"
    "os"
    "github.com/ManInM00N/nicogif/gifencoder"
)

func main() {
    // 创建图像帧
    frames := []image.Image{
        createFrame(0),
        createFrame(1),
        createFrame(2),
    }
    
    // 设置每帧延迟(毫秒)
    delays := []int{100, 100, 100}
    
    // 编码为 GIF
    gifData, _ := gifencoder.EncodeGIF(frames, delays)
    
    // 保存文件
    os.WriteFile("output.gif", gifData, 0644)
}

func createFrame(n int) image.Image {
    img := image.NewRGBA(image.Rect(0, 0, 100, 100))
    // 绘制图像...
    return img
}
示例 1: 手动控制编码器
func advancedUsage() {
    encoder := gifencoder.NewGIFEncoder(300, 300)
    
    // 设置选项
    encoder.SetRepeat(0)        // 0 = 无限循环
    encoder.SetQuality(10)      // 1-30, 值越小质量越好
    encoder.SetFrameRate(10)    // 10 FPS
    
    // 可选:设置透明色
    encoder.SetTransparent(&color.RGBA{255, 255, 255, 255})
    
    // 添加帧
    for i := 0; i < 20; i++ {
        img := createFrame(300, 300, i)
        encoder.SetDelay(100) // 每帧 100ms
        encoder.AddFrame(img)
    }
    
    encoder.Finish()
    gifData := encoder.GetData()
    
    os.WriteFile("advanced.gif", gifData, 0644)
}
示例 2: 使用自定义选项
func withOptions() {
    frames := []image.Image{ /* ... */ }
    
    opts := gifencoder.EncodeOptions{
        Width:   200,
        Height:  200,
        Repeat:  0,     // 无限循环
        Quality: 5,     // 高质量
        Dither:  false,
        Delays:  []int{80, 80, 80, 80, 80},
    }
    
    gifData, err := gifencoder.EncodeGIFWithOptions(frames, opts)
    if err != nil {
        panic(err)
    }
    
    os.WriteFile("custom.gif", gifData, 0644)
}
创建编码器
func NewGIFEncoder(width, height int) *GIFEncoder
配置方法
方法 说明
SetDelay(ms int) 设置帧延迟(毫秒)
SetFrameRate(fps int) 设置帧率
SetRepeat(repeat int) 设置重复次数(-1=播放一次, 0=无限循环)
SetQuality(quality int) 设置质量(1-30,越小越好)
SetTransparent(*color.RGBA) 设置透明色
SetDither(bool) 启用/禁用抖动
SetGlobalPalette([]byte) 设置全局调色板
SetDispose(int) 设置帧处理方式
编码方法
方法 说明
AddFrame(image.Image) error 添加一帧
Finish() 完成编码
GetData() []byte 获取 GIF 数据
Stream() *ByteArray 获取输出流
便捷函数
// 快速编码
func EncodeGIF(images []image.Image, delays []int) ([]byte, error)

// 带选项编码
type EncodeOptions struct {
    Width         int
    Height        int
    Repeat        int
    Quality       int
    Dither        bool
    GlobalPalette []byte
    Delays        []int
}

func EncodeGIFWithOptions(images []image.Image, opts EncodeOptions) ([]byte, error)

⚙️ 性能优化建议

质量参数
  • 1-5: 最佳质量,编码较慢(适合重要图像)
  • 10-15: 推荐值,质量和速度平衡(日常使用)
  • 20-30: 快速编码,质量略降(快速预览)
encoder.SetQuality(10) // 推荐值
全局调色板

对于颜色相似的多帧动画,使用全局调色板可显著减小文件大小:

encoder.SetGlobalPalette(nil) // 从第一帧自动生成
图像尺寸

较小的图像尺寸会显著提高编码速度:

// 200x200 比 800x800 快约 16 倍
encoder := gifencoder.NewGIFEncoder(200, 200)

❓ 常见问题

Q: 如何减小 GIF 文件大小?

A: 几种方法:

  1. 使用全局调色板:encoder.SetGlobalPalette(nil)
  2. 提高质量参数:encoder.SetQuality(15-20)
  3. 减小图像尺寸
  4. 减少帧数或增加帧延迟
Q: 为什么颜色不准确?

A: GIF 最多只支持 256 色。对于颜色丰富的图像,降低质量参数(1-5)可获得更好的颜色匹配:

encoder.SetQuality(1) // 最佳质量,但较慢
Q: 如何创建透明背景 GIF?

A:

encoder.SetTransparent(&color.RGBA{255, 255, 255, 255})
Q: 支持哪些图像格式作为输入?

A: 支持所有实现了 image.Image 接口的类型,包括:

  • image.RGBA
  • image.NRGBA
  • image.Gray
  • PNG、JPEG 解码后的图像等

🙏 致谢

  • gif.js - 原始 JavaScript 实现
  • Anthony Dekker - NeuQuant 算法作者
  • Lempel, Ziv, Welch - LZW 压缩算法

🔗 相关链接

🐛 问题反馈

如果遇到问题,请提交 Issue 到 GitHub。

Documentation

Index

Constants

View Source
const (
	EOF   = -1
	BITS  = 12
	HSIZE = 5003 // 80% occupancy
)

Variables

View Source
var (
	// FalseFloydSteinberg 抖动核心
	FalseFloydSteinberg = DitheringKernel{
		{3.0 / 8.0, 1, 0},
		{3.0 / 8.0, 0, 1},
		{2.0 / 8.0, 1, 1},
	}

	// FloydSteinberg 抖动核心(最常用)
	FloydSteinberg = DitheringKernel{
		{7.0 / 16.0, 1, 0},
		{3.0 / 16.0, -1, 1},
		{5.0 / 16.0, 0, 1},
		{1.0 / 16.0, 1, 1},
	}

	// Stucki 抖动核心
	Stucki = DitheringKernel{
		{8.0 / 42.0, 1, 0},
		{4.0 / 42.0, 2, 0},
		{2.0 / 42.0, -2, 1},
		{4.0 / 42.0, -1, 1},
		{8.0 / 42.0, 0, 1},
		{4.0 / 42.0, 1, 1},
		{2.0 / 42.0, 2, 1},
		{1.0 / 42.0, -2, 2},
		{2.0 / 42.0, -1, 2},
		{4.0 / 42.0, 0, 2},
		{2.0 / 42.0, 1, 2},
		{1.0 / 42.0, 2, 2},
	}

	// Atkinson 抖动核心
	Atkinson = DitheringKernel{
		{1.0 / 8.0, 1, 0},
		{1.0 / 8.0, 2, 0},
		{1.0 / 8.0, -1, 1},
		{1.0 / 8.0, 0, 1},
		{1.0 / 8.0, 1, 1},
		{1.0 / 8.0, 0, 2},
	}
)

预定义的抖动核心

Functions

func EncodeGIF

func EncodeGIF(images []image.Image, delays []int) ([]byte, error)

EncodeGIF is a convenience function to quickly encode multiple images into a GIF images: slice of images to encode delays: slice of delays in milliseconds for each frame

func EncodeGIFWithOptions

func EncodeGIFWithOptions(images []image.Image, opts EncodeOptions) ([]byte, error)

EncodeGIFWithOptions encodes images with custom options

func MAXCODE

func MAXCODE(nBits int) int

MAXCODE returns the maximum code value for n bits

Types

type ByteArray

type ByteArray struct {
	// contains filtered or unexported fields
}

ByteArray implements a growing byte buffer similar to the JavaScript version

func NewByteArray

func NewByteArray() *ByteArray

NewByteArray creates a new ByteArray with default page size

func (*ByteArray) GetCursor

func (ba *ByteArray) GetCursor() int

GetCursor returns the current cursor position

func (*ByteArray) GetData

func (ba *ByteArray) GetData() []byte

GetData returns all written data as a single byte slice

func (*ByteArray) GetPageSize

func (ba *ByteArray) GetPageSize() int

GetPageSize returns the page size

func (*ByteArray) GetPages

func (ba *ByteArray) GetPages() [][]byte

GetPages returns the internal pages for direct access

func (*ByteArray) WriteByte

func (ba *ByteArray) WriteByte(val byte)

WriteByte writes a single byte to the buffer

func (*ByteArray) WriteBytes

func (ba *ByteArray) WriteBytes(data []byte)

WriteBytes writes a byte slice to the buffer

func (*ByteArray) WriteUTFBytes

func (ba *ByteArray) WriteUTFBytes(s string)

WriteUTFBytes writes a string as UTF-8 bytes

type DitherMethod

type DitherMethod string

DitherMethod 抖动方法

const (
	DitherNone                DitherMethod = "none"
	DitherFloydSteinberg      DitherMethod = "FloydSteinberg"
	DitherFalseFloydSteinberg DitherMethod = "FalseFloydSteinberg"
	DitherStucki              DitherMethod = "Stucki"
	DitherAtkinson            DitherMethod = "Atkinson"
)

type DitheringKernel

type DitheringKernel [][]float64

DitheringKernel 定义抖动核心

type EncodeOptions

type EncodeOptions struct {
	Width           int         // width of output GIF
	Height          int         // height of output GIF
	Repeat          int         // -1 = once, 0 = forever, >0 = count
	Quality         int         // 1-30, lower is better
	Dither          interface{} // dithering method: bool, string, or DitherMethod
	GlobalPalette   []byte      // optional global palette
	Delays          []int       // delays in milliseconds
	SaturationBoost float64     // 饱和度增强, [0.0,2.0], 1.0为原始
	ContrastBoost   float64     // 对比度增强, [0.0,2.0], 1.0为原始
}

EncodeGIFWithOptions provides more control over encoding options

type GIFEncoder

type GIFEncoder struct {
	// contains filtered or unexported fields
}

GIFEncoder encodes images into GIF format

func NewGIFEncoder

func NewGIFEncoder(width, height int) *GIFEncoder

NewGIFEncoder creates a new GIF encoder

func NewGIFEncoderWithOptions

func NewGIFEncoderWithOptions(width, height int, opts EncodeOptions) *GIFEncoder

func (*GIFEncoder) AddFrame

func (ge *GIFEncoder) AddFrame(img image.Image) error

AddFrame adds next GIF frame

func (*GIFEncoder) Cleanup

func (ge *GIFEncoder) Cleanup()

func (*GIFEncoder) CleanupAll

func (ge *GIFEncoder) CleanupAll()

CleanupAll 完全清理包括输出缓冲区 只在确定不再需要GetData()时调用

func (*GIFEncoder) Finish

func (ge *GIFEncoder) Finish()

Finish adds final trailer to the GIF stream

func (*GIFEncoder) GetData

func (ge *GIFEncoder) GetData() []byte

GetData retrieves the GIF stream as byte array

func (*GIFEncoder) GetGlobalPalette

func (ge *GIFEncoder) GetGlobalPalette() []byte

GetGlobalPalette returns global palette used for all frames

func (*GIFEncoder) SetColorEnhancement

func (ge *GIFEncoder) SetColorEnhancement(saturationBoost, contrastBoost float64)

SetColorEnhancement 设置颜色增强选项 saturationBoost: 饱和度 ([0.0,2.0], 1.0为原始) contrastBoost: 对比度 ([0.0,2.0], 1.0为原始)

func (*GIFEncoder) SetDelay

func (ge *GIFEncoder) SetDelay(milliseconds int)

SetDelay sets the delay time between each frame, or changes it for subsequent frames

func (*GIFEncoder) SetDispose

func (ge *GIFEncoder) SetDispose(disposalCode int)

SetDispose sets the GIF frame disposal code

func (*GIFEncoder) SetDither

func (ge *GIFEncoder) SetDither(method interface{})

SetDither sets dithering method. Available methods: - "none" or "" or false: no dithering - "FloydSteinberg" or true: Floyd-Steinberg dithering (recommended) - "FalseFloydSteinberg": False Floyd-Steinberg dithering - "Stucki": Stucki dithering - "Atkinson": Atkinson dithering Add "-serpentine" suffix to use serpentine scanning (e.g., "FloydSteinberg-serpentine")

func (*GIFEncoder) SetFrameRate

func (ge *GIFEncoder) SetFrameRate(fps int)

SetFrameRate sets frame rate in frames per second

func (*GIFEncoder) SetGlobalPalette

func (ge *GIFEncoder) SetGlobalPalette(palette []byte)

SetGlobalPalette sets global palette for all frames

func (*GIFEncoder) SetQuality

func (ge *GIFEncoder) SetQuality(quality int)

SetQuality sets quality of color quantization (1-30, lower is better)

func (*GIFEncoder) SetRepeat

func (ge *GIFEncoder) SetRepeat(repeat int)

SetRepeat sets the number of times the set of GIF frames should be played

func (*GIFEncoder) SetTransparent

func (ge *GIFEncoder) SetTransparent(c *color.RGBA)

SetTransparent sets the transparent color

func (*GIFEncoder) Stream

func (ge *GIFEncoder) Stream() *ByteArray

Stream returns the output ByteArray

type LZWEncoder

type LZWEncoder struct {
	// contains filtered or unexported fields
}

LZWEncoder encodes image data using LZW compression

func NewLZWEncoder

func NewLZWEncoder(width, height int, pixels []byte, colorDepth int) *LZWEncoder

NewLZWEncoder creates a new LZW encoder

func (*LZWEncoder) Encode

func (enc *LZWEncoder) Encode(out *ByteArray)

Encode encodes and writes pixel data to the output stream

type NeuQuant

type NeuQuant struct {
	// contains filtered or unexported fields
}

NeuQuant is a neural network color quantizer

func NewNeuQuant

func NewNeuQuant(pixels []byte, samplefac int) *NeuQuant

NewNeuQuant creates a new NeuQuant instance pixels: array of pixels in RGB format [r,g,b,r,g,b,...] samplefac: sampling factor 1 to 30 where lower is better quality

func (*NeuQuant) BuildColormap

func (nq *NeuQuant) BuildColormap()

BuildColormap builds the color map 1. initializes network 2. trains it 3. removes misconceptions 4. builds colorindex

func (*NeuQuant) GetColormap

func (nq *NeuQuant) GetColormap() []byte

GetColormap returns the color map as byte array [r,g,b,r,g,b,...]

func (*NeuQuant) LookupRGB

func (nq *NeuQuant) LookupRGB(r, g, b byte) int

LookupRGB looks for the closest r, g, b color in the map and returns its index

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL