获取和保存照片
???? 有一些處理高分辨率圖片的應(yīng)用程序會遇到的問題。例如,由于應(yīng)用程序可以使用使用 PhotoChooserTask 和
MediaLibrary APIs 從圖片庫獲取圖片,用戶可能遭遇意想不到的像內(nèi)存占用過高甚至用盡了內(nèi)存。因此,下面為
在應(yīng)用程序間分享圖片制定了一些規(guī)則:
—應(yīng)用程序應(yīng)該把高分辨率的照片保存到應(yīng)用的本地存儲里,低分辨率的圖片保存到圖片庫。
—當(dāng)應(yīng)用程序從圖片庫中打開一些圖片時,可以匹配圖片庫中的圖片和本地存儲中的高分辨率照片,比如,根據(jù)
照片文件的文件名
—應(yīng)用程序這么做就必須保證適時的清理應(yīng)用程序本地存儲,以避免沒用的高分辨率圖片占用磁盤空間。
?
?? 關(guān)于保存圖片的低分辨率版本,500萬像素是比較恰當(dāng)?shù)?#xff0c;既可以在 A3 的紙上進(jìn)行清晰打印,尺寸又足夠小可以適應(yīng)
各種分享的場合。
??? 因為你在圖片庫中只保存了低分辨率的圖片,所以強(qiáng)烈建議你為你的應(yīng)用程序添加富媒體支持。從而讓用戶
方便的到你的應(yīng)用程序中查看原圖,從而有增加了你的應(yīng)用程序的使用頻率。
?? 上面描述的規(guī)則和富媒體擴(kuò)展,你的應(yīng)用都應(yīng)該支持,例如,示例應(yīng)用 ?Photo Inspector?和 Nokia Pro Camera 應(yīng)用程序。
另外,高分辨率的圖片也不能被其他第三方應(yīng)用程序獲得。
?
? 雙保存之保存到本地存儲和圖片庫
??? 下面的示例演示了你如何保存高分辨率版本圖片到應(yīng)用的本地存儲,低分辨率的版本保持到
照片庫以供其它應(yīng)用使用。特別是當(dāng)照片在 1000+萬 以上的大尺寸時,需要考慮壓縮圖片并且使用雙保存
策略。如果圖片超過了 500-800萬的范圍雙保存通常是有意義的。有些像使用 870萬分辨率的手機(jī)拍出的照
片不需要做額外的工作去壓縮圖片。除非你考慮到其它特殊的場合,比如分享到一些社交網(wǎng)絡(luò)上。確保圖片
沒有超過 Windows Phone 8 的 4096X 4096 像素最大紋理尺寸是比較合理的,因為這可能導(dǎo)致應(yīng)用程序出現(xiàn)
意想不到的問題,從而可以適當(dāng)避免處理這么大分辨率的圖片。
????? 下面的代碼片段演示了縮小圖片到 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
??? 現(xiàn)在你有兩個分辨率版本的圖片,分別在圖片庫中的分辨率版本和應(yīng)用本地存儲中的高分辨率原圖,如果在應(yīng)用中使用
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];}... }
?富媒體和照片編輯選擇器擴(kuò)展
?? 一個很實用的方式就是你的應(yīng)用和媒體庫建立鏈接,可以參考 ??Rich media extensibility (MSDN) 和 ?Photo edit picker 
extensibility (MSDN)?進(jìn)行集成。從而鼓勵用戶用你的應(yīng)用程序打開圖片。
??? 通過富媒體擴(kuò)展,你保存到媒體庫中的圖片會顯示一個鏈接,用來啟動你的應(yīng)用,當(dāng)用戶單擊這個鏈接打開你的應(yīng)用時,
會在導(dǎo)航路徑中同時傳遞一個特殊的 token ,你可以使用相應(yīng)的 api 利用這個 token 來打開照片。
??? 通過照片編輯選擇器擴(kuò)展,任何保存在圖片庫中的圖片都可以通過編輯菜單中的編輯選項在你的應(yīng)用中打開。和富媒體擴(kuò)展的
方式一樣,你的應(yīng)用也是通過導(dǎo)航的 URI 中的 token 來獲取相應(yīng)的圖片。
???? 下面的示例演示你怎樣通過一個照片的 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 );}}}... }
從圖片庫中獲取圖片的縮略圖
???? 如果你的應(yīng)用程序使用的雙保存,意味著你保存在本地的圖片在圖片庫中還有相應(yīng)的副本,你可以很輕松的從
圖片庫獲取相應(yīng)的縮略圖,而不需要自己在應(yīng)用程序中另外保存副本。
??? 下面的代碼演示了如何從圖片庫中獲取你本地保存圖片的縮略圖。
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;}... }
保持應(yīng)用的本地存儲整潔
??? 第三個關(guān)于保存和加載照片需要注意的就是應(yīng)用的本地存儲避免保存不需要的照片。
??? 下面的方法演示了通過遍歷本地保存的圖片并且檢查媒體庫中是否還有相應(yīng)的副本,
如果沒有,則刪除本地的文件。
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
轉(zhuǎn)載于:https://www.cnblogs.com/hebeiDGL/p/3316994.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
 
                            
                        - 上一篇: ios7 uuid的获取方法
- 下一篇: 《王者荣耀》520亚瑟新皮肤太过250:
