Click here to Skip to main content
15,867,568 members
Articles / Desktop Programming / WPF
Article

Quick Retouch+

Rate me:
Please Sign up or sign in to vote.
5.00/5 (7 votes)
7 Oct 2012CPOL3 min read 23.4K   13   12
This app will help users to quickly add different type of effects on a picture like sketch, oldphoto, emboss, nightvision, cartoon, oilify, etc.

This article is an entry in our AppInnovation Contest. Articles in this sub-section are not required to be full articles so care should be taken when voting.

Introduction

For the App Innovation Contest, I propose to develop a Quick Retouch+ App.

This app will help users to quickly add different type of effects on a picture like sketch, oldphoto, emboss, nightvision, cartoon, oilify, etc. Users will also be able to add different types of frame just using a single touch, change EXIF information, and resize or crop an image. You can also perform red eye reduction, and there is a lens correction option. Finally, the user can directly upload his modified image to any social network using Quick Retouch+.

Background

Nowadays, retouching images is a fashion and social networks make it more popular with image sharing. Besides this, sometimes users need to change the brightness, contrast, or size to make it more fashionable. Here, I have just packed all things into one bundle and made it a fun task. Everything is possible from one place.

Note

I am developing this app for my own interest and now "Windows 8 Ultra Book App Dev Contest" has provided me a good opportunity to expose my ideas and show my strength. Some parts of this app are still under development.

Development Step

To make my development more understandable, I will discuss some code sections to represent my Details Level Design (DLD) and most of the UI activities.

Let's start the journey.

1. APP UI Code Section

I have used Expression Studio to design my primary mockup of UI. It is a great development tool for UI design. And WPF, which employs XAML, an XML-based language, to define and link various UI elements.

