2009-08-30 13 views
2

サンプル画像:alt textDirectShow&.Net - イメージの左側にあるストライプがビットマップに表示されますか?

私はDirectShow.netを使用して自分のプログラムにウェブカメラ映像を取得しています。 これを達成するために、私はグラフにソースカメラを加え、VideoMixingRenderer9を追加します。

その部分はすごく動き出していますが、GetCurrentImage(out lpDib)を使用してフレームを抽出する部分は、奇妙な問題としてしか記述できません。

私は、Marshal.PtrToSTructureを使ってlpDibからBitmapInfoHeaderを作成し、width/height/stride/&ピクセル形式を計算しています。

ビットマップに保存された画像を見ると問題が発生します。実際には右から来た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の代わりにサンプルグラバーフィルターを使用する方法もあります。

G

+0

サンプルグラバーを正しく動作させるには時間がかかっていました。適切に動作するように巻き上げられました(私は1台のカメラしか使用していないので、出力はよく分かります)。それは右側にあります。 あなたの助けていただきありがとうございます。それはそれが何であるかの理由で、これを回答としてマークします! – Matt

2

このコードはDirectShowLibサンプルを使用して作られており、それが動作します:SampleGrabberを使用しないようにしたい人のために

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

0

。 "ストライプ"問題は、ビットマップヘッダーのオフセットを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です。

関連する問題