<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Nathanael Jones &#187; image resizer</title>
	<atom:link href="http://nathanaeljones.com/tag/image-resizer/feed/" rel="self" type="application/rss+xml" />
	<link>http://nathanaeljones.com</link>
	<description>Ramblings of a computer linguist</description>
	<lastBuildDate>Mon, 04 Jan 2010 21:12:43 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Demo Version of Image Resizing Module</title>
		<link>http://nathanaeljones.com/199/demo-version-of-image-resizing-module/</link>
		<comments>http://nathanaeljones.com/199/demo-version-of-image-resizing-module/#comments</comments>
		<pubDate>Thu, 21 May 2009 16:00:35 +0000</pubDate>
		<dc:creator>Nathanael Jones</dc:creator>
				<category><![CDATA[Image Resizing]]></category>
		<category><![CDATA[image resizer]]></category>

		<guid isPermaLink="false">http://66.29.219.39/?p=199</guid>
		<description><![CDATA[I've received many requests for a 'trial' version of the image resizer. This demo version is fully-functional, but watermarks 50% of the generated images with "Unlicensed".]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve received many requests for a &#8216;trial&#8217; of the <a href="/products/asp-net-image-resizer/">image resizer</a>. This demo version is fully-functional, but watermarks 50% of the generated images with &#8220;Unlicensed&#8221;. Another note: the trial version includes supports resizing animated GIFs. That plug-in isn&#8217;t included in the default version; contact me for details.</p>
<p>Installation is the <a href="/11141_Image_Resizer_Installation">same as for the full version</a>.</p>
<p><a onclick="javascript:pageTracker._trackPageview('/download/resizertrial');" href="/wp-content/uploads/2009/11/ImageResizer2.1b-Nov-3-09-Trial-Version.zip">Download Trial version and sample project (4MB)</a></p>
<p>When you upgrade to the full version, remember to delete the <em>imagecache</em> directory, or you will continue to see the word &#8220;Unlicensed&#8221; on old pictures.</p>
]]></content:encoded>
			<wfw:commentRss>http://nathanaeljones.com/199/demo-version-of-image-resizing-module/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>20 Image Resizing Pitfalls</title>
		<link>http://nathanaeljones.com/163/20-image-resizing-pitfalls/</link>
		<comments>http://nathanaeljones.com/163/20-image-resizing-pitfalls/#comments</comments>
		<pubDate>Tue, 19 May 2009 15:18:49 +0000</pubDate>
		<dc:creator>Nathanael Jones</dc:creator>
				<category><![CDATA[Image Resizing]]></category>
		<category><![CDATA[image resizer]]></category>

		<guid isPermaLink="false">http://66.29.219.39/?p=163</guid>
		<description><![CDATA[Dozens of articles on server-side image resizing have been written. If we count other tongues, maybe hundreds. These contributions to the community have been invaluable to me, and I truly appreciate the time each author spent to share his or her knowledge.]]></description>
			<content:encoded><![CDATA[<p>
        Dozens of articles on server-side image resizing have been written. If we count other tongues, maybe hundreds. These contributions to the community<br />
        have been invaluable to me, and I truly appreciate the time each author spent to share his or her knowledge.</p>
<p>
        So why am I writing another? </p>
<p>
        Because each article I have read includes one of the errors below, leading readers to write either<br />
        slow, insecure, or incorrectly functioning code.  I have discovered many of these pitfalls the hard way.<br />
         I hope others won&#8217;t have to.
         </p>
<p>Instead of giving step-by-step instructions, this article will simply list pitfalls and the alternatives. I hope to publish my approach in a Part 2.</p>
<h2>
        Security and Performance Pitfalls</h2>
<ol class="normallist">
<li>Not using using(){}. You *must* wrap your Graphics, Bitmap, and MemoryStream objects<br />
            in a using(){} clause, or else they will not get cleaned out of memory for a while.<br />
            Under load this can cause *serious* issues. Read<br />
            <a href="http://blogs.msdn.com/tess/archive/2009/02/03/net-memory-leak-to-dispose-or-not-to-dispose-that-s-the-1-gb-question.aspx"><br />
                <em>to dispose, or not to dispose, that&#8217;s the 1GB question</em></a> if you have<br />
            any doubts regarding the severity of this error.</p>
<p>If you find yourself nesting a lot of using(){} statements, you can also use equivalent try{}finally{} code.</p>
<pre name="code" class="brush:c-sharp">
//Using method. object must implement IDisposable for this to work
using (object a = new object())
{
    using (object b = new object())
    {
        using (object c = new object())
        {

        }
    }
}

//Try finally method
object a = null;
object b = null;
object c = null;
try
{
    a = new object();
    b = new object();
    c = new object();
}
finally
{
    if (a != null) a.Dispose(); //If one of the Dispose methods throws an error, the others will not execute.
    if (b != null) b.Dispose(); //So there is an advantage to using nested using(){} clauses
    if (c != null) c.Dispose(); //You could nest try{} finally{ try{} finally{ try{} finally{}}} to solve that...
    //Two different techniques - take your pick
}
</pre>
</li>
<li>Using on-the-fly image resizing <em>without</em> disk caching! The ASP.NET<br />
            memory cache won&#8217;t cut it here folks &#8211; it gets cleaned out every application reboot,<br />
            and besides, you probably have more images than RAM. Resizing an image is fast,<br />
            but it will still flood the CPU if a single user browses a single page with 20 or more<br />
            resized images on it. This is a do-it-yourself <a href="http://en.wikipedia.org/wiki/Denial-of-service_attack"><br />
                DOS</a> attack. On-the-fly resizing is fine if you have disk caching. </li>
<li><em>Not</em> using on-the-fly resizing. This one bites also. If you decide to convert all<br />
            your images up-front, please realize how difficult it will be to track down the<br />
            originals and resizing them again next time you make a resolution jump. I&#8217;ve been<br />
            through this enough, and it&#8217;s painful &#8211; that&#8217;s why I wrote a dynamic image resizer!
        </li>
<li>Disk-caching without checking for updated (or reverted!) source files. Debugging<br />
            a resized image that won&#8217;t update can eat up lots of time. Make sure you set the<br />
            LastWriteTimeUTC on your cached images to match the source image file (and check<br />
            they match) &#8211; don&#8217;t simply check to see if the source file is newer than the cached<br />
            file, since that will break if you copy an older file over a source image. Always<br />
            use something like RoughCompare() to compare filesystem dates &#8211; *never* inequalities.<br />
            Remember that filesystem dates are less precise than DateTime, and get rounded.</p>
<pre name="code" class="brush:c-sharp">
/// &lt;summary&gt;
/// Returns true if both dates are equal (to the nearest 200th of a second)
/// &lt;/summary&gt;
/// &lt;param name=&quot;modifiedOn&quot;&gt;&lt;/param&gt;
/// &lt;param name=&quot;dateTime&quot;&gt;&lt;/param&gt;
/// &lt;returns&gt;&lt;/returns&gt;
private static bool RoughCompare(DateTime d1, DateTime d2)
{
	return (new TimeSpan((long)Math.Abs(d1.Ticks - d2.Ticks)).Milliseconds &lt;= 5);
}
</pre>
</li>
<li>Disk-caching without cleanup! Another do-it-yourself <a href="http://en.wikipedia.org/wiki/Denial-of-service_attack"><br />
            DOS</a> attack, although not quite as bad as the first. Left unchecked, your cache<br />
            directory could grow very large over a few years as orphaned<br />
            image versions accumulate. If a malicious visitor realizes that you have automatic resizing,<br />
            he could try to fill up your hard drive by requesting an endless variety of resolutions<br />
            for a given image. Of course, security-conscious developers will have cache-limiting<br />
            systems in place. I suggest cleaning out the least recently used 10-20% of the cache<br />
            directory whenever the file limit is reached. Handle locked files gracefully.</li>
<li>Checking the cache size for cleanup every image request. This will swamp your I/O.<br />
        Instead of running that directory listing each time, keep a static counter that  tracks how many <em>new</em> images have been resized<br />
        since the application started. Run the cache cleanup on the first image request and each time the counter passes the cleanup threshold.</li>
<li>Disk caching without protecting the cache directory. Unless you want anonymous users to potentially view the same images<br />
        as authorized users, you need your cache directory locked down. A Web.config file in the directory can do this &#8211; just verify your URL rewriting rules<br />
        don&#8217;t leave another way to access the directory. </p>
<p>
        The cache directory needs to stay inside the application to permit request rewriting to the cached files.  </p>
</li>
<li>Disk caching without proper locking code. This is a minor problem, since the<br />
            consequences are light &#8211; but it is good to remember that 2 image requests for the<br />
            same image size could happen at the same time, and (if they aren&#8217;t cached), they<br />
            may conflict when trying to write to the same file at the same time. You&#8217;ll probably<br />
            get a &#8220;The process cannot access the file because it is being used by another process.&#8221;<br />
            message if this happens. You can prevent this by creating a locking system so that<br />
            only one thread can save a give resized image at a time. Optimally, you want multiple resizes for different images to occur at the same time. If you&#8217;re<br />
            not as concerned about concurrency performance as I was, you could cheat at make the whole resizing method locked. (For new image requests only!) </li>
<li>Writing directly to the output stream. If you&#8217;re caching to disk, but still serving<br />
            the image contents in code, you&#8217;re only supporting a little bit of the HTTP standard,<br />
            and you&#8217;re bypassing all of the work <a id="A1" href="~/11081" runat="server">Thomas<br />
                Marquardt did to bring StaticFileHandler up to snuff</a> . Implement your resizer<br />
                as and HttpModule, not an HttpHandler or you&#8217;re stuck.</li>
<li>Serving a file from disk by loading it into memory. Think about how much RAM your server has,<br />
        how large a single image is, how long<br />
            it has to stay in memory before users finish downloading it, and how many users<br />
            you have requesting images. Don&#8217;t load anything into memory after the initial resize.</p>
<p><a href="http://msdn.microsoft.com/en-us/library/dyfzssz9.aspx">WriteFile()</a><br />
            serves directly from disk, and is *much* safer and more efficient. However &#8211; you<br />
            shouldn&#8217;t be using WriteFile() either if you can avoid it. Letting StaticFileHandler<br />
            do its job is a much better choice. </p>
</li>
<li>Making an HttpHandler instead of an HttpModule. I actually did this in<br />
            v1.0, and it was a *mess*, as well as being non-optimal from a performance standpoint.<br />
            There are several problems with doing this as an HttpHandler.</p>
<ol class="normallist">
<li>It&#8217;s very difficult to make an HttpHandler catch only *some* requests (i.e., those<br />
                    requesting resizing), for a certain extension. It&#8217;s very hard, in fact, and involves<br />
                    subclassing DefaultHttpHandler and re-implementing a lot of code. While that&#8217;s possible<br />
                    on IIS5/6/7 classic, it doesn&#8217;t work on IIS7 Integrated. So IIS7 integrated is a<br />
                    complete deal-breaker if you want to let standard images alone. </li>
<li>It&#8217;s difficult to pass a request from one HttpHandler to another. When building<br />
                    an image resizer, we don&#8217;t want to be responsible for serving the resized file,<br />
                    just making sure the resized version has been cached to disk, and then rewriting<br />
                    the request to point to that file. An HttpModule, on the other hand, is perfectly<br />
                    suited to checking for image resize requests, caching the results, and rewriting<br />
                    the request so StaticFileHandler or whatever is the default in IIS 8 , 9, or 10<br />
                    can take of it. I do this in PostAuthorizeRequest, by calling context.RewritePath(virtualPath, false);</li>
</ol>
</li>
<li>Not setting context.Response.ContentType properly. You&#8217;ll get all kinds of interesting,<br />
            varied, and peculiar results from browsers if you omit this step. Things can be really<br />
            interesting if the format is changed during the resize, since the extension will<br />
            match the original format. </li>
<li>Obvious, but you should have caching enabled for your images, regardless<br />
            of whether they are being resized or not. Disk caching is great, but memory caching allows for even faster responses to frequently requested images, and shouldn&#8217;t be omitted.<br />
            In addition, HttpCacheability.Public enables client and proxy caching too, so browsers and some firewalls will cache the result from the server. You can adjust the amount of time<br />
            the files are cached with SetExpires.</p>
<p>
            This is the code I use during PreSendRequestHeaders
        </p>
<pre name="code" class="brush:c-sharp">
HttpApplication app = sender as HttpApplication;
HttpContext context = (app != null) ? app.Context : null;

if (context != null &amp;&amp; context.Items != null &amp;&amp; context.Items[&quot;FinalContentType&quot;] != null &amp;&amp; context.Items[&quot;FinalCachedFile&quot;] != null)
{
	//Clear previous output
	//context.Response.Clear();
	context.Response.ContentType = context.Items[&quot;FinalContentType&quot;].ToString(); //FinalContentType is set to image/jpeg or whatever the image mime-type is earlier in code.
	//Add caching headers
	context.Response.AddFileDependency(context.Items[&quot;FinalCachedFile&quot;].ToString());

	if (context.Items[&quot;ContentExpires&quot;] != null)
		context.Response.Cache.SetExpires((DateTime)context.Items[&quot;ContentExpires&quot;]); //ContentExpires is set to DateTime.Now.AddMinutes(x), where x is how long the clients should locally cache the image before checking for updates.

	//Enables in-memory caching
	context.Response.Cache.SetCacheability(HttpCacheability.Public);
	context.Response.Cache.SetLastModifiedFromFileDependencies();
	context.Response.Cache.SetValidUntilExpires(false);
}
</pre>
</li>
<li>Accepting the file path as a querystring parameter. This mistake makes me cringe<br />
            &#8211; I find it amazing each time how much people trust their filtering code to prevent<br />
            abuse of this feature. (If they have path filtering code at all!) Just&#8230; don&#8217;t&#8230;<br />
            do it&#8230; please. Do you know how many ways there are to encode filenames and circumvent<br />
            pattern-matching techniques? Yes, there are ways to protect this kind of system, but why?</p>
<p>Why choose /resizeimage.ashx?path=~%2fimg%2fproducts%2fbox.jpg&amp;maxwidth=100&amp;maxheight=100<br />
            over /img/products/box.jpg?maxwidth=100&amp;maxheight=100 ?</p>
<p>
            If you&#8217;re stuck in IIS6 and you aren&#8217;t allowed to modify handler mappings, you should look for a better host.</p>
</li>
</ol>
<h2>
        Pitfalls in Image Resizing</h2>
<ol class="normallist">
<li>Using GetThumbnailImage(). <a href="http://msdn.microsoft.com/en-us/library/system.drawing.image.getthumbnailimage.aspx"><br />
            GetThumbnailImage</a>() seems the obvious choice, and many articles recommend its<br />
            use.<br />
            Unfortunately, it always grabs the embedded jpeg thumbnail if present.<br />
            Some photos have these, some don&#8217;t &#8211; it usually depends on your camera. You&#8217;ll wonder<br />
            why GetThumbnailImage works good on some photo, but on others is horribly<br />
            blurred. GetThumbnailImage() isn&#8217;t reliable for photos larger than 10px by 10px for that reason.</li>
<li>Forgetting to set InterpolationMode, SmoothingMode, CompositingQuality, and PixelOffsetMode.<br />
            With all these set properly, you<br />
            should be able to get resized images indistinguishable from Photoshop results. If<br />
            you don&#8217;t, you&#8217;ll end up with trash. GDI has dumb defaults. (BTW, the low-quality<br />
            settings aren&#8217;t always much faster) <a href="http://www.glennjones.net/Post/799/Highqualitydynamicallyresizedimageswithnet.htm"><br />
                This article</a> explains why those are needed to make DrawImage compose the<br />
            image well.</p>
<pre name="code" class="brush:c-sharp">
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode  = SmoothingMode.HighQuality;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            </pre>
</li>
<li>Not maintaining aspect ratio. I see this often, and I&#8217;m not sure why &#8211; the math<br />
            isn&#8217;t too hard. Well, for those who are wondering how, I hope this code is rather<br />
            transparent (no pun intended).</p>
<pre name="code" class="brush:c-sharp">
double aspectRatio = imageWidth/imageHeight;
double boxRatio = maxWidth/maxHeight;
double scaleFactor = 0;
if (boxRatio &gt; aspectRatio)
 //Use height, since that is the most restrictive dimension of box.
 scaleFactor = maxHeight / imageHeight;
else
 scaleFactor = maxWidth / imageWidth;

double newWidth = imageWidth * scaleFactor;
double newHeight = imageHeight * scaleFactor;
</pre>
</li>
<li>Not setting the Jpeg quality to 90. You&#8217;ll get huge Jpegs from Image.Save unless<br />
            you pass in the proper parameters. 90 seems to be the magic value &#8211; great quality<br />
            and much lower file size than 100.</p>
<pre name="code" class="brush:c-sharp">
int quality = 90; //90 is the magic setting - really. It has excellent quality and file size.
System.Drawing.Imaging.EncoderParameters encoderParameters = new System.Drawing.Imaging.EncoderParameters(1);
encoderParameters.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)quality);
thumb.Save(stream, GetImageCodeInfo(&quot;image/jpeg&quot;), encoderParameters);

