Tinting and Gray Scaling Pictures with Visual Studio 2012

Introduction

I love photos. I love taking photos, even though I am by no means a professional or even an amateur. I love taking pictures spontaneously, especially about my wife and daughter. Funny thing is: I hate being in a photograph!

I also love PhotoShop with all its features to improve the quality of pictures.  I love the effect of a black and white photo! This got me thinking, wouldn't it be nice to make a small tool for my personal use, to make my pictures tinted or gray scaled. This is what we'll do today. It is not too complicated, so we can take it easy ( for a change ).

Design

Our design is quite simple. All you will need on your form is the following objects:

  • 6 Buttons
    1. Red
    2. Green
    3. Blue
    4. Choose A Color
    5. Gray
    6. Save
  • 2 PictureBoxes
    1. Source PictureBox
    2. Destination PictureBox
  • 1 SaveFileDialog
  • 1 ColorDialog

You could name all the objects anything you like.

Coding

In all honesty, I was pleasantly surprised about the small amount of code that was needed in this project. I think it comes down to using the right tools for the job. In this case: the ColorMatrix object

As usual, let us start with the Namespaces:

VB.NET

Imports System.Drawing.Imaging ' Advanced Image Functionalities
Imports System.IO 'File Operations

C#

using System.Drawing.Imaging; //Advanced Image Functionalities
using System.IO; //File Operations

Add our Tint function:

VB.NET

    Private Function Tint(ByVal bmpSource As Bitmap, ByVal clrScaleColor As Color, ByVal sngScaleDepth As Single) As Bitmap

        Dim bmpTemp As New Bitmap(bmpSource.Width, bmpSource.Height) 'Create Temporary Bitmap To Work With

        Dim iaImageProps As New ImageAttributes 'Contains information about how bitmap and metafile colors are manipulated during rendering. 

        Dim cmNewColors As ColorMatrix 'Defines a 5 x 5 matrix that contains the coordinates for the RGBAW space

        cmNewColors = New ColorMatrix(New Single()() _
            {New Single() {1, 0, 0, 0, 0}, _
             New Single() {0, 1, 0, 0, 0}, _
             New Single() {0, 0, 1, 0, 0}, _
             New Single() {0, 0, 0, 1, 0}, _
             New Single() {clrScaleColor.R / 255 * sngScaleDepth, clrScaleColor.G / 255 * sngScaleDepth, clrScaleColor.B / 255 * sngScaleDepth, 0, 1}})

        iaImageProps.SetColorMatrix(cmNewColors) 'Apply Matrix

        Dim grpGraphics As Graphics = Graphics.FromImage(bmpTemp) 'Create Graphics Object and Draw Bitmap Onto Graphics Object

        grpGraphics.DrawImage(bmpSource, New Rectangle(0, 0, bmpSource.Width, bmpSource.Height), 0, 0, bmpSource.Width, bmpSource.Height, GraphicsUnit.Pixel, iaImageProps)

        Return bmpTemp

    End Function

C#

    private Bitmap Tint(Bitmap bmpSource, Color clrScaleColor, float sngScaleDepth)
    {

        Bitmap bmpTemp = new Bitmap(bmpSource.Width, bmpSource.Height); //Create Temporary Bitmap To Work With

        ImageAttributes iaImageProps = new ImageAttributes(); //Contains information about how bitmap and metafile colors are manipulated during rendering. 

        ColorMatrix cmNewColors = default(ColorMatrix); //Defines a 5 x 5 matrix that contains the coordinates for the RGBAW space
	    cmNewColors = new ColorMatrix(new float[][] {
		    new float[] {
			    1,
			    0,
			    0,
			    0,
			    0
		    },
		    new float[] {
			    0,
			    1,
			    0,
			    0,
			    0
		    },
		    new float[] {
			    0,
			    0,
			    1,
			    0,
			    0
		    },
		    new float[] {
			    0,
			    0,
			    0,
		    	1,
		    	0
		    },
		    new float[] {
			    clrScaleColor.R / 255 * sngScaleDepth,
			    clrScaleColor.G / 255 * sngScaleDepth,
			    clrScaleColor.B / 255 * sngScaleDepth,
			    0,
			    1
		    }
	    });

	    iaImageProps.SetColorMatrix(cmNewColors); //Apply Matrix

        Graphics grpGraphics = Graphics.FromImage(bmpTemp); //Create Graphics Object and Draw Bitmap Onto Graphics Object

	    grpGraphics.DrawImage(bmpSource, new Rectangle(0, 0, bmpSource.Width, bmpSource.Height), 0, 0, bmpSource.Width, bmpSource.Height, GraphicsUnit.Pixel, iaImageProps);
	    
        return bmpTemp;

    }

