-
Notifications
You must be signed in to change notification settings - Fork 5
/
ciexyy.lisp
127 lines (108 loc) · 4.44 KB
/
ciexyy.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
;;; ciexyy.lisp --- CIE xyY color space.
;; Copyright (C) 2014 Ralph Schleicher
;; Redistribution and use in source and binary forms, with or without
;; modification, are permitted provided that the following conditions
;; are met:
;;
;; * Redistributions of source code must retain the above copyright
;; notice, this list of conditions and the following disclaimer.
;;
;; * Redistributions in binary form must reproduce the above copyright
;; notice, this list of conditions and the following disclaimer in
;; the documentation and/or other materials provided with the
;; distribution.
;;
;; * Neither the name of the copyright holder nor the names of its
;; contributors may be used to endorse or promote products derived
;; from this software without specific prior written permission.
;;
;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
;; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
;; COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
;; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
;; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
;; CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
;; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
;; ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
;; POSSIBILITY OF SUCH DAMAGE.
;;; Code:
(in-package :rs-colors)
(defclass ciexyy-color (color-object)
((x*
:initarg :x*
:initform 0
:type (real 0 1)
:documentation "First chromaticity coordinate, default zero.")
(y*
:initarg :y*
:initform 0
:type (real 0 1)
:documentation "Second chromaticity coordinate, default zero.")
(y
:initarg :y
:initform 0
:type (real 0)
:documentation "Second tristimulus value, default zero."))
(:documentation "Color class for the CIE xyY color space."))
(defmethod color-coordinates ((color ciexyy-color))
(with-slots (x* y* y) color
(values x* y* y)))
(defun make-ciexyy-color (x* y* y)
"Create a new color in the CIE xyY color space.
Arguments X* and Y* are the chromaticity coordinates.
Argument Y is the second tristimulus value (luminance)."
(make-instance 'ciexyy-color :x* x* :y* y* :y y))
(defun ciexyy-from-ciexyz (x y z)
"Convert CIE XYZ color space coordinates
into CIE xyY color space coordinates."
(declare (type real x y z))
(let ((s (+ x y z)))
(declare (type real s))
(when (zerop s)
(error 'division-by-zero :operation 'ciexyy-from-ciexyz :operands (list x y z)))
(values (/ x s) (/ y s) y)))
(defun ciexyz-from-ciexyy (x* y* y)
"Convert CIE xyY color space coordinates
into CIE XYZ color space coordinates."
(declare (type real x* y* y))
(when (zerop y*)
(error 'division-by-zero :operation 'ciexyz-from-ciexyy :operands (list x* y* y)))
(let ((s (/ y y*)))
(declare (type real s))
(values (* x* s) y (* (- 1 x* y*) s))))
(defgeneric ciexyy-color-coordinates (color)
(:documentation "Return the CIE xyY color space coordinates of the color.
Argument COLOR is a color object.
Values are the X and Y chromaticity coordinates and the Y tristimulus
value (luminance).")
(:method ((color ciexyy-color))
(color-coordinates color))
;; Otherwise, go via CIE XYZ.
(:method ((color color-object))
(multiple-value-call #'ciexyy-from-ciexyz
(ciexyz-color-coordinates color))))
(defmethod ciexyz-color-coordinates ((color ciexyy-color))
(multiple-value-call #'ciexyz-from-ciexyy
(color-coordinates color)))
(defmethod update-instance-for-different-class :after ((old color-object) (new ciexyy-color) &key)
(with-slots (x* y* y) new
(multiple-value-setq (x* y* y)
(ciexyy-color-coordinates old))))
(defmethod absolute-luminance ((color ciexyy-color))
(slot-value color 'y))
(defmethod normalize-color ((color ciexyy-color) &key (white 1) (black 0))
(let ((yw (absolute-luminance white))
(yk (absolute-luminance black)))
(with-slots (y) color
(setf y (/ (- y yk) (- yw yk)))))
color)
(defmethod absolute-color ((color ciexyy-color) &key (white 1) (black 0))
(let ((yw (absolute-luminance white))
(yk (absolute-luminance black)))
(with-slots (y) color
(setf y (+ yk (* y (- yw yk))))))
color)
;;; ciexyy.lisp ends here