【问题标题】:Trying to Understand this Image function试图理解这个图像功能
【发布时间】:2021-11-12 11:55:49
【问题描述】:
private void ReadImage()
    {
        int i, j;
        GreyImage = new int[Width, Height];  //[Row,Column]
        Bitmap image = Obj;
        BitmapData bitmapData1 = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
                                 ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
        unsafe
        {
            byte* imagePointer1 = (byte*)bitmapData1.Scan0;

            for (i = 0; i < bitmapData1.Height; i++)
            {
                for (j = 0; j < bitmapData1.Width; j++)
                {
                    GreyImage[j, i] = (int)((imagePointer1[0] + imagePointer1[1] + imagePointer1[2]) / 3.0);
                    //4 bytes per pixel
                    imagePointer1 += 4;
                }//end for j
                //4 bytes per pixel
                imagePointer1 += bitmapData1.Stride - (bitmapData1.Width * 4);
            }//end for i
        }//end unsafe
        image.UnlockBits(bitmapData1);
        return;
    }

GreyImage[j,i] = (int)((imagePointer1[0] ..... 行似乎像数组一样读入byte*,显然我不能将不安全的代码位分配给数组以供以后处理,所以我想可能只是将这 4 个字节分配给数组。

如何将这 4 个字节分配给数组?

我想通过做:

var imageData = new byte[Width, Height][];
imageData[x,y] = pixelSet //basically byte[];

【问题讨论】:

    标签: c# arrays unsafe


    【解决方案1】:

    我认为您正在尝试做这样的事情。显然,我还没有测试过这段代码,但它会让你朝着你想要的方向前进。

    byte[] save = new byte[4];
    Array.Copy(*imagePointer1, save, 4);
    

    byte[] save = new byte[4];
    save[0] = bitmapData1.Scan0[0];
    save[1] = *(imagePointer1 + 1);
    save[2] = *(imagePointer1 + 2);
    save[3] = *(imagePointer1 + 3);
    

    指向数组的指针始终指向元素零。您可以通过添加到指针或增加指针来访问其他元素。

     (imagePointer1 + 5)  // pointer to 5th element
    *(imagePointer1 + 5)  // value of 5th element
      imagePointer1 += 5; // imagePointer1 now starts at element 5
    

    加号和减号将指针引用移动构成数组数据类型大小的字节数。如果是 int[],+ 和 - 将以 4 个字节为增量移动指针。

    【讨论】:

    • 是的,这正是我正在寻找的,我在谷歌旅行时确实发现了类似的东西,但是,当谈到选择 byte[] 数组大小时,我不知道,所以我想“你是如何从imagePointer 得到的”,所以我想我明白 imagePointer 是整个图像的权利。
    • 是的,imagePointer1 是指向 bitmapData1.Scan0[0] 的指针。如果你试图读取过去的 bitmapData1.Scan0.Length,你会遇到问题。
    【解决方案2】:

    该函数应该将您的图像转换为灰度图像,并将颜色值存储到GreyScale 数组中。但是这个函数有一个错误(实际上是2个)。

    首先,你只读取图像的左上角像素,而不是使用这个:

    GreyImage[j, i] = (int)((imagePointer1[j * 4 + i * bitmapData1.Width * 4] + imagePointer1[j * 4 + i * bitmapData1.Width * 4 + 1] + imagePointer1[j * 4 + i * bitmapData1.Width * 4 + 2]) / 3.0);
    

    另一件事是,当您转换图像时,所有颜色都不“相等”,您可以在 google 上找到应用于红色、绿色和蓝色通道的常用因子,以便轻松转换为灰度。

    为了回答您的问题,在您的函数中将值分配给数组的方式是正确的。

    编辑

    回答你的问题:

    在括号[] 中,我计算坐标(j, i) 处像素的颜色信息所在的数组中的偏移量。 (顺便说一句,我们通常使用i 代表xj 代表y,这里正好相反)

    假设您想知道坐标x = 2, y = 4 处像素的颜色值,您需要使用以下公式:

    color = y * &lt;number of bytes per line&gt; + x

    由于您的图像是 32 位的,使用上面的公式,您将获得颜色的红色值。 如果你想要绿色的加 1,蓝色的你加 2。

    在我发布的那段代码中,我假设每一行都占用 width * 4 字节,这对于 32 位图像大部分时间都是正确的,但并非总是如此,所以最好实际使用这个公式:

    [imagePointer[i * bitmapData1.Stride + j]

    【讨论】:

    • 我不想存储灰度,我想将组成图像的 4 个字节保留在一个新数组中,就像我在答案底部所说的那样,感谢您澄清问题,非常感谢
    • @No1_Melman 可以使用同一段代码,只是去掉行尾的/ 3.0
    • 非常感谢,您能否再解释一下您在 imagePointer1 的[] 中所做的事情,只是对使用的数字或使用的变量的解释。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2019-09-06
    • 2014-06-01
    • 1970-01-01
    • 2018-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多