Click here to Skip to main content
15,867,835 members
Articles / Desktop Programming / XAML

Image Processing in Metro

Rate me:
Please Sign up or sign in to vote.
3.35/5 (14 votes)
4 Apr 2012CPOL2 min read 63.3K   2.9K   24   14
How to do third party image processing in new Metro style apps.

Introduction

I finally got around to playing with the Windows 8 developer preview and Metro apps. After tinkering around with the new Start Menu and apps, I decided to try a simple image display and processing Metro app.  

Using the Code

First, I created a basic layout with 2 buttons, an image, and label for displaying some metadata. I was happy to see that they stuck with XAML so the learning curve was very small.

XML
<Grid x:Name="LayoutRoot" Background="#FF0C0C0C">
   <StackPanel>
      <StackPanel Orientation="Horizontal">
         <Button Content="Load" FontSize="24" Width="200" Height="60" Click="Load_Click" />
         <Button Content="Process" FontSize="24" Width="200" Height="60" 
            Click="Process_Click" />
      </StackPanel>
      <Image x:Name="Image1" Width="800" Height="600" Stretch="Uniform" 
         Source="Windows8Logo.png"/>
      <TextBlock x:Name="DisplayText" FontSize="48" Foreground="White" />
   </StackPanel>
</Grid> 

To load the image, I used the new FileOpenPicker. I really liked the look and feel of this control and found its file filter an improvement on the old WinForms way of using a single string.

C#
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".cmp");
openPicker.FileTypeFilter.Add(".png");
openPicker.FileTypeFilter.Add(".tif");
openPicker.FileTypeFilter.Add(".gif");
openPicker.FileTypeFilter.Add(".bmp");
StorageFile file = await openPicker.PickSingleFileAsync();
int loadBitsPerPixel = 0;
RasterCodecs codecs = new RasterCodecs();
if (file != null)
{
   string fileName = file.Path;
   var winRTStream = await file.OpenAsync(FileAccessMode.ReadWrite);
   IInputStream inputStream = winRTStream.GetInputStreamAt(0);
   DataReader dataReader = new DataReader(inputStream);
   await dataReader.LoadAsync((uint)winRTStream.Size);
   var buffer = dataReader.ReadBuffer((uint)winRTStream.Size);
   using (System.IO.Stream oldRTStream = buffer.AsStream())
   {
      using (RasterImage rasterImage = codecs.Load(oldRTStream, loadBitsPerPixel, 
         CodecsLoadByteOrder.BgrOrGray, 1, 1))
      {
         DisplayText.Text = string.Format("Filename: {0} - {1}x{2}x{3} - {4}", 
            file.FileName, 
            rasterImage.Width, 
            rasterImage.Height, 
            rasterImage.BitsPerPixel, 
            rasterImage.OriginalFormat.ToString());
         Image1.Source = RasterImageConverter.ConvertToSource(rasterImage, 
            ConvertToSourceOptions.None);
      }
   }
}  

metroimageprocessing/filepicker_screen.jpg

I’ve always felt like native image processing was lacking and don’t mind using third party libraries, so I tried an evaluation copy of LEADTOOLS I had from a previous project to see if it worked on the new Windows 8. The .NET 4 libraries worked, but in order to convert form the LEADTOOLS RasterImage class to the new Metro ImageSource, I used a pre-release DLL from their support department:

C#
using (RasterImage image = RasterImageConverter.ConvertFromSource(Image1.Source, 
   ConvertFromSourceOptions.None))
{ 
   BricksTextureCommand cmd = new BricksTextureCommand(60, 20, 4, 3);
   cmd.Run(image);
   Image1.Source = RasterImageConverter.ConvertToSource(image, 
      ConvertToSourceOptions.None);
}

metroimageprocessing/ip_screen.jpg

Overall, I enjoy the new Metro style apps. It was fun to play around with the developer preview and it was comforting to see the learning curve is minimal and that third party components are already getting their feet wet as well rather than waiting for Windows 8 to be "officially" released.

Note Regarding Visual Studio 11 Beta and Windows 8 Consumer Preview

When I originally wrote this, I used Visual Studio 11 Developer Preview.  Since then I've tried the same example with Visual Studio 11 Beta and Windows 8 Consumer Preview and it no longer works due to Metro apps now using .Netcore rather than accepting .NET Framework 4.0 libraries (see this forum post for more details). 

Native Code Example

As requested by some users, I've attached an app that does some image processing without any 3rd party tools.  

