Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用位图.LockBits函数访问的底层缓冲区在C#中处理位图_C#_.net_Image Processing_System.drawing_Lockbits - Fatal编程技术网

使用位图.LockBits函数访问的底层缓冲区在C#中处理位图

使用位图.LockBits函数访问的底层缓冲区在C#中处理位图,c#,.net,image-processing,system.drawing,lockbits,C#,.net,Image Processing,System.drawing,Lockbits,我需要对任意图像进行分析。我想从最简单的例子开始——只需将图像复制到picturebox Bitmap foreImg = new Bitmap("input.jpg"); //output image Bitmap resImg = new Bitmap(foreImg.Width, foreImg.Height); unsafe { BitmapData oneBits = foreImg.LockBits(new Rectangle(0, 0, foreImg.Width, for

我需要对任意图像进行分析。我想从最简单的例子开始——只需将图像复制到picturebox

Bitmap foreImg = new Bitmap("input.jpg");
//output image
Bitmap resImg = new Bitmap(foreImg.Width, foreImg.Height);
unsafe
{
    BitmapData oneBits = foreImg.LockBits(new Rectangle(0, 0, foreImg.Width, foreImg.Height), ImageLockMode.ReadOnly, foreImg.PixelFormat);
    BitmapData thrBits = resImg.LockBits(new Rectangle(0, 0, resImg.Width, resImg.Height), ImageLockMode.WriteOnly, resImg.PixelFormat);

    System.Threading.Tasks.Parallel.For(0, foreImg.Width * foreImg.Height, j =>
    {
        Pixel* pxOne = (Pixel*)((byte*)oneBits.Scan0 + j * sizeof(Pixel));
        Pixel* pxRes = (Pixel*)((byte*)thrBits.Scan0 + j * sizeof(Pixel));
        pxRes->Green = pxOne->Green;
        pxRes->Red = pxOne->Red;
        pxRes->Blue = pxOne->Blue;

     });

    foreImg.UnlockBits(oneBits);
    resImg.UnlockBits(thrBits);
}
在我的程序中,图像被扭曲了 原件:
之后:。我做错什么了?

谢谢!问题是输入图像的像素格式与我的结构像素不匹配。事实上,我没有添加alpha字节,在本例中,我假设使用Format24bppRgb。

您的图像复制代码有两个错误,这是由于对所复制的特定图像的假设不成立。首先假设,当您为复制操作创建新的目标图像时,它将具有与源图像完全相同的像素表示形式,这有时可能是正确的,但在许多情况下不会:

Bitmap resImg=新位图(foreImg.Width、foreImg.Height)

应改为:

Bitmap resImg=新位图(foreImg.Width、foreImg.Height、foreImg.PixelFormat)

根据图像的不同,下一个假设可能会出错,也可能不会出错,这是一个隐式假设,即源图像
PixelFormat
的大小正好是3个字节,对应于
PixelFormat.Format24bppRgb
格式(或3个字节的倍数,因为我不知道像素结构中红色、绿色或蓝色通道的大小,可能是
PixelFormat.Format48bppRgb
format),因此基于此假设,字节从源图像复制到目标图像

要执行精确复制,必须将相同数量的字节从源图像复制到目标图像,并且不需要使用底层的
像素
结构,而是可以基于整数复制。最后但并非最不重要的一点是,如果目标是复制图像而不是逐像素分析其内容,则方法是使用专门的内存复制功能:

System.Buffer.MemoryCopy((void*)oneBits.Scan0,(void*)thrBits.Scan0,byteLength,byteLength);

下面是一个代码列表,其中包含使用
ulong
作为
carrier
复制图像的代码。我添加了返回
Pixel
大小(以字节为单位)的函数,用于计算图像大小(以字节为单位)并执行精确复制。但是,它可以用于选择匹配的
Pixel
结构,而不是可以使用的结构d分析图像数据。例如,如果图像具有
PixelFormat.Format24bppRgb
格式,则可以使用3字节大小和RGB颜色的
Pixel
结构。对于其他格式,需要定义其他直接复制图像
Pixel
格式的
Pixel
结构

using System;
using System.Drawing;
using System.Drawing.Imaging;

