【问题标题】:C# convert stride/buffer/width/height to bitmapC# 将步幅/缓冲区/宽度/高度转换为位图
【发布时间】:2012-07-31 11:40:24
【问题描述】:

我有一个图像宽度/高度/步幅和缓冲区。

如何将此信息转换为 System.Drawing.Bitmap?有这4样东西还能找回原图吗?

【问题讨论】:

  • 你的意思是说上传时要将图像以二进制格式保存到数据库中并检索值并显示为图像?
  • 我的意思是有人编写了一个代码来获取摄像机的高度/宽度/步幅/缓冲区。他现在要我为它做点什么。我想使用位图图像,他使用 writeablebitmap 并告诉我如何获得步幅/宽度等...

标签: c# bitmap writeablebitmap


【解决方案1】:

有一个Bitmap 构造函数重载,它需要你拥有的一切(加上PixelFormat):

public Bitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0);

这可能有效(如果 args.Buffer 是一个 blittable 类型的数组,例如 byte):

Bitmap bitmap;
var gch = System.Runtime.InteropServices.GCHandle.Alloc(args.Buffer, GCHandleType.Pinned);
try
{
    bitmap = new Bitmap(
        args.Width, args.Height, args.Stride,
        System.Drawing.Imaging.PixelFormat.Format24bppRgb,
        gch.AddrOfPinnedObject());
}
finally
{
    gch.Free();
}

更新:

可能最好手动将图像字节复制到新创建的Bitmap,因为构造函数似乎不会这样做,并且如果图像数据的byte[] 数组被垃圾收集,则可能会发生各种不好的事情。

var bitmap = new Bitmap(args.Width, args.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
var data = bitmap.LockBits(
    new Rectangle(0, 0, args.Width, args.Height),
    System.Drawing.Imaging.ImageLockMode.WriteOnly,
    System.Drawing.Imaging.PixelFormat.Format24bppRgb);

if(data.Stride == args.Stride)
{
    Marshal.Copy(args.Buffer, 0, data.Scan0, args.Stride * args.Height);
}
else
{
    int arrayOffset = 0;
    int imageOffset = 0;
    for(int y = 0; y < args.Height; ++y)
    {
        Marshal.Copy(args.Buffer, arrayOffset, (IntPtr)(((long)data.Scan0) + imageOffset), data.Stride);
        arrayOffset += args.Stride;
        imageOffset += data.Stride;
    }
}

bitmap.UnlockBits(data);

【讨论】:

  • 我得到的只是我可以在 args 中找到 stride/buffer 等 -> args.Buffer = buffer... args.Stride = stride 等 但是使用 Bitmap test = new Bitmap (args.Width, args.Height, args.Stride, PixelFormats.Rgb24, args.Buffer);给我一个错误:(我对图像编程有点陌生...
  • 这行得通吗……好吧……把我带到某个地方……? var test = BitmapFrame.Create(args.Width, args.Height, 300D, 300D, PixelFormats.Rgb24, null, args.Buffer, args.Stride);
  • args.Buffer 是什么类型? byte[]? System.Drawing.BitmapBitmapFrame 来自 2 个不同的 GUI 框架,你必须决定使用什么。
  • 好吧...我会坚持使用 Bitmap,因为这就是我其余代码的内容...我已经完成了代码,现在将其放入他的系统...是的,args.Buffer 是 byte[] 这给了我需要 System.IntPtr 的错误...所以我现在也很高兴查找该转换:)
  • 是的,有效。必须整理格式,因为目前它是蓝色的……猜他给了我关于像素格式的错误信息……而且,现在运行代码会导致程序其他地方出现问题。 :( 不过感谢您的帮助!希望我能解决其他问题 :)
【解决方案2】:

如果您将缓冲区设置为 byte[]、宽度和高度 + 像素格式(步幅),这应该可以工作

    public Bitmap CreateBitmapFromRawDataBuffer(int width, int height, PixelFormat imagePixelFormat, byte[] buffer)
    {
        Size imageSize = new Size(width, height);

        Bitmap bitmap = new Bitmap(imageSize.Width, imageSize.Height, imagePixelFormat);
        Rectangle wholeBitmap = new Rectangle(0, 0, bitmap.Width, bitmap.Height);

        // Lock all bitmap's pixels.
        BitmapData bitmapData = bitmap.LockBits(wholeBitmap, ImageLockMode.WriteOnly, imagePixelFormat);

        // Copy the buffer into bitmapData.
        System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bitmapData.Scan0, buffer.Length);

        // Unlock  all bitmap's pixels.
        bitmap.UnlockBits(bitmapData);

        return bitmap;
    }

【讨论】:

  • 简单、简洁、快速。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-20
  • 2020-10-13
  • 2019-05-27
  • 2021-01-14
相关资源
最近更新 更多