XML
<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
            mc:Ignorable="d" x:Class="WPFGui.MainWindow"
        Title="MainWindow" Height="687" Width="1010" 
           Background="Transparent"  WindowStyle="None" KeyDown="Window_KeyDown" 
           BorderThickness="0" AllowsTransparency="True" BorderBrush="#FF73695C">
    <Window.Resources>
 
        <!--Border Brush for Select Image-->
        <LinearGradientBrush x:Key="SelectionBrush" EndPoint="0.5,1" 
               MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
            <LinearGradientBrush.RelativeTransform>
                <TransformGroup>
                    <ScaleTransform CenterY="0.5" CenterX="0.5"/>
                    <SkewTransform CenterY="0.5" CenterX="0.5"/>
                    <RotateTransform Angle="-45" CenterY="0.5" CenterX="0.5"/>
                    <TranslateTransform/>
                </TransformGroup>
            </LinearGradientBrush.RelativeTransform>
            <GradientStop Color="#FFC3681E" Offset="0"/>
            <GradientStop Color="#FFFBA503" Offset="1"/>
        </LinearGradientBrush>
        <!---->
        
        <!--Toolbar style-->
        <SolidColorBrush x:Key="toolbarMouseOver" Color="White" Opacity=".2"/>
        <SolidColorBrush x:Key="toolbarMouseClick" Color="Black" Opacity=".7"/>
        
        <Style x:Key="toolbarButton" TargetType="{x:Type Button}">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
 
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border  x:Name="buttonBorder" BorderBrush="Transparent" 
                                Margin="0,2,2,2" BorderThickness="1" CornerRadius="1">
                            <ContentPresenter />
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="buttonBorder" Property="Background" 
                                     Value="{StaticResource ResourceKey=toolbarMouseOver}" />
                                <Setter TargetName="buttonBorder" Property="BorderBrush" 
                                     Value="{StaticResource ResourceKey=toolbarMouseOver}" />
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter TargetName="buttonBorder" Property="Background" 
                                    Value="{StaticResource toolbarMouseClick}" />
                                <Setter TargetName="buttonBorder" Property="BorderBrush" 
                                    Value="{StaticResource toolbarMouseClick}" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
 
        <!-- Static Image Resources-->
        <ImageBrush x:Key="Logo" ImageSource="UIRES\kies-png-small.png" />
        <!--Style TargetType="{x:Type MenuItem}">
            <Setter Property="Background" Value="#FFFFFF"/>
            <Setter Property="Foreground" Value="#854E3B"/>
        </Style-->
        <Style TargetType="{x:Type Control}" x:Key="baseStyle">
            <Setter Property="FontFamily" Value="Tahoma"/>
            <Setter Property="FontSize" Value="11"/>
        </Style>
        <!--<Style TargetType="{x:Type Button}" BasedOn="{StaticResource baseStyle}"/>
        <Style TargetType="{x:Type Label}" BasedOn="{StaticResource baseStyle}"/>
        <Style TargetType="{x:Type Menu}" BasedOn="{StaticResource baseStyle}"/>
        <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource baseStyle}"/>
        <Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource baseStyle}"/>-->
    </Window.Resources>
    
    <Grid>
        <Rectangle x:Name="LeftMargin" Margin="0,0,993,16" Fill="#FFCFC7BC"/>
        <Rectangle x:Name="RifghtMargin" Margin="0,0,0,16" 
              Fill="#FFCFC7BC" HorizontalAlignment="Right" Width="6"/>
        <Rectangle x:Name="Title" Height="29" 
               VerticalAlignment="Top" 
               MouseLeftButtonDown="Title_MouseLeftButtonDown" Fill="#FFCFC7BC"/>
        <Rectangle x:Name="Bottom" Height="29" 
              VerticalAlignment="Bottom" 
              MouseLeftButtonDown="Title_MouseLeftButtonDown" Fill="#FFCFC7BC"/>
        <Rectangle x:Name="Logo" Height="16" VerticalAlignment="Top" 
               MouseLeftButtonDown="Title_MouseLeftButtonDown" 
               Fill="{StaticResource ResourceKey=Logo}" Margin="12,5,0,0" 
               HorizontalAlignment="Left" Width="16" />
        <StackPanel Margin="27,0,647,657" Background="Transparent" 
                       Orientation="Horizontal">
            <Menu Name="MainMenu" Background="Transparent" 
                     DockPanel.Dock="Left" Margin="5,5,5,-3" 
                     Style="{StaticResource ResourceKey=baseStyle}" Height="27" Width="331.3">
                <MenuItem Header="File" Margin="9,0,9,0" Style="{StaticResource StyleMenuItem}">
                    <MenuItem Header="Add file to Library"/>
                    <MenuItem Header="Add folder to Library"/>
                    <Separator/>
                    <MenuItem Header="Add file to Connected Device" IsEnabled="False"/>
                    <MenuItem Header="Add Folder to Connected Device" IsEnabled="False"/>
                    <Separator/>
                    <MenuItem InputGestureText="Alt+F4" Header="Exit" Click="CloseButton_Click"/>
                </MenuItem>
                <MenuItem Header="Edit" Margin="9,0,9,0" Style="{StaticResource StyleMenuItem}">
                    <MenuItem Header="Copy"/>
                    <MenuItem Header="Pase" IsEnabled="False"/>
                    <Separator/>
                    <MenuItem Header="Delete"/>
                    <Separator/>
                    <MenuItem Header="Select All"/>
                    <MenuItem Header="Deselect All"/>
                </MenuItem>
                <MenuItem Header="View" Margin="9,0,9,0" Style="{StaticResource StyleMenuItem}">
                    <MenuItem Header="List View"/>
                    <MenuItem Header="Thumbnail View"/>
                    <Separator />
                    <MenuItem Header="Sort Thumbnails" IsEnabled="False"/>
                    <MenuItem Header="Goto Current playing Music" IsEnabled="False"/>
                    <MenuItem Header="Goto Current playing Podcast" IsEnabled="False"/>
                </MenuItem>
                <MenuItem Header="Tool" Margin="9,0,9,0" Style="{StaticResource StyleMenuItem}">
                    <MenuItem Header="Connect Using Bluetooth"/>
                    <Separator/>
                    <MenuItem Header="Emergency Firmware Recovery"/>
                    <MenuItem Header="Firmware Updgrade Settings"/>
                </MenuItem>
                <MenuItem Header="Help" 
                Margin="10,0,9,0" Style="{StaticResource StyleMenuItem}">
                    <MenuItem Header="Kies Help"/>
                    <MenuItem Header="Kies Tutorial"/>
                    <Separator/>
                    <MenuItem Header="Check for updates"/>
                    <Separator/>
                    <MenuItem Header="Kies Information"/>
                </MenuItem>
                <MenuItem Name="webShareMenu" Header="WebShare" 
                     Margin="10,0,9,0" 
                     Style="{StaticResource StyleMenuItem}" Visibility="Hidden"/>
            </Menu>
        </StackPanel>
 
        <Border x:Name="Body" Margin="205,29,6,29" 
        BorderBrush="#FF85817E" MouseUp="Body_MouseUp">
            <Border.Background>
            	<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
            		<GradientStop Color="#FF3C3C3C" Offset="0"/>
            		<GradientStop Color="#FF2B2B2B" Offset="1"/>
            	</LinearGradientBrush>
            </Border.Background>
        </Border>
        <Border x:Name="TitleBorder" BorderBrush="#FF73695C" 
        BorderThickness="1" CornerRadius="0.5">
            <StackPanel x:Name="stackPanel1" />
        </Border>
        <DockPanel LastChildFill="False" VerticalAlignment="Top" 
                   HorizontalAlignment="Right" Margin="0,1.664,0,0">
            <Button x:Name="MinimizeButton" 
                    Visibility="Visible" 
                    DockPanel.Dock="Left"
                    Style="{StaticResource LooklessButton}" 
                    Margin="2" Click="MinimizeButton_Click">
                <Image Stretch="Uniform" 
                           Source="UIRES\min-1.png" 
                           Height="10" 
                           Width="10" Margin="3"/>
            </Button>
            
            <Button x:Name="MaximizeButton" 
                    Visibility="Visible" 
                    DockPanel.Dock="Left"
                    Style="{StaticResource LooklessButton}" 
                    Margin="2" Click="MaximizeButton_Click">
                <Image Stretch="Uniform" 
                           Source="UIRES\max-1.png" 
                           Height="10" 
                           Width="10" Margin="3"/>
            </Button>
            
            <Button x:Name="CloseButton" 
                    Visibility="Visible" 
                    DockPanel.Dock="Left"
                    Style="{StaticResource LooklessButton}" 
                    Margin="2" Click="CloseButton_Click">
                <Image Stretch="Uniform" 
                           Source="UIRES\close-1.png" 
                           Height="10" 
                           Width="10" Margin="3"/>
            </Button>
        </DockPanel>
        <StackPanel x:Name="SideBar" Margin="7,29,766,29" >
        	<Image Source="UIRes\SideBar.png" Stretch="Fill" 
                 Height="641.384" Margin="0,0,31,0"/>
        </StackPanel>
        <StackPanel x:Name="RightSide" 
        Margin="214,30,6,16" Orientation="Vertical">
            <Grid>
                <Rectangle Height="36" 
                HorizontalAlignment="Center" VerticalAlignment="Center">
                    <Rectangle.Fill>
                            <LinearGradientBrush  EndPoint="0.5,1" StartPoint="0.5,0">
                                <GradientStop Color="#FF747067" Offset="0"/>
                                <GradientStop Color="#FF5A5750" Offset="1"/>
                            </LinearGradientBrush>
                        </Rectangle.Fill>
                </Rectangle>
                <Button Content="Add Photos"
                        Height="28" 
                        HorizontalAlignment="Left" x:Name="button1"
                        VerticalAlignment="Top" Width="89.5"
                        Style="{StaticResource ResourceKey=CustomButtonMainInterface}" 
                        Foreground="White" 
                        Margin="4,4,0,0" />
                <Button Content="Delete"
                	Height="28" HorizontalAlignment="Left" x:Name="button1_Copy"
                	VerticalAlignment="Top" 
                	Width="72.167"
                	Style="{StaticResource ResourceKey=CustomButtonMainInterface}" 
                	Foreground="#FF929292" 
                	Margin="90.836,4,0,0" IsEnabled="False" />
                <Button Content="Transfer To Device"
                	Height="28" HorizontalAlignment="Left" x:Name="button1_Copy1"
                	VerticalAlignment="Top" Width="120.5"
                	Style="{StaticResource ResourceKey=CustomButtonMainInterface}" 
                	        Foreground="#FF929292" 
                	        Margin="175.667,4,0,0" IsEnabled="False" />
                <Button Visibility="Hidden" Content="Edit" 
                           Height="28" HorizontalAlignment="Left" Margin="311,4,0,0" 
                           Name="editButton" Style="{StaticResource CustomButtonMainInterface}" 
                           VerticalAlignment="Top" 
                           Width="63" Click="editButton_Click">
                	<Button.Foreground>
                		<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                			<GradientStop Color="#FF7492EB" Offset="1"/>
                			<GradientStop Color="#FF4A66BC"/>
                		</LinearGradientBrush>
                	</Button.Foreground>
                </Button>
            </Grid>
            <Border>
                    <Image Source="UIRes\topBar2.png" Stretch="Uniform"/>
            </Border>
            <Border Height="28" BorderBrush="#FF222222" 
                     BorderThickness="1" HorizontalAlignment="Stretch">
                <Border.Background>
                    <LinearGradientBrush  EndPoint="0.5,1" StartPoint="0.5,0">
                        <GradientStop Color="#FF474747" Offset="0"/>
                        <GradientStop Color="#FF444444" Offset="1"/>
                    </LinearGradientBrush>
                </Border.Background>
                <Label Content="2012-2-21" Height="14" x:Name="label1" 
                       Margin="26,0,0,0" Width="52" 
                       Padding="0" HorizontalAlignment="Left" 
                       VerticalAlignment="Center" 
                       Foreground="White" FontWeight="Light"/>
            </Border>
            <StackPanel Height="214" x:Name="imagePanel" 
            Width="Auto" Orientation="Horizontal">
                <StackPanel VerticalAlignment="Center" 
                HorizontalAlignment="Center">
                    <Border x:Name="imgBorder1" 
                    BorderThickness="1" BorderBrush="Wheat" 
                               Height="104" Margin="20,10" 
                               MouseUp="Border_MouseClick">
                        <Image Source="UIRes\image1.jpg" />
                    </Border>
                    <Border x:Name="imgToolbar1" 
                    BorderThickness="1" BorderBrush="Black" 
                               CornerRadius="1" 
                               Width="102" Height="24" 
                               d:LayoutOverrides="Width, 
                               Height" Visibility="Hidden">
                    	<Border.Effect>
                    		<DropShadowEffect BlurRadius="3" ShadowDepth="2"/>
                    	</Border.Effect>
                    	<Border.Background>
                    		<ImageBrush ImageSource="UIRes\toolbar.png"/>
                    	</Border.Background>
                    	<StackPanel Width="102" 
                    	Height="22" Orientation="Horizontal" 
                    	          HorizontalAlignment="Center" 
                    	          VerticalAlignment="Center">
                    		<Button Style="{StaticResource ResourceKey=toolbarButton}" 
                                                Margin="2,0">
                    			<Image Source="UIRes\iconStar.png"/>
                    		</Button>
                    		<Path Data="M150,2 L150,22" Margin="0,0.75,0,0.25" 
                    		        Stretch="Fill" 
                    		        Width="1" Stroke="#FFB8B8B8"/>
                    		<Button Margin="2,0" 
                    		        Style="{StaticResource ResourceKey=toolbarButton}" 
                                                Width="22" >
                    			<Image Source="UIRes\iconTag.png"/>
                    		</Button>
                    		<Path Data="M150,2 L150,22" Margin="0,0.75,0,0.25" 
                    		        Stretch="Fill" 
                    		        Width="1" Stroke="#FFB8B8B8"/>
                    		<Button Margin="2,0" 
                    		         Style="{StaticResource ResourceKey=toolbarButton}" 
                                                 Width="22" >
                    			<Image Source="UIRes\iconUndo.png" Margin="0"/>
                    		</Button>
                    		<Path Data="M150,2 L150,22" 
                    		Margin="0,0.75,0,0.25" 
                    		          Stretch="Fill" 
                    		          Width="1" Stroke="#FFB8B8B8"/>
                    		<Button Margin="2,0" 
                                 Style="{StaticResource 
                                 ResourceKey=toolbarButton}" Width="22">
                    			<Image Source="UIRes\iconRedo.png"/>
                    		</Button>
                    	</StackPanel>
                    </Border>
                </StackPanel>
 
                <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                    <Border x:Name="imgBorder2" BorderBrush="Wheat" 
                            BorderThickness="1" Height="93" 
                            Margin="20,10" MouseUp="Border_MouseClick">
                        <Image Source="UIRes\image2.jpg"/>
                    </Border>
                    <Border x:Name="imgToolbar2" 
                    BorderThickness="1" BorderBrush="Black" 
                             CornerRadius="1" Width="102" Height="24" 
                             d:LayoutOverrides="Width, Height" Visibility="Hidden">
                    	<Border.Effect>
                    		<DropShadowEffect BlurRadius="3" ShadowDepth="2"/>
                    	</Border.Effect>
                    	<Border.Background>
                    		<ImageBrush ImageSource="UIRes/toolbar.png"/>
                    	</Border.Background>
                    	<StackPanel Width="102" 
                    	Height="22" Orientation="Horizontal" 
                    	        HorizontalAlignment="Center" VerticalAlignment="Center">
                    		<Button Style="{StaticResource ResourceKey=toolbarButton}" 
                                                Margin="2,0">
                    			<Image Source="UIRes\iconStar.png"/>
                    		</Button>
                    		<Path Data="M150,2 L150,22" Margin="0,0.75,0,0.25" 
                    		        Stretch="Fill" 
                    		        Width="1" Stroke="#FFB8B8B8"/>
                    		<Button Margin="2,0" 
                    		         Style="{StaticResource ResourceKey=toolbarButton}" 
                    		         Width="22" >
                    			<Image Source="UIRes/iconTag.png"/>
                    		</Button>
                    		<Path Data="M150,2 L150,22" Margin="0,0.75,0,0.25" 
                    		      Stretch="Fill" 
                    		      Width="1" Stroke="#FFB8B8B8"/>
                    		<Button Margin="2,0" 
                    		       Style="{StaticResource ResourceKey=toolbarButton}" 
                                               Width="22" >
                    			<Image Source="UIRes/iconUndo.png" Margin="0"/>
                    		</Button>
                    		<Path Data="M150,2 L150,22" Margin="0,0.75,0,0.25" 
                    		        Stretch="Fill" Width="1" Stroke="#FFB8B8B8"/>
                    		<Button Margin="2,0" 
                                 Style="{StaticResource ResourceKey=toolbarButton}" 
                                 Width="22">
                    			<Image Source="UIRes/iconRedo.png"/>
                    		</Button>
                    	</StackPanel>
                    </Border>
                </StackPanel>
 
                <StackPanel VerticalAlignment="Center">
                    <Border x:Name="imgBorder3"  BorderBrush="Wheat" 
                             BorderThickness="1" Height="128" 
                             Margin="20,10" MouseUp="Border_MouseClick">
                        <Image Source="UIRes\image3.jpg"/>
                    </Border>
                    <Border x:Name="imgToolbar3" BorderThickness="1" 
                             BorderBrush="Black" CornerRadius="1" Width="102" 
                             Height="24" d:LayoutOverrides="Width, 
                             Height" Visibility="Hidden">
                    	<Border.Effect>
                    		<DropShadowEffect BlurRadius="3" ShadowDepth="2"/>
                    	</Border.Effect>
                    	<Border.Background>
                    		<ImageBrush ImageSource="UIRes/toolbar.png"/>
                    	</Border.Background>
                    	<StackPanel Width="102" Height="22" 
                    	           Orientation="Horizontal" 
                    	           HorizontalAlignment="Center" 
                    	           VerticalAlignment="Center">
                    		<Button Style="{StaticResource ResourceKey=toolbarButton}" 
                                                Margin="2,0">
                    			<Image Source="UIRes\iconStar.png"/>
                    		</Button>
                    		<Path Data="M150,2 L150,22" Margin="0,0.75,0,0.25" 
                    		       Stretch="Fill" 
                    		       Width="1" Stroke="#FFB8B8B8"/>
                    		<Button Margin="2,0" 
                                 Style="{StaticResource ResourceKey=toolbarButton}" 
                                 Width="22" >
                    			<Image Source="UIRes/iconTag.png"/>
                    		</Button>
                    		<Path Data="M150,2 L150,22" Margin="0,0.75,0,0.25" 
                    		       Stretch="Fill" Width="1" Stroke="#FFB8B8B8"/>
                    		<Button Margin="2,0" 
                                 Style="{StaticResource ResourceKey=toolbarButton}" 
                                 Width="22" >
                    			<Image Source="UIRes/iconUndo.png" Margin="0"/>
                    		</Button>
                    		<Path Data="M150,2 L150,22" Margin="0,0.75,0,0.25" 
                    		          Stretch="Fill" 
                    		          Width="1" Stroke="#FFB8B8B8"/>
                    		<Button Margin="2,0" 
                                 Style="{StaticResource ResourceKey=toolbarButton}" 
                                 Width="22">
                    			<Image Source="UIRes/iconRedo.png"/>
                    		</Button>
                    	</StackPanel>
                    </Border>
                </StackPanel>
            </StackPanel>
            
        </StackPanel>
        <Frame x:Name="EditFrame"  Content="Frame" 
          Margin="6,29,6,16" Visibility="Hidden" 
          NavigationUIVisibility="Hidden" />
 
    </Grid>
