Color quantization: Difference between revisions
Content added Content deleted
(Add Common Lisp implementation) |
m (Don't deduplicate colors/pixels) |
||
Line 139: | Line 139: | ||
(defun image->pixels (image) |
(defun image->pixels (image) |
||
(check-type image 8-bit-rgb-image) |
(check-type image 8-bit-rgb-image) |
||
(let |
(let (pixels) |
||
(do-pixels (y x) image |
(do-pixels (y x) image |
||
( |
(push (pixel* image y x) pixels)) |
||
pixels)) |
|||
collect p))) |
|||
(defun greatest-color-range (pixels) |
(defun greatest-color-range (pixels) |
||
Line 164: | Line 163: | ||
(defun median-cut (pixels target-num-colors) |
(defun median-cut (pixels target-num-colors) |
||
(assert (zerop (mod (log target-num-colors 2) 1))) |
(assert (zerop (mod (log target-num-colors 2) 1))) |
||
(if (or (= target-num-colors 1) ( |
(if (or (= target-num-colors 1) (null (rest pixels))) |
||
(list pixels) |
(list pixels) |
||
(let* ((channel (greatest-color-range pixels)) |
(let* ((channel (greatest-color-range pixels)) |
||
Line 174: | Line 173: | ||
(defun quantize-colors (pixels target-num-colors) |
(defun quantize-colors (pixels target-num-colors) |
||
( |
(let ((color-map (make-hash-table :test #'equal))) |
||
(dolist (bucket (median-cut pixels target-num-colors) color-map) |
|||
(loop for (r g b) in bucket |
|||
sum r into r-sum |
|||
sum g into g-sum |
|||
sum b into b-sum |
|||
count t into num-pixels |
|||
finally (let ((average (list (round r-sum num-pixels) |
|||
(round g-sum num-pixels) |
|||
(round b-sum num-pixels)))) |
|||
(dolist (pixel bucket) |
|||
(setf (gethash pixel color-map) average))))))) |
|||
finally (return color-map))) |
|||
(defun quantize-image (input-file output-file target-num-colors) |
(defun quantize-image (input-file output-file target-num-colors) |