If you can use .NET 5, 6, or 7, use Imageflow.Server in place of ImageResizer. This readme is for ImageResizer 5.x for .NET Framework 4.x. Click for the ImageResizer 4.x, 3.x, or 2.x readme.
We've made some major changes in V5 to greatly improve image quality, file sizes, concurrency, maintainability, and response times. Read the changelog and follow suggestions in /resizer.debug
when migrating from V4.
Quick Start: Install the ImageResizer.WebConfig
NuGet package, run your app, then visit /resizer.debug
<picture>
and srcset
without leaving your IDE (bye, Photoshop).ImageResizer
includes an HttpModule for .NET Framework 4.7.2/4.8. ImageResizer.WebConfig
installs the HttpModule in Web.config.ImageResizer.Plugins.Imageflow
installs the Imageflow backend. Imageflow is what provides excellent image quality and file sizes, and is required for most image manipulation commands. If you're not using ASP.NET, you can use it directly via the Imageflow.Net
package.Imageflow.NativeRuntime.win-x86 (enable pre-release)
installs the 32-bit imageflow.dllImageflow.NativeRuntime.win-x86_64 (enable pre-release)
installs the 64-bit imageflow.dll. Keep this pacakge updated!ImageResizer.Plugins.AzureReader2
allows processing images located in Azure Blob storage.ImageResizer.Plugins.S3Reader2
allows processing images located in Amazon S3.ImageResizer.Plugins.HybridCache
is essential for scaling your website to high traffic. It offers an insanely well optimized, low latency disk cache with accurate space limiting. It replaces DiskCache and does everything better.ImageResizer.Storage
is useful for integrating ImageResizer with alternate image storage locations.ImageResizer has a very simple (and powerful) URL API.
For more information, check out the website.
Below is a basic installation guide, although a more comprehensive one can be found on our website.
Starting with ImageResizer v5, you'll want to avoid nuget.packages and use the ProjectReference format instead in your projects.
PM> Install-Package Imageflow.NativeRuntime.win-x86 -pre
PM> Install-Package Imageflow.NativeRuntime.win-x86_64 -pre
In V5, ImageResizer rolled the vast majority of plugin features into ImageResizer.Plugins.Imageflow. That's why so many plugins are deprecated; they're duplicating Imageflow functionality.
Nearly all ImageResizer plugins are on NuGet. You can enable source symbols from symbolsource.org for an enhanced debugging experience.
Get the basics:
PM> Install-Package ImageResizer.WebConfig
PM> Install-Package ImageResizer.Plugins.Imageflow
PM> Install-Package Imageflow.NativeRuntime.win-x86 -pre
PM> Install-Package Imageflow.NativeRuntime.win-x86_64 -pre
PM> Install-Package ImageResizer.Plugins.HybridCache
<add name="PluginName" />
Application_Start
, create an instance of the plugin and install it. new PluginName().Install(ImageResizer.Configuration.Config.Current);
You will need to add the appropriate namespace reference to access the plugin.
Most configuration and plugin installation issues can be resolved by checking ImageResizer’s self-diagnostics page. If your local website is running at http://localhost:5000/
, then you should browse to http://localhost:5000/resizer.debug.ashx
to access it. See [the Troubleshooting](#troubleshooting section) for more details.
The following is a list of all plugins currently available on ImageResizer, and links to their more detailed documentation on our website. They are grouped according to the license necessary to access them. Higher level licenses include all plugins from lower level licenses. Their order, from lowest to highest, is Essential, Performance, Creative, Elite. If you have any further questions about ImageResizer licenses, we encourage you to look at our licenses page.
scale
) are omitted.Please note that width/height/maxwidth/maxheight do NOT include border, margin, or padding widths, and do not include the extra space used by rotation. They constrain the image, not the canvas.
1
for impressionist, 100
for modern art :)These act as fallback decoders, but you can tell them to try first by using
In addition to jpeg quality and gif/png colors, you can configure the jpeg subsampling for both Wic and FreeImage.
Most tasks with the managed API only require one line:
ImageResizer.ImageBuilder.Current.Build(object source, object dest, ResizeSettings settings)
or
Bitmap b = ImageResizer.ImageBuilder.Current.Build(object source, ResizeSettings settings)
May be a physical path (C:..), an app-relative virtual path (~/folder/image.jpg), an Image, Bitmap, Stream, VirtualFile, or HttpPostedFile instance.
May be a Stream instance, a physical path, or an app-relative virtual path.
ResizeSettings is a friendly wrapper for a query string which provides named properties as well as the regular NameValueCollection interface.
You can create one like so:
new ResizeSettings("maxwidth=200&maxheight=200")
//or
new ResizeSettings(Request.QueryString)
//or
var r = new ResizeSettings();
r.MaxWidth = 200;
r.MaxHeight = 300;
using ImageResizer;
//Converts a jpeg into a png
ImageBuilder.Current.Build("~/images/photo.jpg","~/images/photo.png",
new ResizeSettings("format=png"));
//Crops to a square (in place)
ImageBuilder.Current.Build("~/images/photo.jpg","~/images/photo.jpg",
new ResizeSettings("width=100&height=200&crop=auto"));
Variables include the correct extension
This makes many scenarios much easier to code, and reduces room for error. Many users make critical errors in their upload code, such as not sanitizing filenames, or using the original extension (immediate server highjacking, here we go).
With the new feature, a proper upload system is 3 lines:
ImageJob i = new ImageJob(file,
"~/uploads/<guid>.<ext>",
new ResizeSettings("width=1600"));
i.CreateParentDirectory = true;
i.Build();
You can also filter values. <filename:A-Za-z0-9>
keeps only the alphanumeric characters from the original filename.
The following is a basic, typical configuration of v4.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="resizer" type="ImageResizer.ResizerSection,ImageResizer" requirePermission="false" />
</configSections>
<resizer>
<!-- Unless you (a) use Integrated mode, or (b) map all requests to ASP.NET,
you'll need to add .ashx to your image URLs: image.jpg.ashx?width=200&height=20
Optional - this is the default setting -->
<pipeline fakeExtensions=".ashx" defaultCommands="autorotate.default=true" />
<plugins>
<add name="DiskCache" />
<add name="PrettyGifs" />
</plugins>
</resizer>
<system.web>
<httpModules>
<!-- This is for IIS7/8 Classic and Cassini-->
<add name="ImageResizingModule" type="ImageResizer.InterceptModule"/>
</httpModules>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules>
<!-- This is for IIS7/8 Integrated mode -->
<add name="ImageResizingModule" type="ImageResizer.InterceptModule"/>
</modules>
</system.webServer>
</configuration>
The PostRewrite event is the last of the URL rewriting events, and can be used to enforce certain settings.
You can add an event handler during the Application\Start method in Global.asax.cs.
The following sample code applies a watermark to all images inside 'folder' that are probably above 100x100. I say probably, because the size estimation is based on the assumption that the original image is a 600x600 square. Given a 600x100 actual image size and the querystring "?height=99", the image could escape watermarking and display at 594x99.
So, with this code, you can only know that one of the dimensions will be less than 100px - you can't know that both will be.
Config.Current.Pipeline.PostRewrite += delegate(IHttpModule sender, HttpContext context, IUrlEventArgs ev) {
//Check folder
string folder = VirtualPathUtility.ToAbsolute("~/folder");
if (ev.VirtualPath.StartsWith(folder, StringComparison.OrdinalIgnoreCase)) {
//Estimate final image size, based on the original image being 600x600.
Size estimatedSize = ImageBuilder.Current.GetFinalSize(new System.Drawing.Size(600,600),
new ResizeSettings(ev.QueryString));
if (estimatedSize.Width > 100 || estimatedSize.Height > 100){
//It's over 100px, apply watermark
ev.QueryString["watermark"] = "Sun_256.png";
}
}
};
While the above enforces watermarking on all processed images, the process=no
command can disable processing of the image completely, avoiding all resizing and watermarking.
To prevent this, you should add some more code inside PostRewrite
Config.Current.Pipeline.PostRewrite += delegate(IHttpModule sender, HttpContext context, IUrlEventArgs ev) {
//Check folder
string folder = VirtualPathUtility.ToAbsolute("~/folder");
if (ev.VirtualPath.StartsWith(folder, StringComparison.OrdinalIgnoreCase)) {
//Estimate final image size, based on the original image being 600x600.
Size estimatedSize = ImageBuilder.Current.GetFinalSize(new System.Drawing.Size(600,600),
new ResizeSettings(ev.QueryString));
if (estimatedSize.Width > 100 || estimatedSize.Height > 100){
//It's over 100px, apply watermark
ev.QueryString["watermark"] = "Sun_256.png";
//Force processing if it's an image
if (Config.Current.Pipeline.IsAcceptedImageType(ev.VirtualPath))
ev.QueryString["process"] = "Always";
}
}
};
While the ImageResizer shines at on-the-fly image processing, you can also use it to drastically simplify pre-processing and ahead-of-time resizing as well. We strongly recommend using the dynamic method instead of pre-generating your images, as pre-generating versions reduces agility and flexibility. In the examples below, only one line is required to perform all the image decoding, format conversion, processing, resizing, and re-encoding. The rest is path/filename logic. Two different solutions are presented - 1 for processing images as they are uploaded, and another for processing images that are already saved to disk.
This method generates 3 versions of an image as it is uploaded, adding a _thumb, _medium, and _large suffix to each filename. Uploaded files are named using a generated GUID, as uploaded file names are never safe for use as-is. Even with proper sanitization (alphanumeric filtering AND length limiting), you will encounter duplicates using uploaded filenames on your server.
Dictionary<string, string> versions = new Dictionary<string, string>();
//Define the versions to generate
versions.Add("_thumb", "width=100&height=100&crop=auto&format=jpg"); //Crop to square thumbnail
versions.Add("_medium", "maxwidth=400&maxheight=400&format=jpg"); //Fit inside 400x400 area, jpeg
versions.Add("_large", "maxwidth=1900&maxheight=1900&format=jpg"); //Fit inside 1900x1200 area
//Loop through each uploaded file
foreach (string fileKey in HttpContext.Current.Request.Files.Keys) {
HttpPostedFile file = HttpContext.Current.Request.Files[fileKey];
if (file.ContentLength <= 0) continue; //Skip unused file controls.
//Get the physical path for the uploads folder and make sure it exists
string uploadFolder = MapPath("~/uploads");
if (!Directory.Exists(uploadFolder)) Directory.CreateDirectory(uploadFolder);
//Generate each version
foreach (string suffix in versions.Keys) {
//Generate a filename (GUIDs are best).
string fileName = Path.Combine(uploadFolder, System.Guid.NewGuid().ToString() + suffix);
//Let the image builder add the correct extension based on the output file type
fileName = ImageBuilder.Current.Build(file, fileName, new ResizeSettings(versions[suffix]), false, true);
}
}
This example method generates 3 versions of the specified file, and returns a list of the final path names.
For example,
GenerateVersions("~/images/image.jpg")
Will generate
/images/image\_thumb.jpg
/images/image\_medium.jpg
/images/image\_large.jpg
And will return a list of those paths.
public IList<string> GenerateVersions(string original) {
Dictionary<string, string> versions = new Dictionary<string, string>();
//Define the versions to generate and their filename suffixes.
versions.Add("_thumb", "width=100&height=100&crop=auto&format=jpg"); //Crop to square
versions.Add("_medium", "maxwidth=400&maxheight=400format=jpg"); //Fit inside 400x400
versions.Add("_large", "maxwidth=1900&maxheight=1900&format=jpg"); //Fit inside 1900x1200
string basePath = ImageResizer.Util.PathUtils.RemoveExtension(original);
//To store the list of generated paths
List<string> generatedFiles = new List<string>();
//Generate each version
foreach (string suffix in versions.Keys)
//Let the image builder add the correct extension based on the output file type
generatedFiles.Add(ImageBuilder.Current.Build(original, basePath + suffix,
new ResizeSettings(versions[suffix]), false, true));
return generatedFiles;
}
Resizing and processing images as they are uploaded is very straightforward. Most of the required code is about paths and directories.
The following sample code generates a GUID filename for each upload, determines the appropriate file extension that is needed, then resizes/crops/formats the image according to the specified ResizeSettings.
//Loop through each uploaded file
foreach (string fileKey in HttpContext.Current.Request.Files.Keys)
{
HttpPostedFile file = HttpContext.Current.Request.Files[fileKey];
if (file.ContentLength <= 0) continue; //Skip unused file controls.
//The resizing settings can specify any of 30 commands.. See http://imageresizing.net for details.
//Destination paths can have variables like <guid> and <ext>, or
//even a santizied version of the original filename, like <filename:A-Za-z0-9>
ImageResizer.ImageJob i = new ImageResizer.ImageJob(file, "~/uploads/<guid>.<ext>", new ImageResizer.ResizeSettings(
"width=2000;height=2000;format=jpg;mode=max"));
i.CreateParentDirectory = true; //Auto-create the uploads directory.
i.Build();
}
'Loop through each uploaded file
For Each fileKey As String In HttpContext.Current.Request.Files.Keys
Dim file As HttpPostedFile = HttpContext.Current.Request.Files(fileKey)
If (file.ContentLength > 0) Then 'Skip unused file controls.
'The resizing settings can specify any of 30 commands.. See http://imageresizing.net for details.
'Destination paths can have variables like <guid> and <ext>, or
'even a santizied version of the original filename, like <filename:A-Za-z0-9>
Dim i As ImageResizer.ImageJob = New ImageResizer.ImageJob(file, "~/uploads/<guid>.<ext>", New ImageResizer.ResizeSettings("width=2000;height=2000;format=jpg;mode=max"))
i.CreateParentDirectory = True 'Auto-create the uploads directory.
i.Build()
End If
Next
If some images are not displaying correctly, you must visit the image url directly to get the exact error message.
The image URL is not the same as the page URL; viewing the broken image icons on the parent page doesn't tell us anything useful.
If you do not get a specific error message, you must enable detailed error messages on your ASP.NET site.
If you have local access to the server, you can set the customErrors mode to RemoteOnly and access the URLs using "localhost".
Otherwise, you may need to temporarily set customErrors to "Off", so you can get error messages from a remote location. Temporarily is the key word! Detailed error messages are considered a security risk and have enabled certain types of attacks to function. They should not be enabled for more than a few hours at most on a publicly accessible server.
You may also have to temporarily change <deployment retail to "False" for the customErrors setting to take effect.
The customErrors setting is case-sensitive; use "Off", "On", and "RemoteOnly".
Most configuration and plugin installation issues can be resolved by checking ImageResizer’s self-diagnostics page. If your local website is running at http://localhost:5000/
, then you can visit it at http://localhost:5000/resizer.debug.ashx
.
If you’re not using ImageResizer from a web app, you can access the page as a string via ImageResizer.Configuration.Config.Current.GetDiagnosticsPage()
or write it to disk with ImageResizer.Configuration.Config.Current.WriteDiagnosticsTo(string path)
.
By default, the Diagnostics plugin uses the same setting as customErrors (which defaults to Localhost). Thus, if you can see ASP.NET error messages, you will also be able to get the diagnostics page. This ensures that the diagnostics page never exposes data to a host that doesn't already have access to detailed error messages.
To override, add one of the following to the <resizer> section.
<diagnostics enableFor="AllHosts" />
<diagnostics enableFor="Localhost" />
<diagnostics enableFor="None" />
To get support or use this guide, make sure you get the detailed error message from visiting the image URL directly. This guide cannot offer a solution to a generic 500 error, 404 error, or a "broken image icon", as those symptoms are far too generic to be useful. The troubleshooting tips presented here are specific to v4. Switch to the v3 troubleshooting page if you are using v3.
If this page doesn't resolve your issue, visit the Support page for information about the bug bounty and free support requirements.
You might be trying to resize certain large images for the first time. Even a 15MB jpg, however, uncompresses to about 80MB in bitmap form (depending on the compression level). If you are resizing to a 2MB jpg (15MB BMP), memory requirements for the operation are roughly 110MB (15 + 80 + 15). If you plan on using ImageResizer for very high-resolution photos (above 8MP), we suggest making sure you have ample amounts of RAM. 400MB to 1GB is usually plenty for the average web site with disk caching enabled.
Potential causes:
<remove />
statements in the child Web.config to cancel out the inherited <add />
statements from the parent Web.config. Option (c) will disable image resizing within the sub-application.When using the ImageResizer from a .NET project that is not a web project you may get the following build error:
The type or namespace name "ImageResizer" could not be found (are you missing a using directive or assembly reference?)
This is caused by using a Client Profile version of .NET instead of the Full version. You can change this in Project Properties -> Application -> Target Framework. The ImageResizer requires the full version, as it is also designed to support ASP.NET usage and references the System.Web assembly (which is not part of the client profile version of .NET).
Potential causes:
&scale=both
(The default behavior is to never upscale images, but this can be changed).Potential causes:
Description: The type of page you have requested is not served because it has been explicitly forbidden. The extension '.jpg' may be incorrect. Please review the URL below and make sure that it is spelled correctly.
Possible causes
This generic error message often hides a more descriptive message, but that message is always guaranteed to be a "Not Authorized To View this Content" kind of error.
Server object error 'ASP 0178 : 80070005' Server.CreateObject Access Error The call to Server.CreateObject failed while checking permissions. Access is denied to this object.
This error usually means that the user that the ASP website is running under does not have NTFS permissions to the ImageResizer dlls.
Right click the C:\Program Files\ImageResizingNet\v3
folder and choose Properties, Security, hit Edit, then click Add, type in the user name your website is running under, hit OK, then check Read & Execute, and hit OK, then Apply.
On IIS6, this account is typically IUSR_ComputerName, but on IIS7, the account is usually NETWORK SERVICE
or (if you're not use a default app pool), a custom user account. You'll need to open IIS and inspect the appropriate Application Pool to find out which account you need to give permissions to.
If that fails, providing Readonly access to the Everyone group should work, but that may not be acceptable if you have highly-isolated application pools which you don't want to be able to access the ImageResizer dlls files.
If you still encounter issues, perform a reinstall with COMInstaller.exe, and save the install log. If the reinstall doesn't fix the problem, send the install log to support@imageresizing.net to get help with your issue.
This is a known bug in GDI+. GDI+ opens 8-bit grayscale Jpeg images as 4-bit images. Here's the bug report at Microsoft Connect.
The workaround is to use WIC or FreeImage for these requests. Any of the following plugins will solve the problem
&decoder=wic
to affected URLs. (best quality)&builder=wic
to affected URLs. Faster, but slightly lower quality than #1 (nearly imperceptible)&decoder=freeimage
&builder=freeimage
. Slowest, but highest quality.
with builder=freeimage
or builder=wic
This is tricky to get right - read the full article here.
You must have the PrettyGifs plugin installed to get high-quality, transparent GIF and 8-bit PNG results. You may also want the AnimatedGifs plugin.
By default, ImageResizer limits the output size of images to 3200x3200. This can be changed by configuring (or removing) the SizeLimiting plugin.
The short version: ImageResizer has several license packages that have different tiers of access to our plugins, including free packages in our essential and trial packages. To find out about our license packages, visit our website.
We also offer email support plans and custom support contracts. Contact us at sales@imazen.io to learn more.
We can be reached at support@imazen.io. We usually respond within 2 or 3 business days. Of course, you could also check out StackOverflow, where over 500 ImageResizer questions have been answered.