</Window>

Key Features

Through screenshots, here I will describe the key features of the app.

Main UI

Image 1

UI looks like this when closing the left and right dock panels.

Image 2

EXIF Info

Image 3

Tuning Control

Tuning control helps users to change brightness, contrast, sharpness, etc. using slider.

Image 4

Resize and Crop

The user has two options to resize the image: percentage wise and pixel wise. Crop can be done manually or according to an aspect ratio.

Image 5

Add Frame

Some predefined frames which can be added in a picture.

Image 6

Add Effects

Currently, twelve effects are available: sketch, oilify, nightvision, cartoon, photocopy, vignating, softglow, simple makeup, poster, canvas, oldphoto. Just touch any of the effects and get the result on the original image.

Image 7

Lens Correction and Red Eye Reduction

Image 8

Recently used operations are shown on the leftside.

Web Share

After completing all the work, to share the image, just select any social site, provide the username and password and press Login. The image will be uploaded to your profile.

Image 9

2. Code Design

All types of modules are handled by their own handler like effect handler handles effect request. So it does not interrupt others, we can add more effects as we need. I also made a DLL of effects to increase usablity.

It looks odd if I copy and paste all code in here. I put some code blocks here to understand the design and code flow. Here is the request handler code for adding an effect.

C#
private void Effect_Button_Click(object sender, RoutedEventArgs e)
{
    Button b = (Button)sender;
    ImageEffects effect = new ImageEffects(ref m_unmanagedImg);
    AF.UnmanagedImage newImg = null;
    //string s = (string)b.Content; // comment by 
    string s = (string)b.Name; // 

    switch(s)
    {
        case "ButtonSketch":
            newImg = effect.ApplyEffect(EffectID.Sketch);
            break;
        case "ButtonPoster":
            newImg = effect.ApplyEffect(EffectID.Poster);
            break;
        case "ButtonNightVision":
            newImg = effect.ApplyEffect(EffectID.NightVision);
            break;
        case "ButtonCartoon":
            newImg = effect.ApplyEffect(EffectID.Cartoon);
            break;
        case "ButtonPhotocopy":
            newImg = effect.ApplyEffect(EffectID.Photocopy);
            break;
        case "ButtonVignetting":
            newImg = effect.ApplyEffect(EffectID.Vignetting);
            break;
        case "ButtonMosaic":
            newImg = effect.ApplyEffect(EffectID.Mosaic);
            break;
        case "ButtonSoftGlow":
            newImg = effect.ApplyEffect(EffectID.SoftGlow);
            break;
        case "ButtonOldImage":
            newImg = effect.ApplyEffect(EffectID.OldImage);
            break;
        case "ButtonOilify":
            newImg = effect.ApplyEffect(EffectID.Oilify);
            break;
        case "ButtonCanvas":
            newImg = effect.ApplyEffect(EffectID.Canvas);
            break;
        case "ButtonEdgeGlow":
            newImg = effect.ApplyEffect(EffectID.EdgeGlow);
            break;
        case "ButtonEmboss":
            newImg = effect.ApplyEffect(EffectID.Emboss);
            break;
        case "ButtonSimpleMakeup":
            newImg = effect.ApplyEffect(EffectID.SimpleMakeup);
            break;
        default:
            break;
    }

    DrawThumb(newImg);
    ShowBitmap(newImg);
    UpdateHistogram(newImg);
}

