使用位图在C#中的快速工作 [英] Fast work with Bitmaps in C#

查看:262
本文介绍了使用位图在C#中的快速工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要访问一个位图的每个像素,与他们合作,然后将它们保存到一个位图。

I need to access each pixel of a Bitmap, work with them, then save them to a Bitmap.

使用 Bitmap.GetPixel() Bitmap.SetPixel(),我的程序运行缓慢。

Using Bitmap.GetPixel() and Bitmap.SetPixel(), my program runs slowly.

我怎样可以快速转换位图字节[]和回?

How can I quickly convert Bitmap to byte[] and back?

我需要一个字节[] 长度=(4 *宽*高),载有RGBA数据每个像素

I need a byte[] with length = (4 * width * height), containing RGBA data of each pixel.

推荐答案

您可以做几个不同的方式。您可以使用不安全来直接获取数据,也可以使用编组将数据复制来回。不安全的code是速度快,但封送处理不需要不安全code。这里有一个<一个href="http://davidthomasbernal.com/blog/2008/03/14/c-image-processing-performance-unsafe-vs-safe-$c$c-part-ii/">performance比较我做了一段时间回来。

You can do it a couple of different ways. You can use unsafe to get direct access to the data, or you can use marshaling to copy the data back and forth. The unsafe code is faster, but marshaling doesn't require unsafe code. Here's a performance comparison I did a while back.

下面是一个使用lockbits一个完整的示例:

Here's a complete sample using lockbits:

/*Note unsafe keyword*/
public unsafe Image ThresholdUA(float thresh)
{
    Bitmap b = new Bitmap(_image);//note this has several overloads, including a path to an image

    BitmapData bData = b.LockBits(new Rectangle(0, 0, _image.Width, _image.Height), ImageLockMode.ReadWrite, b.PixelFormat);

    byte bitsPerPixel = GetBitsPerPixel(bData.PixelFormat);

    /*This time we convert the IntPtr to a ptr*/
    byte* scan0 = (byte*)bData.Scan0.ToPointer();

    for (int i = 0; i < bData.Height; ++i)
    {
        for (int j = 0; j < bData.Width; ++j)
        {
            byte* data = scan0 + i * bData.Stride + j * bitsPerPixel / 8;

            //data is a pointer to the first byte of the 3-byte color data
        }
    }

    b.UnlockBits(bData);

    return b;
}

下面是同样的事情,但封送处理:

Here's the same thing, but with marshaling:

/*No unsafe keyword!*/
public Image ThresholdMA(float thresh)
{
    Bitmap b = new Bitmap(_image);

    BitmapData bData = b.LockBits(new Rectangle(0, 0, _image.Width, _image.Height), ImageLockMode.ReadWrite, b.PixelFormat);

    /* GetBitsPerPixel just does a switch on the PixelFormat and returns the number */
    byte bitsPerPixel = GetBitsPerPixel(bData.PixelFormat);

    /*the size of the image in bytes */
    int size = bData.Stride * bData.Height;

    /*Allocate buffer for image*/
    byte[] data = new byte[size];

    /*This overload copies data of /size/ into /data/ from location specified (/Scan0/)*/
    System.Runtime.InteropServices.Marshal.Copy(bData.Scan0, data, 0, size);

    for (int i = 0; i < size; i += bitsPerPixel / 8 )
    {
        double magnitude = 1/3d*(data[i] +data[i + 1] +data[i + 2]);

        //data[i] is the first of 3 bytes of color

    }

    /* This override copies the data back into the location specified */
    System.Runtime.InteropServices.Marshal.Copy(data, 0, bData.Scan0, data.Length);

    b.UnlockBits(bData);

    return b;
}

这篇关于使用位图在C#中的快速工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