I have to cover four possible scenarios with Magick Image
:
IF width or height of the image uploaded is less than 150 center the image and paint everything in the background in black
Width > 150 and aspect ratio different from 1:1 crop image from both sides to cover 150px
Height > 150 and aspect ratio different from 1:1 crop image from both sides to cover 150 px
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;
}
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.