Windows 通用应用程序中位图 (System.Drawing) 的替代
Alternative of Bitmap (System.Drawing) in Windows Universal Application
我正在开发 Windows 通用应用程序,它将在 ARM 架构上 运行(RaspberryPi 3,OS:Windows IoT).
我面临的问题是 UWP 不允许很多标准的 .Net 库,例如 "System.Drawing"
我目前有一个 IntPtr,其中包含图像的原始数据,我需要将其用作 Bitmap,这当然是在这种情况下不可能。是否有任何可能的替代方案。
我已经寻找 BitmapImage 但没有找到任何解决方案。
我也试过将 IntPtr 转换为 Byte[] 然后将数组转换为 Image 或 BitmapImage 在 UWP 中是不可能的。
请放轻松,因为我是 C# 编程的新手。
我只想要来自 IntPtr 的任何类型的位图或图像
提前致谢!
我想追加更多,但我还不能编辑评论,所以我的原始回复自动变成了评论。基本上看起来你的困境很常见,但你必须研究第三方解决方案。
要将IntPtr
转换为Byte[]
,我们可以使用Marshal.Copy
方法。它将数据从一维托管 8 位无符号整数数组复制到非托管内存指针。
然后我们可以使用WriteableBitmap
class设置Byte[]为WriteableBitmap
。
The image source data of a WriteableBitmap is an underlying pixel buffer. PixelBuffer cannot be written to directly, however, you can use language-specific techniques to access the buffer and change its contents.
To access the pixel content from C# or Microsoft Visual Basic, you can use the AsStream extension method to access the underlying buffer as a stream.
有关详细信息,请参阅 Remarks of the WriteableBitmap。
要将 WriteableBitmap
转换为 BitmapImage
,我们应该能够对来自 WriteableBitmap
的流进行编码。
例如:
private byte[] managedArray;
private async void Button_Click(object sender, RoutedEventArgs e)
{
Windows.Storage.Streams.IRandomAccessStream random = await Windows.Storage.Streams.RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/sunset.jpg")).OpenReadAsync();
Windows.Graphics.Imaging.BitmapDecoder decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(random);
Windows.Graphics.Imaging.PixelDataProvider pixelData = await decoder.GetPixelDataAsync();
byte[] buffer = pixelData.DetachPixelData();
unsafe
{
fixed (byte* p = buffer)
{
IntPtr ptr = (IntPtr)p;
managedArray = new byte[buffer.Length];
Marshal.Copy(ptr, managedArray, 0, buffer.Length);
}
}
WriteableBitmap bitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight);
await bitmap.PixelBuffer.AsStream().WriteAsync(managedArray, 0, managedArray.Length);
InMemoryRandomAccessStream inMemoryRandomAccessStream = new InMemoryRandomAccessStream();
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, inMemoryRandomAccessStream);
Stream pixelStream = bitmap.PixelBuffer.AsStream();
byte[] pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight, 96.0, 96.0, pixels);
await encoder.FlushAsync();
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(inMemoryRandomAccessStream);
MyImage.Source = bitmapImage;
}
我正在开发 Windows 通用应用程序,它将在 ARM 架构上 运行(RaspberryPi 3,OS:Windows IoT).
我面临的问题是 UWP 不允许很多标准的 .Net 库,例如 "System.Drawing"
我目前有一个 IntPtr,其中包含图像的原始数据,我需要将其用作 Bitmap,这当然是在这种情况下不可能。是否有任何可能的替代方案。
我已经寻找 BitmapImage 但没有找到任何解决方案。
我也试过将 IntPtr 转换为 Byte[] 然后将数组转换为 Image 或 BitmapImage 在 UWP 中是不可能的。
请放轻松,因为我是 C# 编程的新手。
我只想要来自 IntPtr 的任何类型的位图或图像
提前致谢!
我想追加更多,但我还不能编辑评论,所以我的原始回复自动变成了评论。基本上看起来你的困境很常见,但你必须研究第三方解决方案。
要将IntPtr
转换为Byte[]
,我们可以使用Marshal.Copy
方法。它将数据从一维托管 8 位无符号整数数组复制到非托管内存指针。
然后我们可以使用WriteableBitmap
class设置Byte[]为WriteableBitmap
。
The image source data of a WriteableBitmap is an underlying pixel buffer. PixelBuffer cannot be written to directly, however, you can use language-specific techniques to access the buffer and change its contents.
To access the pixel content from C# or Microsoft Visual Basic, you can use the AsStream extension method to access the underlying buffer as a stream.
有关详细信息,请参阅 Remarks of the WriteableBitmap。
要将 WriteableBitmap
转换为 BitmapImage
,我们应该能够对来自 WriteableBitmap
的流进行编码。
例如:
private byte[] managedArray;
private async void Button_Click(object sender, RoutedEventArgs e)
{
Windows.Storage.Streams.IRandomAccessStream random = await Windows.Storage.Streams.RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/sunset.jpg")).OpenReadAsync();
Windows.Graphics.Imaging.BitmapDecoder decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(random);
Windows.Graphics.Imaging.PixelDataProvider pixelData = await decoder.GetPixelDataAsync();
byte[] buffer = pixelData.DetachPixelData();
unsafe
{
fixed (byte* p = buffer)
{
IntPtr ptr = (IntPtr)p;
managedArray = new byte[buffer.Length];
Marshal.Copy(ptr, managedArray, 0, buffer.Length);
}
}
WriteableBitmap bitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight);
await bitmap.PixelBuffer.AsStream().WriteAsync(managedArray, 0, managedArray.Length);
InMemoryRandomAccessStream inMemoryRandomAccessStream = new InMemoryRandomAccessStream();
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, inMemoryRandomAccessStream);
Stream pixelStream = bitmap.PixelBuffer.AsStream();
byte[] pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight, 96.0, 96.0, pixels);
await encoder.FlushAsync();
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(inMemoryRandomAccessStream);
MyImage.Source = bitmapImage;
}