Now the ImageEffects class code which perform activities through a DLL call. Pass the input image data, reference the output image data and sometimes some parameters. The final effect is obtained in the output image data and displayed in the UI.

C#
using System;
using System.Runtime.InteropServices;
 
namespace WPFGui
{
    using AF = AForge.Imaging;
    using GDI = System.Drawing; 
 
    public enum EffectID
    {
        Sketch,
        Poster,
        NightVision,
        Cartoon,
        Photocopy,
        Vignetting,
        Mosaic,
        SoftGlow,
        OldImage,
        Oilify,
        Canvas,
        EdgeGlow,
        Emboss,
        SimpleMakeup 
    }
 
    unsafe class ImageEffects : IDisposable
    {
    #region EffectDLLImport
        protected const string dllPath = "Effects.dll";
        [DllImport(dllPath, CallingConvention=CallingConvention.Cdecl)]
        unsafe public static extern Int32 SketchImage
        (ImgInfo* imageIn, ImgInfo* imageOut, float* parameter, int ParamNo);
        [DllImport(dllPath, CallingConvention=CallingConvention.Cdecl)]
        unsafe public static extern Int32 ApplyEffectEmbos
        (ImgInfo* imageIn, ImgInfo* imageOut, float* parameter, int ParamNo);
        [DllImport(dllPath, CallingConvention=CallingConvention.Cdecl)]
        unsafe public static extern Int32 ApplyOilify
        (ImgInfo* imageIn, ImgInfo* imageOut, float* parameter, int ParamNo);
        [DllImport(dllPath, CallingConvention=CallingConvention.Cdecl)]
        unsafe public static extern Int32 OldimageEffect
        (ImgInfo* imageIn, ImgInfo* imageOut, float* parameter, int ParamNo);
        [DllImport(dllPath, CallingConvention=CallingConvention.Cdecl)]
        unsafe public static extern Int32 PhotocopyFilter
        (ImgInfo* imageIn, ImgInfo* imageOut, float* parameter, int ParamNo);
        [DllImport(dllPath, CallingConvention=CallingConvention.Cdecl)]
        unsafe public static extern Int32 ApplyCanvas
        (ImgInfo* imageIn, ImgInfo* imageOut, float* parameter, int ParamNo);
        [DllImport(dllPath, CallingConvention=CallingConvention.Cdecl)]
        unsafe public static extern Int32 NightVision2(ImgInfo* RGBarray);
        [DllImport(dllPath, CallingConvention=CallingConvention.Cdecl)]
        unsafe public static extern Int32 NightVision
        (ImgInfo* imageIn, ImgInfo* imageOut, float* parameter, int ParamNo);
        [DllImport(dllPath, CallingConvention=CallingConvention.Cdecl)]
        unsafe public static extern Int32 Posterize
        (ImgInfo* imageIn, ImgInfo* imageOut, float* parameter, int ParamNo);
        [DllImport(dllPath, CallingConvention=CallingConvention.Cdecl)]
        unsafe public static extern Int32 VignettingFilter
        (ImgInfo* imageIn, ImgInfo* imageOut, float* parameter, int ParamNo);
        [DllImport(dllPath, CallingConvention=CallingConvention.Cdecl)]
        unsafe public static extern Int32 Mosaic
        (ImgInfo* imageIn, ImgInfo* imageOut, float* parameter, int ParamNo);
        [DllImport(dllPath, CallingConvention=CallingConvention.Cdecl)]
        unsafe public static extern Int32 SimpleMakeUp
        (ImgInfo* imageIn, ImgInfo* imageOut, float* parameter, int ParamNo);
        [DllImport(dllPath, CallingConvention=CallingConvention.Cdecl)]
        unsafe public static extern Int32 SoftGlowFilter
        (ImgInfo* imageIn, ImgInfo* imageOut, float* parameter, int ParamNo);
        [DllImport(dllPath, CallingConvention=CallingConvention.Cdecl)]
        unsafe public static extern Int32 CartoonFilter
        (ImgInfo* imageIn, ImgInfo* imageOut, float* parameter, int ParamNo);
        [DllImport(dllPath, CallingConvention=CallingConvention.Cdecl)]
        unsafe public static extern Int32 EdgeGlow
        (ImgInfo* imageIn, ImgInfo* imageOut, float* parameter, int ParamNo);
    #endregion
 
