/// <summary> /// Processes a request to determine if it matches a known image, otherwise it will generate it. /// </summary> /// <param name="context"></param> /// <returns></returns> public async Task Invoke(HttpContext context) { var path = context.Request.Path; var extension = Path.GetExtension(path.Value); if (!GenericHelpers.IsGetOrHeadMethod(context.Request.Method)) { this.logger.LogRequestMethodNotSupported(context.Request.Method); } else if (!GenericHelpers.IsRequestFileTypeSupported( extension, this.options.OutputFormats.SelectMany( x => x.FileEndings).ToArray() ) ) { this.logger.LogRequestFileTypeNotSupported(extension); } else if (!GenericHelpers.TryMatchPath(path, this.options.TargetFolder)) { this.logger.LogPathMismatch(path); } else { // get the image location on disk var imagePath = Path.Combine( this.env.WebRootPath, path.Value .Replace('/', Path.DirectorySeparatorChar) .TrimStart(Path.DirectorySeparatorChar) ); if (!File.Exists(imagePath)) { this.logger.LogProcessingImage(path.Value); var size = Path.GetFileNameWithoutExtension(path.Value).ToLower(); var filename = Directory.GetParent(path.Value).Name; // var imageSourcePath = Path.Combine( // $"{this.env.ContentRootPath}{this.options.SourceFolder}", // $"{filename}{extension}" // ); FileInfo sourceImageFile; var sourceImageFolder = new DirectoryInfo(Path.Combine( $"{this.env.ContentRootPath}{this.options.SourceFolder}" )); var sourceImageFiles = sourceImageFolder.GetFiles($"{filename}.*"); if (sourceImageFiles == null || sourceImageFiles.Length == 0) { // Image source not found! // Hand over to the next middleware and return. this.logger.LogSourceImageNotFound($"{filename}.*"); await this.next(context); return; } else { if (sourceImageFiles.Length > 1) { this.logger.LogWarning( $"Found multiple source images, take first one: {sourceImageFiles[0].Name}" ); } sourceImageFile = sourceImageFiles[0]; } var targetDir = Path.Combine( this.env.WebRootPath, this.options.TargetFolder .Replace('/', Path.DirectorySeparatorChar) .TrimStart(Path.DirectorySeparatorChar), filename ); if (!Directory.Exists(targetDir)) { this.logger.LogInformation($"Create Directory: \"{targetDir}\""); Directory.CreateDirectory(targetDir); } var sizeSetting = this.options.Sizes.FirstOrDefault( x => (x.Name ?? x.Width.ToString()).ToLower() == size ); if (sizeSetting == null) { // Not supported size! // Hand over to the next middleware and return. this.logger.LogSizeNotSupported(size); await this.next(context); return; } var sourceImageFileExtension = sourceImageFile.Extension.Trim('.'); var isSourceFileSupported = Enum.TryParse <MagickFormat>(sourceImageFileExtension, true, out var format); if (isSourceFileSupported) { using (var image = new MagickImage()) { try { image.Read(sourceImageFile); } // Something went wrong while loading the image with ImageMagick catch (MagickException exception) { this.logger.LogError($"Error while loading image: {exception}"); await this.next(context); return; } image.Resize(sizeSetting.Width, sizeSetting.Height); image.Strip(); if (sizeSetting.Quality >= 0) { this.logger.LogInformation($"Setting Quality to: \"{sizeSetting.Quality}\""); image.Quality = sizeSetting.Quality; } if (sizeSetting.Progressive) { image.Format = MagickFormat.Pjpeg; } using (var stream = new MemoryStream()) { image.Write(stream); stream.Position = 0; this.logger.LogInformation($"LosslessCompress before: {stream.Length / 1024} kb"); var imageOptimizer = new ImageOptimizer(); if (options.LosslessCompress) { imageOptimizer.LosslessCompress(stream); } else { imageOptimizer.Compress(stream); } this.logger.LogInformation($"LosslessCompress after: {stream.Length / 1024} kb"); using ( FileStream file = new FileStream( imagePath, FileMode.Create, System.IO.FileAccess.Write ) ) { stream.WriteTo(file); file.Flush(); } } } } else { this.logger.LogSourceFileTypeNotSupported($"{sourceImageFileExtension}"); await this.next(context); return; } } } await this.next(context); }