[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re- Colours, or how to make d



To:     Charlene Bloch Abrams    bloch@informatics.wustl.edu
        Steve Strassmann         <straz@cambridge.apple.com>
cc:     info-mcl
From:   Steve Mitchell
Date:   4/27/92
 
Subject: Colours, or how to make dilute cyanide
 
>  [Charlene:]
>  >  I'm using 2.0f2 and am trying to do a very simple sort of animation
>  >  using the quickdraw interface available. One of the things I want to
>  >  do is for the coloured dots in my window to fade in intensity until
>  >  they eventually disappear. I noticed that in the Control Panel when
>  >  you fool around with colours, and specifically decrease the saturation,
>  >  this would give the correct effect; however decreasing intensity
corresponds
>  >  to decreasing 2 of the red-green-blue components of the particular
>  >  colours at different rates.
>  >  My question is this: does anyone have soem sort of a mapping (or know
where
>  >  I can find said animal) which will tell how to alter the r-g-b components
>  >  of a colour in order to decrease its intensity?
 
You didn't say what color your background is. It matters:
 - to fade a color to white, you decrease Saturation, and
 - to fade a color to black, you decrease Brightness
 
In Color Picker terms, decreasing Saturation corresponds to moving
towards the center of the color wheel, and decreasing Brightness
corresponds to dragging the slider downwards.
 
[Steve Strassmann:]
>  [...]
>  A simplified rule of thumb: to get the luminosity (greyscale brightness)
>  of a color, take  (.2R + .7G + .1B). The eye is much more sensitive
>  to brightness changes in green than in red or blue, so that's what a
>  black and white TV does when it displays a color video signal.
>  [...]
 
The Mac RGB Color Model's number ranges already adjust for the relative
brightness of the primary colors - greys are represented by R = G = B,
and the ranges are linearized, so that (0.5, 0.5, 0.5) is 50% grey.
 
The color picker gives the HSV numbers as well as the RGB numbers.
If you pick white, and pull down the Brightness slider (maintaining
Hue and Saturation, but dropping "Value"), you'll see all the RGB
values drop LINEARLY TOGETHER, through the greys.
 
On the other hand, if you pick pure yellow (which is Red and Green)
at full brightness and reduce the Saturation, the Blue component
will increase; nothing else will change.
 
The Color Picker, the Mac color models, and xlating between them are
documented in Inside Mac, Volume 6, chapter 19 (which supersedes the
info in Volume 5).
 
Following is some code to play with. It takes a color in RGB space,
maps it to HSV space so you can scale the Saturation and/or
Brightness, and maps it back into RGB space for display:
 
;;; - - - - - - - - - - - - - - - - - - - - - - -
 
;; Excerpted from ":Library:Interfaces:QuickDraw.lisp"
(defrecord RGBColor
   (red :unsigned-integer)              ; magnitude of red component
   (green :unsigned-integer)            ; magnitude of green component
   (blue :unsigned-integer)             ; magnitude of blue component
   )
;; Excerpted from ":Library:Interfaces:Picker.lisp",
;; (modified slightly; IM-VI: p9-9 says SmallFracts are UNSIGNED):
(defrecord HSVColor
   (hue :unsigned-integer)        ; Fraction of circle, red at 0
   (saturation :unsigned-integer) ; 0-1, 0 for gray, 1 for pure color
   (value :unsigned-integer)      ; 0-1, 0 for black, 1 for max intensity
   )
(deftrap _hsv2rgb ((hcolor :hsvcolor) (rcolor (:pointer :rgbcolor)))
   nil
   (:stack-trap #xA82E hcolor rcolor (7 :signed-integer)))
(deftrap _rgb2hsv ((rcolor :rgbcolor) (hcolor (:pointer :hsvcolor)))
   nil
   (:stack-trap #xA82E rcolor hcolor (8 :signed-integer)))
 
(defun hsv-scale-sv (hsv-record s-factor v-factor)
  "Scale the saturation and brightness components of the HSV record,
clamping to 0-65535. Updates hsv-record, returns nothing."
  (let ((old-s (rref hsv-record :hsvcolor.saturation))
        (old-v (rref hsv-record :hsvcolor.value)))
    (let ((new-s (max 0 (min 65535 (round (* old-s s-factor)))))
          (new-v (max 0 (min 65535 (round (* old-v v-factor))))))
      (rset hsv-record :hsvcolor.saturation new-s)
      (rset hsv-record :hsvcolor.value new-v)))
  (values))
 
(defun rgb-scale-sv (rgb-record s-factor v-factor)
  "Scale the saturation and brightness of the RGB record.
Updates rgb-record, returns nothing."
  (rlet ((hsv-rec :hsvcolor :hue 0 :saturation 0 :value 0))
    (#_rgb2hsv rgb-record hsv-rec)
    (hsv-scale-sv hsv-rec s-factor v-factor)
    (#_hsv2rgb hsv-rec rgb-record)))
 
(defun test-saturation-brightness (color scale-pair-list &key (picker nil) (win
nil))
  "Display the color with its saturation and brightness scaled to different
values."
  (with-rgb (initial-rgb-rec color)
    (unless (or win picker)
      (error "Specify a win or picker."))
    (when win
      (set-back-color win color)
      (sleep 2))
    (if picker
      (catch-cancel (user-pick-color :color color)))
    (dolist (s-v scale-pair-list)
      (with-rgb (rgb-rec (rgb-to-color initial-rgb-rec))
        (rgb-scale-sv rgb-rec (first s-v) (second s-v))
        (when win
          (set-back-color win (rgb-to-color rgb-rec))
          (sleep 2))
        (if picker
          (catch-cancel (user-pick-color :color (rgb-to-color rgb-rec)))))))
  (values))
 
;;;yellow fades to white as saturation drops:
(test-saturation-brightness *yellow-color* '((0.8 1) (0.6 1) (0.4 1) (0.2 1) (0
1))
                            :picker nil :win (make-instance 'window :color-p
t))
;;re-run with *tan-color* to see tan fade to gray due to low initial brightness
;;re-run with :picker t to see the HSB values in the color picker
 
;;;yellow fades to black as brightness drops:
(test-saturation-brightness *yellow-color* '((1 0.8) (1 0.6) (1 0.4) (1 0.2) (1
0))
                            :picker nil :win (make-instance 'window :color-p
t))
;;re-run with :picker t to see the HSB values in the color picker
 
_Steve