将索引 BMP 保存为 PNG 不会在 Mac 上保存透明度
Posted
技术标签:
【中文标题】将索引 BMP 保存为 PNG 不会在 Mac 上保存透明度【英文标题】:Saving indexed BMP as a PNG doesn't save transparency on Mac 【发布时间】:2020-06-25 04:43:48 【问题描述】:我正在使用一种旧的游戏格式,他们使用索引位图。对于某些具有透明度的材质,它们使用调色板中的第一个索引作为设置为不可见的值。在代码中,我克隆位图,将此调色板值设置为完全透明,然后将其导出为 PNG。它在 Windows 上完美运行。但在 Mac 上却没有。
这是我的工作:
Bitmap cloneBitmap;
cloneBitmap = image.Clone(new Rectangle(0, 0, image.Width, image.Height), PixelFormat.Format8bppIndexed);
var palette = cloneBitmap.Palette;
palette.Entries[0] = Color.FromArgb(0, 0, 0, 0);
cloneBitmap.Palette = palette;
cloneBitmap.Save(filePath + fileName, ImageFormat.Png);
这在 PC 上运行良好。图像以透明度输出。在 Mac 上,它没有透明度,具有此索引的像素只是黑色。
【问题讨论】:
你试过用 0,255,255,255 代替吗:docs.microsoft.com/en-us/dotnet/api/… @SimonMourier 这使得应该是透明的白色而不是黑色的像素。它对保存透明度没有影响。 是 .NET Core 吗?还是单声道?还是什么? 【参考方案1】:我假设您在应用程序中使用标准 System.Drawing
库进行图像处理。这个库中有很多功能是围绕Windows GDI+ API 的薄包装器。所以macOS可能没有一些处理图片的功能。
所以你有这些选项来处理这个问题:
在你的 Mac 上安装 GDI+ 库
如果您使用单声道,您可以尝试安装 GDI+ 库为System.Drawing
(source) 提供 GDI+ api。
brew install mono-libgdiplus
使用 Windows 兼容包
Windows Compatibility Pack 提供 API,仅供 Windows 中的 .NET Framework 使用,用于跨平台应用程序,使用 .NET Core/Standard 编写。
详情请见docs。
但是,Microsoft.Windows.Compatibility
包包含许多您可能根本不需要的与 Windows 相关的 API。如果是这样,您只能安装 System.Drawing.Common
包。此包是System.Drawing
函数的兼容性包的一部分。
请参阅有用的 article,了解如何在 .NET Core 中使用 System.Drawing.Common
。
使用其他第三方库
如果以前的解决方案对您的问题没有帮助,请尝试使用第三方开源库来完成您的任务。它们肯定会在 macOS 上正常工作。
请参阅来自 Microsoft 博客的有用文章 this,以查找适合您的图像处理库。
【讨论】:
感谢您的帮助。【参考方案2】:要求
输入:256 色调色板 (8bpp) BMP 输出:具有透明度的 PNG,输入图像中使用相关调色板第一个条目的区域必须透明显示 操作系统:macOS 和 Windows验证
为了有一个测试用例,我创建了一个具有不同颜色的 256 色调色板 (8bpp) BMP 在 BMP 中间有一个矩形区域,使用索引为 0 的颜色 为确保中间区域是透明的,我在图像编辑软件中打开了生成的 .png,该软件以棋盘格图案显示透明区域原始代码
当使用有问题的原始代码进行测试时,它会给出以下结果:
Windows .NET Framework:中间区域是透明的 Windows .NET Core:中间区域是透明的 macOS .NET Core:中间区域为黑色 macOS Mono:中间区域为黑色这是意料之中的,因为 OP 在问题中也指出了这一点。
解决方法
一种适用于所有 4 种环境(Windows .NET Framework、.NET Core Windows/Mac 和 Mono)的方法是使用第一个条目的颜色调用 MakeTransparent 方法。
文档说:
public void MakeTransparent(System.Drawing.Color transparentColor);
使该位图的指定颜色透明。
见 https://docs.microsoft.com/en-us/dotnet/api/system.drawing.bitmap.maketransparent?view=netcore-3.1#System_Drawing_Bitmap_MakeTransparent_System_Drawing_Color_
在代码中它看起来像这样:
var firstColor = image.Palette.Entries[0];
image.MakeTransparent(Color.FromArgb(0, firstColor.R, firstColor.G, firstColor.B));
image.Save(filePath + fileName, ImageFormat.Png);
如果第一个颜色也可能出现在调色板的其他条目中,您可能需要确保源调色板的第一个条目中的颜色是唯一的,以防止其他区域也变得透明。
测试
如果在图像编辑程序中打开生成的 PNG,可以看到图像中间的透明区域:
【讨论】:
感谢完整的测试用例分解。帮助我意识到我并不疯狂。我最终使用了 MakeTransparent 方法,但通过调色板运行并确保第一个索引是唯一的,如果不是,则生成一个随机索引。 不过,这不会保留调色板。您可以在最终的屏幕截图中看到该图像被视为 RGBA 是的,它是一个 RGBA PNG。据我了解,要求是输出应该是具有透明度的 PNG,并且不一定具有 8 位调色板颜色空间。现在几乎没有理由使用 8 位调色板,除非您有特殊要求。另请参阅我的回答的第一句话。以上是关于将索引 BMP 保存为 PNG 不会在 Mac 上保存透明度的主要内容,如果未能解决你的问题,请参考以下文章