使用 MagickImage 和 C# 调整图像大小并添加黑色背景

Resizing an image and adding black background using MagickImage and C#

我必须用 Magick Image 涵盖四种可能的情况:

  1. IF width or height of the image uploaded is less than 150 center the image and paint everything in the background in black

  2. Width > 150 and aspect ratio different from 1:1 crop image from both sides to cover 150px

  3. Height > 150 and aspect ratio different from 1:1 crop image from both sides to cover 150 px

  4. in all other cases resize to 150x150

我很难找到相关文档或任何信息。我正在尝试和错误。

我先画了所有案例的草图,然后我想将其实现到 C# 代码中

    public async Task<IActionResult> SetImageFroUser([FromRoute] string userId, [FromForm] byte[] avatar)
    {
        if (string.IsNullOrEmpty(userId) || avatar == null || avatar.Length == 0) return BadRequest();

        var user = await userManagerWrapper.FindByIdAsync(userId);

        if (user == null) return NotFound();

        // if (User == null || !User.IsInRole("Administrator")) return Forbid();
        if ((User == null || !User.IsInRole("Administrator")) && !user.Id.Equals(userId)) return Forbid();

        try
        {
            avatarManager.SetAvatar(user, new MemoryStream(avatar));
        }
        catch (MagickException)
        {
            return BadRequest("Invalid image format");
        }

        return NoContent();
    }

    public void SetAvatar(IntentUser user, Stream avatar)
    {
        using (var ms = new MemoryStream())
        {
            avatar.CopyTo(ms);
            ms.Seek(0, SeekOrigin.Begin);

            using MagickImage image = new MagickImage(ms);
            ms.Seek(0, SeekOrigin.Begin);
            ProcessImage(image.Width, image.Height, image);
            image.Write(ms, MagickFormat.Jpeg);

            var dbUser = database.Users.FirstOrDefault(u => u.Id == user.Id);
            if (dbUser == null)
            {
                throw new NotFoundException();
            }

            dbUser.Avatar = ms.ToArray();
            user.Avatar = dbUser.Avatar;
            database.SaveChanges();
        }
    }


    private void ProcessImage(int width, int height, MagickImage image)
    {
        double startPosition, endPosition;

    if (width < 150 && height < 150)
    {
        startPosition = 150 - width;
        endPosition = 150 - height;
        //center image
        image.Draw(new DrawableRectangle(startPosition / 2, endPosition / 2, startPosition / 2 + width, endPosition / 2 + height));

        image.Draw(new DrawableFillColor(MagickColors.Black));

        //rest of background is black
    }

    else if (width < 150 && height > 150)
    {
        startPosition = 150 - width;
        endPosition = height - 150;

        image.Draw(new DrawableRectangle(startPosition / 2, endPosition / 2, startPosition / 2 + width, endPosition / 2 + height));
        image.Draw(new DrawableFillColor(MagickColors.Black));
    }

    else if (width > 150 && height > 150 && width != height)
    {
        startPosition = width - 150;
        endPosition = height - 150;

        image.Draw(new DrawableRectangle(startPosition / 2, endPosition / 2, startPosition / 2 + width, endPosition / 2 + height));
        image.Draw(new DrawableFillColor(MagickColors.Black));
    }

    else if (width > 150 && height < 150)
    {
        startPosition = width - 150;
        endPosition = 150 - height;

        image.Draw(new DrawableRectangle(startPosition / 2, endPosition / 2, startPosition / 2 + width, endPosition / 2 + height));
        image.Draw(new DrawableFillColor(MagickColors.Black));
    }
    else
    {
        image.Resize(150, 150);

    }
    image.Strip();
    image.Quality = 75;
    }

这里是原图:

非常简单的解决方案。

我还添加了一个检查以保留图像的纵横比,这样它就不会被挤压:

var aspect_ratio = (decimal)image.Width / (decimal)image.Height;

    if (aspect_ratio > 1)
    {
         var newWidth = (int) Math.Round((decimal) (aspect_ratio * 150));
         image.Resize(newWidth, 150);
         // cut width and new width is multiply 150 by aspect ratio
    }

   else if (aspect_ratio < 1) 
   {
         //cut height and new height is multiply 150 by aspect ratio
         var newHeight = (int)Math.Round((decimal)((decimal)image.Height / (decimal)image.Width * 150));
         image.Resize(150, newHeight);
   }

   private void ProcessImage(MagickImage image, MemoryStream ms)
    {
        using var finalImage = new MagickImage(new MagickColor("#000000"), 150, 150);

        finalImage.Composite(image, Gravity.Center, CompositeOperator.Over);

        finalImage.Write(ms, MagickFormat.Jpg);

        image.Strip();
        image.Quality = 75;
    }

对于 ImageMagick 文档,请参考他们的 github: https://github.com/dlemstra/Magick.NET

如果您下载项目并打开文档,您可以看到文档 - 描述方法的注释,然后是方法中的逻辑。