使用WPF和GIFBITMAPENCODER创建具有1位透明背景的GIF,有人做到了吗?

发布于 2025-01-30 03:02:52 字数 3157 浏览 5 评论 0原文

IVE能够使用WPF和GIFBIFMAPENCODER在C#中创建GIF文件,但它们没有透明度。我可以使用alpha技术删除代码中的黑色背景,并在我的MainWindow中的图像上显示透明的背景图像,但是GIF不支持Alpha透明度,因此GIF文件最终以非透明的白色背景。我知道GIF支持“ 1位透明”背景,但我不知道如何使用WPF和GibitMapenCoder进行设置。我搜索了Stackoverflow,Bing,Google,Duckduck等。我唯一的结论是Microsoft忽略了GifBitmapenCoder中的这一重要功能。我错了吗?有很多在线服务可以免费进行此转换,但这不会帮助我。如果有一种方法可以通过与调色板,ColorProfiles或Metadata或编解码器划定1位透明度,则肯定是隐藏的信息。

为了我尝试的是值得的:(即时通知在具有黑色背景的gif中阅读钻头列表,然后在执行无用的Alpha透明度后将其归档回到另一个GIF。)

    GifBitmapDecoder GifDC = new GifBitmapDecoder(imageStreamSource, BitmapCreateOptions.DelayCreation,                     BitmapCacheOption.Default);
    List<BitmapSource> listBmpSources = new List<BitmapSource>();

    foreach (var thisBF in GifDC.Frames)
            {
                //Extract pixels for this BitmapFrame from dropped file
                byte[] thesePixels = new byte[thisBF.PixelHeight * thisBF.PixelWidth];
                thisBF.CopyPixels(thesePixels, thisBF.PixelWidth, 0);

                //Construct new BitmapSource list with Black set to Transparent
                List<System.Windows.Media.Color> thisListColors = new List<System.Windows.Media.Color>();
                SetBlackAsTransparent(thisBF, thisListColors);
                BitmapPalette thisBmpPalette = new BitmapPalette(thisListColors);
                BitmapSource thisBitmapSourceImage = BitmapSource.Create(thisBF.PixelWidth, thisBF.PixelHeight, thisBF.DpiX, 
                    thisBF.DpiY, thisBF.Format, thisBmpPalette, thesePixels, thisBF.PixelWidth);

                //Store bmp sources for GIFEncoder
                listBmpSources.Add(thisBitmapSourceImage);
            }

//Useless alpha transparency that doesnt survive rendering out to a Gif file:
    private void SetBlackAsTransparent(BitmapSource thisBF, List<System.Windows.Media.Color> listSWMC)
        {
            foreach (var thisColor in thisBF.Palette.Colors)
            {
                {
                    if (thisColor == Colors.Black)
                    {
                        listSWMC.Add(Colors.Transparent);
                        continue;
                    }

                    if (Feather(5, thisColor, listSWMC)) continue;
                    if (Feather(10, thisColor, listSWMC)) continue;
                    if (Feather(15, thisColor, listSWMC)) continue;
                    if (Feather(25, thisColor, listSWMC)) continue;
                    if (Feather(50, thisColor, listSWMC)) continue;
                    listSWMC.Add(thisColor);
                }
            }
        }

  void EncodeGifFile(List<BitmapSource> pListBmpSources, string pSaveAs)
        {
            GifBitmapEncoder encoder = new GifBitmapEncoder();
            
            foreach (var thisBmpSource in pListBmpSources)
            {   
                var thisBmpFrame = BitmapFrame.Create(thisBmpSource);
                encoder.Palette = thisBmpSource.Palette;
                encoder.Frames.Add(thisBmpFrame);

            }
            var stream = new FileStream(pSaveAs, FileMode.CreateNew);
            encoder.Save(stream);
            stream.Close();
        }

Ive been able to use WPF and GifBitmapEncoder to create GIF files in C# but they are without transparency. I can remove the black background in code using alpha techniques and display transparent background images on an Image in my MainWindow, but GIF doesnt support alpha transparency, so the GIF files end up with non transparent white backgrounds. I know GIF supports "1-bit transparent" backgrounds but I have no clue how to use WPF and GiBitmapEncoder to set this up. I searched StackOverflow, Bing, Google, DuckDuck etc. Seems my only conclusion is that Microsoft has ignored this important feature in GifBitmapEncoder. Am I Wrong? There are tons of online services that will do this conversion for free but that wont help me. If there is a way to get 1 bit transparency by dinking with the palettes, ColorProfiles or MetaData or Codec it sure is well hidden information.

