Hi,
I'm looking for a simple code to put an Image (Colored one) into Black and White...
Any links or sample codes ?
Printable View
Hi,
I'm looking for a simple code to put an Image (Colored one) into Black and White...
Any links or sample codes ?
The easiest way to do it is to simply extract the individual RGB values from the color, average them, and create a new color using the average for all three components. Simple, but it is incorrect, visually, as far as I know. Someone else may be in here at some point to give you a better solution.
Z.
Do this:VB Code:
Function GetLum(R As Long, G As Long, B As Long) As Long Dim Hi As Long Dim Lo As Long Hi = Max(R, G, B) Lo = Min(R, G, B) GetLum = (Hi + Lo) / 2 End Function Function Min(R As Long, G As Long, B As Long) As Long If R < G Then If R < B Then Min = R Else Min = B End If Else If G < B Then Min = G Else Min = B End If End If End Function Function Max(R As Long, G As Long, B As Long) As Long If R > G Then If R > B Then Max = R Else Max = B End If Else If G > B Then Max = G Else Max = B End If End If End Function
Here is what i have done, i think it's more smart...
In the graphics biz, the standard way is to calculate the luminance value for each point and then map it over to an array of
RGB(0,0,0) -> RGB(255,255,255).
I've posted this code about four-five times now - do a search on
this forum for the word 'luminance' Don't search on my name - my account got hosed and the search engine thinks my old posts belong to 'Guest' or something.
It's a weighted average. Using the weighting factors
R: 0.3333 (1/3)
G: 0.59
B: 011
So the grey value would be
(0.3333 * R + 0.59 * G + 0.11 * B) / 3
try mine:
VB Code:
Public Sub BlackAndWhite(ByVal picPictureBox As PictureBox) Dim X As Single Dim Y As Single Dim PrevColor As Long Dim NewColor As Long Dim TempColor As Single For Y = 0 To picPictureBox.ScaleHeight - 1 For X = 0 To picPictureBox.ScaleWidth - 1 PrevColor = GetPixel(picPictureBox.hdc, X, Y) TempColor = Round2((GetRed(PrevColor) + GetGreen(PrevColor) + GetBlue(PrevColor)) / 3) NewColor = RGB(TempColor, TempColor, TempColor) SetPixelV picPictureBox.hdc, X, Y, NewColor Next X Next Y End Sub Public Function GetRed(Color As Long) As Integer GetRed = Color And 255 End Function Public Function GetGreen(Color As Long) As Integer GetGreen = (Color And 65280) \ 256 End Function Public Function GetBlue(Color As Long) As Integer GetBlue = (Color And 16711680) \ 65535 End Function Public Function Round2(Number As Single) As Integer If Number - Round(Number) >= 0.05 Then Number = Round(Number, 1) + 0.1 If Number - Round(Number) < 0.05 Then Number = Round(Number, 1) Round2 = Number End Function
here's a sample image changed with my code:
http://www.vbforums.com/attachment.p...postid=1232159
Perhaps this was the first post?Quote:
Originally posted by cyborg
try mine:
VB Code:
Public Sub BlackAndWhite(ByVal picPictureBox As PictureBox) Dim X As Single Dim Y As Single Dim PrevColor As Long Dim NewColor As Long Dim TempColor As Single For Y = 0 To picPictureBox.ScaleHeight - 1 For X = 0 To picPictureBox.ScaleWidth - 1 PrevColor = GetPixel(picPictureBox.hdc, X, Y) TempColor = Round2((GetRed(PrevColor) + GetGreen(PrevColor) + GetBlue(PrevColor)) / 3) NewColor = RGB(TempColor, TempColor, TempColor) SetPixelV picPictureBox.hdc, X, Y, NewColor Next X Next Y End Sub Public Function GetRed(Color As Long) As Integer GetRed = Color And 255 End Function Public Function GetGreen(Color As Long) As Integer GetGreen = (Color And 65280) \ 256 End Function Public Function GetBlue(Color As Long) As Integer GetBlue = (Color And 16711680) \ 65535 End Function Public Function Round2(Number As Single) As Integer If Number - Round(Number) >= 0.05 Then Number = Round(Number, 1) + 0.1 If Number - Round(Number) < 0.05 Then Number = Round(Number, 1) Round2 = Number End Function
Z.
you mean your post?
i just showed a routine i made to make it easy for him...
the other 2 ones didnt work properly...
the first one took the average from the lowest and highest value from r, g and b.....
the other one changed to less colors...
Just look closely at the name of the function : Black & White, it means NO GREY. (2 Colors : 1. White, 2. Black )
I've build this little Module on the principles that :
(Recall)
RGB(0,0,0) = BLACK
RGB(255,255,255) = WHITE
So a colour is coded on 3 Bytes stored in a long (4 Bytes)
R G B R G B
a Colour is coded to &H 00 00 00 to & H FF FF FF
I extract each colors (R, G, B) by an AND and see if each of them are bigger than 127 (Brithness indeed, no ?)
:)
Your code is great, and helpfull, thanks !
:rolleyes:
But what do you think about writing a function like :
GreyImage(pPictureBox as PictureBox, byval GreyLevel as byte)
Where GreyLevel is the accuracy in grey :
Example :
(Grey level cannot be 0 or 1), because
GreyLevel =2, it will be black and white only
GreyLevel =3 will be black and white and Perfect Grey
and so on... with different grey levels
Once the picture is modified, if i want to save to disk, it doesn't work using the SavePicture function
Should i call a API function and give it hDC of the picture box ??
For the GrayLevel function:
pseudocode
VB Code:
Dim px As Pixel Dim clr As Color Dim gr As Byte Dim i As Integer If GrayLevel < 2 Then Exit Sub End If For px = Each Pixel in pPictureBox clr = px.color gr = (0.3333*clr.red+0.59*clr.green+0.11*clr.blue)/3 ' You need to refine this part, it doesn't work this way For i = 1 To GrayLevel-1 If gr < (255 / GrayLevel)*i Then gr = (255/GrayLevel)*i-1 Goto Done End If Next i gr = 255 Done: clr.red = clr.green = clr.blue = gr px.color = clr Next px
The problem of this spacing algorithm is that every one that I could come up when thinking about this would either not work with more than 2 greys or exactly black & white.
Thanks
But, I haven't understand your post on :
It's a weighted average. Using the weighting factors
R: 0.3333 (1/3)
G: 0.59
B: 011
So the grey value would be
(0.3333 * R + 0.59 * G + 0.11 * B) / 3
Can you develop why is there coefficient in front of R,G,B
I thought grey was RGB(127,127,127) .....
Thanks.
There are many shades of gray, computers usually display 256 (RGB(0,0,0) to RGB(255,255,255)).
When you have a color picture you usually take the average of the color components to get the shade of grey this particular color correspondends to. But it would be wrong to simply use every color component the same (0.3333*r+0.3333*g+0.3333*b), because the human eye values the components differently. A bright green looks far brighter than a bright blue. Therefore you have to use a weighted average: (0.3333*r+0.59*g+0.11*b). I have to correct myself, there is no /3 there.
I didn't know that, is there any article on the subject ?
There probably is, but I don't know where...
Try googling for "grayscale conversion" or similar terms.
If you want a black-and-white artistic feeling, use one of the excellent grayscale code snippets in this thread, and if R, G, and B are under 128, make all 0 (black). If they're 128 or over, make them 255 (white).
If you want something more accurate, you'll have to look into things like dithering and error defusion.