Adam Drew
Adam Drew

Reputation: 245

C# / WinRT: How to save image to file

I'm an iOS developer learning Windows Store App development with no previous Microsoft technology experience.

I need to save an image to a file. I figured this would be easy, but I've been at it for a day and I've got nothing to show for it. Either this is extremely difficult in Windows, or I'm missing something due to ignorance of the platform / APIs.

The source of the image I need to save is Windows.UI.Xaml.Media.Imaging.RenderTargetBitmap. RenderTargetBitmap can return an image as either a source for Windows.UI.Xaml.Controls.Image or as a IBuffer.

I can verify that RenderTargetBitmap is rendering the image correctly. However, I have not been able to save the image to a file. I'd hoped that Image would have a Save() method, but it doesn't. So I figured I'd need to use the IBuffer somehow. I got close, I was able to save the buffer to disk, but it was unencoded, so I couldn't open it in anything.

So, next, I tried converting the buffer to a stream, encoding that into PNG with BitmapEncoder. That worked, but that left me with my PNG data in a IRandomAccessStream. I have no idea how to save a IRandomAccessStream to a file.

I tried 5-10 different convoluted approaches, such as going through type conversion hell to attempt to turn a IRandomAccessStream into an IBuffer so I could use .WriteAsync() on a file stream. I tried using a DataWriter on a file stream fed by a DataReader on my IRandomAccessStream but I ran into a type mismatch problem. Etc, etc.

So, how can I save my file? Here's what I got so far:

private async void saveButton_Click(object sender, RoutedEventArgs e)
{

    //Create a new temporary image for saving
    //Image tempImage = new Image();

    //Create a render object
    RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
    //Render the app's display buffer
    await renderTargetBitmap.RenderAsync(null);
    //Set the temp image to the contents of the app's display buffer
    //tempImage.Source = renderTargetBitmap;

    //Create a new file picker, set the default name, and extenstion
    FileSavePicker savePicker = new FileSavePicker();
    savePicker.SuggestedFileName = "New LightTable.png";
    savePicker.FileTypeChoices.Add("Image", new List<string>(){".png"});

    //Get the file the user selected
    StorageFile saveFile = await savePicker.PickSaveFileAsync();

    //Only move on if the user actually selected a file
    if (saveFile != null)
    {
        //Get a buffer of the pixels captured from the screen
        Windows.Storage.Streams.IBuffer buffer = await renderTargetBitmap.GetPixelsAsync();

        //Get a stream of the data in the buffer
        System.IO.Stream stream = buffer.AsStream();

        //Convert the stream into a IRandomAccessStream because I don't know what I'm doing.
        Windows.Storage.Streams.IRandomAccessStream raStream = stream.AsRandomAccessStream();

        //Attempt to encode the stream into a PNG
        BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, raStream);

        //Get a stream for the file the user selected
        Windows.Storage.Streams.IRandomAccessStream fileStream = await saveFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);

        //FIND SOME WAY TO SAVE raStream TO fileStream
        //Something like:
        // await fileStream.WriteAsync(raStream.AsStreamForRead());

    }

}

Either I'm just missing the very end: how to write my raStream to a file, or my approach is totally off.

I appreciate the help. Keep in mind I've only been developing with Microsoft tech for a week now. I have no .NET, Silverlight, or other MS tech experience. Saving an encoded image from a UIImage control on iOS is a single method call, so the shear complexity of the solution I'm circling makes me think I'm missing something really easy that I just don't know about.

Upvotes: 1

Views: 5727

Answers (1)

Heath
Heath

Reputation: 3311

You need to set the pixel data into the StorageFile stream. See http://basquang.wordpress.com/2013/09/26/windows-store-8-1-save-visual-element-to-bitmap-image-file/ for an example.

Upvotes: 3

Related Questions