locked
Save Image file to Local Storage

    Question

  • Hi,

    I have a Bitmap Image(.jpg or .png) and I want to store it in a local app data store( as bytes ). I found a example here (http://bit.ly/1DPlXbt ) that explains how to save file as byte array, But I am struggling to convert Bitmap Image to bytes array. I cannot find any sample codes from Microsoft to do this.

    Any help?

    (I am targeting Windows Phone 8.1 Universal App)



    • Edited by MohanRajK Wednesday, December 17, 2014 8:05 PM
    Wednesday, December 17, 2014 7:40 PM

All replies

  • The bitmap class has a save method which takes a stream. Use that.

    WinSDK Support Team Blog: http://blogs.msdn.com/b/winsdk/

    Wednesday, December 17, 2014 7:42 PM
  • The bitmap class has a save method which takes a stream. Use that.

    WinSDK Support Team Blog: http://blogs.msdn.com/b/winsdk/

    In Windows store SDK, bitmap class don't have save method to write a stream. Please understand the question before you answer. Here is the BitmapImage class for Windows Store API.
    Wednesday, December 17, 2014 7:47 PM
  • Hi Mohan,

    Can you elaborate on your specific scenario? Where is the bitmap in question coming from? Do you have an image file itself? A URL returning a bitmap? An image loaded in your app?

    For the first two it'd be better to copy or download the file directly rather than to put it into an Image control and then extract it. That will avoid decoding and encoding the image an extra time.

    If you need to manipulate the image then there are several ways to load it.

    If you don't need to display it but just need to load and manipulate the pixels then you can use a BitmapDecoder to read the image from a file and decode it to get the pixel data. See How to decode an image

    If you want to display it then you can use a WriteableBitmap instead of a BitmapImage. These are both BitmapSources and can be used identically in most cases, but the WriteableBitmap also allows access to the image's PixelBuffer. There isn't any good way to access the BitmapImage's pixels: you have to either get them back from the source file (if you can) or re-render with RenderTargetBitmap.

    Either way, once you have the pixel buffer you can use a BitmapEncoder to encode the file back to a png or jpg and then stream that buffer to disk as shown in the quickstart you linked. See How to encode an image

    Wednesday, December 17, 2014 9:02 PM
    Owner
  • Hi Mohan,

    look at this sample :

    https://code.msdn.microsoft.com/How-to-Import-a-set-of-409ed7a2

    and this answer :

    https://social.msdn.microsoft.com/Forums/windowsapps/en-US/7b281eb0-8bcc-442c-8aa0-b06847488a6b/set-background-using-file-picker?forum=winappswithcsharp#7cf34bb9-cdf9-46bb-a953-b225f62bee35

    Regards

    Torsten

    Thursday, December 18, 2014 4:46 PM
  • Hi Rob,

         I have bitmap image got from storage file and I know how to copy the file to local storage. But I want to know how to write the file using the bytes array since its much easy in WP Silverlight application. This is what I've tried. Please help me in finishing this code.
            public static async void writeImageToFile(String fileName, BitmapImage bitmap, String fileType)
            {
                WriteableBitmap wmp = new WriteableBitmap(bitmap.PixelWidth, bitmap.PixelHeight); //Is this correct?
                StorageFile file = await storageFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
                System.Guid encoderId;
                switch (fileType)
                {
                    case ".jpg":
                    case ".jpeg":
                        encoderId = BitmapEncoder.JpegEncoderId;
                        break;
                    case ".png":
                        encoderId = BitmapEncoder.PngEncoderId;
                        break;
                }
                using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
                {
                    stream.Size = 0;
                    var encoder = await BitmapEncoder.CreateAsync(encoderId, stream);
                    encoder.SetPixelData(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Straight, (uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight, 96, 96, wmp.PixelBuffer.ToArray()); 
    //Compilation error. Cannot convert pixelbuffer(IBuffer) to array since it doesn't have method, and And need explanation for this line(set pixel data()) please.
    
                }
    
            }



    • Edited by MohanRajK Thursday, December 18, 2014 5:22 PM
    Thursday, December 18, 2014 5:21 PM
  •      

    using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
    {
            BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
            encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, 300, 342, 96, 96, pixelData);
            await encoder.FlushAsync();
            await stream.FlushAsync();
    }

    Thursday, December 18, 2014 8:51 PM
  • Torsten, please stop confusing the issue. Your posts aren't particularly relevant to the problem. Your code snippet just restates the problem, it doesn't help explain how to get the pixel data.

    Mohan, what exactly do you mean by writing a file from a bytes array? Why do you want to do this? Where is this bytes array coming from? How are you loading the file?

    It is not possible to extract the pixels directly from a BitmapImage (you sort of can via RenderTargetBitmap, but it's not quite the same thing). If you need to extract the pixels from a bitmap source then you need to use a WriteableBitmap instead of a BitmapImage.

    The ToArray() error is because ToArray() is an extension method in System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions. To use it you need to add "using System.Runtime.InteropServices.WindowsRuntime" to your file.

    The bigger issue with your code is that the WriteableBitmap doesn't have any data in it. You need to load the image into it before you you can extract it. Again: how and when to do this is very scenario dependent so we need to know what you are doing in order to provide good advice.

    Thursday, December 18, 2014 9:43 PM
    Owner
  • The source of the bitmap image is came from contact.Thumbnail.OpenReadAsync() method. I managed to save the file as stream but the problem is when I try to retrieve the local file stream and set the source to bitmapimage. The line await bitmapImage.SetSourceAsync(fileStream);  gives me the exception "The component cannot be found. (Exception from HRESULT: 0x88982F50)". These are the methods I'm using it for storing and retrieving the image file.

        public async Task<BitmapImage> RetrieveImageFromFile(String fileName)
        {
            try
            {
                StorageFile localFile = await _storageFolder.GetFileAsync(fileName + "Img");
                BitmapImage bitmapImage = new BitmapImage();
                using (IRandomAccessStream fileStream = await localFile.OpenAsync(FileAccessMode.Read))
                {
                    await bitmapImage.SetSourceAsync(fileStream);
                }
                return bitmapImage;
            }
            catch(Exception e)
            {
                return null;
            }
        }

        public async void WriteImageToFile(string fileName, IRandomAccessStreamWithContentType stream )
        {
            StorageFile file = await _storageFolder.CreateFileAsync(fileName + "Img", CreationCollisionOption.ReplaceExisting);
            Stream streamToSave = stream.AsStreamForWrite();
            using (Stream fileStram = await file.OpenStreamForWriteAsync())
            {
                streamToSave.CopyTo(fileStram);
            }
        }



    • Edited by MohanRajK Sunday, May 17, 2015 12:45 PM
    Sunday, May 17, 2015 12:43 PM