Showing posts with label PresentationCore. Show all posts
Showing posts with label PresentationCore. Show all posts

01 July 2009

Using PresentationCore in Azure requires full trust

Sometimes the answer is staring you in the face... I was trying to load an image from an URL in code. Imagine the code for that being something like this
var blobURL = "http://www.somewhere.com/image.jpg";
var multiTileImage = new BitmapImage(); 
multiTileImage.BeginInit(); 
multiTileImage.UriSource = new Uri(blobURL);
multiTileImage.CacheOption = BitmapCacheOption.None;
multiTileImage.EndInit();
This fails with an security expection, you get something like "Request for the permission of type 'System.Security.Permissions.MediaPermission failed in System.Windows.Media.Imaging.BitmapImage.EndInit" Dennis van der Stelt suggested that this may have to do something with full trust. And indeed it does. In your service definition file by default is defined
<WebRole name="WebRole" enableNativeCodeExecution="false">
I noticed that, I just failed to see the connection between "enableNativeCodeExecution" and "full trust". In fact, I still fail to see that connection ;-) but you just need to set the value for enableNativeCodeExecution in the appropriate tag to "true" and then PresentationCore classes - with apparently are not thrustworthy - can be used from Web- or Worker roles.

07 May 2009

Cutting images with PresentationCore

In my business cutting images into smaller images is something that happens quite often these days, since tile based mapping systems like Google Maps, Virtual Earth and OpenLayers are becoming ever more popular. For the past few years I have been using GDI+ as my workhorse, but last week I've kissed it goodbye. Over are the days of messing around with Graphics and Bitmap and not forgetting to dispose them. Enter PresentationCore with the System.Windows.Media.Imaging classes! To use this API, you need to make references to both PresentationCore.dll and WindowsBase.dll. I created a small sample cutter class like this:
using System;
using System.Windows;
using System.Windows.Media.Imaging;
using System.IO;

namespace LocalJoost.ImageCutting
{
  public class ImageCutter
  {
    private string _fileName;
    public ImageCutter(string fileName)
    {
      _fileName = fileName;
    }

    public void Cut(int TileSize, int TilesX, int TilesY)
    {
      var img = new BitmapImage();
      img.BeginInit();
      img.UriSource = new Uri(_fileName);
      img.CacheOption = BitmapCacheOption.OnLoad;
      img.EndInit();

      var fInfo = new FileInfo(_fileName);

      for (int x = 0; x < TilesX; x++)
      {
        for (int y = 0; y < TilesY; y++)
        {
          var subImg = new CroppedBitmap(img,
                   new Int32Rect(x * TileSize,
                          y * TileSize,
                          TileSize, TileSize));
          SaveImage(subImg, fInfo.Extension, 
            string.Format( "{0}_{1}{2}", x, y, fInfo.Extension));

        }
      }
    }
 
    private void SaveImage(BitmapSource image, 
                           string extension, string filePath)
    {
      var encoder = ImageUtilities.GetEncoderFromExtension(extension);
      using (var fs = new FileStream(filePath, 
              FileMode.Create, FileAccess.Write))
      {
        encoder.Frames.Add(BitmapFrame.Create(image));
        encoder.Save(fs);
        fs.Flush();
        fs.Close();
      }
    }
  }
}
You construct this class with a full path to an image file as a string, and then call the "Cut" method with tilesize in pixels (tiles are considered to be square) and the number of tiles in horizontal and vertical direction. It then goes on to cut the image into tiles of TileSize x TileSize pixels. Notice a few things:
img.CacheOption = BitmapCacheOption.OnLoad;
makes sure the image is loaded in one go, and does not get locked The trick of cutting the image itself is done by
var subImg = new CroppedBitmap(img,
               new Int32Rect(x * TileSize,
               y * TileSize,
               TileSize, TileSize));
and then it is fed to a simple private method that saves it to a file. Last, I do not check if the image is large enough to cut the number of tiles you want from. This is a sample, eh? The sample uses a small utility class that gets the right imaging encoder from either the file extension or the mime type, whatever you pass on to it
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace LocalJoost.ImageCutting
{
  /// 
  /// Class with Image utilities - duh
  /// 
  public static class ImageUtilities
  {
    public static BitmapEncoder GetEncoderFromMimeType(string mimeType)
    {
      switch (mimeType.ToLower())
      {
        case "image/jpg":
        case "image/jpeg": 
          return new JpegBitmapEncoder();
        case "image/gif": 
          return new GifBitmapEncoder();
        case "image/png":
          return new PngBitmapEncoder();
        case "image/tif":
        case "image/tiff":
          return new TiffBitmapEncoder();
        case "image/bmp": 
          return new BmpBitmapEncoder();
      }
      return null;
    }

    public static BitmapEncoder GetEncoderFromExtension(string extension)
    {
      return GetEncoderFromMimeType( extension.Replace(".", "image/"));
    }
  }
}
Not only are the System.Windows.Media.Imaging classes easier to use, they are also faster: switching from GDI+ to System.Windows.Media.Imaging reduced processing time to 50%, with an apparant significant lower CPU load and memory requirement. A complete example, including a unit test project that contains a test image which performs the completely hypothetical action of cutting a large 2048x2048 map file into 256x256 tiles ;-), is downloadable here. This project contains the following statement
Path.GetDirectoryNameAssembly.GetExecutingAssembly().Location
don't be intimidated by this, that's just a way to determine the full path of the current directory, i.e. the directory in which the unit test is running - you will find the resulting images there.