NuGet Package of the Week: ImageProcessor - lightweight image manipulation in C#
I really enjoy image manipulation in code. Sure, resizing photos is fun in Photoshop, but there's something viscerally enjoyable when you change images with your own code.
I've talked about image resizing libraries like ImageResizer before, but there's certainly room for more than one. Today I want to showcase ImageProcessor, an open source "collection of lightweight libraries written in C# that allows you to manipulate images on-the-fly using .NET 4+." ImageProcessor is available on GitHub.
ImageProcessor methods include; Resize, Rotate, Rounded Corners, Flip, Crop, Watermark, Filter, Saturation, Brightness, Contrast, Quality, Format, Vignette, Gaussian Blur, Gaussian Sharpen, and Transparency.
ImageProcessor has a notable number of configuration options for web apps, and a supporting ImageProcessor.Web package as well. It's an impressive body of work.
I like this simple example of loading, resizing, and saving an image with their fluent API:
// Read a file and resize it.
byte[] photoBytes = File.ReadAllBytes(file);
int quality = 70;
ImageFormat format = ImageFormat.Jpeg;
Size size = new Size(150, 0)
using (MemoryStream inStream = new MemoryStream(photoBytes))
{
using (MemoryStream outStream = new MemoryStream())
{
using (ImageFactory imageFactory = new ImageFactory())
{
// Load, resize, set the format and quality and save an image.
imageFactory.Load(inStream)
.Resize(size)
.Format(format)
.Quality(quality)
.Save(outStream);
}
// Do something with the stream.
}
}
You can easily chain functions with the API, like tinting and constraning:
imageFactory.Load(inStream)
.Constrain(size)
.Tint(Color.FromArgb(255, 106, 166, 204))
.Format(format)
.Save(outStream);
When you add ImageProcessor.Web it adds caching that takes pressure off your web servers. You can easily add HttpHandlers to watermark an image, for example, and cache the result.
This is a library that has as a lot of potential. Since it's open source, I'm sure they'd appreciate help from the community! Personally, I think they could use more Unit Tests and more examples.
Head over to https://github.com/JimBobSquarePants/ImageProcessor and star this project! Get involved, file issues, and contribute! http://imageprocessor.org/
Related Links
- Accessing EXIF Photo Data from JPEGs with PowerShell
- NuGet Package of Week #11 - ImageResizer enables clean, clear image resizing in ASP.NET
- Back to Basics: Dynamic Image Generation, ASP.NET Controllers, Routing, IHttpHandlers
Sponsor: Many thanks to Izenda for sponsoring the blog feed this week. Please do check out their Intuitive Ad Hoc Reporting with Stunning Visualizations - Embed real time dashboards into your ASP.NET applications for easy, custom reports across all devices. Download a FREE TRIAL of Izenda Today!
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
Umbraco now incorporates this functionality by default for it's image cropper, and there's no drama at all from a performance point of view...
This wrapper can be used to create strongly typed ImageProcessor URLs, so you don't have to look-up the URL querystring parameters you want to use :-)
Classes within the System.Drawing namespace are not supported for use within a Windows or ASP.NET service.
Attempting to use these classes from within one of these application types may produce unexpected problems,
such as diminished service performance and run-time exceptions.
Damien, that message on the documentation doesn't actually mean what you, or I when I first read it, think it does; it's actually a lot less severe. There's an explanation here from Cheryl Simmons, the person who added the statement to the documentation.
http://blogs.msdn.com/b/winformsue/archive/2007/05/14/what-does-not-supported-mean.aspx
I've worked incredibly hard to ensure that the libraries not only work but are efficient also. I use it in every site I work on without issue and as Robert said, Umbraco use it in every install of their CMS. It's well tested.
That said...
I would love to get a v2 going which would be truly cross platform (Sorry Denis, not yet), to do that I'd probably have to shift things across to using the WritableBitmap class.
I can't do all that on my own though.
Scott's right. I would definitely appreciate and would most welcome contributions from the community. It's essentially a one man show and it takes up an insane amount of my time. I need help writing unit tests (I know sorry), updating documentation, people to test the libraries across operating systems and devices, sense check some of my code, and a whole bunch of other stuff.
I'm totally committed to open source and I'd really like to build something special that will make our collective developer lives a little bit easier.
Thanks again Scott for sharing my work. You're an absolute legend!
Therefore I assume the license should be Microsoft Public License (Ms-PL) as this says:
(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution.
Btw, chaining using syntax is more elegant syntax IMHO:
using (MemoryStream inStream = new MemoryStream(photoBytes))
using (MemoryStream outStream = new MemoryStream())
using (ImageFactory imageFactory = new ImageFactory()) {
...
}
I really enjoy your posts on these nuget nuggets (yes, pun intended). What would make them even more awesome would be some way to see where (on what platforms) the package can be used.
in this case the author of the package already clearly detailed this, but I hope you can take my suggestion for the next package you highlight (and the next and the next and the...)
Keep up the good work!
For example please compare
http://dotnetimageprocessor.codeplex.com/SourceControl/latest#Main/ImageProcessor/Filters/OctreeQuantizer.cs
With
https://github.com/JimBobSquarePants/ImageProcessor/blob/master/src/ImageProcessor/Imaging/OctreeQuantizer.cs
Compare methods in source they are (at least today) all methods completely identical down to all the comments !
http://codebetter.com/brendantompkins/2007/06/14/gif-image-color-quantizer-now-with-safe-goodness/
I've had a look at the other library. I hadn't heard of it before you commented. Our methodologies are entirely different, the process is entirely different. The only thing in common is that they both share the name ImageProcessor, which considering the name describes the function is not remarkable.
Don't be a that kind of person. I've tried to do something that is for the benefit of the community, something free that always will be. I've worked incredibly hard in order to do so and it's really quite unpleasant to read someone attacking me. Use my work if you want to, don't if you don't but don't question my integrity or belittle my effort.
Sent by the department of veteran affairs.
I was just looking for your code because of scotts post and the similar name led me to navigate to the codeplex project.
Then something very unlikely happened: I intuitively browsed to the files Quantizer.cs and OctreeQuantizer.cs in both projects and saw this very high similarity.
Possibly you can understand my assumption. I should have compared much more! So please excuse my blame!
Great work, I will certainly use this!
Regards,
I use Image Magick because it's the only solution that maintains quality and also keeps colour profiles of photos exported from Photoshop preventing it from losing colour.
Then I tried Azure Websites. Oh dear.
You really can't use System.Drawing reliably on Azure Websites - so there might be a problem for this library in that context - has anyone tried it? (Other flavours of Azure do not have this problem)
@Thomas Thanks! That's excellent. I'll merge, test and if everything is ok I'll make sure it is in the next release.
@Tez, thanks for your support, I think it was just a misunderstanding.
@Phillip I use the Image.FromStream Method (Stream, Boolean) which is supposed to preserve any embedded colour information. I haven't noticed any discernible colour loss in my tests. Other than that I don't know right now.
@Rizwan thanks :)
@Will Azure Websites don't seem to support GDI+ so unfortunately not in this instance. I can't seem to find any details on whether they support WIC.
@Ben, Thanks, I worked hard to ensure that streams were getting preserved and what should be getting disposed was getting so at the correct point. Part of my reason for writing the library was seeing so many developers get working with System.Drawing so wrong. Lot's of poor examples on blogs all over the internet.
Scott recommending a library which won't actually run on his department's favourite platform could be just what's needed to get it sorted out.
Scott, could we have a nice piece about IPv6 next, please... ;-)
I guess you've just been lucky enough to avoid the broken bits. (Or perhaps the broken bits are very few, but I've been unlucky to hit them the moment I started looking at Azure...)
Unfortunately I've been unable to find any coherent guidance from MS on what the problem is - various discussion threads around the place mostly read like some kind of Onion-style parody of an MS Connect thread...
@Jeff I wasn't aware of this issue. (I don't own any apple products to test with). ImageProcessor at present discards the EXIF data (to keep sizes small) so yeah, it will get rotated. Turns out Windows Explorer and Picture viewer in 7 and below ignored it also.
I've been pondering adding the ability to copy over the data with an overload to the ImageFactory class. I think it's a necessity now. Would you care to raise it as an issue on my github page?
So as long as we don't call stuff which implicitly refers to a screen DC, then we should get a bit further. It may well be that Fonts are the main culprit here (I see other references to the screenDC in the Font.cs) which is why it's not a problem for your library.
Thanks for unwittingly providing the impetus to look into this more!
You'll be happy to no I've just released an updated version which now supports EXIF metadata preservation. I've also switched the build to use the client profile.
I'm working hard to improve the documentation also.
Check it out! http://imageprocessor.org/
I have literally just finished integrating this in to my site and its perfect, only thing I need to do now is set the orientation because some images it uploads tend to flip from vertical to horizontal not 100% why its doing that but I shall find out :)
Comments are closed.