如何从SoftwareBitmap中获取字节数组
本文关键字:字节 字节数 数组 获取 SoftwareBitmap | 更新日期: 2023-09-27 18:26:55
Hi我需要如何从C#UWP中的SoftwareBitmap
获取字节数组的帮助,这样我就可以通过TCP套接字发送它。
我还可以访问一个"VideoFrame previewFrame"对象,这是我获取SoftwareBitmap
的地方。
我在网上看到过这样做,但UWP不支持wb.SaveJpeg(...)
。除非我错过了什么?
MemoryStream ms = new MemoryStream();
WriteableBitmap wb = new WriteableBitmap(myimage);
wb.SaveJpeg(ms, myimage.PixelWidth, myimage.PixelHeight, 0, 100);
byte [] imageBytes = ms.ToArray();
任何帮助或正确方向的指示都将不胜感激。
谢谢,Andy
当然,您可以从SoftwareBitmap
访问编码的byte[]
数组。
请参阅此示例,提取jpeg编码的byte[]
:
// includes BitmapEncoder, which defines some static encoder IDs
using Windows.Graphics.Imaging;
private async void PlayWithData(SoftwareBitmap softwareBitmap)
{
// get encoded jpeg bytes
var data = await EncodedBytes(softwareBitmap, BitmapEncoder.JpegEncoderId);
// todo: save the bytes to a DB, etc
}
private async Task<byte[]> EncodedBytes(SoftwareBitmap soft, Guid encoderId)
{
byte[] array = null;
// First: Use an encoder to copy from SoftwareBitmap to an in-mem stream (FlushAsync)
// Next: Use ReadAsync on the in-mem stream to get byte[] array
using (var ms = new InMemoryRandomAccessStream())
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(encoderId, ms);
encoder.SetSoftwareBitmap(soft);
try
{
await encoder.FlushAsync();
}
catch ( Exception ex ){ return new byte[0]; }
array = new byte[ms.Size];
await ms.ReadAsync(array.AsBuffer(), (uint)ms.Size, InputStreamOptions.None);
}
return array;
}
要从SoftwareBitmap获取字节数组,可以使用"SoftwareBitmap.CopyToBuffer"
但是,首先你需要:
使用System.Runtime.InteropServices.WindowsRuntime;
由于方法AsBuffer()到字节[]
StorageFile file = await StorageFile.GetFileFromPathAsync(ImageFilePath);
using (IRandomAccessStream fileStream = await File.OpenAsync(FileAccessMode.Read),
memStream = new InMemoryRandomAccessStream())
{
// Open a Stream and decode a JPG image
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream);
var softwareBitmap = await decoder.GetSoftwareBitmapAsync();
byte [] imageBytes = new byte[4*decoder.PixelWidth*decoder.PixelHeight];
softwareBitmap.CopyToBuffer(imageBytes.AsBuffer());
//... now you can use the imageBytes[]
}
据我所知,你做不到。但你可以使用SoftwareBitmap。参见示例:https://msdn.microsoft.com/en-us/library/windows/apps/mt244351.aspx(SoftwareBitmap是SoftwareBitmapSource的私有字段…只是通过反射读取…也许这是完全错误的建议)
private async void SaveSoftwareBitmapToFile(SoftwareBitmap softwareBitmap, StorageFile outputFile)
{
using (IRandomAccessStream stream = await outputFile.OpenAsync(FileAccessMode.ReadWrite))
{
// Create an encoder with the desired format
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
// Set the software bitmap
encoder.SetSoftwareBitmap(softwareBitmap);
// Set additional encoding parameters, if needed
encoder.BitmapTransform.ScaledWidth = 320;
encoder.BitmapTransform.ScaledHeight = 240;
encoder.BitmapTransform.Rotation = Windows.Graphics.Imaging.BitmapRotation.Clockwise90Degrees;
encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Fant;
encoder.IsThumbnailGenerated = true;
try
{
await encoder.FlushAsync();
}
catch (Exception err)
{
switch (err.HResult)
{
case unchecked((int)0x88982F81): //WINCODEC_ERR_UNSUPPORTEDOPERATION
// If the encoder does not support writing a thumbnail, then try again
// but disable thumbnail generation.
encoder.IsThumbnailGenerated = false;
break;
default:
throw;
}
}
if (encoder.IsThumbnailGenerated == false)
{
await encoder.FlushAsync();
}
}
}
Get-Preview Frame UWP相机样本获取一个相机帧作为SoftwareBitmap
,并通过数组对其上的像素进行操作,然后可以将其保存为JPEG。如果我正确理解你的问题,你需要的所有代码都应该在那里。
基本上,这应该是它的大部分(包括一些相机代码):
private async Task GetPreviewFrameAsSoftwareBitmapAsync()
{
// Get information about the preview
var previewProperties = _mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview) as VideoEncodingProperties;
// Create the video frame to request a SoftwareBitmap preview frame
var videoFrame = new VideoFrame(BitmapPixelFormat.Bgra8, (int)previewProperties.Width, (int)previewProperties.Height);
// Capture the preview frame
using (var currentFrame = await _mediaCapture.GetPreviewFrameAsync(videoFrame))
{
// Collect the resulting frame
SoftwareBitmap previewFrame = currentFrame.SoftwareBitmap;
// Add a simple green filter effect to the SoftwareBitmap
EditPixels(previewFrame);
}
}
private unsafe void EditPixels(SoftwareBitmap bitmap)
{
// Effect is hard-coded to operate on BGRA8 format only
if (bitmap.BitmapPixelFormat == BitmapPixelFormat.Bgra8)
{
// In BGRA8 format, each pixel is defined by 4 bytes
const int BYTES_PER_PIXEL = 4;
using (var buffer = bitmap.LockBuffer(BitmapBufferAccessMode.ReadWrite))
using (var reference = buffer.CreateReference())
{
// Get a pointer to the pixel buffer
byte* data;
uint capacity;
((IMemoryBufferByteAccess)reference).GetBuffer(out data, out capacity);
// Get information about the BitmapBuffer
var desc = buffer.GetPlaneDescription(0);
// Iterate over all pixels
for (uint row = 0; row < desc.Height; row++)
{
for (uint col = 0; col < desc.Width; col++)
{
// Index of the current pixel in the buffer (defined by the next 4 bytes, BGRA8)
var currPixel = desc.StartIndex + desc.Stride * row + BYTES_PER_PIXEL * col;
// Read the current pixel information into b,g,r channels (leave out alpha channel)
var b = data[currPixel + 0]; // Blue
var g = data[currPixel + 1]; // Green
var r = data[currPixel + 2]; // Red
// Boost the green channel, leave the other two untouched
data[currPixel + 0] = b;
data[currPixel + 1] = (byte)Math.Min(g + 80, 255);
data[currPixel + 2] = r;
}
}
}
}
}
并在类外声明这一点以启用GetBuffer
方法:
[ComImport]
[Guid("5b0d3235-4dba-4d44-865e-8f1d0e4fd04d")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
unsafe interface IMemoryBufferByteAccess
{
void GetBuffer(out byte* buffer, out uint capacity);
}
当然,你的项目将不得不允许不安全的代码,所有这些工作。
最后,这就是如何将SoftwareBitmap
保存为JPEG文件:
private static async Task SaveSoftwareBitmapAsync(SoftwareBitmap bitmap, StorageFile file)
{
using (var outputStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, outputStream);
// Grab the data from the SoftwareBitmap
encoder.SetSoftwareBitmap(bitmap);
await encoder.FlushAsync();
}
}