Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.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# 为什么WriteableBitmap BackBufferStride与EmguCV Mat步骤不同_C#_Wpf_Emgucv - Fatal编程技术网

C# 为什么WriteableBitmap BackBufferStride与EmguCV Mat步骤不同

C# 为什么WriteableBitmap BackBufferStride与EmguCV Mat步骤不同,c#,wpf,emgucv,C#,Wpf,Emgucv,使用netcoreapp3.1和EmguCV 3.4.1,我一方面创建了一个可写的位图,另一方面创建了一个EmguCV Mat。两者的尺寸相同,为2793 x 2585 var wb = new WriteableBitmap(2793, 2585, 96, 96, PixelFormats.Bgr24, null); int wbStride = wb.BackBufferStride; //8380 var m = new Mat(2585, 2793, DepthType.Cv8U,

使用netcoreapp3.1和EmguCV 3.4.1,我一方面创建了一个可写的位图,另一方面创建了一个EmguCV Mat。两者的尺寸相同,为2793 x 2585

var wb = new WriteableBitmap(2793, 2585, 96, 96, PixelFormats.Bgr24, null);
int wbStride = wb.BackBufferStride; //8380 

var m = new Mat(2585, 2793, DepthType.Cv8U, 3);
int matStride = m.Step; //8379
对于WriteableBitmap BackBufferStride=8380,但对于Mat,我得到了Step=8379。我发现有两种不同的公式经常用于计算步幅:

a)步幅=((宽度*比特像素+31)和~31)>3

b)步幅=(宽度*比特像素+7)/8

公式a)生成我为WriteableBitmap BackBufferStride获取的值,公式b)生成EmguCV Mat的值


为什么相同宽度和高度的步幅不同?哪个公式是正确的?

不确定为什么
BackBufferStride
会返回该值

但是,任何大于或等于最小跨距
(宽度*bpp+7)/8
的值都对位图的跨距有效。只要求跨距足够大,即每个扫描行有足够的字节来容纳所有位

您可以尝试以下代码并添加到stride,例如
stride+=100。只需确保步幅也用于计算像素缓冲区的大小

var width = 2793;
var height = 2585;
var stride = (width * PixelFormats.Bgr24.BitsPerPixel + 7) / 8; // 8379

stride += 100;

var buffer = new byte[stride * height];

for (int y = 0; y < height; y++)
{
    for (int x = y % 10; x < width; x += 10)
    {
        buffer[stride * y + 3 * x + 0] = 0xFF;
        buffer[stride * y + 3 * x + 1] = 0xFF;
        buffer[stride * y + 3 * x + 2] = 0xFF;
    }
}

var bitmap = BitmapSource.Create(
    width, height, 96, 96, PixelFormats.Bgr24, null, buffer, stride);
var宽度=2793;
var高度=2585;
变量步长=(宽度*像素格式.Bgr24.BitsPerPixel+7)/8;//8379
步幅+=100;
var buffer=新字节[步幅*高度];
对于(int y=0;y
Stride是一个底层实现细节,详细说明位图行在内存中的布局方式。跨步与一行像素相关,要求跨步必须足够大以存储整行像素,但可以更大。正如克莱门斯指出的,任意增加步幅是完全有效的;这种差异会导致对齐或填充字节,这是历史上添加的

由于两个公式都满足这一要求,因此都是正确的:第一个公式为每行像素填充内存,使其在32位边界上对齐,而第二个公式将每行对齐到8位边界。但这两种方法都会产生足够大的步幅来容纳整行像素

由于兼容性的原因,32位对齐的跨步可能仍然在.NET领域中使用,特别是关于如何在内存中复制像素行

另一方面,EmguCV的
Mat
完全是另一回事;它是一个通用矩阵,不需要符合.NET使用的任何位图约定。上的文档表明,无填充字节或公式B是默认行为。重载允许您指定自定义步骤,但您确实需要将其指向预定义的缓冲区:

var buffer=Marshal.AllocHGlobal(2585*8380);
var m=新垫(25852793,深度类型.Cv8U,3,缓冲器,8380);
int matStride=m.阶跃//8380
自由全球元帅(缓冲区);