Here is how I loaded the image programmatically using the FileOpenPicker:

C#
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".cmp");
openPicker.FileTypeFilter.Add(".png");
openPicker.FileTypeFilter.Add(".tif");
openPicker.FileTypeFilter.Add(".gif");
openPicker.FileTypeFilter.Add(".bmp");
StorageFile file = await openPicker.PickSingleFileAsync();
IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read);
BitmapImage bmp = new BitmapImage();
bmp.SetSource(stream);
Image1.Source = bmp;

Here's the code for flipping an image. The first step is to gain access to the pixel data by creating a WriteableBitmap. Then read from the top and bottom of the image and swap the rows.

C#
// Cast the image in the viewer as a WriteableBitmap
WriteableBitmap wb = Image1.Source as WriteableBitmap;

// If it's a WriteableBitmap, just use it, otherwise create one
if (wb == null) 
{
   BitmapSource bs = Image1.Source as BitmapSource;
   wb = new WriteableBitmap(bs);
}

// Assume 32 bits since that is what Metro currently supports
int stride = wb.PixelWidth * 4; 

// extension method defined in System.Runtime.InteropServices.WindowsRuntime
System.IO.Stream pixelStream = wb.PixelBuffer.AsStream(); 

byte[] row1 = new byte[stride];
byte[] row2 = new byte[stride];

// flip the image
for (int row = 0; row < wb.PixelHeight / 2; row++)
{
   pixelStream.Read(row2, 0, stride);
   pixelStream.Seek((wb.PixelHeight - row - 1) * stride, SeekOrigin.Begin);
   pixelStream.Read(row1, 0, stride);
   pixelStream.Seek(-stride, SeekOrigin.Current);
   pixelStream.Write(row2, 0, stride);
   pixelStream.Seek(row * stride, SeekOrigin.Begin);
   pixelStream.Write(row1, 0, stride);
}

wb.Invalidate();
Image1.Source = wb; 

metroimageprocessing/flip.jpg

History

  • 7th November, 2011: Initial post  
  • 11th November, 2011: Added non-third party example 
  • 4th April, 2012: Added note about Consumer Preview 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
Starting with my NES in 1990, I've loved computers ever since. Writing video game hacks (the kinds for unlimited health and super-powerful guns mind you...I always purchase my software!) and webpages for fun in middle school, a college education in Computer Science and a career in software development was a lock.

Currently, I work as a web developer and technical writer and primarily use .NET.

Comments and Discussions

 
GeneralMy vote of 3 Pin
LLLLGGGG1-Jul-13 22:29
LLLLGGGG1-Jul-13 22:29 
Questioncool Pin
Hellowlf23-Jul-12 22:02
Hellowlf23-Jul-12 22:02 
GeneralMy vote of 5 Pin
Farhan Ghumra27-Jun-12 19:23
professionalFarhan Ghumra27-Jun-12 19:23 
QuestionLeadTools does not exists in example with using LeadTools dlls Pin
ilia198726-Jan-12 4:58
ilia198726-Jan-12 4:58 
AnswerRe: LeadTools does not exists in example with using LeadTools dlls Pin
gregtheross26-Jan-12 5:04
gregtheross26-Jan-12 5:04 
SuggestionLove it! Pin
Terry Powell himself21-Nov-11 7:03
Terry Powell himself21-Nov-11 7:03 
GeneralRe: Love it! Pin
gregtheross22-Nov-11 4:03
gregtheross22-Nov-11 4:03 
QuestionPerfect, and I have a question. Pin
PierreBonnet21-Nov-11 6:54
PierreBonnet21-Nov-11 6:54 
AnswerRe: Perfect, and I have a question. Pin
gregtheross22-Nov-11 4:01
gregtheross22-Nov-11 4:01 
GeneralMy vote of 1 Pin
Richard Deeming15-Nov-11 8:19
mveRichard Deeming15-Nov-11 8:19 
GeneralMy vote of 1 Pin
User 482203315-Nov-11 2:37
User 482203315-Nov-11 2:37 
QuestionWhy? Pin
HaBiX7-Nov-11 23:43
HaBiX7-Nov-11 23:43 
AnswerRe: Why? Pin
gregtheross8-Nov-11 4:04
gregtheross8-Nov-11 4:04 
GeneralMy vote of 1 PinPopular
Axel Rietschin7-Nov-11 7:21
professionalAxel Rietschin7-Nov-11 7:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.