2

Summary: I have a collection FrameworkElements (basically web view brushes drawn on rectanlges), and I'd like to save each of these as a PNG file in my UWP app.

More details: I followed the example at https://stackoverflow.com/a/17222629/2884981 to split the content of a WebView into separate "pages".

I've put the main bits of code at the bottom.

At the bottom of GetWebPages() I have return pages; At this point I have a list of all the "pages".

What I'd like to do, is then convert each of those pages into an image (so by the end of it I'd have a collection of PNG files, for instance).

Does anyone know how I can do this? Thanks in advance.

    public async Task<WebViewBrush> GetWebViewBrush(WebView webView)
    {
        // resize width to content
        double originalWidth = webView.Width;
        var widthString = await webView.InvokeScriptAsync("eval", new[] { "document.body.scrollWidth.toString()" });
        int contentWidth;

        if (!int.TryParse(widthString, out contentWidth))
        {
            throw new Exception(string.Format("failure/width:{0}", widthString));
        }

        webView.Width = contentWidth;

        // resize height to content
        double originalHeight = webView.Height;
        var heightString = await webView.InvokeScriptAsync("eval", new[] { "document.body.scrollHeight.toString()" });
        int contentHeight;

        if (!int.TryParse(heightString, out contentHeight))
        {
            throw new Exception(string.Format("failure/height:{0}", heightString));
        }

        webView.Height = contentHeight;

        // create brush
        var originalVisibilty = webView.Visibility;
        webView.Visibility = Windows.UI.Xaml.Visibility.Visible;

        WebViewBrush brush = new WebViewBrush
        {
            SourceName = webView.Name,
            Stretch = Stretch.Uniform
        };

        brush.Redraw();

        // reset, return
        webView.Width = originalWidth;
        webView.Height = originalHeight;
        webView.Visibility = originalVisibilty;

        return brush;
    }

And:

        public async Task<IEnumerable<FrameworkElement>> GetWebPages(WebView webView, Windows.Foundation.Size page)
        {
            // ask the content its width
            var widthString = await webView.InvokeScriptAsync("eval", new[] { "document.body.scrollWidth.toString()" });
            int contentWidth;

            if (!int.TryParse(widthString, out contentWidth))
            {
                throw new Exception(string.Format("failure/width:{0}", widthString));
            }

            webView.Width = contentWidth;

            // ask the content its height
            var heightString = await webView.InvokeScriptAsync("eval", new[] { "document.body.scrollHeight.toString()" });
            int contentHeight;

            if (!int.TryParse(heightString, out contentHeight))
            {
                throw new Exception(string.Format("failure/height:{0}", heightString));
            }

            webView.Height = contentHeight;

            // how many pages will there be?
            double scale = page.Width / contentWidth;
            double scaledHeight = (contentHeight * scale);
            double pageCount = (double) scaledHeight / page.Height;
            pageCount = pageCount + ((pageCount > (int) pageCount) ? 1 : 0);

            // create the pages
            var pages = new List<Windows.UI.Xaml.Shapes.Rectangle>();

            for (int i = 0; i < (int)pageCount; i++)
            {
                var translateY = -page.Height * i;

                var rectanglePage = new Windows.UI.Xaml.Shapes.Rectangle
                {
                    Height = page.Height,
                    Width = page.Width,
                    Margin = new Thickness(5),
                    Tag = new TranslateTransform { Y = translateY },
                };

                rectanglePage.Loaded += (async (s, e) =>
                {
                    var subRectangle = s as Windows.UI.Xaml.Shapes.Rectangle;
                    var subBrush = await GetWebViewBrush(webView);
                    subBrush.Stretch = Stretch.UniformToFill;
                    subBrush.AlignmentY = AlignmentY.Top;
                    subBrush.Transform = subRectangle.Tag as TranslateTransform;
                    subRectangle.Fill = subBrush;
                });

                pages.Add(rectanglePage);
            }

            return pages;
        }
Community
  • 1
  • 1
b85411
  • 9,420
  • 15
  • 65
  • 119

1 Answers1

1

I'd like to save each of these as a PNG file in my UWP app.

You can get all the rectangles and show them in the ItemsControl in the NavigationCompleted event of WebView like this:

private async void webView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{
    MyWebViewRectangle.Fill = await GetWebViewBrush(webView);
    MyPrintPages.ItemsSource = await GetWebPages(webView, new Windows.Foundation.Size(842, 595));
}

Then in a button click event you can save all the items as .png images like this:

private async void Savetoimage_Clicked(object sender, RoutedEventArgs e)
{
    var piclib = Windows.Storage.KnownFolders.PicturesLibrary;
    foreach (var item in MyPrintPages.Items)
    {
        var rect = item as Rectangle;
        RenderTargetBitmap renderbmp = new RenderTargetBitmap();
        await renderbmp.RenderAsync(rect);
        var pixels = await renderbmp.GetPixelsAsync();
        var file = await piclib.CreateFileAsync("webview.png", Windows.Storage.CreationCollisionOption.GenerateUniqueName);
        using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
        {
            BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
            byte[] bytes = pixels.ToArray();
            encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                             BitmapAlphaMode.Ignore,
                             (uint)rect.Width, (uint)rect.Height,
                             0, 0, bytes);
            await encoder.FlushAsync();
        }
    }
}
Grace Feng
  • 16,564
  • 2
  • 22
  • 45