Capturing and saving images from the camera

[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]

Here's how to capture an image from a camera and then save it or share it.

Capturing a photo from a camera

Most new devices running Windows 8 will have at least one built-in camera, possibly two. Here's some C# code to capture the image from the camera, using the default camera user interface control (CameraCaptureUI). This control will ask the user to select a camera (if more than one is present), optionally pick a time-delay and then take a picture.

Note  The CameraCaptureUI control is not available on Windows Phone 8.1 devices. Use the lower-level Windows.Media.Capture API instead: see Quickstart: capturing video by using the MediaCapture api for more information.

 

        async private void CameraCapture()
        {
            // Remember to set permissions in the manifest!

            // using Windows.Media.Capture;
            // using Windows.Storage;
            // using Windows.UI.Xaml.Media.Imaging;

            CameraCaptureUI cameraUI = new CameraCaptureUI();

            cameraUI.PhotoSettings.AllowCropping = false;
            cameraUI.PhotoSettings.MaxResolution = CameraCaptureUIMaxPhotoResolution.MediumXga;

            Windows.Storage.StorageFile capturedMedia =
                await cameraUI.CaptureFileAsync(CameraCaptureUIMode.Photo);

            if (capturedMedia != null)
            {
                using (var streamCamera = await capturedMedia.OpenAsync(FileAccessMode.Read))
                {

                    BitmapImage bitmapCamera = new BitmapImage();
                    bitmapCamera.SetSource(streamCamera);
                    // To display the image in a XAML image object, do this:
                    // myImage.Source = bitmapCamera;

                    // Convert the camera bitap to a WriteableBitmap object, 
                    // which is often a more useful format.

                    int width = bitmapCamera.PixelWidth;
                    int height = bitmapCamera.PixelHeight;

                    WriteableBitmap wBitmap = new WriteableBitmap(width, height);

                    using (var stream = await capturedMedia.OpenAsync(FileAccessMode.Read))
                    {
                        wBitmap.SetSource(stream);
                    }
                }
            }
        }

In this example, the camera is configured to take a small, still photograph and the cropping control is disabled. You can alter the properties of cameraUI.PhotoSettings to change these preferences, and also activate video capture rather than still image capture.

This code captures an image, ready to be displayed using an XAML image object. However, if you wish to process the image further, you will need to convert it into a WritableBitmap object. Once in this format, you can process the image using code as detailed in the topicLoading and processing bitmaps.

Saving the captured image to disk

Once you have captured and (optionally) processed your image, you'll probably want to let the user save it. However, before the image can be saved to disk, you will need to encode it from the raw bitmap state into something more suitable, such as a JPG. Here's some C# code which does just that.

        private async void SaveImageAsJpeg()
        {
            // using Windows.Graphics.Imaging;
            // using Windows.Storage.Pickers;
            // using Windows.Storage.Streams;
            // using System.Runtime.InteropServices.WindowsRuntime; // If you leave this out, AsStream() will not be available

            // Create the File Picker control
            FileSavePicker picker = new FileSavePicker();
            picker.FileTypeChoices.Add("JPG File", new List<string>() { ".jpg" });
            StorageFile file = await picker.PickSaveFileAsync();

            if (file != null)
            {
                // If the file path and name is entered properly, and user has not tapped 'cancel'..

                using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
                {
                    // Encode the image into JPG format,reading for saving
                    BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
                    Stream pixelStream = wBitmap.PixelBuffer.AsStream();
                    byte[] pixels = new byte[pixelStream.Length];
                    await pixelStream.ReadAsync(pixels, 0, pixels.Length);
                    encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)wBitmap.PixelWidth, (uint)wBitmap.PixelHeight, 96.0, 96.0, pixels);
                    await encoder.FlushAsync();
                }
            }
        }

Sharing your image with the share charm

Windows 8 provides the ability to share your image with other apps: see the Charms topic for an overview. There are two steps to this process: first, you must set up the mechanism to respond to the request for sharing, and second you need to encode the image into a format ready to share.

When your app's page initializes, create a DataTransferManager member variable, and then initialize it and create an event handler like this:

        dataTransferManager = DataTransferManager.GetForCurrentView();
        dataTransferManager.DataRequested += new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(this.ShareImageHandler);

This code tells your app to call a method called ShareImageHandler when the user opens the share charm. Here's what that method looks like:

        private async void ShareImageHandler(DataTransferManager sender, DataRequestedEventArgs e)
        {
            // using Windows.ApplicationModel.DataTransfer;

            DataRequest request = e.Request;
            request.Data.Properties.Title = "Share picture";
            request.Data.Properties.Description = "Share a picture from your app";

            // Must use a deferral because we are using async methods 
            // to construct our image.
            DataRequestDeferral deferral = request.GetDeferral();

            try
            {
                using (var stream = new InMemoryRandomAccessStream())
                {
                    var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
                    var pixelStream = wBitmap.PixelBuffer.AsStream();
                    byte[] pixels = new byte[pixelStream.Length];
                    await pixelStream.ReadAsync(pixels, 0, pixels.Length);
                    encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)wBitmap.PixelWidth, (uint)wBitmap.PixelHeight, 96.0, 96.0, pixels);
                    await encoder.FlushAsync();
                    request.Data.SetBitmap(RandomAccessStreamReference.CreateFromStream(stream));
                }
            }
            finally
            {
                deferral.Complete();
            }
        }

This method shares much in common with the method that saves the image, because in both cases the bitmap needs encoded into a more suitable format. However, in the code above we create a PNG file rather than a JPG, just because we can.

Note  Remember that the user can open the share charm at any time, even before you have captured your first image: your code needs to take this into account!

 

CameraCaptureUI Sample

Quickstart: Image and ImageBrush

How to load file resources (Windows Store apps using JavaScript and HTML)

BackgroundTaskDeferral class