我有一个程序可以通过点击从网络摄像头捕获一个帧。捕获工作正常,我把它保存为位图确定,但我有一个奇怪的问题,位图是偏移的 - 大小是正确的,但它从底部切掉一部分(如图片的25%)和顶部全黑。
任何想法是什么导致了这个?
流程如下:
public static string TempPicLocation = @"%USERPROFILE%\AppData\Local\temppic.bmp";
private void StartButton_Click(object sender, RoutedEventArgs e)
{
int capturedeviceindex = cboDevices.SelectedIndex;
FilterInfo cd = CaptureDevice[cboDevices.SelectedIndex];
string cdms = cd.MonikerString;
FinalFrame = new VideoCaptureDevice(cdms);
FinalFrame.NewFrame += FinalFrame_NewFrame;
FinalFrame.Start();
}
private void FinalFrame_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
var imageSource = ImageSourceForBitmap(eventArgs.Frame);
imageSource.Freeze();
this.Dispatcher.Invoke(
new Action(
() =>
{
pboLive.Source = imageSource;
return;
}
)
);
}
//If you get 'dllimport unknown'-, then add 'using System.Runtime.InteropServices;'
[DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteObject([In] IntPtr hObject);
public ImageSource ImageSourceForBitmap(Bitmap bmp)
{
var handle = bmp.GetHbitmap();
try
{
return Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
}
finally { DeleteObject(handle); }
}
private void CaptureButton_Click(object sender, RoutedEventArgs e)
{
ImageSource Captured = pboLive.Source;
pboSnap.Source = Captured.Clone();
capturedpictures.Add(pboLive.Source);
var filePath = Environment.ExpandEnvironmentVariables(TempPicLocation);
ImageHandlers.SaveToBmp(pboLive, filePath);
}
internal static void SaveToBmp(FrameworkElement visual, string fileName)
{
var encoder = new BmpBitmapEncoder(); //In System.Windows.Media.Imaging
SaveUsingEncoder(visual, fileName, encoder);
}
internal static void SaveUsingEncoder(FrameworkElement visual, string fileName, BitmapEncoder encoder)
{
//Here the commented part is the right size, but with 5k x 5k is used to check that the entire picture actually is there. And yes, it indeed is.
//RenderTargetBitmap bitmap = new RenderTargetBitmap((int)visual.ActualWidth, (int)visual.ActualHeight, 96, 96, PixelFormats.Pbgra32); //In System.Windows.Media.Imaging
RenderTargetBitmap bitmap = new RenderTargetBitmap(5000, 5000, 96, 96, PixelFormats.Pbgra32); //In System.Windows.Media.Imaging
bitmap.Render(visual);
BitmapFrame frame = BitmapFrame.Create(bitmap); //In System.Windows.Media.Imaging
encoder.Frames.Add(frame);
string filePath = fileName.Replace(Path.GetFileName(fileName), string.Empty);
System.IO.Directory.CreateDirectory(filePath);
using (var stream = File.Create(fileName))
{
encoder.Save(stream);
}
}
答案 0 :(得分:-1)
public static BitmapSource CreateBitmapFromVisual(Visual target, Double dpiX, Double dpiY)
{
if (target == null)
{
return null;
}
Rect bounds = VisualTreeHelper.GetContentBounds(target);
RenderTargetBitmap rtb = new RenderTargetBitmap((Int32)(bounds.Width * dpiX / 96.0),
(Int32)(bounds.Height * dpiY / 96.0),
dpiX,
dpiY,
PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(target);
dc.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
}
rtb.Render(dv);
return rtb;
}
这段代码是由微软的一些人发布的,然后你可以这样做:
using (FileStream outStream = new FileStream(@"C:\mycanvas.png", FileMode.Create))
{
PngBitmapEncoder enc = new PngBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(CreateBitmapFromVisual(myCanvas, 96, 96)));
enc.Save(outStream);
}