You convert any color to an Integer with Color.ToARGB. GetPixel is indeed notoriously slow, so you need to use the Bitmap.Lockbits method to convert the image to an array of data. An easy way to do that is to use my FastPix class -- see Rapid Pixel Processing in my signature below. Here's an example (not tested yet!) that copies the skin tone pixels to a 1-dimensional array called naughtyArray whose size equals the number of pixels in the jpeg. You can easily convert that to a 2D array if you want but it would be better to do that outside the loop. First store the skin colors in an Integer array (skinTones in the code below) using Color.ToARGB, and then:
My tests indicate that using FastPix with a simple Integer comparison as in my example works over 100x as fast as a similar loop using SetPixel and GetPixel. The comparison for GetPixel alone will probably be a bit less extreme but considerable all the same.Code:Dim myBitmap = New Bitmap(myJpeg) Using fp As New FastPix(myBitmap) Dim pixels As Integer() = fp.PixelArray For i As Integer = 0 To pixels.Count-1 Dim px As Integer = pixels(i) For j As Integer = 0 To skinTones.Count-1 If px = skinTones(j) Then naughtyArray(i) = px Exit For End If Next j Next i End Using
As a general rule, to get the best performance in an image processing loop like the above:
1. Use only Integer, Logical and Shift operations inside the loop. I haven't checked with floating point (Single or Double) but Integer will always be faster.
2. Avoid "anything with a dot in it" such as Color.ToArgb or Math.Round inside the loop. It takes a lot of time to resolve references to methods and objects outside the class.
BB




Reply With Quote