gpt4 book ai didi

c# - 如何从像素字节数组创建 BitmapImage(实时视频显示)

转载 作者:太空狗 更新时间:2023-10-29 21:09:28 26 4
gpt4 key购买 nike

我需要在 WPF 控件上显示实时图像。我正在寻找使用 WPF 执行此操作的最快方法。

我正在使用相机的 dll API ( AVT ) 从相机捕捉图像。

图像由 dll 写入,相机使用 IntPtr 向名为 tFrame 的图像结构(如下所述)发起回调。像素数据存储在 ImageBuffer 属性中,是字节数组的 InPtr。

我知道如何从像素字节数组创建位图,但不知道 BitmapImage。因此可以创建一个位图,然后从中创建一个 BitmapImagem。 Here there is a way to create a BitmapImage from a Bitmap on the memory .但我想直接从数据源 (tFrame) 创建 BitmapImage。我该怎么做?

我知道 BitmapImage 有一个 CopyPixels 方法,但它缺少一个 SetPixels。

public struct tFrame
{
public IntPtr AncillaryBuffer;
public uint AncillaryBufferSize;
public uint AncillarySize;
public tBayerPattern BayerPattern;
public uint BitDepth;
public tFrameCtx Context;
public tImageFormat Format;
public uint FrameCount;
public uint Height;
public IntPtr ImageBuffer;
public uint ImageBufferSize;
public uint ImageSize;
public uint RegionX;
public uint RegionY;
public tErr Status;
public uint TimestampHi;
public uint TimestampLo;
public uint Width;
}

下面是我如何从像素字节数组创建位图。这用于软件的 WinForm 版本。

private void CreateBitmap(tFrame frame)
{
//This sample is for a 8bpp captured image
PixelFormat pxFormat = PixelFormat.Format8bppIndexed;

//STRIDE
//[https://stackoverflow.com/questions/1983781/why-does-bitmapsource-create-throw-an-argumentexception/1983886#1983886][3]
//float bitsPerPixel = System.Drawing.Image.GetPixelFormatSize(format);
int bitsPerPixel = ((int)pxFormat >> 8) & 0xFF;
//Number of bits used to store the image data per line (only the valid data)
int validBitsPerLine = ((int)frame.Width) * bitsPerPixel;
//4 bytes for every int32 (32 bits)
int stride = ((validBitsPerLine + 31) / 32) * 4;

Bitmap bmp = new Bitmap((int)frame.Width, (int)frame.Height, stride, pxFormat, frame.ImageBuffer);
}

编辑 1:

感谢 dr.mo,现在我能够以 ~3% 的 CPU 使用率显示 60 FPS 1024x1024 图像!我正在做的是:

//@ UI Thread
public WriteableBitmap wbm = new WriteableBitmap(1024, 1024, (double)96, (double)96, System.Windows.Media.PixelFormats.Gray8, null);
this.wbBackBuffer = this.wbm.BackBuffer;

//This can be called by a timer in the UI thread or at the grab Thread for every image, the CPU usage is almost the same.
void UpdateDisplayImage()
{
wbm.Lock();
wbm.AddDirtyRect(new Int32Rect(0, 0, wbm.PixelWidth, wbm.PixelHeight));
wbm.Unlock();
}

//@ Grab Thread
//Update the backbuffer with new camera image data.
UpdateBackBuffer(...);

/// <summary>
/// [http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.writeablebitmap.aspx]
/// </summary>
public void UpdateBackBuffer(IntPtr pData, int w, int h, int ch)
{
//Can not acess wbm from outside UI thread
//CopyMemory(wbm.BackBuffer, pData, (uint)(w * h * ch));
//I dont know if it is safe to write to it buffer like this:
CopyMemory(this.wbBackBuffer, pData, (uint)(w * h * ch));
}

最佳答案

这应该可以解决问题。它 super 快。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.Drawing;
using System.Runtime.InteropServices;
using System.IO;
using System.ComponentModel;


public class MakeBitmapSource
{
[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
public static extern void CopyMemory(IntPtr Destination, IntPtr Source, uint Length);



public static BitmapSource FromNativePointer(IntPtr pData, int w, int h, int ch)
{
PixelFormat format = PixelFormats.Default;

if (ch == 1) format = PixelFormats.Gray8; //grey scale image 0-255
if (ch == 3) format = PixelFormats.Bgr24; //RGB
if (ch == 4) format = PixelFormats.Bgr32; //RGB + alpha


WriteableBitmap wbm = new WriteableBitmap(w, h, 96, 96, format, null);
CopyMemory(wbm.BackBuffer, pData, (uint)(w * h * ch));

wbm.Lock();
wbm.AddDirtyRect(new Int32Rect(0, 0, wbm.PixelWidth, wbm.PixelHeight));
wbm.Unlock();

return wbm;
}

public static BitmapSource FromArray(byte[] data, int w, int h, int ch)
{
PixelFormat format = PixelFormats.Default;

if (ch == 1) format = PixelFormats.Gray8; //grey scale image 0-255
if (ch == 3) format = PixelFormats.Bgr24; //RGB
if (ch == 4) format = PixelFormats.Bgr32; //RGB + alpha


WriteableBitmap wbm = new WriteableBitmap(w, h, 96, 96, format, null);
wbm.WritePixels(new Int32Rect(0, 0, w, h), data, ch * w, 0);

return wbm;
}
}

关于c# - 如何从像素字节数组创建 BitmapImage(实时视频显示),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16220472/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com