Saving Bitmaps to Isolated Storage in Silverlight 3

摘要:Saving Bitmaps to Isolated Storage in Silverlight 3


There may be times when you wish to save a bitmap image to the user‘s local storage. Perhaps it was a generated image that is used in the application, or maybe it is an externally referenced image that you are loading locally for caching purposes. I found many examples online of generating a "save dialog" box, but none for saving it.

This is a very bare bones application that demonstrates how to save the image. This is in no industry-standard format - it literally writes out the size of the image in pixels (height, width), then streams out the bytes for alpha, red, green, and blue. It is meant as a foundation to better understand how to get the image data and manipulate it. Once you "know" the pixels, then you can easily start to apply more advanced algorithms like BMP, PNG, JPG, or even GIF to save and retrieve the data.

Here is the XAML - you can create a new Silverlight Application and literally plop in the XAML and code-behind to get started:

view sourceprint?

01. < UserControl x:Class = "BitmapSaver.MainPage"
02. ???? xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"?
03. ???? xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
04. ???? xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"?
05. ???? mc:Ignorable = "d" d:DesignWidth = "640" d:DesignHeight = "480" >
06. ?? < Grid x:Name = "LayoutRoot" >
07. ???????? < Grid.RowDefinitions >
08. ???????????? < RowDefinition Height = "30" > RowDefinition>
09.????????????<RowDefinition Height="30"> RowDefinition>
10.????????????<RowDefinition> RowDefinition>
11.???????? Grid.RowDefinitions>
12.????????<Canvas HorizontalAlignment="Left" x:Name="CanvasSource" Height="20" Width="100" Grid.Row="0">
13.????????????????<TextBlock FontSize="14" VerticalAlignment="Center" HorizontalAlignment="Center" Width="Auto" Height="Auto" Foreground="Red" FontWeight="Bold" Text="BitMapExample"/>????????????????????????????
14.???????? Canvas>
15.????????<Image HorizontalAlignment="Left" x:Name="BitmapImageRef" Stretch="None" Grid.Row="1"/>
16.????????<TextBlock x:Name="Status" Text="Processing..." Grid.Row="2"/>????????
17.?? Grid>
18. UserControl>


In the XAML, there is a grid with three rows. The first is a canvas with red text inside it. This is what we‘ll turn into a bitmap image and save. The second row is an image "placeholder" for the image that we process. The final row is a simple text block to update the status.

Here is the code-behind:

view sourceprint?

001.public partial class MainPage
002.{
003.????private const string SAVEDIMG = "SavedBitmapImage.xyz";
004.??????????
005.????///

006.????///???? Default constructor
007.????///

008.????public MainPage()
009.????{
010.????????InitializeComponent();
011.????????CanvasSource.Loaded += _MainPageLoaded;
012.????}
013.??
014.????///
015.????///???? Canvas loaded
016.????///

017.????///
018.????///
019.????void _MainPageLoaded(object sender, RoutedEventArgs e)
020.????{
021.????????Status.Text = "Checking disk...";
022.????????byte[] buffer = _LoadIfExists(SAVEDIMG);?
023.??
024.????????if (buffer.Length > 0)
025.????????{
026.????????????Status.Text = "Loading...";
027.????????????BitmapImageRef.Source = _GetImage(buffer);
028.????????????Status.Text = "Loaded.";
029.????????}
030.????????else
031.????????{
032.????????????Status.Text = "Rendering...";
033.????????????WriteableBitmap bitmap = new WriteableBitmap(CanvasSource, new TransformGroup());
034.????????????BitmapImageRef.Source = bitmap;
035.????????????Status.Text = "Saving...";
036.????????????_SaveToDisk(_GetSaveBuffer(bitmap), SAVEDIMG);
037.????????????Status.Text = "Saved.";
038.????????}???????????????????????
039.????}
040.??
041.????///
042.????///???? Load file, if it exists
043.????///

044.????/// The filename
045.????/// The byte array for the file
046.????private static byte[] _LoadIfExists(string fileName)
047.????{
048.????????byte[] retVal;
049.??
050.????????using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
051.????????{
052.????????????if (iso.FileExists(fileName))
053.????????????{
054.????????????????using (IsolatedStorageFileStream stream = iso.OpenFile(fileName, FileMode.Open))
055.????????????????{
056.????????????????????retVal = new byte[stream.Length];
057.????????????????????stream.Read(retVal, 0, retVal.Length);
058.????????????????}
059.????????????}
060.????????????else
061.????????????{
062.????????????????retVal = new byte[0];
063.????????????}
064.????????}
065.????????return retVal;
066.????}
067.??
068.????///
069.????///???? Saves to isolated storage
070.????///

071.????/// The buffer
072.????///
073.????private static void _SaveToDisk(byte[] buffer, string fileName)
074.????{
075.????????using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
076.????????{
077.????????????using (
078.????????????????IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.CreateNew,
079.?????????????????????????????????????????????????????????????????????????????????iso))
080.????????????{
081.????????????????stream.Write(buffer, 0, buffer.Length);
082.????????????}
083.????????}
084.????}
085.??
086.????///
087.????///???? Gets an image from storage
088.????///

