aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Ingebrigtsen2019-11-19 11:47:19 +0100
committerLars Ingebrigtsen2019-11-19 11:47:25 +0100
commit067a42f8dd2ce19de3203605ee8c1c08aa192580 (patch)
treeb316871e26d62bad39e8d9068f7884b401a57f0d
parent49192e9510fe3c491b8c759a639bbe8bccf35856 (diff)
downloademacs-067a42f8dd2ce19de3203605ee8c1c08aa192580.tar.gz
emacs-067a42f8dd2ce19de3203605ee8c1c08aa192580.zip
Allow eww to display exotic images like webp
* lisp/image.el (image-type): Allow passing in the image type. (create-image): Make conversion work with data in addition to files. * lisp/image/image-converter.el (image-convert-p): Allow taking working on data in addition to files (bug#38036). (image-convert): Ditto. (image-converter--convert): Extend signature to say whether we're getting a file or data. (image-converter--convert-magick): Convert data. (image-converter--convert): Ditto.
-rw-r--r--lisp/image.el38
-rw-r--r--lisp/image/image-converter.el105
2 files changed, 102 insertions, 41 deletions
diff --git a/lisp/image.el b/lisp/image.el
index ad2ee6c6071..5f24475ce5b 100644
--- a/lisp/image.el
+++ b/lisp/image.el
@@ -369,8 +369,10 @@ be determined."
369 ;; If nothing seems to be supported, return first type that matched. 369 ;; If nothing seems to be supported, return first type that matched.
370 (or first (setq first type)))))))) 370 (or first (setq first type))))))))
371 371
372(declare-function image-convert-p "image-converter.el" (file)) 372(declare-function image-convert-p "image-converter.el"
373(declare-function image-convert "image-converter.el" (image)) 373 (source &optional image-format))
374(declare-function image-convert "image-converter.el"
375 (image &optional image-format))
374 376
375;;;###autoload 377;;;###autoload
376(defun image-type (source &optional type data-p) 378(defun image-type (source &optional type data-p)
@@ -380,12 +382,20 @@ Optional TYPE is a symbol describing the image type. If TYPE is omitted
380or nil, try to determine the image type from its first few bytes 382or nil, try to determine the image type from its first few bytes
381of image data. If that doesn't work, and SOURCE is a file name, 383of image data. If that doesn't work, and SOURCE is a file name,
382use its file extension as image type. 384use its file extension as image type.
383Optional DATA-P non-nil means SOURCE is a string containing image data." 385
386Optional DATA-P non-nil means SOURCE is a string containing image
387data. If DATA-P is a symbol with a name on the format
388`image/jpeg', that may be used as a hint to determine the image
389type if we can't otherwise guess it."
384 (when (and (not data-p) (not (stringp source))) 390 (when (and (not data-p) (not (stringp source)))
385 (error "Invalid image file name `%s'" source)) 391 (error "Invalid image file name `%s'" source))
386 (unless type 392 (unless type
387 (setq type (if data-p 393 (setq type (if data-p
388 (image-type-from-data source) 394 (or (image-type-from-data source)
395 (and image-use-external-converter
396 (progn
397 (require 'image-converter)
398 (image-convert-p source data-p))))
389 (or (image-type-from-file-header source) 399 (or (image-type-from-file-header source)
390 (image-type-from-file-name source) 400 (image-type-from-file-name source)
391 (and image-use-external-converter 401 (and image-use-external-converter
@@ -457,14 +467,18 @@ Images should not be larger than specified by `max-image-size'.
457Image file names that are not absolute are searched for in the 467Image file names that are not absolute are searched for in the
458\"images\" sub-directory of `data-directory' and 468\"images\" sub-directory of `data-directory' and
459`x-bitmap-file-path' (in that order)." 469`x-bitmap-file-path' (in that order)."
460 ;; It is x_find_image_file in image.c that sets the search path. 470 (let ((data-format
461 (setq type (image-type file-or-data type data-p)) 471 ;; Pass the image format, if any, if this is data.
462 ;; If we have external image conversion switched on (for exotic, 472 (and data-p (or (plist-get props :format) t))))
463 ;; non-native image formats), then we convert the file. 473 ;; It is x_find_image_file in image.c that sets the search path.
464 (when (eq type 'image-convert) 474 (setq type (ignore-error unknown-image-type
465 (setq file-or-data (image-convert file-or-data) 475 (image-type file-or-data type data-format)))
466 type 'png 476 ;; If we have external image conversion switched on (for exotic,
467 data-p t)) 477 ;; non-native image formats), then we convert the file.
478 (when (eq type 'image-convert)
479 (setq file-or-data (image-convert file-or-data data-format)
480 type 'png
481 data-p t)))
468 (when (image-type-available-p type) 482 (when (image-type-available-p type)
469 (append (list 'image :type type (if data-p :data :file) file-or-data) 483 (append (list 'image :type type (if data-p :data :file) file-or-data)
470 (and (not (plist-get props :scale)) 484 (and (not (plist-get props :scale))
diff --git a/lisp/image/image-converter.el b/lisp/image/image-converter.el
index 2e09976c011..dedccadcf46 100644
--- a/lisp/image/image-converter.el
+++ b/lisp/image/image-converter.el
@@ -48,43 +48,58 @@ installed on the system."
48 (imagemagick :command "convert" :probe ("-list" "format"))) 48 (imagemagick :command "convert" :probe ("-list" "format")))
49 "List of supported image converters to try.") 49 "List of supported image converters to try.")
50 50
51(defun image-convert-p (file) 51(defun image-convert-p (source &optional data-p)
52 "Return `image-convert' if FILE is an image file that can be converted." 52 "Return `image-convert' if SOURCE is an image that can be converted.
53SOURCE can either be a file name or a string containing image
54data. In the latter case, DATA-P should be non-nil. If DATA-P
55is a string, it should be a MIME format string like
56\"image/gif\"."
53 ;; Find an installed image converter. 57 ;; Find an installed image converter.
54 (unless image-converter 58 (unless image-converter
55 (image-converter--find-converter)) 59 (image-converter--find-converter))
56 (and image-converter 60 (and image-converter
57 (string-match image-converter-regexp file) 61 (or (and (not data-p)
62 (string-match image-converter-regexp source))
63 (and data-p
64 (symbolp data-p)
65 (string-match "/" (symbol-name data-p))
66 (string-match
67 image-converter-regexp
68 (concat "foo." (image-converter--mime-type data-p)))))
58 'image-convert)) 69 'image-convert))
59 70
60(defun image-convert (image) 71(defun image-convert (image &optional image-format)
61 "Convert IMAGE file to the PNG format. 72 "Convert IMAGE file to the PNG format.
62IMAGE can either be a file name, which will make the return value 73IMAGE can either be a file name, which will make the return value
63a string with the image data. It can also be an image object as 74a string with the image data.
64returned by `create-image'. If so, it has to be an image object 75
65where created with DATA-P nil (i.e., it has to refer to a file)." 76If IMAGE-FORMAT is non-nil, IMAGE is a string containing the
77image data, and IMAGE-FORMAT is a symbol with a MIME format name
78like \"image/webp\".
79
80IMAGE can also be an image object as returned by `create-image'."
66 ;; Find an installed image converter. 81 ;; Find an installed image converter.
67 (unless image-converter 82 (unless image-converter
68 (image-converter--find-converter)) 83 (image-converter--find-converter))
69 (unless image-converter 84 (unless image-converter
70 (error "No external image converters available")) 85 (error "No external image converters available"))
71 (when (and (listp image)
72 (not (plist-get (cdr image) :file)))
73 (error "Only images that refer to files can be converted"))
74 (with-temp-buffer 86 (with-temp-buffer
75 (set-buffer-multibyte nil) 87 (set-buffer-multibyte nil)
76 (when-let ((err (image-converter--convert 88 (when-let ((err (image-converter--convert
77 image-converter 89 image-converter
78 (if (listp image) 90 (if (listp image)
79 (plist-get (cdr image) :file) 91 (plist-get (cdr image) :file)
80 image)))) 92 image)
93 (if (listp image)
94 (plist-get (cdr image) :data-p)
95 image-format))))
81 (error "%s" err)) 96 (error "%s" err))
82 (if (listp image) 97 (if (listp image)
83 ;; Return an image object that's the same as we were passed, 98 ;; Return an image object that's the same as we were passed,
84 ;; but ignore the :type and :file values. 99 ;; but ignore the :type value.
85 (apply #'create-image (buffer-string) 'png t 100 (apply #'create-image (buffer-string) 'png t
86 (cl-loop for (key val) on (cdr image) by #'cddr 101 (cl-loop for (key val) on (cdr image) by #'cddr
87 unless (memq key '(:type :file)) 102 unless (eq key :type)
88 append (list key val))) 103 append (list key val)))
89 (buffer-string)))) 104 (buffer-string))))
90 105
@@ -159,33 +174,65 @@ where created with DATA-P nil (i.e., it has to refer to a file)."
159 image-converter-regexp (concat "\\." (regexp-opt formats) "\\'")) 174 image-converter-regexp (concat "\\." (regexp-opt formats) "\\'"))
160 (throw 'done image-converter))))) 175 (throw 'done image-converter)))))
161 176
162(cl-defmethod image-converter--convert ((type (eql graphicsmagick)) file) 177(cl-defmethod image-converter--convert ((type (eql graphicsmagick)) source
178 image-format)
163 "Convert using GraphicsMagick." 179 "Convert using GraphicsMagick."
164 (image-converter--convert-magick type file)) 180 (image-converter--convert-magick type source image-format))
165 181
166(cl-defmethod image-converter--convert ((type (eql imagemagick)) file) 182(cl-defmethod image-converter--convert ((type (eql imagemagick)) source
183 image-format)
167 "Convert using ImageMagick." 184 "Convert using ImageMagick."
168 (image-converter--convert-magick type file)) 185 (image-converter--convert-magick type source image-format))
186
187(defun image-converter--mime-type (image-format)
188 (and (symbolp image-format)
189 (cadr (split-string (symbol-name image-format) "/"))))
169 190
170(defun image-converter--convert-magick (type file) 191(defun image-converter--convert-magick (type source image-format)
171 (let ((command (image-converter--value type :command))) 192 (let ((command (image-converter--value type :command)))
172 (unless (zerop (apply #'call-process (car command) 193 (unless (zerop (if image-format
173 nil t nil 194 ;; We have the image data in SOURCE.
174 (append (cdr command) 195 (progn
175 (list (expand-file-name file) "png:-")))) 196 (insert source)
197 (apply #'call-process-region (point-min) (point-max)
198 (car command) t t nil
199 (append
200 (cdr command)
201 (list (format "%s:-"
202 (image-converter--mime-type
203 image-format))
204 "png:-"))))
205 ;; SOURCE is a file name.
206 (apply #'call-process (car command)
207 nil t nil
208 (append (cdr command)
209 (list (expand-file-name source) "png:-")))))
176 ;; If the command failed, hopefully the buffer contains the 210 ;; If the command failed, hopefully the buffer contains the
177 ;; error message. 211 ;; error message.
178 (buffer-string)))) 212 (buffer-string))))
179 213
180(cl-defmethod image-converter--convert ((type (eql ffmpeg)) file) 214(cl-defmethod image-converter--convert ((type (eql ffmpeg)) source
215 image-format)
181 "Convert using ffmpeg." 216 "Convert using ffmpeg."
182 (let ((command (image-converter--value type :command))) 217 (let ((command (image-converter--value type :command)))
183 (unless (zerop (apply #'call-process 218 (unless (zerop (if image-format
184 (car command) 219 (progn
185 nil '(t nil) nil 220 (insert source)
186 (append (cdr command) 221 (apply #'call-process-region
187 (list "-i" (expand-file-name file) 222 (point-min) (point-max) (car command)
188 "-c:v" "png" "-f" "image2pipe" "-")))) 223 t '(t nil) nil
224 (append
225 (cdr command)
226 (list "-i" "-"
227 "-c:v" "png"
228 "-f" "image2pipe" "-"))))
229 (apply #'call-process
230 (car command)
231 nil '(t nil) nil
232 (append (cdr command)
233 (list "-i" (expand-file-name source)
234 "-c:v" "png" "-f" "image2pipe"
235 "-")))))
189 "ffmpeg error when converting"))) 236 "ffmpeg error when converting")))
190 237
191(provide 'image-converter) 238(provide 'image-converter)