private string CreateCacheFileName(IImageResizeSettings settings, IImageAssetRenderable asset) { const string format = "w{0}h{1}c{2}s{3}bg{4}a{5}"; string s = string.Format(format, settings.Width, settings.Height, settings.Mode, settings.Scale, settings.BackgroundColor, settings.Anchor); s = WebUtility.UrlEncode(s); return(Path.ChangeExtension(s, asset.FileExtension)); }
/// <summary> /// Gets the url for an image asset, with optional resizing parameters /// </summary> /// <param name="asset">asset to get the url for</param> /// <param name="settings">Optional resizing settings for the image</param> public string ImageAsset(IImageAssetRenderable asset, IImageResizeSettings settings = null) { if (asset == null) { return(string.Empty); } SetDefaultCrop(asset, settings); return(ImageAsset(asset.ImageAssetId, asset.FileName, asset.Extension, settings)); }
/// <summary> /// Gets the url for an image asset, with optional resizing parameters /// </summary> /// <param name="asset">asset to get the url for</param> /// <param name="settings">Optional resizing settings for the image</param> public string ImageAsset(IImageAssetRenderable asset, IImageResizeSettings settings = null) { if (asset == null) { return(string.Empty); } SetDefaultCrop(asset, settings); return(GetUrl(asset, settings)); }
/// <summary> /// Simple but less efficient way of getting an image url if you only know /// the id. Use the overload accepting an IImageAssetRenderable if possible to save a /// potential db query if the route isn't cached. /// </summary> /// <param name="imageAssetId">Id of the image asset to get the url for</param> /// <param name="settings">Optional resizing settings for the image</param> public string ImageAsset(int?imageAssetId, IImageResizeSettings settings = null) { if (!imageAssetId.HasValue) { return(string.Empty); } var asset = _queryExecutor.GetById <ImageAssetRenderDetails>(imageAssetId.Value); return(ImageAsset(asset, settings)); }
/// <summary> /// Simple but less efficient way of getting an image url if you only know /// the id. Use the overload accepting an IImageAssetRenderable if possible to save a /// potential db query if the route isn't cached. /// </summary> /// <param name="imageAssetId">Id of the image asset to get the url for</param> /// <param name="settings">Optional resizing settings for the image</param> public async Task <string> ImageAssetAsync(int?imageAssetId, IImageResizeSettings settings = null) { if (!imageAssetId.HasValue) { return(string.Empty); } var getImageQuery = new GetImageAssetRenderDetailsByIdQuery(imageAssetId.Value); var asset = await _queryExecutor.ExecuteAsync(getImageQuery); return(ImageAsset(asset, settings)); }
private static string GetUrl(IImageAssetRenderable asset, IImageResizeSettings settings = null) { var fileName = Path.ChangeExtension(SlugFormatter.ToSlug(asset.FileName), asset.FileExtension); var pathPart = asset.ImageAssetId + "-" + asset.FileStamp + "-" + asset.VerificationToken; var url = $"/assets/images/{pathPart}/{fileName}"; if (settings != null) { url += settings.ToQueryString(); } return(url); }
/// <summary> /// Creates a short string unique to the settings which can be used /// as a file name. /// </summary> public static string CreateCacheFileName(this IImageResizeSettings settings) { if (settings == null) { throw new ArgumentNullException(nameof(settings)); } const string format = "w{0}h{1}c{2}s{3}bg{4}a{5}"; string s = string.Format(format, settings.Width, settings.Height, settings.Mode, settings.Scale, settings.BackgroundColor, settings.Anchor); s = WebUtility.UrlEncode(s); return(s); }
private static void SetDefaultCrop(IImageAssetRenderable asset, IImageResizeSettings settings) { if (settings == null) { return; } if (isDefinedAndChanged(settings.Width, asset.Width) || isDefinedAndChanged(settings.Height, asset.Height)) { if (asset.DefaultAnchorLocation.HasValue) { settings.Anchor = asset.DefaultAnchorLocation.Value; } } }
private void ValidateSettings(IImageResizeSettings settings) { // Scale mode not supported yet settings.Scale = ImageScaleMode.Both; if (settings.Width > _imageAssetsSettings.MaxResizeWidth) { throw new InvalidImageResizeSettingsException($"Requested image width exceeds the maximum permitted value of {_imageAssetsSettings.MaxResizeWidth} pixels"); } if (settings.Height > _imageAssetsSettings.MaxResizeHeight) { throw new InvalidImageResizeSettingsException($"Requested image height exceeds the maximum permitted value of {_imageAssetsSettings.MaxResizeHeight} pixels"); } }
/// <summary> /// Validates that the image asset can be resized using the settings /// supplied by the client. /// </summary> /// <param name="settings">Settings to validate.</param> /// <param name="asset">Asset attempting to be resized. Cannot be null.</param> public void Validate(IImageResizeSettings settings, IImageAssetRenderable asset) { if (settings.RequiresResizing(asset) && _imageAssetsSettings.DisableResizing) { throw new InvalidImageResizeSettingsException("Image resizing has been requested but is disabled.", settings); } if (settings.Width > _imageAssetsSettings.MaxResizeWidth) { throw new InvalidImageResizeSettingsException($"Requested image width exceeds the maximum permitted value of {_imageAssetsSettings.MaxResizeWidth} pixels"); } if (settings.Height > _imageAssetsSettings.MaxResizeHeight) { throw new InvalidImageResizeSettingsException($"Requested image height exceeds the maximum permitted value of {_imageAssetsSettings.MaxResizeHeight} pixels"); } }
protected string WatermarkArguments(IImageResizeSettings settings, string outPutFilePath) { var watermarkArguments = string.Empty; if (!string.IsNullOrEmpty(settings.WatermarkPath)) { var watermarkOptions = new Dictionary<string, string>() { {"-dissolve", settings.WatermarkDissolveLevels.ToString()}, {"-gravity", Enum.GetName(typeof(Gravity), settings.WatermarkGravity)} }; var commandArguments = watermarkOptions.Select(x => x.Key + " " + x.Value).Aggregate(new StringBuilder(), (x, y) => x.Append(" " + y)).ToString(); watermarkArguments = string.Format("{0} {1} {2} {2}", commandArguments.ToString(), settings.WatermarkPath, outPutFilePath); } return watermarkArguments; }
/// <summary> /// Determines if the settings indicate that an image asset should /// be resized. If width and hight are not specified or the dimensions /// in the settings are the same as the image then false will be returned. /// </summary> /// <param name="asset">The asset to check. Cannot be null.</param> public static bool RequiresResizing(this IImageResizeSettings settings, IImageAssetRenderable asset) { if (settings == null) { throw new ArgumentNullException(nameof(settings)); } if (asset == null) { throw new ArgumentNullException(nameof(asset)); } if ((settings.Width < 1 && settings.Height < 1) || (settings.Width == asset.Width && settings.Height == asset.Height)) { return(false); } return(true); }
/// <summary> /// Gets the url for an image asset, with optional resizing parameters /// </summary> /// <param name="asset">asset to get the url for</param> /// <param name="settings">Optional resizing settings for the image</param> public string ImageAsset(IImageAssetRenderable image, IImageResizeSettings settings = null) { return(_imageAssetRouteLibrary.ImageAsset(image, settings)); }
public Task <Stream> GetAsync(IImageAssetRenderable asset, IImageResizeSettings inputSettings) { // Resizing only supported via plugin return(GetFileStreamAsync(asset.ImageAssetId)); }
/// <summary> /// Simple but less efficient way of getting an image url if you only know /// the id. Use the overload accepting an IImageAssetRenderable if possible to save a /// potential db query if the route isn't cached. /// </summary> /// <param name="imageAssetId">Id of the image asset to get the url for</param> /// <param name="settings">Optional resizing settings for the image</param> public string ImageAsset(int?imageAssetId, IImageResizeSettings settings = null) { return(_imageAssetRouteLibrary.ImageAsset(imageAssetId, settings)); }
public Stream Get(IImageAssetRenderable asset, IImageResizeSettings inputSettings) { // Resizing only supported via plugin return(GetFileStream(asset.ImageAssetId)); }
/// <summary> /// Simple but less efficient way of getting an image url if you only know /// the id. Use the overload accepting an IImageAssetRenderable if possible to save a /// potential db query if the route isn't cached. /// </summary> /// <param name="imageAssetId">Id of the image asset to get the url for.</param> /// <param name="settings">Optional resizing settings for the image.</param> public Task <string> ImageAssetAsync(int?imageAssetId, IImageResizeSettings settings = null) { return(_imageAssetRouteLibrary.ImageAssetAsync(imageAssetId, settings)); }
private ResizeOptions ConvertSettings(IImageResizeSettings inputSettings) { var resizeSettings = new ResizeOptions(); resizeSettings.Size = new Size(inputSettings.Width, inputSettings.Height); // Scale options not supported yet //resizeSettings.Scale = (ScaleMode)inputSettings.Scale; switch (inputSettings.Mode) { case ImageFitMode.Default: case ImageFitMode.Crop: resizeSettings.Mode = ResizeMode.Crop; break; case ImageFitMode.Max: resizeSettings.Mode = ResizeMode.Max; break; case ImageFitMode.Pad: resizeSettings.Mode = ResizeMode.Pad; break; default: throw new NotSupportedException("ImageFitMode not supported: " + inputSettings.Mode); } switch (inputSettings.Anchor) { case ImageAnchorLocation.BottomCenter: resizeSettings.Position = AnchorPositionMode.Bottom; break; case ImageAnchorLocation.BottomLeft: resizeSettings.Position = AnchorPositionMode.BottomLeft; break; case ImageAnchorLocation.BottomRight: resizeSettings.Position = AnchorPositionMode.BottomRight; break; case ImageAnchorLocation.MiddleCenter: resizeSettings.Position = AnchorPositionMode.Center; break; case ImageAnchorLocation.MiddleLeft: resizeSettings.Position = AnchorPositionMode.Left; break; case ImageAnchorLocation.MiddleRight: resizeSettings.Position = AnchorPositionMode.Right; break; case ImageAnchorLocation.TopCenter: resizeSettings.Position = AnchorPositionMode.Top; break; case ImageAnchorLocation.TopLeft: resizeSettings.Position = AnchorPositionMode.TopLeft; break; case ImageAnchorLocation.TopRight: resizeSettings.Position = AnchorPositionMode.TopRight; break; default: throw new NotSupportedException("ImageAnchorLocation not supported: " + inputSettings.Anchor); } return(resizeSettings); }
private static string ImageAsset(int assetId, string fileName, string extension, IImageResizeSettings settings = null) { var pathFileName = Path.ChangeExtension(assetId + "_" + SlugFormatter.ToSlug(fileName), extension); var url = "/assets/images/" + pathFileName; if (settings != null) { url += settings.ToQueryString(); } return(url); }
/// <summary> /// Indicates if the resize height has been specified i.e. is greater than 0. /// </summary> public static bool IsHeightSet(this IImageResizeSettings settings) { return(settings.Height > 0); }
/// <summary> /// Indicates if the resize width has been specified i.e. is greater than 0. /// </summary> public static bool IsWidthSet(this IImageResizeSettings settings) { return(settings.Width > 0); }
protected string ThumbnailArguments(IImageResizeSettings settings, string inputFilePath, string outPutFilePath) { var backgroundColour = settings.BackgroundColour; if (!string.IsNullOrEmpty(backgroundColour)) { if (backgroundColour == "#00FFFFFF") { backgroundColour = "#00000000"; //This is imagemagicks transparent color } backgroundColour = " -background " + backgroundColour; } var quality = string.Empty; if (settings.Quality.HasValue) { quality = " -quality " + settings.Quality.Value; } var commandArguments = string.Empty; switch (settings.ResizeMode) { case ResizeMode.AreaToFit: { var area = settings.Width * settings.Height; commandArguments = String.Format( "-define jpeg:size=\"{0}x{1}\" \"{2}\" -thumbnail \"{3}@\"{4} -gravity {5} -extent \"{6}x{7}\"{8}", settings.Width * 2, settings.Height * 2, inputFilePath, area, backgroundColour, Enum.GetName(typeof(Gravity), settings.Gravity), settings.Width, settings.Height, quality); break; } case ResizeMode.CutToFit: { commandArguments = String.Format("-define jpeg:size=\"{0}x{1}\" \"{2}\" -thumbnail \"{3}x{4}^\" -gravity {5} -extent \"{6}x{7}\"{8}", settings.Width * 2, settings.Height * 2, inputFilePath, settings.Width, settings.Height, Enum.GetName(typeof(Gravity), settings.Gravity), settings.Width, settings.Height, quality); break; } case ResizeMode.Zoom: { commandArguments = String.Format( "-define jpeg:size=\"{0}x{1}\" \"{2}\" -thumbnail \"{3}x{4}>\" {5} -gravity {6} -extent \"{7}x{8}\"{9}", settings.Width * 2, settings.Height * 2, inputFilePath, settings.Width, settings.Height, backgroundColour, Enum.GetName(typeof(Gravity), settings.Gravity), settings.Width, settings.Height, quality); break; } case ResizeMode.Stretch: { commandArguments = String.Format("-define jpeg:size=\"{0}x{1}\" \"{2}\" -thumbnail \"{3}x{4}!\"{5}", settings.Width * 2, settings.Height * 2, inputFilePath, settings.Width, settings.Height, quality); break; } case ResizeMode.FitWidth: { commandArguments = String.Format("-define jpeg:size=\"{0}\" \"{1}\" -thumbnail \"{2}\"{3}", settings.Width * 2, inputFilePath, settings.Width, quality); break; } case ResizeMode.FitMaximumWidth: { commandArguments = String.Format("-define jpeg:size=\"{0}>\" \"{1}\" -thumbnail \"{2}>\"{3}", settings.Width * 2, inputFilePath, settings.Width, quality); break; } case ResizeMode.FitMinimumWidth: { commandArguments = String.Format("-define jpeg:size=\"{0}\" \"{1}\" -thumbnail \"{2}^\"{3}", settings.Width * 2, inputFilePath, settings.Width, quality); break; } case ResizeMode.FitHeight: { commandArguments = String.Format("-define jpeg:size=\"x{0}\" \"{1}\" -thumbnail \"x{2}\"{3}", settings.Height * 2, inputFilePath, settings.Height, quality); break; } case ResizeMode.FitMaximumHeight: { commandArguments = String.Format("-define jpeg:size=\"x{0}\" \"{1}\" -thumbnail \"x{2}>\"{3}", settings.Height * 2, inputFilePath, settings.Height, quality); break; } case ResizeMode.FitMinimumHeight: { commandArguments = String.Format("-define jpeg:size=\"x{0}\" \"{1}\" -thumbnail \"x{2}^\"{3}", settings.Height * 2, inputFilePath, settings.Height, quality); break; } default: { commandArguments = String.Format("\"{0}\"", inputFilePath); break; } } commandArguments += string.Format(" \"{0}\"", outPutFilePath); return commandArguments; }
public async Task <Stream> GetAsync(IImageAssetRenderable asset, IImageResizeSettings inputSettings) { if ((inputSettings.Width < 1 && inputSettings.Height < 1) || (inputSettings.Width == asset.Width && inputSettings.Height == asset.Height)) { return(await GetFileStreamAsync(asset.ImageAssetId)); } if (_imageAssetsSettings.DisableResizing) { throw new InvalidImageResizeSettingsException("Image resizing has been requested but is disabled.", inputSettings); } var fullFileName = asset.FileNameOnDisk + "/" + CreateCacheFileName(inputSettings, asset); Stream imageStream = null; ValidateSettings(inputSettings); if (await _fileService.ExistsAsync(IMAGE_ASSET_CACHE_CONTAINER_NAME, fullFileName)) { return(await _fileService.GetAsync(IMAGE_ASSET_CACHE_CONTAINER_NAME, fullFileName)); } else { imageStream = new MemoryStream(); IImageFormat imageFormat = null; using (var originalStream = await GetFileStreamAsync(asset.ImageAssetId)) using (var image = Image.Load(originalStream, out imageFormat)) { if (imageFormat == null) { throw new Exception("Unable to determine image type for image asset " + asset.ImageAssetId); } var encoder = Configuration.Default.ImageFormatsManager.FindEncoder(imageFormat); if (encoder == null) { throw new InvalidOperationException("Encoder not found for image format " + imageFormat.Name); } var resizeOptions = ConvertSettings(inputSettings); image.Mutate(cx => { cx.Resize(resizeOptions); if (!string.IsNullOrWhiteSpace(inputSettings.BackgroundColor)) { var color = Rgba32.ParseHex(inputSettings.BackgroundColor); cx.BackgroundColor(color); } else if (CanPad(resizeOptions)) { if (SupportsTransparency(imageFormat)) { cx.BackgroundColor(Color.Transparent); encoder = EnsureEncoderSupportsTransparency(encoder); } else { // default background for jpg encoder is black, but white is a better default in most scenarios. cx.BackgroundColor(Color.White); } } }); image.Save(imageStream, encoder); } try { // Try and create the cache file, but don't throw an error if it fails - it will be attempted again on the next request await _fileService.CreateIfNotExistsAsync(IMAGE_ASSET_CACHE_CONTAINER_NAME, fullFileName, imageStream); } catch (Exception ex) { if (Debugger.IsAttached) { throw; } else { _logger.LogError(0, ex, "Error creating image asset cache file. Container name {ContainerName}, {fullFileName}", IMAGE_ASSET_CACHE_CONTAINER_NAME, fullFileName); } } imageStream.Position = 0; return(imageStream); } }
public InvalidImageResizeSettingsException(string message, IImageResizeSettings imageResizeSettings) : base(message) { ImageResizeSettings = imageResizeSettings; }