在 wpf 中调整大小并将 byte[] 绑定到图像的最佳方式
Optimal way to resize and bind byte[] to image in wpf
我有 byte[]
存储一些未知大小的图像。我需要将此位图调整为 160 x 160 并绑定到 Wpf window.
我是否应该将 byte[]
转换为 Bitmap
、调整大小、从中生成 BitmapSource
然后在 wpf 中使用?
//result of this method binds to wpf
private static BitmapSource SetImage(byte[] dataBytes)
{
var picture = BitmapHelper.ByteToBitmap(dataBytes);
var resizedPicture = BitmapHelper.Resize(picture, 160, 160);
var bitmapSource = BitmapHelper.GetSourceFromBitmap(resizedPicture);
bitmapSource.Freeze();
return bitmapSource;
}
//位图助手class:
public static Bitmap ByteToBitmap(byte[] byteArray)
{
using (var ms = new MemoryStream(byteArray))
{
var img = (Bitmap)Image.FromStream(ms);
return img;
}
}
internal static Bitmap Resize(Bitmap bitmap, int width, int height)
{
var newImage = new Bitmap(width, height);
using (var gr = Graphics.FromImage(newImage))
{
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.DrawImage(bitmap, new Rectangle(0, 0, width, height));
}
return newImage;
}
internal static BitmapSource GetSourceFromBitmap(Bitmap source)
{
Contract.Requires(source != null);
var ip = source.GetHbitmap();
BitmapSource bs;
int result;
try
{
bs = Imaging.CreateBitmapSourceFromHBitmap(ip,
IntPtr.Zero, Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
finally
{
result = NativeMethods.DeleteObject(ip);
}
if (result == 0)
throw new InvalidOperationException("NativeMethods.DeleteObject returns 0 (operation failed)");
return bs;
}
internal static class NativeMethods
{
[DllImport("gdi32")]
static internal extern int DeleteObject(IntPtr o);
}
这种情况下最快最常用的方法是什么?
我建议您使用 BitmapImage
class(继承自 ImageSource
)的 DecodePixelWidth
和/或 DecodePixelHeight
属性。
看看here:
BitmapSource GetImage(byte[] dataBytes)
{
using (MemoryStream stream = new MemoryStream(dataBytes))
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
// This is important: the image should be loaded on setting the StreamSource property, afterwards the stream will be closed
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.DecodePixelWidth = 160;
// Set this to 160 to get exactly 160x160 image
// Comment it out to retain original aspect ratio having the image width 160 and auto calculated image height
bi.DecodePixelHeight = 160;
bi.StreamSource = stream;
bi.EndInit();
return bi;
}
}
我有 byte[]
存储一些未知大小的图像。我需要将此位图调整为 160 x 160 并绑定到 Wpf window.
我是否应该将 byte[]
转换为 Bitmap
、调整大小、从中生成 BitmapSource
然后在 wpf 中使用?
//result of this method binds to wpf
private static BitmapSource SetImage(byte[] dataBytes)
{
var picture = BitmapHelper.ByteToBitmap(dataBytes);
var resizedPicture = BitmapHelper.Resize(picture, 160, 160);
var bitmapSource = BitmapHelper.GetSourceFromBitmap(resizedPicture);
bitmapSource.Freeze();
return bitmapSource;
}
//位图助手class:
public static Bitmap ByteToBitmap(byte[] byteArray)
{
using (var ms = new MemoryStream(byteArray))
{
var img = (Bitmap)Image.FromStream(ms);
return img;
}
}
internal static Bitmap Resize(Bitmap bitmap, int width, int height)
{
var newImage = new Bitmap(width, height);
using (var gr = Graphics.FromImage(newImage))
{
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.DrawImage(bitmap, new Rectangle(0, 0, width, height));
}
return newImage;
}
internal static BitmapSource GetSourceFromBitmap(Bitmap source)
{
Contract.Requires(source != null);
var ip = source.GetHbitmap();
BitmapSource bs;
int result;
try
{
bs = Imaging.CreateBitmapSourceFromHBitmap(ip,
IntPtr.Zero, Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
finally
{
result = NativeMethods.DeleteObject(ip);
}
if (result == 0)
throw new InvalidOperationException("NativeMethods.DeleteObject returns 0 (operation failed)");
return bs;
}
internal static class NativeMethods
{
[DllImport("gdi32")]
static internal extern int DeleteObject(IntPtr o);
}
这种情况下最快最常用的方法是什么?
我建议您使用 BitmapImage
class(继承自 ImageSource
)的 DecodePixelWidth
和/或 DecodePixelHeight
属性。
看看here:
BitmapSource GetImage(byte[] dataBytes)
{
using (MemoryStream stream = new MemoryStream(dataBytes))
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
// This is important: the image should be loaded on setting the StreamSource property, afterwards the stream will be closed
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.DecodePixelWidth = 160;
// Set this to 160 to get exactly 160x160 image
// Comment it out to retain original aspect ratio having the image width 160 and auto calculated image height
bi.DecodePixelHeight = 160;
bi.StreamSource = stream;
bi.EndInit();
return bi;
}
}