65.9K
CodeProject 正在变化。 阅读更多。
Home

在 Silverlight 3 中将位图保存到隔离存储

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.20/5 (6投票s)

2009年7月31日

CPOL

3分钟阅读

viewsIcon

38076

如何在 Silverlight 3 中将位图保存到隔离存储。

有时您可能希望将位图图像保存到用户的本地存储中。 也许它是在应用程序中使用的生成的图像,或者它是一个外部引用的图像,您正在本地加载它以用于缓存目的。 我在网上找到了很多生成“保存对话框”的示例,但没有一个用于保存它。

这是一个非常简单的应用程序,演示了如何保存图像。这不符合任何行业标准格式 - 它实际上输出了图像的像素大小(高度、宽度),然后流出alpha、红色、绿色和蓝色的字节。它旨在作为更好地理解如何获取图像数据和操作它的基础。一旦您“知道”了像素,就可以轻松地开始应用更高级的算法,如 BMP、PNG、JPG 甚至 GIF 来保存和检索数据。

这是 XAML - 您可以创建一个新的 Silverlight 应用程序,并直接将 XAML 和代码隐藏插入其中以开始使用

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

在 XAML 中,有一个包含三行的网格。第一行是一个带有红色文本的画布。这就是我们将转换为位图图像并保存的内容。第二行是用于我们处理的图像的“占位符”。最后一行是一个简单的文本块来更新状态。

这是代码隐藏文件

public partial class MainPage
{
    private const string SAVEDIMG = "SavedBitmapImage.xyz";
        
    /// <summary>
    ///     Default constructor
    /// </summary>
    public MainPage()
    {
        InitializeComponent();
        CanvasSource.Loaded += _MainPageLoaded;
    }

    /// <summary>
    ///     Canvas loaded
    /// </summary>
    /// <param name="sender">
    /// <param name="e">
    void _MainPageLoaded(object sender, RoutedEventArgs e)
    {
        Status.Text = "Checking disk...";
        byte[] buffer = _LoadIfExists(SAVEDIMG); 

        if (buffer.Length > 0)
        {
            Status.Text = "Loading...";
            BitmapImageRef.Source = _GetImage(buffer);
            Status.Text = "Loaded.";
        }
        else
        {
            Status.Text = "Rendering...";
            WriteableBitmap bitmap = new WriteableBitmap
				(CanvasSource, new TransformGroup());
            BitmapImageRef.Source = bitmap;
            Status.Text = "Saving...";
            _SaveToDisk(_GetSaveBuffer(bitmap), SAVEDIMG);
            Status.Text = "Saved.";
        }                       
    }

    /// <summary>
    ///     Load file, if it exists
    /// </summary>
    /// <param name="fileName">The filename</param>
    /// <returns>The byte array for the file</returns>
    private static byte[] _LoadIfExists(string fileName)
    {
        byte[] retVal;

        using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
        {
            if (iso.FileExists(fileName))
            {
                using (IsolatedStorageFileStream stream = 
				iso.OpenFile(fileName, FileMode.Open))
                {
                    retVal = new byte[stream.Length];
                    stream.Read(retVal, 0, retVal.Length);
                }
            }
            else
            {
                retVal = new byte[0];
            }
        }
        return retVal;
    }

    /// <summary>
    ///     Saves to isolated storage
    /// </summary>
    /// <param name="buffer">The buffer</param>
    /// <param name="fileName"></param>
    private static void _SaveToDisk(byte[] buffer, string fileName)
    {
        using (IsolatedStorageFile iso = 
			IsolatedStorageFile.GetUserStoreForApplication())
        {
            using (
                IsolatedStorageFileStream stream = 
			new IsolatedStorageFileStream(fileName, FileMode.CreateNew,
                           	iso))
            {
                stream.Write(buffer, 0, buffer.Length);
            }
        }
    }

    /// <summary>
    ///     Gets an image from storage
    /// </summary>
    /// <param name="buffer"></param>
    /// <returns>The bitmap</returns>
    private static WriteableBitmap _GetImage(byte[] buffer)
    {
        int width = buffer[0]*256 + buffer[1];
        int height = buffer[2]*256 + buffer[3];

        long matrixSize = width*height;

        WriteableBitmap retVal = new WriteableBitmap(width, height);

        int bufferPos = 4; 

        for (int matrixPos = 0; matrixPos < matrixSize; matrixPos++)
        {
            int pixel = buffer[bufferPos++];
            pixel = pixel << 8 | buffer[bufferPos++];
            pixel = pixel << 8 | buffer[bufferPos++];
            pixel = pixel << 8 | buffer[bufferPos++];
            retVal.Pixels[matrixPos] = pixel;
        }

        return retVal; 
    }

    /// <summary>
    ///     Gets the buffer to save to disk from the writeable bitmap
    /// </summary>
    /// <param name="bitmap">The bitmap image</param>
    /// <returns>The buffer of bytes</returns>
    private static byte[] _GetSaveBuffer(WriteableBitmap bitmap)
    {
        long matrixSize = bitmap.PixelWidth*bitmap.PixelHeight;
        
        long byteSize = matrixSize*4 + 4; 

        byte[] retVal = new byte[byteSize];

        long bufferPos = 0;

        retVal[bufferPos++] = (byte) ((bitmap.PixelWidth / 256) & 0xff);
        retVal[bufferPos++] = (byte) ((bitmap.PixelWidth % 256) & 0xff);
        retVal[bufferPos++] = (byte) ((bitmap.PixelHeight / 256) & 0xff);
        retVal[bufferPos++] = (byte) ((bitmap.PixelHeight % 256) & 0xff);

        for (int matrixPos = 0; matrixPos < matrixSize; matrixPos++)
        {
            retVal[bufferPos++] = (byte)((bitmap.Pixels[matrixPos] >> 24) & 0xff);
            retVal[bufferPos++] = (byte)((bitmap.Pixels[matrixPos] >> 16) & 0xff);
            retVal[bufferPos++] = (byte)((bitmap.Pixels[matrixPos] >> 8) & 0xff);
            retVal[bufferPos++] = (byte)((bitmap.Pixels[matrixPos]) & 0xff);    
        }

        return retVal;
    }
}

主要过程只是等待画布加载。

我们检查图像是否保存在隔离存储中。如果存在,我们渲染它并将其附加到图像。如果不存在,我们基于第一行的画布渲染它,然后保存它。

_LoadIfExists 是一个基本例程,用于检查文件是否存在,如果存在,则将其加载到字节缓冲区中并返回。如果该文件不存在,则返回一个空的字节数组。

_SaveToDisk 接受一个字节数组并将其持久保存到隔离存储中。对此例程的可能增强功能包括检查可用存储是否存在并在需要时提示用户扩展它,以及将文件组织到子目录中并检查/创建它们。

_GetSaveBuffer 接受位图并返回一个字节缓冲区。前两个字节是宽度,后两个是高度,最后剩余的字节包含位图中每个像素的alpha、红色、绿色和蓝色通道。显然,您可以在此处符合任何可用的图形标准并提供您自己的压缩。

_GetImage 获取以前的格式保存的图像的缓冲区,并将其渲染到位图中,以便可以显示它。

这个例子的想法是在调试中运行并逐步查看。 第一次运行它时,它将简单地复制图像(在这种情况下是文本)并显示它,并将其保存到隔离存储中。 任何后续运行都将从存储中加载它并显示它,除非您清除存储或更改文件名。

同样,这只是一个关于在隔离存储中操作和保存位图的基本介绍。

Jeremy Likness

© . All rights reserved.