namespace DrawingImagingOperations
{
    class Program
    {
        static void Main(string[] args)
        {
            Bitmap foreImg = new Bitmap(@"..\..\YaHI9.jpg");
            //output image
            Bitmap resImg = new Bitmap(foreImg.Width, foreImg.Height, foreImg.PixelFormat);
            unsafe
            {
                BitmapData oneBits = foreImg.LockBits(new Rectangle(0, 0, foreImg.Width, foreImg.Height), ImageLockMode.ReadOnly, foreImg.PixelFormat);
                BitmapData thrBits = resImg.LockBits(new Rectangle(0, 0, resImg.Width, resImg.Height), ImageLockMode.WriteOnly, resImg.PixelFormat);
                int pixelSize = GetPixelSize(foreImg.PixelFormat);

                var byteLength = foreImg.Width * foreImg.Height * pixelSize;
                var length = byteLength / sizeof(UInt64);
                var reminder = byteLength % sizeof(UInt64);


                System.Threading.Tasks.Parallel.For(0, length, j =>
                {
                    ulong* pxOne = (ulong*)((byte*)oneBits.Scan0 + j * sizeof(UInt64));
                    ulong* pxRes = (ulong*)((byte*)thrBits.Scan0 + j * sizeof(UInt64));
                    *pxRes = *pxOne;
                });

                if (reminder > 0)
                {
                    byte* pSrc = (byte*)oneBits.Scan0 + (pixelSize * length);
                    byte* pDst = (byte*)thrBits.Scan0 + (pixelSize * length);
                    for (int j = length; j < byteLength; j++)
                        *pDst++ = *pSrc++;

                }

                foreImg.UnlockBits(oneBits);
                resImg.UnlockBits(thrBits);
            }

            resImg.Save(@"..\..\imgCopy.jpg");
        }

        internal static int GetPixelSize(PixelFormat data)
        {
            switch (data)
            {
                case PixelFormat.Format8bppIndexed:
                    return 1;
                case PixelFormat.Format16bppGrayScale:
                case PixelFormat.Format16bppRgb555:
                case PixelFormat.Format16bppRgb565:
                case PixelFormat.Format16bppArgb1555:
                    return 2;
                case PixelFormat.Format24bppRgb:
                    return 3;
                case PixelFormat.Canonical:
                case PixelFormat.Format32bppArgb:
                case PixelFormat.Format32bppPArgb:
                case PixelFormat.Format32bppRgb:
                    return 4;
                case PixelFormat.Format48bppRgb:
                    return 6;
                case PixelFormat.Format64bppArgb:
                case PixelFormat.Format64bppPArgb:
                    return 8;
            }

            throw new FormatException("Unsupported image format: " + data);
        }
    }
}
使用系统;
使用系统图;
使用系统、绘图、成像;
命名空间DrawingImagingOperations
{
班级计划
{
静态void Main(字符串[]参数)
{
位图foreImg=新位图(@.\..\YaHI9.jpg);
//输出图像
位图大小=新位图(foreImg.Width、foreImg.Height、foreImg.PixelFormat);
不安全的
{
BitmapData oneBits=foreImg.LockBits(新矩形(0,0,foreImg.Width,foreImg.Height),ImageLockMode.ReadOnly,foreImg.PixelFormat);
BitmapData thrBits=resImg.LockBits(新矩形(0,0,resImg.Width,resImg.Height),ImageLockMode.WriteOnly,resImg.PixelFormat);
int pixelSize=GetPixelSize(foreImg.PixelFormat);
var byteLength=前景宽度*前景高度*像素大小;
var长度=byteLength/sizeof(UInt64);
var提醒=通过发送长度%sizeof(UInt64);
System.Threading.Tasks.Parallel.For(0,length,j=>
{
ulong*pxOne=(ulong*)((字节*)oneBits.Scan0+j*sizeof(UInt64));
ulong*pxRes=(ulong*)((字节*)thrBits.Scan0+j*sizeof(UInt64));
*pxRes=*pxOne;
});
如果(提醒>0)
{
byte*pSrc=(byte*)oneBits.Scan0+(像素大小*长度);
字节*pDst=(字节*)thrBits.Scan0+(像素大小*长度);
对于(int j=长度;j
你能解释一下你在做什么样的图像处理吗?什么是
像素
?我猜你的像素结构缺少字母的一个字节。在任何情况下,不要锁定未知的格式,选择与你的处理相匹配的格式,看起来你假设
格式24bpprgb
你总是非常非常关心像素f当您直接操作位图数据时,ormat。所以