public async Task CreateThumbnailAsync(Stream source, string mimeType, Stream destination, ResizeOptions options, CancellationToken ct = default) { Guard.NotNull(source, nameof(source)); Guard.NotNull(destination, nameof(destination)); Guard.NotNull(options, nameof(options)); if (!options.IsValid) { await source.CopyToAsync(destination, ct); return; } var w = options.TargetWidth ?? 0; var h = options.TargetHeight ?? 0; using (var image = Image.Load(source, out var format)) { image.Mutate(x => x.AutoOrient()); if (w > 0 || h > 0) { var isCropUpsize = options.Mode == ResizeMode.CropUpsize; if (!Enum.TryParse <ISResizeMode>(options.Mode.ToString(), true, out var resizeMode)) { resizeMode = ISResizeMode.Max; } if (isCropUpsize) { resizeMode = ISResizeMode.Crop; } if (w >= image.Width && h >= image.Height && resizeMode == ISResizeMode.Crop && !isCropUpsize) { resizeMode = ISResizeMode.BoxPad; } var resizeOptions = new ISResizeOptions { Size = new Size(w, h), Mode = resizeMode, PremultiplyAlpha = true }; if (options.FocusX.HasValue && options.FocusY.HasValue) { resizeOptions.CenterCoordinates = new PointF( +(options.FocusX.Value / 2f) + 0.5f, -(options.FocusY.Value / 2f) + 0.5f ); } image.Mutate(operation => { operation.Resize(resizeOptions); if (Color.TryParse(options.Background, out var color)) { operation.BackgroundColor(color); } else { operation.BackgroundColor(Color.Transparent); } }); } var encoder = options.GetEncoder(format); await image.SaveAsync(destination, encoder, ct); } }