Colormodels: RGB, CMY, HLS, HSL (HLS, HSI)

Share your advanced PureBasic knowledge/code with the community.
Froggerprogger
Enthusiast
Enthusiast
Posts: 423
Joined: Fri Apr 25, 2003 5:22 pm
Contact:

Colormodels: RGB, CMY, HLS, HSL (HLS, HSI)

Post by Froggerprogger »

Hi!
Here some procedures to convert between the colormodels named in the title.
Sense of those: e.g. decrease the saturation of a color by one parameter, which is hard to do in rgb directly.

3 examples are contained.

For HSV, HSL see:
http://en.wikipedia.org/wiki/HSV_color_space
http://en.wikipedia.org/wiki/HLS_color_space

Code: Select all

;- Color v1.1
;-
;- Procedures for handling colors not only in RGB, but also CMY, HSV and HSL (sometimes called HLS oder HSI)
;- Especially the last both let you modify the saturation and hue much more intuitively
;- See Wikipedia for more information on HSV and HSL
;-
;- The procedures contains all conversions between those color-types. The internal RGB-format
;- uses values in range [0.0, 1.0], so scale them manually to [0, 255] or use ColorRGB() for their usage in PB.
;-
;- Feel free to use this code for anything you want but without infringing its copyright.
;- (don't describe as it's author, don't sell itself - so just stay as nice as you are :)
;-
;- 19.09.06 by Froggerprogger
;-
;- v1.1:
;-         - added example 3
;-
;- please report any bugs, etc. to Froggerprogger in the Purebasic-Forums

Enumeration
  ; do not change their order!
  #COLOR_RGB
  #COLOR_CMY
  #COLOR_HSV
  #COLOR_HSL
EndEnumeration

Structure Color
  StructureUnion
    r.f ; Red in RGB [0.0, 1.0]
    c.f ; Cyan in CMY [0.0, 1.0]
    h.f ; Hue in HSV/HSL [0.0, 360.0[
  EndStructureUnion
  StructureUnion
    g.f ; Green in RGB [0.0, 1.0]
    m.f ; Magenta in CMY [0.0, 1.0]
    s.f ; Saturation in HSV/HSL [0.0, 1.0]
  EndStructureUnion
  StructureUnion
    b.f ; Blue in RGB [0.0, 1.0]
    y.f ; Yellow in CMY [0.0, 1.0]
    v.f ; Value in HSV [0.0, 1.0]
    l.f ; Lightness in HSL [0.0, 1.0]
  EndStructureUnion
  type.l ; gives the type. One of #COLOR_RGB, #COLOR_CMY, #COLOR_HSV, #COLOR_HSL
EndStructure

;- some neccessary declares
DeclareDLL.l Color2RGB(*c.Color)
DeclareDLL.l Color2CMY(*c.Color)
DeclareDLL.l Color2HSV(*c.Color)
DeclareDLL.l Color2HSL(*c.Color)

;- some helper-proceudures
Procedure.f Max3F(a.f, b.f, c.f)
  If a > b
    If a > c
      ProcedureReturn a
    Else
      ProcedureReturn c
    EndIf
  Else
    If b > c
      ProcedureReturn b
    Else
      ProcedureReturn c
    EndIf
  EndIf
EndProcedure

Procedure.f Min3F(a.f, b.f, c.f)
  If a < b
    If a < c
      ProcedureReturn a
    Else
      ProcedureReturn c
    EndIf
  Else
    If b < c
      ProcedureReturn b
    Else
      ProcedureReturn c
    EndIf
  EndIf
EndProcedure

;- some global color-procedures
ProcedureDLL.l IsColorValid(*c.Color) ; returns #True or #False whether *c specifies a valid color or not
  If *c\type < #COLOR_RGB Or *c\type > #COLOR_HSL
    ProcedureReturn #False
  EndIf
 
  ; check r, c in [0.0, 1.0] or h in [0.0, 360.0]
  If *c\type <= #COLOR_CMY
    If *c\r < 0 Or *c\r > 1.0
      ProcedureReturn #False
    EndIf
  Else
    If *c\h < 0 Or *c\h >= 360.0
      ProcedureReturn #False
    EndIf
  EndIf
 
  ; check g, m, s, b, y, v, l in [0.0, 1.0]
  If *c\g < 0 Or *c\g > 1.0
    ProcedureReturn #False
  EndIf
  If *c\b < 0 Or *c\b > 1.0
    ProcedureReturn #False
  EndIf
 
  ProcedureReturn #True
EndProcedure

ProcedureDLL.l ColorCopy(*c.Color) ; copies *c and returns *copy
  Protected *out = AllocateMemory(SizeOf(Color))
  CopyMemory(*c, *out, SizeOf(Color))
  ProcedureReturn *out
EndProcedure

ProcedureDLL.l ColorComplement(*c.Color) ; complements *c and returns *c
  If *c\type <= #COLOR_CMY
    ; if #COLOR_RGB or #COLOR_CMY
    *c\r = 1.0 - *c\r
    *c\g = 1.0 - *c\g
    *c\b = 1.0 - *c\b
  Else
    ; if #COLOR_HSV or #COLOR_HSL
    If *c\h >= 180.0
      *c\h - 180.0
    Else
      *c\h + 180.0
    EndIf
  EndIf
EndProcedure

ProcedureDLL.l ColorChangeType(*c.Color, type.l) ; changes the type of *c to the new type and returns *c. type = #COLOR_*
  Select type
    Case #COLOR_RGB : Color2RGB(*c)
    Case #COLOR_CMY : Color2CMY(*c)
    Case #COLOR_HSV : Color2HSV(*c)
    Case #COLOR_HSL : Color2HSL(*c)
  EndSelect
EndProcedure

ProcedureDLL.l IsSameColors(*c1.Color, *c2.Color, tolerance.f) ; compares the two colors (of any type) without modifiing them and returns #True if they describe the same color equal, #False otherwise
  Protected same.l
 
  ; compare in RGB to easy treat special cases in HSL, HSV
  *c1c.Color = ColorCopy(*c1)
  *c2c.Color = ColorCopy(*c2)
  Color2RGB(*c1c)
  Color2RGB(*c2c)
 
  If tolerance = 0
    same = CompareMemory(*c1c, *c2c, SizeOf(Color))
  Else
    same = #True
    If Abs(*c1c\r - *c2c\r) > tolerance
      same = #False
    EndIf
    If Abs(*c1c\g - *c2c\g) > tolerance
      same = #False
    EndIf
    If Abs(*c1c\b - *c2c\b) > tolerance
      same = #False
    EndIf
  EndIf
  FreeMemory(*c1c)
  FreeMemory(*c2c)
  ProcedureReturn same
EndProcedure

ProcedureDLL.s ColorToStr(*c.Color)
  Protected s.s
  Select *c\type
    Case #COLOR_RGB : s = "RGB"
    Case #COLOR_CMY : s = "CMY"
    Case #COLOR_HSV : s = "HSV"
    Case #COLOR_HSL : s = "HSL"
  EndSelect
 
  s + ": " + StrF(*c\r, 2) + ", " + StrF(*c\g, 2) + ", " + StrF(*c\b, 2)
 
  ProcedureReturn s
EndProcedure

;- change color to RGB
ProcedureDLL.l CMY2RGB(*c.Color) ; converts CMY-color *c to RGB and returns *c. No check if CMY is made!
  *c\r = 1.0 - *c\c
  *c\g = 1.0 - *c\m
  *c\b = 1.0 - *c\y
  *c\type = #COLOR_RGB
 
  ProcedureReturn *c
EndProcedure

ProcedureDLL.l HSV2RGB(*c.Color) ; converts HSV-color *c to RGB and returns *c. No check if HSV is made!
  Protected h.f, s.f, v.f
  Protected f.f, p.f, q.f, t.f, i.l
 
  h = *c\h
  s = *c\s
  v = *c\v
 
  If s = 0
    ; it's a gray-tone
    *c\r = v
    *c\g = v
    *c\b = v
  Else
    h / 60.0
    i = Round(h, 0)
    f = h-i
    p = v*(1.0-s)
    q = v*(1.0-s*f)
    t = v*(1.0-s*(1.0-f))
   
    Select i
      Case 0 : *c\r = v : *c\g = t : *c\b = p
      Case 1 : *c\r = q : *c\g = v : *c\b = p
      Case 2 : *c\r = p : *c\g = v : *c\b = t
      Case 3 : *c\r = p : *c\g = q : *c\b = v
      Case 4 : *c\r = t : *c\g = p : *c\b = v
      Case 5 : *c\r = v : *c\g = p : *c\b = q
    EndSelect
   
  EndIf
 
  *c\type = #COLOR_RGB
 
  ProcedureReturn *c
EndProcedure

Procedure.f HSL2RGBHelper(q1.f, q2.f, h.f)
  If h >= 360.0
    h - 360.0
  ElseIf h < 0.0
    h + 360.0
  EndIf
 
  If h < 60.0
    ProcedureReturn q1+(q2-q1)*h/60.0
  ElseIf h < 180.0
    ProcedureReturn q2
  ElseIf h < 240.0
    ProcedureReturn q1+(q2-q1)*(240.0-h)/60.0
  Else
    ProcedureReturn q1
  EndIf
EndProcedure

ProcedureDLL.l HSL2RGB(*c.Color) ; converts HSL-color *c to RGB and returns *c. No check if HSL is made!
  Protected h.f, l.f, s.f
  Protected f.f, p1.f, p2.f, t.f
  Protected i.l
 
  h = *c\h
  l = *c\l
  s = *c\s
 
  If l<=0.5
    p2 = l*(1.0+s)
  Else
    p2 = l+s-l*s
  EndIf
 
  p1 = 2.0*l-p2
 
  If s=0.0
    ; it's a gray-tone
    *c\r = l
    *c\g = l
    *c\b = l
  Else
    *c\r = HSL2RGBHelper(p1, p2, h+120.0)
    *c\g = HSL2RGBHelper(p1, p2, h)
    *c\b = HSL2RGBHelper(p1, p2, h-120.0)
  EndIf
 
  *c\type = #COLOR_RGB
 
  ProcedureReturn *c
EndProcedure

ProcedureDLL.l Color2RGB(*c.Color) ; converts *c from any color-type to RGB and returns *c
  Select *c\type
    Case #COLOR_RGB : ProcedureReturn *c
    Case #COLOR_CMY : ProcedureReturn CMY2RGB(*c)
    Case #COLOR_HSV : ProcedureReturn HSV2RGB(*c)
    Case #COLOR_HSL : ProcedureReturn HSL2RGB(*c)
  EndSelect
EndProcedure

ProcedureDLL.l ColorSetRGB(*c.Color, r.f, g.f, b.f) ; sets *c to the RGB-color given by r,g,b, each in range [0.0, 1.0] (no check is made) and returns *c
  *c\r = r
  *c\g = g
  *c\b = b
  *c\type = #COLOR_RGB
 
  ProcedureReturn *c
EndProcedure

;- change color to CMY
ProcedureDLL.l RGB2CMY(*c.Color) ; converts RGB-color *c to CMY and returns *c. No check if RGB is made!
  *c\c = 1.0 - *c\r
  *c\m = 1.0 - *c\g
  *c\y = 1.0 - *c\b
  *c\type = #COLOR_CMY
 
  ProcedureReturn *c
EndProcedure

ProcedureDLL.l HSV2CMY(*c.Color) ; converts HSV-color *c to CMY and returns *c. No check if HSV is made!
  ; complement
  If *c\h >= 180.0
    *c\h - 180.0
  Else
    *c\h + 180.0
  EndIf
 
  HSV2RGB(*c) ; HSV2RGB of complement
 
  *c\type = #COLOR_CMY
 
  ProcedureReturn *c
EndProcedure

ProcedureDLL.l HSL2CMY(*c.Color) ; converts HSL-color *c to CMY and returns *c. No check if HSL is made!
  ; complement
  If *c\h >= 180.0
    *c\h - 180.0
  Else
    *c\h + 180.0
  EndIf
 
  HSL2RGB(*c) ; HSL2RGB of complement
 
  *c\type = #COLOR_CMY
 
  ProcedureReturn *c
EndProcedure

ProcedureDLL.l Color2CMY(*c.Color) ; converts *c from any color-type to CMY and returns *c
  Select *c\type
    Case #COLOR_RGB : ProcedureReturn RGB2CMY(*c)
    Case #COLOR_CMY : ProcedureReturn *c
    Case #COLOR_HSV : ProcedureReturn HSV2CMY(*c)
    Case #COLOR_HSL : ProcedureReturn HSL2CMY(*c)
  EndSelect
EndProcedure

ProcedureDLL.l ColorSetCMY(*c.Color, c.f, m.f, y.f) ; sets *c to the CMY-color given by c,m,y, each in range [0.0, 1.0] (no check is made) and returns *c
  *c\c = c
  *c\m = m
  *c\y = y
  *c\type = #COLOR_CMY
 
  ProcedureReturn *c
EndProcedure

;- change color to HSV
ProcedureDLL.l RGB2HSV(*c.Color) ; converts RGB-color *c to HSV and returns *c. No check if RGB is made!
  Protected r.f, g.f, b.f, max.f, min.f, delta.f
  r = *c\r
  g = *c\g
  b = *c\b
 
  max = Max3F(r,g,b)
  min = Min3F(r,g,b)
 
  ; get value
  *c\v = max
  If max <> 0.0
    delta = max - min
   
    ; get saturation
    *c\s = delta/max
   
    ; get hue
    If delta <> 0.0
      If r = max
        *c\h = (g-b)/delta
      ElseIf g = max
        *c\h = 2.0 + (b-r)/delta
      ElseIf b = max
        *c\h = 4.0 + (r-g)/delta
      EndIf
     
      *c\h * 60.0
     
      If *c\h<0.0
        *c\h + 360.0
      EndIf
    Else
      ; it's a gray-tone
      *c\h = 0 ; *c\h is even undefined
    EndIf
   
  Else
    ; it's black
    *c\s = 0
    *c\h = 0 ; *c\h is even undefined
  EndIf
 
  *c\type = #COLOR_HSV
 
  ProcedureReturn *c
EndProcedure

ProcedureDLL.l CMY2HSV(*c.Color) ; converts CMY-color *c to HSV and returns *c. No check if CMY is made!
  ; treat as RGB-color
  RGB2HSV(*c)
 
  ; complement
  If *c\h >= 180.0
    *c\h - 180.0
  Else
    *c\h + 180.0
  EndIf
 
  ProcedureReturn *c
EndProcedure

ProcedureDLL.l HSL2HSV(*c.Color) ; converts HSL-color *c to HSV and returns *c. No check if HSL is made!
  ProcedureReturn RGB2HSV(HSL2RGB(*c)) ; it's the easiest, though not fastet way
EndProcedure

ProcedureDLL.l Color2HSV(*c.Color) ; converts *c from any color-type to HSV And returns *c
  Select *c\type
    Case #COLOR_RGB : ProcedureReturn RGB2HSV(*c)
    Case #COLOR_CMY : ProcedureReturn CMY2HSV(*c)
    Case #COLOR_HSV : ProcedureReturn *c
    Case #COLOR_HSL : ProcedureReturn HSL2HSV(*c)
  EndSelect
EndProcedure

ProcedureDLL.l ColorSetHSV(*c.Color, h.f, s.f, v.f) ; sets *c to the HSV-color given by h in range [0.0, 360.0] and s,v in range [0.0, 1.0] (no check is made) and returns *c
  If h = 360.0
    h = 0
  EndIf
 
  *c\h = h
  *c\s = s
  *c\v = v
  *c\type = #COLOR_HSV
 
  ProcedureReturn *c
EndProcedure


;- change color to HSL
ProcedureDLL.l RGB2HSL(*c.Color) ; converts RGB-color *c to HSL and returns *c. No check if RGB is made!
  Protected r.f, g.f, b.f, max.f, min.f, delta.f
  r = *c\r
  g = *c\g
  b = *c\b
 
  max = Max3F(r,g,b)
  min = Min3F(r,g,b)
  delta = max - min
 
  If delta <> 0.0
    ; get lightness
    *c\l = (max + min) / 2.0
   
    ; get saturation
    If *c\l <= 0.5
      *c\s = delta/(max+min)
    Else
      *c\s = delta/(2-max-min)
    EndIf
   
    ; get hue
    If r = max
      *c\h = (g-b)/delta
    ElseIf g = max
      *c\h = 2.0 + (b-r)/delta
    ElseIf b = max
      *c\h = 4.0 + (r-g)/delta
    EndIf
   
    *c\h * 60.0
   
    If *c\h<0.0
      *c\h + 360.0
    EndIf
  Else
    ; it's black
    *c\s = 0
    *c\h = 0 ; *c\h is even undefined
  EndIf
 
  *c\type = #COLOR_HSL
 
  ProcedureReturn *c
EndProcedure

ProcedureDLL.l CMY2HSL(*c.Color) ; converts CMY-color *c to HSL and returns *c. No check if CMY is made!
  ; treat as RGB-color
  RGB2HSL(*c)
 
  ; complement
  If *c\h >= 180.0
    *c\h - 180.0
  Else
    *c\h + 180.0
  EndIf
 
  ProcedureReturn *c
EndProcedure

ProcedureDLL.l HSV2HSL(*c.Color) ; converts HSV-color *c to HSL and returns *c. No check if HSV is made!
  ProcedureReturn RGB2HSL(HSV2RGB(*c)) ; it's the easiest, though not fastet way
EndProcedure

ProcedureDLL.l Color2HSL(*c.Color) ; converts *c from any color-type to HSL and returns *c
  Select *c\type
    Case #COLOR_RGB : ProcedureReturn RGB2HSL(*c)
    Case #COLOR_CMY : ProcedureReturn CMY2HSL(*c)
    Case #COLOR_HSV : ProcedureReturn HSV2HSL(*c)
    Case #COLOR_HSL : ProcedureReturn *c
  EndSelect
EndProcedure

ProcedureDLL.l ColorSetHSL(*c.Color, h.f, l.f, s.f) ; sets *c to the HSL-color given by h in range [0.0, 360.0[ and l,s in range [0.0, 1.0] (no check is made) and returns *c
  *c\h = h
  *c\l = l
  *c\s = s
  *c\type = #COLOR_HSL
 
  ProcedureReturn *c
EndProcedure

;- change color to PureBasic's RGB
ProcedureDLL.l ColorRGBFast(*c.Color) ; converts *c to RGB and returns a Purebasic-RGB-colorcode same as returned by PB's RGB()
  Color2RGB(*c)
  ProcedureReturn RGB(255 * *c\r, 255 * *c\g, 255 * *c\b)
EndProcedure

ProcedureDLL.l ColorRGB(*c.Color) ; converts an internal copy of *c to RGB and returns a Purebasic-RGB-colorcode same as returned by PB's RGB()
  Protected *cc.Color, rgb.l
  *cc = ColorCopy(*c)
  Color2RGB(*cc)
  rgb = RGB(255 * *cc\r, 255 * *cc\g, 255 * *cc\b)
  FreeMemory(*cc)
  ProcedureReturn rgb
EndProcedure


;-
;- debug test functionality
;-
Procedure.l DebugTestFunctionality()
  ; RGB <-> CMY
  For i=0 To 10000
    ColorSetRGB(c.Color, Random(100)/100.0, Random(100)/100.0, Random(100)/100.0)
    *c2.Color = Color2RGB(Color2CMY(ColorCopy(c)))
   
    If IsSameColors(c, *c2, 0.1) = #False
      Debug "ERROR RGB <-> CMY"
      End
    EndIf
    FreeMemory(*c2)
  Next
 
  ; RGB <-> HSV
  For i=0 To 10000
    ColorSetRGB(c.Color, Random(100)/100.0, Random(100)/100.0, Random(100)/100.0)
    *c2.Color = Color2RGB(Color2HSV(ColorCopy(c)))
   
    If IsSameColors(c, *c2, 0.1) = #False
      Debug "ERROR RGB <-> HSV"
      End
    EndIf
    FreeMemory(*c2)
  Next
 
  ; RGB <-> HSL
  For i=0 To 10000
    ColorSetRGB(c.Color, Random(100)/100.0, Random(100)/100.0, Random(100)/100.0)
    *c2.Color = Color2RGB(Color2HSL(ColorCopy(c)))
   
    If IsSameColors(c, *c2, 0.1) = #False
      Debug "ERROR RGB <-> HSL"
      End
    EndIf
    FreeMemory(*c2)
  Next
 
  ; CMY <-> HSV
  For i=0 To 10000
    ColorSetCMY(c.Color, Random(100)/100.0, Random(100)/100.0, Random(100)/100.0)
    *c2.Color = Color2CMY(Color2HSV(ColorCopy(c)))
   
    If IsSameColors(c, *c2, 0.1) = #False
      Debug "ERROR CMY <-> HSV"
      End
    EndIf
    FreeMemory(*c2)
  Next
 
  ; CMY <-> HSL
  For i=0 To 10000
    ColorSetCMY(c.Color, Random(100)/100.0, Random(100)/100.0, Random(100)/100.0)
    *c2.Color = Color2CMY(Color2HSL(ColorCopy(c)))
   
    If IsSameColors(c, *c2, 0.1) = #False
      Debug "ERROR CMY <-> HSL"
      End
    EndIf
    FreeMemory(*c2)
  Next
 
  ; HSV <-> HSL
  For i=0 To 10000
    ColorSetHSV(c.Color, Random(360)/100.0, Random(100)/100.0, Random(100)/100.0)
    *c2.Color = Color2HSV(Color2HSL(ColorCopy(c)))
   
    If IsSameColors(c, *c2, 0.1) = #False
      Debug "ERROR HSV <-> HSL"
      End
    EndIf
    FreeMemory(*c2)
  Next
 
  Debug "All Tests done."
EndProcedure

;Goto example3

;-
;- example 1
;-
example1:

ColorSetRGB(rgbCol.Color, 0.0, 0.0, 1.0) ; full blue
s.s = "Create blue, decrease its saturation towards gray and move it" + #CRLF$
s.s + "slightly towards green without changing it's intensity" + #CRLF$ + #CRLF$

s.s + "Original color: " + ColorToStr(rgbCol) + #CRLF$

; we dont' like this green, we want to make it a little bit darker and remove it's saturation
Color2HSL(rgbCol)

s.s + "Original color: " + ColorToStr(rgbCol) + #CRLF$
rgbCol\h - 30 ; be careful to stay in range [0, 360[. Here we know h is 240
rgbCol\s = 0.5

s.s + "Modified color: " + ColorToStr(rgbCol) + #CRLF$
Color2RGB(rgbCol)
s.s + "Modified color: " + ColorToStr(rgbCol) + #CRLF$


MessageRequester("Color example 1/3:", s)

MessageRequester("Color example 2/3:", "Click OK to run a HSL-demonstration in fullscreen.")
;-
;- example 2
;-
example2:

InitSprite()
InitKeyboard()

OpenScreen(1024, 768, 32, "Color-example")

framecounter = 0
fps = 0
lastFrametimer = 0

Repeat
  ; fps-calculation
  framecounter+1
  If ElapsedMilliseconds() - lastFrametimer > 1000
    fps = framecounter
    framecounter = 0
    lastFrametimer = ElapsedMilliseconds()
  EndIf
 
  ; draw the colorbars
  ClearScreen(RGB(0, 0, 50))
  StartDrawing(ScreenOutput())
  FrontColor(RGB(255,255,255))
  DrawingMode(1)
  DrawText(10,10, "HSL-colors for 1.440.000 individual colored pixels at " + Str(fps) + " fps. Press ESC to exit.")
 
  ; create 1.440.000 combinations of hue, sat and lightness and display them
  sat.f = 0.05
  While sat <= 1.0
    lig.f = 0
    While lig <= 1.0
      hue.f = 0
      While hue < 360.0
        ; create a new hsl-colored pixel (you might fill your structure manually, too)
        ColorSetHSL(HSLCol.Color, hue, sat, lig)
       
        ; draw it on the screen after converting to PB's RGB
        Plot(152 + 2*hue, 180 + 20*lig + 400*sat, ColorRGBFast(HSLCol))
       
        hue + 0.5
      Wend
      lig + 0.05
    Wend
    sat + 0.1
  Wend
  StopDrawing()
  FlipBuffers()
 
  Delay(10)
 
  ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)
CloseScreen()

;-
;- example 3
;-
example3:

Procedure.l GetContrastedPBColor(red.l, green.l, blue.l)
  Protected col.Color
  ColorSetRGB(col.Color, red/255.0, green/255.0, blue/255.0)
  Color2HSV(col)
  ColorComplement(col) ; build the normal complement
 
  ; modify saturation and value
  ; you might experiment with those to achieve other results
  col\s + 0.5
  If col\s > 1.0
    col\s - 1.0
  EndIf

  col\v + 0.5
  If col\v > 1.0
    col\v - 1.0
  EndIf

  Color2RGB(col)
  ProcedureReturn RGB(col\r*255, col\g*255, col\b*255)
EndProcedure

CreateImage(0, 500, 500)
For i=0 To 9
  Select i
    Case 0 : col.l = $000000
    Case 1 : col.l = $FFFFFF
    Case 2 : col.l = $7F7F7F
    Case 3 : col.l = $660000
    Case 4 : col.l = $00FF00
    Case 5 : col.l = $000033
    Case 6 : col.l = $FF9900
    Case 7 : col.l = $FF33FF
    Case 8 : col.l = $3754A9
    Case 9 : col.l = $9F3F20
  EndSelect
 
  contrCol = GetContrastedPBColor(Red(col), Green(col), Blue(col))
 
  StartDrawing(ImageOutput(0))
  Box(0, i*50, 500, 50, col)
  DrawingMode(#PB_2DDrawing_Transparent)
    DrawText(10, i*50 + 20, "This is just an example-text in a color contrasted to the background", contrCol)
  StopDrawing()
Next

OpenWindow(0, 0, 0, 500, 500, "Color example 3/3:")
CreateGadgetList(WindowID(0))
ImageGadget(0, 0, 0, 500, 500, ImageID(0))
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Last edited by Froggerprogger on Mon Jan 21, 2008 10:34 am, edited 2 times in total.
%1>>1+1*1/1-1!1|1&1<<$1=1
dige
Addict
Addict
Posts: 1391
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Post by dige »

Very nice. Thx Frogger!
danraymond
User
User
Posts: 43
Joined: Wed Jun 28, 2006 6:02 am

Thankx frogger

Post by danraymond »

Thanks was looking for this info.

Just a question;

When you shutdown WIndows XP the screen fades from colour to greyscale before the shutdown menu pops up.

Any ideas how to do that in PB? (the shifting of the monitor colors to greyscale)

thanks


Dan Raymond
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post by thefool »

You take the average of r+g+b of each pixel.

Code: Select all

;**********************
;By Daniel M (thefool)
;**********************

  Structure myBITMAPINFO
    bmiHeader.BITMAPINFOHEADER
    bmiColors.RGBQUAD[1]
  EndStructure 

Procedure GrayImage(image) ;Grayscale!

  
  hBmp=ImageID(image)
  
  If hBmp 
    
    imageWidth=ImageWidth(image)
    imageHeight=ImageHeight(image)
    
    mem=AllocateMemory(imageWidth*imageHeight*4)
    bmi.myBITMAPINFO 
    bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
    bmi\bmiHeader\biWidth = imageWidth
    bmi\bmiHeader\biHeight = imageHeight
    bmi\bmiHeader\biPlanes = 1
    bmi\bmiHeader\biBitCount = 32
    bmi\bmiHeader\biCompression = #BI_RGB 
    
    hdc = StartDrawing(ImageOutput(image))
    Debug hdc
    GetDIBits_(hdc,hBmp,0,imageHeight,mem,bmi,#DIB_RGB_COLORS)
    
    *pixels.LONG = mem
    For A = 1 To imageWidth*(imageHeight)
      r=Red(*pixels\l)
      g=Green(*pixels\l)
      b=Blue(*pixels\l)
      
      average=(r+g+b)/3
      *pixels\l=RGB(average,average,average)
      
      *pixels + 4
    Next A
    
  SetDIBits_(hdc,hBmp,0,imageHeight,mem,bmi,#DIB_RGB_COLORS) ;<> 0
  StopDrawing()
  ProcedureReturn 1  
EndIf
  
EndProcedure
now; to get the monitor do that you could take a screenshot, show it on top and let it fade to greyscale.
danraymond
User
User
Posts: 43
Joined: Wed Jun 28, 2006 6:02 am

BUt windoze don't take screenshot

Post by danraymond »

Dear thefool,

thanx so much for info, hadn't realised its was just the rgb average and I can see how it works now on an image.

but if you have XP hit the "turn off computer" selcetion and just wait. It slowly fades to grey scale. And yet returns to color if you cancel.

that's what I want to do!

any further help greatly appreciated.

Dan Raymond
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post by thefool »

im not 100% sure here; but you could actually make a "morph"/"fade" or "blend"algorithm. then you got 2 images; colours & not and then you slowly fade over to the one.

Eventually you can layer them, having the greyscale at 0% transperrency going to 100%. (alpha?)

another way:
when calculated the greyscale, you compare each pixel and then if the greyscale pic r, g and b is more or less you add or remove 1.

Now you just do this till every pixel are equal (that would be the fade algo)
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: Colormodels: RGB, CMY, HLS, HSL (HLS, HSI)

Post by c4s »

@Froggerprogger
This deserves a bump: Great code, thank you!
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
Post Reply