/// &lt;summary&gt;
/// Returns the first ImageCodeInfo instance with the specified mime type. Some people try to get the ImageCodeInfo instance by index - sounds rather fragile to me.
/// &lt;/summary&gt;
/// &lt;param name=&quot;mimeType&quot;&gt;&lt;/param&gt;
/// &lt;returns&gt;&lt;/returns&gt;
public static ImageCodecInfo GetImageCodeInfo(string mimeType)
{
	ImageCodecInfo[] info = ImageCodecInfo.GetImageEncoders();
	foreach (ImageCodecInfo ici in info)
		if (ici.MimeType.Equals(mimeType, StringComparison.OrdinalIgnoreCase)) return ici;
	return null;
}
</pre>
</li>
<li>Using the built-in quantization (palette creation) for GIFs, 8-bit PNGs and BMPs.<br />
            The default palette is truly terrible, and while you can specify your own set of<br />
            255 colors &#8211; which ones should they be? The process of determining which colors<br />
            to choose for the palette and to produce the best quality images is call quantization.<br />
            I recommend the very efficient and decent-quality <a href="http://codebetter.com/blogs/brendan.tompkins/archive/2004/01/26/use-gdi-to-save-crystal-clear-gif-images-with-net.aspx"><br />
                octree quantization algorithm</a>. It does have a number of bugs you will have<br />
            to patch. Follow the transparency patch instructions found in the comments. Use the safe version of the library. Patch the Marshal.ReadInt32() bug (original is ReadByte()).<br />
            Change any casts from IntPtr->int to IntPtr->long to make the code 64-bit safe.</p>
