简体   繁体   中英

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

I have to cover four possible scenarios with 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

I struggle to find documentation or any info on it. I am using trial and error.

I draw a sketch of all the cases first then I wanted to implement this into C# code

    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;
    }

输出图像 48x10px

And here is the original image:

在此处输入图片说明

Very simple solution.

Also I added a check to preserve the aspect of the image so it is not squeezed:

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;
    }

For ImageMagick doc refer to their github: https://github.com/dlemstra/Magick.NET

If you download the project and open docs you can see a documentation - comments that describe the methods and then the logic in the methods.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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