Shahul hameed
Shahul hameed

Reputation: 23

Changing color of an image

I m making an windows application using vb.net 2008,in that i want to change color of an image programmatically. For e.g. Change white color to green. Can you please help me. Thanks in advance.

Upvotes: 1

Views: 11153

Answers (2)

Darren S
Darren S

Reputation: 656

Synaps3 offers a good pixel-by-pixel method which works best for fixed palette adjustments, but if you want to just colorize an entire image of many different shades while still preserving those differences, you'll want to create a color matrix that you'll later assign as the "imageattributes" argument for any of the various overloads of DrawImage.

( What is the ImageAttributes variable anyway? It's just a specialized data type that specifies recoloring and gamma information for an image object. )

The color matrix must be a 5 x 5 grid of singles, which can be declared and defined in one go like so:

Private ReadOnly normal_cm As New Drawing.Imaging.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() {0, 0, 0, 0, 1}})

The above color matrix is the "default" color matrix that is applied to everything you do, all colors (and alpha) show up at 100% their original colors and are not modified or rotated in any way. The first single() are the red scaling factors, the next is green's, the next is blue's, the next is the alpha channel's and the last are your translation scaling factors. If you want the white to be green, there are several ways of accomplishing it, but the simplest would be to experiment with the values in the second internal array of singles, like so:

Private ReadOnly green_cm As New Drawing.Imaging.ColorMatrix(New Single()() _
    {New Single() {0.8, 0, 0, 0, 0},  ' reduces red values by 20%
    New Single() {0, 1.2, 0, 0, 0},   ' increases green by 20%
    New Single() {0, 0, 0.8, 0, 0},   ' reduces blue by 20%
    New Single() {0, 0, 0, 1, 0},     ' transparency stays the same
    New Single() {0, 0, 0, 0, 1}})

Once you have your color matrix ready, you'll need a proper image attributes variable:

Private myImgAttr As New Drawing.Imaging.ImageAttributes

I usually decide inside my method which of my color matrices to use via program logic, if you "dim" your variables on the fly, you'll need to .dispose of the ImageAttributes afterwards to avoid a memory leak. I will apply the color matrix to my image attributes variable and then pass image attributes into the DrawImage command like so:

Dim baseImage As Drawing.Image = Drawing.Image.FromFile("base\image\file.png")
Dim gfx As Drawing.Graphics = Drawing.Graphics.FromImage(baseImage )
myImgAttr.SetColorMatrix(green_cm)
gfx.DrawImage(Drawing.Image.FromFile("path\to\file.png"), targetRectangle,
    0, 0, srcImageWidth, srcImageHeight,
    Drawing.GraphicsUnit.Pixel, myImgAttr)

There are a couple other DrawImage overloads that I sometimes use but by and large this one is the most flexible. If you are making a game you can start with your character's body sprite using the first BaseImage, then you can draw a white clothing picture on top to be your team's color that gets colorized green or red or whatever color you like, then you return your baseImage to assign it to your unit or draw it on the map, etc..

Upvotes: 2

Synaps3
Synaps3

Reputation: 1657

Here is the basic idea, you can modify for your needs. Create a button and a pic box named pic. Place this code in the button click event and replace path with an image of your choice. You just need to alter code in the if statements to create thresholds of certain colors. To figure out the RGB values for your thresholds, you can probably use a paint program or online color thing to find the right values for the color range you want.

    Dim x As Integer
    Dim y As Integer
    Dim red As Byte
    Dim green As Byte
    Dim blue As Byte

    Dim img As Bitmap = New Bitmap("D:\dump\raycaster\Debug\pics\redbrick.png")

    For x = 0 To img.Width - 1
        For y = 0 To img.Height - 1
            red = img.GetPixel(x, y).R
            green = img.GetPixel(x, y).G
            blue = img.GetPixel(x, y).B
            If red > 128 Then
                img.SetPixel(x, y, Color.Green)
            End If
            If blue > 200 And green > 200 Then
                img.SetPixel(x, y, Color.Red)
            End If
        Next
    Next

    pic.Image = img

And for specifically changing white to green like you said:

If red > 240 And green > 240 And blue > 240 Then
    img.SetPixel(x, y, Color.Green)
End If

I did 240 because a lot of times you're not going to have a pure white.

Upvotes: 7

Related Questions