<p>I&#8217;m working on adding adjustable Floyd-Steinberg dithering to <a href="http://nathanaeljones.com/products/asp-net-image-resizer/">the version in my resizer </a>, and<br />
           the results have been very promising so far.</p>
</li>
<li>Inheriting the palette from the original image. While at first this seems like an<br />
            <a href="http://getlara.com/north-america/canada/alberta/edmonton/post/2008/10/13/png-jpg-gif-image-resize-with-net-with-transparency"><br />
                easy way to solve the palette problem</a> for GIFs, realize that the bicubic<br />
            resizing will have combined colors, and the new thumbnail may not have any of colors<br />
            of the original image. Also, any operations performed on the bitmap in 8-bit mode<br />
            will be poor quality, and this won&#8217;t allow conversion between image formats. There are<br />
            other ways to keep transparency. This is probably better than leaving the default palette, but YMMV.</li>
<li>Resizing images that don&#8217;t request it. Your code should only activate when an image has a querystring with one of the supported<br />
        commands. Pushing all images through your code is unnecessary. </li>
<li>And one last piece of advice.<strong> Have Good Defaults. Always.</strong>
<p>The output image type should default to the source image type, unless it&#8217;s a BMP or TIFF.<br />
        Default behavior should always preserve aspect ratio.
        </p>
<p>Many developers stop after making their code configurable. They don&#8217;t take that extra 10 minutes to give<br />
        everything smart defaults. Smart defaults distinguish good software from <em>great</em> software.</p>
