Directshow&.Net - 位图从图像左侧的右侧显示条纹?

问题描述:

示例图像:alt textDirectshow&.Net - 位图从图像左侧的右侧显示条纹?

我正在使用DirectShow.net将网络摄像头素材导入到我的程序中。 为了实现这一点,我将源摄像头添加到图形中,并添加VideoMixingRenderer9。

这个部分全部都在流畅地运行,但是我使用GetCurrentImage(out lpDib)提取帧的部分只能说明我是一个奇怪的问题。

我正在做的是使用Marshal.PtrToSTructure从lpDib创建一个BitmapInfoHeader,然后计算宽度/高度/跨度/ &像素格式。

问题来了,当我看着位图中存储的图像 - 它有一个10px宽的线左下方来自实际上是正确的!

值得注意的是,我从GetCurrentImage调用获得的数据实际上是颠倒的 - 请注意对Cap.RotateFlip的调用。

IntPtr lpDib; 
windowlessCtrl.GetCurrentImage(out lpDib); 

BitmapInfoHeader head; 
head = (BitmapInfoHeader)Marshal.PtrToStructure(lpDib, typeof(BitmapInfoHeader)); 
int width = head.Width; 
int height = head.Height; 
int stride = width * (head.BitCount/8); 
PixelFormat pixelFormat = PixelFormat.Format24bppRgb; 

switch (head.BitCount) 
{ 
    case 24: pixelFormat = PixelFormat.Format24bppRgb; break; 
    case 32: pixelFormat = PixelFormat.Format32bppRgb; break; 
    case 48: pixelFormat = PixelFormat.Format48bppRgb; break; 
    default: throw new Exception("Unknown BitCount"); 
} 

Cap = new Bitmap(width, height, stride, pixelFormat, lpDib); 
Cap.RotateFlip(RotateFlipType.RotateNoneFlipY); 
//if we examine Cap here (Cap.Save, for example) I'm seeing the odd stripe. 

我完全迷失在这里。看起来像某种抵消的问题,我试着大步调整一些,但无济于事(只是创建奇怪的对角线外观)。

视频渲染器正在扩展位图以适应其自己的内存对齐需求,但它将调整媒体类型以匹配。媒体类型中的VIDEOINFOHEADER(或VIDEOINFOHEADER2结构)将具有rcTarget矩形,该矩形定义较大位图内的有效区域。您可以查询输入引脚上的当前媒体类型并获取该信息。

你会发现渲染器只需要一些格式的扩展步长,所以也许你最简单的方法是强制采用不同的捕捉格式。另一种方法是使用采样器过滤器而不是VMR。

+0

有一段时间让采样卡工作正常 - 结束了让事情适当工作(我只使用一个摄像头,所以输出是众所周知的),只需剪掉左侧10个像素关闭和移动它在右侧。 感谢您的帮助,将此标记为答案,因为这就是它! – Matt 2009-09-10 19:30:41

该代码使用由DirectShowLib样本,它的工作原理:

public Bitmap GetCurrentImage() 
     { 
      Bitmap bmp = null; 
      if (windowlessCtrl != null) 
      { 
       IntPtr currentImage = IntPtr.Zero; 

       try 
       { 
        int hr = windowlessCtrl.GetCurrentImage(out currentImage); 
        DsError.ThrowExceptionForHR(hr); 

        if (currentImage != IntPtr.Zero) 
        { 
         BitmapInfoHeader structure = new BitmapInfoHeader(); 
         Marshal.PtrToStructure(currentImage, structure); 

         PixelFormat pixelFormat = PixelFormat.Format24bppRgb; 
         switch (structure.BitCount) 
         { 
          case 24: 
           pixelFormat = PixelFormat.Format24bppRgb; 
           break; 
          case 32: 
           pixelFormat = PixelFormat.Format32bppRgb; 
           break; 
          case 48: 
           pixelFormat = PixelFormat.Format48bppRgb; 
           break; 
          default: 
           throw new Exception("BitCount desconhecido"); 
         } 

         // este trecho: new IntPtr(currentImage.ToInt64() + 40), é o que resolve o problema da faixa (strip) da direita na esquerda. 
         bmp = new Bitmap(structure.Width, structure.Height, (structure.BitCount/8) * structure.Width, pixelFormat, new IntPtr(currentImage.ToInt64() + 40)); 
         bmp.RotateFlip(RotateFlipType.RotateNoneFlipY); 
        } 
       } 
       catch (Exception anyException) 
       { 
        MessageBox.Show("Falha gravando imagem da Webcam: " + anyException.ToString()); 
       } 
       finally 
       { 
        Marshal.FreeCoTaskMem(currentImage); 
       } 
      } 
      return bmp; 
     } 
+0

你能告诉我什么是'windowlessCtrl'。 – Gopichandar 2015-03-05 10:13:45

对于那些谁想要避免使用SampleGrabber。 “条带”问题可以通过将位图头的偏移量添加到IntPtr来解决。然而这需要不安全的代码

IntPtr pBuffer = IntPtr.Zero; 
    int xBufferSize = 0; 
    int xWidth, xHeight; 

    basicVideo.get_VideoWidth(out xWidth); 
    basicVideo.get_VideoHeight(out xHeight); 

    int hr = basicVideo.GetCurrentImage(ref xBufferSize, IntPtr.Zero); 
    pBuffer = Marshal.AllocCoTaskMem(xBufferSize); 

    // Get the pixel buffer for the thumbnail 
    hr = basicVideo.GetCurrentImage(ref xBufferSize, pBuffer); 

    // Offset for BitmapHeader info 
    var bitmapHeader = (BitmapInfoHeader)Marshal.PtrToStructure(pBuffer, typeof(BitmapInfoHeader)); 
    var pBitmapData = (byte*)pBuffer.ToPointer(); 
    pBitmapData += bitmapHeader.Size; 

    // This will be the pointer to the bitmap pixels 
    var bitmapData = new IntPtr(pBitmapData); 

    //Change for your format type! 
    System.Drawing.Imaging.PixelFormat xFormat = (System.Drawing.Imaging.PixelFormat.Format32bppRgb); 

    int bitsPerPixel = ((int)xFormat & 0xff00) >> 8; 
    int bytesPerPixel = (bitsPerPixel + 7)/8; 
    int stride = 4 * ((xWidth * bytesPerPixel + 3)/4); 

    Bitmap image = new Bitmap(xWidth, xHeight, stride, xFormat, bitmapData); 
    image.RotateFlip(RotateFlipType.RotateNoneFlipY); 
    return image; 

计算步幅可以找到here