(install): Synchronize rules for compiling with Unix version.
[bpt/emacs.git] / lisp / image.el
1 ;;; image.el --- image API
2
3 ;; Copyright (C) 1998, 1999 Free Software Foundation, Inc.
4 ;; Keywords: multimedia
5
6 ;; This file is part of GNU Emacs.
7
8 ;; GNU Emacs is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 2, or (at your option)
11 ;; any later version.
12
13 ;; GNU Emacs is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
17
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GNU Emacs; see the file COPYING. If not, write to the
20 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 ;; Boston, MA 02111-1307, USA.
22
23 ;;; Commentary:
24
25 ;;; Code:
26
27 (defconst image-type-regexps
28 '(("^/\\*.*XPM.\\*/" . xpm)
29 ("^P[1-6]" . pbm)
30 ("^GIF8" . gif)
31 ("JFIF" . jpeg)
32 ("^\211PNG\r\n" . png)
33 ("^#define" . xbm)
34 ("^\\(MM\0\\*\\)\\|\\(II\\*\0\\)" . tiff)
35 ("^%!PS" . ghostscript))
36 "Alist of (REGEXP . IMAGE-TYPE) pairs used to auto-detect image types.
37 When the first bytes of an image file match REGEXP, it is assumed to
38 be of image type IMAGE-TYPE.")
39
40
41 ;;;###autoload
42 (defun image-type-from-data (data)
43 "Determine the image type from image data DATA.
44 Value is a symbol specifying the image type or nil if type cannot
45 be determined."
46 (let ((types image-type-regexps)
47 type)
48 (while (and types (null type))
49 (let ((regexp (car (car types)))
50 (image-type (cdr (car types))))
51 (when (string-match regexp data)
52 (setq type image-type))
53 (setq types (cdr types))))
54 type))
55
56
57 ;;;###autoload
58 (defun image-type-from-file-header (file)
59 "Determine the type of image file FILE from its first few bytes.
60 Value is a symbol specifying the image type, or nil if type cannot
61 be determined."
62 (unless (file-name-directory file)
63 (setq file (expand-file-name file data-directory)))
64 (setq file (expand-file-name file))
65 (let ((header (with-temp-buffer
66 (insert-file-contents-literally file nil 0 256)
67 (buffer-string))))
68 (image-type-from-data header)))
69
70
71 ;;;###autoload
72 (defun image-type-available-p (type)
73 "Value is non-nil if image type TYPE is available.
74 Image types are symbols like `xbm' or `jpeg'."
75 (not (null (memq type image-types))))
76
77
78 ;;;###autoload
79 (defun create-image (file-or-data &optional type data-p &rest props)
80 "Create an image.
81 FILE-OR-DATA is an image file name or image data.
82 Optional TYPE is a symbol describing the image type. If TYPE is omitted
83 or nil, try to determine the image type from its first few bytes
84 of image data. If that doesn't work, and FILE-OR-DATA is a file name,
85 use its file extension.as image type.
86 Optional DATA-P non-nil means FILE-OR-DATA is a string containing image data.
87 Optional PROPS are additional image attributes to assign to the image,
88 like, e.g. `:heuristic-mask t'.
89 Value is the image created, or nil if images of type TYPE are not supported."
90 (when (and (not data-p) (not (stringp file-or-data)))
91 (error "Invalid image file name `%s'" file-or-data))
92 (cond ((null data-p)
93 ;; FILE-OR-DATA is a file name.
94 (unless (or type
95 (setq type (image-type-from-file-header file-or-data)))
96 (let ((extension (file-name-extension file-or-data)))
97 (unless extension
98 (error "Cannot determine image type"))
99 (setq type (intern extension)))))
100 (t
101 ;; FILE-OR-DATA contains image data.
102 (unless type
103 (setq type (image-type-from-data file-or-data)))))
104 (unless type
105 (error "Cannot determine image type"))
106 (unless (symbolp type)
107 (error "Invalid image type `%s'" type))
108 (when (image-type-available-p type)
109 (append (list 'image :type type (if data-p :data :file) file-or-data)
110 props)))
111
112
113 ;;;###autoload
114 (defun put-image (image pos string &optional area)
115 "Put image IMAGE in front of POS in the current buffer.
116 IMAGE must be an image created with `create-image' or `defimage'.
117 IMAGE is displayed by putting an overlay into the current buffer with a
118 `before-string' STRING that has a `display' property whose value is the
119 image.
120 POS may be an integer or marker.
121 AREA is where to display the image. AREA nil or omitted means
122 display it in the text area, a value of `left-margin' means
123 display it in the left marginal area, a value of `right-margin'
124 means display it in the right marginal area."
125 (let ((buffer (current-buffer)))
126 (unless (eq (car image) 'image)
127 (error "Not an image: %s" image))
128 (unless (or (null area) (memq area '(left-margin right-margin)))
129 (error "Invalid area %s" area))
130 (setq string (copy-sequence string))
131 (let ((overlay (make-overlay pos pos buffer))
132 (prop (if (null area) image (list (list 'margin area) image))))
133 (put-text-property 0 (length string) 'display prop string)
134 (overlay-put overlay 'put-image t)
135 (overlay-put overlay 'before-string string))))
136
137
138 ;;;###autoload
139 (defun insert-image (image string &optional area)
140 "Insert IMAGE into current buffer at point.
141 IMAGE is displayed by inserting STRING into the current buffer
142 with a `display' property whose value is the image.
143 AREA is where to display the image. AREA nil or omitted means
144 display it in the text area, a value of `left-margin' means
145 display it in the left marginal area, a value of `right-margin'
146 means display it in the right marginal area."
147 (unless (eq (car image) 'image)
148 (error "Not an image: %s" image))
149 (unless (or (null area) (memq area '(left-margin right-margin)))
150 (error "Invalid area %s" area))
151 (when area
152 (setq image (list (list 'margin area) image)))
153 (let ((start (point)))
154 (insert string)
155 ;; Copy `image' so that inserting it twice in a row (adjacently)
156 ;; displays two copies of the image.
157 (add-text-properties start (point)
158 (list 'display (copy-sequence image)
159 'intangible (list t) ; something unique
160 'rear-nonsticky (list 'display)))))
161
162
163 ;;;###autoload
164 (defun remove-images (start end &optional buffer)
165 "Remove images between START and END in BUFFER.
166 Remove only images that were put in BUFFER with calls to `put-image'.
167 BUFFER nil or omitted means use the current buffer."
168 (unless buffer
169 (setq buffer (current-buffer)))
170 (let ((overlays (overlays-in start end)))
171 (while overlays
172 (let ((overlay (car overlays)))
173 (when (overlay-get overlay 'put-image)
174 (delete-overlay overlay)))
175 (setq overlays (cdr overlays)))))
176
177
178 ;;;###autoload
179 (defmacro defimage (symbol specs &optional doc)
180 "Define SYMBOL as an image.
181
182 SPECS is a list of image specifications. DOC is an optional
183 documentation string.
184
185 Each image specification in SPECS is a property list. The contents of
186 a specification are image type dependent. All specifications must at
187 least contain the properties `:type TYPE' and either `:file FILE' or
188 `:data DATA', where TYPE is a symbol specifying the image type,
189 e.g. `xbm', FILE is the file to load the image from, and DATA is a
190 string containing the actual image data. The first image
191 specification whose TYPE is supported, and FILE exists, is used to
192 define SYMBOL.
193
194 Example:
195
196 (defimage test-image ((:type xpm :file \"~/test1.xpm\")
197 (:type xbm :file \"~/test1.xbm\")))"
198 (let (image)
199 (while (and specs (null image))
200 (let* ((spec (car specs))
201 (type (plist-get spec :type))
202 (data (plist-get spec :data))
203 (file (plist-get spec :file)))
204 (when (image-type-available-p type)
205 (cond ((stringp file)
206 (setq file (expand-file-name file data-directory))
207 (when (file-readable-p file)
208 (setq image (cons 'image (plist-put spec :file file)))))
209 ((not (null data))
210 (setq image (cons 'image spec)))))
211 (setq specs (cdr specs))))
212 `(defvar ,symbol ',image ,doc)))
213
214
215 (provide 'image)
216
217 ;;; image.el ends here