Login or Signup

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_1+ years ago
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
			WritePixelFast X,Y,Greyscale%(Pixel,Contrast%),ImageBuffer(Image)
	UnlockBuffer ImageBuffer(Image)
End Function

Function Greyscale%(Colour_ARGB,Amount%)		
	If Not( Amount)
		Return (Colour_ARGB)
		If Amount=100
			Return ARGB(Mean,Mean,Mean)
			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


xlsior(Posted 1+ years ago)

"Contrast$=Contrast% Mod 100" ?

contrast$ doesn't seem right there.

_PJ_(Posted 1+ years ago)
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 :)

xlsior(Posted 1+ years ago)
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_(Posted 1+ years ago)
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!

xlsior(Posted 1+ years ago)
Here's another version that runs in B3D / BlitzPlus / BlitzBasic:


(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_(Posted 1+ years ago)
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?

xlsior(Posted 1+ years ago)
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_(Posted 1+ years ago)
Obsolete due to the DeSaturateImage functionality here:

Code Archives Forum
Blitz Social Club