Code archives/Graphics/Desaturate Image
This code has been declared by its author to be Public Domain code.
Download source code
| 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
"Contrast$=Contrast% Mod 100" ?
contrast$ doesn't seem right there.
| 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 :)
| 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:
(= 1.0 total)
For comparison, see my desaturation fader: http://www.blitzbasic.com/codearcs/codearcs.php?code=2089
| 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!
| 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)
| 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?
| 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.
Obsolete due to the DeSaturateImage functionality here:
Code Archives Forum