获取和保存照片
???? 有一些處理高分辨率圖片的應用程序會遇到的問題。例如,由于應用程序可以使用使用 PhotoChooserTask 和
MediaLibrary APIs 從圖片庫獲取圖片,用戶可能遭遇意想不到的像內存占用過高甚至用盡了內存。因此,下面為
在應用程序間分享圖片制定了一些規則:
—應用程序應該把高分辨率的照片保存到應用的本地存儲里,低分辨率的圖片保存到圖片庫。
—當應用程序從圖片庫中打開一些圖片時,可以匹配圖片庫中的圖片和本地存儲中的高分辨率照片,比如,根據
照片文件的文件名
—應用程序這么做就必須保證適時的清理應用程序本地存儲,以避免沒用的高分辨率圖片占用磁盤空間。
?
?? 關于保存圖片的低分辨率版本,500萬像素是比較恰當的,既可以在 A3 的紙上進行清晰打印,尺寸又足夠小可以適應
各種分享的場合。
??? 因為你在圖片庫中只保存了低分辨率的圖片,所以強烈建議你為你的應用程序添加富媒體支持。從而讓用戶
方便的到你的應用程序中查看原圖,從而有增加了你的應用程序的使用頻率。
?? 上面描述的規則和富媒體擴展,你的應用都應該支持,例如,示例應用 ?Photo Inspector?和 Nokia Pro Camera 應用程序。
另外,高分辨率的圖片也不能被其他第三方應用程序獲得。
?
? 雙保存之保存到本地存儲和圖片庫
??? 下面的示例演示了你如何保存高分辨率版本圖片到應用的本地存儲,低分辨率的版本保持到
照片庫以供其它應用使用。特別是當照片在 1000+萬 以上的大尺寸時,需要考慮壓縮圖片并且使用雙保存
策略。如果圖片超過了 500-800萬的范圍雙保存通常是有意義的。有些像使用 870萬分辨率的手機拍出的照
片不需要做額外的工作去壓縮圖片。除非你考慮到其它特殊的場合,比如分享到一些社交網絡上。確保圖片
沒有超過 Windows Phone 8 的 4096X 4096 像素最大紋理尺寸是比較合理的,因為這可能導致應用程序出現
意想不到的問題,從而可以適當避免處理這么大分辨率的圖片。
????? 下面的代碼片段演示了縮小圖片到 500萬(保存到圖片庫的推薦尺寸)。注意這里演示的雙保存是依賴
文件的名稱—保持不同分辨率版本的文件使用相同的文件名稱。
using Microsoft.Xna.Framework.Media; using Microsoft.Xna.Framework.Media.PhoneExtensions; using Nokia.Graphics.Imaging; using Windows.Foundation;...public class Utilities {.../// <summary>/// Asynchronously saves a low resolution version of given photo to MediaLibrary. If the photo is too/// large to be saved to MediaLibrary as is, also saves the original high resolution photo to application's/// local storage so that the high resolution version is not lost./// <param name="image">Photo to save</param>/// <returns>Path to the saved file in MediaLibrary</returns>/// </summary>public static async Task<string> SaveAsync(IBuffer image){var savedPath = "";if (image != null && image.Length > 0){uint maxBytes = 2 * 1024 * 1024; // 2 megabytesvar maxPixels = 5 * 1024 * 1024; // 5 megapixelsvar maxSize = new Size(4096, 4096); // Maximum texture size on WP8 is 4096x4096 AutoResizeConfiguration resizeConfiguration = null;using (var editingSession = new EditingSession(image)){if (editingSession.Dimensions.Width * editingSession.Dimensions.Height > maxPixels){var compactedSize = CalculateSize(editingSession.Dimensions, maxSize, maxPixels);resizeConfiguration = new AutoResizeConfiguration(maxBytes, compactedSize,new Size(0, 0), AutoResizeMode.Automatic, 0, ColorSpace.Yuv420);}}var filenameBase = "myphotoapp_" + DateTime.UtcNow.Ticks.ToString();if (resizeConfiguration != null){// Store high resolution original to application local storageusing (var store = IsolatedStorageFile.GetUserStoreForApplication()){var localPath = @"\LocalImages";if (!store.DirectoryExists(localPath )){store.CreateDirectory(localPath );}using (var file = store.CreateFile(localPath + @"\" + filenameBase + @".jpg")){using (var localImage = image.AsStream()){localImage.CopyTo(file);file.Flush();}}}// Compact the image for saving to the library image = await Nokia.Graphics.Imaging.JpegTools.AutoResizeAsync(image, resizeConfiguration);}using (var library = new MediaLibrary()){using (var libraryImage = image.AsStream()){using (var picture = library.SavePictureToCameraRoll(filenameBase, libraryImage)){savedPath = picture.GetPath();}}}}return savedPath;}/// <summary>/// Calculates a new size from originalSize so that the maximum area is maxArea/// and maximum size is maxSize. Aspect ratio is preserved./// </summary>/// <param name="originalSize">Original size</param>/// <param name="maxArea">Maximum area</param>/// <param name="maxSize">Maximum size</param>/// <returns>Area in same aspect ratio fits the limits set in maxArea and maxSize</returns>private static Size CalculateSize(Size originalSize, Size maxSize, double maxArea){// Make sure that the image does not exceed the maximum sizevar width = originalSize.Width;var height = originalSize.Height;if (width > maxSize.Width){var scale = maxSize.Width / width;width = width * scale;height = height * scale;}if (height > maxSize.Height){var scale = maxSize.Height / height;width = width * scale;height = height * scale;}// Make sure that the image does not exceed the maximum areavar originalPixels = width * height;if (originalPixels > maxArea){var scale = Math.Sqrt(maxArea / originalPixels);width = originalSize.Width * scale;height = originalSize.Height * scale;}return new Size(width, height);}... }?
匹配圖片庫里和本地保存的文件
?PhotoChooserTask and MediaLibrary APIs
??? 現在你有兩個分辨率版本的圖片,分別在圖片庫中的分辨率版本和應用本地存儲中的高分辨率原圖,如果在應用中使用
PhotoChooserTask 或者 Medialibrary APIs 打開圖片,下面演示了你如何檢查選擇的圖片,與之匹配的本地高分辨率
是否可用。
using Microsoft.Phone.Tasks;...public partial class PreviewPage : PhoneApplicationPage {private PhotoChooserTask _photoChooserTask = new PhotoChooserTask();...public PreviewPage(){..._photoChooserTask.Completed += PhotoChooserTask_Completed;}...private void PhotoChooserTask_Completed(object sender, PhotoResult e){if (e.TaskResult == TaskResult.OK){if (e.ChosenPhoto.CanRead && e.ChosenPhoto.Length > 0){var localStream = Utilities.LocalPhotoFromLibraryPath(e.OriginalFileName);if (localStream != null){e.ChosenPhoto.Close();localStream.Position = 0;// Note that while we use the high resolution original here, the BitmapImage// will scale it down for display due to the texture size limit. Therefore// using the high resolution photo would only make sense if we would also be// doing something really high resolution dependent with it InitializePreview(localStream);}else{InitializePreview(e.ChosenPhoto);}}}}... } ...public class Utilities {.../// <summary>/// Takes a MediaLibrary photo path and tries to find a local high resolution copy of the same photo./// </summary>/// <param name="libraryPath">Path to a photo in MediaLibrary</param>/// <returns>Stream to a local copy of the same photo</returns>public static Stream LocalPhotoFromLibraryPath(string libraryPath){var localPathCandidate = @"\LocalImages\" + FilenameFromPath(libraryPath);using (var store = IsolatedStorageFile.GetUserStoreForApplication()){if (store.FileExists(localPathCandidate)){return store.OpenFile(localPathCandidate, FileMode.Open);}}return null;}/// <summary>/// Takes a local high resolution photo path and tries to find MediaLibrary copy of the same photo./// </summary>/// <param name="localPath">Path to a locally saved photo</param>/// <returns>Stream to a MediaLibrary copy of the same photo</returns>public static Stream LibraryPhotoFromLocalPath(string localPath){var localFilename = FilenameFromPath(localPath);using (var library = new MediaLibrary()){using (var pictures = library.Pictures){for (int i = 0; i < pictures.Count; i++){using (var picture = pictures[i]){var libraryFilename = FilenameFromPath(picture.GetPath());if (localFilename == libraryFilename){return picture.GetImage();}}}}}return null;}/// <summary>/// Takes a full path to a file and returns the last path component./// </summary>/// <param name="path">Path</param>/// <returns>Last component of the given path</returns>private static string FilenameFromPath(string path){var pathParts = path.Split('\\');return pathParts[pathParts.Length - 1];}... }
?富媒體和照片編輯選擇器擴展
?? 一個很實用的方式就是你的應用和媒體庫建立鏈接,可以參考 ??Rich media extensibility (MSDN) 和 ?Photo edit picker
extensibility (MSDN)?進行集成。從而鼓勵用戶用你的應用程序打開圖片。
??? 通過富媒體擴展,你保存到媒體庫中的圖片會顯示一個鏈接,用來啟動你的應用,當用戶單擊這個鏈接打開你的應用時,
會在導航路徑中同時傳遞一個特殊的 token ,你可以使用相應的 api 利用這個 token 來打開照片。
??? 通過照片編輯選擇器擴展,任何保存在圖片庫中的圖片都可以通過編輯菜單中的編輯選項在你的應用中打開。和富媒體擴展的
方式一樣,你的應用也是通過導航的 URI 中的 token 來獲取相應的圖片。
???? 下面的示例演示你怎樣通過一個照片的 token 匹配到本地保存的高分辨率版本的照片
?
...public class Utilities {.../// <summary>/// Takes a MediaLibrary photo token and tries to find a local high resolution copy of the same photo./// </summary>/// <param name="token">Photo token</param>public static Stream LocalPhotoFromLibraryToken(string token){using (var library = new MediaLibrary()){using (var picture = library.GetPictureFromToken(token)){var libraryPath = picture.GetPath();return LocalPhotoFromLibraryPath(libraryPath );}}}... }
從圖片庫中獲取圖片的縮略圖
???? 如果你的應用程序使用的雙保存,意味著你保存在本地的圖片在圖片庫中還有相應的副本,你可以很輕松的從
圖片庫獲取相應的縮略圖,而不需要自己在應用程序中另外保存副本。
??? 下面的代碼演示了如何從圖片庫中獲取你本地保存圖片的縮略圖。
using Microsoft.Xna.Framework.Media.PhoneExtensions;...public class Utilities {...public struct Photo{public string Filename = null;public Stream Thumbnail = null;}/// <summary>/// Attempts to get a thumbnail for given photo filenames from MediaLibrary./// </summary>/// <param name="localFilenames">Photo filenames</param>/// <returns>List of photo items for which a thumbnail was found</returns>private static List<Photo> GetLibraryThumbnails(List<string> localFilenames){var photos = new List<Photo>();using (var library = new MediaLibrary()){using (var pictures = library.Pictures){foreach (var localFilename in localFilenames){for (int i = 0; i < pictures.Count; i++){using (var picture = pictures[i]){var libraryPath = picture.GetPath();var libraryFilename = FilenameFromPath(libraryPath);if (localFilename == libraryFilename){var thumbnail = picture.GetThumbnail();var photo = new Photo(){Filename = localFilename,Thumbnail = thumbnail};photos.Add(photo);break;}}}}}}return photos;}... }
保持應用的本地存儲整潔
??? 第三個關于保存和加載照片需要注意的就是應用的本地存儲避免保存不需要的照片。
??? 下面的方法演示了通過遍歷本地保存的圖片并且檢查媒體庫中是否還有相應的副本,
如果沒有,則刪除本地的文件。
using Microsoft.Xna.Framework.Media.PhoneExtensions;...public class Utilities {.../// <summary>/// Goes through all the locally saved photos and tries to find a match for them in the MediaLibrary./// If a match is not found (photo has been deleted from the MediaLibrary) this routine deletes/// also the locally saved photo./// </summary>public void CleanLocalPhotos(){using (var store = IsolatedStorageFile.GetUserStoreForApplication()){var localPath = @"\LocalImages";if (store.DirectoryExists(localPath )){var array = store.GetFileNames(localPath + @"\*");using (var library = new MediaLibrary()){using (var pictures = library.Pictures){foreach (var localFilename in array){var found = false;for (int i = 0; i < pictures.Count && !found; i++){using (var picture = pictures[i]){var libraryFilename = FilenameFromPath(picture.GetPath());if (localFilename == libraryFilename){found = true;}}}if (!found){store.DeleteFile(localPath + @"\" + localFilename);}}}}}}}... }?
Nokia Wiki 原文鏈接:http://developer.nokia.com/Resources/Library/Lumia/#!imaging/working-with-high-resolution-photos/accessing-and-saving-photos.html
轉載于:https://www.cnblogs.com/hebeiDGL/p/3316994.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
- 上一篇: ios7 uuid的获取方法
- 下一篇: UVALive 6044(双连通分量的应