Resize image with Silverlight and FJCore before uploading to server

4

Posted by Joe | Posted in Silverlight, WCF | Posted on 22-06-2009

I have a Silverlight application which allows the user to select images from their local PC which are then uploaded to a server via a WCF Service.

It is easy enough to resize the image once it gets to the server, but this would still mean that the full image is being sent over the wire.

In Silverlight 2 there are no built in features that allow us to do the resizing at the client, but it can be achieved using an open source imaging library called FJCore.

To get the FJCore source from Subversion I use an open source plug-in for Visual Studio called AnkhSVN.  It is then possible to build the solution and add a reference to the FJCore library to my own solution.

In my application I allow the user to select multiple files using the OpenFileDialog which are then processed as byte arrays and sent to the server via the WCF Service.  Before doing the upload I am using FJCore to check if the image needs to be resized, and if so resize the image.

The resizing requires the following using statements.

using FluxJpeg.Core;
using FluxJpeg.Core.Decoder;
using FluxJpeg.Core.Filtering;
using FluxJpeg.Core.Encoder;

The following code shows how to use FJCore to take the files selected with the OpenFileDialog and do the resizing before calling the service method to upload to the server.  Here the maximum edge length is 640px, so if width or height is greater than 640px, the resize code is used to resize the maximum edge length to 640px while keeping perspective.


OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "JPEG Files (*.jpg;*.jpeg)|*.jpg;*.jpeg";
ofd.Multiselect = true;

if (ofd.ShowDialog().GetValueOrDefault(false))
{
    //The path to upload the files on the server
    string serverPath = "d:\uploads";

    foreach (FileInfo image in ofd.Files)
    {
        FileStream stream = image.OpenRead();
        using (stream)
        {
            byte[] data;
                      Â
            //Decode image
            DecodedJpeg origJpeg = new JpegDecoder(stream).Decode();

            //Check if the image needs resizing
            if (ImageResizer.ResizeNeeded(origJpeg.Image, 640))
            {
                //Resize image
                DecodedJpeg resizedJpeg =
                    new DecodedJpeg(new ImageResizer(origJpeg.Image).Resize(640, ResamplingFilters.NearestNeighbor), origJpeg.MetaHeaders);

                //Encode resized image
                MemoryStream resizedStream = new MemoryStream();
                new JpegEncoder(resizedJpeg, 100, resizedStream).Encode();

                //Read resized stream to byte array
                resizedStream.Seek(0, SeekOrigin.Begin);
                data = new byte[resizedStream.Length];
                resizedStream.Read(data, 0, Convert.ToInt32(resizedStream.Length));
            }
            else
            {
                //Read original stream to byte array
                stream.Seek(0, SeekOrigin.Begin);
                data = new byte[stream.Length];
                stream.Read(data, 0, Convert.ToInt32(stream.Length));
            }

            //Upload image via service
            GalleryContractClient proxy = new GalleryContractClient();
            proxy.UploadImageCompleted += new EventHandler<uploadImageCompletedEventArgs>(proxy_UploadImageCompleted);
            proxy.UploadImageAsync(serverPath, image.Name, data);
        }
    }
}

Post to Twitter Post to Delicious Post to Digg Post to Facebook Post to Reddit

Enum description using reflection and extension methods

0

Posted by Joe | Posted in C# | Posted on 18-06-2009

I don’t take credit for this as it was written by another developer on the the project, but I thought it was good and worth writing about.

On the current project I’m working on we use a lot of enumerations for statuses which are shown in drop-down lists and grids. It can get a bit ugly from a UI perspective when simply using the ToString method as enumeration values cannot have spaces and are usually shortened for ease of use when coding.

One way to overcome this is to add a description attribute to each enumeration value and write an extension method that uses reflection to obtain the value in the description attribute.

The description attribute is part of the System.ComponentModel namespace so we need to import this.  The attribute value can then be set on each enumeration value:

public enum Status : int
{
    [Description("Application pending")]
    Pending = 0,
    [Description("Application received")]
    Received = 1,
    [Description("Application processing in progress")]
    Processing = 2,
    [Description("Application processed")]
    Processed = 3
}

The next step is to create the extension method.  Extension methods were introduced in  C# 3 and allow you to easily add new methods to existing types.  Scott Guthrie has a good blog post on them here.  Extensions methods need to be static, and contained in a static class.  In the method signature the ‘this’ keyword is used to indicate which type the extension method is for.  Below is the extension method that will get the description attribute for an enumeration using reflection.

public static string Description(this Enum enumeration)
{
    string value = enumeration.ToString();
    Type type = enumeration.GetType();
    //Use reflection to try and get the description attribute for the enumeration
    DescriptionAttribute[] descAttribute = (DescriptionAttribute[])type.GetField(value).GetCustomAttributes(typeof(DescriptionAttribute), false);
    return descAttribute.Length > 0 ? descAttribute[0].Description : value;
}

Any enumeration will now have a method called Description that will try to return the value of the description attribute, and if the attribute is not present return the result of calling ToString.  For example:

Console.WriteLine(Status.Processing.Description());

Â
Will display:

exmethod1

