CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5

Threaded View

  1. #1
    Join Date
    Aug 2008
    Posts
    902

    Image manipulation in WPF

    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:

    Code:
    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.
    Last edited by Chris_F; September 29th, 2010 at 01:23 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured