C# GIF encoder/decoder
C# GIF encoder/decoder
我正在开发一个加载动画 GIF 文件并更改某些像素的程序,然后将其作为新的动画 GIF 文件吐出。输出的 GIF 动画在 Windows、浏览器和 Photoshop 中运行良好。
但是,如果我尝试用我的程序加载 GIF,它不会生成动画。另外,我无法获得正确的调色板。加载代码与我最初用于加载原始 GIF 的代码完全相同。
这是我的保存代码:
public int saveAsGif(string absPath, byte[] mark)
{
BitmapPalette palette = new BitmapPalette(getPaletteAsMediaColorList(m_Pal));
int width = m_CanvasWidth;
int height = m_CanvasHeight;
using (FileStream fs = new FileStream(absPath, FileMode.Create))
{
GifBitmapEncoder encoder = new GifBitmapEncoder();
for (int f = 0; f < m_NumberOfFrames; f++)
{
FrameData frame = m_Frames[f];
byte[] pixels = frame.pixels;
BitmapSource image = BitmapSource.Create(
width,
height,
96,
96,
System.Windows.Media.PixelFormats.Indexed8,
palette,
pixels,
width);
encoder.Frames.Add(BitmapFrame.Create(image));
}
encoder.Save(fs);
fs.Close();
}
return RESULT_SUCCESFUL;
}
为了确保这不是我的加载代码,我使用以下代码创建了一个普通的新项目:
private void Form1_Load(object sender, EventArgs e)
{
Bitmap test1 = new Bitmap(@"F:\original.gif");
pictureBox1.Image = test1;
Bitmap test2 = new Bitmap(@"F:\exported.gif");
pictureBox2.Image = test2;
}
original.gif 会完美加载和播放,exported.gif 只会显示静止画面。但是,在Windows/Browser/Photoshop exported.gif 会播放。
我找到了一个相对简单的解决方案。它并不完美,但对我有用。它只适用于 GifBitmapEncoder,不需要额外的库。
您需要做的一切;
- 将 GIF 数据从编码器写入内存流。
- 二进制写入前 13 个字节(GIF89a header 和东西)。
- 二进制写入“ApplicationExtention”块。
- 二进制写剩下的GIF数据。
ApplicationExtention 块允许动画。如果没有设置延迟时间,则使用默认时间 100ms。如果您确实希望为每一帧自定义延迟,则需要在两者之间添加更多字节(请参阅 GIF 文件格式文档)。
代码:
public void saveAsGif(string absPath)
{
int width = m_CanvasWidth;
int height = m_CanvasHeight;
GifBitmapEncoder encoder = new GifBitmapEncoder();
BitmapPalette palette = new BitmapPalette(getPaletteAsMediaColorList(m_Pal));
for (int f = 0; f < m_NumberOfFrames; f++)
{
FrameData frame = m_Frames[f];
byte[] pixels = frame.pixels;
BitmapSource image = BitmapSource.Create(
width,
height,
96,
96,
System.Windows.Media.PixelFormats.Indexed8,
palette,
pixels,
width);
encoder.Frames.Add(BitmapFrame.Create(image));
}
byte[] GifData;
using (MemoryStream ms = new MemoryStream())
{
encoder.Save(ms);
GifData = ms.ToArray();
}
byte[] ApplicationExtention = { 33, 255, 11, 78, 69, 84, 83, 67, 65, 80, 69, 50, 46, 48, 3, 1, 0, 0, 0 };
using (FileStream fs = new FileStream(absPath, FileMode.Create))
{
fs.Write(GifData, 0, 13);
fs.Write(ApplicationExtention, 0, ApplicationExtention.Length);
fs.Write(GifData, 13, GifData.Length - 13);
}
}
我正在开发一个加载动画 GIF 文件并更改某些像素的程序,然后将其作为新的动画 GIF 文件吐出。输出的 GIF 动画在 Windows、浏览器和 Photoshop 中运行良好。
但是,如果我尝试用我的程序加载 GIF,它不会生成动画。另外,我无法获得正确的调色板。加载代码与我最初用于加载原始 GIF 的代码完全相同。
这是我的保存代码:
public int saveAsGif(string absPath, byte[] mark)
{
BitmapPalette palette = new BitmapPalette(getPaletteAsMediaColorList(m_Pal));
int width = m_CanvasWidth;
int height = m_CanvasHeight;
using (FileStream fs = new FileStream(absPath, FileMode.Create))
{
GifBitmapEncoder encoder = new GifBitmapEncoder();
for (int f = 0; f < m_NumberOfFrames; f++)
{
FrameData frame = m_Frames[f];
byte[] pixels = frame.pixels;
BitmapSource image = BitmapSource.Create(
width,
height,
96,
96,
System.Windows.Media.PixelFormats.Indexed8,
palette,
pixels,
width);
encoder.Frames.Add(BitmapFrame.Create(image));
}
encoder.Save(fs);
fs.Close();
}
return RESULT_SUCCESFUL;
}
为了确保这不是我的加载代码,我使用以下代码创建了一个普通的新项目:
private void Form1_Load(object sender, EventArgs e)
{
Bitmap test1 = new Bitmap(@"F:\original.gif");
pictureBox1.Image = test1;
Bitmap test2 = new Bitmap(@"F:\exported.gif");
pictureBox2.Image = test2;
}
original.gif 会完美加载和播放,exported.gif 只会显示静止画面。但是,在Windows/Browser/Photoshop exported.gif 会播放。
我找到了一个相对简单的解决方案。它并不完美,但对我有用。它只适用于 GifBitmapEncoder,不需要额外的库。
您需要做的一切;
- 将 GIF 数据从编码器写入内存流。
- 二进制写入前 13 个字节(GIF89a header 和东西)。
- 二进制写入“ApplicationExtention”块。
- 二进制写剩下的GIF数据。
ApplicationExtention 块允许动画。如果没有设置延迟时间,则使用默认时间 100ms。如果您确实希望为每一帧自定义延迟,则需要在两者之间添加更多字节(请参阅 GIF 文件格式文档)。
代码:
public void saveAsGif(string absPath)
{
int width = m_CanvasWidth;
int height = m_CanvasHeight;
GifBitmapEncoder encoder = new GifBitmapEncoder();
BitmapPalette palette = new BitmapPalette(getPaletteAsMediaColorList(m_Pal));
for (int f = 0; f < m_NumberOfFrames; f++)
{
FrameData frame = m_Frames[f];
byte[] pixels = frame.pixels;
BitmapSource image = BitmapSource.Create(
width,
height,
96,
96,
System.Windows.Media.PixelFormats.Indexed8,
palette,
pixels,
width);
encoder.Frames.Add(BitmapFrame.Create(image));
}
byte[] GifData;
using (MemoryStream ms = new MemoryStream())
{
encoder.Save(ms);
GifData = ms.ToArray();
}
byte[] ApplicationExtention = { 33, 255, 11, 78, 69, 84, 83, 67, 65, 80, 69, 50, 46, 48, 3, 1, 0, 0, 0 };
using (FileStream fs = new FileStream(absPath, FileMode.Create))
{
fs.Write(GifData, 0, 13);
fs.Write(ApplicationExtention, 0, ApplicationExtention.Length);
fs.Write(GifData, 13, GifData.Length - 13);
}
}