繁体   English   中英

模糊上传的图像 ASP.NET Core API

[英]Blurring an uploaded image ASP.NET Core API

我正在使用 .NET 6 编写一个 api。
作为我的要求的一部分,我需要:

  • 处理文件上传,仅支持图片。
  • 我需要将图像转换为 jpg(删除任何 alpha 通道)。
  • 如果需要,调整大小(缩小)。
  • 创建图像的模糊副本,当然还要保存两个图像。

我尝试了以下软件包:

  • Magick.NET - 模糊图像非常缓慢。
  • ImageSharp - 导致巨大的内存泄漏(10 个并发请求将内存从 140 MB 提高到 600 MB,对于 1 MB 图像)。
  • OpenCV (EmguCV 或 OpenCVSharp) - 大量使用字节流。
  • ImageProcessor - 不支持 .NET 核心或 .NET 5+。

我首先尝试解决模糊问题,我想如果我能找到一个好的模糊支持库,我会找到其他所有东西......我有点卡在这里。

这就是我到目前为止所拥有的(使用 ImageSharp)

    [Route("api/[controller]")]
    [ApiController]
    public class PhotosController : ControllerBase
    {
        [HttpPost]
        [Consumes("multipart/form-data")]
        public async Task<IActionResult> UploadAsync([FromForm] IFormFile photo)
        {
            if (photo.Length > 0)
            {
                try
                {
                    var folderName = Path.Combine("Resources", "Images");
                    var pathToSave = Path.Combine(Directory.GetCurrentDirectory(), folderName);
                    var fileNameWithoutExt = Path.GetFileNameWithoutExtension(ContentDispositionHeaderValue.Parse(photo.ContentDisposition).FileName.Trim('"'));
                    var ext = ".jpg";
                    var fullPath = Path.Combine(pathToSave, fileNameWithoutExt) + ext;
                    var dbPath = Path.Combine(folderName, fileNameWithoutExt) + ext;

                    using (var stream = photo.OpenReadStream())
                    {
                        using (var outputStream = Blur(stream))
                        {
                            using(var fileStream = System.IO.File.Create(fullPath))
                            {
                                outputStream.CopyTo(fileStream);
                            }
                        }
                    }

                    return Ok(new { dbPath });
                }
                catch (Exception ex)
                {
                    return StatusCode(500, $"Internal server error: {ex}");
                }
            }
            else
            {
                return BadRequest();
            }
        }

        private static Stream Blur(Stream stream)
        {
            var outputStream = new MemoryStream();
            using (var image = Image.Load(stream, new PngDecoder()))
            {
                image.Mutate(ctx =>
                {
                    ctx.GaussianBlur(35);
                });
                image.SaveAsJpeg(outputStream);
            }
            return outputStream;
        }
    }

谢谢 !

在 asp.net core 中搜索了一些模糊支持库后,我没有发现任何有用的东西。 所以这里有一个关于创建图像的模糊副本的演示,当然可以在没有任何第三方类库的情况下保存两个图像。 我只是使用console.app来测试,你只需要在api中上传文件时更改一点代码。

 static void Main(string[] args)
        {
            //When you upload the image, You can save the image in the specified path, Then read it. For testing convience, I just read the exciting file here.
            string path = @"xxxxxxxxxxxx";

            //set the path of output image
            string path2 = @"xxxxxxxxxxxxxxxx";
            Bitmap bitmap = new Bitmap(path);
            bitmap = Blur(bitmap, 10);
            bitmap.Save(path2);
        }

        private static Bitmap Blur(Bitmap image, Int32 blurSize)
        {
            return Blur(image, new Rectangle(0, 0, image.Width, image.Height), blurSize);
        }

        private unsafe static Bitmap Blur(Bitmap image, Rectangle rectangle, Int32 blurSize)
        {
            Bitmap blurred = new Bitmap(image.Width, image.Height);

            // make an exact copy of the bitmap provided
            using (Graphics graphics = Graphics.FromImage(blurred))
                graphics.DrawImage(image, new Rectangle(0, 0, image.Width, image.Height),
                    new Rectangle(0, 0, image.Width, image.Height), GraphicsUnit.Pixel);

            // Lock the bitmap's bits
            BitmapData blurredData = blurred.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, blurred.PixelFormat);

            // Get bits per pixel for current PixelFormat
            int bitsPerPixel = Image.GetPixelFormatSize(blurred.PixelFormat);

            // Get pointer to first line
            byte* scan0 = (byte*)blurredData.Scan0.ToPointer();

            // look at every pixel in the blur rectangle
            for (int xx = rectangle.X; xx < rectangle.X + rectangle.Width; xx++)
            {
                for (int yy = rectangle.Y; yy < rectangle.Y + rectangle.Height; yy++)
                {
                    int avgR = 0, avgG = 0, avgB = 0;
                    int blurPixelCount = 0;

                    // average the color of the red, green and blue for each pixel in the
                    // blur size while making sure you don't go outside the image bounds
                    for (int x = xx; (x < xx + blurSize && x < image.Width); x++)
                    {
                        for (int y = yy; (y < yy + blurSize && y < image.Height); y++)
                        {
                            // Get pointer to RGB
                            byte* data = scan0 + y * blurredData.Stride + x * bitsPerPixel / 8;

                            avgB += data[0]; // Blue
                            avgG += data[1]; // Green
                            avgR += data[2]; // Red

                            blurPixelCount++;
                        }
                    }

                    avgR = avgR / blurPixelCount;
                    avgG = avgG / blurPixelCount;
                    avgB = avgB / blurPixelCount;

                    // now that we know the average for the blur size, set each pixel to that color
                    for (int x = xx; x < xx + blurSize && x < image.Width && x < rectangle.Width; x++)
                    {
                        for (int y = yy; y < yy + blurSize && y < image.Height && y < rectangle.Height; y++)
                        {
                            // Get pointer to RGB
                            byte* data = scan0 + y * blurredData.Stride + x * bitsPerPixel / 8;

                            // Change values
                            data[0] = (byte)avgB;
                            data[1] = (byte)avgG;
                            data[2] = (byte)avgR;
                        }
                    }
                }
            }

            // Unlock the bits
            blurred.UnlockBits(blurredData);

            return blurred;
        }

如果您认为这些方法很慢,我认为您可以将它们放在后台服务中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM