温故而知心之操作图片(一)

在Windows Phone 中我们经常会对图片进行操作 例如 加载图片 存储图片到独立存储 从独立存储中读取图片 把图片存储到图片库 今天我顺手就谢了一个类 封装了一些常用的 处理图片操作的方法

 

首先 我们可能在我们的应用中有一张图片是要在网上下载的 但是每次在打开应用之后下载图片不仅加载慢 而且对用户来说是非常浪费流量的 大家也知道 天朝的手机上网流量是这么的“便宜”,所以我们完全可以在独立存储中创建一个图片的缓存文件夹 当每次应用程序在加载的时候先去搜索缓存文件中是否有需要的图片,如果有就直接加载 如果没有再从网上下载。 废话不多说看我是怎样实现的:

先看一下此类中要引用的命名空间:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;
using System.IO;
using System.IO.IsolatedStorage;
using System.Diagnostics;
using Microsoft.Xna.Framework.Media;

下面是创建“缓存”文件的方法:

public sealed class PictureHandle : BitmapSource
    {
        private readonly string filePath;
        private readonly Uri picUri;
        private const string cacheDirectory = "cacheDirecory";

        /// <summary>
        /// 静态构造函数 在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数来初始化类 且只执行一次
        /// </summary>
        static PictureHandle()
        {
            using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (!isf.DirectoryExists(cacheDirectory))
                {
                    isf.CreateDirectory(cacheDirectory);
                }
            }
        }

        public PictureHandle(Uri picUri)
        {
            this.picUri = picUri;
            filePath = System.IO.Path.Combine(cacheDirectory, picUri.AbsolutePath.TrimStart('/').Replace('/', '_'));
            GetPicSource();
        }

        /// <summary>
        /// 获取图片资源
        /// </summary>
        private void GetPicSource()
        {
            bool exist;
            using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
            {
                exist = isf.FileExists(filePath);
            }
            if (exist)
            {
                SetCacheSource();
            }
            else
            {
                SetWebSource();
            }
        }

        /// <summary>
        /// 异步下载图片
        /// </summary>
        private void SetWebSource()
        {
            HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(picUri);
            httpRequest.AllowReadStreamBuffering = true;
            httpRequest.BeginGetResponse(CallBack, httpRequest);

        }

        /// <summary>
        /// 回调
        /// </summary>
        /// <param name="result">异步操作状态对象</param>
        void CallBack(IAsyncResult result)
        {
            HttpWebRequest httpRequest = result.AsyncState as HttpWebRequest;
            if (httpRequest == null)
            {
                return;
            }
            try
            {
                HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.EndGetResponse(result);

                using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (Stream stream = httpResponse.GetResponseStream())
                    {
                        using (IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(filePath, FileMode.Create, isf))
                        {
                            stream.CopyTo(isfs);
                        }
                    }
                }
                Dispatcher.BeginInvoke(SetCacheSource);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// 设置本地缓存流
        /// </summary>
        void SetCacheSource()
        {
            using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (Stream stream = isf.OpenFile(filePath, FileMode.Open, FileAccess.Read))
                {
                    SetSource(stream);
                }
            }
        }

下面封装的两个方法中第一个是把文件 不管是以内容还是以资源方式存储在安装包 还是在网上下载的图片 只要能找到包含此图片的流就可以将其存储到独立存储

第二个是把图片在独立存储中读取出来 将其以一个BitmapImage的实例返回(其实返回一个流会更通用一些)