As the extension method is for Enum, and not just the Status enumeration I created, we could do this:

Array values = Enum.GetValues(typeof(Status));
foreach (Enum e in values)
    Console.WriteLine("{0} - {1}", e, e.Description());

The result here would be:

exmethod2

There are lots of uses for extension methods which are used extensively with Linq, but I particularly like this idea to provide a more readable value for an enumeration.

Post to Twitter Post to Delicious Post to Digg Post to Facebook Post to Reddit

Simple double click in Silverlight

0

Posted by Joe | Posted in Silverlight | Posted on 05-06-2009

I needed to pick up on a double click on an image in Silverlight but there is no event to handle this. It can be done quite easily using a DispatchTimer.  I am doing this for an image but you should be able to do it for any UIElement.

First I have imported the System.Windows.Theading namespace where the DispatchTimer lives.  In the constructor of the User Control containing the image I have instantiated the Timer and set its interval to 200 milliseconds, this is the amount of time allowed between clicks for it to be considered a double click.  I have also added a listener to the Tick event of the Timer which fires with each iteration.

Â
using System.Windows.Threading;

public partial class Image : UserControl
{
    DispatcherTimer _timer;

    public Image()
    {
        InitializeComponent();

        _timer = new DispatcherTimer();
        _timer.Interval = new TimeSpan(0, 0, 0, 0, 200);
        _timer.Tick += new EventHandler(_timer_Tick);
    }
}

My event handler for the Image’s MouseLeftButtonDown will check if the Timer has already been started, and if so we know this is a double click, if not we start the timer.  The first time the event is raised the timer won’t be started, but the second time, on the second click it will be so this is our double click.

private void imgImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    if (_timer.IsEnabled)
    {
        MessageBox.Show("Double Click");
    }
        else
    {
        _timer.Start();
    }
}

Finally I handle the Tick event of the Timer, and simply stop the timer so that after 200 milliseconds the timer is no longer active, and any subsequent clicks are not counted as the second click of a double click.

void _timer_Tick(object sender, EventArgs e)
{
    _timer.Stop();
}

This is a fairly basic and not very reusable but does the job for what I need.  You could also use the GetPosition property of MouseButtonEventArgs to make sure that the mouse hasn’t moved between clicks.

Post to Twitter Post to Delicious Post to Digg Post to Facebook Post to Reddit

Setting the SelectedItem in a Silverlight TreeView

0

Posted by Joe | Posted in Silverlight | Posted on 04-06-2009

I wanted to select a specific item in my Silverlight TreeView programatically.  Looking at the TreeView.SelectedItem property the setter is not public so it cannot be done this way.

If you are simply adding TreeViewItems to the TreeView you can cast the item you want to select in the Items collection to a TreeViewItem and set the IsSelected property to true. The following example will grab the first item and set it to selected.

TreeViewItem item = tvDirectories.Items[0] as TreeViewItem;
item.IsSelected = true;

If you are binding a list of business objects to the TreeView this will not work as the Items collection will be a list of your object.  In this scenario you can use the ItemContainerGenerator property of the TreeView to get the underlying TreeViewItem.  In this example I have a collection of Gallery objects bound to my TreeView and am using the ContainerFromIndex method to get the TreeViewItem at position 0.

TreeViewItem item = tvDirectories.ItemContainerGenerator.ContainerFromIndex(0) as TreeViewItem;
item.IsSelected = true;

The ItemContainerGenerator class also has a ContainerFromItem method that will get the TreeViewItem by passing it an instance of the business object you want to select.

Gallery gallery = GetGallery(); //Some method that gets the object you want to select in the TreeView
TreeViewItem item = tvDirectories.ItemContainerGenerator.ContainerFromItem(gallery) as TreeViewItem;
item.IsSelected = true;

In my application I want to select the TreeViewItem based on the ServerPath of the Gallery object so I’m using some of the nifty Linq extension methods (Cast and Single) to get my business object.

public void SelectGallery(string serverPath)
{
    Gallery gallery = tvDirectories.Items.Cast<gallery>().Single(x => x.ServerPath.Equals(serverPath));
          Â
    if (gallery != null)
    {
        TreeViewItem item = tvDirectories.ItemContainerGenerator.ContainerFromItem(gallery) as TreeViewItem;
        item.IsSelected = true;
    }
}

Post to Twitter Post to Delicious Post to Digg Post to Facebook Post to Reddit

Disable enter submitting form with JavaScript

0

Posted by Joe | Posted in JavaScript | Posted on 04-06-2009

On a project I was working on I was asked to disable the enter key submitting the form.  Usually it would be better just to ensure that hitting enter performed the correct action but if you do want to disable this you can do so with JavaScript.

I created a JavaScript function called disableEnterSubmit which takes in the event as a parameter as shown below.

function disableEnterSubmit(e)
{
    if (e.keyCode)
       return (e.keyCode != 13); //IE
    else
        return (e.which != 13); //FireFox
}

The event has different properties for the code of the pressed key for Internet Explorer and FireFox. In Internet Explorer we use e.keyCode and for FireFox it’s e.which.  The function simply returns false if the key is enter (key code 13).

