public async Task <BaseImage> RotateAsync(float angle) { if (_sourceImage.AppliedEffects.Any(e => e.Type.HasFlag(EffectType.Rotated))) { throw new Exception($"The image {_sourceImage.Id} is already rotated. Use the original one"); } using (var sourceStream = File.OpenRead(_sourceImage.GetFileServerPath())) using (var sourceImg = Image.Load(sourceStream)) { int originalWidth = sourceImg.Width; int originalHeight = sourceImg.Height; sourceImg.Mutate(x => x.Rotate(angle)); //TODO: Review why we must expand image (otherwise it fails) //Recenter the image var addedWidth = (sourceImg.Width - originalWidth) / 2f; var addedHeight = (sourceImg.Height - originalHeight) / 2f; var addedWidthInt = (int)addedWidth; var addedHeightInt = (int)addedHeight; var vectorToAdd = new Vector2(addedWidth - addedWidthInt, addedHeight - addedHeightInt); var xCenter = originalWidth / 2f; var yCenter = originalHeight / 2f; var facePoints = _sourceImage.FacePoints.Select(p => p.RotatePoint(xCenter, yCenter, angle) + vectorToAdd).ToArray(); sourceImg.Mutate(x => x.Crop(new Rectangle(addedWidthInt, addedHeightInt, originalWidth, originalHeight))); var img = await BaseImage.CreateAsync(sourceImg, _sourceImage.Name, Effect.RotationEffect(angle, _sourceImage.AppliedEffects.LastOrDefault()), _sourceImage, isRgb : _sourceImage.IsRgb).ConfigureAwait(false); img.SetFaceLandmarks(facePoints); return(img); } }
public async Task <BaseImage> GenerateFlipAsync(FlipMode flipMode) { if (_sourceImage.AppliedEffects.Any(e => e.Type.HasFlag(EffectType.FlippedHorizontal) || e.Type.HasFlag(EffectType.FlippedVertical) || e.Type.HasFlag(EffectType.FlippedBoth))) { throw new Exception($"The image {_sourceImage.Id} is already flipped. Use the original one"); } using (var sourceStream = File.OpenRead(_sourceImage.GetFileServerPath())) using (var sourceImg = Image.Load(sourceStream)) { switch (flipMode) { case FlipMode.Horizontal: sourceImg.Mutate(x => x.Flip(FlipType.Horizontal)); return(await BaseImage.CreateAsync(sourceImg, _sourceImage.Name, Effect.FlipEffect(flipMode, _sourceImage.AppliedEffects.LastOrDefault()), _sourceImage, _sourceImage.FacePoints.Select(p => new Vector2(_sourceImage.Width - p.X, p.Y)), xTop : _sourceImage.XTopLeftOriginal, yTop : _sourceImage.YTopLeftOriginal, xBottom : _sourceImage.XBottomRightOriginal, yBottom : _sourceImage.YBottomRightOriginal, isRgb : _sourceImage.IsRgb).ConfigureAwait(false)); case FlipMode.Vertical: sourceImg.Mutate(x => x.Flip(FlipType.Vertical)); return(await BaseImage.CreateAsync(sourceImg, _sourceImage.Name, Effect.FlipEffect(flipMode, _sourceImage.AppliedEffects.LastOrDefault()), _sourceImage, _sourceImage.FacePoints.Select(p => new Vector2(p.X, _sourceImage.Height - p.Y)), xTop : _sourceImage.XTopLeftOriginal, yTop : _sourceImage.YTopLeftOriginal, xBottom : _sourceImage.XBottomRightOriginal, yBottom : _sourceImage.YBottomRightOriginal, isRgb : _sourceImage.IsRgb).ConfigureAwait(false)); case FlipMode.Both: sourceImg.Mutate(x => x.Flip(FlipType.Horizontal).Flip(FlipType.Vertical)); return(await BaseImage.CreateAsync(sourceImg, _sourceImage.Name, Effect.FlipEffect(flipMode, _sourceImage.AppliedEffects.LastOrDefault()), _sourceImage, _sourceImage.FacePoints.Select(p => new Vector2(_sourceImage.Width - p.X, _sourceImage.Height - p.Y)), xTop : _sourceImage.XTopLeftOriginal, yTop : _sourceImage.YTopLeftOriginal, xBottom : _sourceImage.XBottomRightOriginal, yBottom : _sourceImage.YBottomRightOriginal, isRgb : _sourceImage.IsRgb).ConfigureAwait(false)); default: throw new ArgumentOutOfRangeException(nameof(flipMode), flipMode, null); } } }
public async Task <BaseImage> GenerateGrayAsync() { if (!_sourceImage.IsRgb) { throw new Exception($"The image {_sourceImage.Id} is already converted to gray. Use the original one"); } using (Stream sourceStream = File.OpenRead(_sourceImage.GetFileServerPath())) using (var sourceImg = Image.Load(sourceStream)) { sourceImg.Mutate(x => x.Grayscale()); return(await BaseImage.CreateAsync(sourceImg, _sourceImage.Name, Effect.ConvertToGrayEffect(_sourceImage.AppliedEffects.LastOrDefault()), _sourceImage, _sourceImage.FacePoints, xTop : _sourceImage.XTopLeftOriginal, yTop : _sourceImage.YTopLeftOriginal, xBottom : _sourceImage.XBottomRightOriginal, yBottom : _sourceImage.YBottomRightOriginal, isRgb : false).ConfigureAwait(false)); } }
public async Task <BaseImage> GenerateBlurAsync(float sigma = 3) { if (_sourceImage.AppliedEffects.Any(e => e.Type.HasFlag(EffectType.Blurred))) { throw new Exception($"The image {_sourceImage.Id} is already blurred. Use the original one"); } using (var sourceStream = File.OpenRead(_sourceImage.GetFileServerPath())) using (var sourceImg = Image.Load(sourceStream)) { sourceImg.Mutate(x => x.GaussianBlur(sigma)); return(await BaseImage.CreateAsync(sourceImg, _sourceImage.Name, Effect.BlurEffect(sigma, _sourceImage.AppliedEffects.LastOrDefault()), _sourceImage, _sourceImage.FacePoints, xTop : _sourceImage.XTopLeftOriginal, yTop : _sourceImage.YTopLeftOriginal, xBottom : _sourceImage.XBottomRightOriginal, yBottom : _sourceImage.YBottomRightOriginal, isRgb : _sourceImage.IsRgb).ConfigureAwait(false)); } }
//public async Task<BaseImage> GenerateElasticSearchAsync(int kernelSize = 13, double sigma = 6, double alpha = 36) //{ // if (_sourceImage.AppliedEffects.Any(e => e.Type.HasFlag(EffectType.ElasticDistorsionated))) // { // throw new Exception($"The image {_sourceImage.Id} is already elastic distorsioned. Use the original one"); // } // using (var sourceStream = File.OpenRead(_sourceImage.GetFileServerPath())) // using (var sourceImg = Image.Load(sourceStream)) // using (var imageE = new Image<Rgba32>(sourceImg.Width, sourceImg.Height)) // { // Vector2[] destFacePoints = new Vector2[_sourceImage.FacePoints.Length]; // Image. // GenerateElasticPixels(kernelSize, sigma, alpha, sourceImg.Pixels, imageE.Pixels, sourceImg.Width, sourceImg.Height, _sourceImage.FacePoints, destFacePoints); // return await BaseImage.CreateAsync(imageE, _sourceImage.Name, Effect.ElasticDeformationEffect(sigma, alpha, kernelSize, _sourceImage.AppliedEffects.LastOrDefault()), _sourceImage, destFacePoints, // xTop: _sourceImage.XTopLeftOriginal, yTop: _sourceImage.YTopLeftOriginal, xBottom: _sourceImage.XBottomRightOriginal, yBottom: _sourceImage.YBottomRightOriginal, isRgb: _sourceImage.IsRgb).ConfigureAwait(false); // } //} public async Task <BaseImage> CropAndResizeAsync(int x, int y, int width, int height, int newWidth, int newHeight) { const float minDownscaleFactor = 0.5f; var xFactor = (1f * newWidth) / width; var yFactor = (1f * newHeight) / height; float xFactorStep = xFactor < minDownscaleFactor ? minDownscaleFactor : xFactor; float yFactorStep = yFactor < minDownscaleFactor ? minDownscaleFactor : yFactor; using (var sourceStream = File.OpenRead(_sourceImage.GetFileServerPath())) using (var sourceImg = Image.Load(sourceStream)) { sourceImg.Mutate(img => img.Crop(new Rectangle(x, y, width, height)).Resize(new ResizeOptions() { Mode = ResizeMode.Stretch, Size = new Size((int)Math.Round(width * xFactorStep), (int)Math.Round(height * yFactorStep)), Sampler = new Lanczos3Resampler() })); while (sourceImg.Width > newWidth) { xFactorStep = (1f * newWidth) / sourceImg.Width; xFactorStep = xFactorStep < minDownscaleFactor ? minDownscaleFactor : xFactorStep; yFactorStep = (1f * newHeight) / sourceImg.Height; yFactorStep = yFactorStep < minDownscaleFactor ? 0.5f : yFactorStep; sourceImg.Mutate(img => img.Resize(new ResizeOptions { Mode = ResizeMode.Stretch, Size = new Size((int)Math.Round(sourceImg.Width * xFactorStep), (int)Math.Round(sourceImg.Height * yFactorStep)), Sampler = new Lanczos3Resampler() })); } int?xTop = _sourceImage.XTopLeftOriginal - x; int?yTop = _sourceImage.YTopLeftOriginal - y; int?xBottom = xTop + newWidth; int?yBottom = yTop + newHeight; var facePoints = _sourceImage.FacePoints.Select(p => new Vector2(xFactor * (p.X - x), yFactor * (p.Y - y))); return(await BaseImage.CreateAsync(sourceImg, _sourceImage.Name, Effect.CropAndResizeEffect(_sourceImage.AppliedEffects.LastOrDefault()), _sourceImage, facePoints, xTop : xTop, yTop : yTop, xBottom : xBottom, yBottom : yBottom, isRgb : _sourceImage.IsRgb).ConfigureAwait(false)); } }