Exemple #1
0
        /// <summary>
        /// Save the image used to represent the climb in thumbnails and on the main page. Also saves the image to the climbs media stream
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="stream"></param>
        /// <param name="cropOptions"></param>
        /// <returns></returns>
        public Media SaveClimbAvatar(Climb obj, Stream stream, ImageCropOpts cropOptions)
        {
            ObjectModMeta meta = null;

            //-- We don't need to set ModProfile on thread, or retrieve object mod-meta for indoor climbs
            if (obj.Type == CfType.ClimbOutdoor)
            {
                meta = SaveClimbAvatarAuthorization(obj, stream, cropOptions);
            }

            var original = obj.GetSimpleTypeClimbClone();

            //-- Also save the image to the climbs's media real
            //-- If the climb is indoor we don't save indoor climb avatar as
            var media = new MediaService().CreateImageMedia(new Media()
            {
                FeedVisible = (obj.Type != CfType.ClimbIndoor),
                Title       = "Climbing pic of " + obj.Name, ContentType = "image/jpg"
            }, obj.ID, stream);

            SaveAvatar240Thumb(stream, obj.Avatar, obj.NameUrlPart, ImageManager.ClimbPath,
                               fileName => { obj.Avatar = fileName; climbRepo.Update(obj); }, cropOptions, media.Content);

            //-- We don't want to save mod trail if it's indoor (the setters working, kinda boring!)
            if (obj.Type == CfType.ClimbOutdoor)
            {
                //-- No change occurs to the mods profile because the image has to be verified by other users
                SaveModActionAndUpdateModProfile(ModActionType.ClimbSetAvatar, original, obj, meta,
                                                 (m, actionID) => m.SetAvatarChanged(actionID), null, "set climb img {0}", obj.Name);
            }

            return(media);
        }
        /// <summary>
        /// Saves the climbing image (used as the avatar/map image)
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="stream"></param>
        /// <param name="cropOpts"></param>
        /// <returns></returns>
        //public string SaveLocationIndoorAvatar(LocationIndoor obj, Stream stream, ImageCropOpts cropOpts)
        //{
        //    throw new NotImplementedException("SaveLocationIndoorAvatar");
        //    //var meta = SaveLocationIndoorAvatarAuthorization(obj, stream, cropOpts);
        //    //var original = obj.GetSimpleTypeClone();

        //    ////-- Also save the image to the location's media real
        //    //var media = new MediaService().CreateImageMedia(new Media() { Title = "Climbing pic of " + obj.Name, ContentType = "image/jpg" }, obj.ID, stream);

        //    //var newImgUrl = SaveAvatar240Thumb(stream, obj.Avatar, obj.NameUrlPart, ImageManager.ClimbingIndoorPath,
        //    //    fileName => { obj.Avatar = fileName; locIndoorRepo.Update(obj); }, cropOpts, media.Content);

        //    ////-- No change occurs to the mod's profile because the image has to be verified by other users
        //    //SaveModActionAndUpdateModProfile(ModActionType.LocationIndoorSetAvatar, original, obj, meta,
        //    //    (m, actionID) => m.SetAvatarChanged(actionID), null, "set map img {0}", obj.Name);

        //    //return newImgUrl;
        //}

        public Media SaveLocationAvatar(Location obj, Stream stream, ImageCropOpts cropOpts)
        {
            var locTypePath = ImageManager.ClimbingIndoorPath;
            var actionType  = ModActionType.LocationIndoorSetAvatar;

            if (obj.Type.ToPlaceCateogry() == PlaceCategory.OutdoorClimbing)
            {
                locTypePath = ImageManager.ClimbingOutdoorPath;
                actionType  = ModActionType.LocationOutdoorSetAvatar;
            }

            var meta     = SaveLocationAvatarAuthorization(obj, stream, cropOpts);
            var original = obj.GetSimpleTypeClone();

            //-- Also save the image to the location's media real
            var media = new MediaService().CreateImageMedia(new Media()
            {
                FeedVisible = true, Title = "Climbing pic of " + obj.Name, ContentType = "image/jpg"
            }, obj.ID, stream);

            SaveAvatar240Thumb(stream, obj.Avatar, obj.NameUrlPart, locTypePath,
                               fileName => { obj.Avatar = fileName; locRepo.UpdateLocationAvatar(obj.ID, fileName); }, cropOpts, media.Content);

            //-- No change occurs to the mod's profile because the image has to be verified by other users
            SaveModActionAndUpdateModProfile(actionType, original, obj, meta,
                                             (m, actionID) => m.SetAvatarChanged(actionID), null, "set map img {0}", obj.Name);

            return(media);
        }
