;; ;; starlet/colours.scm ;; ;; Copyright © 2020-2021 Thomas White ;; ;; This file is part of Starlet. ;; ;; Starlet is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;; (define-module (starlet colours) #:use-module (oop goops) #:use-module (ice-9 exceptions) #:export ( colour? cmy rgb colour-as-cmy colour-as-rgb colour-as-rgbw cyan magenta yellow red green blue interpolate-colour white)) (define-class () (type #:init-form (error "Colour type must be specified") #:init-keyword #:type #:getter colour-type) (value #:init-form (error "Colour value must be specified") #:init-keyword #:value #:getter colour-value)) (define (colour? c) (is-a? c )) (define cyan car) (define magenta cadr) (define yellow caddr) (define red car) (define green cadr) (define blue caddr) (define-method (display (col ) port) (format port "#< ~a ~a>" (colour-type col) (colour-value col))) (define (three-sf n) (/ (round (* (exact->inexact n) 10)) 10)) (define-method (write (col ) port) (let ((cmy (colour-as-cmy col))) (format port "(cmy ~a ~a ~a)" (three-sf (cyan cmy)) (three-sf (magenta cmy)) (three-sf (yellow cmy))))) (define (cmy c m y) (make #:type 'cmy #:value (list c m y))) (define (rgb r g b) (make #:type 'rgb #:value (list r g b))) (define white (cmy 0 0 0)) (define (colour-as-rgb col) (let ((val (colour-value col))) (case (colour-type col) ((rgb) val) ((cmy) (list (- 100 (red val)) (- 100 (green val)) (- 100 (blue val)))) (else (raise-exception (make-exception (make-exception-with-message "Unrecognised colour type") (make-exception-with-irritants (colour-type col)))))))) (define (colour-as-rgbw col) (let ((rgb (colour-as-rgb col))) (let ((w (apply min rgb))) (list (- (red rgb) w) (- (green rgb) w) (- (blue rgb) w) w)))) (define (colour-as-cmy col) (let ((val (colour-value col))) (case (colour-type col) ((cmy) val) ((rgb) (list (- 100 (red val)) (- 100 (green val)) (- 100 (blue val)))) (else (raise-exception (make-exception (make-exception-with-message "Unrecognised colour type") (make-exception-with-irritants (colour-type col)))))))) (define (interpolate-cmy a b frac) (let ((cmy1 (colour-as-cmy a)) (cmy2 (colour-as-cmy b))) (cmy (+ (cyan cmy1) (* frac (- (cyan cmy2) (cyan cmy1)))) (+ (magenta cmy1) (* frac (- (magenta cmy2) (magenta cmy1)))) (+ (yellow cmy1) (* frac (- (yellow cmy2) (yellow cmy1))))))) (define* (interpolate-colour a b frac #:key (interpolation-type 'linear-cmy)) (case interpolation-type ((linear-cmy) (interpolate-cmy a b frac)) (else (raise-exception (make-exception (make-exception-with-message "Unrecognised colour interpolation type") (make-exception-with-irritants interpolation-type))))))