/// <summary>
        /// 把图片存储到独立存储 利用返回值可以提示用户保存是否成功
        /// </summary>
        /// <param name="stream">包含图片资源的流</param>
        /// <param name="directoryName">路径名</param>
        /// <param name="fileName">文件名</param>
        /// <returns></returns>
        public static bool SavePicToIso(Stream stream, string directoryName, string fileName)
        {
            if (stream == null)
            {
                return false;
            }
            string path;
            if (directoryName == null || fileName == null)
            {
                path = DateTime.Now.ToString("yyyy-mm-dd_hh:mm:ss");
            }
            else
            {
                path = System.IO.Path.Combine(directoryName, fileName);
            }
            using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(path, FileMode.Create, isf))
                {
                    stream.CopyTo(isfs);
                }
            }
            return true;
        }

        /// <summary>
        /// 从独立存储空间中读取图片
        /// </summary>
        /// <param name="directoryName">路径名</param>
        /// <param name="fileName">文件名</param>
        /// <returns></returns>
        public static BitmapImage ReadPicFromIso(string directoryName, string fileName)
        {
            if (directoryName == null || fileName == null)
            {
                return null;
            }
            else
            {
                BitmapImage bmp = new BitmapImage();
                string path = System.IO.Path.Combine(directoryName, fileName);
                using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    if (!isf.FileExists(path))
                    {
                        return null;
                    }
                    using (IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(path, FileMode.Open, isf))
                    {
                        bmp.SetSource(isfs);
                        return bmp;
                    }
                }
            }
        }

下面的方法是将图片存储到手机的图片库 需要注意的是要引入XNA的类库 用到MediaLibrary这个类 还有就是在存储之前我现根据图片的文件头 可以判断出图片的格式 如果是jpg格式就可以直接存储 如果是其它格式 要先进行图片转换

 

 /// <summary>
        /// 将图片保存到图片库
        /// </summary>
        /// <param name="stream">包含图片的流</param>
        /// <param name="flleName">文件名</param>
        public static bool SavePicToLibrary(Stream stream, string fileName)
        {
            if (stream == null)
            {
                return false;
            }
            if (fileName==null)
            {
                fileName = DateTime.Now.ToString("yyyy-mm-dd_hh:mm:ss");
            }
            //存储到图片库 需要引用XNA类库Microsoft.Xna.Framework 并添加引用 using Microsoft.Xna.Framework.Media;
            MediaLibrary media = new MediaLibrary();
            //因为图片库默认只能存储jpg格式的图片 所以在存储之前可以利用文件头判断是否为jpg 如果不是 则先进行转换
            //  1.Png图片文件包括8字节:89 50 4E 47 0D 0A 1A 0A。即为 .PNG....。 
            //2.Jpg图片文件包括2字节:FF D8。
            //3.Gif图片文件包括6字节:47 49 46 38 39|37 61 。即为 GIF89(7)a。
            //4.Bmp图片文件包括2字节:42 4D。即为 BM。

            byte[] head = new byte[2];//这里只判断j是否为jpg格式 所以获取前两个字节就可以 
            stream.Read(head, 0, head.Length);
            if (head[0] == 0xFF && head[1] == 0xD8)
            {
                //说明是jpg格式
                stream.Position = 0;
                media.SavePicture(fileName, stream);
                return true;
            }
            else
            {    //对图片进行转换
                using (Stream memoryStream = new MemoryStream())
                {
                    BitmapImage bmp = new BitmapImage();
                    bmp.SetSource(stream);
                    WriteableBitmap wbp = new WriteableBitmap(bmp);
                    wbp.Invalidate();
                    //try
                    //{
                    Extensions.SaveJpeg(wbp, memoryStream, wbp.PixelWidth, wbp.PixelHeight, 0, 100);
                    memoryStream.Position = 0;
                    media.SavePicture(fileName, memoryStream);
                        return true;
                    //}
                    //catch (Exception ex )
                    //{
                    //    Debug.WriteLine(ex.Message);
                    //    return false;
                    //}                  
               }              
            }
        }
  

今天先复习这么多 明天的话会复习一些其他的关于图片操作的知识点 欢迎大家指正代码中的错误或者是您有什么优化意见可以指教指教小弟

 

posted on 2012-05-04 01:58  MessageDream  阅读(499)  评论(0)    收藏  举报

导航