1 ;;; w3m-image.el --- Image conversion routines.
3 ;; Copyright (C) 2001, 2002, 2003, 2005, 2007, 2008
4 ;; TSUCHIYA Masatoshi <tsuchiya@namazu.org>
6 ;; Authors: Yuuichi Teranishi <teranisi@gohome.org>
7 ;; Keywords: w3m, WWW, hypermedia
9 ;; This file is a part of emacs-w3m.
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with this program; see the file COPYING. If not, write to
23 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
29 ;; This file contains the stuffs to convert images for emacs-w3m.
30 ;; For more detail about emacs-w3m, see:
32 ;; http://emacs-w3m.namazu.org/
34 ;; Routines in this file require ImageMagick's convert.
35 ;; For more detail about ImageMagick, see:
37 ;; http://www.imagemagick.org/
48 (if (not (fboundp 'defcustom))
51 ;; Functions and variables which should be defined in the other module
54 (defvar w3m-async-exec)
55 (defvar w3m-current-url)
56 (defvar w3m-profile-directory)
57 (defvar w3m-work-buffer-name)
58 (defvar w3m-work-buffer-list))
60 (defcustom w3m-imagick-convert-program (if noninteractive
62 (w3m-which-command "convert"))
63 "*Program name of ImageMagick's `convert'."
65 :set (lambda (symbol value)
66 (custom-set-default symbol (if (and (not noninteractive)
68 (if (file-name-absolute-p value)
69 (if (file-executable-p value)
71 (w3m-which-command value)))))
74 (defcustom w3m-imagick-identify-program (if noninteractive
76 (w3m-which-command "identify"))
77 "*Program name of ImageMagick's `identify'."
79 :set (lambda (symbol value)
80 (custom-set-default symbol (if (and (not noninteractive)
82 (if (file-name-absolute-p value)
83 (if (file-executable-p value)
85 (w3m-which-command value)))))
88 ;;; Image handling functions.
89 (defcustom w3m-resize-images (and w3m-imagick-convert-program t)
90 "*If non-nil, resize images to the specified width and height."
92 :set (lambda (symbol value)
93 (custom-set-default symbol (and w3m-imagick-convert-program value)))
96 (put 'w3m-imagick-convert-program 'available-p 'unknown)
98 (defun w3m-imagick-convert-program-available-p ()
99 "Return non-nil if ImageMagick's `convert' program is available.
100 If not, `w3m-imagick-convert-program' and `w3m-resize-images' are made
102 (cond ((eq (get 'w3m-imagick-convert-program 'available-p) 'yes)
104 ((eq (get 'w3m-imagick-convert-program 'available-p) 'no)
106 ((and (stringp w3m-imagick-convert-program)
107 (file-executable-p w3m-imagick-convert-program))
108 (put 'w3m-imagick-convert-program 'available-p 'yes)
109 ;; Check whether convert supports png32.
110 (put 'w3m-imagick-convert-program 'png32
111 (unless (or (featurep 'xemacs)
112 (< emacs-major-version 22))
114 (set-buffer-multibyte nil)
117 (call-process-region (point-min) (point-max)
118 w3m-imagick-convert-program
119 t t nil "pbm:-" "png32:-")
121 (goto-char (point-min))
122 (looking-at "\211PNG\r\n"))))
125 (when w3m-imagick-convert-program
126 (message "ImageMagick's `convert' program is not available")
128 (setq w3m-imagick-convert-program nil
129 w3m-resize-images nil)
130 (put 'w3m-imagick-convert-program 'available-p 'no)
133 ;;; Synchronous image conversion.
134 (defun w3m-imagick-convert-buffer (from-type to-type &rest args)
135 (when (w3m-imagick-convert-program-available-p)
136 (let* ((in-file (make-temp-name
137 (expand-file-name "w3mel" w3m-profile-directory)))
138 (buffer-file-coding-system 'binary)
139 (coding-system-for-read 'binary)
140 (coding-system-for-write 'binary)
141 (default-process-coding-system (cons 'binary 'binary))
143 (write-region (point-min) (point-max) in-file nil 'nomsg)
147 w3m-imagick-convert-program
152 (concat from-type ":"))
155 (if (and (string-equal to-type "png")
156 (get 'w3m-imagick-convert-program
159 (concat to-type ":-"))
161 (when (file-exists-p in-file) (delete-file in-file))
162 (if (and (numberp return)
165 (message "Image conversion failed (code `%s')"
167 (string-as-multibyte return)
171 (defun w3m-imagick-convert-data (data from-type to-type &rest args)
173 (set-buffer-multibyte nil)
175 (and (apply 'w3m-imagick-convert-buffer from-type to-type args)
176 (not (zerop (buffer-size)))
179 ;;; Asynchronous image conversion.
180 (defun w3m-imagick-start-convert-data (handler
181 data from-type to-type &rest args)
182 (w3m-process-do-with-temp-buffer
183 (success (when (w3m-imagick-convert-program-available-p)
184 (set-buffer-multibyte nil)
186 (apply 'w3m-imagick-start-convert-buffer
187 handler from-type to-type args)))
189 (not (zerop (buffer-size))))
192 (defun w3m-imagick-start-convert-buffer (handler from-type to-type &rest args)
193 (lexical-let ((in-file (make-temp-name
194 (expand-file-name "w3mel" w3m-profile-directory)))
195 (out-buffer (current-buffer)))
196 (setq w3m-current-url "non-existent")
197 (let ((coding-system-for-write 'binary)
198 (buffer-file-coding-system 'binary)
199 jka-compr-compression-info-list
201 (write-region (point-min) (point-max) in-file nil 'nomsg))
203 (success (with-current-buffer out-buffer
207 w3m-imagick-convert-program
212 (concat from-type ":"))
215 (if (and (string-equal to-type "png")
216 (get 'w3m-imagick-convert-program
219 (concat to-type ":-"))
221 (when (file-exists-p in-file)
222 (delete-file in-file))
225 (defun w3m-resize-image (data width height handler)
226 "Resize image DATA to WIDTH and HEIGHT asynchronously.
227 HANDLER is called after conversion with resized data as an argument."
229 (result (w3m-imagick-start-convert-data
231 data nil nil "-geometry"
232 (concat (number-to-string width)
234 (number-to-string height)
238 (defun w3m-resize-image-by-rate (data rate handler)
239 "Resize image DATA at RATE asynchronously.
240 HANDLER is called after conversion with resized data as an argument.
241 Note that this function requires that the `convert' program allows the
244 (result (w3m-imagick-start-convert-data
246 data nil nil "-resize"
247 (concat (number-to-string rate) "%")))
250 (defun w3m-favicon-usable-p ()
251 "Check whether ImageMagick's `convert' supports a Windoze ico format in
252 a large number of bits per pixel."
253 (let ((xpm (condition-case nil
254 (w3m-imagick-convert-data
255 (string 0 0 1 0 1 0 2 1 0 0 1 0 24 0 52 0
256 0 0 22 0 0 0 40 0 0 0 2 0 0 0 2 0
257 0 0 1 0 24 0 0 0 0 0 0 0 0 0 0 0
258 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
259 0 255 255 255 0 0 0 0 0 0)
262 (and xpm (string-match "\"2 1 2 1\"" xpm) t)))
266 ;;; w3m-image.el ends here