1

我从相机里得到镜头。像这样:

初始化:

uint pcount = (uint)(capGrabber.Width * capGrabber.Height * PixelFormats.Bgr32.BitsPerPixel / 8);
section = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, 0x04, 0, pcount, null);
map = MapViewOfFile(section, 0xF001F, 0, 0, pcount);
BitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromMemorySection(section, capGrabber.Width, capGrabber.Height, PixelFormats.Bgr32, capGrabber.Width * PixelFormats.Bgr32.BitsPerPixel / 8, 0) as InteropBitmap;
capGrabber.Map = map;

在哪里

IntPtr map;
IntPtr section;
InteropBitmap BitmapSource;

抓斗(capGrabber):

public int BufferCB(double sampleTime, IntPtr pBuffer, int bufferLen)
{
    if (Map != IntPtr.Zero)
    {
        CopyMemory(Map, pBuffer, bufferLen);
        OnNewFrameArrived();
    }

    return 0;            
}

我把图像倒过来(自上而下)。需要解决这个问题。我找到了一些东西(使用结构 BITMAPINFO),但我没有工作。问任何想法。

4

3 回答 3

1

这个问题似乎与Top-Down vs. Bottom-Up DIBs有关。

有些人添加 WPF 转换将位图旋转 180 度,但我发现最简单的解决方案是以相反的顺序复制位图,即替换

CopyMemory(Map, pBuffer, bufferLen);

经过

for(IntPtr pMap = Map, pBuf = pBuffer+bufferLen; pBuf.ToInt64() > pBuffer.ToInt64(); pMap += 4, pBuf -= 4)
    CopyMemory(pMap, pBuf-4, 4);

请注意,数字 4 表示代表一个像素的字节数,即 32 位 (RGB32) 除以 8。

于 2013-03-23T12:07:17.093 回答
1

Petr Gotthard 想到了正确的问题,但代码并没有解决问题。

根据MSDN

在自下而上的 DIB 中,图像缓冲区从底行像素开始,然后是下一行,依此类推。图像的顶行是缓冲区中的最后一行。因此,内存中的第一个字节是图像的左下角像素。在 GDI 中,所有的 DIB 都是自下而上的。下图显示了自下而上 DIB 的物理布局。

这意味着您的图像首先绘制底行,而不是顶行。这会产生垂直镜面效果。但是,它不会左右颠倒。

考虑以下数组:

[ 0, 1, 2 ]
[ 3, 4, 5 ]
[ 6, 7, 8 ]

自上而下将按照说明进行读取和输出。但是自下而上会以这种方式解析它:

[ 6, 7, 8 ]
[ 3, 4, 5 ]
[ 0, 1, 2 ]

如果我们简单地反转它,我们会得到:

[ 2, 1, 0 ]
[ 5, 4, 3 ]
[ 8, 7, 6 ]

所以把它放回去,我们需要步幅(宽度),然后我们逐行反转。

因此,采用 Petr 的答案并增加步伐,我们得到:

int stride = Width * PixelFormats.Bgr32.BitsPerPixel / 8;
for (IntPtr pMap = Map, pBuf = buffer + bufferLen; pBuf.ToInt64() > buffer.ToInt64(); pMap += stride, pBuf -= stride)
    CopyMemory(pMap, pBuf - stride, stride);
于 2014-11-07T20:01:52.923 回答
1
var target = m_Map;
var bytesPerRow = (m_Width * 4);
var source = aBuffer + aLength - bytesPerRow;

for (int i = m_Height - 1; i > 0; i--)
{
    Interop.CopyMemory(target, source, bytesPerRow);
    target += bytesPerRow;
    source -= bytesPerRow;
}

性能更高。原始代码每次迭代需要 224 467 428 个滴答。每行复制只需要 4 041 288 个滴答声

于 2013-10-21T12:29:13.003 回答