Чтение / сохранение растрового изображения PNG PixelFormat.Format48bppRgb в .NET? - PullRequest
2 голосов
/ 02 сентября 2011

Я смог создать файл Format48bppRgb .PNG (из некоторых внутренних данных HDR), используя следующий код C #:

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 ]

5 голосов
/ 02 сентября 2011

FYI - Я нашел решение .NET для этого, используя System.Windows.Media.Imaging (я использовал исключительно 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, пожалуйста, поделитесь!

2 голосов
/ 10 июля 2012

Используйте Image.FromFile(String, Boolean) или Bitmap.FromFile(String, Boolean)

И установите логическое значение равным true. Все свойства изображения будут сохранены в новом изображении.

Здесь строка - это имя файла с полным путем ...

Если изображение уже загружено в программу и вы хотите создать с ним новый растровый рисунок, вы также можете использовать

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
...