This function makes use of the ColorMatrix class to calculate how the colors in the picture should change. We get all the associated RGB ( Red, Green, Blue ) values from the picture, divide it by 255 ( there are only 256 shades of red or green or blue in the RGB Color model. Then, we multiply it with the depth that we want. Any value between .25 and .75 will give you the best results.

Create a Bitmap Variable and add the following line into your Form_Load event:

VB.NET

    Dim bmpNewPic As Bitmap 'Source Bitmap

    Private Sub frmTint_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        bmpNewPic = New Bitmap(picSource.Image) ' Source Picture To Work With

    End Sub

C#

    Bitmap bmpNewPic; //Source Bitmap

        private void frmTint_Load(object sender, EventArgs e)
        {

             bmpNewPic = new Bitmap(picSource.Image); //Source Picture To Work With

        }

This creates a bitmap object to apply the tint to.

Add the following for the Red, Green and Blue buttons:

VB.NET

    Private Sub btnRed_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRed.Click

        picDest.Image = Tint(bmpNewPic, Color.Red, 0.3) 'Red

    End Sub

    Private Sub btnGreen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGreen.Click

        picDest.Image = Tint(bmpNewPic, Color.Green, 0.3) 'Green

    End Sub

    Private Sub btnBlue_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBlue.Click

        picDest.Image = Tint(bmpNewPic, Color.Blue, 0.3) 'Blue

    End Sub

C#

    private void btnRed_Click(System.Object sender, System.EventArgs e)
    {

        picDest.Image = Tint(bmpNewPic, Color.Red, 0.3f); //Red

    }

    private void btnGreen_Click(System.Object sender, System.EventArgs e)
    {

    	picDest.Image = Tint(bmpNewPic, Color.Green, 0.3f); //Green

    }

    private void btnBlue_Click(System.Object sender, System.EventArgs e)
    {

	    picDest.Image = Tint(bmpNewPic, Color.Blue, 0.3f); //Blue

    }

We call the Tint function for each of the associated colors.

Add the following code for the Choose Color button:

VB.NET

    Private Sub btnChoose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnChoose.Click

        If cdTint.ShowDialog = DialogResult.OK Then 'Show Color Dialog

            Dim clrSel As Color
            clrSel = cdTint.Color 'Store Selected Color

            picDest.Image = Tint(bmpNewPic, clrSel, 0.3) 'Apply Tint

        End If

    End Sub

C#

    private void btnChoose_Click(object sender, EventArgs e)
    {
        DialogResult drColors = cdTint.ShowDialog(); //Show Color Dialog
        
        if (drColors == DialogResult.OK)
        {
        
            Color clrSel = cdTint.Color; //Store Selected Color
        
            picDest.Image = Tint(bmpNewPic, clrSel, 0.3f); //Apply Tint

        }
    }

Same logic, we just allow the user to select a tint color.

Add the following code for the Gray Scale button:

VB.NET

    Private Sub btnGray_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGray.Click

        Dim intX As Integer 'X Counter
        Dim intY As Integer 'Y Counter

        Dim clrOld As Integer 'Previous Color

        For intX = 0 To bmpNewPic.Width - 1 'Loop Horizontally

            For intY = 0 To bmpNewPic.Height - 1 'Loop Vertically

                'Get Existing Color At Each Pixel Location and Divide By Scale Depth
                'Any Range Between .25 and .75 Will Give optimal Results
                clrOld = (CInt(bmpNewPic.GetPixel(intX, intY).R) + _
                       bmpNewPic.GetPixel(intX, intY).G + _
                       bmpNewPic.GetPixel(intX, intY).B) \ 3

                bmpNewPic.SetPixel(intX, intY, Color.FromArgb(clrOld, clrOld, clrOld)) 'Apply Tint

            Next intY

        Next intX

        picDest.Image = bmpNewPic 'Set New Picture

    End Sub

C#

    private void btnGray_Click(System.Object sender, System.EventArgs e)
    {

	    int intX = 0; //X Counter
	    int intY = 0; //Y Counter

	    int clrOld = 0; //Previous Color

        for (intX = 0; intX <= bmpNewPic.Width - 1; intX++) //Loop Horizontally
        {
            for (intY = 0; intY <= bmpNewPic.Height - 1; intY++) //Loop Vertically
            {
                 //Get Existing Color At Each Pixel Location and Divide By Scale Depth
                //Any Range Between .25 and .75 Will Give optimal Results
                clrOld = (Convert.ToInt32(bmpNewPic.GetPixel(intX, intY).R) + bmpNewPic.GetPixel(intX, intY).G + bmpNewPic.GetPixel(intX, intY).B) / 3;

                bmpNewPic.SetPixel(intX, intY, Color.FromArgb(clrOld, clrOld, clrOld)); //Apply Tint
		    }
	     }

        picDest.Image = bmpNewPic; //Set New Picture
      
    }

A more complicated way of tinting. We get each pixel's color and replace it. This is more time consuming and processor intensive.

All that is left is to save our tinted picture:

VB.NET

    Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click

        If sfdTint.ShowDialog = DialogResult.OK Then

            picDest.Image.Save(sfdTint.FileName) 'Save

        End If

    End Sub

C#

        private void btnSave_Click(object sender, EventArgs e)
        {
            DialogResult drSave = sfdTint.ShowDialog();

           if(drSave == DialogResult.OK)
           {

               picDest.Image.Save(sfdTint.FileName); //Save

           }
        
        }

Conclusion

This wasn't so complicated now, was it? I am attaching the working projects with this article. Thanks for reading! Until next time, cheers!



Related Articles

Downloads

Comments

  • Short piece of content exposes the unquestionable info about chanel and in what way it could actually harm customers.

    Posted by emeseesip on 05/07/2013 08:32pm

    Among The Most Comprehensive nike Manual You Ever Read Or Your Cash Back [url=http://www.guccija.biz/]グッチ バッグ[/url] Whoa, astounding item. People got to check out adidas instantly when it's still available to buy ! ! [url=http://www.guccija.biz/]グッチ キーケース[/url] adidas helps all of us by simply including several exclusive functions and options. Its a unvaluable item for any supporter of nike. [url=http://www.guccija.biz/]グッチ ショルダーバッグ[/url] Independent piece of writing unveil Four great new things over nike that none is bringing up. [url=http://www.chanelja.biz/]シャネル 財布[/url] This is why no one is chatting about gucci and therefore exactly what one ought to accomplish this afternoon. [url=http://www.chanelja.biz/]シャネル チェーンウォレット[/url] Hot questions on gucci replied to and as a result the reasons you will need study each and every concept within this guide. [url=http://www.chanelja.biz/]財布 chanel[/url] The basic fundamentals of the nike that you're able to make full use of commencing today.[url=http://www.nikeja.biz/]nike[/url] Information about how to understand all kinds of things there is to find regarding nike in five easy steps.

    Reply
  • Media Consultant

    Posted by Herbert Dupree, II on 04/25/2013 05:05am

    I am new to Visual Basic programming. Visual Studio 2012 Premium SP2 on DreamSpark Pentium Dual-Core 2.3 Ghz, 8 GB/640, Windows 8 I downloaded the code and opened it in Visual Studio to observe and view. I changed the default picture and added one of my own. At runtime, the picture output after the tint properly, and at saving, I could not find a save as file type nor a default name. It saves as a file, meaning either a .jpg extension to filename or file association with a .jpg viewer. I know there is a way to make it automatic, searched web for possible syntax, but could not get it to work. Please assist and thank you.

    Reply
  • Media Consultant

    Posted by Herbert Dupree, II on 04/25/2013 04:58am

    I am new to VB programming and downloaded the code samples in this article. Running VS 2012 Premium (DS) on Windows 8, 8 GB, Pentium DC 2.3. I switched out a picture of my own, but have tried to get two issues covered. One, the picture is 640 x 480 and will not center in the picture box on the preview portion, but will work on output with tint. Two, when I save it, it does not put a default file name nor a save as file type. When I give a name and save, it saves it as a file, with no idea what to open it with unless I either add a .jpeg extension to the filename or associate this file with a picture viewer. There is something missing about the code to make this happen. Please help. Thank you.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • VMware vCloud® Government Service provided by Carpathia® is an enterprise-class hybrid cloud service that delivers the tried and tested VMware capabilities widely used by government organizations today, with the added security and compliance assurance of FedRAMP authorization. The hybrid cloud is becoming more and more prevalent – in fact, nearly three-fourths of large enterprises expect to have hybrid deployments by 2015, according to a recent Gartner analyst report. Learn about the benefits of …

Most Popular Programming Stories

More for Developers

RSS Feeds