    #region Necessary Structures (Unsafe)
        [StructLayout(LayoutKind.Sequential)]
        unsafe public struct RGBQuad
        {
            public byte B;
            public byte G;
            public byte R;
        }
 
        [StructLayout(LayoutKind.Sequential)]
        unsafe public struct ImgInfo
        {
            public RGBQuad** rgb;
            public byte** gray;
            public int height;
            public int width;
            public int bitdepth;
        }
        #endregion
 
    #region DATA MEMBERS
        public unsafe RGBQuad** rgbInput;
        public unsafe RGBQuad** rgbOutput;
 
        public unsafe ImgInfo* nativeInputBitmap;
        public unsafe ImgInfo* nativeOutputBitmap;
 
        unsafe byte* inputStream;
        unsafe byte* effectOutput;
 
        readonly AF.UnmanagedImage m_inputImage;
        AF.UnmanagedImage m_outputImage;
    #endregion
 
        unsafe public float* param;
 
        public ImageEffects(ref AF.UnmanagedImage inputBitmap)
        {
            this.m_inputImage = inputBitmap;
 
            m_outputImage = m_inputImage.Clone();
 
            byte* ptr = (byte*)m_inputImage.ImageData;
            int stride = m_inputImage.Stride;
            int numBytes = stride * m_inputImage.Height;
 
            inputStream = ptr;
            rgbInput = (RGBQuad**)Marshal.AllocHGlobal(sizeof(RGBQuad*) * inputBitmap.Height);
 
            //Output image to be disposed
            rgbOutput = (RGBQuad**)Marshal.AllocHGlobal(sizeof(RGBQuad*) * inputBitmap.Height);
 
            effectOutput = (byte*)m_outputImage.ImageData;
 
            //int nextPtr = inputBitmap.Width * 3 + padding;
            int nextPtr = stride;
            for (int i = 0; i < inputBitmap.Height; i++)
            {
                *(rgbInput + i) = (RGBQuad*)inputStream;
                inputStream += nextPtr;
 
                *(rgbOutput + i) = (RGBQuad*)effectOutput;
                effectOutput += nextPtr;
            }
            inputStream = ptr;
 
            nativeInputBitmap = (ImgInfo*)Marshal.AllocHGlobal(sizeof(ImgInfo));
            nativeOutputBitmap = (ImgInfo*)Marshal.AllocHGlobal(sizeof(ImgInfo));
 
            nativeInputBitmap->width = nativeOutputBitmap->width = inputBitmap.Width;
            nativeInputBitmap->height = nativeOutputBitmap->height = inputBitmap.Height;
            nativeInputBitmap->bitdepth = nativeOutputBitmap->bitdepth = 24;
 
            nativeInputBitmap->rgb = rgbInput;
            nativeOutputBitmap->rgb = rgbOutput;
            nativeInputBitmap->gray = null;
            nativeOutputBitmap->gray = null;
        }
 
