如何在C#中打开位图时保留原PixelFormat不被转换?
解决C#加载8bppIndexed格式PNG时自动转换像素格式的问题
问题原因
使用new Bitmap("myImage.png")加载8bppIndexed格式的PNG时,GDI+会自动将其转换为32bppRgb格式,这是默认的优化行为;而1bppIndexed格式的图像因为是黑白单色,不会触发该转换。
解决方案
方法1:基于System.Drawing的手动流加载(无需额外程序集)
通过文件流读取图像,再克隆为原始像素格式,绕过自动转换逻辑:
using System.IO; using System.Drawing; // 读取文件流 using (var fileStream = new FileStream("myImage.png", FileMode.Open)) { // 加载图像时禁用颜色管理与数据验证 using (var sourceImage = Image.FromStream(fileStream, false, false)) { // 克隆图像以保留原始像素格式 Bitmap originalFormatBitmap = sourceImage.Clone( new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), sourceImage.PixelFormat ); // 此时originalFormatBitmap.PixelFormat为Format8bppIndexed,可直接用于你的海龟图形处理代码 } }
方法2:使用WPF的PngBitmapDecoder(保留原始格式更可靠)
如果项目允许引用PresentationCore和WindowsBase程序集,可直接读取原始索引格式:
using System.IO; using System.Drawing; using System.Windows.Media.Imaging; using (var fileStream = new FileStream("myImage.png", FileMode.Open)) { // 解码器指定保留原始像素格式 var decoder = new PngBitmapDecoder( fileStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad ); var imageFrame = decoder.Frames[0]; // 若需要转换为System.Drawing.Bitmap供现有代码使用 using (var memoryStream = new MemoryStream()) { var encoder = new PngBitmapEncoder(); encoder.Frames.Add(imageFrame); encoder.Save(memoryStream); memoryStream.Position = 0; Bitmap indexedBitmap = new Bitmap(memoryStream); // 此时indexedBitmap.PixelFormat为Format8bppIndexed } }
注意事项
- 方法1中
Image.FromStream的后两个参数设为false,是为了避免颜色管理和数据验证导致的格式转换; - 方法2需要添加对
PresentationCore.dll和WindowsBase.dll的引用,适合WPF项目或允许引入这些程序集的WinForms项目。
内容的提问来源于stack exchange,提问作者Hammerite
相关产品推荐
相关产品推荐

