C# 有谁能解释bitmapdata中的STERE功能? Bitmap bit1=新位图(bmpimg、宽度、高度); 位图bit2=新位图(bmp、宽度、高度); 位图bmpresult=新位图(宽度、高度); BitmapData data1=bit1.LockBits(新矩形(0,0,bit1.Width,bit1.Height),ImageLockMode.ReadWrite,PixelFormat.Format24bppRgb); BitmapData data2=bit2.LockBits(新矩形(0,0,bit2.Width,bit2.Height),ImageLockMode.ReadWrite,PixelFormat.Format24bppRgb); BitmapData data3=bmpresult.LockBits(新矩形(0,0,bmpresult.Width,bmpresult.Height),ImageLockMode.ReadWrite,PixelFormat.Format24bppRgb); 不安全的 { int remain1=data1.Stride-data1.Width*3; int remain2=data2.Stride-data2.Width*3; int remain3=data3.Stride-data3.Width*3; 字节*ptr1=(字节*)数据1.Scan0; 字节*ptr2=(字节*)数据2.Scan0; 字节*ptr3=(字节*)数据3.Scan0; 对于(int i=0;i

C# 有谁能解释bitmapdata中的STERE功能? Bitmap bit1=新位图(bmpimg、宽度、高度); 位图bit2=新位图(bmp、宽度、高度); 位图bmpresult=新位图(宽度、高度); BitmapData data1=bit1.LockBits(新矩形(0,0,bit1.Width,bit1.Height),ImageLockMode.ReadWrite,PixelFormat.Format24bppRgb); BitmapData data2=bit2.LockBits(新矩形(0,0,bit2.Width,bit2.Height),ImageLockMode.ReadWrite,PixelFormat.Format24bppRgb); BitmapData data3=bmpresult.LockBits(新矩形(0,0,bmpresult.Width,bmpresult.Height),ImageLockMode.ReadWrite,PixelFormat.Format24bppRgb); 不安全的 { int remain1=data1.Stride-data1.Width*3; int remain2=data2.Stride-data2.Width*3; int remain3=data3.Stride-data3.Width*3; 字节*ptr1=(字节*)数据1.Scan0; 字节*ptr2=(字节*)数据2.Scan0; 字节*ptr3=(字节*)数据3.Scan0; 对于(int i=0;i,c#,C#,是否有必要保留数据对象扫描线通常在边界上对齐 有一个很好的图表 实现CPU可访问位图的人希望在处理器字边界上对齐他们的扫描线,因为访问和操作处理器字的机器代码可能比不对齐地址的机器代码要快得多。由于硬件要求不幸泄漏到API中,因此存在着跨步层 这一点很重要,因为Windows驱动程序有时要求扫描线(图像中的行)与内存对齐。这就是为什么它们有时比严格要求的要大 例如,请参阅这篇MSDN文章 每个扫描线都是DWORD对齐的。扫描线被缓冲以对齐;缓冲不一定是0 您的处理似乎足够了。Stride是代码必

是否有必要保留数据对象

扫描线通常在边界上对齐

有一个很好的图表


实现CPU可访问位图的人希望在处理器字边界上对齐他们的扫描线,因为访问和操作处理器字的机器代码可能比不对齐地址的机器代码要快得多。

由于硬件要求不幸泄漏到API中,因此存在着跨步层

这一点很重要,因为Windows驱动程序有时要求扫描线(图像中的行)与内存对齐。这就是为什么它们有时比严格要求的要大

例如,请参阅这篇MSDN文章

每个扫描线都是DWORD对齐的。扫描线被缓冲以对齐;缓冲不一定是0


您的处理似乎足够了。

Stride是代码必须迭代通过才能到达下一个垂直像素的字节数

如果硬件需要一定倍数的宽度,这可能与图像的宽度*像素大小不同。

是的,这是必要的

步长值是从一条扫描线的起点到下一条扫描线起点的偏移量。如果扫描行被填充,则该值比扫描行中像素所需的值多几个字节


如果位图颠倒存储在内存中(即首先是底部扫描线),则步长值为负值。如果在不使用步长值的情况下读取这样的位图,则在第一行扫描后会出现垃圾或内存访问错误。

步长值是位图表示一行像素所用的字节数。因此,您可以将内存指针向前移动一大步以向下移动一行

在上述给定代码中,是否需要使用数据。大步的基本用途是什么?我希望你现在能理解,迭代应该是字节,而不是像素,因为从一条扫描线开始到下一条扫描线的偏移量不一定是像素大小的倍数。例如,3像素宽的24位图像每行使用9个字节,但可以填充到10个字节(3 1/3像素)或12个字节(4像素)。我不认为这是一个硬件要求,因为在有图形硬件可以进行加速(blitting)之前,就存在stride。如果我没记错的话,这更多的是为了优化早期PC上的图形性能,因为所有的图形操作都是由CPU完成的。最明显的原因是为了使像素索引更容易-使跨步为2字节的幂次,并消除乘法(过去很慢)。此外,早期的图形卡使用位平面来存储帧缓冲区,这意味着存储图像的最简单方法是将图像填充到8个像素宽图像的倍数。感谢您不再需要担心基于位平面的硬件。哇。这是重要的信息。因此,正确获取图像上实际像素数据的唯一方法是获取图像宽度并将其乘以每个像素的字节数,然后?图表链接被中断
        Bitmap bit1 = new Bitmap( bmpimg , width , height );
        Bitmap bit2 = new Bitmap( bmp , width , height );

        Bitmap bmpresult = new Bitmap( width , height );

        BitmapData data1 = bit1.LockBits( new Rectangle( 0 , 0 , bit1.Width , bit1.Height ) , ImageLockMode.ReadWrite , PixelFormat.Format24bppRgb );
        BitmapData data2 = bit2.LockBits( new Rectangle( 0 , 0 , bit2.Width , bit2.Height ) , ImageLockMode.ReadWrite , PixelFormat.Format24bppRgb );
        BitmapData data3 = bmpresult.LockBits( new Rectangle( 0 , 0 , bmpresult.Width , bmpresult.Height ) , ImageLockMode.ReadWrite , PixelFormat.Format24bppRgb );

unsafe
        {
            int remain1 = data1.Stride - data1.Width * 3;
            int remain2 = data2.Stride - data2.Width * 3;
            int remain3 = data3.Stride - data3.Width * 3;


            byte* ptr1 = ( byte* )data1.Scan0;
            byte* ptr2 = ( byte* )data2.Scan0;
            byte* ptr3 = ( byte* )data3.Scan0;

            for( int i = 0 ; i < height ; i ++ )
            {
                for( int j = 0 ; j < width * 3 ; j ++ )
                {
                    ptr3[ 0 ] = ( byte ) ( XOR_Operator( ptr1[ 0 ] , ptr2[ 0 ] ) );
                    ptr1 ++;
                    ptr2 ++;
                    ptr3 ++;
                }

                ptr1 += remain1;
                ptr2 += remain2;
                ptr3 += remain3;
            }


        }

        bit1.UnlockBits( data1 );
        bit2.UnlockBits( data2 );
        bmpresult.UnlockBits( data3 );

        return bmpresult;
    }