        ~ImageEffects()
        {
            Dispose();
        }
 
        public void Dispose()
        {
            if (rgbInput != null)
            {
                Marshal.FreeHGlobal((IntPtr)rgbInput);
                rgbInput = null;
            }
            if (rgbOutput != null)
            {
                Marshal.FreeHGlobal((IntPtr)rgbOutput);
                rgbOutput = null;
            }
            //if (effectOutput != null)
            //{
            //    Marshal.FreeHGlobal((IntPtr)effectOutput);
            //    effectOutput = null;
            //}

            if (nativeInputBitmap != null)
            {
                Marshal.FreeHGlobal((IntPtr)nativeInputBitmap);
                nativeInputBitmap = null;
            }
 
            if (nativeOutputBitmap != null)
            {
                Marshal.FreeHGlobal((IntPtr)nativeOutputBitmap);
                nativeOutputBitmap = null;
            }
 
            inputStream = null;
            effectOutput = null;    
        }
 
#if !DISABLE
        public AF.UnmanagedImage ApplyEffect(EffectID effectId)
        {
            int paramNo;
            switch (effectId)
            {
                case EffectID.Sketch:
                    {
                        //--------- SKETCH IMAGE EFFECT _------------------------------
                        paramNo = 1;
                        param = (float*)Marshal.AllocHGlobal(sizeof(float) * (paramNo));
                        param[0] = 16;
                        SketchImage(nativeInputBitmap, nativeOutputBitmap, param, paramNo);
                        break;
                    }
                case EffectID.Poster:
                    {
                        //--------- Posterize && --------- ---------------------
                        paramNo = 1;
                        param = (float*)Marshal.AllocHGlobal(sizeof(float) * (paramNo));
                        param[0] = 128;
                        Posterize(nativeInputBitmap, nativeOutputBitmap, param, paramNo);
                        break;
                    }
                case EffectID.NightVision:
                    {
                        //NightVision--- image Effect--
                        paramNo = 1;
                        param = (float*)Marshal.AllocHGlobal(sizeof(float) * (paramNo));
                        //param = (float*)Marshal.AllocHGlobal(sizeof(float) * 6);
                        param[0] = 200;
                        //NightVision2(nativeInputBitmap);
                        NightVision(nativeInputBitmap, nativeOutputBitmap, param, 1);
                        break;
                    }
                case EffectID.Cartoon:
                    {
                        // -------------- cartoon ---------  --------------------------------
                        paramNo = 2;
                        param = (float*)Marshal.AllocHGlobal(sizeof(float) * (paramNo));
                        param[0] = 8.0f;
                        param[1] = 0.3f;
                        CartoonFilter(nativeInputBitmap, nativeOutputBitmap, param, paramNo);
                        break;
                    }
                case EffectID.Photocopy:
                    {
                        //---------------  Photocopy----  -------------------------
                        paramNo = 2;
                        param = (float*)Marshal.AllocHGlobal(sizeof(float) * (paramNo));
                        param[0] = 25;
                        param[1] = 0.85f;
                        PhotocopyFilter(nativeInputBitmap, nativeOutputBitmap, param, paramNo);
                        break;
                    }
                case EffectID.Vignetting:
                    {
                        ////---------------  vignetting----   -------------------------
                        paramNo = 1;
                        param = (float*)Marshal.AllocHGlobal(sizeof(float) * (paramNo));
                        param[0] = 1.2f;
                        VignettingFilter(nativeInputBitmap, nativeOutputBitmap, param, paramNo);
                        break;
                    }
                case EffectID.Mosaic:
                    {
                        ////---------------  Mosaic---   -------------------------
                        paramNo = 3;
                        param = (float*)Marshal.AllocHGlobal(sizeof(float) * (paramNo));
                        param[0] = 15;
                        param[1] = 200;  // range 0.0 to 1.0, increment 0.2
                        param[2] = 4;
                        Mosaic(nativeInputBitmap, nativeOutputBitmap, param, paramNo);
                        break;
                    }
                case EffectID.SoftGlow:
                    {
                        ////--------Softglow ----
                        paramNo = 1;
                        param = (float*)Marshal.AllocHGlobal(sizeof(float) * (paramNo));
                        param[0] = 5;
                        SoftGlowFilter(nativeInputBitmap, nativeOutputBitmap, param, paramNo);
                        break;
                    }
                case EffectID.OldImage:
                    {
                        ////------------ OLD image---------------------- ------------
                        paramNo = 1;
                        param = (float*)Marshal.AllocHGlobal(sizeof(float) * (paramNo));
                        param[0] = 0.2f;
                        OldimageEffect(nativeInputBitmap, nativeOutputBitmap, param, paramNo);
                        break;
                    }
                case EffectID.Oilify:
                    {
                        paramNo = 2;
                        param = (float*)Marshal.AllocHGlobal(sizeof(float) * (paramNo));
                        param[0] = 10;
                        param[1] = 10;
                        ApplyOilify(nativeInputBitmap, nativeOutputBitmap, param, paramNo);
                        break;
                    }
                case EffectID.Canvas:
                    {
                        paramNo = 3;
                        param = (float*)Marshal.AllocHGlobal(sizeof(float) * (paramNo));
                        param[0] = 2;
                        param[1] = 1;
                        param[2] = 1;
                        ApplyCanvas(nativeInputBitmap, nativeOutputBitmap, param, paramNo);
                        break;
                    }
                case EffectID.EdgeGlow:
                    {
                        ////-----Edgeglow
                        paramNo = 3;
                        param = (float*)Marshal.AllocHGlobal(sizeof(float) * (paramNo));
                        param[0] = 11;
                        param[1] = 11;
                        param[2] = 1;
                        EdgeGlow(nativeInputBitmap, nativeOutputBitmap, param, paramNo);
                        break;
                    }
                case EffectID.Emboss:
                    {
                        ////-----Emboss
                        paramNo = 0;
                        param = (float*)Marshal.AllocHGlobal(sizeof(float) * (paramNo));
                        ApplyEffectEmbos(nativeInputBitmap, nativeOutputBitmap, param, paramNo);
                        break;
                    }
                case EffectID.SimpleMakeup:
                    {
                        paramNo = 2;
                        param = (float*)Marshal.AllocHGlobal(sizeof(float) * (paramNo));
                        param[0] = 4;
                        param[1] = 45;
                        SimpleMakeUp(nativeInputBitmap, nativeOutputBitmap, param, paramNo);
                        break;
                    }
                default:
                    System.Windows.MessageBox.Show("Done Nothing");
                    break;
            }
 
            Marshal.FreeHGlobal((IntPtr)param);
            param = null;
 
            return m_outputImage;
        }
#endif
 
    }
}

