micky
micky

Reputation: 45

Trying To take Screenshot in uwp programatically on tapping of an image

trying to capture screenshot on uwp But some issue is arising,saying

1) writable map doesn't contain a definition for Render.

2) writable map doesn't contain a definition for Save.jpeg

3)Type or namespace media library doesn't found. any type of help would be appreciated. Code

private void Download(object sender, TappedRoutedEventArgs e)
        {
            // Create a WriteableBitmap with height and width same as that of Layoutroot
            WriteableBitmap bmp = new WriteableBitmap(480, 696);

            //Render the layoutroot element on it
            bmp.Render(Scrshot, null);
            bmp.Invalidate();


            //Save the image to Medialibrary

            //create a stream of image
            var ms = new MemoryStream();
            bmp.SaveJpeg(ms, 480, 696, 0, 100);
            ms.Seek(0, SeekOrigin.Begin);


            //every path must be unique
            var filePath = "myfile" + DateTime.Now.ToString();

            //Remember to include Medialib capabilty from WMAppManifest.xml for acessing the Medialibrary
            var lib = new MediaLibrary();
            lib.SavePicture(filePath, ms);

            MessageBox.Show("Saved in your media library!", "Done", MessageBoxButton.OK);
        }

Upvotes: 0

Views: 573

Answers (1)

DevAttendant
DevAttendant

Reputation: 636

Instead of WriteableBitmap use RenderTargetBitmap to create a bitmap representation of a visible UIElement. To save this bitmap as a file you can use this extension method I've created (here's a great example for extension methods):

public static class RenderTargetBitmapExtensions {
    public static async Task<StorageFile> ToFile(this RenderTargetBitmap renderTargetBitmap, string filename, StorageFolder folder = null, bool overrideExisting = true) {
        if (folder == null) folder = ApplicationData.Current.TemporaryFolder;

        try {
            byte[] pixels = (await renderTargetBitmap.GetPixelsAsync()).ToArray();

            StorageFile outputFile = await folder.CreateFileAsync(filename, overrideExisting ? CreationCollisionOption.ReplaceExisting : CreationCollisionOption.GenerateUnique);
            var bitmapEncodingMode = BitmapEncoder.PngEncoderId;

            using (var writeStream = await outputFile.OpenAsync(FileAccessMode.ReadWrite)) {
                var encoder = await BitmapEncoder.CreateAsync(bitmapEncodingMode, writeStream);
                encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint)renderTargetBitmap.PixelWidth, (uint)renderTargetBitmap.PixelHeight, 96, 96, pixels);
                await encoder.FlushAsync();
            }
            return outputFile;
        } catch {
            return null;
        }
    }
}

And finally to get the public Images folder (as MediaLibrary is a Silverlight class and does not exist in UWP anymore) you can do the following according to this thread:

StorageFolder picturesLibrary = KnownFolders.PicturesLibrary;
StorageFolder savedPicturesFolder = await picturesLibrary.CreateFolderAsync("Saved Pictures", CreationCollisionOption.OpenIfExists);

Note: By default, apps do not have access to the Pictures Library. You must add the capability in Package.appxmanifest. Open Package.appxmanifest and click on the Capabilities tab. There is a checkbox for the Pictures Library.

So a whole code to do this should be:

RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(LayoutRoot, Convert.ToInt32(LayoutRoot.ActualWidth), Convert.ToInt32(LayoutRoot.ActualHeight));

StorageFolder savedPicturesFolder = await KnownFolders.PicturesLibrary.CreateFolderAsync("Saved Pictures", CreationCollisionOption.OpenIfExists);

await renderTargetBitmap.ToFile("filename.jpg", savedPicturesFolder);

Or if you don't want to override existing files, the last line would be:

await renderTargetBitmap.ToFile("filename.jpg", savedPicturesFolder, false);

For that you can alternatively create a time-based filename:

string filename = String.Format("downloaded_{0}.jpg", DateTime.Now.ToString("yyyyMMdd_HHmmss"));
await renderTargetBitmap.ToFile(filename, savedPicturesFolder, false);

Upvotes: 1

Related Questions