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;
}
是否需要保留数据对象
答案 0 :(得分:7)
由于硬件要求不幸泄漏到API层,因此存在Stride。
这很重要,因为Windows驱动程序有时需要扫描线(图像中的行)与内存对齐。这就是为什么它们有时比它们严格需要的要大。
请参阅此MSDN文章DIBs and Their Use。
每条扫描线都是 DWORD - 对齐。扫描线被缓冲到对齐;缓冲不一定是0。
您的处理似乎已足够。
答案 1 :(得分:5)
Stride 是您的代码必须迭代到达下一个垂直像素的字节数。
如果硬件要求宽度为特定倍数,则可能与图像的宽度*像素大小不同。
答案 2 :(得分:3)
扫描线通常在processor word边界上对齐。
http://javaboutique.internet.com/tutorials/rasters/index2.html有一个很好的图表。
实现CPU可访问位图的人希望在处理器字边界上对齐其扫描线,因为访问和操作处理器字的机器代码可能比非对齐地址的机器代码快得多。
答案 3 :(得分:1)
是的,这是必要的。
步幅值是从一条扫描线的起点到下一条扫描线的起点的偏移量。如果扫描线被填充,则该值比扫描线中的像素所需的值多几个字节。
如果位图倒置存储在存储器中(即首先是底部扫描线),则步幅值为负。如果你在不使用步幅值的情况下读取这样的位图,那么在第一条扫描线或内存访问错误之后你就会得到垃圾。
答案 4 :(得分:1)
步幅值是位图用于表示一行像素的字节数。所以你可以通过步幅向前移动一个记忆指针来向下移动