public static ImageSource SaveThumbnail(ThumbnailOptions options) { // Make sure this method runs in the UI thread. if (!Deployment.Current.Dispatcher.CheckAccess()) { return(Deployment.Current.Dispatcher.Invoke <ImageSource>(() => { return SaveThumbnail(options); })); } // Gets the images. WriteableBitmap preferedImage = GetBitmapSource(options.PreferedMedia); WriteableBitmap fallbackImage = GetBitmapSource(options.FallbackMedia); // Determines which image needs to be saved. WriteableBitmap targetImage = preferedImage; if (preferedImage == null) { // Use the fallback image if the prefered image does not exist. targetImage = fallbackImage; } else if (fallbackImage != null && options.MinWidth > -1 && preferedImage.PixelWidth < options.MinWidth && preferedImage.PixelWidth < fallbackImage.PixelWidth) { // Use the fallback image if its width is bigger than the prefered image's width, the latter being // smaller than the min width. targetImage = fallbackImage; } // No image? Return. if (targetImage == null) { return(null); } // Gets the dimensions of the target image. int targetWidth = (int)Math.Max(options.MinWidth, targetImage.PixelWidth); double sourcePixelRatio = targetImage.PixelWidth / (double)targetImage.PixelHeight; int targetHeight = (int)Math.Floor(targetWidth / sourcePixelRatio); // Blurs the image if needed. ExtendedImage targetExtendedImage = null; if (options.Blur) { // Converts the image to an ImageTools image. targetExtendedImage = targetImage.ToImage(); // Resizes the image if it can help decreasing the time needed to blur it. // The image is only resized if the target size is less than the original size. // Otherwise it means that the original image is smaller than the target size, in which case we blur it // as it is and let WP scale up the blurred image later. if (targetExtendedImage.PixelHeight * targetExtendedImage.PixelWidth > targetWidth * targetHeight) { targetExtendedImage = ExtendedImage.Resize(targetExtendedImage, targetWidth, targetHeight, new ImageTools.Filtering.NearestNeighborResizer()); } // Inits the blur filter if needed and runs it. if (_gaussianBlurFilter == null) { _gaussianBlurFilter = new ImageTools.Filtering.GaussianBlur() { Variance = 2d }; } targetExtendedImage = ExtendedImage.ApplyFilters(targetExtendedImage, _gaussianBlurFilter); } // Crops the image if needed. if (options.CropRectangle.HasValue) { if (targetExtendedImage == null) { // Converts the image to an ImageTools image. targetExtendedImage = targetImage.ToImage(); } // Computes the downscaled crop rectangle. // We're downscaling the crop rectangle instead of upscaling the image and then cropping it, // in order to save some time. // WP will upscale the cropped image later on. int conformedCropWidth = Math.Min(options.CropRectangle.Value.Width, targetWidth); int conformedCropHeight = Math.Min(options.CropRectangle.Value.Height, targetHeight); double scaleFactor = (double)targetExtendedImage.PixelWidth / (double)targetWidth; Rectangle crop = options.CropRectangle.Value; crop.Width = (int)(conformedCropWidth * scaleFactor); crop.Height = (int)(conformedCropHeight * scaleFactor); crop.X = (int)((double)crop.X * scaleFactor); crop.Y = (int)((double)crop.Y * scaleFactor); // Crops the image. if (crop.Width > 0 && crop.Height > 0) { targetExtendedImage = ExtendedImage.Crop(targetExtendedImage, crop); } // Stores the final dimensions of the image for later scaling. targetWidth = conformedCropWidth; targetHeight = conformedCropHeight; } if (targetExtendedImage != null) { targetImage = targetExtendedImage.ToBitmap(); } // Saves the image. try { if (targetWidth > 0 && targetHeight > 0) { using (IsolatedStorageFileStream stream = options.IsoStoreFile.OpenFile(options.Filename, FileMode.Create, FileAccess.ReadWrite)) { targetImage.SaveJpeg(stream, targetWidth, targetHeight, 0, 100); } } } catch (IsolatedStorageException ex) { // Nothing to do, let's just dump this for further analysis. DebugUtils.DumpException(ex, string.Format("OpenFile(f:{0})", options.Filename), true); } catch (ArgumentException ex) { // Nothing to do, let's just dump this for further analysis. DebugUtils.DumpException(ex, string.Format("SaveJpeg(w:{0},h:{1})", targetWidth, targetHeight), true); } // Returns the image. return(targetImage); }