예제 #1
0
        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));
        }
예제 #2
0
        /// <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));
        }
예제 #4
0
        /// <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));
        }
예제 #5
0
        /// <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);
        }
예제 #7
0
        /// <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);
        }
예제 #8
0
        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;
                }
            }
        }
예제 #9
0
        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;
		}
예제 #12
0
        /// <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);
        }
예제 #13
0
 /// <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));
 }
예제 #14
0
 public Task <Stream> GetAsync(IImageAssetRenderable asset, IImageResizeSettings inputSettings)
 {
     // Resizing only supported via plugin
     return(GetFileStreamAsync(asset.ImageAssetId));
 }
예제 #15
0
 /// <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));
 }
예제 #17
0
 /// <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));
 }
예제 #18
0
        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);
        }
예제 #19
0
        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);
        }
예제 #20
0
 /// <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);
 }
예제 #21
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;
		}
예제 #23
0
        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);
            }
        }
예제 #24
0
 public InvalidImageResizeSettingsException(string message, IImageResizeSettings imageResizeSettings)
     : base(message)
 {
     ImageResizeSettings = imageResizeSettings;
 }