不安全代码解释

unsafe code explanation

        private static Complex[,] FromBitmapData(BitmapData _BitmapData)
        {
            if (_BitmapData.PixelFormat != PixelFormat.Format8bppIndexed)
            {
                throw new Exception("Source can be grayscale (8bpp indexed) only.");
            }

            int width = _BitmapData.Width;
            int height = _BitmapData.Height;
            int offset = _BitmapData.Stride - width;

            if ((!Utils.IsPowerOf2(width)) || (!Utils.IsPowerOf2(height)))
            {
                throw new Exception("Image width and height should be power of 2.");
            }

            Complex[,] data = new Complex[width, height];

            unsafe
            {
                byte* src = (byte*)_BitmapData.Scan0.ToPointer();

                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++, src++)
                    {
                        data[y, x] = new Complex((float)*src / 255, 
                                                    data[y, x].Imaginary);
                    }

                    src += offset;
                }
            }

            return data;
        }

为什么*src指向的值除以255?

什么是Stride

出于对齐等目的,有时位图中的像素行比宽度长 - 它的长度称为步幅。因此,您可以设置宽度 = 3 和步幅 = 4,数据行将如下所示:

Row: [Pixel][Pixel][Pixel][Unused]

offset代表什么?

这是步幅和宽度之间的区别,即当你读取了一行中的所有真实像素时,你需要跳过多少未使用的像素才能到达下一行。

为什么src在内循环中加1,而在外循环中又加offset

内循环读取行的像素,因此 src 在每次迭代中递增 1 以到达下一个像素。但是在你全部阅读完之后,你需要跳过 offset 未使用的数据才能进入下一行。

为什么*src指向的值除以255

复杂类型有浮点分量,8bpp位图中的像素是用字节表示的,所以它们的值来自0–255。除以 255 将它们转换为 0.0–1.0.

范围内的浮点数

为什么data[x,y].Imaginary作为参数传递?

由于某些原因,此函数以复杂类型存储位图数据,而复杂类型具有实部和虚部,因此赋值

data[y, x] = new Complex(something, data[y,x].Imaginary); 

意思是:将 data[y,x] 的实部设置为某个值,而虚部保持原样。