Page 1 of 1
routine for desaturate a picture/image?
Posted: Wed Apr 27, 2005 6:15 pm
by zued
Hi
Is there an exampel for desaturate a image?
I found a api command for gdi+ :
class HueSaturationLightness -
http://msdn.microsoft.com/library/defau ... htness.asp
But.. as a beginner I dont get it
Any help is welcome..
Thanks
ZuedTheSwede
Posted: Wed Apr 27, 2005 8:42 pm
by El_Choni
Hi,
I don't know how to do it with GDIPlus, but you can do it without. This code uses tinman's
hsv2rgb procedures from this post:
viewtopic.php?t=8251
Code: Select all
Structure COLORREF
FutureAlpha.b ;)
b.b
g.b
r.b
EndStructure
Procedure SetSaturation(ImageID, Saturation) ; Saturation: 0-100%
If Saturation>100:Saturation = 100:EndIf
If Saturation<0:Saturation = 0:EndIf
GetObject_(ImageID, SizeOf(BITMAP), @bm.BITMAP)
width = bm\bmWidth
height = bm\bmHeight
BitmapByteSize = width*height*4
*BitmapBits = AllocateMemory(BitmapByteSize)
hDC = CreateDC_("DISPLAY", #NULL, #NULL, #NULL)
bmi.BITMAPINFOHEADER
bmi\biSize = SizeOf(BITMAPINFOHEADER)
bmi\biWidth = width
bmi\biHeight = -height
bmi\biPlanes = 1
bmi\biBitCount = 32
bmi\biCompression = #BI_RGB
GetDIBits_(hDC, ImageID, 0, height, *BitmapBits, @bmi, 0)
*BitmapBitsSeeker.COLORREF = *BitmapBits
For i=0 To BitmapByteSize-4 Step 4
rv = *BitmapBitsSeeker\r&$ff
gv = *BitmapBitsSeeker\g&$ff
bv = *BitmapBitsSeeker\b&$ff
rgb.COLOUR\r = rv/255
rgb\g = gv/255
rgb\b = bv/255
RGB2HSV(@rgb, @hsvValue.HSV)
hsvValue\s = Saturation/100
HSV2RGB(@hsvValue, @rgb)
*BitmapBitsSeeker\r = rgb\r*255
*BitmapBitsSeeker\g = rgb\g*255
*BitmapBitsSeeker\b = rgb\b*255
*BitmapBitsSeeker+4
Next
SetDIBits_(hDC, ImageID, 0, height, *BitmapBits, @bmi, 0)
DeleteDC_(hDC)
FreeMemory(*BitmapBits)
EndProcedure
I hope it helps...
Posted: Thu Apr 28, 2005 9:31 am
by zued
it sounds good.. but cant test it because of an error on this line:
rgb.COLOUR\r = rv
errorcode - structure not found: COLOR
?Whats wrong?
Thanks for the fast answere
/zuedTheSwede
Posted: Thu Apr 28, 2005 11:17 am
by El_Choni
Well, you must copy tinman's source from the link I put above my code. You'll find that structure there. My code won't do nothing without his procedures.
Posted: Thu Apr 28, 2005 12:46 pm
by zued
don that

..
added this part last to test:
Code: Select all
LoadImage(0,"c:\testc.bmp")
SetSaturation(0,50)
SaveImage(0,"c:\testcorrected.bmp")
but gets another error at:(line137)
*BitmapBits = AllocateMemory(BitmapByteSize)
code-> Cant allocate a memory block of size 0
Thanks again!
ZuedTheSwede
Posted: Thu Apr 28, 2005 12:54 pm
by zued
Heres the "structure"!
I added some debuggers
Code: Select all
#USE_ASM_PROCEDURES=1
Structure COLORREF
FutureAlpha.b ;)
b.b
g.b
r.b
EndStructure
Structure COLOUR
r.f
g.f
b.f
EndStructure
Structure HSV
h.f
s.f
v.f
EndStructure
CompilerIf #USE_ASM_PROCEDURES=1
; Uses the MinF and MaxF functions posted to the tricks & tips forum by Psychophanta
Procedure.f MinF(n1.f,n2.f)
!FINIT
!FLD dword[Esp+4]
!FLD dword[Esp]
!fcomi st1
!fcmovnb st1
EndProcedure
Procedure.f MaxF(n1.f,n2.f)
!FINIT
!FLD dword[Esp+4]
!FLD dword[Esp]
!fcomi st1
!fcmovb st1
EndProcedure
CompilerElse
Procedure.f MinF(n1.f, n2.f)
If n1<n2
ProcedureReturn n1
EndIf
ProcedureReturn n2
EndProcedure
Procedure.f MaxF(n1.f, n2.f)
If n1>n2
ProcedureReturn n1
EndIf
ProcedureReturn n2
EndProcedure
CompilerEndIf
Procedure HSV2RGB(*c1.HSV, *rgb.COLOUR)
DefType.COLOUR sat
While *c1\h < 0
*c1\h = *c1\h + 360
Wend
While *c1\h > 360
*c1\h = *c1\h - 360
Wend
If *c1\h < 120
sat\r = (120 - *c1\h) / 60.0
sat\g = *c1\h / 60.0
sat\b = 0
ElseIf *c1\h < 240
sat\r = 0
sat\g = (240 - *c1\h) / 60.0
sat\b = (*c1\h - 120) / 60.0
Else
sat\r = (*c1\h - 240) / 60.0
sat\g = 0
sat\b = (360 - *c1\h) / 60.0
EndIf
sat\r = MinF(sat\r, 1)
sat\g = MinF(sat\g, 1)
sat\b = MinF(sat\b, 1)
*rgb\r = (1 - *c1\s + *c1\s * sat\r) * *c1\v
*rgb\g = (1 - *c1\s + *c1\s * sat\g) * *c1\v
*rgb\b = (1 - *c1\s + *c1\s * sat\b) * *c1\v
EndProcedure
Procedure RGB2HSV(*c1.COLOUR, *hsv.HSV)
DefType.f themin,themax,delta
themin = MinF(*c1\r,MinF(*c1\g,*c1\b))
themax = MaxF(*c1\r,MaxF(*c1\g,*c1\b))
delta = themax - themin
Debug themax
Debug themin
Debug delta
*hsv\v = themax
*hsv\s = 0
If themax > 0
*hsv\s = delta / themax
EndIf
*hsv\h = 0
If delta > 0
If themax=*c1\r And themax<>*c1\g
*hsv\h = *hsv\h + ((*c1\g - *c1\b) / delta)
EndIf
If themax=*c1\g And themax<>*c1\b
*hsv\h = *hsv\h + (2 + (*c1\b - *c1\r) / delta)
EndIf
If themax=*c1\b And themax<>*c1\r
*hsv\h = *hsv\h + (4 + (*c1\r - *c1\g) / delta)
EndIf
*hsv\h = *hsv\h * 60
EndIf
EndProcedure
Procedure SetSaturation(ImageID, Saturation) ; Saturation: 0-100%
If Saturation>100:Saturation = 100:EndIf
If Saturation<0:Saturation = 0:EndIf
Debug SizeOf(BITMAP)
GetObject_(ImageID, SizeOf(BITMAP), @bm.BITMAP)
Debug bm
Debug bmHeight
Width = bm\bmWidth
Debug Width
Height = bm\bmHeight
Debug Height
BitmapByteSize = Width*Height*4
*BitmapBits = AllocateMemory(BitmapByteSize)
hDC = CreateDC_("DISPLAY", #Null, #Null, #Null)
bmi.BITMAPINFOHEADER
bmi\biSize = SizeOf(BITMAPINFOHEADER)
bmi\biWidth = Width
bmi\biHeight = -Height
bmi\biPlanes = 1
bmi\biBitCount = 32
bmi\biCompression = #BI_RGB
GetDIBits_(hDC, ImageID, 0, Height, *BitmapBits, @bmi, 0)
*BitmapBitsSeeker.COLORREF = *BitmapBits
For i=0 To BitmapByteSize-4 Step 4
rv = *BitmapBitsSeeker\r&$FF
gv = *BitmapBitsSeeker\g&$FF
bv = *BitmapBitsSeeker\b&$FF
rgb.COLOUR\r = rv
rgb\g = gv
rgb\b = bv
RGB2HSV(@rgb, @hsvValue.HSV)
hsvValue\s = Saturation/100
HSV2RGB(@hsvValue, @rgb)
*BitmapBitsSeeker\r = rgb\r
*BitmapBitsSeeker\g = rgb\g
*BitmapBitsSeeker\b = rgb\b
*BitmapBitsSeeker+4
Next
SetDIBits_(hDC, ImageID, 0, Height, *BitmapBits, @bmi, 0)
DeleteDC_(hDC)
FreeMemory(*BitmapBits)
EndProcedure
;main
LoadImage(0,"c:\testc.bmp")
SetSaturation(0,50)
SaveImage(0,"c:\testcorrected.bmp")
Posted: Thu Apr 28, 2005 3:38 pm
by El_Choni
You must send the ImageID, not the index. I made it so it can be used with any bitmap handle.
Posted: Thu Apr 28, 2005 4:34 pm
by zued
El_Choni ... your my man!
Thanks!!!
/still a small problem left.. blue channel doesnt go down!..
( it can be my night lesson to find the *bug*

)
Thanks again!
ZuedTheSwede