root/trunk/thirdparty/cl-gd-0.5.6/misc.lisp

Revision 2429, 11.5 kB (checked in by hhubner, 1 year ago)

Fix buglet with DO-PIXELS/GET-PIXEL that made SBCL choke.

Line 
1 ;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-GD; Base: 10 -*-
2 ;;; $Header: /usr/local/cvsrep/gd/misc.lisp,v 1.15 2007/01/01 23:41:00 edi Exp $
3
4 ;;; Copyright (c) 2003-2007, Dr. Edmund Weitz.  All rights reserved.
5
6 ;;; Redistribution and use in source and binary forms, with or without
7 ;;; modification, are permitted provided that the following conditions
8 ;;; are met:
9
10 ;;;   * Redistributions of source code must retain the above copyright
11 ;;;     notice, this list of conditions and the following disclaimer.
12
13 ;;;   * Redistributions in binary form must reproduce the above
14 ;;;     copyright notice, this list of conditions and the following
15 ;;;     disclaimer in the documentation and/or other materials
16 ;;;     provided with the distribution.
17
18 ;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
19 ;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 ;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 ;;; ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 ;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 ;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
24 ;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 ;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 ;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 ;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 ;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 (in-package :cl-gd)
31
32 (defun interlacedp (&optional (image *default-image*))
33   "Returns whether IMAGE will be stored in an interlaced fashion."
34   (check-type image image)
35   (not (zerop (gd-image-get-interlaced (img image)))))
36
37 (defun (setf interlacedp) (interlaced &optional (image *default-image*))
38   "Sets whether IMAGE will be stored in an interlaced fashion."
39   (check-type image image)
40   (gd-image-interlace (img image) (if interlaced 1 0))
41   interlaced)
42
43 (defun differentp (image1 image2)
44   "Returns false if the two images won't appear different when
45 displayed. Otherwise the return value is a list of keywords describing
46 the differences between the images."
47   (check-type image1 image)
48   (check-type image2 image)
49   (let ((result (gd-image-compare (img image1) (img image2))))
50     (cond ((zerop (logand +gd-cmp-image+ result))
51             nil)
52           (t
53             (loop for (gd-flag keyword) in `((,+gd-cmp-num-colors+
54                                               :different-number-of-colors)
55                                              (,+gd-cmp-color+
56                                               :different-colors)
57                                              (,+gd-cmp-size-x+
58                                               :different-widths)
59                                              (,+gd-cmp-size-y+
60                                               :different-heights)
61                                              (,+gd-cmp-transparent+
62                                               :different-transparent-colors)
63                                              (,+gd-cmp-background+
64                                               :different-background-colors)
65                                              (,+gd-cmp-interlace+
66                                               :different-interlace-settings)
67                                              (,+gd-cmp-true-color+
68                                               :true-color-versus-palette-based))
69                   when (plusp (logand gd-flag result))
70                   collect keyword)))))
71
72 (defun copy-image (source destination
73                    source-x source-y
74                    dest-x dest-y
75                    width height
76                    &key resample
77                         rotate angle
78                         resize dest-width dest-height
79                         merge merge-gray)
80   "Copies \(a part of) image SOURCE into image DESTINATION. Copies the
81 rectangle with the upper left corner \(SOURCE-X,SOURCE-Y) and size
82 WIDTH x HEIGHT to the rectangle with the upper left corner
83 \(DEST-X,DEST-Y).
84
85 If RESAMPLE is true pixel colors will be smoothly interpolated. If
86 RESIZE is true the copied rectangle will be strechted or shrinked so
87 that its size is DEST-WIDTH x DEST-HEIGHT. If ROTATE is true the image
88 will be rotated by ANGLE. In this particular case DEST-X and DEST-Y
89 specify the CENTER of the copied image rather than its upper left
90 corner! If MERGE is true it has to be an integer in the range 0-100
91 and the two images will be 'merged' by the amount specified. If MERGE
92 is 100 then the source image will simply be copied. If instead
93 MERGE-GRAY is true the hue of the source image is preserved by
94 converting the destination area to gray pixels before merging.
95
96 The keyword options RESAMPLE, ROTATE, RESIZE, MERGE, and MERGE-GRAY
97 are mutually exclusive \(with the exception of RESAMPLE and
98 RESIZE). ANGLE is assumed to be specified in degrees if it's an
99 integer, and in radians otherwise."
100   (check-type source image)
101   (check-type destination image)
102   (check-type source-x integer)
103   (check-type source-y integer)
104   (unless rotate
105     (check-type dest-x integer)
106     (check-type dest-y integer))
107   (check-type width integer)
108   (check-type height integer)
109   (check-type angle (or null number))
110   (check-type dest-width (or null integer))
111   (check-type dest-height (or null integer))
112   (check-type merge (or null (integer 0 100)))
113   (check-type merge-gray (or null (integer 0 100)))
114   (when (and merge merge-gray)
115     (error "You can't specify MERGE and MERGE-GRAY at the same time."))
116   (when (and (or merge merge-gray)
117              (or resample rotate resize))
118     (error "MERGE and MERGE-GRAY can't be combined with RESAMPLE, ROTATE, or RESIZE."))
119   (when (and (or dest-width dest-height)
120              (not resize))
121     (error "Use RESIZE if you want to specify DEST-WIDTH or DEST-HEIGHT"))
122   (when (and resize
123              (not (or dest-width dest-height)))
124     (error "Please specify DEST-WIDTH and DEST-HEIGHT together with RESIZE."))
125   (when (and angle
126              (not rotate))
127     (error "Use ROTATE if you want to specify ANGLE."))
128   (when (and rotate
129              (not angle))
130     (error "Please specify ANGLE together with ROTATE."))
131   (when (and rotate
132              (or resample resize))
133     (error "ROTATE can't be used together with RESAMPLE or RESIZE."))
134   (cond ((and resample resize)
135           (gd-image-copy-resampled (img destination) (img source)
136                                    dest-x dest-y source-x source-y
137                                    dest-width dest-height width height))
138         (resample
139           (gd-image-copy-resampled (img destination) (img source)
140                                    dest-x dest-y source-x source-y
141                                    width height width height))
142         ((and rotate (integerp angle))
143           (gd-image-copy-rotated (img destination) (img source)
144                                  (coerce dest-x 'double-float)
145                                  (coerce dest-y 'double-float)
146                                  source-x source-y width height angle))
147         (rotate
148           (gd-image-copy-rotated (img destination) (img source)
149                                  (coerce dest-x 'double-float)
150                                  (coerce dest-y 'double-float)
151                                  source-x source-y width height
152                                  (round (* angle +radians-to-degree-factor+))))
153         (resize
154           (gd-image-copy-resized (img destination) (img source)
155                                  dest-x dest-y source-x source-y
156                                  dest-width dest-height width height))
157         (merge
158           (gd-image-copy-merge (img destination) (img source)
159                                dest-x dest-y source-x source-y
160                                width height merge))
161         (merge-gray
162           (gd-image-copy-merge-gray (img destination) (img source)
163                                     dest-x dest-y source-x source-y
164                                     width height merge-gray))
165         (t
166           (gd-image-copy (img destination) (img source) dest-x dest-y
167                          source-x source-y width height)))
168   destination)
169          
170 (defun copy-palette (source destination)
171   "Copies palette of image SOURCE to image DESTINATION attempting to
172 match the colors in the target image to the colors in the source
173 palette."
174   (check-type source image)
175   (check-type destination image)
176   (gd-image-palette-copy (img destination) (img source))
177   destination)
178
179 (defun true-color-to-palette (&key dither (colors-wanted 256) (image *default-image*))
180   "Converts the true color image IMAGE to a palette-based image using
181 a high-quality two-pass quantization routine. If DITHER is true, the
182 image will be dithered to approximate colors better, at the expense of
183 some obvious \"speckling.\" COLORS-WANTED can be any positive integer
184 up to 256 \(which is the default). If the original source image
185 includes photographic information or anything that came out of a JPEG,
186 256 is strongly recommended. 100% transparency of a single transparent
187 color in the original true color image will be preserved. There is no
188 other support for preservation of alpha channel or transparency in the
189 destination image."
190   (check-type image image)
191   (check-type colors-wanted (integer 0 256))
192   (gd-image-true-color-to-palette (img image)
193                                   (if dither 1 0)
194                                   colors-wanted)
195   image)
196
197 (defmacro do-rows ((y-var &optional (image '*default-image*)) &body body)
198   (with-rebinding (image)
199     (with-unique-names (img width height true-color-p raw-pixels row x-var inner-body)
200       `(let* ((,img (img ,image))
201               (,width (gd-image-get-sx ,img))
202               (,height (gd-image-get-sy ,img))
203               (,true-color-p (true-color-p ,image)))
204         (declare (fixnum ,width ,height))
205         (cond (,true-color-p
206                 (let ((,raw-pixels (get-slot-value ,img 'gd-image 't-pixels)))
207                   (declare (type t-pixels-array ,raw-pixels))
208                   (dotimes (,y-var ,height)
209                     (let ((,row (deref-array ,raw-pixels '(:array (* :int)) ,y-var)))
210                       (declare (type t-pixels-row ,row))
211                       (macrolet ((do-pixels-in-row ((,x-var) &body ,inner-body)
212                                    `(dotimes (,,x-var ,',width)
213                                      (macrolet ((raw-pixel ()
214                                                   `(deref-array ,',',row '(:array :int) ,',,x-var)))
215                                        (locally
216                                          ,@,inner-body)))))
217                         (locally
218                           ,@body))))))
219               (t
220                 (let ((,raw-pixels (get-slot-value ,img 'gd-image 'pixels)))
221                   (declare (type pixels-array ,raw-pixels))
222                   (dotimes (,y-var ,height)
223                     (let ((,row (deref-array ,raw-pixels '(:array (* :unsigned-byte)) ,y-var)))
224                       (declare (type pixels-row ,row))
225                       (macrolet ((do-pixels-in-row ((,x-var) &body ,inner-body)
226                                    `(dotimes (,,x-var ,',width)
227                                      (macrolet ((raw-pixel ()
228                                                   `(deref-array ,',',row '(:array :unsigned-byte) ,',,x-var)))
229                                        (locally
230                                          ,@,inner-body)))))
231                         (locally
232                           ,@body)))))))))))
233
234 (defmacro do-pixels ((&optional (image '*default-image*)) &body body)
235   (with-unique-names (x y)
236     `(do-rows (,y ,image)
237       (do-pixels-in-row (,x)
238         ,@body))))
Note: See TracBrowser for help on using the browser.