This tutor will show some routines I have developed to filter colors on images.
This is only a sample to introduce the concepts, it is not a finished program, it will only allow for 32bppArgb and 24bppArgb pixelformats, so if you want other formats you need to modify a little the routines to include your format.
In a normal picture, you don't have a clear edge between shapes or colors: if I stand beside a blue wall, my skin will have some blue reflected from the wall, if I am in a bright place, the edge between my arm and the background won't be perfectly delimited.
If I cut a color, the edges will have some shades of different color, and will not be smooth. A drawing of a cartoon character will have better edges, because the limits will be well defined and the colors won't have too much variation.
My program allows to select a color by clicking on picture1 and, depending on the values of the numeric up-downs, a range of colors will be selected, having the selected color in middle and the ranges of red, green and blue from lower to higher included. The program shows on the label with a gradient background, and the range values shown.
By lowering the value of the numeric up-downs, I have more precise colors when cropping, but some shades won't be included. By increasing, it will include more shades of a color, but will also capture colors on the range, that won't look similar to the desired one.
Remember, to construct a color we need 3 components, red, green and blue. Green will be 0,G,0. Where G could have any value from 0 to 255. 0 for the darkest, 255 for the brightest. So if I have 0,188,0 , this is green, same as 0,120,0. But if I have any red or blue component like: 25,204,13, still looks green, but is not green. A forest have a lost of greens, but little pure greens.
Here I have some examples of croping:
The original image on picture1 can be preserved while copying colors to picture2, or the colors cut and tranferred to picture2.
Also it is possible to add colors to the resulting image.
The tooltips will give some information on what to do, but the best way is to experiment. I have included a label that shows the color under the mouse to make it easier to select a color, a routine to save results, and a pixelformat detection routine.
Also there is a couple of undo's for picturebox1, when transferring colors, so you don't have to reload the image.
The adding to the second picture selection should be done after a first transfer or copy, so you have a clear image and white areas, with a color showing. If you don't do that you will have the first picture copied to the second, and won't note the difference.
I am am using lockbits for speed:
Dim rect As Rectangle = Rectangle.Round(PictureBox1.Image.GetBounds(GraphicsUnit.Pixel)) Dim wid As Integer = PictureBox1.Image.Width Dim hgt As Integer = PictureBox1.Image.Height Dim img, img1 As New Bitmap(wid, hgt) img = PictureBox1.Image.Clone img1 = PictureBox2.Image.Clone Dim bmpSr As BitmapData = img.LockBits(New Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadWrite, img.PixelFormat) Dim bmpDest As BitmapData = img1.LockBits(New Rectangle(0, 0, img1.Width, img1.Height), ImageLockMode.ReadWrite, img1.PixelFormat) Dim ptrSr As IntPtr = bmpSr.Scan0 Dim ptrDest As IntPtr = bmpDest.Scan0 Dim R, G, B, A As Integer A = 3 R = 2 G = 1 B = 0 Dim bytesSr As Integer = bmpSr.Stride * img.Height Dim rgbvaluesSr(bytesSr) As Byte System.Runtime.InteropServices.Marshal.Copy(ptrSr, rgbvaluesSr, 0, bytesSr) Dim bytesDest As Integer = bmpDest.Stride * img1.Height Dim rgbvaluesDest(bytesDest) As Byte System.Runtime.InteropServices.Marshal.Copy(ptrDest, rgbvaluesDest, 0, bytesDest)
Checking the pixel format to see which part of the routine to use:
If img.PixelFormat = System.Drawing.Imaging.PixelFormat.Format24bppRgb Then
And checking if the rgb values on picture1 fall in the range and then modifying the rgb values on picture2 and clearing the pixels in picture1
If Math.Abs(RR - MinusR) < NRed.Value And Math.Abs(GG - MinusG) < NGreen.Value And Math.Abs(BB - MinusB) < NBlue.Value Then rgbvaluesDest(x + R) = rgbvaluesSr(x + R) rgbvaluesDest(x + G) = rgbvaluesSr(x + G) rgbvaluesDest(x + B)/> = rgbvaluesSr(x + B)/> If RadioButton2.Checked = True Then rgbvaluesSr(x + R) = 255 rgbvaluesSr(x + G) = 255 rgbvaluesSr(x + B)/> = 255 End If Else
You can save the partial results on picture1 or picture2 using this routine that will save them on sequential numbering in the program directory.
Private Sub ToolStripMenuItem2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripMenuItem2.Click Dim i As Integer Dim str As String = "" For i = 1 To 1000 If i < 10 Then str = "Picture_00" & i.ToString & ".jpg" If i > 9 And i < 100 Then str = "Picture_0" & i.ToString & ".jpg" If i > 99 Then str = "Picture_" & i.ToString & ".jpg" If i > 900 Then MsgBox("You Have Over 900 Pictures, Please Check And Delete Unnecesary Ones") If Not System.IO.File.Exists(str) Then Try PictureBox1.Image.Save(str, System.Drawing.Imaging.ImageFormat.Jpeg) 'Cropped Catch Ex As Exception MsgBox("Could Not Write To Location") End Try Exit For End If Next End Sub
I have included the program and code in the attached zip.
I hope this will be helpful for someone. By the way I am using vb2010 express.
Cut,Crop,Copy Range Of Colors On Image.zip (546.74K)
Number of downloads: 958