For what its worth heres what I tried: (Im reading in a gif with black background into a list of BitmapSources, then rendering those back out to a another GIF after performing useless alpha transparency.)

    GifBitmapDecoder GifDC = new GifBitmapDecoder(imageStreamSource, BitmapCreateOptions.DelayCreation,                     BitmapCacheOption.Default);
    List<BitmapSource> listBmpSources = new List<BitmapSource>();

    foreach (var thisBF in GifDC.Frames)
            {
                //Extract pixels for this BitmapFrame from dropped file
                byte[] thesePixels = new byte[thisBF.PixelHeight * thisBF.PixelWidth];
                thisBF.CopyPixels(thesePixels, thisBF.PixelWidth, 0);

                //Construct new BitmapSource list with Black set to Transparent
                List<System.Windows.Media.Color> thisListColors = new List<System.Windows.Media.Color>();
                SetBlackAsTransparent(thisBF, thisListColors);
                BitmapPalette thisBmpPalette = new BitmapPalette(thisListColors);
                BitmapSource thisBitmapSourceImage = BitmapSource.Create(thisBF.PixelWidth, thisBF.PixelHeight, thisBF.DpiX, 
                    thisBF.DpiY, thisBF.Format, thisBmpPalette, thesePixels, thisBF.PixelWidth);

                //Store bmp sources for GIFEncoder
                listBmpSources.Add(thisBitmapSourceImage);
            }

//Useless alpha transparency that doesnt survive rendering out to a Gif file:
    private void SetBlackAsTransparent(BitmapSource thisBF, List<System.Windows.Media.Color> listSWMC)
        {
            foreach (var thisColor in thisBF.Palette.Colors)
            {
                {
                    if (thisColor == Colors.Black)
                    {
                        listSWMC.Add(Colors.Transparent);
                        continue;
                    }

                    if (Feather(5, thisColor, listSWMC)) continue;
                    if (Feather(10, thisColor, listSWMC)) continue;
                    if (Feather(15, thisColor, listSWMC)) continue;
                    if (Feather(25, thisColor, listSWMC)) continue;
                    if (Feather(50, thisColor, listSWMC)) continue;
                    listSWMC.Add(thisColor);
                }
            }
        }

  void EncodeGifFile(List<BitmapSource> pListBmpSources, string pSaveAs)
        {
            GifBitmapEncoder encoder = new GifBitmapEncoder();
            
            foreach (var thisBmpSource in pListBmpSources)
            {   
                var thisBmpFrame = BitmapFrame.Create(thisBmpSource);
                encoder.Palette = thisBmpSource.Palette;
                encoder.Frames.Add(thisBmpFrame);

            }
            var stream = new FileStream(pSaveAs, FileMode.CreateNew);
            encoder.Save(stream);
            stream.Close();
        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不打扰别人 2025-02-06 03:02:52

这是一个简短的示例,该示例显示了如何通过透明的颜色条目从清除的Bitmapsource编写透明度的GIF文件。

var colors = new Color[] { Colors.Transparent, Colors.Red, };

var bitmap = new WriteableBitmap(200, 200, 96, 96, PixelFormats.Indexed8,
                                 new BitmapPalette(colors));

var redPixels = Enumerable.Range(0, 10000).Select(i => (byte)1).ToArray();

bitmap.WritePixels(new Int32Rect(50, 50, 100, 100), redPixels, 100, 0);

var encoder = new GifBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));

using (var stream = File.Create("test.gif"))
{
    encoder.Save(stream); // save
}

image.Source = BitmapFrame.Create(new Uri("test.gif", UriKind.Relative)); // reload

在此XAML的测试应用程序中,

<Grid>
    <Border HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Background="AliceBlue">
        <Image x:Name="image" Stretch="None"/>
    </Border>
</Grid>

输出是:

”在此处输入图像说明”

Here is a short example that shows how to write a GIF file with transparency from a paletted BitmapSource with a transparent Color entry.

var colors = new Color[] { Colors.Transparent, Colors.Red, };

var bitmap = new WriteableBitmap(200, 200, 96, 96, PixelFormats.Indexed8,
                                 new BitmapPalette(colors));

var redPixels = Enumerable.Range(0, 10000).Select(i => (byte)1).ToArray();

bitmap.WritePixels(new Int32Rect(50, 50, 100, 100), redPixels, 100, 0);

var encoder = new GifBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));

using (var stream = File.Create("test.gif"))
{
    encoder.Save(stream); // save
}

image.Source = BitmapFrame.Create(new Uri("test.gif", UriKind.Relative)); // reload

In a test application with this XAML

<Grid>
    <Border HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Background="AliceBlue">
        <Image x:Name="image" Stretch="None"/>
    </Border>
</Grid>

the output is this:

enter image description here

迷爱 2025-02-06 03:02:52

我根据Clemens的结果取得了不错的进步,但最终放弃了WPF的GifbitMapenCoder,并使用了Magickimage库,并且在第十个时间内有了一个完美的解决方案。我使用MagickimageCollection收集PNG文件并以透明度输出动画GIF。我可以设置动画延迟,并使用添加的每个图像上的简单属性清除背景。 Magick.net有有用的例子和出色的文档。 Visual Studio Nuget软件包管理器使其非常容易安装。我确实看到有人在堆栈OVF上发布了您,建议您不要使用System.Drawing。

I made decent progress based on Clemens result but finally gave up on WPF's GifBitmapEncoder and used the MagickImage library and within a tenth of the time had a perfect solution. I used the MagickImageCollection to collect png files and output an animated GIF with transparency. I could set the Animation delay and clear the background using simple properties on each image added. Magick.Net has helpful examples and excellent documentation. And the Visual Studio NuGet package manager makes it super easy to install. I did see though someone posted on Stack OVF that you are advised not to use System.Drawing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文