Mark
Mark

Reputation: 863

Saving list of Bitmap Images

I have a list of Bitmap images. I need to save them to local folder. This doesn't work on windows 10 Universal application.

var serializer = new DataContractSerializer(typeof(List<BitmapImage>));
    using (var stream = await ApplicationData.Current.LocalCacheFolder.OpenStreamForWriteAsync(fileName, CreationCollisionOption.ReplaceExisting)) {
            serializer.WriteObject(stream, collection);
        }

WriteObject method throws the following error

Exception thrown: 'System.Runtime.Serialization.InvalidDataContractException' in System.Private.DataContractSerialization.dll

Upvotes: 1

Views: 1525

Answers (2)

Sunteen Wu
Sunteen Wu

Reputation: 10627

You cannot extract the bitmap from a BitmapImage. There is no way to save a BitmapImage to file directly. The only way is to remember the original source and save that out. For more details about save BitmapImage to file please reference this thread.

If you know the original source, for example, you read the BitmapImage from the file picked by a FileOpenPicker, then you can read the image file to a WriteableBitmap then you can extract the PixelBuffer, encode it with a BitmapEncoder, and then save the resulting stream to a StorageFile as Rob said. Sample code as follows:

private async void btncreate_Click(object sender, RoutedEventArgs e)
{
    FileOpenPicker openpicker = new FileOpenPicker();
    openpicker.FileTypeFilter.Add(".jpg");
    openpicker.FileTypeFilter.Add(".png");
    StorageFile originalimage = await openpicker.PickSingleFileAsync();
    WriteableBitmap writeableimage1;
    using (IRandomAccessStream stream = await originalimage.OpenAsync(FileAccessMode.Read))
    {
        SoftwareBitmap softwareBitmap;
        BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
        softwareBitmap = await decoder.GetSoftwareBitmapAsync();
        writeableimage1 = new WriteableBitmap(softwareBitmap.PixelWidth, softwareBitmap.PixelHeight);
        writeableimage1.SetSource(stream);
    }
    StorageFolder folder = ApplicationData.Current.LocalFolder;
    StorageFile newimage = await folder.CreateFileAsync(originalimage.Name, CreationCollisionOption.ReplaceExisting);
    using (IRandomAccessStream ras = await newimage.OpenAsync(FileAccessMode.ReadWrite))
    {
        BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, ras);
        var stream = writeableimage1.PixelBuffer.AsStream();
        byte[] buffer = new byte[stream.Length];
        await stream.ReadAsync(buffer, 0, buffer.Length);
        encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)writeableimage1.PixelWidth, (uint)writeableimage1.PixelHeight, 96.0, 96.0, buffer);
        await encoder.FlushAsync();
    }
}

For list of images, you may need save them one by one.

Upvotes: 0

Matt Spinks
Matt Spinks

Reputation: 6698

BitmapImage is not serializable. Convert that to a byte array and write that to disk instead:

public static byte[] ConvertToBytes(BitmapImage bitmapImage)
{
    using (var ms = new MemoryStream())
    {
        var btmMap = new WriteableBitmap(bitmapImage.PixelWidth, bitmapImage.PixelHeight);
        btmMap.SaveJpeg(ms, bitmapImage.PixelWidth, bitmapImage.PixelHeight, 0, 100);
        return ms.ToArray();
    }
}

var serializer = new DataContractSerializer(typeof(byte[]));
    using (var stream = await ApplicationData.Current.LocalCacheFolder.OpenStreamForWriteAsync(fileName, CreationCollisionOption.ReplaceExisting)) {
        serializer.WriteObject(stream, ConvertToBytes(collection));
    }

Upvotes: 1

Related Questions