/// <summary> /// Create a sprite image from a list of images and the CSS to render each image. /// </summary> /// <param name="images">The list of images to include in the sprite.</param> /// <param name="placeholderImages">The list of custom placeholder images.</param> /// <param name="spriteSettings">The settings to use when creating the sprite.</param> public void CreateSprite(IReadOnlyCollection<ISpriteImage> images, IReadOnlyCollection<ISpriteImage> placeholderImages, SpriteSettings spriteSettings) { if (images == null) { throw new ArgumentNullException(nameof(images)); } if (images.GroupBy(x => x.Key).Any(x => x.Skip(1).Any())) { throw new ArgumentException("The list of keys must be unique.", nameof(images)); } if (placeholderImages == null || !placeholderImages.Any()) { placeholderImages = DefaultPlaceholderImages; } if (placeholderImages.GroupBy(x => x.Key).Any(x => x.Skip(1).Any())) { throw new ArgumentException("The list of keys must be unique.", nameof(placeholderImages)); } if (spriteSettings == null) { throw new ArgumentNullException(nameof(spriteSettings)); } var spritePlaceholderImages = new List<SpritePlaceholderImage>(); using (var spriteImages = new MagickImageCollection()) { var css = new StringBuilder(); var nextSpriteImageTop = 0; foreach (ISpriteImage image in images) { var hasImageBeenAddedToSprite = false; int selectedImageHeight; int selectedImageTop; int selectedImageWidth; var selectedHoverImageHeight = 0; var selectedHoverImageTop = 0; var selectedHoverImageWidth = 0; MagickImage imageForSprite = ImageToMagickImage(image); if (imageForSprite != null) { spriteImages.Add(imageForSprite); hasImageBeenAddedToSprite = true; selectedImageTop = nextSpriteImageTop; selectedImageHeight = imageForSprite.Height; selectedImageWidth = imageForSprite.Width; } else { string selectedPlaceholderImageKey = placeholderImages.Any(x => x.Key == image.PlaceholderImageKey) ? image.PlaceholderImageKey : placeholderImages.First().Key; ISpriteImage selectedPlaceholderImage = placeholderImages.FirstOrDefault(x => x.Key == selectedPlaceholderImageKey); imageForSprite = ImageToMagickImage(selectedPlaceholderImage); SpritePlaceholderImage spritePlaceholderImage = spritePlaceholderImages.FirstOrDefault(x => x.Key == selectedPlaceholderImageKey && x.Width == imageForSprite.Width && x.Height == imageForSprite.Height); if (spritePlaceholderImage == null) { spritePlaceholderImage = new SpritePlaceholderImage(selectedPlaceholderImageKey, nextSpriteImageTop, imageForSprite.Height, imageForSprite.Width); spritePlaceholderImages.Add(spritePlaceholderImage); spriteImages.Add(imageForSprite); hasImageBeenAddedToSprite = true; } selectedImageTop = spritePlaceholderImage.Top; selectedImageHeight = spritePlaceholderImage.Height; selectedImageWidth = spritePlaceholderImage.Width; } string selectedImageTopText = selectedImageTop != 0 ? $"-{selectedImageTop}px" : "0"; css.Append($"#{image.Key}{{height:{selectedImageHeight}px;width:{selectedImageWidth}px;background:url('{spriteSettings.SpriteUrl}') 0 {selectedImageTopText};}}"); if (hasImageBeenAddedToSprite) { nextSpriteImageTop += selectedImageHeight; } if (image.HoverImage != null) { MagickImage hoverImageForSprite = ImageToMagickImage(image.HoverImage, imageForSprite); if (hoverImageForSprite != null) { spriteImages.Add(hoverImageForSprite); hasImageBeenAddedToSprite = true; selectedHoverImageTop = nextSpriteImageTop; selectedHoverImageHeight = hoverImageForSprite.Height; selectedHoverImageWidth = hoverImageForSprite.Width; } string selectedHoverImageTopText = selectedHoverImageTop != 0 ? $"-{selectedHoverImageTop}px" : "0"; css.Append($"#{image.Key}:hover{{height:{selectedHoverImageHeight}px;width:{selectedHoverImageWidth}px;background:url('{spriteSettings.SpriteUrl}') 0 {selectedHoverImageTopText};}}"); if (hasImageBeenAddedToSprite) { nextSpriteImageTop += selectedHoverImageHeight; } } } _imageProcessor.CreateSprite(spriteImages, spriteSettings.SpriteFilename); _cssProcessor.CreateCss(css.ToString(), spriteSettings.CssFilename); } }
/// <summary> /// Create a sprite image from a list of images and the CSS to render each image. /// </summary> /// <param name="images">The list of images to include in the sprite.</param> /// <param name="placeholderImages">The list of custom placeholder images.</param> /// <param name="spriteSettings">The settings to use when creating the sprite.</param> public void CreateSprite(IReadOnlyCollection <ISpriteImage> images, IReadOnlyCollection <ISpriteImage> placeholderImages, SpriteSettings spriteSettings) { if (images == null) { throw new ArgumentNullException(nameof(images)); } if (images.GroupBy(x => x.Key).Any(x => x.Skip(1).Any())) { throw new ArgumentException("The list of keys must be unique.", nameof(images)); } if (placeholderImages == null || !placeholderImages.Any()) { placeholderImages = DefaultPlaceholderImages; } if (placeholderImages.GroupBy(x => x.Key).Any(x => x.Skip(1).Any())) { throw new ArgumentException("The list of keys must be unique.", nameof(placeholderImages)); } if (spriteSettings == null) { throw new ArgumentNullException(nameof(spriteSettings)); } var spritePlaceholderImages = new List <SpritePlaceholderImage>(); using (var spriteImages = new MagickImageCollection()) { var css = new StringBuilder(); var nextSpriteImageTop = 0; foreach (var image in images) { var hasImageBeenAddedToSprite = false; int selectedImageHeight; int selectedImageTop; int selectedImageWidth; var selectedHoverImageHeight = 0; var selectedHoverImageTop = 0; var selectedHoverImageWidth = 0; var imageForSprite = ImageToMagickImage(image); if (imageForSprite != null) { spriteImages.Add(imageForSprite); hasImageBeenAddedToSprite = true; selectedImageTop = nextSpriteImageTop; selectedImageHeight = imageForSprite.Height; selectedImageWidth = imageForSprite.Width; } else { var selectedPlaceholderImageKey = placeholderImages.Any(x => x.Key == image.PlaceholderImageKey) ? image.PlaceholderImageKey : placeholderImages.First().Key; var selectedPlaceholderImage = placeholderImages.FirstOrDefault(x => x.Key == selectedPlaceholderImageKey); imageForSprite = ImageToMagickImage(selectedPlaceholderImage); var spritePlaceholderImage = spritePlaceholderImages.FirstOrDefault(x => x.Key == selectedPlaceholderImageKey && x.Width == imageForSprite.Width && x.Height == imageForSprite.Height); if (spritePlaceholderImage == null) { spritePlaceholderImage = new SpritePlaceholderImage(selectedPlaceholderImageKey, nextSpriteImageTop, imageForSprite.Height, imageForSprite.Width); spritePlaceholderImages.Add(spritePlaceholderImage); spriteImages.Add(imageForSprite); hasImageBeenAddedToSprite = true; } selectedImageTop = spritePlaceholderImage.Top; selectedImageHeight = spritePlaceholderImage.Height; selectedImageWidth = spritePlaceholderImage.Width; } var selectedImageTopText = selectedImageTop != 0 ? $"-{selectedImageTop}px" : "0"; // Not sure if this should be more robust/precise, it's currently just escaping any invalid characters it finds based on a set of invalid css characters. var regex = new Regex(@"[!""#$%&'()\*\+,\./:;<=>\?@\[\\\]^`{\|}~ ]"); var imageKey = regex.Replace(image.Key, m => $"\\{m.Value}"); css.Append($".{imageKey}{{height:{selectedImageHeight}px;width:{selectedImageWidth}px;background:url('{spriteSettings.SpriteUrl}') 0 {selectedImageTopText};}}"); if (hasImageBeenAddedToSprite) { nextSpriteImageTop += selectedImageHeight; } if (image.HoverImage != null) { var hoverImageForSprite = ImageToMagickImage(image.HoverImage, imageForSprite); if (hoverImageForSprite != null) { spriteImages.Add(hoverImageForSprite); hasImageBeenAddedToSprite = true; selectedHoverImageTop = nextSpriteImageTop; selectedHoverImageHeight = hoverImageForSprite.Height; selectedHoverImageWidth = hoverImageForSprite.Width; } var selectedHoverImageTopText = selectedHoverImageTop != 0 ? $"-{selectedHoverImageTop}px" : "0"; css.Append($".{image.Key}:hover{{height:{selectedHoverImageHeight}px;width:{selectedHoverImageWidth}px;background:url('{spriteSettings.SpriteUrl}') 0 {selectedHoverImageTopText};}}"); if (hasImageBeenAddedToSprite) { nextSpriteImageTop += selectedHoverImageHeight; } } } _imageProcessor.CreateSprite(spriteImages, spriteSettings.SpriteFilename); _cssProcessor.CreateCss(css.ToString(), spriteSettings.CssFilename); } }