Just starting out? Need help? Post your questions and find answers here.
Joubarbe
Enthusiast
Posts: 703 Joined: Wed Sep 18, 2013 11:54 am
Location: France
Post
by Joubarbe » Thu Apr 02, 2015 2:38 pm
Hello,
As you can (barely) see in this image, the inside of this icon is green, and I would like to be able to redraw it in whatever color the user choose. So I can use FillArea() you would say, but no, because if you look closely, there's an inner shadow in this, meaning that I need to keep this effect when changing color. Thus, keeping the Brightness value, and FillArea won't do that.
1/ So, I guess my question is : how to recolor a sprite without affecting the default Brightness values ?
2/ And a bonus question : how to manage the glowing color behind the unit ? I guess it's not the same answer.
Thanks
kenmo
Addict
Posts: 2033 Joined: Tue Dec 23, 2003 3:54 am
Post
by kenmo » Thu Apr 02, 2015 4:53 pm
Here is a very simple example to get you started...
Code: Select all
InFile.s = OpenFileRequester("Open Image", GetCurrentDirectory(), "Images|*.png;*.bmp", 0) ; "test.png"
NewColor.i = ColorRequester() ; RGB(255, 255, 0)
Procedure.i _Max(x.i, y.i)
If (x > y)
ProcedureReturn x
Else
ProcedureReturn y
EndIf
EndProcedure
Procedure ColorizeImage(Image.i, Color.i)
If IsImage(Image)
If StartDrawing(ImageOutput(0))
For x = 0 To ImageWidth(Image) - 1
For y = 0 To ImageHeight(Image) - 1
; This is a very simple version!
OldColor.i = Point(x, y)
Brightness.f = _Max(_Max(Red(OldColor), Green(OldColor)), Blue(OldColor)) / 255.0
NewColor.i = RGB(Brightness * Red(Color), Brightness * Green(Color), Brightness * Blue(Color))
Plot(x, y, NewColor)
Next y
Next x
StopDrawing()
EndIf
EndIf
EndProcedure
UsePNGImageDecoder()
UsePNGImageEncoder()
If LoadImage(0, InFile)
ColorizeImage(0, NewColor)
OutFile.s = InFile + ".png"
SaveImage(0, OutFile, #PB_ImagePlugin_PNG)
RunProgram(OutFile)
EndIf
Now a more advanced version might preserve the pixels' gamma, saturation, only colorize selective hues, etc...
Joubarbe
Enthusiast
Posts: 703 Joined: Wed Sep 18, 2013 11:54 am
Location: France
Post
by Joubarbe » Thu Apr 02, 2015 5:41 pm
Oh... That was so easy I'm ashamed of having asked that question
And uh... Is it also that simple to obtain hue and saturation ?
Hey man, you could have said "just take the higher RGB value of your old color to get the brightness, then multiply your new RGB values with this brightness", but no, you wrote a nice working example ! Thanks a lot for that
(The simple version will do, because it's working perfectly)
BasicallyPure
Enthusiast
Posts: 539 Joined: Thu Mar 24, 2011 12:40 am
Location: Iowa, USA
Post
by BasicallyPure » Thu Apr 02, 2015 10:17 pm
Joubarbe wrote: And uh... Is it also that simple to obtain hue and saturation ?
Hi Joubarbe,
I just worked this out the other day.
Here are procedures that will convert BGR to HSV color space and back to BGR.
Code: Select all
; BGR to HSV to BGR floating point example
Structure HSV_color_Type
Hue.f
Saturation.f
Value.f
EndStructure
EnableExplicit
Procedure BGR_To_HSV(BGRcolor, *output.HSV_color_Type)
; this procedure uses floating point math
; input standard PureBasic BGRcolor value : 0<= BGRcolor <= $FFFFFF
; *output.HSV_color_Type
; \Hue.f : 0<= Hue < 360
; \Saturation.f : 0<= Saturation <= 1
; \Value.f : 0<= Value <= 1
Protected.i delta, BGR_min, BGR_max, R, G, B
R = BGRcolor & $FF : BGRcolor >> 8
G = BGRcolor & $FF : BGRcolor >> 8
B = BGRcolor & $FF
; find the smallest of R, G, B
If g<=b:If r<=g:BGR_min=r:Else:BGR_min=g:EndIf:ElseIf r<=b:BGR_min=r:Else:BGR_min=b:EndIf
; find the largest of R, G, B
If g>=b:If r>=g:BGR_max=r:Else:BGR_max=g:EndIf:ElseIf r>=b:BGR_max=r:Else:BGR_max=b:EndIf
With *output
\Value = BGR_max / 255.0
If \Value = 0
\Hue = 0
\Saturation = 0
ProcedureReturn
EndIf
delta = BGR_max - BGR_min
\Saturation = delta / BGR_max
If \Saturation = 0 Or delta = 0
\Hue = 0
ProcedureReturn
EndIf
If BGR_max = R
\Hue = 60 * (G - B) / delta
ElseIf BGR_max = G
\Hue = 120 + 60 *(B - R) / delta
Else
\Hue = 240 + 60 *(R - G) / delta
EndIf
If \Hue < 0 : \Hue + 360 : EndIf
EndWith
EndProcedure
Procedure HSV_to_BGR(*input.HSV_color_Type)
; this procedure uses floating point math
; input HSV_color_Type
; *input\Hue.f : 0<= Hue < 360
; *input\Saturation.f : 0<= Saturation <= 1
; *input\Value.f : 0<= Value <= 1
; returns the standard PureBasic BGR color value : 0 <= BGRcolor <= $FFFFFF
Protected.f C, X, M
Protected.i R, G, B
With *input
If \Saturation = 0
R = \Value * 255
ProcedureReturn ( R<<16 | R<<8 | R )
EndIf
C = \Value * \Saturation
X = C * (1 - Abs(Mod(\Hue / 60, 2) - 1))
M = (\Value - C) * 255
C * 255
X * 255
If \Hue < 60
R = C+M : G = X+M : B = M
ElseIf \Hue < 120
R = X+M : G = C+M : B = M
ElseIf \Hue < 180
R = M : G = C+M : B = X+M
ElseIf \Hue < 240
R = M : G = X+M : B = C+M
ElseIf \Hue < 300
R = X+M : G = M : B = C+M
Else
R = C+M : G = M : B = X+M
EndIf
EndWith
ProcedureReturn ( B<<16 | G<<8 | R )
EndProcedure
Define HSVcolor.HSV_color_Type
Define BGRcolor = Random($FFFFFF)
Debug "------ original BGR ------"
Debug "Blue = " + Blue(BGRcolor)
Debug "Green = " + Green(BGRcolor)
Debug "Red = " + Red(BGRcolor)
Debug ""
Debug "----- convert to HSV -----"
BGR_To_HSV(BGRcolor, @HSVcolor)
Debug "Hue = " + HSVcolor\Hue
Debug "Sat = " + HSVcolor\Saturation
Debug "Val = " + HSVcolor\Value
Debug ""
Debug "------ back to BGR -------"
BGRcolor = HSV_to_BGR(@HSVcolor)
Debug "Blue = " + Blue(BGRcolor)
Debug "Green = " + Green(BGRcolor)
Debug "Red = " + Red(BGRcolor)
BasicallyPure
Until you know everything you know nothing, all you have is what you believe.
Joubarbe
Enthusiast
Posts: 703 Joined: Wed Sep 18, 2013 11:54 am
Location: France
Post
by Joubarbe » Thu Apr 02, 2015 10:26 pm
Hmm... Thanks, hue seems harder to define !
Blue
Addict
Posts: 964 Joined: Fri Oct 06, 2006 4:41 am
Location: Canada
Post
by Blue » Sun Apr 05, 2015 7:36 am
Hello kenmo
I'm curious...
In the following code you provide
kenmo wrote:
Code: Select all
...
Procedure.i _Max(x.i, y.i)
If (x > y)
ProcedureReturn x
Else
ProcedureReturn y
EndIf
EndProcedure
....
why do you start the Max() function with an underscore ?
Any compelling reason, besides a style preference ?
PB Forums : Proof positive that 2 heads (or more...) are better than one
kenmo
Addict
Posts: 2033 Joined: Tue Dec 23, 2003 3:54 am
Post
by kenmo » Sun Apr 05, 2015 3:58 pm
No important reason.
Just in case Joubarbe wanted to drop some of that example into his project. Didn't want to cause any name conflicts... maybe he already has Max() defined as a procedure for floats, or an array, or something
Blue
Addict
Posts: 964 Joined: Fri Oct 06, 2006 4:41 am
Location: Canada
Post
by Blue » Sun Apr 05, 2015 10:26 pm
kenmo wrote: No important reason.
Just in case Joubarbe wanted to drop some of that example into his project. Didn't want to cause any name conflicts... maybe he already has Max() defined as a procedure for floats, or an array, or something
OK.
So, just good forward thinking on your part.
Nice.
Thanks kenmo.
PB Forums : Proof positive that 2 heads (or more...) are better than one