Similarly, for adding a frame, use a frame handler:

C#
private void Frame_Button_Click(object sender, RoutedEventArgs e)
{
    string buttonName = (string)((Button)sender).Name;

    string fileName = @"Frames\" + buttonName + ".png";

    AF.UnmanagedImage frameImage = null;
    DisposableGDIBitmap frameBMP = new DisposableGDIBitmap(fileName);
    try
    {
        //New Instance of Unmanaged bitmap
        frameImage = new AF.UnmanagedImage(frameBMP.GetBitmapData);
    }
    catch (Exception ex)
    {
        System.Windows.MessageBox.Show(ex.ToString());
    }

    AF.UnmanagedImage viewImg = this.m_frames.getFramedImage(frameImage, m_unmanagedImg);

    DrawThumb(viewImg);
    ShowBitmap(viewImg);
    UpdateHistogram(viewImg);
}

This class is responsible for adding a frame to an image:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace WPFGui
{
    using AF = AForge.Imaging;
    using GDI = System.Drawing;
 
    class ImageFrame
    { 
        AF.UnmanagedImage resizedFrame;
        AF.UnmanagedImage originalFrame;
        AF.UnmanagedImage resultImage;
        AF.Filters.ResizeBilinear resizeBilinearFilter;
        GDI.Color framePixelColor;
 
        AF.Filters.RotateBilinear rotateBilinearFilter;
 
        private int RED = 240;
        private int GREEN = 240;
        private int BLUE = 240;
        private float frameRatio;
        private float mainImageRatio;
 
        public ImageFrame()
        {
        }
 
        public AF.UnmanagedImage getFramedImage
              (AF.UnmanagedImage frameUnmImg, AF.UnmanagedImage mainImageUnmImg)
        {
            this.resultImage = mainImageUnmImg.Clone();
 
            this.frameRatio = (float)frameUnmImg.Width / (float)frameUnmImg.Height;
            this.mainImageRatio = 
                   (float)this.resultImage.Width / (float)this.resultImage.Height;
 
            if (!((this.frameRatio <= 1.0 && this.mainImageRatio <= 1.0) || 
                  (1.0 <= this.frameRatio && 1.0 <= this.mainImageRatio)))
            {
                this.rotateBilinearFilter = new AF.Filters.RotateBilinear(90, false);
                this.originalFrame = this.rotateBilinearFilter.Apply(frameUnmImg);
            }
            else
            {
                this.originalFrame = frameUnmImg.Clone();
            }
 
            this.resizeBilinearFilter = 
              new AF.Filters.ResizeBilinear(this.resultImage.Width, this.resultImage.Height);
            this.resizedFrame = this.resizeBilinearFilter.Apply(originalFrame);
 
            try
            {
                for (int h = 0; h < this.resultImage.Height; h++)
                {
                    for (int w = 0; w < this.resultImage.Width; w++)
                    {
                        this.framePixelColor = this.resizedFrame.GetPixel(w, h);
                        if (!((0 == this.framePixelColor.A) || (this.framePixelColor.R > 
                            this.RED && this.framePixelColor.G > 
                            this.GREEN && this.framePixelColor.B > this.BLUE)))
                        {
                            this.resultImage.SetPixel(w, h, this.framePixelColor);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                System.Windows.MessageBox.Show(ex.ToString());
            }
            return this.resultImage;
        }
    }
}

The webshare handler handles all types of image upload requests:

C#
private void LoginToWebshare(object sender, RoutedEventArgs e)
{
    string userName = UserNameBox.Text;
   string userPassword =  UserPasswordBox.Password;
    System.Windows.MessageBox.Show(userName);
    Button b = (Button)sender;
    if (m_unmanagedImg == null)
        return;
//	LoginToSocialNetwork(userName,userPassword,networkName);
}

Ultrabook Features Utilized in the Application

Swipe and touch feature for controlling activities, slider, zoom in/out, and image switching.

License

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


Written By
Software Developer Worked in a Research & Development Center
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionFilters.dll ? Pin
francis29105-Jun-13 14:23
francis29105-Jun-13 14:23 
AnswerRe: Filters.dll ? Pin
Briti Sundar5-Jun-13 17:52
Briti Sundar5-Jun-13 17:52 
GeneralRe: Filters.dll ? Pin
francis29105-Jun-13 21:29
francis29105-Jun-13 21:29 
GeneralRe: Filters.dll ? Pin
Briti Sundar6-Jun-13 19:10
Briti Sundar6-Jun-13 19:10 
GeneralRe: Filters.dll ? Pin
francis29106-Jun-13 22:09
francis29106-Jun-13 22:09 
GeneralTHANX Pin
Manoj Benjamin23-May-13 3:48
Manoj Benjamin23-May-13 3:48 
Hi man please upload source code .This will really useful for us .
QuestionGreat work Pin
ridoy7-Oct-12 8:51
professionalridoy7-Oct-12 8:51 
AnswerRe: Great work Pin
Briti Sundar7-Oct-12 17:59
Briti Sundar7-Oct-12 17:59 
QuestionNeed info Pin
Tridip Bhattacharjee7-Oct-12 6:42
professionalTridip Bhattacharjee7-Oct-12 6:42 
AnswerRe: Need info Pin
Briti Sundar7-Oct-12 7:13
Briti Sundar7-Oct-12 7:13 
GeneralMy vote of 5 Pin
sreenivasulu vasu7-Oct-12 6:39
sreenivasulu vasu7-Oct-12 6:39 
GeneralRe: My vote of 5 Pin
Briti Sundar7-Oct-12 7:14
Briti Sundar7-Oct-12 7:14 

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.