# Other .NET Programming > Windows Presentation Foundation (WPF) & XAML forum >  Image manipulation in WPF

## Chris_F

I want do do some image editing, bluring, levels adjustment and other random effects, and normally this is really slow in C#. I've done it before with GetPixel / SetPixel using System.Drawing.Bitmap, which is easy to implement, but gruesomely slow. Next I tried converting the Bitmap into a byte[] and then manipulating the image as an array, which is much faster than the previous methods.

I stumbled upon this a while back and messed around with it.

http://blogs.microsoft.co.il/blogs/t...-tutorial.aspx

It uses a HLSL shader to do the image manipulation, and is probably 10,000 times faster than anything else you could do in C#. I'm familiar with HLSL, but I have never used WPF before and am at a loss when it comes to how to implement this in my program. I'd like to be able to open an image, apply the filter, and then save the image.

Here is the code from the link I gave:



```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Win32;
using System.IO;
using System.Diagnostics;
using System.Windows.Media.Effects;

namespace HLSLTester
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

       

        private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "Images|*.jpg;*.png;*.bmp;*.gif|All Files|*.*";
            if (ofd.ShowDialog(this) == true)
            {

                img.Source = new BitmapImage(new Uri(ofd.FileName));
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            string path = string.Format("{0}\\tmp",Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData));
            using (FileStream fs = new FileStream(path+".fx", FileMode.Create))
            {
                byte[] data = Encoding.ASCII.GetBytes(code.Text);
                fs.Write(data,0,data.Length);
            }


            ProcessStartInfo psi = new ProcessStartInfo("fxc");
            psi.CreateNoWindow = true;
            psi.UseShellExecute = false;
            
            psi.RedirectStandardError = true;

            psi.Arguments = string.Format("/T ps_3_0 /E main /Fo\"{0}.ps\" \"{0}.fx\"",path);
            comp.Text = string.Empty;
            using (Process p = Process.Start(psi))
            {

                StreamReader sr = p.StandardError;
                comp.Text = sr.ReadToEnd().Replace(path+".fx","Line ");

                p.WaitForExit();
            }

            if (comp.Text == string.Empty)
            {
                PixelShader ps = new PixelShader();
                ps.UriSource = new Uri(path + ".ps");
                CustomShaderEffect se = new CustomShaderEffect(ps);
 
                img.Effect = se;
            }
            
        }
    }

    class CustomShaderEffect : ShaderEffect
    {
        public CustomShaderEffect(PixelShader shader)
        {
            PixelShader = shader;
            UpdateShaderValue(InputProperty);
        }

        public Brush Input
        {
            get { return (Brush)GetValue(InputProperty); }
            set { SetValue(InputProperty, value); }
        }

        public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(CustomShaderEffect), 0);

    }
}
```

I get how this works, but I have NO clue how to save the resulting image back to a file. In general, I have very little clue how Image, BitmapImage and other classes work, as I am only familiar with the System.Drawing image and bitmap classes.

For anyone looking at the code who needs additional explaining, it is taking a .fx file with your pixel shader code and using fxc.exe to compile it into .ps shader file.

Thanks for any help in advance.

----------


## TheGreatCthulhu

Check out the BmpBitmapEncoder class. If you scroll all the way down, you'll find an example.

The XyzBitmapEncoder classes apparently provide a lot of flexibility, compared to what you had before with Bitmap.Save(...) methods at least.

You can also try and pull some bitmap data (bitmap bits) based stunt to get an System.Drawing.Bitmap object.

----------


## Chris_F

> Check out the BmpBitmapEncoder class. If you scroll all the way down, you'll find an example.
> 
> The XyzBitmapEncoder classes apparently provide a lot of flexibility, compared to what you had before with Bitmap.Save(...) methods at least.
> 
> You can also try and pull some bitmap data (bitmap bits) based stunt to get an System.Drawing.Bitmap object.


Hmm, well I know how to load an image, and display it with a shader effect, and I also know how to load an image and then save it, but I don't know how to load an image, apply an effect and then save it.

----------


## Dani123

> Hmm, well I know how to load an image, and display it with a shader effect, and I also know how to load an image and then save it, but I don't know how to load an image, apply an effect and then save it.


I have exactly the same problem. I can load a photo to an Image-control, manipulate it with some fancy pixel shaders, but i've failed to save the manipulated photo in original size. I managed to save a jpeg with 800xSomething, but I need it in full size.

Uncle Google hasn't provided any useful code snippets about the saving thing, so i'm happy about every reply.

Greetings from Switzerland
Dani123

----------


## Chris_F

I guess it can be done using either RenderTargetBitmap or WritableBitmap, but the problem is that if you do this, the pixel shading gets done in software, there is no way to get hardware acceleration. You also can't use multiple shaders or use a multi-pass shader (major disappointment, these seem like huge flaws)  so WPF is useless for what I wanted.

----------