I then just need to set the onkeydown event in the body tag of my HTML to call the method.

<body onkeydown="return disableEnterSubmit(event)">

Post to Twitter Post to Delicious Post to Digg Post to Facebook Post to Reddit

Xbox 360 – Project Natal – No controller gaming?

0

Posted by Joe | Posted in Xbox 360 | Posted on 04-06-2009

Microsoft have announced Project Natal for Xbox 360.  It boasts controller-less gaming with face and voice recognition.  Obviously influenced by the Wii, the concept video does look interesting.  As a fan of the Skate and Skate 2 games the use of full motion body capture could be cool when it comes to skateboarding games, or it could be a complete flop. Will have to wait and see…

Post to Twitter Post to Delicious Post to Digg Post to Facebook Post to Reddit

Alert, confirm and input message boxes in Silverlight

0

Posted by Joe | Posted in Silverlight | Posted on 03-06-2009

To use alert, confirm and input message boxes in Silverlight you need to import the following namespace.

using System.Windows.Browser;

You can then show an alert box by doing…

HtmlPage.Window.Alert("This is an alert")

Or a confirm dialog by doing…

if (HtmlPage.Window.Confirm("Are you sure you want to do something?"))
{
    //Do something
}

Or an input prompt by doing…

string name = HtmlPage.Window.Prompt("What is your name?");

Post to Twitter Post to Delicious Post to Digg Post to Facebook Post to Reddit

Passing a byte array to a WCF method from Silverlight – The remote server returned an error: NotFound

4

Posted by Joe | Posted in Silverlight | Posted on 03-06-2009

My Silverlight application calls a method to get an image from the server as a byte array. When adding my Service Reference the ServiceReferences.ClientConfig automatically generated the binding’s MaxBufferSize and MaxRecievedMessageSize as 2147483647 which is a lot bigger than I want to I changed them to 5242880 (5MB).  When the application calls the service to bring down an image these values are used to limit the size of the response message.

I also set the MaxBufferSize and MaxRecievedMessageSize to 5242880 in the web.config file of the web application hosting my service.  At this point when I call the method in my service to upload an image passing a byte array I get a The remote server returned an error: NotFound error message, which really isn’t very helpful.

In this instance the problem is that the maximum array length for the XML reader has been exceeded. This can be fixed by expanding the binding section to insert a readerQuotas section and increase the maxArrayLength.

<services>
    <service behaviorConfiguration="GalleryServiceBehavior" name="GalleryService.GalleryService">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpLargeMessage" contract="GalleryService.IGalleryService" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    </service>
</services>

<bindings>
    <basicHttpBinding>
        <binding name="basicHttpLargeMessage" maxReceivedMessageSize="5242880" maxBufferSize="5242880">
            <readerQuotas maxArrayLength="5242880" />
        </binding>
    </basicHttpBinding>
</bindings>

I can now upload and download files up to 5MB through my service.

Post to Twitter Post to Delicious Post to Digg Post to Facebook Post to Reddit

Set Silverlight Image Source from byte array

7

Posted by Joe | Posted in Silverlight | Posted on 03-06-2009

I’ve been playing around with Silverlight and WCF services and I came across the need to set the Source of an Image control in Silverlight from a byte array. I have a service method which returns an image from the server as a byte array which I want to show in the Silverlight application.

My service method is simple and looks like this:

using System.IO;

public byte[] GetImage(string serverPath)
{
    return File.ReadAllBytes(serverPath);
}

In the Silverlight application I create a MemoryStream from the byte array, then a BitmapImage from the MemoryStream and set the image source to the BitmapImage.


using System.IO;
using System.Windows.Media.Imaging;

void proxy_GetImageCompleted(object sender, GetImageCompletedEventArgs e)
{
    MemoryStream stream = new MemoryStream(e.Result);
    BitmapImage b = new BitmapImage();
    b.SetSource(stream);
    imgImage.Source = b;
}

proxy_GetImageCompleted is the event handler for when my asynchronous call to GetImage completes, where e.Result is the byte array.

Post to Twitter Post to Delicious Post to Digg Post to Facebook Post to Reddit

Wrapped Listbox items in Silverlight and WPF

0

Posted by Joe | Posted in Silverlight, WCF | Posted on 02-06-2009

I wanted to display a list of image thumbnails similar to how Windows Explorer does it so they are displayed horizontally and wrap onto the next line. The ListBox allows you to choose a template for the panel used to display items. The following XAML uses the WrapPanel for the ItemsPanelTemplate and gives the functionality I wanted.

<listBox x:Name="ImageList" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
    <listBox.ItemTemplate>
        <dataTemplate>
            <usrcntrl:Image ImageName="{Binding Name}" ServerPath="{Binding ServerPath}" />
        </dataTemplate>
    </listBox.ItemTemplate>
    <listBox.ItemsPanel>
        <itemsPanelTemplate>
            <controls:WrapPanel />
        </itemsPanelTemplate>
    </listBox.ItemsPanel>
</listBox>

I have also disabled the horizontal scroll bar so the images wrap to the next line.

Post to Twitter Post to Delicious Post to Digg Post to Facebook Post to Reddit