I am using the following to resize images:
public interface IImageService
{
byte[] ResizeImage(byte[] imageBytes, ImageFormat format, int thumbnailWidth = 150, bool autoRotate = false);
}
public ImageService : IImageService
{
public byte[] ResizeImage(byte[] imageBytes, ImageFormat format, int thumbnailWidth = 150, bool autoRotate = false)
{
byte[] outputBytes = null;
using (var outStream = new MemoryStream())
{
new ImageResizer.Plugins.Basic.AutoRotate().Install(Config.Current);
var r = new ResizeSettings { Width = thumbnailWidth, Quality = 90, Mode = FitMode.Max };
r.Add("autorotate", "true");
ImageBuilder.Current.Build(imageBytes, outStream, r);
outputBytes = outStream.ToArray();
}
return outputBytes;
}
}
The code works, but the API leaves my code looking unpleasant, namely, the lines:
new ImageResizer.Plugins.Basic.AutoRotate().Install(Config.Current);
and:
ImageBuilder.Current.Build(imageBytes, outStream, r);
As you can see, I've wrapped the entire method in a class and interface so I can unit test my other code without these dependencies, but still it looks nasty.
Is there a nicer way to do this?
From perspective of the SOLID principles, what you're doing looks fine, because:
So from a design and maintainability perspective, I would say what you're doing is very good.
You have some concerns about the code inside this class. I don't see a problem here. Yes, I agree, the API that ImageResizer exposes is ugly, but there's not much you can do about this - nor should do. You have elegantly abstracted away this ugly API from your application. Your interface is the port and the ImageService
is the adapter between your application and ImageResizer. So it has to deal with the ImageResizer API. You could try abstracting away this again, but that would be weird, and only lead to code that is more complex, because you would expect this class to be the only class in the system that needs a dependency on ImageResizer.
Still though, what I find weird is the new AutoRotate().Install(Config.Current)
call; especially doing this during every call! I know nothing about ImageResizer, so this might be needed, but I my first intuition would be to move this code to a static constructor, to allow it to be called just once for the app domain.