Exemple #3
0
        public string SaveMediaAsClimbAvatar(Climb obj, Media media, ImageCropOpts cropOptions)
        {
            if (obj == null || media == null || media.Type != MediaType.Image)
            {
                throw new ArgumentException("SaveMediaAsClimbAvatar invalid arguments");
            }
            if (media.ObjectMedias.Where(om => om.OnOjectID == obj.ID).Count() == 0)
            {
                throw new ArgumentException("Media does not belong to climb");
            }

            var    mediaImageUrl = string.Format("{0}/media/{1}", Stgs.ImgsRt, media.Content);
            string newImgUrl     = string.Empty;

            using (Stream stream = new ImageDownloader().DownloadImageAsStream(mediaImageUrl))
            {
                var   meta     = SaveClimbAvatarAuthorization(obj, stream, cropOptions);
                Climb original = obj.GetSimpleTypeClimbClone();

                newImgUrl = SaveAvatar240Thumb(stream, obj.Avatar, obj.NameUrlPart, ImageManager.ClimbPath,
                                               fileName => { obj.Avatar = fileName; climbRepo.Update(obj); }, cropOptions, Path.GetFileName(media.ThumbUrl()));

                //-- No change occurs to the mods profile because the image has to be verified by other users
                SaveModActionAndUpdateModProfile(ModActionType.ClimbSetAvatar, original, obj, meta,
                                                 (m, actionID) => m.SetAvatarChanged(actionID), null, "set climb img {0}", obj.Name);
            }

            return(newImgUrl);
        }
        ObjectModMeta SaveLocationAvatarAuthorization(Location obj, Stream stream, ImageCropOpts cropOpts)
        {
            var meta = SetModDetailsOnPrincipalAndStopModIfNegativeReputationAndReturnObjectModMeta(obj);

            if (meta.VerifiedAvatar > 1 && !currentUser.IsInRole("ModAdmin,ModSenior"))
            {
                throw new AccessViolationException("SaveLocationIndoorClimbingImage: Only Senior Moderators can change images that have already been verified by other users");
            }

            return meta;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="originalImageUrl"></param>
        /// <param name="cropOptions"></param>
        /// <returns></returns>
        public ObjectModMeta SaveClimbAvatarAuthorization(Climb obj, Stream stream, ImageCropOpts cropOptions)
        {
            var meta = SetModDetailsOnPrincipalAndStopModIfNegativeReputationAndReturnObjectModMeta(obj);

            if (meta.VerifiedAvatar > 1 && !currentUser.IsInRole("ModAdmin,ModSenior"))
            {
                throw new AccessViolationException("SaveAreaProfileImage: Only Senior Moderators can change avatar images that have already been verified by other users");
            }

            return(meta);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="destFilePath"></param>
        /// <param name="destFileName"></param>
        /// <param name="cropOptions"></param>
        /// <param name="resizeOptions"></param>
        /// <param name="compressOptions"></param>
        public void ProcessAndSaveImageFromStream(Stream stream, string destFilePath, string destFileName, 
            ImageCropOpts cropOptions, ImageResizeOpts resizeOptions, ImageCrompressOpts compressOptions, ImageCropOpts maxDimensionsAftersize)
        {
            stream.Seek(0, SeekOrigin.Begin);

            using (var image = Image.FromStream(stream))
            {
                //-- Set the processed image to the original image incase we don't apply any cropping or resizing we'll save the image as is.
                Image processedImg = image;
                if (cropOptions != null) { processedImg = ImageCropper.Crop(processedImg, cropOptions); }
                if (resizeOptions != null) { processedImg = ImageResizer.ResizeImage(processedImg, resizeOptions); }

                //-- Clip the width or height if it's still too large after resized
                if (maxDimensionsAftersize != null)
                {
                    if ((maxDimensionsAftersize.W != 0) && (processedImg.Width > maxDimensionsAftersize.W)) {
                        var widthCropOptions = new ImageCropOpts(0, 0, maxDimensionsAftersize.W, processedImg.Height);
                        processedImg = ImageCropper.Crop(processedImg, widthCropOptions);
                    }
                    if ((maxDimensionsAftersize.H != 0) && (processedImg.Height > maxDimensionsAftersize.H)) {
                        var heightCropOptions = new ImageCropOpts(0, 0, processedImg.Width, maxDimensionsAftersize.H);
                        processedImg = ImageCropper.Crop(processedImg, heightCropOptions);
                    }
                }

                //-- TODO: think about putting in a max dimensions crop, where if an image is resized by exact width or height, we clip
                //-- the corresponding height or width
                //if (maxDimensionsAftersize != null) { }

                using (var compressedImgStream = ImageCompressor.CompressImage(processedImg, compressOptions))
                {
                    //-- If there's been no cropping or resizing & the original image size is small enough
                    //-- then we're going to save the original stream to avoid image quality degradation
                    if (processedImg.Height == image.Height && processedImg.Width == processedImg.Width)
                    {
                        bool originalImageSizeUnderThreshold = (stream.Length < compressOptions.OriginalByteLengthThreshold);

                        //-- If it's under the threshold then we just use the original image would compounding the compression
                        if (originalImageSizeUnderThreshold)
                        {
                            stream.CopyTo(compressedImgStream); //http://stackoverflow.com/questions/230128/best-way-to-copy-between-two-stream-instances-c-sharp
                            stream.Position = compressedImgStream.Position = 0;

                            ImagePersister.SaveImage(compressedImgStream, destFilePath, destFileName);
                            return;
                        }
                    }

                    ImagePersister.SaveImage(compressedImgStream, destFilePath, destFileName);
                }
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="originalImageUrl"></param>
        /// <param name="cropOpts"></param>
        /// <returns></returns>
        /// <remarks>Overload was added for creating/migrating cf3 accounts while the user isn't yet on the thread</remarks>
        public string SaveProfileAvatarPic(Stream imgStream, ImageCropOpts cropOpts)
        {
            var user = profileRepo.GetByID(CfIdentity.UserID);

            //-- Save (4) different version of our avatar (2) inside of personality media
            string fileName = SavePersonalityMediaImage(user.ID, imgStream, user.DisplayName + " Avatar", PersonalityCategory.Avatar, cropOpts);

            imgManager.ProcessAndSaveImageFromStream(imgStream, ImageManager.UserMainPic240Path, fileName, null, ImageResizeOpts.ObjectAvatar240, new ImageCrompressOpts(90, ImageConstants.Kb50), new ImageCropOpts(0, 0, 0, 320));
            imgManager.SaveThumb40x40_HighCompressed(imgStream, ImageManager.UserMainPicTmPath, fileName, cropOpts);

            user.Avatar = fileName;
            profileRepo.Update(user);

            return(user.Avatar);
        }
        /// <summary>
        /// Save the logo for an indoor climbing gym
        /// </summary>
        public string SaveLocationIndoorLogo(LocationIndoor obj, Stream stream, ImageCropOpts cropOpts)
        {
            var meta     = SaveLocationIndoorLogoAuthorization(obj, stream, cropOpts);
            var original = obj.GetSimpleTypeClone();

            var newImgUrl = SaveAvatar240Thumb(stream, obj.Logo, obj.NameUrlPart, ImageManager.LogoIndoorPath,
                                               fileName => { obj.Logo = fileName; locIndoorRepo.Update(obj); }, cropOpts);

            //-- No change occurs to the mods profile because the image has to be verified by other users
            SaveModActionAndUpdateModProfile(ModActionType.LocationIndoorSetLogo, original, obj, meta,
                                             null, // don't really have an action FK on the objModMeta just for the logo, so don't update it
                                             null, "set indoor logo {0}", obj.Name);

            //-- If we don't yet have an avatar/climbing image, let's use the logo for the avatar/map scroll over image
            //if (String.IsNullOrWhiteSpace(obj.ImageFileMap)) { SaveLocationIndoorAvatar(obj,  stream, cropOpts); }

            return(newImgUrl);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="originalImageUrl"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="w"></param>
        /// <param name="h"></param>
        /// <returns></returns>
        public string SaveAreaAvatar(Area obj, Stream stream, ImageCropOpts cropOpts)
        {
            var meta     = SaveAreaAvatarAuthorization(obj, stream, cropOpts);
            var original = obj.GetCloneWithGeo();

            //-- Also save the image to the location's media real
            var media = new MediaService().CreateImageMedia(new Media()
            {
                FeedVisible = true, Title = "Climbing pic of " + obj.Name, ContentType = "image/jpg"
            }, obj.ID, stream);

            var newImgUrl = SaveAvatar240Thumb(stream, obj.Avatar, obj.NameUrlPart, ImageManager.ClimbinAreaPath,
                                               fileName => { obj.Avatar = fileName; areaRepo.Update(obj); }, cropOpts, media.Content);

            //-- No change occurs to the mod's profile because the image has to be verified by other users
            SaveModActionAndUpdateModProfile(ModActionType.AreaSetAvatar, original, obj, meta,
                                             (m, actionID) => m.SetAvatarChanged(actionID), null, "set map img {0}", obj.Name);

            return(newImgUrl);
        }
        private string SaveAvatar240Thumb(Stream stream, string oldImageName, string objectNameUrlPart,
                                          string destPath, Action <string> objectDBupdateAction, ImageCropOpts cropOpts, string newFilename)
        {
            stream.Seek(0, SeekOrigin.Begin);

            imgManager.ProcessAndSaveImageFromStream(stream, destPath, newFilename,
                                                     cropOpts,
                                                     ImageResizeOpts.ObjectAvatar240,
                                                     ImageCrompressOpts.Avatar240Image,
                                                     new ImageCropOpts(0, 0, 0, 300)); //-- After resize if it's too high, chop the bottom

            //-- Update the object in the database
            objectDBupdateAction(newFilename);

            return(string.Format(@"{0}{1}{2}", Stgs.ImgsRt, destPath, newFilename));
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="oldImageName"></param>
        /// <param name="objectNameUrlPart"></param>
        /// <param name="destPath"></param>
        /// <param name="objectDBupdateAction"></param>
        /// <returns></returns>
        private string SaveAvatar240Thumb(Stream stream, string oldImageName, string objectNameUrlPart,
                                          string destPath, Action <string> objectDBupdateAction, ImageCropOpts cropOpts)
        {
            //-- TODO revise naming convention
            string fileName = string.Format("{0}-{1:MMddhhmmss}.jpg", objectNameUrlPart.Substring(0, 3), DateTime.Now);

            return(SaveAvatar240Thumb(stream, oldImageName, objectNameUrlPart,
                                      destPath, objectDBupdateAction, cropOpts, fileName));
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="imgStream"></param>
        /// <returns></returns>
        public string SavePersonalityMediaImage(Guid userID, Stream imgStream, string name, PersonalityCategory category, ImageCropOpts cropOpts)
        {
            var media = new Media()
            {
                FeedVisible = true, Title = name, ContentType = "image/jpg"
            };

            new MediaService().CreateImageMedia(media, userID, imgStream);

            new UserPersonalityMediaRepository().Create(
                new UserPersonalityMedia()
            {
                ID = Guid.NewGuid(), CategoryID = (byte)category, MediaID = media.ID, UserID = userID
            });

            return(media.Content);
        }
        /// <summary>
        /// Save the logo for an indoor climbing gym
        /// </summary>
        public string SaveLocationIndoorLogo(LocationIndoor obj, Stream stream, ImageCropOpts cropOpts)
        {
            var meta = SaveLocationIndoorLogoAuthorization(obj, stream, cropOpts);
            var original = obj.GetSimpleTypeClone();

            var newImgUrl = SaveAvatar240Thumb(stream, obj.Logo, obj.NameUrlPart, ImageManager.LogoIndoorPath,
                fileName => { obj.Logo = fileName; locIndoorRepo.Update(obj); }, cropOpts);

            //-- No change occurs to the mods profile because the image has to be verified by other users
            SaveModActionAndUpdateModProfile(ModActionType.LocationIndoorSetLogo, original, obj, meta,
                    null, // don't really have an action FK on the objModMeta just for the logo, so don't update it
                    null, "set indoor logo {0}", obj.Name);

            //-- If we don't yet have an avatar/climbing image, let's use the logo for the avatar/map scroll over image
            //if (String.IsNullOrWhiteSpace(obj.ImageFileMap)) { SaveLocationIndoorAvatar(obj,  stream, cropOpts); }

            return newImgUrl;
        }
        /// <summary>
        /// Saves the climbing image (used as the avatar/map image)
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="stream"></param>
        /// <param name="cropOpts"></param>
        /// <returns></returns>
        //public string SaveLocationIndoorAvatar(LocationIndoor obj, Stream stream, ImageCropOpts cropOpts)
        //{
        //    throw new NotImplementedException("SaveLocationIndoorAvatar");
        //    //var meta = SaveLocationIndoorAvatarAuthorization(obj, stream, cropOpts);
        //    //var original = obj.GetSimpleTypeClone();
        //    ////-- Also save the image to the location's media real
        //    //var media = new MediaService().CreateImageMedia(new Media() { Title = "Climbing pic of " + obj.Name, ContentType = "image/jpg" }, obj.ID, stream);
        //    //var newImgUrl = SaveAvatar240Thumb(stream, obj.Avatar, obj.NameUrlPart, ImageManager.ClimbingIndoorPath,
        //    //    fileName => { obj.Avatar = fileName; locIndoorRepo.Update(obj); }, cropOpts, media.Content);
        //    ////-- No change occurs to the mod's profile because the image has to be verified by other users
        //    //SaveModActionAndUpdateModProfile(ModActionType.LocationIndoorSetAvatar, original, obj, meta,
        //    //    (m, actionID) => m.SetAvatarChanged(actionID), null, "set map img {0}", obj.Name);
        //    //return newImgUrl;
        //}
        public Media SaveLocationAvatar(Location obj, Stream stream, ImageCropOpts cropOpts)
        {
            var locTypePath = ImageManager.ClimbingIndoorPath;
            var actionType = ModActionType.LocationIndoorSetAvatar;

            if (obj.Type.ToPlaceCateogry() == PlaceCategory.OutdoorClimbing) {
                locTypePath = ImageManager.ClimbingOutdoorPath;
                actionType = ModActionType.LocationOutdoorSetAvatar;
            }

            var meta = SaveLocationAvatarAuthorization(obj, stream, cropOpts);
            var original = obj.GetSimpleTypeClone();

            //-- Also save the image to the location's media real
            var media = new MediaService().CreateImageMedia(new Media() { FeedVisible = true, Title = "Climbing pic of " + obj.Name, ContentType = "image/jpg" }, obj.ID, stream);

            SaveAvatar240Thumb(stream, obj.Avatar, obj.NameUrlPart, locTypePath,
                fileName => { obj.Avatar = fileName; locRepo.UpdateLocationAvatar(obj.ID, fileName); }, cropOpts, media.Content);

            //-- No change occurs to the mod's profile because the image has to be verified by other users
            SaveModActionAndUpdateModProfile(actionType, original, obj, meta,
                (m, actionID) => m.SetAvatarChanged(actionID), null, "set map img {0}", obj.Name);

            return media;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="originalImageUrl"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="w"></param>
        /// <param name="h"></param>
        /// <returns></returns>
        public string SaveAreaAvatar(Area obj, Stream stream, ImageCropOpts cropOpts)
        {
            var meta = SaveAreaAvatarAuthorization(obj, stream, cropOpts);
            var original = obj.GetCloneWithGeo();

            //-- Also save the image to the location's media real
            var media = new MediaService().CreateImageMedia(new Media() { FeedVisible = true, Title = "Climbing pic of " + obj.Name, ContentType = "image/jpg" }, obj.ID, stream);

            var newImgUrl = SaveAvatar240Thumb(stream, obj.Avatar, obj.NameUrlPart, ImageManager.ClimbinAreaPath,
                fileName => { obj.Avatar = fileName; areaRepo.Update(obj); }, cropOpts, media.Content);

            //-- No change occurs to the mod's profile because the image has to be verified by other users
            SaveModActionAndUpdateModProfile(ModActionType.AreaSetAvatar, original, obj, meta,
                (m, actionID) => m.SetAvatarChanged(actionID), null, "set map img {0}", obj.Name);

            return newImgUrl;
        }
        ObjectModMeta SaveLocationIndoorLogoAuthorization(LocationIndoor obj, Stream stream, ImageCropOpts cropOpts)
        {
            var meta = SetModDetailsOnPrincipalAndStopModIfNegativeReputationAndReturnObjectModMeta(obj);

            if (meta.VerifiedDetails > 1 && !currentUser.IsInRole("ModAdmin,ModSenior"))
            {
                throw new AccessViolationException("SaveLocationIndoorLogoImage: Only Senior Moderators can change images that have already been verified by other users");
            }

            return(meta);
        }
        /// <summary>
        /// Save a thumbnail of an image with x/y dimensions specified by thumbW & thumbH
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="destFilePath"></param>
        /// <param name="destFileName"></param>
        /// <param name="thumbW"></param>
        /// <param name="thumbH"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="compressOptions"></param>
        private void SaveThumbImageWithResizeThenCrop(Stream stream, string destFilePath, string destFileName, int thumbW, int thumbH,
            ImageCropOpts cropOpts, ImageCrompressOpts compressOptions)
        {
            var thumbPixelBuffer = 0;
            ImageResizeOpts resizeOpts = new ImageResizeOpts() { Mode = ResizeMode.ShrinkOnly, Height = thumbW + thumbPixelBuffer, Width = thumbH + thumbPixelBuffer };

            stream.Seek(0, SeekOrigin.Begin);
            using (var image = Image.FromStream(stream))
            {
                //-- Set the processed image to the original image incase we don't apply any cropping or resizing we'll save the image as is.
                Image processedImg = image;

                //-- Do the initial crop
                if (cropOpts != null) { processedImg = ImageCropper.Crop(image, cropOpts); }

                //-- If our cropped image dimensions are bigger than the Thumb buffer dimensions
                if (processedImg.Width > resizeOpts.Width && processedImg.Height > resizeOpts.Height)
                {
                    processedImg = ImageResizer.ResizeImage(processedImg, resizeOpts);
                }

                //-- In case the image width is smaller than the desired thumb width, we enlarge it
                if (processedImg.Width < thumbW)
                {
                    //-- If the image is smaller we first enlarge the image based of width, if the height is still to small we enlarge it again
                    var enlargeWidthOptions = new ImageResizeOpts() { Mode = ResizeMode.ExactWidth, Height = 0, Width = thumbH };

                    //-- First try the width
                    processedImg = ImageResizer.ResizeImage(processedImg, enlargeWidthOptions);
                }

                //-- In case the image height is smaller than the desired Thumb height, we enlarge it
                if (processedImg.Height < thumbH)
                {
                    ImageResizeOpts enlargeHeightOptions = new ImageResizeOpts() { Mode = ResizeMode.ExactHeight, Height = thumbW, Width = 0 };
                    processedImg = ImageResizer.ResizeImage(processedImg, enlargeHeightOptions);
                }

                //-- If needed, crop the width to be exact
                if (processedImg.Width > thumbW)
                {
                    var widthCropOptions = new ImageCropOpts(0, 0, thumbW, processedImg.Height);
                    processedImg = ImageCropper.Crop(processedImg, widthCropOptions);
                }

                //-- If needed, crop the height to be exact
                if (processedImg.Height > thumbH)
                {
                    var heightCropOptions = new ImageCropOpts(0, 0, processedImg.Width, thumbH);
                    processedImg = ImageCropper.Crop(processedImg, heightCropOptions);
                }

                //-- Save the thumb compressed heavily
                using (var compressedImage = ImageCompressor.CompressImage(processedImg, compressOptions))
                {
                    ImagePersister.SaveImage(compressedImage, destFilePath, destFileName);
                }
            }
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="stream"></param>
 /// <param name="destFilePath"></param>
 /// <param name="destFileName"></param>
 /// <param name="x"></param>
 /// <param name="y"></param>
 /// <remarks>
 /// Used for profile Avatar thumbs
 /// </remarks>
 public void SaveThumb40x40_HighCompressed(Stream stream, string destFilePath, string destFileName, ImageCropOpts cropOpts)
 {
     var compressOptions = new ImageCrompressOpts(90, ImageConstants.Kb05);
     SaveThumbImageWithResizeThenCrop(stream, destFilePath, destFileName, 40, 40, cropOpts, compressOptions);
 }
 /// <summary>
 /// Take an existing image somewhere on the internet and save it using the destination path/name, crop and resize options.
 /// </summary>
 /// <param name="originalImgUrl"></param>
 /// <param name="destFilePath"></param>
 /// <param name="destFileName"></param>
 /// <param name="cropOptions"></param>
 /// <param name="resizeOptions"></param>
 /// <remarks>
 /// This method is useful when saving images from "web" (external sites). It is also useful during the upload / cropping process
 /// </remarks>
 public void ProcessAndSaveImageFromWebUrl(string originalImgUrl, string destFilePath, string destFileName, 
     ImageCropOpts cropOptions, ImageResizeOpts resizeOptions, ImageCrompressOpts compressOptions)
 {
     using (Stream imageStream = new ImageDownloader().DownloadImageAsStream(originalImgUrl))
     {
         ProcessAndSaveImageFromStream(imageStream, destFilePath, destFileName, cropOptions, resizeOptions, compressOptions, null);
     }
 }