Xtreme Visual Basic Talk

Xtreme Visual Basic Talk (http://www.xtremevbtalk.com/)
-   .NET Interface and Graphics (http://www.xtremevbtalk.com/-net-interface-and-graphics/)
-   -   Changing Color of Simple Bitmaps (http://www.xtremevbtalk.com/-net-interface-and-graphics/325857-changing-color-simple-bitmaps.html)

Ninth Wave 04-17-2013 05:00 PM

Changing Color of Simple Bitmaps
If I load a bitmap let's say it has only two colors, white pixels on black pixels.


Dim myBitmap As Bitmap
myBitmap = Bitmap.FromFile("file.bmp")


Could I change the foreground white pixels to another color at runtime?

passel 04-17-2013 06:22 PM

There are a number of ways it could be done.
One way is to use a colorMatrix to adjust the red,green and blue levels when you draw the bitmap to another place, eg. the form, another control, or another bitmap.

This example code uses a colorMatrix to turn the white X into another color set by using three trackbars to adjust the level of Red,Green,Blue (color matrix expects range 0.0 to 1.0)
Assumes you have the picture in the application directory.

Imports System.Drawing.Imaging

Public Class Form1
  Dim myBitmap As New Bitmap("file.bmp")
  Dim redScale As Single = 1.0F
  Dim greenScale As Single = 1.0F
  Dim bluescale As Single = 1.0F

  Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    TrackBar1.Maximum = 255 : TrackBar1.TickFrequency = 16
    TrackBar2.Maximum = 255 : TrackBar2.TickFrequency = 16
    TrackBar3.Maximum = 255 : TrackBar3.TickFrequency = 16
  End Sub

  Private Sub PictureBox1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
    Dim cm As New ColorMatrix
    cm.Matrix00 = redScale
    cm.Matrix11 = greenScale
    cm.Matrix22 = bluescale
    Dim imageAtt As New ImageAttributes()
    imageAtt.SetColorMatrix(cm, ColorMatrixFlag.Default, ColorAdjustType.Bitmap)
    Dim iWidth As Integer = myBitmap.Width
    Dim iHeight As Integer = myBitmap.Height

      New Rectangle(0, 0, iWidth, iHeight),
      0.0F, 0.0F,
      iWidth, iHeight, GraphicsUnit.Pixel, imageAtt)
  End Sub

  Private Sub TrackBar1_Scroll(sender As System.Object, e As System.EventArgs) Handles TrackBar1.Scroll
    redScale = TrackBar1.Value / 255.0F
  End Sub

  Private Sub TrackBar2_Scroll(sender As System.Object, e As System.EventArgs) Handles TrackBar2.Scroll
    greenScale = TrackBar2.Value / 255.0F
  End Sub

  Private Sub TrackBar3_Scroll(sender As System.Object, e As System.EventArgs) Handles TrackBar3.Scroll
    bluescale = TrackBar3.Value / 255.0F
  End Sub

End Class

CodeCruncher 04-21-2013 09:42 PM

You never cease to amaze me passel... I had to add this to find the bmp


        Dim ofdFile As New OpenFileDialog With {.Filter = "Bitmap |*.bmp"}
        If (ofdFile.ShowDialog() = Windows.Forms.DialogResult.OK) Then
            myBitmap = New Bitmap(ofdFile.FileName)
        End If

But I can't see where you are specifying it is the "X" in the bmp you want to work on. Is there a specific line of code you can point out?

passel 04-22-2013 10:53 AM

The color matrix is technically modifying the whole bitmap, but since the bitmap is made up of Black and White, you only see the White X being affected.

What the color matrix is doing scaling the red, green and blue portions of all the pixels to a value between 0 and 100 percent of themselves.
Since Black has Red, Green and Blue componenets with values of zero, any percentage of 0 is still 0.
Since White is made up of 100% Red, Green and Blue, then any percentage given to any of those three values will reduce that component by that amount directly affecting the result of the white color.

If you were to use this example with a bitmap that wasn't strickly Black and White, then the results would be quite different, but generally predictable. The code can only reduce a given color's components, so if you reduced the Red component by 50%, pixels that were pure red would be darkened. Colors with Red in them, such as yellow, would shift to a color with less red, towards brown. Colors with no red in them, such as Cyan or Green, would not be affected.

CodeCruncher 04-22-2013 07:15 PM

Ok thanks that makes a lot of sense when you have someone who understands colour explain it :)

I'm afraid my solution would have been much more primitive, with an array of different coloured bitmaps. Yours lacks that sledgehammer approach ;)

starmanMike 01-09-2018 12:10 PM

Hi Passel,
I also want to do something like this - if anything, simpler and with no user input since the code does everything.
Procedure is always the same - convert 'black pixels on white background' to 'red pixels on black background' . New to vb.net and even newer to all the graphics tools such as colo(u)r matrices, so apologies for ignorance! (Such as... does the 'bitmap' have to be an actual .bmp?) I suspect not, but you never know. Mine are likely to be .gif or .png images.

passel 02-13-2018 10:35 PM

I guess for that you would want to use a colorMap array.
You would load the image in a bitmap object (shouldn't matter if you loaded it from .gif or .png file).
You would then create a bitmap the same size (easiest would be to clone the bitmap loaded), then setup a colorMap array to convert the two src colors into the two destination colors, and draw the source image into the cloned image (or vice versa depending on which image you want to keep) using the colorMap table to remap the colors.

Here's a quick example of the color mapping.
Add a picturebox to a form and size it however big you want, upto 1/2 the size of the form. Copy it and paste to create a second picturebox the same size and position it where you want.

Paste in the following code.
When you run the program you will see the first picturebox has a white background. If you drag on it you will draw black lines on the box. (Technically you're drawing on a defined bitmap, but that bitmap was "loaded" into the image propery of the picturebox.
The image property of the picturebox and the bitmap variable both reference the same bitmap so you can draw in the bitmap, then invalidate or refresh the picturebox and it will refresh the screen area from that referenced bitmap).

Calling the transformImage sub draws the source bitmap into the destination bitmap, remapping the colors as specified in the colormap table (i.e. array). Invalidating the second picturebox updates the screen area of the picturebox with that bitmap since the .Image property of that picturebox was set to reference the destination bitmap.

Imports System.Drawing.Imaging

Public Class Form1
    Dim srcBitmap As Bitmap
    Dim redBitmap As Bitmap

    Private Sub Form1_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown
        With PictureBox1.ClientSize
            srcBitmap = New Bitmap(.Width, .Height)
        End With
        redBitmap = srcBitmap.Clone

        PictureBox1.Image = srcBitmap  'Set the .Image property to reference the srcBitmap
        PictureBox2.Image = redBitmap  'Set the .Image property to reference the redBitmap
        Using g As Graphics = Graphics.FromImage(srcBitmap) 'clear the src bitmap to white
        End Using
        PictureBox1.Refresh()  'refresh the picturebox so it updates the screen area from the bitmap
    End Sub

    Private Sub TransformImage()
        Dim colorMapping(1) As ColorMap
        Dim imageAtt As New ImageAttributes()

        colorMapping(0) = New ColorMap              'Map Black to Red
        colorMapping(0).OldColor = Color.Black
        colorMapping(0).NewColor = Color.Red

        colorMapping(1) = New ColorMap              'Map White to Black
        colorMapping(1).OldColor = Color.White
        colorMapping(1).NewColor = Color.Black

        Dim iWidth As Integer = srcBitmap.Width
        Dim iHeight As Integer = srcBitmap.Height
        Using g As Graphics = Graphics.FromImage(redBitmap)  'Draw the srcBitmap to the redBitmap (remapping the colors)
              New Rectangle(0, 0, iWidth, iHeight),
              0.0F, 0.0F,
              iWidth, iHeight, GraphicsUnit.Pixel, imageAtt)
        End Using
    End Sub

    Private Sub PictureBox1_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
        Static lpos As Point

        If e.Button = Windows.Forms.MouseButtons.Left Then
            Using g As Graphics = Graphics.FromImage(srcBitmap)  'Draw on the source bitmapa line on the bitmap from last position to current position
                g.DrawLine(Pens.Black, lpos, e.Location)          'Draw a line on the bitmap from last position to current position
                TransformImage()                                  'Draw the srcBitmap to the redBitmap with remapped colors
                PictureBox1.Invalidate()                          'Have Picturebox1 update its screen area from the srcBitmap
                PictureBox2.Invalidate()                          'Have Picturebox2 update its screen area from the redBitmap
            End Using
        End If
        lpos = e.Location
    End Sub
End Class

All times are GMT -6. The time now is 04:57 AM.

Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Search Engine Optimisation provided by DragonByte SEO v2.0.15 (Lite) - vBulletin Mods & Addons Copyright © 2018 DragonByte Technologies Ltd.
All site content is protected by the Digital Millenium Act of 1998. Copyright©2001-2011 MAS Media Inc. and Extreme Visual Basic Forum. All rights reserved.
You may not copy or reproduce any portion of this site without written consent.