Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.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

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
C# C语言中无彩色对象像素的RGB提取#_C#_.net_Rgb - Fatal编程技术网

C# C语言中无彩色对象像素的RGB提取#

C# C语言中无彩色对象像素的RGB提取#,c#,.net,rgb,C#,.net,Rgb,我试图用以下代码从像素中提取RGB值: for ( int i=0; i < pixeldata.length; i++) { IntPtr ptr = bmd.Scan0+i; byte* pixel = (byte*)ptr; //here is the problem :O float r = pixel[1]; float g = pixel[2]; float b = pi

我试图用以下代码从像素中提取RGB值:

for ( int i=0; i < pixeldata.length; i++)
    {
        IntPtr ptr = bmd.Scan0+i;
        byte* pixel = (byte*)ptr;

        //here is the problem :O

        float r = pixel[1];
        float g = pixel[2];
        float b = pixel[3];
     }
....
源代码是我输入的位图,它是一个图像。
我试图避免使用颜色对象。我已经这样做了,它是有效的,我想用另一种方式,但问题是ptr是一个数字,我必须从中提取rgb

如果有一种格式将R、G和B以一个字节的顺序线性存储在内存中,那么提取RGB值的代码应该如下所示

byte r = pixel[0];
byte g = pixel[1];
byte b = pixel[2];
请注意,索引偏移量从0开始,返回的值是
byte
而不是
float
(如果愿意,当然可以强制转换)

此外,由于3个相邻字节表示单个像素,因此必须将i增加3而不是1

您最好测试
源代码。PixelFormat
确实使用您假设的格式

为了在C#中使用指针,还必须使用/unsafe开关进行编译

更新

根据@Don的评论以及您自己的评论,线性内存中的顺序将是ABGR。这意味着代码将是:

