Directshow&.Net - 位图从图像左侧的右侧显示条纹?
示例图像:Directshow&.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。
摹
该代码使用由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;
}
你能告诉我什么是'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。
有一段时间让采样卡工作正常 - 结束了让事情适当工作(我只使用一个摄像头,所以输出是众所周知的),只需剪掉左侧10个像素关闭和移动它在右侧。 感谢您的帮助,将此标记为答案,因为这就是它! – Matt 2009-09-10 19:30:41