Code archives/Graphics/Desaturate Image

This code has been declared by its author to be Public Domain code.

Download source code

Desaturate Image by _PJ_2009
I've made it as fast as I can, but it still may be optimised further.

The "Contrast" parameter is a percentage where 0 is low (black) and 100 is the clearest greyscale.
"Image" parameter must be an existing image handle.
;By Malice 2009
;
;Use DeSaturate(Image%,Contrast%) to Call function.
;
; Other functions are required, but are called from within.


Function DeSaturate(Image,Contrast%=100)
	Contrast%=Contrast% Mod 100
	Local Width%=ImageWidth(Image)-1
	Local Height=ImageHeight(Image)-1
	Local X
	Local Y
	LockBuffer ImageBuffer(Image)
	For X=0 To Width
		For Y=0 To Height
			Pixel=ReadPixelFast(X,Y,ImageBuffer(Image))
			WritePixelFast X,Y,Greyscale%(Pixel,Contrast%),ImageBuffer(Image)
		Next
	Next
	UnlockBuffer ImageBuffer(Image)
End Function






Function Greyscale%(Colour_ARGB,Amount%)		
	Mean=((Red(Colour_ARGB)+Blue(Colour_ARGB)+Green(Colour_ARGB))*0.33)
	If Not( Amount)
		Return (Colour_ARGB)
	Else
		If Amount=100
			Return ARGB(Mean,Mean,Mean)
		Else
			Return ARGB(Filter(Red(Colour_ARGB),Mean)*Amount%*0.01,Filter(Green(Colour_ARGB),Mean)*Amount%*0.01,Filter(Blue(Colour_ARGB),Mean)*Amount%*0.01)
		End If	
	End If
End Function

Function ARGB(r,g,b)
	Return (b Or (g Shl 8) Or (r Shl 16) )
End Function
Function Red(ARGB)
	Return (RGB Shr 16 And 255)
End Function
Function Green(ARGB)
	Return (ARGB Shr 8 And 255)
End Function
Function Blue(ARGB)
	Return (ARGB And 255)
End Function

Function Filter%(Colour,Filter)
	Return (Colour-(Colour-Filter))
End Function

Comments

xlsior2009
Um....

"Contrast$=Contrast% Mod 100" ?

contrast$ doesn't seem right there.


_PJ_2009
You're right...

I think that snuck in when I was exttracting the code to place here. In my version "Contrast" was a global variable from elsewhere, so I musta hit '4' instead of '5' when updating the declaration.

Anyway, should be fixed now :)


xlsior2009
One other thing: while your desaturation routine does turn an image monochrome, it's not 'proper' black-and-white: You don't take the relative luminosity of the different color channels into consideration.
Simply averaging out all the colors equally will looks really weird on some images, depending on which colors were used (especially if you had a lot of blue in the image)

the human eye is most sensitive to green, less to red, and poor to blue.

To convert a color image to a shade that's comparable to how it would look on an old-fashioned black-and-white TV, you should use the following channel mixture:
red: 0.299
green: 0.587
blue: 0.114
(= 1.0 total)

For comparison, see my desaturation fader: http://www.blitzbasic.com/codearcs/codearcs.php?code=2089


_PJ_2009
I can't run your fader, I don;t own BMax, but I see how it works, and it's generally the same principle albeit with your inclusion of the ratios.

Though I wasn't intending to obtain such a result, I just wanted to remove colour hiues, I appreciate the info and biology lesson :D
Different functions for different results, but thanks for the info!


xlsior2009
Here's another version that runs in B3D / BlitzPlus / BlitzBasic:

http://www.blitzbasic.com/codearcs/codearcs.php?code=836

(The blitzmax sample is faster though, since it only calculates the B&W version once and then alpha-blends the color and monochrome versions to their respective ratios)


_PJ_2009
Wow, that's neat.
I especially like how it;s able to restore the colour too.

If only I'd seen this before :D

Just wondering though, why doesn't it use WritePixelFast? Is that for compatibility?


xlsior2009
Just because I didn't think of it at the time. ;-)

This was a very old piece of code -- The blitzmax version is much more recent, and way nicer.


_PJ_2011
Deprecated.
Obsolete due to the DeSaturateImage functionality here:
http://blitzbasic.com/codearcs/codearcs.php?code=2847


Code Archives Forum