Replace all instances of a color in a picturebox

  • Thread starter Thread starter Shane Stewart
  • Start date Start date
S

Shane Stewart

I've created a user control inheriting a picturebox. I want to set a
non-rectangular area to the current system color.control.

I'm looking for either a "fill" command that will set all contiguous
pixels of the same color to a new color, or possibly a command that
changes all pixels of a color to a new color; the only instance of
color.control in the picture is in the background area.

There is a C# edge detection routine that I found on bobpowell.net
(which is an excellent graphics source)so that I could probably use to
build a fill path, but I figure that there must be an easier way.

Thanks in advance.
 
Shane Stewart said:
I've created a user control inheriting a picturebox. I want to set a
non-rectangular area to the current system color.control.

I'm looking for either a "fill" command that will set all contiguous
pixels of the same color to a new color, or possibly a command that
changes all pixels of a color to a new color; the only instance of
color.control in the picture is in the background area.

Create a 'Bitmap' object of appropriate size, obtain a 'Graphics' object
using 'Graphics.FromImage', fill the image in the desired color, call
'MakeTransparent' on the source bitmap in order to make the pixels filled
with the color that should be replaced transparent. Then use the 'Graphics'
object's 'DrawImage' method to draw the transparent bitmap ontp the
destination bitmap. Call the bitmaps 'Save' method in order to save the
file to disk, or display it using a picturebox control.
 
Hi folks ! :O)

I ain't know much about GDI+ yet so I'd like your input about this code. ie.
is there any speed and/or memory issues ?

This sample change to black any color the user clicks.
'***
Option Explicit On

Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices

Public Class Form1
Inherits System.Windows.Forms.Form

<DllImport("gdi32.dll")> _
Public Shared Function BitBlt( _
ByVal hdcDest As IntPtr, _
ByVal nXDest As Int32, _
ByVal nYDest As Int32, _
ByVal nWidth As Int32, _
ByVal nHeight As Int32, _
ByVal hdcSrc As IntPtr, _
ByVal nXSrc As Int32, _
ByVal nYSrc As Int32, _
ByVal dwRop As Int32 _
) As Boolean
End Function
Private Shared ReadOnly SRCCOPY As Int32 = &HCC0020

' Windows Designer's generated code region goes here

Protected Overrides Sub OnPaint(ByVal e As
System.Windows.Forms.PaintEventArgs)

MyBase.OnPaint(e)

' draw something
e.Graphics.FillRectangle(Brushes.Maroon, 10, 10, 100, 100)
e.Graphics.FillEllipse(Brushes.Blue, 10, 10, 100, 100)
e.Graphics.FillEllipse(Brushes.DarkBlue, 20, 20, 80, 80)
e.Graphics.FillRectangle(Brushes.Coral, 75, 75, 50, 50)

End Sub

Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown

Dim bmp As Bitmap = CreateBitmapFromControl(Me)
Dim nSearchCol As Int32 = bmp.GetPixel(e.X, e.Y).ToArgb()
Dim nReplaceCol As Int32 = Color.Black.ToArgb()
Dim bd As BitmapData = bmp.LockBits(New Rectangle(0, 0, bmp.Width,
bmp.Height), Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat)

' loop through the bitmap data and replace
' the matching pixels with black
For i As Int32 = 0 To (bd.Stride * bd.Height) - 1 Step
Marshal.SizeOf(GetType(Int32))
If (Marshal.ReadInt32(bd.Scan0, i) = nSearchCol) Then
Marshal.WriteInt32(bd.Scan0, i, nReplaceCol)
End If
Next

bmp.UnlockBits(bd)
Me.CreateGraphics().DrawImage(Image.FromHbitmap(bmp.GetHbitmap()),
0, 0)

End Sub

Private Function CreateBitmapFromControl(ByVal ctl As Control) As Bitmap

Dim gCtl As Graphics = ctl.CreateGraphics()
Dim bmp As Bitmap = New Bitmap(ctl.ClientRectangle.Width,
ctl.ClientRectangle.Height, gCtl)
Dim gMem As Graphics = Graphics.FromImage(bmp)
Dim hCtlHDC As IntPtr = gCtl.GetHdc()
Dim hMemHDC As IntPtr = gMem.GetHdc()

BitBlt(hMemHDC, 0, 0, ctl.ClientRectangle.Width,
ctl.ClientRectangle.Height, hCtlHDC, 0, 0, SRCCOPY)

gCtl.ReleaseHdc(hCtlHDC)
gMem.ReleaseHdc(hMemHDC)

Return bmp

End Function

End Class
'***
 
Back
Top