routine for desaturate a picture/image?

Just starting out? Need help? Post your questions and find answers here.
zued
User
User
Posts: 27
Joined: Wed Dec 17, 2003 11:20 pm

routine for desaturate a picture/image?

Post 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
El_Choni
TailBite Expert
TailBite Expert
Posts: 1007
Joined: Fri Apr 25, 2003 6:09 pm
Location: Spain

Post 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...
Last edited by El_Choni on Thu Apr 28, 2005 12:04 pm, edited 1 time in total.
El_Choni
zued
User
User
Posts: 27
Joined: Wed Dec 17, 2003 11:20 pm

Post 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
El_Choni
TailBite Expert
TailBite Expert
Posts: 1007
Joined: Fri Apr 25, 2003 6:09 pm
Location: Spain

Post 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.
El_Choni
zued
User
User
Posts: 27
Joined: Wed Dec 17, 2003 11:20 pm

Post 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
zued
User
User
Posts: 27
Joined: Wed Dec 17, 2003 11:20 pm

Post 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")


El_Choni
TailBite Expert
TailBite Expert
Posts: 1007
Joined: Fri Apr 25, 2003 6:09 pm
Location: Spain

Post by El_Choni »

You must send the ImageID, not the index. I made it so it can be used with any bitmap handle.

Code: Select all

SetSaturation(UseImage(0),50)
El_Choni
zued
User
User
Posts: 27
Joined: Wed Dec 17, 2003 11:20 pm

Post 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
Post Reply