|
|
Title | Reduce the number of colors in a Bitmap and remap them to make interesting effects in Visual Basic .NET |
Description | This example shows how to reduce the number of colors in a Bitmap and remap them to make interesting effects in Visual Basic .NET. |
Keywords | graphics, algorithms, colors, color depth, reduce color depth, Warhol, Andy Warhol, example, example program, Windows Forms programming, Visual Basic .NET, VB.NET |
Categories | Algorithms, Graphics, Graphics |
|
|
Andy Warhol was an American painter, print maker, and file maker. One particularly striking kind of image he produced featured a famous person such as John Lennon or Marilyn Monroe painted in very few colors. Sometimes several images of the same person painted with different color schemes were displayed together.
This program achieves a vaguely similar result by mapping each pixel in an image to the closest target pixel and then changing its value to a corresponding result color. For example, in the picture shown here pixels that are closer to red than to the other target colors are mapped to yellow in the result.
The following code shows how the program "warholizes" an image.
|
|
' Warholize.
Private Sub btnGo_Click(ByVal sender As System.Object, ByVal _
e As System.EventArgs) Handles btnGo.Click
picOutput.Image = Nothing
picOutput.Refresh()
' Get the input and output color data.
Dim in_boxes() As PictureBox = {picFromColor0, _
picFromColor1, picFromColor2, picFromColor3, _
picFromColor4}
Dim out_boxes() As PictureBox = {picToColor0, _
picToColor1, picToColor2, picToColor3, picToColor4}
Dim in_r(0 To in_boxes.Length - 1) As Integer
Dim in_g(0 To in_boxes.Length - 1) As Integer
Dim in_b(0 To in_boxes.Length - 1) As Integer
Dim out_r(0 To in_boxes.Length - 1) As Byte
Dim out_g(0 To in_boxes.Length - 1) As Byte
Dim out_b(0 To in_boxes.Length - 1) As Byte
For i As Integer = 0 To in_boxes.Length - 1
in_r(i) = in_boxes(i).BackColor.R
in_g(i) = in_boxes(i).BackColor.G
in_b(i) = in_boxes(i).BackColor.B
out_r(i) = out_boxes(i).BackColor.R
out_g(i) = out_boxes(i).BackColor.G
out_b(i) = out_boxes(i).BackColor.B
Next i
' Get and lock the Bitmap32.
Dim original_bm As Bitmap = DirectCast(picInput.Image, _
Bitmap)
Dim bm As New Bitmap(original_bm)
Dim bm32 As New Bitmap32(bm)
bm32.LockBitmap()
' Process the pixels.
For y As Integer = 0 To bm.Height - 1
For x As Integer = 0 To bm.Width - 1
' Process pixel (row, col).
Dim r, g, b, a As Byte
bm32.GetPixel(x, y, r, g, b, a)
Dim best_i As Integer = 0
Dim best_dist As Integer = Integer.MaxValue
For i As Integer = 0 To in_boxes.Length - 1
' Compute the distance from this pixel to
' input pixel i.
Dim dr As Integer = r - in_r(i)
Dim dg As Integer = g - in_g(i)
Dim db As Integer = b - in_b(i)
Dim dist As Integer = dr * dr + dg * dg + db _
* db
' See if this is an improvement.
If (dist < best_dist) Then
best_dist = dist
best_i = i
End If
Next i
' Update the pixel.
bm32.SetPixel(x, y, out_r(best_i), _
out_g(best_i), out_b(best_i), 255)
Next x
Next y
' Unlock the Bitmap32.
bm32.UnlockBitmap()
' Display the result.
picOutput.Image = bm
End Sub
|
|
The code uses the Bitmap32 class to quickly manipulate the red, green, and blue color components of the image's pixels. For information about that class, see the code and the example Manipulate image pixels very quickly using LockBits wrapped in a class in VB .NET.
The code loads the image into a Bitmap32 object and locks it. It then loops over each of the image's pixels.
For each pixel, the program finds the target color closest to the pixel's color. It then changes the pixel's value to the corresponding output color.
Load your own images and experiment with the program. Click a target or output color to change the color values and see what happens.
This program can save the result images but it uses 24-bit color depth even though the result image only uses 5 colors.
This example can process a 1000x1000 pixel image in about half a second so it's fast enough that you can use it to make other programs that manipulate an image's pixels in a similar way.
|
|
|
|
|
|
|
|
|