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

<channel>
	<title>BeaverBlog &#187; imagergallery</title>
	<atom:link href="http://blog.crazybeavers.se/index.php/archive/tag/imagergallery/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.crazybeavers.se</link>
	<description>A beaver bloging about webdevelopment, XML and .Net</description>
	<lastBuildDate>Tue, 26 Jul 2011 10:59:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.1</generator>
		<item>
		<title>Någonting Större, my latest project</title>
		<link>http://blog.crazybeavers.se/index.php/archive/nagonting-storre-my-latest-project/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/nagonting-storre-my-latest-project/#comments</comments>
		<pubDate>Wed, 08 Dec 2010 07:22:25 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Beaver]]></category>
		<category><![CDATA[Portfolio]]></category>
		<category><![CDATA[beaversite]]></category>
		<category><![CDATA[imagergallery]]></category>

		<guid isPermaLink="false">http://blog.crazybeavers.se/?p=193</guid>
		<description><![CDATA[I just got around to publish my latest project. It&#8217;s a site for a christian festival/conference called Någonting Större (Something Greater or Something Larger in English). It has taken a while but it turned out really great (mainly because I didn&#8217;t have to do to much work with the design) and hopefully many other great [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.crazybeavers.se/wp-content/uploads/2010/03/fa1b9318c3323fad7f682069ac46502e1.png"><img src="http://blog.crazybeavers.se/wp-content/uploads/2010/03/fa1b9318c3323fad7f682069ac46502e1-142x300.png" alt="www.nagontingstorre.se" title="Någonting Större" width="142" height="300" class="aligncenter size-medium wp-image-168" /></a></p>
<p>I just got around to publish my latest project. It&#8217;s a site for a christian festival/conference called Någonting Större (Something Greater or Something Larger in English). It has taken a while but it turned out really great (mainly because I didn&#8217;t have to do to much work with the design) and hopefully many other great things will come out of the codebase (called BeaverSite, a CMS built with ASP.Net MVC which works GREAT!). A lot of code in this project is also shared with other projects such as BeaverShop and Imager Gallery.Net which both speed up this project and at the same time progressed the others. You can see the page in its full glory at <a href="http://www.xn--ngontingstrre-pfb8x.se/">http://www.någontingstörre.se/</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/nagonting-storre-my-latest-project/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ActionFilters in MVC</title>
		<link>http://blog.crazybeavers.se/index.php/archive/actionfilters-in-mvc/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/actionfilters-in-mvc/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 10:17:13 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[Code samples]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[imagergallery]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[sample]]></category>

		<guid isPermaLink="false">http://blog.crazybeavers.se/?p=124</guid>
		<description><![CDATA[I&#8217;ve been working on two fairly large MVC-projects lately. ImagerGallery.Net and a webshop-application suitably named BeaverShop. While working on those projects I&#8217;ve realized that I just love being able to use ActionFilters in MVC. Basically, they are attributes that you append to action-methods. They can be used to validate input, parse data into more suitable [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on two fairly large MVC-projects lately. ImagerGallery.Net and a webshop-application suitably named BeaverShop. While working on those projects I&#8217;ve realized that I just love being able to use ActionFilters in MVC. Basically, they are attributes that you append to action-methods. They can be used to validate input, parse data into more suitable structures, check security and lots more.</p>
<p>One of my most used filters in both ImagerGallery and BeaverShop is one I named PagingAttribute which I thought I should show to you today.</p>
<p>Any ActionFilter need to inherit the ActionFilterAttribute and implement at least one of the following methods: OnActionExecuting, OnActionExecuted, OnResultExecuting or OnResultExecuted. They are all called during different stages of the execution of an action-method and can be used for various things. The one I&#8217;ll be using is OnActionExecuting since it is executed before the action so that I can pass extra arguments to the action.</p>
<p>The code is quite easy to understand. There is only one property to be set (except for the default property Order which is defined in ActionFilterAttribute) which is which field to be parsed. I check if the field is null or empty, if not ten I use a regular expression to see check if the selected field ends with &#8220;page&#8221; and a numerical value. The numerical value is then returned as a argument for the action called &#8220;pageNo&#8221;. This value is defaulted to 1 to make sure that we always get a number for our page (and not specifying anything should mean the first page). In my case I also want the field to be modified so it doesn&#8217;t contain the &#8220;page&#8221; part but that might not be suitable for everyone. If not, then you can easily remove that part by commenting the line looking like this: <i>filterContext.ActionParameters[Field] = id;</i></p>
<pre class="brush: csharp; title: ;">
using System;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;

namespace BeaverShopMvc.Attributes
{
    /// &lt;summary&gt;
    /// An ActionFilter to parse a page number from a field value
    /// &lt;/summary&gt;
    public class PagingAttribute : ActionFilterAttribute
    {
        /// &lt;summary&gt;
        /// The name of the field to parse
        /// &lt;/summary&gt;
        public string Field { get; set; }

        // A compiled regular expression to speed things up
        private static Regex _pageRegex = new Regex(&quot;page(?&lt;PageNo&gt;\\d+)$&quot;, RegexOptions.CultureInvariant | RegexOptions.Compiled);

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            string id = filterContext.ActionParameters[Field] as string;
            Int32 pageNo = 1;

            // We never need an ending / so remove it
            id = id.TrimEnd('/');

            // Check so that the field isn't empty and while at it also that it
            // contains &quot;page&quot;
            if (!string.IsNullOrEmpty(id) &amp;&amp; id.ToLowerInvariant().Contains(&quot;page&quot;))
            {
                Match match = _pageRegex.Match(id);
                if (match.Success)
                {
                    pageNo = Convert.ToInt32(match.Groups[&quot;PageNo&quot;].Value);
                    if (id.Contains(&quot;/&quot;))
                        id = id.Substring(0, id.LastIndexOf('/'));
                    else
                        id = string.Empty;
                }
            }

            filterContext.ActionParameters[&quot;pageNo&quot;] = pageNo;
            // The line below replaces the old field value with a
            // new one without the &quot;page&quot; part
            filterContext.ActionParameters[Field] = id;

            base.OnActionExecuting(filterContext);
        }
    }
}
</pre>
<p>Using the attribute is really simple and the great thing about this is that it is easily reusable on any actions you need it to. Below is a little sample of it in action.</p>
<pre class="brush: csharp; title: ;">
        [Paging(Field = &quot;id&quot;)]
        public ActionResult ListProducts(string id, Int32 pageNo)
        {
            return View();
        }
</pre>
<p>I have a few more filters that I really like as well (AkismetValidatorAttribute for example) that I might share some other day. I&#8217;m still learning a lot about working with MVC and will keep you posted with what other interesting things I can find.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/actionfilters-in-mvc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reading EXIF with extension methods</title>
		<link>http://blog.crazybeavers.se/index.php/archive/reading-exif-with-extension-methods/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/reading-exif-with-extension-methods/#comments</comments>
		<pubDate>Thu, 20 Aug 2009 12:44:49 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[Code samples]]></category>
		<category><![CDATA[exif]]></category>
		<category><![CDATA[extensionmethods]]></category>
		<category><![CDATA[imagergallery]]></category>
		<category><![CDATA[sample]]></category>

		<guid isPermaLink="false">http://blog.crazybeavers.se/?p=110</guid>
		<description><![CDATA[I&#8217;m still putting quite a lot of work into Imager Gallery.Net. I have a alpha up an running at www.kallesbildarkiv.se though it still lacks quite a lot of features. Keeping my earlier commitment to release interesting code created for the project I can now present you with my next piece of code. I&#8217;ve had problems [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m still putting quite a lot of work into Imager Gallery.Net. I have a alpha up an running at <a href="http://www.kallesbildarkiv.se/" title="Visit www.kallesbildarkiv.se">www.kallesbildarkiv.se</a> though it still lacks quite a lot of features.</p>
<p>Keeping my earlier commitment to release interesting code created for the project I can now present you with my next piece of code. I&#8217;ve had problems with finding a good class to read EXIF-information from images that isn&#8217;t written in VB.Net, really poorly written or licensed under GPL so I decided I had to write my own. After looking into the subject I found that it would be quite easy to implement this as extension methods on the regular Image class. I&#8217;ve decided to release the code under the Creative Commons Attribution-Share Alike license to allow people to use it anywhere as long as they can admit that they are using it.</p>
<pre class="brush: csharp; title: ;">
/*
 * Creative Commons Attribution-Share Alike 3.0 Unported
 * You are free:
 *   to Share — to copy, distribute and transmit the work
 *   to Remix — to adapt the work
 *
 * Under the following conditions:
 *   Attribution — You must attribute the work in the manner
 *   specified by the author or licensor (but not in any way
 *   that suggests that they endorse you or your use of the work).
 *
 *   Share Alike — If you alter, transform, or build upon this work,
 *   you may distribute the resulting work only under the same, similar
 *   or a compatible license.
 *
 * For more information, see http://creativecommons.org/licenses/by-sa/3.0/
 */
using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.Text;
using System.Drawing;

/*
 * This class is completely based on the documentation
 * of the EXIF format found here: http://www.exif.org/Exif2-2.PDF
 */

namespace CrazyBeavers.Extensions
{
    public static partial class ImageExtensions
    {
        #region Enumerations
        #pragma warning disable 1591

        private enum PropertyType
        {
            ByteArray = 1,
            AsciiString = 2,
            UnsignedShort = 3,
            UnsignedLong = 4,
            UnsignedLongPair = 5,
            Any = 6,
            SignedLongArray = 7,
            UnsignedLongPairArray = 10
        }

        public enum PropertyTag
        {
            ImageWidth = 0x100,
            ImageLength = 0x101,
            NBitsPerSample = 0x102,
            Compression = 0x103,
            PhotometricInterpretation = 0x106,
            Orientation = 0x112,
            SamplesPerPixel = 0x115,
            PlanarConfiguration = 0x11C,
            YCbCrSubSampling = 0x212,
            YCbCrPositioning = 0x213,
            XResolution = 0x11A,
            YResolution = 0x11B,
            ResolutionUnit = 0x128,
            StripOffsets = 0x111,
            RowsPerStrip = 0x116,
            StripByteCounts = 0x117,
            JPEGInterchangeFormat = 0x201,
            JPEGInterchangeFormatLength = 0x202,
            TransferFunction = 0x12D,
            WhitePoint = 0x13E,
            PrimaryChromaticities = 0x13F,
            YCbCrCoefficients = 0x211,
            ReferenceBlackWhite = 0x214,
            DateTime = 0x132,
            ImageDescription = 0x10E,
            Make = 0x10F,
            Model = 0x110,
            Software = 0x131,
            Artist = 0x13B,
            Copyright = 0x8298,
            ExifVersion = 0x9000,
            FlashpixVersion = 0xA000,
            ColorSpace = 0xA001,
            ComponentsConfiguration = 0x9101,
            CompressedBitsPerPixel = 0x9102,
            PixelXDimension = 0xA002,
            PixelYDimension = 0xA003,
            MakerNote = 0x927C,
            UserComment = 0x9286,
            RelatedSoundFile = 0xA004,
            DateTimeOriginal = 0x9003,
            DateTimeDigitized = 0x9004,
            SubSecTime = 0x9290,
            SubSecTimeOriginal = 0x9291,
            SubSecTimeDigitized = 0x9292,
            ImageUniqueID = 0xA420,
            ExposureTime = 0x829A,
            FNumber = 0x829D,
            ExposureProgram = 0x8822,
            SpectralSensitivity = 0x8824,
            ISOSpeedRatings = 0x8827,
            OECF = 0x8828,
            ShutterSpeedValue = 0x9201,
            ApertureValue = 0x9202,
            BrightnessValue = 0x9203,
            ExposureBiasValue = 0x9204,
            MaxApertureValue = 0x9205,
            SubjectDistance = 0x9206,
            MeteringMode = 0x9207,
            LightSource = 0x9208,
            Flash = 0x9209,
            FocalLength = 0x920A,
            SubjectArea = 0x9214,
            FlashEnergy = 0xA20B,
            SpatialFrequencyResponse = 0xA20C,
            FocalPlaneXResolution = 0xA20E,
            FocalPlaneYResolution = 0xA20F,
            FocalPlaneResolutionUnit = 0xA210,
            SubjectLocation = 0xA214,
            ExposureIndex = 0xA215,
            SensingMethod = 0xA217,
            FileSource = 0xA300,
            SceneType = 0xA301,
            CFAPattern = 0xA302,
            CustomRendered = 0xA401,
            ExposureMode = 0xA402,
            WhiteBalance = 0xA403,
            DigitalZoomRatio = 0xA404,
            FocalLengthIn35mmFilm = 0xA405,
            SceneCaptureType = 0xA406,
            GainControl = 0xA407,
            Contrast = 0xA408,
            Saturation = 0xA409,
            Sharpness = 0xA40A,
            DeviceSettingDescription = 0xA40B,
            SubjectDistanceRange = 0xA40C
        }

        public enum Compression
        {
            NotSpecified = 0,
            Uncompressed = 1,
            JpegCompression = 6
        }

        public enum PhotometricInterpretation
        {
            RGB = 2,
            YCbCr = 6
        }

        public enum Orientation
        {
            TopLeft = 1,
            TopRight = 2,
            BottomRight = 3,
            BottomLeft = 4,
            LeftTop = 5,
            RightTop = 6,
            RightBottom = 7,
            LeftBottom = 8
        }

        public enum ExposureMode
        {
            AutoExposure = 0,
            ManualExposure = 1,
            AutoBracket = 2
        }

        public enum ExposureProgram
        {
            Undefined = 0,
            Manual = 1,
            Normal = 2,
            AperturePriority = 3,
            ShutterPriority = 4,
            CreativeProgram = 5,
            ActionProgram = 6,
            PortraitMode = 7,
            LandscapeMode = 8
        }

        public enum MeteringMode
        {
            Unknown = 0,
            Average = 1,
            CenterWeightedAverage = 2,
            Spot = 3,
            MultiSpot = 4,
            Pattern = 5,
            Partial = 6,
            Other = 255
        }

        public enum Flash
        {
            FlashDidNotFire = 0x0000,
            FlashFired = 0x0001,
            StrobeReturnNotDetected = 0x0005,
            StrobeReturnDetected = 0x0007,
            FlashFiredCompulsoryMode = 0x0009,
            FlashFiredCompulsoryModeStrobeReturnNotDetected = 0x000D,
            FlashFiredCompulsoryModeStrobeReturnDetected = 0x000F,
            FlashDidNotFireCompulsoryMode = 0x0010,
            FlashDidNotFireAutoMode = 0x0018,
            FlashFiredAutoMode = 0x00019,
            FlashFiredAutoModeStrobeReturnNotDetected = 0x001D,
            FlashFiredAutoModeStrobeReturnDetected = 0x001F,
            NoFlash = 0x0020,
            FlashFiredRedEyeReduction = 0x0041,
            FlashFiredRedEyeReductionStrobeReturnNotDetected = 0x0045,
            FlashFiredRedEyeReductionStrobeReturnDetected = 0x0047,
            FlashFiredCompulsoryModeRedEyeReduction = 0x0049,
            FlashFiredCompulsoryModeRedEyeReductionStrobeReturnNotDetected = 0x004D,
            FlashFiredCompulsoryModeRedEyeReductionStrobeReturnDetected = 0x004F,
            FlashFiredAutoModeRedEyeReduction = 0x0059,
            FlashFiredAutoModeRedEyeReductionStrobeReturnNotDetected = 0x005D,
            FlashFiredAutoModeRedEyeReductionStrobeReturnDetected = 0x005F
        }

        public enum WhiteBalance
        {
            Auto = 0,
            Manual = 1
        }

        public enum SceneCaptureType
        {
            Standard = 0,
            Landscape = 1,
            Portrait = 2,
            NightScene = 3
        }

        public enum LightSource
        {
            Unkown = 0,
            Daylight = 1,
            Fluorescent = 2,
            Tungsten = 3,
            Flash = 4,
            FineWeather = 9,
            CloudyWeather = 10,
            Shade = 11,
            DaylightFluorescent = 12,
            DayWhiteFluorescent = 13,
            CoolWhiteFluorescent = 14,
            WhiteFluorescent = 15,
            StandardLightA = 17,
            StandardLightB = 18,
            StandardLightC = 19,
            D55 = 20,
            D65 = 21,
            D75 = 22,
            D50 = 23,
            ISOStudioTungsten = 24,
            OtherLightSource = 255
        }

        public enum GainControl
        {
            None = 0,
            LowGainUp = 1,
            HighGainUp = 2,
            LowGainDown = 3,
            HighGainDown = 4
        }

        public enum Contrast
        {
            Normal = 0,
            Soft = 1,
            Hard = 2
        }

        public enum Saturation
        {
            Normal = 0,
            LowSaturation = 1,
            HighSaturation = 2
        }

        public enum Sharpness
        {
            Normal = 0,
            Soft = 1,
            Hard = 2
        }

        public enum SubjectDistanceRange
        {
            Unknown = 0,
            Macro = 1,
            CloseView = 2,
            DistantView = 3
        }

        #pragma warning restore 1591
        #endregion

        #region Properties

        public static DateTime ExifDateTime(this Image image)
        {
            return GetPropertyDateTime(image, PropertyTag.DateTime);
        }

        public static DateTime ExifDateTimeDigitized(this Image image)
        {
            return GetPropertyDateTime(image, PropertyTag.DateTimeDigitized);
        }

        public static DateTime ExifDateTimeOriginal(this Image image)
        {
            return GetPropertyDateTime(image, PropertyTag.DateTimeOriginal);
        }

        public static string ExifMake(this Image image)
        {
            return GetPropertyString(image, PropertyTag.Make);
        }

        public static string ExifModel(this Image image)
        {
            return GetPropertyString(image, PropertyTag.Model);
        }

        public static string ExifImageDescription(this Image image)
        {
            return GetPropertyString(image, PropertyTag.ImageDescription);
        }

        public static string ExifSoftware(this Image image)
        {
            return GetPropertyString(image, PropertyTag.Software);
        }

        public static string ExifArtist(this Image image)
        {
            return GetPropertyString(image, PropertyTag.Artist);
        }

        public static Orientation ExifOrientation(this Image image)
        {
            return (Orientation)GetPropertyUInt16(image, PropertyTag.Orientation);
        }

        public static Flash ExifFlash(this Image image)
        {
            return (Flash)GetPropertyUInt16(image, PropertyTag.Flash);
        }

        public static SceneCaptureType ExifSceneCaptureType(this Image image)
        {
            return (SceneCaptureType)GetPropertyUInt16(image, PropertyTag.SceneCaptureType);
        }

        public static WhiteBalance ExifWhiteBalance(this Image image)
        {
            return (WhiteBalance)GetPropertyUInt16(image, PropertyTag.WhiteBalance);
        }

        public static MeteringMode ExifMeteringMode(this Image image)
        {
            return (MeteringMode)GetPropertyUInt16(image, PropertyTag.MeteringMode);
        }

        public static Compression ExifCompression(this Image image)
        {
            return (Compression)GetPropertyUInt16(image, PropertyTag.Compression);
        }

        public static ExposureMode ExifExposureMode(this Image image)
        {
            return (ExposureMode)GetPropertyUInt16(image, PropertyTag.ExposureMode);
        }

        public static ExposureProgram ExifExposureProgram(this Image image)
        {
            return (ExposureProgram)GetPropertyUInt16(image, PropertyTag.ExposureProgram);
        }

        public static PhotometricInterpretation ExifPhotometricInterpretation(this Image image)
        {
            return (PhotometricInterpretation)GetPropertyUInt16(image, PropertyTag.PhotometricInterpretation);
        }

        public static LightSource ExifLightSource(this Image image)
        {
            return (LightSource)GetPropertyUInt16(image, PropertyTag.LightSource);
        }

        public static GainControl ExifGainControl(this Image image)
        {
            return (GainControl)GetPropertyUInt16(image, PropertyTag.GainControl);
        }

        public static Contrast ExifLightContrast(this Image image)
        {
            return (Contrast)GetPropertyUInt16(image, PropertyTag.Contrast);
        }

        public static Saturation ExifSaturation(this Image image)
        {
            return (Saturation)GetPropertyUInt16(image, PropertyTag.Saturation);
        }

        public static Sharpness ExifSharpness(this Image image)
        {
            return (Sharpness)GetPropertyUInt16(image, PropertyTag.Sharpness);
        }

        public static SubjectDistanceRange ExifSubjectDistanceRange(this Image image)
        {
            return (SubjectDistanceRange)GetPropertyUInt16(image, PropertyTag.SubjectDistanceRange);
        }

        public static Rational ExifExposureTime(this Image image)
        {
            return GetPropertyRational(image, PropertyTag.ExposureTime);
        }

        public static double ExifFNumber(this Image image)
        {
            return GetPropertyRational(image, PropertyTag.FNumber).ToDouble();
        }

        public static double ExifAperture(this Image image)
        {
            return GetPropertyRational(image, PropertyTag.ApertureValue).ToDouble();
        }

        public static Rational ExifSubjectDistance(this Image image)
        {
            return GetPropertyRational(image, PropertyTag.SubjectDistance);
        }

        public static double ExifFocalLength(this Image image)
        {
            return GetPropertyRational(image, PropertyTag.FocalLength).ToDouble();
        }

        public static UInt16 ExifISOSpeedRating(this Image image)
        {
            return GetPropertyUInt16(image, PropertyTag.ISOSpeedRatings);
        }

        public static Rational ExifDigitalZoomRatio(this Image image)
        {
            return GetPropertyRational(image, PropertyTag.DigitalZoomRatio);
        }

        #endregion

        public static bool HasProperty(this Image image, PropertyTag property)
        {
            return Array.IndexOf(image.PropertyIdList, (Int32)property) &gt; -1;
        }

        public static DateTime GetPropertyDateTime(this Image image, PropertyTag property)
        {
            if (!image.HasProperty(property))
                return DateTime.MinValue;

            string value = GetPropertyString(image, property);

            // If first char is blank or string is empty no DateTime is present
            if (value == string.Empty || value[0] == ' ')
                return DateTime.MinValue;

            // DateTime is written as YYYY:MM:DD HH:MM:SS
            // and needs to be converted to YYYY-MM-DD HH:MM:SS
            // to be convertable to a .Net DateTime
            string datePart = value.Substring(0, 10).Replace(':', '-');
            string timePart = value.Substring(11);
            return Convert.ToDateTime(datePart + ' ' + timePart);
        }

        public static string GetPropertyString(this Image image, PropertyTag property)
        {
            if (!image.HasProperty(property))
                return string.Empty;

            PropertyItem item = image.GetPropertyItem((Int32)property);
            if (item.Type != (short)PropertyType.AsciiString)
                return string.Empty;

            byte[] buffer = item.Value;
            return Encoding.ASCII.GetString(buffer).Trim('&#92;&#48;');
        }

        public static UInt32 GetPropertyUInt32(this Image image, PropertyTag property)
        {
            if (!image.HasProperty(property))
                return 0;

            PropertyItem item = image.GetPropertyItem((Int32)property);
            if (item.Type != (short)PropertyType.UnsignedLong)
                return 0;

            byte[] buffer = item.Value;
            return BitConverter.ToUInt32(buffer, 0);
        }

        public static UInt16 GetPropertyUInt16(this Image image, PropertyTag property)
        {
            if (!image.HasProperty(property))
                return 0;

            PropertyItem item = image.GetPropertyItem((Int32)property);
            if (item.Type != (short)PropertyType.UnsignedShort)
                return 0;

            byte[] buffer = item.Value;
            return BitConverter.ToUInt16(buffer, 0);
        }

        public static Rational GetPropertyRational(this Image image, PropertyTag property)
        {
            if (!image.HasProperty(property))
                return Rational.Zero;

            PropertyItem item = image.GetPropertyItem((Int32)property);
            if (item.Type != (short)PropertyType.UnsignedLongPair)
                return Rational.Zero;

            byte[] buffer = item.Value;
            Int32 numerator = BitConverter.ToInt32(buffer, 0);
            Int32 denominator = BitConverter.ToInt32(buffer, 4);

            Rational rational = new Rational(numerator, denominator);
            return rational;
        }
    }

    public struct Rational
    {
        private Int32 _numerator;
        public Int32 Numerator
        {
            get
            {
                return _numerator;
            }
            set
            {
                _numerator = value;
            }
        }

        private Int32 _denominator;
        public Int32 Denominator
        {
            get
            {
                return _denominator;
            }
            set
            {
                if (value == 0)
                    throw new ArgumentOutOfRangeException(&quot;Denominator&quot;, 0, &quot;Denominator can't be zero.&quot;);

                _denominator = value;
            }
        }

        public static Rational Zero
        {
            get
            {
                return new Rational(0, 1);
            }
        }

        public Rational(Int32 numerator, Int32 denominator)
        {
            _numerator = 0;
            _denominator = 1;
            Numerator = numerator;
            Denominator = denominator;
        }

        public override string ToString()
        {
            return string.Format(&quot;{0}/{1}&quot;, Numerator, Denominator);
        }

        public double ToDouble()
        {
            return (double)Numerator / Denominator;
        }
    }
}
</pre>
<p>This introduces several new methods to the Image class starting with &#8220;Exif&#8221; such as ExifDateTime, ExifMake and ExifExposureTime. The Rational class was inserted into the same code block in this sample, in the main project it has it&#8217;s own file under CrazyBeavers.Math. Hope you enjoy this piece of code!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/reading-exif-with-extension-methods/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>jQuery Tag Editor</title>
		<link>http://blog.crazybeavers.se/index.php/archive/jquery-tag-editor/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/jquery-tag-editor/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 12:39:24 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Code samples]]></category>
		<category><![CDATA[imagergallery]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://blog.crazybeavers.se/?p=102</guid>
		<description><![CDATA[Something I really like with WordPress is the really nice tag editor. It works so smooth and looks way better then just having a textbox with comma-separated list of tags so for ImagerGallery.Net I decided to write one of my own. I&#8217;ve put up a demo of it for now for those interested, it&#8217;s available [...]]]></description>
			<content:encoded><![CDATA[<p>Something I really like with WordPress is the really nice tag editor. It works so smooth and looks way better then just having a textbox with comma-separated list of tags so for ImagerGallery.Net I decided to write one of my own. I&#8217;ve put up a demo of it for now for those interested, it&#8217;s available at the following url:</p>
<p><a href="http://blog.crazybeavers.se/wp-content/demos/jquery.tag.editor/">http://blog.crazybeavers.se/wp-content/demos/jquery.tag.editor/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/jquery-tag-editor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Compacting CSS on-the-fly</title>
		<link>http://blog.crazybeavers.se/index.php/archive/compacting-css-on-the-fly/</link>
		<comments>http://blog.crazybeavers.se/index.php/archive/compacting-css-on-the-fly/#comments</comments>
		<pubDate>Thu, 02 Jul 2009 10:34:08 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[.Net]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[htthandler]]></category>
		<category><![CDATA[imagergallery]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[sample]]></category>

		<guid isPermaLink="false">http://blog.crazybeavers.se/?p=95</guid>
		<description><![CDATA[I&#8217;m currently doing quite a lot of work on my ny MVC-version of Imager Gallery. I still have a lot to do before I have anything to release (or even use myself) though but I thought I could release a few snippets that I&#8217;ve found useful. First out is a HttpHandler that will process .css-files [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m currently doing quite a lot of work on my ny MVC-version of Imager Gallery. I still have a lot to do before I have anything to release (or even use myself) though but I thought I could release a few snippets that I&#8217;ve found useful.</p>
<p>First out is a HttpHandler that will process .css-files and remove any unused whitespace from the file before sending it to the client. I&#8217;ve been meaning to write this for a long time but never really had the time until someone posted a link about it over at <a href="http://www.aspsidan.se/default.asp?page=forum&#038;fp=showPost&#038;fId=31&#038;pId=584376">ASPSidan.se</a> showing their own implementation. Reading up on his post about it I found that it was based on <a href="http://webdevel.blogspot.com/2007/09/csscompact-webhandler-for-shrinking-css.html">a solution by Sam Collett</a>. Both implementations lacked a few things that I wanted to have so I sat down with Sams code and started improving it, mainly making it a work as a handler for .css-files instead of a Generic Handler wanting a querystring but also adding caching and compiling the regular expression as a static member.</p>
<p>To use this, just pop it in a .cs-file in your your App_Code folder and add it to your web.config (as described in the comments for the class). You also need to configure your IIS to route .css-files through the asp.net process to make it run (not needed under IIS7 or IIS6 configured for MVC). Hope you find it useful!</p>
<pre class="brush: csharp; title: ;">
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Caching;

namespace HttpHandlers
{
    /// &lt;summary&gt;
    /// Handler for compacting css-files on the fly
    /// Based on solution by Sam Collett found at
    /// http://webdevel.blogspot.com/2007/09/csscompact-webhandler-for-shrinking-css.html
    ///
    /// Needs to be added to web.config under System.Web/httpHandlers like this
    /// &lt;add verb=&quot;GET,HEAD&quot; path=&quot;*.css&quot; type=&quot;HttpHandlers.CssCompactHandler&quot;/&gt;
    ///
    /// For debuing purposes you can append a querystring whenbrowsing to your .css-file
    /// to skip the compacting. It would look like this:
    /// http://mySite/Content/Site.css?noCompact=1
    /// &lt;/summary&gt;
    public class CssCompactHandler : IHttpHandler
    {
        // Staticly compiled regex to avoid compiling it each request
        private static Regex RegexRemoval = new Regex(@&quot;^\s+|/\*([^*\\\\]|\*(?!/))+\*/|\r|\n|\t&quot;, RegexOptions.Multiline | RegexOptions.Compiled);

        public void ProcessRequest(HttpContext context)
        {
            HttpResponse Response = context.Response;
            HttpRequest Request = context.Request;
            Cache Cache = context.Cache;

            FileInfo fileInfo = new FileInfo(Request.PhysicalPath);
            if (!fileInfo.Exists)
            {
                Response.StatusDescription = &quot;The server has not found anything that matches the requested URI.&quot;;
                Response.StatusCode = 404;
                Response.End();
            }

            Response.ContentType = &quot;text/css&quot;;
            Response.Cache.SetLastModified(fileInfo.LastWriteTime);

            // If we are in debugmode (set in web.config) then
            // we dont want to cache the css since we are probably
            // still in development
            if (context.IsDebuggingEnabled)
            {
                Response.Cache.SetCacheability(HttpCacheability.NoCache);
            }
            else
            {
                Response.Cache.SetCacheability(HttpCacheability.Public);
                Response.Cache.SetExpires(DateTime.Now.AddDays(1));
            }

            // HEAD requests only need the headers so we skip the
            // content here
            if (Request.HttpMethod != &quot;HEAD&quot;)
            {
                string cacheName = string.Format(&quot;CssCompactHandlerCache_{0}&quot;, fileInfo.FullName);
                string cacheValue = Cache[cacheName] as string;
                if (cacheValue != null &amp;&amp; Request.QueryString[&quot;noCompact&quot;] == null)
                {
                    Response.Write(cacheValue);
                    Response.End();
                }

                using (StreamReader cssStream = fileInfo.OpenText())
                {
                    string cssContent = cssStream.ReadToEnd();
                    if (Request.QueryString[&quot;noCompact&quot;] == null)
                    {
                        cssContent = RegexRemoval.Replace(cssContent, &quot;&quot;);

                        // Set up a CacheDependency on the css-file,
                        // this way the cache will be invalidated if
                        // we change the file
                        CacheDependency dependency = new CacheDependency(fileInfo.FullName);
                        Cache.Add(string.Format(&quot;CssCompactHandlerCache_{0}&quot;, fileInfo.FullName), cssContent, dependency, DateTime.Now.AddYears(1), Cache.NoSlidingExpiration, CacheItemPriority.AboveNormal, null);
                    }
                    Response.Write(cssContent);
                }
            }
        }

        public bool IsReusable
        {
            get
            {
                return true;
            }
        }
    }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.crazybeavers.se/index.php/archive/compacting-css-on-the-fly/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

