WPF - 位图 - 额外的边框?

时间:2017-10-05 18:43:25

标签: c# wpf bitmap

我有一个程序可以通过点击从网络摄像头捕获一个帧。捕获工作正常,我把它保存为位图确定,但我有一个奇怪的问题,位图是偏移的 - 大小是正确的,但它从底部切掉一部分(如图片的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);
    }
}

1 个答案:

答案 0 :(得分:-1)

https://social.msdn.microsoft.com/Forums/vstudio/en-US/984da366-33d3-4fd3-b4bd-4782971785f8/questions-about-rendertargetbitmap?forum=wpf

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);
        }