root/trunk/projects/quickhoney/src/imageproc.lisp

Revision 3868, 6.3 KB (checked in by hans, 2 years ago)

Fix space between buttons.
Repair "full image" display window.
Automatically download iPhone pictures.

Line 
1(in-package :quickhoney.imageproc)
2
3(defparameter *button-size* 208)
4(defparameter *big-button-size* 318)
5
6(cl-interpol:enable-interpol-syntax)
7
8(defun corner-cutout-coords (image-width image-height radius)
9  "Return a list of coordinates that need to be made transparent or
10  colored in background color to get a rounded corner effect.
11  IMAGE-WIDTH and IMAGE-HEIGHT are the dimensions of the image, RADIUS
12  is the desired corner rounding radius.  The list of coordinates that
13  is returned is ordered by row and column so that DO-ROWS and
14  DO-PIXELS-IN-ROW can be used to iterate over the image and pop
15  coordinate pairs off the front of the list at the same time."
16  (let ((radius (floor radius))
17        (diameter (+ 1 radius radius))
18        coords)
19    (assert (and (>= image-width diameter)
20                 (>= image-height diameter)))
21    (with-image (circle diameter diameter)
22      (let ((white (allocate-color 255 255 255 :image circle))
23            (black (allocate-color 0 0 0 :image circle)))
24        (fill-image 0 0 :color white :image circle)
25        (draw-filled-circle radius radius radius :color black :image circle)
26        (do-rows (y circle)
27          (do-pixels-in-row (x)
28            (when (eql (raw-pixel) white)
29              (push (list (if (< x radius) x (+ (- image-width diameter) x))
30                          (if (< y radius) y (+ (- image-height diameter) y)))
31                    coords))))))
32    (nreverse coords)))
33
34(defun corner-image (&key (image *default-image*)
35                          (radius (/ (max (image-width image) (image-height image)) 40))
36                          corner-color)
37  (with-default-image (image)
38    (unless corner-color
39      (setf (save-alpha-p) t
40            corner-color (if (true-color-p) #x7f000000
41                             (or (transparent-color)
42                                 (allocate-color 255 255 255 :alpha 127)
43                                 (error "can't allocate transparent color for button")))
44            (transparent-color) corner-color))
45    (let ((coords (corner-cutout-coords (image-width) (image-height) radius)))
46      (destructuring-bind (x-tx y-tx) (car coords)
47        (do-rows (y)
48          (do-pixels-in-row (x)
49            (when (and (eql x x-tx)
50                       (eql y y-tx))
51              (setf (raw-pixel) corner-color)
52              (when (cdr coords)
53                (setf coords (cdr coords)
54                      x-tx (caar coords)
55                      y-tx (cadar coords))))))))))
56
57(define-imageproc-handler cutout-button (input-image
58                                         &optional keyword
59                                                   (background-color "ffffff")
60                                                   (button-width "208")
61                                                   (button-height "208")
62                                                   (radius "8")
63                                                   category)
64  (let* ((button-width (parse-integer button-width))
65         (button-height (parse-integer button-height))
66         (button-image (create-image button-width button-height t))
67         (category (bknr.utils:make-keyword-from-string category))
68         (scale-factor (funcall (if (eq :pixel category)
69                                    #'ceiling #'identity)
70                                (if (> (/ (image-width input-image) (image-height input-image))
71                                       (/ button-width button-height))
72                                    (/ button-height (image-height input-image))
73                                    (/ button-width (image-width input-image)))))
74         (cutout-width (floor (/ button-width scale-factor)))
75         (cutout-height (floor (/ button-height scale-factor)))
76         (radius (parse-integer radius)))
77    (copy-image input-image button-image
78                (floor (- (image-width input-image) cutout-width) 2)
79                (if (eq :pixel category)
80                    (floor (- (image-height input-image) cutout-height) 2)
81                    0)
82                0 0
83                cutout-width cutout-height
84                :resize t :resample t
85                :dest-width button-width :dest-height button-height)
86    (when keyword
87      (let ((type-store-image (store-image-with-name (format nil "type-~(~A~)" keyword))))
88        (unless type-store-image
89          (error "can't find type image for keyword ~A" keyword))
90        (with-store-image (type-image type-store-image)
91          (copy-image type-image button-image
92                      0 0
93                      0 0
94                      (image-width type-image) (image-height type-image)))))
95    (unless (zerop radius)
96      (corner-image :image button-image
97                    :radius radius
98                    :corner-color (parse-color background-color :image button-image)))
99    button-image))
100
101(define-imageproc-handler center-thumbnail (input-image width height)
102  (setq width (parse-integer width)
103        height (parse-integer height))
104  (unless (or (> width (image-width input-image))
105              (> height (image-width input-image)))
106    (let ((thumbnail-image (create-image width height t)))
107      (copy-image input-image thumbnail-image
108                  (round (/ (- (image-width input-image) width) 2))
109                  (round (/ (- (image-height input-image) height) 2))
110                  0 0
111                  width height)
112      thumbnail-image)))
113
114(defparameter +news-image-width+ 486
115  "Width of news images")
116(defparameter +news-image-corner-radius+ 8
117  "Corner radius for news images")
118
119(define-imageproc-handler news-article-cutout (input-image)
120  (let* ((image-height (floor (* +news-image-width+
121                                 (/ (image-height input-image) (image-width input-image)))))
122         (output-image (create-image +news-image-width+ image-height t)))
123    (copy-image input-image output-image
124                0 0
125                0 0
126                +news-image-width+ image-height
127                :resize t :resample t
128                :dest-width +news-image-width+ :dest-height image-height)
129    (corner-image :image output-image
130                  :radius +news-image-corner-radius+
131                  :corner-color (allocate-color 255 255 255 :image output-image))
132    output-image))
133
134(define-imageproc-handler download (input-image filename)
135  (setf (tbnl:header-out :content-disposition) #?"attachment; filename=$(filename)")
136  input-image)
Note: See TracBrowser for help on using the browser.