<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="http://jamessouth.me/blog/rss/xslt"?>
<rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>James Jackson-South</title>
    <link>http://jamessouth.me/blog/</link>
    <description>Microsoft MVP, Creator of ImageSharp, ImageProcessor and ResponsiveBP, Web developer, Lifter of heavy weights, and all round nice guy.</description>
    <generator>Articulate, blogging built on Umbraco</generator>
    <item>
      <guid isPermaLink="false">1140</guid>
      <link>http://jamessouth.me/archive/context-based-property-mapping-with-umbmapper/</link>
      <category>System.String[]</category>
      <title>Context based property mapping with UmbMapper</title>
      <description>&lt;h2&gt;Mo Mapping, Mo Problems&lt;/h2&gt;
&lt;p&gt;A few weeks ago I wrote an article about my new Umbraco mapping engine &lt;a href="http://jamessouth.me/archive/strong-typed-umbraco-mapping-with-umbmapper/"&gt;UmbMapper&lt;/a&gt;. If you haven't read that post please do, and better yet, please &lt;a href="https://www.nuget.org/packages/umbmapper/"&gt;download&lt;/a&gt; it and give it a try. &lt;/p&gt;
&lt;p&gt;There's been a longstanding puzzle I've been trying to solve for a while now with mapping engines. One that I couldn't crack with Ditto and until today I didn't think I could solve it with UmbMapper.&lt;/p&gt;
&lt;p&gt;I was wrong :)&lt;/p&gt;
&lt;h3&gt;The Problem&lt;/h3&gt;
&lt;p&gt;Consider the following POCO class.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class Page {

    public string Name { get; set; }

    public string Slug =&amp;gt; this.Name.ToUrlSegment();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Mapping this kind of class is impossible with conventional reflection-based run-time mappers as there is no way to guarantee that the &lt;code&gt;Name&lt;/code&gt; property has a value. You'll get a &lt;code&gt;NullReferenceException&lt;/code&gt; and a whole heap of frustration.&lt;/p&gt;
&lt;p&gt;You can workaround this with Umbraco but it's not pretty. You could either &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Turn &lt;code&gt;Slug&lt;/code&gt; into a method which works but makes it impossible to serialize.&lt;/li&gt;
&lt;li&gt;Create an event handler to calculate and store the property when saving the doctype. This is oh-so-ugly and means spreading logic all over the place.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;The Solution&lt;/h3&gt;
&lt;p&gt;With UmbMapper you can map these properties in the following manner. &lt;/p&gt;
&lt;p&gt;First let's define our class.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class Page {

    public string Name { get; set; }

    public string Slug { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And our mapper.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class PageMap : MapperConfig&amp;lt;Page&amp;gt;
{
    public PageMap()
    {
        this.AddMap(p =&amp;gt; p.Name);
        this.AddMap(p =&amp;gt; p.Slug).MapFromInstance(i =&amp;gt; i.Name.ToUrlSlug());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;MapFromInstance&lt;/code&gt; method is our friend here. This has the following signature.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// Sets the property mapping predicate. Used for mapping from known values in the current instance.
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name=&amp;quot;predicate&amp;quot;&amp;gt;The mapping predicate&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;The &amp;lt;see cref=&amp;quot;PropertyMap{T}&amp;quot;/&amp;gt;&amp;lt;/returns&amp;gt;
public PropertyMap&amp;lt;T&amp;gt; MapFromInstance(Func&amp;lt;T, object&amp;gt; predicate)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this method we can map any combination of lazy/non-lazy properties at run-time and be guaranteed the correct result and we keep our mapping logic where it belongs.&lt;/p&gt;
&lt;p&gt;Fantastic!&lt;/p&gt;
&lt;h2&gt;Get it While it's Hot!&lt;/h2&gt;
&lt;p&gt;Give UmbMapper a whirl, it's simple to use but immensely powerful giving you the means to create flexible, scalable Umbraco websites with very little effort.&lt;/p&gt;
</description>
      <pubDate>Mon, 21 Aug 2017 10:15:26 Z</pubDate>
      <a10:updated>2017-08-21T10:15:26Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1139</guid>
      <link>http://jamessouth.me/archive/strong-typed-umbraco-mapping-with-umbmapper/</link>
      <category>System.String[]</category>
      <title>Strong Typed Umbraco Mapping with UmbMapper</title>
      <description>&lt;h2&gt;Greetings and Salutations!&lt;/h2&gt;
&lt;p&gt;It's not often I write code I'm immediately happy with and proud of but this happened to me just recently so I thought I'd share it with the community. &lt;/p&gt;
&lt;p&gt;As I'm sure you know, dear reader, I'm a big fan of a pretty sweet CMS made by some fantastic friends of mine in Denmark called &lt;a href="https://umbraco.com/"&gt;Umbraco&lt;/a&gt;. If you haven't played around with it, please do, it stands out, in my opinion, as easily the most usable, flexible, and fun to work with CMS in the NET ecosystem by a country mile.&lt;/p&gt;
&lt;p&gt;I'm always looking for inventive ways to work with it and to make it even easier for others to do so as well so when I had a flash of inspiration lying, flu-ridden on my couch I had to pop a couple of pills, crank open the laptop, and furiously tap away to produce what I'm sharing.&lt;/p&gt;
&lt;h2&gt;A Little History&lt;/h2&gt;
&lt;p&gt;I've been writing mapping code for Umbraco for a few years now with two of the big guns in the Umbraco package scene, Lee and Matt. You might have heard of the package we produced together called &lt;a href="https://github.com/leekelleher/umbraco-ditto"&gt;Ditto&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;I'm proud of what we achieved with Ditto. I think we've managed to push attribute based mapping about as far as it can go, crafting a very performant, very flexible system that has served me well (and I think many others) over the years. &lt;/p&gt;
&lt;p&gt;I even wrote an article about it a couple of years ago in the fantastic &lt;a href="http://skrift.io/articles/archive/ditto-the-friendly-poco-mapper-for-umbraco/"&gt;Skrift&lt;/a&gt; magazine.&lt;/p&gt;
&lt;p&gt;As my skill-set has grown though and my tastes have changed I have found myself curious about how far and fast I can push mapping. &lt;/p&gt;
&lt;h2&gt;Introducing UmbMapper&lt;/h2&gt;
&lt;p&gt;Not the most exciting name ever but definitely some of the most exciting code I've come up with. &lt;/p&gt;
&lt;p&gt;UmbMapper is a new, convention-based mapper that I've written for mapping &lt;code&gt;IPublishedContent&lt;/code&gt; to strong-typed POCO classes. Strong-typed? Let's quote my own words from a couple of years ago.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Opens dictionary… Strong typing involves the strict enforcement of type rules with no exceptions, allowing the detection of incorrect type usage either at run time or at compile time. Having strong typing catches more type errors than weak typing, resulting in fewer hard errors. It can cut down on many hours of painful debugging.&lt;/p&gt;
&lt;p&gt;Umbraco offers what I would call &amp;quot;Stringly Typing&amp;quot;. You can get your property type out of the API but you have to pass a string in order to do so. That’s pretty damn cool but it doesn’t quite feel natural and easy enough for me to use as a developer. I’m lazy and the last thing I want to do it type lots and learn how to spell things.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Clued up? Great, let's carry on.&lt;/p&gt;
&lt;h2&gt;The Elevator Pitch&lt;/h2&gt;
&lt;p&gt;Why use it? Well, let me explain.&lt;/p&gt;
&lt;p&gt;UmbMapper works in a completely different way to Ditto and ModelsBuilder. It uses the concept of convention-based mapping configuration classes to do the work for you which allows you to perform fine-grained mapping with very little overhead. &lt;/p&gt;
&lt;p&gt;I want my POCO's to be super lean and you should too. Imagine getting to write code like this in your Umbraco project to represent your document types.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class PublishedItem
{
    public int Id { get; set; }

    public string Name { get; set; }

    public DateTime CreateDate { get; set; }

    public DateTime UpdateDate { get; set; }

    public MyEnum MyEnumType{ get; set; }

    public Image Image { get; set; }

    public RelatedLink Link { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ain't that pretty? No attributes, no inheriting of particular interfaces, nothing but pure, good old fashioned POCO goodness! This makes it great for larger projects (As well as small ones) where you can apply design patterns like DDD to maintain flexibility and help your application scale.&lt;/p&gt;
&lt;p&gt;So how do we map it? Here's where the magic happens.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class PublishedItemMap : MapperConfig&amp;lt;PublishedItem&amp;gt;
{
    public PublishedItemMap()
    {
        this.AddMap(p =&amp;gt; p.Id);
        this.AddMap(p =&amp;gt; p.Name);
        this.AddMap(p =&amp;gt; p.CreateDate);
        this.AddMap(p =&amp;gt; p.UpdateDate).SetAlias(p =&amp;gt; p.UpdateDate, p =&amp;gt; p.CreateDate);
        this.AddMap(p =&amp;gt; p.MyEnumType).SetMapper&amp;lt;EnumPropertyMapper&amp;gt;();
        this.AddMap(p =&amp;gt; p.Image).SetMapper&amp;lt;UmbracoPickerPropertyMapper&amp;gt;();
        this.AddMap(p =&amp;gt; p.Link);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Look at that API!! How crisp, how clean, how marvellous! But wait... It gets better. &lt;/p&gt;
&lt;p&gt;For simpler classes, there are more terse mapping methods available&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class PublishedItemMap : MapperConfig&amp;lt;PublishedItem&amp;gt;
{
    public PublishedItemMap()
    {
        this.AddMappings(
            x =&amp;gt; x.Id,
            x =&amp;gt; x.Name,
            x =&amp;gt; x.DocumentTypeAlias,
            x =&amp;gt; x.Level).ForEachIndexed((x, i) =&amp;gt; x.AsLazy());

        this.AddMappings(
            x =&amp;gt; x.SortOrder,
            x =&amp;gt; x.CreateDate,
            x =&amp;gt; x.UpdateDate).ForEach(x =&amp;gt; x.AsLazy());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or for really, really simple classes&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class LazyPublishedItemMap : MapperConfig&amp;lt;LazyPublishedItem&amp;gt;
{
    public LazyPublishedItemMap()
    {
        this.MapAll().ForEachIndexed((x, i) =&amp;gt; x.AsLazy());

        this.MapAll().ForEach(x =&amp;gt; x.AsLazy());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Registering a mapper is as easy as follows&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MapperConfigRegistry.AddMapper(new LazyPublishedItemMap());
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now that's what I call a nice API; super simple to use but powerful with a multitude of other mapping instructions available.&lt;/p&gt;
&lt;h3&gt;Configuration&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;AddMap()&lt;/code&gt; method and subsequent methods called in the mapper constructor each return a &lt;code&gt;PropertyMap&amp;lt;T&amp;gt;&lt;/code&gt; where &lt;code&gt;T&lt;/code&gt; is the class you want to map to. This allows us to use a simple fluent API to configure each property map.&lt;/p&gt;
&lt;p&gt;The various mapping configuration options are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AddMap()&lt;/code&gt; Instructs the mapper to map the property.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AddMappings()&lt;/code&gt; Instructs the mapper to map the collection of properties.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MapAll()&lt;/code&gt; Instructs the mapper to map all the properties in the class.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SetAlias()&lt;/code&gt; Instructs the mapper what aliases to look for in the document type. The order given is the checking order. Case-insensitive.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SetMapper()&lt;/code&gt; Instructs the mapper what specific &lt;code&gt;IPropertyMapper&lt;/code&gt; implementation to use for mapping the property. All properties are initially automatically mapped using the &lt;code&gt;UmbracoPickerPropertyMapper&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SetCulture()&lt;/code&gt; Instructs the mapper what culture to use when mapping values. Defaults to the current culture contained within the &lt;code&gt;UmbracoContext&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AsRecursive()&lt;/code&gt; Instructs the mapper to recursively traverse up the document tree looking for a value to map.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AsLazy()&lt;/code&gt; Instructs the mapper to map the property lazily using dynamic proxy generation. You need to mark your property with the &lt;code&gt;virtual&lt;/code&gt; keyword for that to work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Available &lt;code&gt;IPropertyMapper&lt;/code&gt;implementations all inherit from the &lt;code&gt;PropertyMapperBase&lt;/code&gt; class and are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;UmbracoPickerPropertyMapper&lt;/code&gt; The default mapper. Maps directly from Umbraco's Published Content Cache via &lt;code&gt;GetPropertyValue&lt;/code&gt;. Runs automatically.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EnumPropertyMapper&lt;/code&gt; Maps to enum values. Can handle both integer and string values.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UmbracoPickerPropertyMapper&lt;/code&gt; Maps from all the Umbraco built-in pickers.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DocTypeFactoryPropertyMapper&lt;/code&gt; Allows mapping from mixed &lt;code&gt;IPublishedContent&lt;/code&gt; sources like Nested Content. Inherits &lt;code&gt;FactoryPropertyMapperBase&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These mappers handle most use cases since they rely initially on Umbraco's &lt;code&gt;PropertyValueConverter&lt;/code&gt; API. Additional mappers can be easily created by inheriting the &lt;code&gt;PropertyMapperBase&lt;/code&gt; class which give you all the properties you need.&lt;/p&gt;
&lt;p&gt;I've already built you mappers for Archetype and NuPickers though so you don't need to worry about those :)&lt;/p&gt;
&lt;h2&gt;In Summary&lt;/h2&gt;
&lt;p&gt;I'm hoping by now you can see how beneficial UmbMapper can be in your projects. It's fast, easy to use and should help you build flexible, scalable Umbraco websites giving you the freedom to spend less time boiler-plating and more time concentrating on the fun stuff. &lt;/p&gt;
&lt;p&gt;Please visit the &lt;a href="https://github.com/JimBobSquarePants/UmbMapper"&gt;Github&lt;/a&gt; repo and download the packages from Nuget and if you have any questions, just holler and I'll do my best to help you out. &lt;/p&gt;
&lt;p&gt;Thanks for reading!&lt;/p&gt;
&lt;h2&gt;Update&lt;/h2&gt;
&lt;p&gt;I was asked by my good friend Mads on &lt;a href="https://twitter.com/sniffdk/status/897102781575827456"&gt;Twitter&lt;/a&gt; to elaborate on how lazy mapping works so I thought I best do so.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Any sufficiently advanced technology is indistinguishable from magic. - Gandalf the Grey&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If a mapper is configured using the &lt;code&gt;AsLazy()&lt;/code&gt; instruction and the class contains properties using the virtual keyword, the mapper will generate a dynamic proxy class at run-time to represent the type we are mapping to. This class actually inherits our target class and you'll be able to see it by attaching a debugger.&lt;/p&gt;
&lt;p&gt;The class looks something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class LazyPublishedItemProxy : LazyPublishedItem, IProxy
{
    /// &amp;lt;summary&amp;gt;
    /// Gets or sets the &amp;lt;see cref=&amp;quot;IInterceptor&amp;quot;/&amp;gt; for intercepting 
    /// &amp;lt;see cref=&amp;quot;System.Reflection.MethodBase&amp;quot;/&amp;gt; calls.
    /// &amp;lt;/summary&amp;gt;
    IInterceptor Interceptor { get; set; }

    // Property interceptors are written below using Reflection.Emit
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Any properties configured with lazy mapping are not actually mapped until you specifically call the getter on the property. (Via means of &lt;code&gt;MethodInfo&lt;/code&gt; interception using the terribly complicated Reflection.Emit API).&lt;/p&gt;
&lt;p&gt;This means that we can map large collections with very little overhead. MEGAWHOOP!&lt;/p&gt;
&lt;p&gt;It was really interesting code to write so I encourage you to look through the &lt;a href="https://github.com/JimBobSquarePants/UmbMapper/tree/503f29ebd3b3955e758c729b2a35ac3f0045caed/src/UmbMapper/Proxy"&gt;source&lt;/a&gt; to see how it was all put together, it's very similar to how Entity Framework used to lazy map navigation properties.&lt;/p&gt;
&lt;h3&gt;When to use it?&lt;/h3&gt;
&lt;p&gt;I recommend using this when mapping any pickers or anything that requires significant work when mapped via the Property Value Converter API. You'll most likely be able to use it on all properties but I would always load test any large sites to strike the right performance balance.&lt;/p&gt;
</description>
      <pubDate>Sun, 13 Aug 2017 20:02:23 Z</pubDate>
      <a10:updated>2017-08-13T20:02:23Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1135</guid>
      <link>http://jamessouth.me/archive/imagesharpweb-my-continued-plans-for-world-image-dominance/</link>
      <category>System.String[]</category>
      <title>ImageSharp.Web  (My continued plans for world image dominance)</title>
      <description>&lt;h1&gt;I better build this before someone else does!&lt;/h1&gt;
&lt;p&gt;I recently read a series of blog posts by &lt;a href="https://andrewlock.net/using-imagesharp-to-resize-images-in-asp-net-core-a-comparison-with-corecompat-system-drawing/"&gt;Andrew Lock&lt;/a&gt; comparing &lt;strong&gt;ImageSharp&lt;/strong&gt; to &lt;strong&gt;CoreCompat.System.Drawing&lt;/strong&gt; in which he creates a simple ASP.NET Core &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware"&gt;Middleware&lt;/a&gt; for resizing image via a URI API. They're really, really great and I suggest you read them. &lt;/p&gt;
&lt;p&gt;These posts got me thinking though... I knew I was always going to build a URI API, I just didn't know when I was going to get around to it. I mean... I spend every spare waking hour plus ones I should be sleeping just now building &lt;a href="https://github.com/JimBobSquarePants/ImageSharp"&gt;ImageSharp&lt;/a&gt; (Big HINT &lt;a href="https://github.com/JimBobSquarePants/ImageSharp/issues?q=is:issue%20is:open%20label:%22help%20needed%22"&gt;help me finish the bloody thing&lt;/a&gt;, it's been TWO YEARS!)&lt;/p&gt;
&lt;p&gt;It had to happen sooner rather than later as people are getting twitchy and &lt;strong&gt;ImageSharp&lt;/strong&gt; is getting very close to a beta release, so inspired by Andrew's brilliant writing I got busy...&lt;/p&gt;
&lt;h2&gt;Introducing ImageSharp.Web&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;ImageSharp.Web&lt;/strong&gt; is everything I wished &lt;a href="http://imageprocessor.org/imageprocessor-web/"&gt;ImageProcessor.Web&lt;/a&gt; was and I've only been writing the code for two days. I'm that happy with it. :)&lt;/p&gt;
&lt;p&gt;It runs on ASP.NET Core Middleware, is super extensible, and, should be able to support all your web-based imaging needs once finished. &lt;/p&gt;
&lt;p&gt;You can see the codebase as of time of writing &lt;a href="https://github.com/JimBobSquarePants/ImageSharp/tree/eff6fed0eb1676c4e305be2b029255f6eb6fbdfe/src/ImageSharp.Web"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So how does it work?&lt;/p&gt;
&lt;h2&gt;The Pipeline&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;The hip bone's connected to the...&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The Middleware intercepts the current request, an &lt;code&gt;IUriParser&lt;/code&gt; parses the request looking for commands and creates a dictionary of results.&lt;/li&gt;
&lt;li&gt;An &lt;code&gt;IImageService&lt;/code&gt; is assigned to the request. This will grab the image if required. &lt;/li&gt;
&lt;li&gt;An &lt;code&gt;IImageCache&lt;/code&gt; checks the cache for any previously processed results, if one found, we return the correct response (304, 200) and exit.&lt;/li&gt;
&lt;li&gt;Non cached? We process the file using a collection of &lt;code&gt;IImageWebProcessor&lt;/code&gt; instances using our collected commands via a &lt;code&gt;CommandParser&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The resultant image is cached using the &lt;code&gt;IImageCache&lt;/code&gt; and we return the result with the correct headers.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Simples!&lt;/p&gt;
&lt;p&gt;If all goes well you get something like the following. &lt;/p&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1055/is-web-output.png" alt="Output example for ImageSharp.Web" /&gt;&lt;/p&gt;
&lt;p&gt;So lets examine some of the interfaces I just mentioned. &lt;/p&gt;
&lt;h2&gt;Behind the Curtain&lt;/h2&gt;
&lt;p&gt;All the interfaces described in the pipeline are injected via the &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection"&gt;ASP.NET Core Dependency Injection&lt;/a&gt; container so you can replace them at will.&lt;/p&gt;
&lt;h2&gt;IUriParser&lt;/h2&gt;
&lt;p&gt;This is a neat little interface inspired by some feedback from Andrew that allows you to choose how commands are parsed from the URI. &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public interface IUriParser
{
    IDictionary&amp;lt;string, string&amp;gt; ParseUriCommands(HttpContext context);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;By default &lt;strong&gt;ImageSharp.Web&lt;/strong&gt; will parse &lt;a href="https://github.com/JimBobSquarePants/ImageSharp/blob/eff6fed0eb1676c4e305be2b029255f6eb6fbdfe/src/ImageSharp.Web/Commands/QueryCollectionUriParser.cs"&gt;querystring parameters&lt;/a&gt; but there's nothing to stop you from replacing that with something else. Maybe you want to parse something like &lt;code&gt;/resize/{width}/{height}/{path}&lt;/code&gt; who knows?!&lt;/p&gt;
&lt;h2&gt;IImageService&lt;/h2&gt;
&lt;p&gt;This interface is very similar to the ones found in &lt;a href="http://imageprocessor.org/imageprocessor-web/extending/#iimageservice"&gt;ImageProcessor.Web&lt;/a&gt; except it's a bit simpler&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public interface IImageService
{
    string Key { get; set; }

    IDictionary&amp;lt;string, string&amp;gt; Settings { get; set; }

    Task&amp;lt;bool&amp;gt; IsValidRequestAsync(HttpContext context, ILogger logger, string path);

    Task&amp;lt;byte[]&amp;gt; ResolveImageAsync(HttpContext context, ILogger logger, string path);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;key&lt;/code&gt; property there indicates an identifier in the URI that we use to choose which service to implement e.g &lt;code&gt;http://mysite.com/remote/http://remote-image.jpg?width=200&lt;/code&gt; would resolve to a &lt;code&gt;RemoteImageService&lt;/code&gt; (not built yet) as it uses the &lt;code&gt;remote&lt;/code&gt; prefix. Any implementations without a prefix match all requests.&lt;/p&gt;
&lt;p&gt;I've put together one so far, the &lt;code&gt;PhysicalFileImageService&lt;/code&gt;. You can see the code for that &lt;a href="https://github.com/JimBobSquarePants/ImageSharp/blob/eff6fed0eb1676c4e305be2b029255f6eb6fbdfe/src/ImageSharp.Web/Services/PhysicalFileImageService.cs"&gt;here&lt;/a&gt;. It's pretty simple but leverages the DI container to get certain functionality.&lt;/p&gt;
&lt;h2&gt;IImageCache&lt;/h2&gt;
&lt;p&gt;I didn't want to build this at first as I wanted to use the built in primitives like &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/api/microsoft.extensions.caching.distributed.idistributedcache"&gt;&lt;code&gt;IDistributedCache&lt;/code&gt;&lt;/a&gt; but the API of those primitives was both more complicated than I needed and also lacked the functionality to check if a cached item existed without retrieving it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public interface IImageCache
{
    IDictionary&amp;lt;string, string&amp;gt; Settings { get; set; }

    Task&amp;lt;CachedBuffer&amp;gt; GetAsync(string key);

    Task&amp;lt;CachedInfo&amp;gt; IsExpiredAsync(string key, DateTime minDateUtc);

    Task&amp;lt;DateTimeOffset&amp;gt; SetAsync(string key, byte[] value, int length);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It's again pretty simple but contains enough information to create any kind of cache you require. I've written a &lt;code&gt;PhysicalFileSystemCache&lt;/code&gt; &lt;a href="https://github.com/JimBobSquarePants/ImageSharp/blob/eff6fed0eb1676c4e305be2b029255f6eb6fbdfe/src/ImageSharp.Web/Caching/PhysicalFileSystemCache.cs"&gt;implementation&lt;/a&gt; so far for non-multi-tenant applications but I plan on creating others for Azure etc. (&lt;strong&gt;I will probably charge a small fee for those though as I need to start making some money off the back of my work&lt;/strong&gt; )  
&lt;/p&gt;
&lt;h2&gt;IImageWebProcessor&lt;/h2&gt;
&lt;p&gt;This is how we actually process the image. We pass our commands and process the image accordingly. There's an overload to &lt;code&gt;Image&amp;lt;TPixel&amp;gt;&lt;/code&gt; that loops through available processors. &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public interface IImageWebProcessor
{
    IEnumerable&amp;lt;string&amp;gt; Commands { get; }

    Image&amp;lt;TPixel&amp;gt; Process&amp;lt;TPixel&amp;gt;(Image&amp;lt;TPixel&amp;gt; image, ILogger logger, IDictionary&amp;lt;string, string&amp;gt; commands)
        where TPixel : struct, IPixel&amp;lt;TPixel&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here's the &lt;a href="https://github.com/JimBobSquarePants/ImageSharp/blob/eff6fed0eb1676c4e305be2b029255f6eb6fbdfe/src/ImageSharp.Web/Processors/ResizeWebProcessor.cs"&gt;source code&lt;/a&gt; for the ResizeWebProcessor. This allows you to choose all the available resize options including the size, mode, and sampler. I'll knock up another couple of processors also that ship out-of-the-box too. AutoRotate, Format &amp;amp; BackgroundColor. Any additional ones will require $$ I'm afraid.&lt;/p&gt;
&lt;h2&gt;Commands&lt;/h2&gt;
&lt;p&gt;Parsing input commands is a non-trivial task. The web is a hostile environment and you not only have to deal with potential attacks, you have to deal with developers who are not keen on reading documentation. As such I have had to write a pluggable system of &lt;code&gt;ICommandConverter&lt;/code&gt; &lt;a href="https://github.com/JimBobSquarePants/ImageSharp/tree/eff6fed0eb1676c4e305be2b029255f6eb6fbdfe/src/ImageSharp.Web/Commands"&gt;implementations&lt;/a&gt; that are used by the &lt;code&gt;CommandParser&lt;/code&gt; singleton to deal with common parsing tasks. Again, this is extensible.&lt;/p&gt;
&lt;h2&gt;Rich Returns&lt;/h2&gt;
&lt;p&gt;The Middleware returns the correct response type for processed images (200, 304) and instructs the browser to cache the images for a configurable number of days (we max out by default at 365 days but of course this is configurable)!&lt;/p&gt;
&lt;p&gt;As such you will see a server response like the following.&lt;/p&gt;
&lt;h4&gt;Default Response&lt;/h4&gt;
&lt;p&gt;The result is processed and returned as normal.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1056/is-network.jpg" alt="Raw image processing response shown in the network tab" /&gt;&lt;/p&gt;
&lt;h4&gt;Cached Response&lt;/h4&gt;
&lt;p&gt;The result is cached so no request is made to the server.. Nippy!&lt;/p&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1057/is-network-cached.jpg" alt="Cached image processing response shown in the network tab" /&gt;&lt;/p&gt;
&lt;p&gt;There'll be an event that you can tap into also to add additional headers like Cors headers.&lt;/p&gt;
&lt;h2&gt;Gimme, Gimme, Gimme!&lt;/h2&gt;
&lt;p&gt;So when can you get your hands on this? &lt;/p&gt;
&lt;p&gt;Well... As soon as the main &lt;strong&gt;ImageSharp&lt;/strong&gt; library is ready for primetime I'll release a Nuget package for &lt;strong&gt;ImageSharp.Web&lt;/strong&gt;. By then any issues will be long ironed out and you'll have a great solution to you image processing needs in .NET Core. &lt;/p&gt;
&lt;p&gt;Of course, the sooner you give us a hand, the sooner that can happen ;)&lt;/p&gt;
&lt;p&gt;Please comment below, your feedback is super useful!&lt;/p&gt;
</description>
      <pubDate>Fri, 19 May 2017 06:08:11 Z</pubDate>
      <a10:updated>2017-05-19T06:08:11Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1130</guid>
      <link>http://jamessouth.me/archive/wrangling-the-microsoft-mvp-activity-bookmarklet/</link>
      <category>System.String[]</category>
      <title>Wrangling The Microsoft MVP Activity Bookmarklet</title>
      <description>&lt;p&gt;I'm lucky enough to be a Microsoft MVP in Visual Studio and Development Technologies which is absolutely fantastic. I've been having trouble submitting my work though in an efficient manner so I thought I'd put this short post together to show how I got the MVP Submit Activity Bookmarklet to bend to my will in Microsoft Edge so I can help others in a similar situation.&lt;/p&gt;
&lt;h2&gt;The Problem&lt;/h2&gt;
&lt;p&gt;The &amp;quot;Submit Activity&amp;quot; interface in the MVP website is not great. It's clunky, slow, requires a lot of fields, and requires a lot of tab switching. I find it off-putting to use which means I don't fill it in when I should. Fortunately Microsoft offered an alternative approach.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1051/mvp-bookmark.jpg?width=1000" alt="Introducing MVP Bookmarlet Tool" /&gt;&lt;/p&gt;
&lt;p&gt;All is good. Except that it isn't. There's a couple of issues.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The bookmarklet is fundamentally broken, expecting a relative path in it's code. This means it doesn't work on any page other than within the MVP site!&lt;/li&gt;
&lt;li&gt;When fixed, that bookmarklet doesn't work in Chrome asking you to sign in when you already are.&lt;/li&gt;
&lt;li&gt;Microsoft Edge doesn't support adding bookmarklets through it's interface.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Fortunately we can fix this.&lt;/p&gt;
&lt;h2&gt;The Solution&lt;/h2&gt;
&lt;h3&gt;Fixing the Source&lt;/h3&gt;
&lt;p&gt;First we need to fix the JavaScript snippet so that it actually works.&lt;/p&gt;
&lt;p&gt;Here's the original code.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;javascript: (function () {
    if (window.myBookmarklet !== undefined) {
        myBookmarklet();
    } else {
        document.body.appendChild(document.createElement('script')).src = '/Content/Scripts/bookmarklet.js?';
    }
})();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;See the issue? Yeah that relative src path is never gonna work! &lt;/p&gt;
&lt;p&gt;So knowing the correct URL (Since we know that it works within the MVP site) let's update that.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;javascript: (function () {
    if (window.myBookmarklet !== undefined) {
        myBookmarklet();
    } else {
        document.body.appendChild(document.createElement('script')).src = 'https://mvp.microsoft.com/Content/Scripts/bookmarklet.js?';
    }
})();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ok we have fixed the source code but that's only half of the solution. When we try to use the updated bookmarklet code in Chrome (A browser that natively supports bookmarklets) we are greeted with this.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1052/mvp-sign-in.jpg?width=1000" alt="MVP Sign in model" /&gt;&lt;/p&gt;
&lt;p&gt;But I'm already signed in! Let's give Edge a try since it's Microsoft product and they always work together right.... Right?&lt;/p&gt;
&lt;p&gt;Wrong! As discussed before Microsoft Edge doesn't natively support bookmarklets to we are going to turn to a 3rd paty tool to help us out. &lt;strong&gt;Edge Management&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Edge Management To The Rescue!&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://www.emmet-gray.com/Articles/EdgeManage.html"&gt;Edge Management&lt;/a&gt; is a handy little tool written by a gentleman called &lt;a href="http://www.emmet-gray.com/AboutMe.html"&gt;Emmet Gray&lt;/a&gt; that allows you to manage your Favourites in a manner more consistent with other browsers. We'll use that to add a working bookmarklet.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First you need to create a standard bookmark. Add any page to your Favourites Bar naming it &amp;quot;Submit MVP Activity&amp;quot;. &lt;/li&gt;
&lt;li&gt;Then close Edge and open the Edge Management tool. Edit the URL with our updates code snippet. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1053/mvp-edge.jpg?width=1000" alt="Edge Management interface" /&gt;&lt;/p&gt;
&lt;p&gt;That should have done the trick. Let's test it.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1054/mvp-form.jpg?width=1000" alt="MVP Submit Activity Modal" /&gt;&lt;/p&gt;
&lt;p&gt;Voilà! It works... Now I can submit my work in a much more convenient manner and get back to the business of writing great code. (I've got a &lt;a href="https://github.com/JimBobSquarePants/ImageSharp"&gt;2D graphics library&lt;/a&gt; to ship!)&lt;/p&gt;
&lt;p&gt;Thanks for reading. I hope that you find it useful!&lt;/p&gt;
&lt;p&gt;P.S If anyone who is on the team responsible for the MVP website is reading this please create a proper fix, or even better make the entire process less painful. The MVP website user interface is really quite annoying to use. &lt;/p&gt;
</description>
      <pubDate>Sun, 05 Feb 2017 18:57:26 Z</pubDate>
      <a10:updated>2017-02-05T18:57:26Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1124</guid>
      <link>http://jamessouth.me/archive/imageprocessor-core/</link>
      <category>System.String[]</category>
      <title>ImageProcessor Core</title>
      <description>&lt;h3&gt;So its been a while...&lt;/h3&gt;
&lt;p&gt;It's been roughly a year since my last &lt;a href="http://www.jamessouth.me/archive/mo-images-mo-processing/"&gt;blog post&lt;/a&gt;. I wrote it about a recent ImageProcessor release and opened the last paragraph with the following.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For me this release marks the last I shall actively work on in this
major version. It might well be the last I do ever depending on what
Microsoft do with graphics with the next .NET releases. I've fallen
out of love with the open source community a little over the years due
to the lack of collaboration I've received on this project and others.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sad eh?... Well it turns out I lied. Not only have I released several updates to the &lt;a href="http://www.nuget.org/packages/ImageProcessor/"&gt;V2 branch&lt;/a&gt; with some &lt;a href="https://github.com/jimbobsquarepants/imageprocessor/issues/49"&gt;great contributions&lt;/a&gt; from the community, but I've been hard at work on something a little special... &lt;strong&gt;&lt;a href="https://github.com/JimBobSquarePants/ImageProcessor/tree/Core"&gt;ImageProcessor Core&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;A Little History&lt;/h3&gt;
&lt;p&gt;In 2014 Microsoft blew everyone's minds by &lt;a href="https://blogs.msdn.microsoft.com/somasegar/2014/11/12/opening-up-visual-studio-and-net-to-every-developer-any-application-net-server-core-open-source-and-cross-platform-visual-studio-community-2013-and-preview-of-visual-studio-2015-and-net-2015/"&gt;announcing&lt;/a&gt; that they were building a new, open source, cross-platform framework containing a subset of the full .NET Framework. Everyone rightfully got very excited but a few people (me included) started to worry about the lack of discussion around a graphics API. Issues were opened up on the Github repo and quite a few people &lt;a href="https://github.com/dotnet/corefx/issues/2020"&gt;pitched in with their two cents&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nobody was doing anything though and it was very frustrating for me to watch.&lt;/p&gt;
&lt;p&gt;You see, I have a dream...&lt;/p&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1047/toystory-images-everywhere.jpg" alt="Toy Story meme" /&gt;&lt;/p&gt;
&lt;p&gt;I originally wrote &lt;a href="http://imageprocessor.org"&gt;ImageProcessor&lt;/a&gt; to make it easier for developers to do common tasks with &lt;code&gt;System.Drawing&lt;/code&gt;. I kept seeing blog posts with copy/pasted code examples full of memory leaks and slow code and I wanted to make a difference and give back to a community I learned from.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/JimBobSquarePants/ImageProcessor/tree/Core"&gt;ImageProcessor Core&lt;/a&gt; is an extension of that idea.&lt;/p&gt;
&lt;h3&gt;The Elevator Pitch&lt;/h3&gt;
&lt;p&gt;Common imaging tasks should be accessible to all developers. If you want to resize or crop an image you should be able to use a simple API and do so easily. You shouldn't have to worry about memory leaks and you shouldn't have to worry about  binding to native libraries or deploying in different environments. It should be cross-platform and it should &lt;strong&gt;Just Work &amp;trade;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Oh and of course it needs to be scalable and allow for complex operations and different pixel formats. You know... Simple stuff!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/JimBobSquarePants/ImageProcessor/tree/Core"&gt;ImageProcessor Core&lt;/a&gt; is designed with that in mind.&lt;/p&gt;
&lt;p&gt;So what can it do? As of writing &lt;a href="https://github.com/JimBobSquarePants/ImageProcessor/tree/Core"&gt;ImageProcessor Core&lt;/a&gt; is still very much in alpha status but it turns out quite a lot.&lt;/p&gt;
&lt;p&gt;I have....&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Algorithms for common operations. Resize, Crop, Flip, Rotate, Edge Detection and so on.&lt;/li&gt;
&lt;li&gt;Almost complete support for four different codecs. Bmp, Png, Gif, and of course the most complicated but commonplace of all Jpeg.&lt;/li&gt;
&lt;li&gt;Full EXIF read and write capability using a simple API.&lt;/li&gt;
&lt;li&gt;A generic image class that is signature compatible with Microsoft XNA Game Studio and MonoGame.&lt;/li&gt;
&lt;li&gt;A snazzy new logo that I designed myself :)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And much much more..&lt;/p&gt;
&lt;h3&gt;Example Time&lt;/h3&gt;
&lt;p&gt;To demonstrate the API I will show you some code demonstrating some common tasks. Here's how to resize an image using the default bicubic resampler.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;using (FileStream input = File.OpenRead(&amp;quot;foo.jpg&amp;quot;))
using (FileStream output = File.OpenWrite(&amp;quot;bar.jpg&amp;quot;))
{
    Image image = new Image(input);
    image.Resize(image.Width / 2, image.Height / 2)
         .Save(output);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Want to use a different resampler? We've got you covered.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;using (FileStream input = File.OpenRead(&amp;quot;foo.jpg&amp;quot;))
using (FileStream output = File.OpenWrite(&amp;quot;bar.jpg&amp;quot;))
{
    Image image = new Image(input);
    image.Resize(image.Width / 2, image.Height / 2, new MitchellNetravaliResampler())
         .Save(output);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;How about companding the image to resize with &lt;a href="http://www.4p8.com/eric.brasseur/gamma.html"&gt;gamma correction&lt;/a&gt;?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;using (FileStream input = File.OpenRead(&amp;quot;foo.jpg&amp;quot;))
using (FileStream output = File.OpenWrite(&amp;quot;bar.jpg&amp;quot;))
{
    Image image = new Image(input);
    image.Resize(image.Width / 2, image.Height / 2, true)
         .Save(output);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;How about setting individual pixel values?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Image image = new Image(400, 400);
using (PixelAccessor&amp;lt;Color, uint&amp;gt; pixels = image.Lock())
{
    pixels[200, 200] = Color.White;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;How easy is that?&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Image&lt;/code&gt; class is actually an implementation of a generic class &lt;code&gt;Image&amp;lt;TColor, TPacked&amp;gt;&lt;/code&gt; where &lt;code&gt;TColor&lt;/code&gt; implements an interface identical to the Microsoft XNA Game Studio and MonoGame &lt;a href="https://msdn.microsoft.com/en-us/library/bb197661.aspx"&gt;&lt;code&gt;IPackedVector&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/a&gt;. This allows the library to work well with those frameworks and tightly control memory usage. Underneath the hood it's actually an &lt;code&gt;Image&amp;lt;Color, uint&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Performance&lt;/h3&gt;
&lt;p&gt;A lot of developers say that C# can never be truly fast. A lot of developers are wrong. I've got a long way to go yet but I've been able to get some pretty decent performance going in this early stage.&lt;/p&gt;
&lt;p&gt;Check out this benchmark using the awesome &lt;a href="https://github.com/PerfDotNet/BenchmarkDotNet"&gt;BenchMarkDotNet&lt;/a&gt; comparing a 2000x2000 pixel image downsampled to 400x400 pixels.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Host Process Environment Information:
BenchmarkDotNet-Dev.Core=v0.9.9.0
OS=Microsoft Windows NT 6.2.9200.0
Processor=Intel(R) Core(TM) i7-4712HQ CPU 2.30GHz, ProcessorCount=8
Frequency=2240907 ticks, Resolution=446.2479 ns, Timer=TSC
CLR=MS.NET 4.0.30319.42000, Arch=64-bit RELEASE [RyuJIT]
GC=Concurrent Workstation
JitModules=clrjit-v4.6.1080.0

Type=Resize  Mode=Throughput
                        Method |     Median |    StdDev | Scaled | Scaled-SD |
         System.Drawing Resize | 66.2606 ms | 1.2463 ms |   1.00 |      0.00 |
     ImageProcessorCore Resize | 56.4141 ms | 1.0673 ms |   0.85 |      0.02 |
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Other methods like Crop are much faster and Get/Set pixel is ~94% faster than the &lt;code&gt;System.Drawing&lt;/code&gt; equivalent on my test machine.  I'm very happy with progress so far and I'm sure I can go much faster.&lt;/p&gt;
&lt;h3&gt;So What's The Plan?&lt;/h3&gt;
&lt;p&gt;It's been a very long alpha but I think the API is pretty solid so I shall be moving out of alpha and into beta status soon. Beta releases will be hosted on Nuget as opposed to the current &lt;a href="https://www.myget.org/gallery/imageprocessor"&gt;MyGet&lt;/a&gt; server though you shouldn't use it in production environments until I reach Release Candidate status.&lt;/p&gt;
&lt;p&gt;In beta I shall be concentrating on filling out missing encoder support (&lt;a href="https://github.com/JimBobSquarePants/ImageProcessor/issues/446"&gt;you can help!&lt;/a&gt;) and really cranking up the performance. &lt;/p&gt;
&lt;p&gt;I'd love to get 2D drawing added to the API but that's probably better off in V1.1 as there's a lot of work involved. &lt;/p&gt;
&lt;h3&gt;Want To Help?&lt;/h3&gt;
&lt;p&gt;Please do... Spread the word, contribute algorithms, submit performance improvements, unit tests. Play around with the API and tell me what is missing. &lt;/p&gt;
&lt;p&gt;If you know someone who works in image processing please try to convince them to get involved. &lt;/p&gt;
&lt;p&gt;There's simply no reason why as a community we cannot build an absolute first-class imaging API that can benefit all levels of developer.&lt;/p&gt;
&lt;p&gt;So come on, &lt;a href="https://github.com/JimBobSquarePants/ImageProcessor"&gt;visit the repo&lt;/a&gt; and get mucked in!&lt;/p&gt;
&lt;p&gt;Please let me know what you think in the comments below.&lt;/p&gt;
&lt;h3&gt;Update&lt;/h3&gt;
&lt;p&gt;Shannon below wanted to see the logo so drink it in. Pure design... Take that Instagram!&lt;/p&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1048/imageprocessor-logo-512.png" alt="ImageProcessor Logo" /&gt;&lt;/p&gt;
</description>
      <pubDate>Mon, 05 Sep 2016 09:45:56 Z</pubDate>
      <a10:updated>2016-09-05T09:45:56Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1122</guid>
      <link>http://jamessouth.me/archive/mo-images-mo-processing/</link>
      <category>System.String[]</category>
      <title>Mo Images Mo Processing</title>
      <description>&lt;p&gt;Today marks another big ImageProcessor release, and my first antipodean one - There's a lot going on so here's a run through of new functionality that's been added to &lt;strong&gt;Imageprocessor v2.4&lt;/strong&gt; and &lt;strong&gt;ImageProcessor.Web. v4.4&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;tl;dr... Upgrade&lt;/strong&gt;&lt;/p&gt;
&lt;h1&gt;ImageProcessor&lt;/h1&gt;
&lt;h2&gt;New Stuff&lt;/h2&gt;
&lt;h3&gt;Resolution&lt;/h3&gt;
&lt;p&gt;This method allows you to change the resolution of the given image. &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public ImageFactory Resolution(int horizontal, int vertical, PropertyTagResolutionUnit unit = PropertyTagResolutionUnit.Inch)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If any EXIF data is to be preserved, the metadata will be updated to match the given resolution.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;Resize&lt;/h3&gt;
&lt;p&gt;With this release I've added two new resize modes to the library: &lt;code&gt;ResizeMode.BoxPad&lt;/code&gt; and &lt;code&gt;ResizeMode.Min&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ResizeMode.BoxPad&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;When upscaling an image using this mode the image pixels themselves are not resized, rather the image is padded to fit the given dimensions. When downscaling the image is resized using the rules defined by &lt;code&gt;ResizeMode.Pad&lt;/code&gt;. As with that mode you can recolour the background colour of the padded area for image types without transparency from the default black.&lt;/p&gt;
&lt;p&gt;Here's an example resizing the original to 500x500px:&lt;/p&gt;
&lt;div class="row"&gt;
&lt;div class="col-m-6"&gt;
 &lt;h4&gt;Original Image &lt;/h4&gt;
&lt;img src="http://jamessouth.me/blog/media/1046/car-small.jpg"/&gt;
&lt;/div&gt;
&lt;div class="col-m-6"&gt;
&lt;h4&gt;Padded Image With Hot Pink Background &lt;/h4&gt;
&lt;img src="http://jamessouth.me/blog/media/1046/car-small.jpg?width=500&amp;height=500&amp;mode=boxpad&amp;bgcolor=hotpink"/&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As with &lt;code&gt;ResizeMode.Pad&lt;/code&gt; and &lt;code&gt;ResizeMode.Crop&lt;/code&gt; the position of the image can be anchored to one of nine different anchor points.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ResizeMode.Min&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;This mode looks for the shortest difference in each dimension between the source length and intended length. it will then resize that side to the intended length on the result, the other dimension is resized maintaining the aspect ratio of the original image. Upscaling is disabled in this mode and the original image will be returned if attempted.&lt;/p&gt;
&lt;p&gt;Here's an example downscaling a larger version of the original with target dimensions of  500x500px:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1006/car.jpg?width=500&amp;amp;height=500&amp;amp;mode=min" alt="Image resized using ResizeMode.Min" /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Performance&lt;/h2&gt;
&lt;p&gt;I've managed to reduce the memory usage by up to 25% in some circumstances in this version by rewriting the way I ensure certain methods performs their functionality in the correct colour space. These rewrites have also slightly improved the speed on earlier releases which is a nice bonus.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Bug fixes&lt;/h2&gt;
&lt;p&gt;In this release I've ironed out numerous bugs relating to image resolution. EXIF metadata for any method that changes the dimension of the image are now updated also where previously this was overlooked.&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;ImageProcessor.Web&lt;/h1&gt;
&lt;h2&gt;New Stuff&lt;/h2&gt;
&lt;h3&gt;PostProcessing&lt;/h3&gt;
&lt;p&gt;This is a big one and I'm very pleased with it...&lt;/p&gt;
&lt;p&gt;I'm all about keeping the web lean but the default image encoders in .NET are not that efficient and you can sometimes actually end up with a &lt;a href="https://github.com/JimBobSquarePants/ImageProcessor/issues/208"&gt;larger image&lt;/a&gt; than what you started with. As such, I've been looking at a way to ensure that anything I output has been optimised as much as possible. For previous versions of &lt;strong&gt;ImageProcessor.Web&lt;/strong&gt; I developed a plugin that post-processed any newly cached images using a variety of tools to reduce the file size as much as possible.  
&lt;/p&gt;
&lt;p&gt;This worked... To a point. Firstly it only worked with the disk cache and not any other cache plugins. Secondly it only acted after the first requests so someone, somewhere would always get an unoptimised image, Thirdly one of the tools I used, optipng was incorrectly detected as malware by Windows Defender.... Not good enough.&lt;/p&gt;
&lt;p&gt;As of this version, &lt;strong&gt;every image that is processed using ImageProcessor.Web is passed through a series of tools that reduce the output size&lt;/strong&gt;. This works with whatever cache implementation is used and can dramatically reduce the weight of your pages. This all happens asynchronously and stays snappy so you shouldn't notice any increased processing time.&lt;/p&gt;
&lt;p&gt;Here's the built in tools I use so you can check them out:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;gifsicle : http://www.lcdf.org/gifsicle/&lt;/li&gt;
&lt;li&gt;pngout : http://advsys.net/ken/utils.htm#pngout&lt;/li&gt;
&lt;li&gt;pngquant : https://pngquant.org/&lt;/li&gt;
&lt;li&gt;jpegtran : http://jpegclub.org/&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It's possible to turn off this behaviour vie the &lt;a href="http://imageprocessor.org/imageprocessor-web/configuration/"&gt;config&lt;/a&gt; but you really shouldn't.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;Bug fixes&lt;/h3&gt;
&lt;p&gt;There's been various minor little issues I've found and fixed while building this update, one of note though was an &lt;a href="https://github.com/JimBobSquarePants/ImageProcessor/issues/211"&gt;issue&lt;/a&gt; where prefix values were globally replaced within the request url.&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;So... What's Next?&lt;/h1&gt;
&lt;p&gt;For me this release marks the last I shall actively work on in this major version.  It might well be the last I do ever depending on what Microsoft do with graphics with the next .NET releases. I've fallen out of love with the open source community a little over the years due to the lack of collaboration I've received on this project and others. &lt;/p&gt;
&lt;p&gt;When I started ImageProcessor I didn't know much about images. I was a front end developer who decided to have a go at solving a problem colleagues were struggling with. I'd only been writing C# for a very short while and I was learning as I went on.... I still am. &lt;/p&gt;
&lt;p&gt;These libraries are now hugely popular with hundreds of thousands of downloads but the number of people who contribute is still minuscule. If I can write this stuff I guarantee there are a very great number of people out there who could do it and do it better. &lt;/p&gt;
&lt;p&gt;I'm very grateful for the work and encouragement of the team at Umbraco for their faith in me and contribution to my code but I feel somewhat that they are alone in doing what they do best in promoting a healthy community around developers.&lt;/p&gt;
&lt;p&gt;I'll still fix bugs but I will not add any more new features nor work on making the library cross-platform for now. It's simply too much work for me to do.&lt;/p&gt;
&lt;h3&gt;Help Me To Help You&lt;/h3&gt;
&lt;p&gt;If you want to see ImageProcessor continue and you know anyone with the chops to help me or think you can spend an hour a week tinkering away, please get in touch. I'd love to build a &lt;a href="https://github.com/JimBobSquarePants/ImageProcessor/tree/5c94066bc5e020d9fc34364573c62c049aa5103f"&gt;v3&lt;/a&gt; as part of a community of developers creating something amazing.&lt;/p&gt;
&lt;p&gt;Anyhoo... Enjoy the new releases. As ever you can read about them in the documentation and download them from Nuget.&lt;/p&gt;
</description>
      <pubDate>Sun, 20 Sep 2015 04:16:08 Z</pubDate>
      <a10:updated>2015-09-20T04:16:08Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1120</guid>
      <link>http://jamessouth.me/archive/fun-with-umbracovirtualnoderoutehandler/</link>
      <category>System.String[]</category>
      <title>Fun with UmbracoVirtualNodeRouteHandler</title>
      <description>&lt;p&gt;This morning I answered a question on &lt;a href="https://our.umbraco.org/forum/umbraco-7/using-umbraco-7/64766-IIS-Rewrite-or-ContentFinder-UrlSegments"&gt;Our Umbraco&lt;/a&gt; regarding the best approach to provide a url allowing deep links for virtual nodes in Umbraco. In my answer I demonstrated how to use &lt;code&gt;UmbracoVirtualNodeRouteHandler&lt;/code&gt; as a means of telling Umbraco what node to pass as my &lt;code&gt;RenderModel&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Shannon talks about the &lt;code&gt;UmbracoVirtualNodeRouteHandler&lt;/code&gt; with custom routing on his &lt;a href="http://shazwazza.com/post/Custom-MVC-routes-within-the-Umbraco-pipeline"&gt;blog&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I thought I'd expand on some of the functionality available to the developer by documenting  a trick I use with implementations of &lt;code&gt;UmbracoVirtualNodeRouteHandler&lt;/code&gt; to provide custom routing.&lt;/p&gt;
&lt;h3&gt;Use Case&lt;/h3&gt;
&lt;p&gt;Quite often I find myself reusing a single document type with multiple templates; I'm sure you have also. Most commonly a &lt;em&gt;LoginRegisterPage&lt;/em&gt; or similar. &lt;/p&gt;
&lt;p&gt;Now I don't know about you but one of the things I miss when using Umbraco is the ability to use &lt;code&gt;Url.Action&lt;/code&gt; to generate urls for my content. I like routing in MVC and I think it's important, especially with the type of page as above to be able to generate the correct urls from within your views or controllers.&lt;/p&gt;
&lt;p&gt;To understand what I am going to do here you first need to understand how routing works in Umbraco.&lt;/p&gt;
&lt;p&gt;If you have the &lt;em&gt;DocumentType&lt;/em&gt; &lt;code&gt;LoginRegisterPage&lt;/code&gt; with the assigned template &lt;code&gt;LoginPage&lt;/code&gt; this will map to a &lt;em&gt;RenderMvcController&lt;/em&gt; called &lt;code&gt;LoginRegisterPageController&lt;/code&gt; with an &lt;em&gt;ActionResult&lt;/em&gt; &lt;code&gt;LoginPage&lt;/code&gt;. This behaviour is standardised and predictable so we can utilise it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DocumentType == Controller&lt;/li&gt;
&lt;li&gt;Template == ActionResult&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Example&lt;/h3&gt;
&lt;p&gt;So let's start by creating some routes.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Custom routing for the membership pages so we can use
// proper redirects. 
RouteTable.Routes.MapUmbracoRoute(
&amp;quot;LoginPage&amp;quot;,
&amp;quot;Login/&amp;quot;,
new
{
    controller = &amp;quot;LoginRegisterPage&amp;quot;,
    action = &amp;quot;LoginPage&amp;quot;
},
new LoginRegisterPageNodeRouteHandler());

RouteTable.Routes.MapUmbracoRoute(
&amp;quot;RegisterPage&amp;quot;,
&amp;quot;Register/&amp;quot;,
new
{
    controller = &amp;quot;LoginRegisterPage&amp;quot;,
    action = &amp;quot;RegisterPage&amp;quot;
},
new LoginRegisterPageNodeRouteHandler());
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here I have created two routes that map to the relative urls &lt;em&gt;/Login&lt;/em&gt; and &lt;em&gt;/Register&lt;/em&gt;. They both map to the same controller but since two different templates are used it will map to two different &lt;em&gt;ActionResult&lt;/em&gt; methods. &lt;/p&gt;
&lt;div class="alert"&gt;

Note: I didn't use the word "virtual" in my handler names since I am mapping to actual nodes.

&lt;/div&gt;
&lt;p&gt;From here I will create a class that takes advantage of the predictability.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// An Umbraco route handler that allows the retrieval of the template alias name from the route action. 
/// &amp;lt;/summary&amp;gt;
public abstract class TemplatedUmbracoVirtualNodeRouteHandler : UmbracoVirtualNodeRouteHandler
{
    /// &amp;lt;summary&amp;gt;
    /// Get the template from the current route.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name=&amp;quot;requestContext&amp;quot;&amp;gt;
    /// The &amp;lt;see cref=&amp;quot;RequestContext&amp;quot;/&amp;gt; containing information about the current HTTP request and route. 
    /// &amp;lt;/param&amp;gt;
    /// &amp;lt;returns&amp;gt;
    /// The &amp;lt;see cref=&amp;quot;string&amp;quot;/&amp;gt; representing the template alias.
    /// &amp;lt;/returns&amp;gt;
    protected virtual string GetTemplateAlias(RequestContext requestContext)
    {
        return requestContext.RouteData.GetRequiredString(&amp;quot;action&amp;quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This class adds an additional method &lt;code&gt;GetTemplateAlias&lt;/code&gt; to our handler pulling in the &lt;em&gt;RouteData&lt;/em&gt; &lt;code&gt;action&lt;/code&gt; variable which we know matches the template name of the node we want in the content tree.&lt;/p&gt;
&lt;p&gt;And from here we can implement this our handler.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// The generic login/register page node route handler.
/// &amp;lt;/summary&amp;gt;
public class LoginRegisterPageNodeRouteHandler : TemplatedUmbracoVirtualNodeRouteHandler
{
    /// &amp;lt;summary&amp;gt;
    /// returns the &amp;lt;see cref=&amp;quot;IPublishedContent&amp;quot;/&amp;gt; associated with the route.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name=&amp;quot;requestContext&amp;quot;&amp;gt;
    /// The request context.
    /// &amp;lt;/param&amp;gt;
    /// &amp;lt;param name=&amp;quot;umbracoContext&amp;quot;&amp;gt;
    /// The umbraco context.
    /// &amp;lt;/param&amp;gt;
    /// &amp;lt;returns&amp;gt;
    /// The &amp;lt;see cref=&amp;quot;IPublishedContent&amp;quot;/&amp;gt;.
    /// &amp;lt;/returns&amp;gt;
    protected override IPublishedContent FindContent(RequestContext requestContext, UmbracoContext umbracoContext)
    {
        UmbracoHelper helper = new UmbracoHelper(umbracoContext);
        string alias = typeof(LoginRegisterPage).Name;
        string templateAlias = this.GetTemplateAlias(requestContext);

        return helper.TypedContentAtRoot()
            .First()
            .Descendants()
            .First(d =&amp;gt; d.DocumentTypeAlias.InvariantEquals(alias)
                     &amp;amp;&amp;amp; d.GetTemplateAlias().InvariantEquals(templateAlias));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;div class="alert"&gt;

Note: I use &lt;a href="https://github.com/leekelleher/umbraco-ditto"&gt;Ditto&lt;/a&gt; to create strong-typed models for my back office content. It's ace, you should give it a go!

&lt;/div&gt;
&lt;p&gt;If you look at the code in my handler you will see that I am searching the content for nodes that match both the name and template of the one I want.&lt;/p&gt;
&lt;p&gt;It's as simple as that really... I can now use &lt;code&gt;Url.Action(&amp;quot;LoginPage&amp;quot;, &amp;quot;LoginRegisterPage&amp;quot;)&lt;/code&gt; and &lt;code&gt;Url.Action(&amp;quot;RegisterPage&amp;quot;, &amp;quot;LoginRegisterPage&amp;quot;)&lt;/code&gt; throughout my code to provide the correct urls to my respective pages priding me with functionality I sorely missed.&lt;/p&gt;
</description>
      <pubDate>Wed, 13 May 2015 05:37:56 Z</pubDate>
      <a10:updated>2015-05-13T05:37:56Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1119</guid>
      <link>http://jamessouth.me/archive/experiments-with-umbracos-icontentservice/</link>
      <category>System.String[]</category>
      <title>Experiments with Umbraco's IContentService</title>
      <description>&lt;p&gt;I haven't had very much experience with the Umbraco &lt;a href="https://our.umbraco.org/documentation/Reference/Management-v6/Models/Content"&gt;ContentService&lt;/a&gt;. I've only just started playing around with it so if I've missed something obvious please tell me in the comments.&lt;/p&gt;
&lt;h3&gt;A Confusing API&lt;/h3&gt;
&lt;p&gt;Reading through the documentation, it seems a shade basic considering the importance of the subject matter and really doesn't go out of it's way to explain what to do and what will happen. &lt;/p&gt;
&lt;p&gt;When saving an item using the content service, the methods signature for the first overload available for setting a property value is as follows.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IContentBase.SetValue(string propertyAlias, object value);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;According to the documentation you should be able to set different types as the second argument. At time of writing they give the following example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Given a `ContentService` object get Content by its Id, set a few values
// and saves the Content through the `ContentService`
var content = contentService.GetById(1234);
content.SetValue(&amp;quot;bodyText&amp;quot;, &amp;quot;This text will be added to by RTE field&amp;quot;);
content.SetValue(&amp;quot;date&amp;quot;, DateTime.Now);
contentService.Save(content);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note the &lt;code&gt;DateTime.Now&lt;/code&gt; instance there. Unfortunately support for the different types seems extremely limited. Passing a float causes the following exception.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The best overloaded method match for
'Umbraco.Core.Models.ContentBase.SetPropertyValue(string, string)' has
some invalid arguments.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Yowza! That really doesn't give a great developer experience.&lt;/p&gt;
&lt;h3&gt;Magic Strings&lt;/h3&gt;
&lt;p&gt;Not much in Umbraco when dealing with content is strong-typed. If I were to hazard a guess as to why, &lt;del&gt;I would imagine it was because the code tooling to do some of the conversion functionality we can now was not available when the API's were designed.&lt;/del&gt; (&lt;strong&gt;Update&lt;/strong&gt; Turns out it was just a design decision). I have, however, felt the distinct impression at times through conversation that strong-typing is not wanted in certain areas. &lt;/p&gt;
&lt;p&gt;I'm doing my best to provide it to developers when dealing with the cached  &lt;code&gt;IPublishedContent&lt;/code&gt; methods by contributing to &lt;a href="https://github.com/leekelleher/umbraco-ditto"&gt;Ditto&lt;/a&gt;. Content services, however, are not part of the scope for that project so having spent so much time developing with Umbraco in a strong-typed manner, coming across them here was a bit of a shock.&lt;/p&gt;
&lt;p&gt;Let's look at that method again.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IContentBase.SetValue(string propertyAlias, object value);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first parameter accepts a string. Now I don't know about you but the most common use case I would imagine for the method would be uploading a form or importing content through another service. &lt;/p&gt;
&lt;p&gt;That form or service would contain classes with properties and using the API in this format would require the developer to insert magic strings for every property or use reflection to loop through with the property info name manipulating them for each instance. &lt;/p&gt;
&lt;p&gt;Not code I want to write...&lt;/p&gt;
&lt;h3&gt;Expression Trees to the Rescue!&lt;/h3&gt;
&lt;p&gt;I wanted a way that I could call the method in the following format and not have to write those pesky strings:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IContentBase.SetValue(() =&amp;gt; Class.Property);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In order to do that I will need to create an extension method that uses an &lt;a href="https://msdn.microsoft.com/en-us/library/bb397951.aspx?f=255&amp;amp;MSPPError=-2147217396"&gt;Expression Tree&lt;/a&gt;. This is done by  creating a Lambda Expression to represent the property.&lt;/p&gt;
&lt;p&gt;Once inside our method we check to see whether, a property is being passed, and if so, coerce the various property values to call the old method with sanitized values.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// Sets the value of an &amp;lt;see cref=&amp;quot;IContentBase&amp;quot;/&amp;gt; property to the given value.
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name=&amp;quot;contentBase&amp;quot;&amp;gt;
/// The &amp;lt;see cref=&amp;quot;IContentBase&amp;quot;/&amp;gt;.
/// &amp;lt;/param&amp;gt;
/// &amp;lt;param name=&amp;quot;propertyLambda&amp;quot;&amp;gt;
/// The &amp;lt;see cref=&amp;quot;Expression&amp;quot;/&amp;gt; designating the value to save.
/// &amp;lt;/param&amp;gt;
/// &amp;lt;typeparam name=&amp;quot;T&amp;quot;&amp;gt;
/// The &amp;lt;see cref=&amp;quot;Type&amp;quot;/&amp;gt; of the property value.
/// &amp;lt;/typeparam&amp;gt;
/// &amp;lt;exception cref=&amp;quot;ArgumentException&amp;quot;&amp;gt;
/// Thrown if the given &amp;lt;see cref=&amp;quot;Expression&amp;quot;/&amp;gt; is not in the correct form.
/// &amp;lt;/exception&amp;gt;
public static void SetValue&amp;lt;T&amp;gt;(this IContentBase contentBase, Expression&amp;lt;Func&amp;lt;T&amp;gt;&amp;gt; propertyLambda)
{
    MemberExpression expression = propertyLambda.Body as MemberExpression;

    if (expression == null)
    {
        throw new ArgumentException(&amp;quot;You must pass a lambda of the form: '() =&amp;gt; Class.Property' or '() =&amp;gt; object.Property'&amp;quot;);
    }

    PropertyInfo property = expression.Member as PropertyInfo;
    if (property != null)
    {
        MemberExpression member = (MemberExpression)expression.Expression;
        ConstantExpression constant = (ConstantExpression)member.Expression;
        object fieldInfoValue = ((FieldInfo)member.Member).GetValue(constant.Value);
        object value = property.GetValue(fieldInfoValue, null);
        string name = property.Name.ToSafeAlias(true);
        contentBase.SetValue(name, value.ToString());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It's basic and doesn't take into account type conversion to and from strings, nor existing supported types but it's certainly a step in the right direction and better than what was there before.&lt;/p&gt;
&lt;p&gt;Obviously, also, there is a an element of assumption in that technique in that we cannot predict what the alias will be and can only go on the most likely name based on the property. Personally though I don't believe the alias should be human editable and should be abstracted away with greater convention. That allows greater predictability and better quality code.&lt;/p&gt;
&lt;p&gt;I would like to see more API signatures in Umbraco like the example I have created and would be more than happy to help try to tighten up the various APIs for the next major version.&lt;/p&gt;
&lt;p&gt;Let me know what you think.&lt;/p&gt;
</description>
      <pubDate>Wed, 25 Mar 2015 10:59:31 Z</pubDate>
      <a10:updated>2015-03-25T10:59:31Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1118</guid>
      <link>http://jamessouth.me/archive/announcing-imageprocessorwebpostprocessor/</link>
      <category>System.String[]</category>
      <title>Announcing ImageProcessor.Web.PostProcessor</title>
      <description>&lt;h2&gt;The Nourishing Fruits of Boredom&lt;/h2&gt;
&lt;p&gt;So last night I got a little bored watching the old haunted fishtank and my mind, as it often does, drifted to code.&lt;/p&gt;
&lt;p&gt;I started thinking about a &lt;a href="http://stream.umbraco.org/video/9950321/the-future-of-aspnet-web-tooling"&gt;talk&lt;/a&gt; that &lt;a href="https://twitter.com/mkristensen"&gt;Mads Kristensen&lt;/a&gt; gave at CodeGarden this year that featured a tool he had written with &lt;a href="https://twitter.com/sayedihashimi"&gt;Sayed I. Hashimi&lt;/a&gt; called Azure Image Optimizer which wraps various tools like Jpegtran and Gifsicle in an Azure Job to optimize your file based images. He writes about it &lt;a href="http://madskristensen.net/post/automatic-optimization-of-images-css-and-javascript"&gt;here&lt;/a&gt; and the source can be found &lt;a href="https://github.com/ligershark/AzureJobs"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I thought it was really nifty and since they've kindly released it under the wonderfully permissive Apache 2.0 license I decided to see if I could grab some of the goodies from the code and add something to &lt;a href="http://imageprocessor.org/imageprocessor-web/"&gt;ImageProcessor.Web&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Three hours later &lt;a href="https://www.nuget.org/packages/ImageProcessor.Web.PostProcessor/"&gt;ImageProcessor.Web.PostProcessor&lt;/a&gt; was born...&lt;/p&gt;
&lt;h2&gt;How It Works&lt;/h2&gt;
&lt;p&gt;ImageProcessor.Web fires an event once an image has been processed and saved to the cache that can be wired up to asynchronously to further manipulate that file. Tapping into it is  fairly simple.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ImageProcessingModule.OnPostProcessing += YOUR_POST_PROCESSING_METHOD_ASYNC;

private static async void YOUR_POST_PROCESSING_METHOD_ASYNC(object sender, PostProcessingEventArgs e)
{
     // Do your thang...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Where &lt;code&gt;PostProcessingEventArgs&lt;/code&gt; contains a single property &lt;code&gt;CachedImagePath&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In ImageProcessor.Web.PostProcessor I have embedded copies of the various image compressing tools: &lt;a href="http://www.lcdf.org/gifsicle/"&gt;Gifsicle&lt;/a&gt;, &lt;a href="http://jpegclub.org/jpegtran/"&gt;Jpegtran&lt;/a&gt;, &lt;a href="http://optipng.sourceforge.net/"&gt;Optipng&lt;/a&gt;, and &lt;a href="http://advsys.net/ken/utils.htm"&gt;Pngout&lt;/a&gt; which are extracted into the running web applications folder and are used to further compress the cached images whenever the event is fired. &lt;/p&gt;
&lt;p&gt;If a saving can be found then the cached file is replaced with the newly optimized image and voila your fancy-dancy website is now even leaner and you can celebrate by having a beverage of your choice. &lt;/p&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;p&gt;Simply install the &lt;a href="https://www.nuget.org/packages/ImageProcessor.Web.PostProcessor/"&gt;package&lt;/a&gt; from Nuget and it will instantly kick in; there's no configuration required so go and get it now.&lt;/p&gt;
&lt;p&gt;As ever the source code can be found &lt;a href="https://github.com/JimBobSquarePants/ImageProcessor"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Cheers M'dears!&lt;/p&gt;
</description>
      <pubDate>Thu, 18 Dec 2014 02:32:46 Z</pubDate>
      <a10:updated>2014-12-18T02:32:46Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1117</guid>
      <link>http://jamessouth.me/archive/cruncher-v3/</link>
      <category>System.String[]</category>
      <title>Cruncher v3</title>
      <description>&lt;h1&gt;No More &lt;kbd&gt;Ctrl-F5&lt;/kbd&gt;&lt;/h1&gt;
&lt;p&gt;Last night  at a ridiculous hour I released the latest version of my asset preprocessor for .NET&lt;/p&gt;
&lt;p&gt;Cruncher is a cool bit of kit. It makes optimizing your resources easy. It can bundle unlimited combinations of remote and local CSS, Less, Sass, JavaScript, and CoffeeScript files. Like really... Mix and match them anyway you like and Cruncher will preprocess them accordingly and produce links to the processed output.&lt;/p&gt;
&lt;p&gt;Cruncher can handle nested CSS &lt;code&gt;@import&lt;/code&gt; statements, re-maps relative resource urls and has a self cleaning cache should any changes be made to any of the referenced files. It can also parse CSS and add vendor prefixes to rules by &lt;a href="http://caniuse.com/"&gt;Can I Use&lt;/a&gt; using &lt;a href="https://github.com/postcss/autoprefixer"&gt;AutoPrefixer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can, and most definitely should get it &lt;a href="https://www.nuget.org/packages/Cruncher/"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;How it works&lt;/h2&gt;
&lt;p&gt;When processing a collection of inputs, Cruncher will identify the content type and apply the correct preprocessor to the input converting it to CSS or JavaScript accordingly. CSS files are then passed through an AutoPrefixer postprocessor if it is enabled (By default it is). It will then, if you are running in release mode minify the output using the &lt;a href="http://ajaxmin.codeplex.com/"&gt;Microsoft Ajax Minifier&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Finally links are produced in the page as follows.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/assets-cruncher/-1287271604.css&amp;quot;&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;/assets-cruncher/-1661000378.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Where the name is the hash of the combined output. This allows the native static file handler to take over which is great for performance (though all this activity is also heavily cached both in the browser and the server).  If any changes are detected by file monitors for each file and imported files then the number will change which forces the browser to request the updated output. That allows instant propagation of changes made to the input files. No More &lt;kbd&gt;Ctrl-F5&lt;/kbd&gt;!&lt;/p&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;p&gt;It really couldn't be easier. Simply add &lt;code&gt;@using Cruncher&lt;/code&gt; to your view and use the following methods to add resources. This all works in webforms syntax also.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Default.
@CruncherBundler.RenderCSS(&amp;quot;style.css&amp;quot;, &amp;quot;style.less&amp;quot;, &amp;quot;style.scss&amp;quot;)

// Render the link wth a media query.
@CruncherBundler.RenderCSS(new HtmlString(&amp;quot;media=\&amp;quot;(max-width: 800px)\&amp;quot;&amp;quot;), &amp;quot;style.css&amp;quot;, &amp;quot;style.less&amp;quot;, &amp;quot;style.scss&amp;quot;)

// Default.
@CruncherBundler.RenderJavaScript(&amp;quot;jquery-2.1.1&amp;quot;, &amp;quot;test.coffee&amp;quot;, &amp;quot;test.js&amp;quot;)

// Render the script with the 'async' boolean enabled.
@CruncherBundler.RenderJavaScript(JavaScriptLoadBehaviour.Async, &amp;quot;jquery-2.1.1&amp;quot;, &amp;quot;test.coffee&amp;quot;, &amp;quot;test.js&amp;quot;)

// Render the script with the 'defer' boolean enabled.
@CruncherBundler.RenderJavaScript(JavaScriptLoadBehaviour.Defer, &amp;quot;jquery-2.1.1&amp;quot;, &amp;quot;test.coffee&amp;quot;, &amp;quot;test.js&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There's a great writeup of the &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;defer&lt;/code&gt; attributes &lt;a href="http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Feel free to have a good look through the &lt;a href="https://github.com/JimBobSquarePants/Cruncher"&gt;sourcecode&lt;/a&gt;. It's all, as ever, open source under the Apache 2.0 license and contributions are most welcome.&lt;/p&gt;
&lt;h2&gt;Thanks&lt;/h2&gt;
&lt;p&gt;I'd very much like to thank both &lt;a href="https://github.com/Alain-es"&gt;Alain (I'm so sorry I have forgotten your surname)&lt;/a&gt; for providing some simply awesome ideas and code and &lt;a href="https://github.com/jbreuer"&gt;Jeroen Breuer&lt;/a&gt; for reporting bugs and providing me with projects to tests against for this release. You both got me revisiting code I'd long forgotten about and didn't realise anyone was using. &lt;/p&gt;
</description>
      <pubDate>Sun, 30 Nov 2014 03:17:44 Z</pubDate>
      <a10:updated>2014-11-30T03:17:44Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1116</guid>
      <link>http://jamessouth.me/archive/imageprocessorweb-410-released/</link>
      <category>System.String[]</category>
      <title>ImageProcessor.Web 4.1.0 Released!</title>
      <description>&lt;p&gt;Following yesterdays &lt;a href="http://jamessouth.me/archive/imageprocessor-210-released/"&gt;post&lt;/a&gt; charting the updates in the the core ImageProcessor library I'm going to take the time to chart the updates in the new 4.1.0 release of &lt;a href="https://www.nuget.org/packages/ImageProcessor.Web/"&gt;ImageProcessor.Web&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;New Stuff&lt;/h1&gt;
&lt;h3&gt;Methods&lt;/h3&gt;
&lt;p&gt;All the new methods available to ImageProcessor are available to ImageProcessor.Web. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pixelate &lt;/li&gt;
&lt;li&gt;DetectEdges &lt;/li&gt;
&lt;li&gt;EntropyCrop &lt;/li&gt;
&lt;li&gt;Mask &lt;/li&gt;
&lt;li&gt;Overlay &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Syntactically they are invoked using familiar rules similar to preexisting methods.&lt;/p&gt;
&lt;p&gt;For example.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://your-image?detectedges=prewitt&amp;amp;greyscale=false
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Will produce an image with a &lt;a href="http://en.wikipedia.org/wiki/Prewitt_operator"&gt;Prewitt&lt;/a&gt; operator applied that also retains the original image colours.&lt;/p&gt;
&lt;h3&gt;Original&lt;/h3&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1024/mana.jpg" alt="enter image description here" /&gt;&lt;/p&gt;
&lt;h3&gt;Processed&lt;/h3&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1024/mana.jpg?detectedges=prewitt&amp;amp;greyscale=false" alt="enter image description here" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Swish!&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Handling Images in Instructions&lt;/h3&gt;
&lt;p&gt;Two of the new methods: &lt;a href="http://imageprocessor.org/imageprocessor-web/imageprocessingmodule/mask.html"&gt;Mask&lt;/a&gt; &amp;amp; &lt;a href="http://imageprocessor.org/imageprocessor-web/imageprocessingmodule/overlay.html"&gt;Overlay&lt;/a&gt; accept images as parameters in part of their instruction sets. 
Rather than passing the entire path to the url (which would open up all sorts of security issues) you set the image name only as a parameter. These are mapped to two preconfigured locations.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mask- &lt;code&gt;~/images/imageprocessor/mask/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Overlay - &lt;code&gt;~/images/imageprocessor/overlay/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These can both be overwritten by installing the &lt;a href="https://www.nuget.org/packages/ImageProcessor.Web.Config/"&gt;ImageProcessor.Web.Config&lt;/a&gt; package from Nuget and changing the settings in the &lt;code&gt;processing.config&lt;/code&gt;
file.&lt;/p&gt;
&lt;p&gt;Here's the two of them in action.&lt;/p&gt;
&lt;h3&gt;Mask&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;http://your-image??mask=mask.png&amp;amp;mask.position=30,30&amp;amp;format=png
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Original&lt;/h3&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1022/lock.jpg" alt="Locks on a gate" /&gt;&lt;/p&gt;
&lt;h3&gt;Masked&lt;/h3&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1022/lock.jpg?mask=mask.png&amp;amp;mask.position=30,30&amp;amp;format=png" alt="Masked image of locks on a gate" /&gt;&lt;/p&gt;
&lt;h3&gt;Overlay&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;http://your-image?overlay=monster.png&amp;amp;overlay.position=30,30&amp;amp;overlay.size=100,100&amp;amp;overlay.opacity=80
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Original&lt;/h3&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1042/bear.jpg" alt="A Grizzly bear" /&gt;&lt;/p&gt;
&lt;h3&gt;Overlay Applied&lt;/h3&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1042/bear.jpg?overlay=monster.png&amp;amp;overlay.position=30,30&amp;amp;overlay.size=100,100&amp;amp;overlay.opacity=80" alt="A Grizzly bear" /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;Moar New Stuff&lt;/h1&gt;
&lt;h3&gt;IImageService&lt;/h3&gt;
&lt;p&gt;With this version comes a new system for supplying ImageProcessor.Web images to process; &lt;code&gt;IImageService&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;The &lt;code&gt;IImageService&lt;/code&gt; interface defines methods and properties which allow developers to extend ImageProcessor.Web to retrieve images from alternate locations to process. Think pulling images from from a &lt;a href="https://www.simple-talk.com/sql/learn-sql-server/an-introduction-to-sql-server-filestream/"&gt;SqlServer filestream&lt;/a&gt; or from another custom service.&lt;/p&gt;
&lt;p&gt;Creating a new service simply requires implementing the interface to supply a prefix and a byte array.&lt;/p&gt;
&lt;p&gt;The interface looks like this.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
///  Defines properties and methods for allowing retrieval of image from different sources.
/// &amp;lt;/summary&amp;gt;
public interface IImageService
{
    /// &amp;lt;summary&amp;gt;
    /// Gets or sets the prefix for the given implementation.
    /// &amp;lt;remarks&amp;gt;
    /// This value is used as a prefix for any image requests that should use this service.
    /// &amp;lt;/remarks&amp;gt;
    /// &amp;lt;/summary&amp;gt;
    string Prefix { get; set; }
    /// &amp;lt;summary&amp;gt;
    /// Gets a value indicating whether the image service requests files from
    /// the locally based file system.
    /// &amp;lt;/summary&amp;gt;
    bool IsFileLocalService { get; }
    /// &amp;lt;summary&amp;gt;
    /// Gets or sets any additional settings required by the service.
    /// &amp;lt;/summary&amp;gt;
    Dictionary&amp;lt;string, string&amp;gt; Settings { get; set; }
    /// &amp;lt;summary&amp;gt;
    /// Gets or sets the white list of &amp;lt;see cref=&amp;quot;System.Uri&amp;quot; /&amp;gt;. 
    /// &amp;lt;/summary&amp;gt;
    Uri[] WhiteList { get; set; }
    /// &amp;lt;summary&amp;gt;
    /// Gets a value indicating whether the current request passes sanitizing rules.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name=&amp;quot;path&amp;quot;&amp;gt;
    /// The image path.
    /// &amp;lt;/param&amp;gt;
    /// &amp;lt;returns&amp;gt;
    /// &amp;lt;c&amp;gt;True&amp;lt;/c&amp;gt; if the request is valid; otherwise, &amp;lt;c&amp;gt;False&amp;lt;/c&amp;gt;.
    /// &amp;lt;/returns&amp;gt;
    bool IsValidRequest(string path);
    /// &amp;lt;summary&amp;gt;
    /// Gets the image using the given identifier.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name=&amp;quot;id&amp;quot;&amp;gt;
    /// The value identifying the image to fetch.
    /// &amp;lt;/param&amp;gt;
    /// &amp;lt;returns&amp;gt;
    /// The &amp;lt;see cref=&amp;quot;System.Byte&amp;quot; /&amp;gt; array containing the image data.
    /// &amp;lt;/returns&amp;gt;
    Task&amp;lt;byte[]&amp;gt; GetImage(object id);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Both the local and remote image service implement this interface. View the &lt;a href="https://github.com/JimBobSquarePants/ImageProcessor/tree/master/src/ImageProcessor.Web/Services"&gt;source code&lt;/a&gt; to see examples.&lt;/p&gt;
&lt;h1&gt;Extras&lt;/h1&gt;
&lt;p&gt;With this release I upped the cache to hold 100 images per folder. This now increases the theoretical cache limit to &lt;strong&gt;409,600,000,000&lt;/strong&gt; images though I don't think anyone will be hitting that kind of limit any time soon.&lt;/p&gt;
&lt;p&gt;There's a few performance improvements thrown in also that will make things snappier than ever.&lt;/p&gt;
&lt;h1&gt;In Summary&lt;/h1&gt;
&lt;p&gt;I'm pleased with this release and the benefits it offers. There's only a few feature I think that ImageProcessor.Web is missing (Face detection being one) so I hope  you are enjoying using it as much as I do building it.&lt;/p&gt;
</description>
      <pubDate>Wed, 12 Nov 2014 06:14:43 Z</pubDate>
      <a10:updated>2014-11-12T06:14:43Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1115</guid>
      <link>http://jamessouth.me/archive/imageprocessor-210-released/</link>
      <category>System.String[]</category>
      <title>ImageProcessor 2.1.0 Released!</title>
      <description>&lt;p&gt;Today marks the release of the latest version of &lt;a href="http://imageprocessor.org/"&gt;ImageProcessor&lt;/a&gt; My super, fantastic open source imaging library.&lt;/p&gt;
&lt;p&gt;This is a pretty big release with a multitude of new functionality, performance improvements and bug fixes. I'll run through some of them here and try not to ramble on too much in the process. It's gonna be very image heavy so I recommend a broadband connection.&lt;/p&gt;
&lt;h1&gt;New Stuff&lt;/h1&gt;
&lt;h2&gt;Pixelate&lt;/h2&gt;
&lt;p&gt;This new method allows you to pixelate an image by passing a pixel size to the &lt;code&gt;ImageFactory&lt;/code&gt; in the following format.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public ImageFactory Pixelate(int pixelSize, Rectangle? rectangle = null)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If a rectangle is passed that will constrain the method to only pixelate a portion of the original image.&lt;/p&gt;
&lt;h3&gt;Original&lt;/h3&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1042/bear.jpg" alt="Original picture of a really cool bear" /&gt;&lt;/p&gt;
&lt;h3&gt;Pixelated&lt;/h3&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1042/bear.jpg?pixelate=10" alt="Pixilated picture of a really cool bear" /&gt;&lt;/p&gt;
&lt;p&gt;Cool eh?&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;DetectEdges&lt;/h2&gt;
&lt;p&gt;This method allows you to detect points within an image where the brightness changes sharply. There's lots of different algorithms available to do this using some pretty wild maths see &lt;a href="http://en.wikipedia.org/wiki/Edge_detection"&gt;Wikipedia&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The method is called as follows.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public ImageFactory DetectEdges(IEdgeFilter filter, bool greyscale = true)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I've added 9 different detection methods to get started with.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;KayyaliEdgeFilter &lt;/li&gt;
&lt;li&gt;KirschEdgeFilter &lt;/li&gt;
&lt;li&gt;Laplacian3X3EdgeFilter&lt;/li&gt;
&lt;li&gt;Laplacian5X5EdgeFilter &lt;/li&gt;
&lt;li&gt;LaplacianOfGaussianEdgeFilter&lt;/li&gt;
&lt;li&gt;PrewittEdgeFilter &lt;/li&gt;
&lt;li&gt;RobertsCrossEdgeFilter &lt;/li&gt;
&lt;li&gt;ScharrEdgeFilter&lt;/li&gt;
&lt;li&gt;SobelEdgeFilter&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here an example of it in action using the &lt;code&gt;PrewittEdgeFilter&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Original&lt;/h3&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1045/bridge.jpg" alt="Original picture of a bridge" /&gt;&lt;/p&gt;
&lt;h3&gt;Edges Detected&lt;/h3&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1045/bridge.jpg?detectedges=prewitt" alt="Greyscale picture of a bridge with edges detected" /&gt;&lt;/p&gt;
&lt;h3&gt;Edges Detected  - Keeping Original Colours&lt;/h3&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1045/bridge.jpg?detectedges=prewitt&amp;amp;greyscale=false" alt="Picture of a bridge with edges detected" /&gt;&lt;/p&gt;
&lt;p&gt;Edge detection is one of the fundamental tools of image processing. I use it internally for this method.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;EntropyCrop&lt;/h2&gt;
&lt;p&gt;This one I built for my good friend &lt;a href="https://twitter.com/crumpled_jeavon"&gt;Jeavon Leopold&lt;/a&gt; who preyed upon by inability to resist a challenge. It looks for the area of highest entropy within an image and crops around it. It works particularly well with images containing large areas of a single color or similar colors around the edges.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public ImageFactory EntropyCrop(byte threshold = 128)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Original&lt;/h3&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1014/field.jpg" alt="Picture of a field" /&gt;&lt;/p&gt;
&lt;h3&gt;Cropped to Area of Highest Entropy&lt;/h3&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1014/field.jpg?entropycrop=128" alt="Picture of a field cropped" /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;There's three other new methods added to the &lt;code&gt;Imagefactory&lt;/code&gt; class but I'll just link to the docs as I don't want to go on.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://imageprocessor.org/imageprocessor/imagefactory/replacecolor.html"&gt;ReplaceColor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://imageprocessor.org/imageprocessor/imagefactory/mask.html"&gt;Mask&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://imageprocessor.org/imageprocessor/imagefactory/overlay.html"&gt;Overlay&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Moar New Stuff&lt;/h2&gt;
&lt;p&gt;In this release I've also managed to add a shiny new quantizer based on a vastly improved version of &lt;a href="http://nquant.codeplex.com/"&gt;nQuant&lt;/a&gt;. This dramatically improves the output of indexed png files.
Considering these images contain only 256 colors the output is extraordinary! &lt;/p&gt;
&lt;h3&gt;Original&lt;/h3&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1027/new-york.jpg" alt="New York Scene" /&gt;&lt;/p&gt;
&lt;h3&gt;Indexed PNG&lt;/h3&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1027/new-york.jpg?format=png8" alt="New York Scene" /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;Performance&lt;/h1&gt;
&lt;p&gt;Performance under the hood has been vastly improved. Using a combination of Parallelisation techniques and a new &lt;a href="https://github.com/JimBobSquarePants/ImageProcessor/blob/master/src/ImageProcessor/Imaging/FastBitmap.cs"&gt;FastBitmap&lt;/a&gt; class I was able to improve methods such as &lt;code&gt;GaussianBlur&lt;/code&gt; by up to 7X which was very pleasing.  Every single method that could be has been rewritten to take advantage of the new techniques which has made ImageProcessor purr like a wolverine.&lt;/p&gt;
&lt;p&gt;I've also been testing continuously to ensure that memory usage is kept consistently low  - I'm very pleased with the results.&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;Bug Fixes&lt;/h1&gt;
&lt;p&gt;Version 2.1 now correctly handles images of different resolutions. In some circumstances it was possible to throw certain combinations of methods off  like &lt;code&gt;Resize&lt;/code&gt; and &lt;code&gt;Rotate&lt;/code&gt; for example by passing them an image of a higher resolution than the default 96dpi. This has now been fixed.&lt;/p&gt;
&lt;p&gt;I've also fixed a timing ( rounding error) issue within animated gifs and an encoding one which was making them impossible to share on Twitter. You can now share them anywhere you like.&lt;/p&gt;
&lt;p&gt;On that note I bet you didn't realise that all the methods can be applied to animated gifs did you?&lt;/p&gt;
&lt;p&gt;&lt;img src="http://jamessouth.me/blog/media/1003/mccoy-kirk.gif?pixelate=8&amp;amp;rotate=45" alt="Pixelated, rotated Kirk" /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;Anyhoo&lt;/h1&gt;
&lt;p&gt;I hope this has got you all excited and you find it useful. &lt;/p&gt;
&lt;p&gt;This release has been a &lt;strong&gt;LOT&lt;/strong&gt; of hard work and as ever if you think you can help in anyway then please do. The .NET community needs a tool like this and I can only keep supporting and improving it with your help to please &lt;a href="https://github.com/JimBobSquarePants/ImageProcessor"&gt;Get Involved&lt;/a&gt;. &lt;/p&gt;
</description>
      <pubDate>Tue, 11 Nov 2014 07:14:07 Z</pubDate>
      <a10:updated>2014-11-11T07:14:07Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1114</guid>
      <link>http://jamessouth.me/archive/you-can-win/</link>
      <category>System.String[]</category>
      <title>You Can Win!</title>
      <description>&lt;p&gt;This is a post I'd like to share for &lt;a href="http://geekmentalhelp.com"&gt;Geek Mental Help Week&lt;/a&gt; in the hope that someone out there would find it helpful.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;I am very, very, lucky to be alive and I appreciate that fact every day. &lt;/p&gt;
&lt;p&gt;When I was about 24 something went wrong and I broke. I've no idea what the cause was, probably a multitude of things but I went, in what seemed to be a very short time, from being a confident, strong, happy guy to a complete wreck who wanted nothing more than to spare everyone the misery of being around me.&lt;/p&gt;
&lt;p&gt;In the following four and a half years I inflicted a multitude of horrible acts upon myself.&lt;/p&gt;
&lt;p&gt;I have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Slit my wrists &lt;/li&gt;
&lt;li&gt;Tried to hang myself, &lt;/li&gt;
&lt;li&gt;Taken multiple overdoses&lt;/li&gt;
&lt;li&gt;Starved myself&lt;/li&gt;
&lt;li&gt;Jumped out of a 3rd storey window&lt;/li&gt;
&lt;li&gt;Burned myself with an iron&lt;/li&gt;
&lt;li&gt;Tried to bleed myself out with a drip.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I distinctly remember lying in a hospital bed crying, throwing up over and over in reaction to Acetylcysteine (used in the treatment of Paracetamol overdose), and begging for a nurse to let me die.  I remember the single bloody-mindedness of slicing into my wrist with a Stanley knife despite the incredible pain. I remember the unpleasant sluggishness brought on as a side effect of the multiple medications I was on, and I remember waking up wishing I hadn't.&lt;/p&gt;
&lt;p&gt;It wasn't a pleasant time in my life.&lt;/p&gt;
&lt;p&gt;I was utterly convinced that I was a burden upon those around me, despite the constant care and love I received. My family and friends were incredibly supportive. In my head I had no discernible skills, no future and was a total waste of time and oxygen.&lt;/p&gt;
&lt;p&gt;And then I discovered writing code... &lt;/p&gt;
&lt;p&gt;I’d grown up with code around me. My dad used to make text adventure games for the Commodore 64 in his spare time, we always had a computer or five lying around but I only ever played games and did couple of very poorly taught lessons in Basic at school. I had no idea how awesome writing code could be.&lt;/p&gt;
&lt;p&gt;It’s the raw unadulterated logic of it all. Life has an unfortunate way of throwing up unsolvable problems at you. Work, money, relationships, so many things can go wrong without reasonable answers but code creates solutions. Sure there’s quirks in every language but they are reasoned or a consequence of poor design. It still all boils down to logic and I love logic. I love the little victories, the fist-pumps, and the immediate visible result of your work.&lt;/p&gt;
&lt;p&gt;I was backpacking around Australia in 2008 in a vain attempt to run away from everything when I decided to build a website for people doing the Harvest trail. I’d had very limited success finding farms that weren't intent on exploiting workers and I wanted to help other travellers avoid the bad places and reward the good - The government website was truly awful and I thought I could do better. I didn't have clue how to go about it but as soon as I read the first coding article online I was hooked, I read and absorbed everything I could get my hands upon and couldn't put my laptop down for months. It was amazing and made me feel like I was finally doing something important and useful.&lt;/p&gt;
&lt;p&gt;It was a total disaster. Almost impressively slow and clunky and nobody wanted to use it but I genuinely didn't care. (I’d love to have another go at it sometime, maybe when I finally move back out that way). I had found my vocation. I had and have a million other ideas and I want to code them all. &lt;/p&gt;
&lt;p&gt;Writing code gave me the focus I need to rebuild myself. It gave me the desperate breathing space my brain needed to let me re-evaluate everything sensibly and set myself firmly on the road to recovery. Whenever I needed a break from the world around me I could always depend on a few hours problem solving to set me back on the right path. With that new-found focus I spoke to doctors and counsellors, I read self-help material, took my medication, I was more honest with my friends and family and I took great care to look after myself. &lt;/p&gt;
&lt;p&gt;I got myself a job within a year and have worked hard to make a name for myself, giving back to the community whenever I can through my open source projects. Hopefully I've helped you, the reader, in some small way through writing this.&lt;/p&gt;
&lt;p&gt;It’s not all been sunshine and rainbows. I've had setbacks, some of them very major but I've always been able to fight back and found myself stronger as a result. I can be a grumpy shit at times but I've always had my code to turn to in times of trouble.&lt;/p&gt;
&lt;p&gt;I’ve not needed medication for almost three years now. I feel pretty much spectacularly awesome 99.99% of the time. I’ve rediscovered a very childlike joy in the simple things in life and I recommend to anyone and everyone to try and do the same. When I look back at the incidences of my past it feels like another lifetime.&lt;/p&gt;
&lt;p&gt;I honestly believe that the programmers are particularly prone to depression because we seek logical solutions in things that we cannot possibly control. The particular gifts we have that allow us to successfully solve difficult computational problems are our Achilles heel - We look for answers when there are none and beat ourselves up when we fail. &lt;/p&gt;
&lt;p&gt;My success in battling depression has been due to the ability to separate those types of problems. I guess it helped that I came to programming so late and I was immediately able to see the difference.&lt;/p&gt;
&lt;p&gt;If I have any advice to give is that you should try to do the same. Enjoy the little victories, don’t sweat in unwinnable situations. As long as you are trying, you are winning and nothing can take that away from you.&lt;/p&gt;
</description>
      <pubDate>Mon, 27 Oct 2014 12:06:11 Z</pubDate>
      <a10:updated>2014-10-27T12:06:11Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1112</guid>
      <link>http://jamessouth.me/archive/on-why-i-built-a-responsive-framework/</link>
      <category>System.String[]</category>
      <title>On Why I built a Responsive Framework</title>
      <description>&lt;h3&gt;Why?&lt;/h3&gt;
&lt;p&gt;One of the things a work on in my spare time is a &lt;a href="http://responsivebp.com"&gt;responsive framework&lt;/a&gt;. You might have already seen it.&lt;/p&gt;
&lt;p&gt;A few people have asked my why I built it, as there's already several popular frameworks out there. There's one answer I give every time:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Because I needed it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Complexity&lt;/h3&gt;
&lt;p&gt;The other, sadly more popular frameworks, are great pieces of work. A lot of effort has gone into building and testing them and they do a pretty good job for the most part. They all have the same problem though - They're all too design opinionated.&lt;/p&gt;
&lt;p&gt;If I'm  building a website the last thing I need to do is overwrite styles that have already been added by the base stylesheet. Every single change that you have to perform introduces greater opportunity for error and adds weight to the websites resources. Each change also introduces complexity and makes a website more difficult to maintain. &lt;/p&gt;
&lt;p&gt;That's the last thing I need when I'm working with a tight deadline hanging over me. &lt;/p&gt;
&lt;p&gt;Avoiding the issue of opinionated design has been paramount in the development of &lt;a href="http://responsivebp.com"&gt;Responsive&lt;/a&gt;. Every bit of CSS has been coded specifically not to force excessive styles on the developer. Only the required code is present to provide the functionality to build a cross-browser responsive experience&lt;/p&gt;
&lt;h3&gt;Accessibility&lt;/h3&gt;
&lt;p&gt;Another issue that isn't handled properly with other frameworks is accessibility. There's been meagre attempt to remedy this from other frameworks but for the most part they are a mess. I needed something that would handle the greater bulk of accessibility requirements without the developer having to do anything additional. As a result, every JavaScript component within &lt;a href="http://responsivebp.com"&gt;Responsive&lt;/a&gt; handles the creation and manipulation of &lt;a href="http://www.w3.org/TR/wai-aria/"&gt;ARIA&lt;/a&gt; attribution to ensure that its behaviour is accessible to screen readers.&lt;/p&gt;
&lt;h3&gt;Internationalisation&lt;/h3&gt;
&lt;p&gt;None of the frameworks that I am aware of have support for right-to-left languages built in. Developers shouldn't have to jump through hoops to do this. Grids, floated and positioned elements should switch, touchable components should reverse their behaviour, and directional keyboard events should reverse their behaviour all with the minimum of change required by the developer. &lt;a href="http://responsivebp.com"&gt;Responsive&lt;/a&gt; allows you to switch this by adding the attribute &lt;code&gt;dir=&amp;quot;rtl&amp;quot;&lt;/code&gt; to the html element&amp;#42;&lt;/p&gt;
&lt;h3&gt;In Summary&lt;/h3&gt;
&lt;p&gt;By now you should see why I created the framework and why both you and I should be developing our websites both responsive and fixed with &lt;a href="http://responsivebp.com"&gt;Responsive&lt;/a&gt;. Web development has never been more complicated, we're trying to do so much more with less time and more devices than ever before and we need the best setup possible to ensure that we can build performant, flexible, accessible sites. So give it a go, you'll be surprised at how much there is to offer.&lt;/p&gt;
&lt;p&gt;&amp;#42; &lt;em&gt;There has been conversation with other developers based on an outdated information in this &lt;a href="http://www.w3.org/International/questions/qa-html-dir"&gt;article&lt;/a&gt; that states that we should not do this as it reverses the position of the scrollbar in certain obsolete browsers. Instead, we should hack the document by adding a child element to the body setting the attribute on that. In my humble opinion that is ass-backwards (pun intended) If there is a browser bug in any of the non-obsolete browsers report it, don't hack around it.&lt;/em&gt;&lt;/p&gt;
</description>
      <pubDate>Tue, 02 Sep 2014 21:23:00 Z</pubDate>
      <a10:updated>2014-09-02T21:23:00Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1113</guid>
      <link>http://jamessouth.me/archive/image-processing-for-everybody/</link>
      <category>System.String[]</category>
      <title>Image Processing for Everybody!</title>
      <description>&lt;h2&gt;Happy ImageProcessing Day!&lt;/h2&gt;
&lt;p&gt;Today marks the new release of my open source project &lt;a href="http://imageprocessor.org/"&gt;ImageProcessor&lt;/a&gt;. I'm very proud of it.&lt;/p&gt;
&lt;p&gt;Inspired by the frantic codings of the brilliant people I met at this years &lt;a href="http://codegarden14.com/"&gt;Umbraco CodeGarden&lt;/a&gt; retreat this release has turned into an almost complete rewrite of the library. I've dramatically simplified the code required to write plugins whilst making the library much more robust and modular adding a few very cool (I think so anyway) features.&lt;/p&gt;
&lt;p&gt;We now have the following:&lt;/p&gt;
&lt;h3&gt;ImageProcessor&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Automatic image file type detection&lt;/li&gt;
&lt;li&gt;Automatic plugin detection&lt;/li&gt;
&lt;li&gt;Ability to extend image file type support via the &lt;code&gt;ISupportedImageFormat&lt;/code&gt; interface&lt;/li&gt;
&lt;li&gt;Ability to extend individual processors via the &lt;code&gt;IGraphicsProcessor&lt;/code&gt; interface &lt;/li&gt;
&lt;li&gt;Methods to load embedded native (unmanaged) libraries from within plugins&lt;/li&gt;
&lt;li&gt;True separation of concerns from the .Web extension.&lt;/li&gt;
&lt;li&gt;More specific error handling feedback&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;ImageProcessor.Web&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Automatic plugin detection&lt;/li&gt;
&lt;li&gt;Ability to extend individual processors via the &lt;code&gt;IWebGraphicsProcessor&lt;/code&gt; interface &lt;/li&gt;
&lt;li&gt;Improved and more consistent parsing syntax.&lt;/li&gt;
&lt;li&gt;Improved processing and caching performance&lt;/li&gt;
&lt;li&gt;More images are now cached (theoretically 409,600,000,000)&lt;/li&gt;
&lt;li&gt;Post processing events to tap into. &lt;code&gt;ImageProcessingModule.OnPostProcessing&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Improved error handling for remote image requests&lt;/li&gt;
&lt;li&gt;Url configurable EXIF preservation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There's more but it's probably best for you to read the &lt;a href="http://imageprocessor.org/"&gt;documentation&lt;/a&gt;. As ever, it's a work in progress but I've tried to make them readable and precise. If you want to help at any point to improve the library, there is always a good place to start.&lt;/p&gt;
&lt;p&gt;I'd really like to thank &lt;a href="http://www.hanselman.com/"&gt;Scott Hanselman&lt;/a&gt; for sharing the library on his blog and the &lt;a href="http://umbraco.com/"&gt;Umbraco&lt;/a&gt; team and community for their continuing support and faith in my ability. You guys absolutely rock! #h5yr's and approving nods all round! 
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;img src="http://jamessouth.me/blog/media/1003/mccoy-kirk.gif" alt="Kirk McCoy nodding original" /&gt;
&lt;img src="http://jamessouth.me/blog/media/1003/mccoy-kirk.gif?width=150" alt="Kirk McCoy nodding resized" /&gt;&lt;/p&gt;
</description>
      <pubDate>Wed, 27 Aug 2014 02:51:45 Z</pubDate>
      <a10:updated>2014-08-27T02:51:45Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1111</guid>
      <link>http://jamessouth.me/archive/filepath-too-long/</link>
      <category>System.String[]</category>
      <title>Filepath too long?</title>
      <description>&lt;p&gt;I thought I'd write this post as a reminder to myself and as a helper for anyone daft enough to try to use Node on a Windows machine.&lt;/p&gt;
&lt;p&gt;Node has a mental system for managing packages which involves deeply nesting dependencies in the &lt;code&gt;node_modules&lt;/code&gt; folder. This can lead to all sorts of problems on Windows machines like making the &lt;code&gt;--watch&lt;/code&gt; overload for Jekyll die on its ass.&lt;/p&gt;
&lt;p&gt;You can't even delete the damn thing properly due to Windows path constraints. It's really annoying to say the least but at least they know about &lt;a href="https://github.com/npm/npm/issues/3697"&gt;it&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here's a quick method I use to remove the folder when I need to.&lt;/p&gt;
&lt;p&gt;Open a command prompt or whatever your shell tool of choice is, navigate to the parent folder of the &lt;code&gt;node_modules&lt;/code&gt; folder and type in the following commands:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir foo
robocopy foo node_modules /MIR
del foo
del node_modules
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This command uses the &lt;a href="http://technet.microsoft.com/en-us/library/cc733145.aspx"&gt;robocopy utility&lt;/a&gt; and the /MIR &amp;quot;mirror&amp;quot; flag to mirror the empty &lt;code&gt;foo&lt;/code&gt;  directory to the &lt;code&gt;node_modules&lt;/code&gt; folder emptying it out. You can then delete both directories.&lt;/p&gt;
&lt;p&gt;Voilà :)&lt;/p&gt;
</description>
      <pubDate>Tue, 05 Aug 2014 13:57:28 Z</pubDate>
      <a10:updated>2014-08-05T13:57:28Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1110</guid>
      <link>http://jamessouth.me/archive/a-call-to-arms/</link>
      <category>System.String[]</category>
      <title>A Call To Arms</title>
      <description>&lt;blockquote&gt;
&lt;p&gt;The popularity of the Internet is the most important single development in the world of computing since the IBM PC was introduced in 1981. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Bill Gates was quoted as saying that. I'd go further. &lt;/p&gt;
&lt;p&gt;I believe that the Internet is the &lt;strong&gt;single most important invention we have ever created&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;With the Internet we can now universally share information like never before. We can pool resources to solve problems, provide education resources for each other and future generations, and provide support and services (sometimes lifesaving) for almost all our needs. It has revolutionised almost every aspect of our interaction as a species with billions of people now having access to the largest, free, information portal that has ever been created. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The internet is a Good Thing&lt;/strong&gt; &amp;#0153;&lt;/p&gt;
&lt;p&gt;I am a web developer. I imagine that you, reading this are one also. As such we possess a unique and special set of skills that allow us to create software to expand upon and improve the Internet. I believe that as developers we have an obligation, I would say a privileged one, to &lt;strong&gt;ensure that every single piece of work we produce is delivered to the highest possible standard&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To do that requires effort on our part. It requires dedication, passion, craftsmanship, and an attention to detail.&lt;/p&gt;
&lt;p&gt;At present I don't believe as a profession we do this. I won't go into specific technical details with this post but I will list some of the common mistakes I see professionals make on a daily basis.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Multiple blocking requests of unminified resources in the head of the document.&lt;/li&gt;
&lt;li&gt;Incorrect use of elements rendering websites inaccessible.&lt;/li&gt;
&lt;li&gt;Sporadic, in-line JavaScript and CSS. &lt;/li&gt;
&lt;li&gt;Unoptimized, massive image requests increasing page weight.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;This is bread and butter stuff, day one stuff and we really should do better.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So here is my challenge to you: Every time you release a piece of work, ask yourself whether it is the best that you can do. Is it fast, lightweight? Is it accessible? Have you followed the defined standards? Have you tested it?&lt;/p&gt;
&lt;p&gt;If you haven't, you are doing not only yourself a disservice but also one to the people who consume your work, who depend on your work and you should question your fitness for such an important role.&lt;/p&gt;
&lt;p&gt;Strong words I know but we have a duty of care.&lt;/p&gt;
</description>
      <pubDate>Sat, 26 Jul 2014 12:54:03 Z</pubDate>
      <a10:updated>2014-07-26T12:54:03Z</a10:updated>
    </item>
  </channel>
</rss>