Il giorno 04/giu/2015, alle ore 11.38, Michael Tiedtke ha scritto:

> All I wanted to do was to compute two or three color steps between two colors 
> to fade from one to the other. Usually I would this with available 
> compositing methods but in the current case it's easier to do maths and just 
> redraw with the new color. The usual method to calculate the color steps is 
> the linear one 
> (http://stackoverflow.com/questions/27532/generating-gradients-programmatically).
>  Wouldn't it be nice to define new methods for the usual arithmetic operation 
> generics '(+ - * / < > = abs) to do color arithmetic?
> 
> Example:
> 
> (define color-1 (make-color r1 g1 b1))
> (define color-2 (make-color r2 g2 b2))
> 
> (define color-delta (/ (- color-2 color-1) number-of-steps))
> (let loop ((color color-1))
>   (cons color [if (= color color-2) '() (loop (+ color color-delta))] ))
> 
> NB It's not the best example out there: delta should be computed like any 
> other delta as the absolute numerical distance
>  where the return value of the subtraction might be a negative 
> color-distance% object but colors usually are only
>  positive. Perhaps it's better to do without bigger than and less than when 
> it comes to colors.
> 
> Before I go ahead and just do it I wanted to ask:
> 
> 1) Does such a thing exist somewhere for Scheme or Racket (I couldn't find 
> anything)
>      The only example I found was: 
> https://www.wolframalpha.com/examples/ColorArithmetic.html
> 
> 2) Does anyone know how this proposed color arithmetic would interact with 
> color management / color spaces?
> 2a) Is it true that non-linear color arithmetic produces better results for 
> gradients?
> 
> 3) Any suggestions regarding the implementation of the generics?
> 
> 4) Both Cairo and Quartz do have more sophisticated compositing methods - but 
> they do not expose this low level functionality?
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



Here is a first implementation: it's a bit awkward but does the job.

1) Some things that do not work: I can't provide + - etc. because this results 
in really strange error messages where send doesn't see a color% object but a 
number / rgb component at (define (rgb-delta rgb-1 rgb-2) (vector (- (send 
rgb-1 red) ...

2) I can't compare colors in Racket - two (0 0 0) rgb color objects are neither 
equal? nor object=?. Perhaps I should add an color equal predicate ...


#lang racket

;; Module In
(require racket/draw  ; color%
         plot/utils   ; vector calculus)

;;;
;;; Delta Color: Color Distance Arithmetic
;;;
;;; Rationale: Colors are abstract concepts in the first place which
;;; we can't calculate with. Color distances are easy to define even
;;; for abstract unknown color spaces. The current definition is:
;;;
;;;  If delta is the difference between color 2 and color 1, then
;;;   you get color 2 by adding the delta to color 1.
;;;
;;;  If you divide delta by n and add delta n times to color 1 you
;;;   will get n color steps representing a smooth gradient from color
;;;   1 to color 2.
;;;
;;; Everything else is currently undefined. This Color Distance
;;; Arithmetic is currently only implemented for the usual virtual
;;; interval integer RGB color space (RGB32). Color Deltas are vectors
;;; of exact numbers. For this you can calculate with endless (memory
;;; limited) precision between the color points in the color space.
;;;
;;; Domain Entry and Exit:
;;;
;;;    color - color -> color-delta
;;;    color + color-delta -> color
;;;    color - color-delta -> color


;; RGB Delta: Color Distance in our virtual RGB color space
;; The red, green and blue methods return byte data but we
;; use them as exact integers to allow further computation.
(define (rgb-delta rgb-1 rgb-2)
  (vector (- (send rgb-1 red)   (send rgb-2 red))
          (- (send rgb-1 green) (send rgb-2 green))
          (- (send rgb-1 blue)  (send rgb-2 blue)) ))

(define (delta? a)
  (and (vector? a)
       (= (vector-length a) 3)))
(define (red delta) (vector-ref delta 0))
(define (green delta) (vector-ref delta 1))
(define (blue delta) (vector-ref delta 2))


;; RGB Delta Plus: Domain Exit
(define (rgb-delta-plus rgb delta)
  (make-color (+ (send rgb red)   (red delta))
              (+ (send rgb green) (green delta))
              (+ (send rgb blue)  (blue delta))))

;; RGB Delta Minus: Domain Exit
(define (rgb-delta-minus rgb delta)
  (make-color (- (send rgb red) (red delta))
              (- (send rgb green) (green delta))
              (- (send rgb blue) (blue delta))))


(define (color? a) (is-a? a color%))

(define (subtract a b)
  (cond ([and (color? a) (color? b)] (rgb-delta a b))
        ([and (color? a) (delta? b)] (rgb-delta-minus a b))
        ([and (delta? a) (delta? b)] (v- a b))
        (else
         (error "Delta Color: subtract: out of domain error"))))

(define divide v/)
(define multiply v*)
(define (add a b)
  (cond ([and (delta? a) (delta? b)] (v+ a b)) ; intra-domain
        ([and (delta? a) (color? b)] ; domain exit
         (rgb-delta-plus b a))
        ([and (color? a) (delta? b)]
         (rgb-delta-plus a b))
        (else
         (error "Delta Color: add: out of domain error"))))


;; Module Out
(provide add subtract multiply divide ; suggested prefix-in: deco-
         delta?)

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to