089.????///
090.????/// The bitmap
091.????private static WriteableBitmap _GetImage(byte[] buffer)
092.????{
093.????????int width = buffer[0]*256 + buffer[1];
094.????????int height = buffer[2]*256 + buffer[3];
095.??
096.????????long matrixSize = width*height;
097.??
098.????????WriteableBitmap retVal = new WriteableBitmap(width, height);
099.??
100.????????int bufferPos = 4;?
101.??
102.????????for (int matrixPos = 0; matrixPos < matrixSize; matrixPos++)
103.????????{
104.????????????int pixel = buffer[bufferPos++];
105.????????????pixel = pixel << 8 | buffer[bufferPos++];
106.????????????pixel = pixel << 8 | buffer[bufferPos++];
107.????????????pixel = pixel << 8 | buffer[bufferPos++];
108.????????????retVal.Pixels[matrixPos] = pixel;
109.????????}
110.??
111.????????return retVal;?
112.????}
113.??
114.????///
115.????///???? Gets the buffer to save to disk from the writeable bitmap
116.????///

117.????/// The bitmap image
118.????/// The buffer of bytes
119.????private static byte[] _GetSaveBuffer(WriteableBitmap bitmap)
120.????{
121.????????long matrixSize = bitmap.PixelWidth*bitmap.PixelHeight;
122.??????????
123.????????long byteSize = matrixSize*4 + 4;?
124.??
125.????????byte[] retVal = new byte[byteSize];
126.??
127.????????long bufferPos = 0;
128.??
129.????????retVal[bufferPos++] = (byte) ((bitmap.PixelWidth / 256) & 0xff);
130.????????retVal[bufferPos++] = (byte) ((bitmap.PixelWidth % 256) & 0xff);
131.????????retVal[bufferPos++] = (byte) ((bitmap.PixelHeight / 256) & 0xff);
132.????????retVal[bufferPos++] = (byte) ((bitmap.PixelHeight % 256) & 0xff);
133.??
134.????????for (int matrixPos = 0; matrixPos < matrixSize; matrixPos++)
135.????????{
136.????????????retVal[bufferPos++] = (byte)((bitmap.Pixels[matrixPos] >> 24) & 0xff);
137.????????????retVal[bufferPos++] = (byte)((bitmap.Pixels[matrixPos] >> 16) & 0xff);
138.????????????retVal[bufferPos++] = (byte)((bitmap.Pixels[matrixPos] >> 8) & 0xff);
139.????????????retVal[bufferPos++] = (byte)((bitmap.Pixels[matrixPos]) & 0xff);????
140.?