</li>
</ol>
<p>I hope to post Part 2 soon. I plan on revealing the architecture that has evolved in my resizer,<br />
    and how to design a IIS5/6/7 compatible HttpModule.</p>
]]></content:encoded>
			<wfw:commentRss>http://nathanaeljones.com/163/20-image-resizing-pitfalls/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Server-side Image Resizing Module for ASP.NET, ASP, &amp; PHP/IIS</title>
		<link>http://nathanaeljones.com/162/server-side-image-resizing-module-for-asp-net-asp-phpiis-3/</link>
		<comments>http://nathanaeljones.com/162/server-side-image-resizing-module-for-asp-net-asp-phpiis-3/#comments</comments>
		<pubDate>Sun, 17 May 2009 04:20:03 +0000</pubDate>
		<dc:creator>Nathanael Jones</dc:creator>
				<category><![CDATA[Image Resizing]]></category>
		<category><![CDATA[image resizer]]></category>

		<guid isPermaLink="false">http://66.29.219.39/?p=162</guid>
		<description><![CDATA[Version 2.0 beta is now available!]]></description>
			<content:encoded><![CDATA[
<p style="position: absolute; height: 5px; width: 5px; top: -3000px">
Open-source image resizing module for ASP.NET. Great for thumbnails and slideshows. Features managed disk caching, jpeg/png/gif support, and bicubic resizing.
</p>
<p><script type="text/javascript">
	$(function() {
		$("#tabs").tabs();
	});
	</script></p>
<style type="text/css">
div.articleBody {
line-height:2.1em;
padding:15px 15px 15px 15px;
}
.smallcomments blockquote{
line-height:1em; font-size:8pt;
}
</style>
<div id="tabs">
<ul>
<li><a href="#why">Why</a></li>
<li><a href="#opensource">Open Source</a></li>
<li><a href="#features">Features</a></li>
<li><a href="#quality">Quality</a></li>
<li><a href="#performance">Performance</a></li>
<li><a href="#requirements">Requirements</a></li>
<li><a href="#changelog">Changelog</a></li>
</ul>
<div id="why">
<h3>You need this module if you work with images.</h3>
<p>Once installed, you can size, crop, and change the format of images from anywhere&#8230; HTML, ASP.NET, ASP, PHP, Flex, or Flash &#8230; Just add the desired behavior to the URL with &#8220;?width=100&#8243; or &#8220;?format=jpg&#8221;. It supports scaling, cropping, rotating, flipping, stretching, padding, borders, transparency, jpeg, png, and gif formats. Aspect ratio is <em>always</em> maintained unless &#038;stretch=fill is specified.
</p>
<p class="rightbox">The difference between the actual size and wanted size  of an uploaded image is inversely proportional to the quantiy of time available and the sluggishness of Photoshop.</p>
<p>Server-side image resizing is one of those little features that can have incredible ROI. It can save webmasters several hours each day, and gives you the ability to change the resolution of an image without having to hunt up the original. <%--However, many of the approaches currently on the web don't take security or performance into account.--%></p>
<p>I developed this image resizing system around two years ago. I needed something very intuitive, simple, secure, and efficient. We&#8217;ve been using this system heavily on a live, high-traffic site (<a href="http://youngfoundations.org">youngfoundations.org</a>) for two years, and we have had zero stability problems, memory leaks, or reliability issues with it. It&#8217;s very mature and stable. Version 2.0 is even faster and more scalable than the previous versions, and includes dozens of new features.</p>
<p>Check out the <a href="~/11201" runat="server">samples page</a> to see what it can do. The <a href="~/11151" runat="server">license</a> is much like the GPL, and allows you to redistribute the source code as part of a larger project. You&#8217;ll find the source code very clean, organized, and well commented. </p>
<div class="rightbox">
<a class="download" href="https://www.e-junkie.com/ecom/gb.php?i=254264&#038;c=single&#038;cl=41912">Download Source ($69)</a></p>
<p style="margin-bottom:0;padding-top:0;font-size:7.5pt; color:#909090;">Includes v2.0b &#8211; May 16, 2009</p>
<p><a href="~/11151" runat="server">License</a><br />
<a href="~/11201" runat="server">Samples</a><br />
<a href="~/11141" runat="server">Installation</a></p>
<p>If you have any questions after reading the documentation, leave a comment or e-mail <strong>nathanael.jones@gmail.com</strong>. </p>
</div>
<p>Although I typically release my components for free, I decided to charge a &#8216;download fee&#8217; for this one to help support my other open-source projects. Don&#8217;t worry, this component is still open-source, and the license permits source redistribution as part of a larger system. However, I&#8217;m asking that people who want to integrate this component purchase the download instead of ripping it out of another open-source project. My free to non-free LOC (lines of code) ratio is still over 40 to 1, and I plan on keeping it that way.  I trust this will keep everybody happy.</p>
<p>Your donations are the reason Version 2 exists.</p>
<h2>A few user comments&#8230;</h2>
<div class="smallcomments">
<blockquote>
<p>To anyone thinking of using this module, it worked great and saved me lots of custom-coding time for a client project. On top of that, Nathanael reworked some of the code to my needs for a very reasonable rate, so I have the custom solution I needed. </p>
<p>
If you&#8217;re working on an image display project in asp.net, just use this code and enjoy. It&#8217;s bullet proof!</p>
<p>Jason<br/><br />
<a href="http://webmanufactory.blogspot.com/">http://webmanufactory.blogspot.com/</a>
</p></blockquote>
<blockquote>
<p>Nathanael, I downloaded your code this weekend to use in our portal code base. I was tired of writing code to pick between icon/medium/large/original sizes of the images for different pickers / viewers etc. I was skeptical as to whether the component would be fast enough for the performance we are after in our software, but I am glad to report that your code is super fast and does exactly what you say it does. It was easy to install, and works perfectly. Thank you so much for building this tool, it is going to come in handy!</p>
<p>I do have one question though, which is why the tool will not resize an image to be larger than the original source image. I have a few images that are 800X600 jpegs, and when I tried ?width=1024 the code returned the original image size of 800X600? Is this by design? How hard would it be to make the code upsize and image? <em>[v2 allows this with &amp;scale=both]</em></p>
<p>
Again, thank you for the tool, and to other skeptic developers, Nathan&#8217;s code rocks out of the box.
</p>
<p>Thanks, <br/><br />
Steve
</p></blockquote>
<blockquote><p>
By Dave<br />
just like to say, since using the code (and getting working and donating in next to no time) we have moved three or four of our sites over to using this technique. Previously we had manually run batch resizes initially and then made clients create multiple sizes of the image&#8230; very time consuming and some clients weren&#8217;t technically up to the task. Having been after such a solution for so long, i was really worried that the time to generate images on the fly and the resultant quality would be a problem, but WOW&#8230;.. this code nails it entirely&#8230;i can only say if you are reading these comments, worry not and get this code straight away&#8230;. so much work seems to have gone into this solution, i can&#8217;t rate it too highly&#8230; my find of the year&#8230;&#8230;. thanks Nathanael&#8230;.
</p></blockquote>
</div>
</div>
<div id="buy">
</div>
<div id="features">
<p>Querystring-based resizing is super-simple and can be used from any language (HTML, ASP.NET, PHP, Flash, Flex, etc). </p>
<p>Supports scaling, cropping, rotating, flipping, stretching, padding, borders, transparency, and the 4 main image formats. Aspect ratio is maintained unless <strong>&amp;stretch=fill</strong> is specified.</p>
<p>For example, to make an image 400px or less wide, just add <strong>?width=400</strong>. If you want to set both the maximum height and width, use <strong>?maxwidth=400&amp;maxheight=400</strong>.</p>
<p>Sometimes you need all your images to be exactly the same size, regardless of the original aspect ratio. There are several solutions to this. If you specify both <strong>width</strong> and <strong>height</strong>, whitespace will be automatically added to two sides to make up the difference. Set whitespace color with <strong>&amp;bgcolor</strong>. If you don&#8217;t want whitespace, you can try <strong>&amp;crop=auto</strong>. This &#8220;smart cropping&#8221; will figure out the minimal amount of cropping needed to center the image in the box without changing the aspect ratio or leaving whitespace. And, of course, you could stretch your images with <strong>&amp;stretch=fill</strong>&#8230; if you really wanted to.</p>
<p>Convert between jpg, png, gif, tiff, and bmp images with <strong>&amp;format=jpg|png|gif</strong>. Adjust the quality/size tradeoff of Jpegs with <strong>&amp;quality=1-100</strong>, and the palette size of GIFs and PNGs with <strong>&amp;colors=2-255</strong></p>
<p>Not just for thumbnails &#8211; useful for resizing entire slideshows in real-time as the user changes the window size.</p>
<p>Check out the <a href="~/11201" runat="server">samples page</a> to see the features in action.</p>
<ul class="normallist">
<li>Supported input formats: BMP, GIF, JPG, PNG and TIFF</li>
<li>Supported output formats: <strong>JPG, PNG, and GIF</strong></li>
</li>
</ul>
</div>
<div id="quality">
<p>Bicubic resampling is used exclusively, resulting in very high-quality output. Jpeg compression is excellent, and uses the native windows JPEG encoder. Version 2.0 adds octree quantization for GIF and 8-bit PNG output, providing excellent palette generation for those also.</p>
<p>In my tests, the native windows JPEG encoder and Photoshop have the same visual quality and file size results. Expect photoshop-quality results for both JPEG and PNG output. </p>
<p>GIF and 8-bit PNG output is drastically improved in version 2.0 due to the addition of octree quantization. The primary difference you will notice between Photoshop and module output is the lack of dithering. In most scenarios this doesn&#8217;t affect visual quality much and actually makes the image look &#8216;cleaner&#8217;. Very gentle gradients do benefit from dithering, as do gradients against transparency. </p>
<p>File sizes are excellent &#8211; don&#8217;t expect a measurable improvement when you use Photoshop or ImageReady to compress your images with the same quality settings.</p>
</div>
<div id="performance">
<p>The key to the excellent performance of this module is the disk caching system. This allows even a relatively low-end server to handle the same number of dynamic requests as static file requests.</p>
<ul class="normallist">
<li>Caching doesn&#8217;t get in your way &#8211; if you modify the source file, the resized versions are also updated.</li>
<li>You can resize the same image to several different sizes, and the different versions are cached separately.</li>
<li><strong>Managed disk cache</strong>. If the number of cached files exceeds the configured threshold, a cleanup pass is made on the directory, and a block of the least recently used files are removed.</li>
<li>Client-side caching directives are sent, minimizing repetitive requests from the same client.</li>
<li>Thumbnail generation in <strong>under 20 milliseconds</strong> for most images.</li>
<li>Suitable for slideshows and lists of images. Even the initial resizing of 50 images concurrently isn&#8217;t noticeably slow.</li>
<li>Good with large source files (1-5MB)</li>
</ul>
</div>
<div id="requirements">
<ul class="normallist">
<li>Runs on any of the following following: Windows 2000,  Server 2000, XP, Server 2003, Vista, Server 2008, or Windows 7*. *Not tested, but I don&#8217;t know of any breaking changes to IIS occuring.</li>
<li>Requires .NET 2.0 or higher to be installed on the server and enabled on the website.</li>
<li>The customer must have the ability to copy and paste configuration settings, download files, copy files, and follow simple directions for configuring IIS 6 and below.</li>
<li>Users of version 1.0 should get the free upgrade to 1.2 if they wish to use IIS7 Integrated Mode.</li>
</ul>
</div>
<div id="opensource" style="padding-left:25px">
<p>While I do charge a download fee, the license allows you to redistribute the source as part of another open-source project. I&#8217;m trying to achieve several objectives: 1) Remove the need for users to track licenses, 2) Promote use in open-source projects, 3) Still provide financial support so the project can continue to evolve rapidly.</p>
<ul class="normallist">
<li>Complete source code and an example project is included</li>
<li>Clean, well documented, well designed code. </li>
<li>Great platform to build your own image processing systems on. You can use the disk caching system or image processing code independently from each other.</li>
<li>Very extensible, easy to add new features.</li>
</ul>
<p>CustomFolders.cs can be *easily* modified to do all kinds of work:</p>
<ul class="normallist">
<li>Build rules to automatically resize images based on folder name or other criteria. </li>
<li>Add a new syntax for abbreviating or simplifying common resizing operations. Like /resize(w,h)/.</li>
<li>Easily perform URL rewriting for your images with String.Replace calls. (Regexes work too, if you like them).</li>
</ul>
<p>By purchasing the download, you are permitted to </p>
<ol>
<li>Modify and use the component in all of your projects. </li>
<li>Redistribute the source code as part of another project, provided the component<br />
is less than 5% of the project (in lines of code), and you keep this information attached.</li>
<li>If you received the source code as part of another open source project,<br />
you cannot extract it (by itself) for use in another project without purchasing a download<br />
from http://nathanaeljones.com/. If nathanaeljones.com is no longer running, and a download<br />
cannot be purchased, then you may extract the code.</li>
</ol>
<p>This is basically a developer license &#8211; if you aren&#8217;t a developer (i.e., a hosting company wanting a site or server license), please e-mail me (nathanael.jones@gmail.com).</p>
</div>
<div id="changelog">
<h2>Releases</h2>
<ol class="normallist">
<li>1.0 &#8211; August 6, 2008 (Initial release to the public.) </li>
<li>1.2 &#8211; Nov 23, 2008 (<a href="~/11171" runat="server">Upgrade Notes from 1.0 to 1.2</a>) (<a href="~/11131" runat="server">Original product page</a>) </li>
<li>2.0a Jan 30, 2009 (E-mail distribution)</li>
<li>2.0a Mar 4, 2009 (E-mail distribution)</li>
<li>2.0b May 16, 2009  (<a href="~/11181" runat="server">Upgrade notes from 1.2 to 2.0</a>)
</li>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://nathanaeljones.com/162/server-side-image-resizing-module-for-asp-net-asp-phpiis-3/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Image Resizer 2.0 &#8211; Upgrade notes</title>
		<link>http://nathanaeljones.com/159/image-resizer-2-0-upgrade-notes/</link>
		<comments>http://nathanaeljones.com/159/image-resizer-2-0-upgrade-notes/#comments</comments>
		<pubDate>Sun, 17 May 2009 04:12:57 +0000</pubDate>
		<dc:creator>Nathanael Jones</dc:creator>
				<category><![CDATA[Image Resizing]]></category>
		<category><![CDATA[image resizer]]></category>

		<guid isPermaLink="false">http://66.29.219.39/?p=159</guid>
		<description><![CDATA[Version 2.0 includes dozens of new features and performance enhancements. Upgrading is simple, but there are a few things you should know.]]></description>
			<content:encoded><![CDATA[<h2>Behavior changes</h2>
<ul class="normallist">
<li>When both <strong>?width=x&amp;height=y</strong> are specified, the default behavior has changed. Instead of stretching the image and losing aspect ratio, whitespace is added (controlled with <strong>&amp;bgcolor=color name|code</strong>). You can reinstate the original behavor by adding <strong>&amp;stretch=fill</strong>. Based on customer feedback.</li>
<li>ICC profiles are now read on source images, but changes are merged into the image before output. Since most browsers (including Firefox) do not read ICC profiles, this should produce consistent cross-browser behavior. If you want to ignore the original ICC profile for an image, add <strong>&amp;ignoreicc=true</strong>.</li>
<li>The CustomFolders.cs format has changed, and is now much, much more powerful. All querystring commands can be used, and URL rewriting can be performed. (AllowURLRewriting must be true).</li>
</ul>
<h2>New features</h2>
<p>Check out the <a href="~/11201">samples page</a> to see these features in action.</p>
<ul class="normallist">
<li>Automatic cropping and centering can be performed with <strong>?crop=auto&amp;width=x&amp;height=y</strong>. You can also choose a crop rectangle from the source image manually with <strong>&amp;crop=(x1,y1,x2,y2)</strong>. Negative values indicate distances relative to the bottom-right corner. (10,10,-10,-10) would crop a 10-pixel border off the source image.</li>
<li>Support for 8-bit PNG file output with <strong>&amp;colors=2-255</strong>. Sets the palette size for both PNG and GIF images.</li>
<li>GIF and 8-bit PNG files are now much, much better. Instead of using the GDI default palette, octree quantization is used to calculate the optimal color palette for each image.</li>
<li>Upscaling can be enabled using &amp;scale=both. The default is &amp;scale=downscaleonly. &amp;scale=upscaleonly is also available for certain zooming situations.</li>
<li> Image rotation is supported in degrees. Ex. &amp;rotate=45. Image sizing is performed before rotation, so rotation will cause the final image size to be larger than the size specified in the querystring.</li>
<li>Image flipping can be performed using <strong>&amp;flip=h|v|both.</strong> To flip the source image before other commands occur, use <strong>&amp;sourceFlip=h|v|both</strong>.</li>
<li>BMP and TIFF source files are now supported.</li>
<li>You can add padding around the image with <strong>&amp;paddingWidth=px&amp;paddingColor=color|hex</strong>. paddingColor defaults to bgcolor, which defaults to white.</li>
<li> You can add a border around the image with <strong>&amp;borderWidth=px&amp;borderColor=color|hex</strong>.</li>
<li>Transparency is maintained while resizng PNG files, and when converting from PNG to GIF.</li>
<li>DisableCacheCleanup=true|false is now supported in Web.config. If you have plenty of disk space and wish to manually purge old files from the cache, this setting will allow it. Leave the default value to false unless you have a very good reason.</li>
<li> DiskCacheAlwaysInvalid=true|false is a new Web.config setting for debugging. It forces every request to update the disk cache before responding. Very, very slow, so make *sure* this is false before you launch.</li>
<li>Websites located on UNC paths are now supported. (Ex. \\server\share\website).</li>
</ul>
<h2>Installation</h2>
<ol class="normallist">
<li>Replace the old files with the new files from the ImageResizer folder. If you are using the .DLL, replace the DLL in the bin folder.  Keep a copy of your old CustomFolders.cs if you have modified it.</li>
<li>Delete the /imagecache directory.</li>
<li>If you use both width and height to stretch any images, add <strong>&amp;stretch=fill</strong> to those URLs to maintain the same behavior.</li>
<li>Migrate CustomFolders.cs if you have modified it. The new file includes source comments explaining the process.</li>
</ol>
<p>If you haven&#8217;t upgraded to 1.2, follow <a href="~/11171"> these instructions first</a></p>
]]></content:encoded>
			<wfw:commentRss>http://nathanaeljones.com/159/image-resizer-2-0-upgrade-notes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Image Resizer 1.2, 2.0 &#8211; Web.config</title>
		<link>http://nathanaeljones.com/149/image-resizer-1-2-2-0-web-config/</link>
		<comments>http://nathanaeljones.com/149/image-resizer-1-2-2-0-web-config/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 22:44:56 +0000</pubDate>
		<dc:creator>Nathanael Jones</dc:creator>
				<category><![CDATA[Image Resizing]]></category>
		<category><![CDATA[image resizer]]></category>

		<guid isPermaLink="false">http://66.29.219.39/?p=149</guid>
		<description><![CDATA[Adding web.config settings]]></description>
			<content:encoded><![CDATA[
<p>Version 1.2 of the image resizer is much easier to install in web.config, since it is implemented as an HttpModule instead of an HttpHandler. It still integrates quite well with ASP.NET&#8217;s URL authorization system, and doesn&#8217;t allow access to protected files.</p>
<p>This integration isn&#8217;t valuable to most people, however, since they aren&#8217;t protecting any static files.<br />
Users who don&#8217;t need this protection can enable the &#8220;AllowFolderResizeNotation&#8221; setting to gain additional URL flexibility in exchange.</p>
<p>Version 1.2 now passes *all* file serving work back to IIS. The cached image is now written to disk first rather than last, allowing a simple RewritePath call to handle the work.</p>
<p>The same code can now be used for both IIS5, 6, 7c and 7i. The httpModules section handles IIS5/6/7c, and the modules section handles IIS7 integrated mode.</p>
<pre name="code" class="brush:xml">
&lt;system.web>
  ...
  &lt;httpModules>
    &lt;add name="ImageResizer" type="fbs.ImageResizer.InterceptModule"/>
  &lt;/httpModules>
  ...
&lt;/system.web>
&lt;system.webServer>
  &lt;validation validateIntegratedModeConfiguration="false"/>
  ...
  &lt;modules>
    &lt;add name="ImageResizer" type="fbs.ImageResizer.InterceptModule"/>
  &lt;/modules>
&lt;/system.webServer>
</pre>
<p></script></p>
]]></content:encoded>
			<wfw:commentRss>http://nathanaeljones.com/149/image-resizer-1-2-2-0-web-config/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Image Resizer Documentation</title>
		<link>http://nathanaeljones.com/142/image-resizer-documentation/</link>
		<comments>http://nathanaeljones.com/142/image-resizer-documentation/#comments</comments>
		<pubDate>Fri, 08 Aug 2008 18:28:00 +0000</pubDate>
		<dc:creator>Nathanael Jones</dc:creator>
				<category><![CDATA[Image Resizing]]></category>
		<category><![CDATA[image resizer]]></category>

		<guid isPermaLink="false">http://66.29.219.39/?p=142</guid>
		<description><![CDATA[Installation and configuration instructions for the Image Resizer]]></description>
			<content:encoded><![CDATA[<div style="font-size:130%">
<div style="font-size:12pt; border:1px solid gray; padding:15px; padding-bottom:0; margin-bottom:15px;">
<p>Installation is quick and simple, provided you follow the steps carefully. 99% of problems users encounter are due to skipping a step.</p>
<p>1) <strong>Copy and paste</strong> ImageResizer.dll and ImageResizer.pdb into the /bin directory of your app.<br />
Alternatively, you can copy the inner ImageResizer folder (which contains .cs files) into /App_Code. This second approach allows modification of CustomFolders.cs and Watermark.cs.</p>
<p>2) <strong>Copy and paste</strong> the settings at the bottom of the page into web.config to configure the module.</p>
<p>3) Users of 2.1+, <strong>you&#8217;re done</strong>! You can now resize images using the &#8220;image.jpg.<strong>axd</strong>?width=500&#8243; syntax.<br />
For versions prior to 2.1, or for users wanting the cleaner &#8220;image.jpg?width=500&#8243; syntax, some <a href="/11111">additional IIS configuration is needed</a>.</p>
<p><strong>Upgrading?</strong> Read the <a href="/11171">v1.0-v1.2</a>, <a href="/11181">v1.2 to v2.0</a>, or the <a href="/438/version-2-1b-released/">v2.0-v2.1</a> upgrade notes</a> instead.</div>
<h2>Configuration</h2>
<p>You will need to insert the following settings into web.config in the designated places.</p>
<pre class="brush:xml">&lt;system.web&gt;
  ...
  &lt;httpModules&gt;
    &lt;add name="ImageResizer" type="fbs.ImageResizer.InterceptModule"/&gt;
  &lt;/httpModules&gt;
  ...
&lt;/system.web&gt;
&lt;system.webServer&gt;
  &lt;validation validateIntegratedModeConfiguration="false"/&gt;
  ...
  &lt;modules&gt;
    &lt;add name="ImageResizer" type="fbs.ImageResizer.InterceptModule"/&gt;
  &lt;/modules&gt;
&lt;/system.webServer&gt;</pre>
<p>Last, some app settings for the resizer. You can use the following safely with v2.1 and up. Full configuration reference and notes for other versions can be found in the next section.</p>
<pre class="brush:xml">&lt;appSettings&gt;
    ...
    &lt;add key="ImageDiskCacheDir" value="imagecache" /&gt;
    &lt;add key="MaxCachedImages" value="30000" /&gt;
    &lt;add key="ImageResizerMaxWidth" value="1680" /&gt;
    &lt;add key="ImageResizerMaxHeight" value="1680" /&gt;
    &lt;add key="ImageResizerClientCacheMinutes" value="1440" /&gt;
    &lt;add key="AllowURLRewriting" value="true" /&gt;
    &lt;add key ="ResizeExtension" value=".axd"/&gt;
    ...
&lt;/appSettings&gt;</pre>
<h2>Complete reference</h2>
<pre class="brush:xml">    &lt;!-- The directory to store cached version of images. Relative to the application root --&gt;
    &lt;add key="ImageDiskCacheDir" value="imagecache" /&gt;  

    &lt;!-- How many files to keep in the cache. The 10% least recently used files will be deleted
when this limit is reached. Don't set this lower than the number of images on your site. 2x the image count is a
 good default. If you are getting "Access Denied" messages, this is the cuplrit - you need to increase it --&gt;
    &lt;add key="MaxCachedImages" value="30000" /&gt;  

    &lt;!-- The following settings are optional: --&gt;  

    &lt;!-- The maximum size to permit images to be resized to. --&gt;
    &lt;add key="ImageResizerMaxWidth" value="1680" /&gt;
    &lt;add key="ImageResizerMaxHeight" value="1680" /&gt;  

    &lt;!-- Takes effect in version 1.2. The default (for all versions) is 1440 minutes (24 hours).
        Set to 0 to disable *client* caching (304 "Not Modified" responses will still be returned
        if nothing has changed). Client caching is not related to disk caching. --&gt;
    &lt;add key="ImageResizerClientCacheMinutes" value="1440" /&gt;  

    &lt;!-- This enables /resize(x,y,f)/image.jpg notation in v1.2+. Enabling this
      will make URL authorization ineffective on image files. Changed to AllowURLRewriting in 2.0--&gt;
    &lt;add key="AllowFolderResizeNotation" value="true" /&gt;  

    &lt;!-- This enables /resize(x,y,f)/image.jpg notation and other CustomFolders.cs
rewriting (other than querystring-only changes) in v2.0. Enabling this
      will make URL authorization ineffective on image files on version prior to 2.1b.--&gt;
    &lt;add key="AllowURLRewriting" value="true" /&gt;  

    &lt;!-- (v2.0a+ only) Prevents use of cached files - useful for development when changing resizing algorithms.
          Causes terrible performance - don't leave enabled.--&gt;
        &lt;add key="DiskCacheAlwaysInvalid" value="false"/&gt;  

    &lt;!-- (v2.0b+ only) Prevents the cache cleanup routine from running. If you want to
        manually purge the image cache yourself, and aren't worried about running out
        of disk space via a DOS attack, you can disable this. Not advised. --&gt;
    &lt;add key="DisableCacheCleanup" value="false"/&gt;  

  &lt;!-- (v2.1+ only) Disabling custom quantization allows the resizer to function in low trust
     environments where managed pointer access and data type marshaling is prohibited.
     However, PNGs and BMPs can only be output in 32-bit mode, and GIFs will use the default
     halftone pallete. Enable this if JPGs and PNGs work, but GIFs don't, and using colors=255
      on PNGs causes them to break also.
     Causes much lower quality GIFs to be generated.
      Version 2.1+.
    --&gt;
    &lt;add key ="DisableCustomQuantization" value="false"/&gt;  

     &lt;!-- (v2.1b+ only) This allows images to be resized without any IIS configuration whatsoever.
        Just set this value to ".axd", ".ashx", ".aspx", or any extension
        already registered in IIS, and add the same extension to your image URLs when you are resizing them.
    Doesn't conflict with other pages/files with that extension, unless you name them .jpeg.ashx., etc.

        Ex. /images/media/flower.jpg -&gt; /images/media/flower.jpg.axd?width=x&amp;height=y  

        AllowURLRewriting must be true.   

      Version 2.1b+.
    --&gt;
    &lt;add key ="ResizeExtension" value=".axd"/&gt;</pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://nathanaeljones.com/142/image-resizer-documentation/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Server-side Image Resizing Module for ASP.NET, ASP, &amp; PHP/IIS</title>
		<link>http://nathanaeljones.com/138/server-side-image-resizing-module-for-asp-net-asp-phpiis-2/</link>
		<comments>http://nathanaeljones.com/138/server-side-image-resizing-module-for-asp-net-asp-phpiis-2/#comments</comments>
		<pubDate>Wed, 06 Aug 2008 12:10:47 +0000</pubDate>
		<dc:creator>Nathanael Jones</dc:creator>
				<category><![CDATA[Image Resizing]]></category>
		<category><![CDATA[image resizer]]></category>

		<guid isPermaLink="false">http://66.29.219.39/?p=138</guid>
		<description><![CDATA[Server-side image resizing is one of those tiny features that can have incredible ROI. It can save webmasters several hours each day, and gives you the ability to change the resolution of an image without having to hunt up the original.]]></description>
			<content:encoded><![CDATA[<p style="position: absolute; height: 5px; width: 5px; top: -3000px;">Open-source image resizing module for ASP.NET. Great for thumbnails and slideshows. Features managed disk caching, jpeg/png/gif support, and bicubic resizing.</p>
<p>Server-side image resizing is one of those tiny features that can have incredible ROI. It can save webmasters several hours each day, and gives you the ability to change the resolution of an image without having to hunt up the original. However, many of the approaches currently on the web don&#8217;t take security or performance into account.</p>
<div class="rightbox"><a class="download" href="https://www.e-junkie.com/ecom/gb.php?i=178817&amp;c=single&amp;cl=41912">Download Source ($69)</a></p>
<p style="margin-bottom:0;padding-top:0;font-size:7.5pt; color:#909090;">v1.0 &#8211; August 6, 2008</p>
<p style="margin-bottom:0;padding-top:0;font-size:7.5pt; color:#909090;">v1.2 &#8211; Nov 23, 2008</p>
<p style="margin-bottom:0;padding-top:0;font-size:7.5pt; color:#909090;">v2.0 alpha -Mar 1, 2009 (by request)</p>
<p><a href="~/11151">View License</a><br />
<a href="~/11141">Documentation</a></p>
<p>If you have any questions after reading the documentation, leave a comment or e-mail <strong>nathanael.jones@gmail.com</strong>.</div>
<p>I developed this image resizing system about a year and a half ago. I wanted something very intuitive, simple, secure, and efficient. We&#8217;ve been using this system heavily on a live, high-traffic site (<a href="http://youngfoundations.org">youngfoundations.org</a>) for over a year, and we have had zero stability problems, memory leaks, or other issues with it. It&#8217;s very mature and stable.</p>
<p>Although I typically release my components for free, I decided to charge a &#8216;download fee&#8217; for this one to help support my other open-source projects. Don&#8217;t worry, this component is still open-source, and the license permits source redistribution as part of a larger system. However, I&#8217;m asking that people who want to integrate this component purchase the download instead of ripping it out of another open-source project. My free to non-free LOC (lines of code) ratio is still over 40 to 1, and I plan on keeping it that way.  I trust this will keep everybody happy.</p>
<h3>Features</h3>
<ul class="normallist">
<li>Querystring-based resizing: <strong>image.jpg?width=100</strong>
<ul class="normallist">
<li><strong>?format=jpg|png|gif</strong> — Changes the output format. (This was &#8216;thumbnail&#8217; in v1.0).</li>
<li><strong>&amp;maxwidth=value&amp;maxheight=value</strong> — Specify the maximum size for the resized image. Aspect ratio is maintained. You don&#8217;t have to use both maxwidth and maxheight &#8211; you can use just one.</li>
<li><strong>&amp;height=value&amp;width=value</strong> — If used together, these will force the image to be stretched to the new dimensions. If height or width is used by itself, aspect ratio is maintained.</li>
<li><strong>&amp;quality=0-100</strong> — Changes the jpeg compression setting. 90 is the default value, and you really don&#8217;t need to touch it. 90 produces fantastic quality and tiny files. New in v1.2</li>
</ul>
</li>
<li>Secure &#8211; images still have to pass through ASP.NET&#8217;s URL authorization system.</li>
<li>Can be used from ASP, PHP, HTML files, or any language that runs alongside ASP.NET. Images are separate requests, so you don&#8217;t need to be using ASP.NET to make this work for you.</li>
<li>Not just for thumbnails &#8211; can resize images to any resolution. You can set the size limitations in web.config.</li>
<li>Great for slideshows &#8211; you can change the resolution of the images dynamically as the user resizes.</li>
<li>Supported input formats: BMP, GIF, JPG, PNG and TIFF</li>
<li>Supported output formats: <strong>JPG, PNG, GIF</strong></li>
<li>Photoshop-quality bicubic resizing and jpeg compression.</li>
<li>Works with IIS5, IIS5.1, IIS6, IIS7, and ASP.NET 2.0+. v1.2 is optimized for IIS7 Integrated mode</li>
<li>Well documented, well organized code.</li>
<li>Great platform to build your own image processing systems on. You can use the disk caching system or image processing code separately.</li>
<li>You can set entire folders of images to resize using CustomFolders.cs. (v1.2) You can do &#8220;URL rewriting&#8221; on your images there also.</li>
</ul>
<h3>Bonus functionality</h3>
<ul class="normallist">
<li>Example watermarking code. You can enable this feature by uncommenting the code.</li>
<li><em>yrl</em> class for dealing with virtual paths.</li>
</ul>
<h3>Performance</h3>
<ul class="normallist">
<li><strong>Disk-based caching. Subsequent identical resizes are instantaneous.</strong>
<ul class="normallist">
<li>Caching doesn&#8217;t get in your way &#8211; if you modify the source file, the resized versions are also updated.</li>
<li>You can resize the same image to several different sizes, and the different versions are cached separately.</li>
<li><strong>Managed disk cache</strong>. If the number of cached files exceeds the configured threshold, a cleanup pass is made on the directory, and a block of the least recently used files are removed.</li>
</ul>
</li>
<li>Client-side caching directives are sent, minimizing repetitive requests from the same client.</li>
<li>Thumbnail generation in <strong>under 20 milliseconds</strong> for most images.</li>
<li>Suitable for slideshows and lists of images. Even the initial resizing of 50 images concurrently isn&#8217;t noticeably slow.</li>
<li>Good with large source files (1-5MB)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://nathanaeljones.com/138/server-side-image-resizing-module-for-asp-net-asp-phpiis-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Image Resizer 1.0 &#8211; Web.config</title>
		<link>http://nathanaeljones.com/135/image-resizer-1-0-web-config/</link>
		<comments>http://nathanaeljones.com/135/image-resizer-1-0-web-config/#comments</comments>
		<pubDate>Wed, 06 Aug 2008 11:54:14 +0000</pubDate>
		<dc:creator>Nathanael Jones</dc:creator>
				<category><![CDATA[Image Resizing]]></category>
		<category><![CDATA[image resizer]]></category>

		<guid isPermaLink="false">http://66.29.219.39/?p=135</guid>
		<description><![CDATA[Making required changes in web.config]]></description>
			<content:encoded><![CDATA[<p>The image resizer integrates with ASP.NET&#8217;s URL authorization system quite well. It can&#8217;t be exploited to access protected files, because it is simply a normal Jpeg/Png/Gif handler. However, we only want the handler to execute for files that actually need resizing &#8211; if possible we want control to pass back to IIS6 for performance gains.</p>
<p>Since we only want some .jpg requests to go to the handler, we need to do some logic before we assign a handler. In IIS 6 and IIS7 Classic Pipeline mode, we need to drop in a CustomDefaultHandler at the bottom of the httpHandlers list.</p>
<pre class="brush:xml">&lt;httpHandlers&gt;
      &lt;clear/&gt;
      &lt;add path="trace.axd" verb="*" type="System.Web.Handlers.TraceHandler" validate="true"/&gt;
      &lt;add path="WebResource.axd" verb="GET" type="System.Web.Handlers.AssemblyResourceLoader" validate="true"/&gt;
      &lt;add path="*.axd" verb="*" type="System.Web.HttpNotFoundHandler" validate="true"/&gt;
      &lt;add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="true"/&gt;
      &lt;add path="*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" validate="true"/&gt;
      &lt;add path="*.asmx" verb="*" type="System.Web.Services.Protocols.WebServiceHandlerFactory, System.Web.Services, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" validate="false"/&gt;
      &lt;add path="*.rem" verb="*" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" validate="false"/&gt;
      &lt;add path="*.soap" verb="*" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" validate="false"/&gt;
     &lt;add path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" validate="false"/&gt;

&lt;!-- These are forbidden extensions. I've added a lot here, such as .swp, .sln, .suo, .bak, and .db --&gt;

&lt;add path="*.asax" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.ascx" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.master" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.skin" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.browser" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.sitemap" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.dll.config" verb="GET,HEAD" type="System.Web.StaticFileHandler" validate="true"/&gt;
      &lt;add path="*.exe.config" verb="GET,HEAD" type="System.Web.StaticFileHandler" validate="true"/&gt;
      &lt;add path="*.config" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.cs" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.csproj" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.vb" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.vbproj" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.webinfo" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.licx" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.resx" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.resources" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.mdb" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.vjsproj" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.java" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.jsl" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.ldb" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.ad" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.dd" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.ldd" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.sd" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.cd" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.adprototype" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.lddprototype" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.sdm" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.sdmDocument" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.mdf" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.ldf" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.exclude" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.refresh" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.db" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
      &lt;add path="*.bak" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
		&lt;add path="*.swp" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
		&lt;add path="*.sln" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;
		&lt;add path="*.suo" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;

		&lt;add path="robots.txt" verb="*" type="System.Web.StaticFileHandler" validate="true"/&gt;
&lt;!-- I've also added .txt to prevent my todo files and readme files from being accessible. If you want to serve .txt files, remove this line --&gt;
		&lt;add path="*.txt" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/&gt;

      &lt;add path="*" verb="GET,HEAD,POST" type="fbs.Handlers.CustomDefaultHandler" validate="true"/&gt;
      &lt;add path="*" verb="*" type="System.Web.HttpMethodNotAllowedHandler" validate="true"/&gt;
    &lt;/httpHandlers&gt;</pre>
<p><script src="/scripts/syntaxhighlighter/shCore.js" type="text/javascript"></script><br />
 <script src="/scripts/syntaxhighlighter/shBrushCSharp.js" type="text/javascript"></script><br />
<script src="/scripts/syntaxhighlighter/shBrushXml.js" type="text/javascript"></script><br />
 <script type="text/javascript">// <![CDATA[
dp.SyntaxHighlighter.ClipboardSwf = '/scripts/syntaxhighlighter/clipboard.swf';
dp.SyntaxHighlighter.HighlightAll('code');
// ]]&gt;</script></p>
]]></content:encoded>
			<wfw:commentRss>http://nathanaeljones.com/135/image-resizer-1-0-web-config/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