for ( int i=0; i < pixeldata.length; i+=4)
{
    IntPtr ptr = bmd.Scan0+i;
    byte* pixel = (byte*)ptr;

    byte a = pixel[0]; // You can ignore if you do not need alpha.
    byte b = pixel[1];
    byte g = pixel[2];
    byte r = pixel[3];
}
for(int i=0;i
好的,这很有趣,我已经写了一些代码来玩。假设图像的像素格式为
Format24bppRgb
(有关格式的详细信息,请参见此处)。这种格式将B、G、R值一个接一个地存储在24位中

下面的代码将解析硬盘中的一些
d:\\24bits.bmp
图像,并使用第一个图像数据字节数组中的信息B、G、R创建新的相同图像
“d:\\24bits\u 1.bmp”

unsafe private static void TestBMP()
{
    Bitmap bmp = new Bitmap("d:\\24bits.bmp");

    // Ensure that format is Format24bppRgb.
    Console.WriteLine(bmp.PixelFormat);

    Bitmap copyBmp = new Bitmap(bmp.Width, bmp.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

    // Copy all pixels of initial image for verification.
    int pixels = bmp.Height * bmp.Width;
    Color[,] allPixels = new Color[bmp.Height, bmp.Width];
    for (int i = 0; i < bmp.Height; i++)
        for (int j = 0; j < bmp.Width; j++)
            allPixels[i, j] = bmp.GetPixel(j, i);

    // Lock the bitmap's bits.  
    Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    System.Drawing.Imaging.BitmapData bmpData =
        bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly,
        bmp.PixelFormat);

    IntPtr ptr = bmpData.Scan0;

    byte* stream = (byte*)ptr;

    for (int y = 0; y < bmp.Height; y++)
        for (int x = 0; x < bmp.Width; x++)
        {
            int byteIndex = y * bmpData.Stride + x * 3;

            byte r = stream[byteIndex + 2];
            byte g = stream[byteIndex + 1];
            byte b = stream[byteIndex];

            Color c = allPixels[y, x];
            if (r != c.R || g != c.G || b != c.B)
            {
                Console.WriteLine("This should never appear");
            }
            copyBmp.SetPixel(x, y, Color.FromArgb(255, r, g, b));
        }

    // Save new image. It should be the same as initial one.
    copyBmp.Save("d:\\24bits_1.bmp");
}
不安全的私有静态void TestBMP()
{
位图bmp=新位图(“d:\\24bits.bmp”);
//确保格式为24bpprgb。
Console.WriteLine(bmp.PixelFormat);
位图copyBmp=新位图(bmp.Width、bmp.Height、System.Drawing.Imaging.PixelFormat.Format24bppRgb);
//复制初始图像的所有像素以进行验证。
int像素=bmp.Height*bmp.Width;
颜色[,]所有像素=新颜色[bmp.Height,bmp.Width];
对于(int i=0;i
这是一个能为您提供正确答案的解决方案

Bitmap source = new Bitmap(image);

            Rectangle rect = new Rectangle(0, 0, source.Width, source.Height);

            BitmapData bmd = source.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            int totalPixels = rect.Height * rect.Width;
            int[] pixelData = new int[totalPixels];
            for (int i = 0; i < totalPixels; i++)
            {
                byte* pixel = (byte*)bmd.Scan0;
                pixel = pixel + (i * 4);

                byte b = pixel[0];
                byte g = pixel[1];
                byte r = pixel[2];

                int luma = (int)(r * 0.3 + g * 0.59 + b * 0.11);
                pixelData[i] = luma;
            }
位图源=新位图(图像);
矩形rect=新矩形(0,0,source.Width,source.Height);
BitmapData bmd=源.LockBits(rect、ImageLockMode.ReadOnly、PixelFormat.Format32bppArgb);
int totalPixels=矩形高度*矩形宽度;
int[]pixelData=新的int[totalPixels];
对于(int i=0;i
这取决于像素格式。只是好奇,为什么要避免使用颜色对象?假设这是我的CTO提出的挑战。用彩色物体做这件事很容易,我也做过,但是上面的方法应该会给你正确的答案,但是结果大错特错。大多数答案都不正确。为什么我要接受它们?@user843681-然后请随意添加正确的答案并接受它。我认为第一个索引是Alpha,这对我没有用。我实施了你的建议,结果仍然非常错误。@user843681:如果你也有Alpha,然后,您的索引是正确的,但每次迭代必须将
i
增加4。另请参阅@Don关于线性内存中像素顺序的评论。更新了我的答案以反映两者。我实现了这一点,但它没有给出正确的答案。在调试模式下,我选择了一个随机值。使用Color对象,我得到一个特定像素的这些值:ARGB=(255133129),而使用指针方法得到同一像素的这些值:r=255,g=130,b=126。顺便说一下,这个像素的ptr值是116916268。好的,今晚让我测试一下,然后再给你回复。谢谢您的试用。嗨,Sergey,我浏览了您的代码,我必须告诉您,不幸的是,您的代码无法通过我的标准,因为它使用GetPixel方法,这是一种非常慢的方法(我的意思是非常慢!)。此外,使用两个循环会使代码更难在以后变得并行。我所做的是将所有值放在一个大小为height*width的数组中。然后从这个数组中读取并从每个像素字节中提取RGB。我将对此做更多的工作,如果我能正确地解决它,我将发布我的解决方案。@user843681-我的代码使用GetPixel()只是为了证明它是正确的。实际算法d
Bitmap source = new Bitmap(image);

            Rectangle rect = new Rectangle(0, 0, source.Width, source.Height);

            BitmapData bmd = source.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            int totalPixels = rect.Height * rect.Width;
            int[] pixelData = new int[totalPixels];
            for (int i = 0; i < totalPixels; i++)
            {
                byte* pixel = (byte*)bmd.Scan0;
                pixel = pixel + (i * 4);

                byte b = pixel[0];
                byte g = pixel[1];
                byte r = pixel[2];

                int luma = (int)(r * 0.3 + g * 0.59 + b * 0.11);
                pixelData[i] = luma;
            }