2009-08-30 137 views
2

示例圖像: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. 

我完全迷失在這裏。看起來像某種抵消的問題,我試着大步調整一些,但無濟於事(只是創建奇怪的對角線外觀)。

回答

1

視頻渲染器正在擴展位圖以適應其自己的內存對齊需求,但它將調整媒體類型以匹配。媒體類型中的VIDEOINFOHEADER(或VIDEOINFOHEADER2結構)將具有rcTarget矩形,該矩形定義較大位圖內的有效區域。您可以查詢輸入引腳上的當前媒體類型並獲取該信息。

你會發現渲染器只需要一些格式的擴展步長,所以也許你最簡單的方法是強制採用不同的捕捉格式。另一種方法是使用採樣器過濾器而不是VMR。

+0

有一段時間讓採樣卡工作正常 - 結束了讓事情適當工作(我只使用一個攝像頭,所以輸出是衆所周知的),只需剪掉左側10個像素關閉和移動它在右側。 感謝您的幫助,將此標記爲答案,因爲這就是它! – Matt 2009-09-10 19:30:41

2

該代碼使用由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

0

對於那些誰想要避免使用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

相關問題