In these days I’m working on an Asp.Net image manipulation HttpHandler (well, I’m REworking on my old HttpHandler) that is built upon WPF libraries.
I’m new at image manipulation programming, and I don’t know WPFs so well, so I need to TRY nearly every single line of code. This handler is compiled in an assembly, referenced by a test website. This means that each time I make a change in the source code I need to recompile the assembly (wich contains a lot of other classes), update the reference, refresh the page on the browser just to see that I’ve done another horrible mistake.
Luckly I’ve found out that the latest beta version of LINQPad (4.31, at the time of writing) allows us to dump images on the result window.
Don’t you know LINQPad?
Damn, you MUST.
LINQPad is an awesome tool developed by Joseph Albahari, that works as code snippet editor, database navigator, learning tool and more. It’s free (without intellisense), cheap (with intellisense), it’s built upon the .NET framework and can execute your C#/VB.Net statements, programs or expressions (and SQL, of course). It can reference assemblies from GAC, or it can be linked to your own DLLs, allowing you to call compiled methods, instantiate classes, etc., speeding up the development.
In this tip I just want to show to you how to configure LINQPad for working with WPF and how to have fun with image manipulation, in a fast and easy way.
Download LINQPad
First of all you have to download the latest version of LINQPad (at least the version 4.31, that by now it’s only in beta). There are two versions: for the .NET framework 3.5 or 4.0, depending on your system.
Referencing the needed Assemblies
For my tests I need 3 assemblies from the GAC:
- WindowsBase.dll
- PresentationCore.dll
- System.Xaml.dll
To use them in the project just click on Query -> Query Properties

On “Additional References” tab click on “Add…”. You can now find and add to the query environment the previous mentioned dlls.

In order to simplify the writing of your code, you can import necessary namespaces on the query (as the “using” keyword does on Visual Studio) from the Query Properties’ tab “Additional Namespace Imports”. I’ve just added:
- System.Windows
- System.Windows.Media
- System.Windows.Media.Imaging
Ready to start.
A sample program
Related to C#, LINQPad allows you to write expressions, statements or entire programs that contain classes, methods and so on. To make the code most portable as possible I’ve selected “C# Program” from the Language combo on the query window, obtaining a basic snippet:
void Main()
{
}
// Define other methods and classes here
Now let’s start to code.
This example will load an image (a frame from the Futurama titles), then composes a new image applying scaling, rotation and watermarking a text.
It’s completely unnecessary for the target of this article… but it’s funny, you know.
The scale factor is 35% and the image will be rotated 10° counterclockwise.
void Main()
{
RotateAndScale("C:\\futurama.jpg", 0.35, -10);
}
public void RotateAndScale(string ImagePath, double Scale, double Degrees)
{
BitmapImage originalImage = new BitmapImage();
originalImage.BeginInit();
originalImage.CacheOption = BitmapCacheOption.OnLoad;
originalImage.UriSource = new Uri(ImagePath);
originalImage.EndInit();
double newWidth = originalImage.Width * Scale;
double newHeight = originalImage.Height * Scale;
RenderTargetBitmap targetImage = new RenderTargetBitmap((int)Math.Ceiling(newWidth),
(int)Math.Ceiling(newHeight),
96, 96,
PixelFormats.Default);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
dc.PushTransform(new RotateTransform(Degrees, newWidth/2, newHeight/2));
ImageBrush db = new ImageBrush(originalImage);
dc.DrawRectangle(db, new Pen() { Brush = Brushes.Transparent }, new Rect(0, 0, newWidth, newHeight));
FormattedText formattedText = new FormattedText("Is back",
System.Globalization.CultureInfo.CurrentCulture,
System.Windows.FlowDirection.RightToLeft,
new Typeface(new FontFamily("Tahoma"),
FontStyles.Italic,
FontWeights.Normal,
FontStretches.Normal),
18,
System.Windows.Media.Brushes.Black);
dc.PushTransform(new RotateTransform(-Degrees, newWidth/2, newHeight/2));
dc.DrawText(formattedText, new Point(newWidth - 5, newHeight - 18));
}
targetImage.Render(dv);
StreamOut(targetImage);
}
public void StreamOut(BitmapSource image)
{
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(image));
using (MemoryStream stream = new MemoryStream())
{
encoder.Save(stream);
}
}
Now you can execute this small program by pressing F5, or the Execute button on the top of the query window.
…But nothing happens.
That’s because we haven’t put the BitmapSource image on the result window.
Dump to output
LINQPad has an extension method called Dump() that you can use to push something on the result window. It works with any .NET types, and for the complex types it bulds an HTML table representing the object you’re dumping. But we can’t dump the stream we have built on the last step, because we will obtain something like this:

But we need to SEE the resulting image.
As I mentioned before, the latest beta version of LINQPad has an awesome helper method to stream out images, that is called Image() and it’s accessible from the Util class. This method returns an object that can be safely dumped to the result window.
So we’ll modify the StreamOut method as follows:
public void StreamOut(BitmapSource image)
{
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(image));
using (MemoryStream stream = new MemoryStream())
{
encoder.Save(stream);
Util.Image(stream.ToArray()).Dump();
}
}
F5 angain and…

…you can see the result of the program in real-time. Now every time we make a change to the previous code, we just need to press F5 to see the effects of our changes.
When the code above will be ready, we have to copy it back to the handler class and replace the specificity of LINQPad with the correct method for the output (that in my case means to change the StreamOut() method with):
public void StreamOut(BitmapSource image)
{
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(image));
using (MemoryStream stream = new MemoryStream())
{
encoder.Save(stream);
stream.WriteTo(HttpContext.Current.Response.OutputStream);
}
}