在.NET中读取/保留PixelFormat.Format48bppRgb PNG位图?

时间:2011-09-01 20:37:29

标签: c# .net png gdi+ system.drawing.imaging

我已经能够使用以下C#代码创建Format48bppRgb .PNG文件(来自某些内部HDR数据):

Bitmap bmp16 = new Bitmap(_viewer.Width, _viewer.Height, System.Drawing.Imaging.PixelFormat.Format48bppRgb);
System.Drawing.Imaging.BitmapData data16 = bmp16.LockBits(_viewer.ClientRectangle, System.Drawing.Imaging.ImageLockMode.WriteOnly, bmp16.PixelFormat);
unsafe {  (populates bmp16) }
bmp16.Save( "C:/temp/48bpp.png", System.Drawing.Imaging.ImageFormat.Png );

ImageMagik(和其他应用程序)验证这确实是16bpp图像:

C:\temp>identify 48bpp.png
48bpp.png PNG 1022x1125 1022x1125+0+0 DirectClass 16-bit 900.963kb

然而,我很失望地发现,在重新阅读PNG时,它已被转换为Format32bppRgb,在使用时:

Bitmap bmp = new Bitmap( "c:/temp/48bpp.png", false );
String info = String.Format("PixelFormat: {0}", bmp.PixelFormat );
...

鉴于PNG编解码器可以编写Format48bppRgb,有没有什么方法可以使用.NET在没有转换的情况下读取它?我不介意它是否为DrawImage调用执行此操作,但我想访问解压缩的原始数据以进行某些直方图/图像处理工作。

2 个答案:

答案 0 :(得分:5)

仅供参考 - 我确实使用System.Windows.Media.Imaging找到了一个.NET解决方案(我一直在使用严格的WinForms / GDI + - 这需要添加WPF程序集,但有效。)有了这个,我得到一个Format64bppArgb PixelFormat ,所以没有遗失的信息:

using System.Windows.Media.Imaging; // Add PresentationCore, WindowsBase, System.Xaml
...

    // Open a Stream and decode a PNG image
Stream imageStreamSource = new FileStream(fd.FileName, FileMode.Open, FileAccess.Read, FileShare.Read);
PngBitmapDecoder decoder = new PngBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];

    // Convert WPF BitmapSource to GDI+ Bitmap
Bitmap bmp = _bitmapFromSource(bitmapSource);
String info = String.Format("PixelFormat: {0}", bmp.PixelFormat );
MessageBox.Show(info);

...

此代码段来自:http://www.generoso.info/blog/wpf-system.drawing.bitmap-to-bitmapsource-and-viceversa.html

private System.Drawing.Bitmap _bitmapFromSource(BitmapSource bitmapsource) 
{ 
    System.Drawing.Bitmap bitmap; 
    using (MemoryStream outStream = new MemoryStream()) 
    { 
        // from System.Media.BitmapImage to System.Drawing.Bitmap 
        BitmapEncoder enc = new BmpBitmapEncoder(); 
        enc.Frames.Add(BitmapFrame.Create(bitmapsource)); 
        enc.Save(outStream); 
        bitmap = new System.Drawing.Bitmap(outStream); 
    } 
    return bitmap; 
} 

如果有人知道不需要WPF的方法,请分享!

答案 1 :(得分:2)

使用Image.FromFile(String, Boolean)Bitmap.FromFile(String, Boolean)

并将布尔值设置为true。所有图像属性都将保存在新图像中。

这里String是具有完整路径的文件名...

如果图像已经加载到程序中并且您想要使用它创建新的位图,您也可以使用

MemoryStream ms = new MemoryStream();
img.Save(ms, ImageFormat.Bmp); // img is any Image, previously opened or came as a parameter
Bitmap bmp = (Bitmap)Bitmap.FromStream(ms,true);

常见的替代方案是

Bitmap bmp = new Bitmap(img); // this won't preserve img.PixelFormat
相关问题