/// <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); }
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); } }