comparison lisp/tumme.el @ 68815:3e8cc27a9bcf

Remove todo item about Thumbnail Managing Standard. (tumme) <defgroup>: Change :group to `multimedia'. (tumme-thumbnail-storage): Add choice `standard' for Thumbnail Managing Standard. (tumme-cmd-create-thumbnail-options): Use %w and %h instead of %s. Fix dostring. (tumme-cmd-create-temp-image-options): Use %w and %h instead of %x and %y. Fix docstring. (tumme-cmd-pngnq-program, tumme-cmd-pngcrush-program) (tumme-cmd-create-standard-thumbnail-command): New user options. (tumme-thumb-size): Set default to 128 if tumme-thumbnail-storage is `standard'. Fix docstring. (tumme-thumb-width, tumme-thumb-height): New user options. (tumme-external-viewer): Try to find various viewers. (tumme-get-thumbnail-image): Use `create-image' instead of constructing the `image' structure. (tumme-insert-thumbnail): Use `png' if tumme-thumbnail-storage is `standard'. (tumme-thumb-name): Add file name generation for standard storage. Simplify code for other storages. (tumme-thumb-name): Use width %w and height %h instead of size %s. Add modification time %m and thumbnail-nq8 %q. Use `tumme-cmd-create-standard-thumbnail-command' if tumme-thumbnail-storage is `standard'. (tumme-dired-insert-marked-thumbs): New autoload command. (tumme-dired-after-readin-hook): New function. (tumme-line-up-dynamic): Use `tumme-thumb-width' instead of `tumme-thumb-size'. (tumme-display-image): Replace size-x %x and size-y %y with width %w and height %h.
author Juri Linkov <juri@jurta.org>
date Sun, 12 Feb 2006 17:44:30 +0000
parents 268f839373ee
children 207844891bb3
comparison
equal deleted inserted replaced
68814:fe9073ac802e 68815:3e8cc27a9bcf
514 ;; 514 ;;
515 ;; 515 ;;
516 ;; TODO 516 ;; TODO
517 ;; ==== 517 ;; ====
518 ;; 518 ;;
519 ;; * Look into supporting the Thumbnail Managing Standard, maybe as a
520 ;; configurable option.
521 ;;
522 ;; * Support gallery creation when using per-directory thumbnail 519 ;; * Support gallery creation when using per-directory thumbnail
523 ;; storage. 520 ;; storage.
524 ;; 521 ;;
525 ;; * Some sort of auto-rotate function based on rotate info in the 522 ;; * Some sort of auto-rotate function based on rotate info in the
526 ;; EXIF data. 523 ;; EXIF data.
577 (require 'format-spec) 574 (require 'format-spec)
578 575
579 (defgroup tumme nil 576 (defgroup tumme nil
580 "Use dired to browse your images as thumbnails, and more." 577 "Use dired to browse your images as thumbnails, and more."
581 :prefix "tumme-" 578 :prefix "tumme-"
582 :group 'files) 579 :group 'multimedia)
583 580
584 (defcustom tumme-dir "~/.emacs.d/tumme/" 581 (defcustom tumme-dir "~/.emacs.d/tumme/"
585 "*Directory where thumbnail images are stored." 582 "*Directory where thumbnail images are stored."
586 :type 'string 583 :type 'string
587 :group 'tumme) 584 :group 'tumme)
592 controlled by this variable. \"Use tumme dir\" means that the 589 controlled by this variable. \"Use tumme dir\" means that the
593 thumbnails are stored in a central directory. \"Per directory\" 590 thumbnails are stored in a central directory. \"Per directory\"
594 means that each thumbnail is stored in a subdirectory called 591 means that each thumbnail is stored in a subdirectory called
595 \".tumme\" in the same directory where the image file is." 592 \".tumme\" in the same directory where the image file is."
596 :type '(choice :tag "How to store thumbnail files" 593 :type '(choice :tag "How to store thumbnail files"
594 (const :tag "Thumbnail Managing Standard" standard)
597 (const :tag "Use tumme-dir" use-tumme-dir) 595 (const :tag "Use tumme-dir" use-tumme-dir)
598 (const :tag "Per-directory" per-directory)) 596 (const :tag "Per-directory" per-directory))
599 :group 'tumme) 597 :group 'tumme)
600 598
601 (defcustom tumme-db-file "~/.emacs.d/tumme/.tumme_db" 599 (defcustom tumme-db-file "~/.emacs.d/tumme/.tumme_db"
637 Used together with `tumme-cmd-create-thumbnail-options'." 635 Used together with `tumme-cmd-create-thumbnail-options'."
638 :type 'string 636 :type 'string
639 :group 'tumme) 637 :group 'tumme)
640 638
641 (defcustom tumme-cmd-create-thumbnail-options 639 (defcustom tumme-cmd-create-thumbnail-options
642 "%p -size %sx%s \"%f\" -resize %sx%s +profile \"*\" jpeg:\"%t\"" 640 "%p -size %wx%h \"%f\" -resize %wx%h +profile \"*\" jpeg:\"%t\""
643 "*Format of command used to create thumbnail image. 641 "*Format of command used to create thumbnail image.
644 Available options are %p which is replaced by 642 Available options are %p which is replaced by
645 `tumme-cmd-create-thumbnail-program', %s which is replaced by 643 `tumme-cmd-create-thumbnail-program', %w which is replaced by
646 `tumme-thumb-size', %f which is replaced by the file name of the 644 `tumme-thumb-width', %h which is replaced by `tumme-thumb-height',
647 original image and %t which is replaced by the file name of the 645 %f which is replaced by the file name of the original image and %t
648 thumbnail file." 646 which is replaced by the file name of the thumbnail file."
649 :type 'string 647 :type 'string
650 :group 'tumme) 648 :group 'tumme)
651 649
652 (defcustom tumme-cmd-create-temp-image-program 650 (defcustom tumme-cmd-create-temp-image-program
653 "convert" 651 "convert"
655 Used together with `tumme-cmd-create-temp-image-options'." 653 Used together with `tumme-cmd-create-temp-image-options'."
656 :type 'string 654 :type 'string
657 :group 'tumme) 655 :group 'tumme)
658 656
659 (defcustom tumme-cmd-create-temp-image-options 657 (defcustom tumme-cmd-create-temp-image-options
660 "%p -size %xx%y \"%f\" -resize %xx%y +profile \"*\" jpeg:\"%t\"" 658 "%p -size %wx%h \"%f\" -resize %wx%h +profile \"*\" jpeg:\"%t\""
661 "*Format of command used to create temporary image for display window. 659 "*Format of command used to create temporary image for display window.
662 Available options are %p which is replaced by 660 Available options are %p which is replaced by
663 `tumme-cmd-create-temp-image-program', %x and %y which is replaced by 661 `tumme-cmd-create-temp-image-program', %w and %h which is replaced by
664 the calculated max size for x and y in the image display window, %f 662 the calculated max size for width and height in the image display window,
665 which is replaced by the file name of the original image and %t which 663 %f which is replaced by the file name of the original image and %t which
666 is replaced by the file name of the temporary file." 664 is replaced by the file name of the temporary file."
665 :type 'string
666 :group 'tumme)
667
668 (defcustom tumme-cmd-pngnq-program (executable-find "pngnq")
669 "*The file name of the `pngnq' program.
670 It quantizes colors of PNG images down to 256 colors."
671 :type '(choice (const :tag "Not Set" nil) string)
672 :group 'tumme)
673
674 (defcustom tumme-cmd-pngcrush-program (executable-find "pngcrush")
675 "*The file name of the `pngcrush' program.
676 It optimizes the compression of PNG images. Also it adds PNG textual chunks
677 with the information required by the Thumbnail Managing Standard."
678 :type '(choice (const :tag "Not Set" nil) string)
679 :group 'tumme)
680
681 (defcustom tumme-cmd-create-standard-thumbnail-command
682 (concat
683 tumme-cmd-create-thumbnail-program " "
684 "-size %wx%h \"%f\" "
685 (unless (or tumme-cmd-pngcrush-program tumme-cmd-pngnq-program)
686 (concat
687 "-set \"Thumb::MTime\" \"%m\" "
688 "-set \"Thumb::URI\" \"file://%f\" "
689 "-set \"Description\" \"Thumbnail of file://%f\" "
690 "-set \"Software\" \"" (emacs-version) "\" "))
691 "-thumbnail %wx%h png:\"%t\""
692 (if tumme-cmd-pngnq-program
693 (concat
694 " ; " tumme-cmd-pngnq-program " -f \"%t\""
695 (unless tumme-cmd-pngcrush-program
696 " ; mv %q %t")))
697 (if tumme-cmd-pngcrush-program
698 (concat
699 (unless tumme-cmd-pngcrush-program
700 " ; cp %t %q")
701 " ; " tumme-cmd-pngcrush-program " -q "
702 "-text b \"Description\" \"Thumbnail of file://%f\" "
703 "-text b \"Software\" \"" (emacs-version) "\" "
704 ;; "-text b \"Thumb::Image::Height\" \"%oh\" "
705 ;; "-text b \"Thumb::Image::Mimetype\" \"%mime\" "
706 ;; "-text b \"Thumb::Image::Width\" \"%ow\" "
707 "-text b \"Thumb::MTime\" \"%m\" "
708 ;; "-text b \"Thumb::Size\" \"%b\" "
709 "-text b \"Thumb::URI\" \"file://%f\" "
710 "%q %t"
711 " ; rm %q")))
712 "*Command to create thumbnails according to the Thumbnail Managing Standard."
667 :type 'string 713 :type 'string
668 :group 'tumme) 714 :group 'tumme)
669 715
670 (defcustom tumme-cmd-rotate-thumbnail-program 716 (defcustom tumme-cmd-rotate-thumbnail-program
671 "mogrify" 717 "mogrify"
755 "*List of \"hidden\" tags. 801 "*List of \"hidden\" tags.
756 Used by `tumme-gallery-generate' to leave out \"hidden\" images." 802 Used by `tumme-gallery-generate' to leave out \"hidden\" images."
757 :type '(repeat string) 803 :type '(repeat string)
758 :group 'tumme) 804 :group 'tumme)
759 805
760 (defcustom tumme-thumb-size 100 806 (defcustom tumme-thumb-size (if (eq 'standard tumme-thumbnail-storage) 128 100)
761 "Size of thumbnails, in pixels." 807 "Size of thumbnails, in pixels.
808 This is the default size for both `tumme-thumb-width' and `tumme-thumb-height'."
809 :type 'integer
810 :group 'tumme)
811
812 (defcustom tumme-thumb-width tumme-thumb-size
813 "Width of thumbnails, in pixels."
814 :type 'integer
815 :group 'tumme)
816
817 (defcustom tumme-thumb-height tumme-thumb-size
818 "Height of thumbnails, in pixels."
762 :type 'integer 819 :type 'integer
763 :group 'tumme) 820 :group 'tumme)
764 821
765 (defcustom tumme-thumb-relief 2 822 (defcustom tumme-thumb-relief 2
766 "*Size of button-like border around thumbnails." 823 "*Size of button-like border around thumbnails."
839 \(without path) of original image file, %t with the list of tags and %c 896 \(without path) of original image file, %t with the list of tags and %c
840 with the comment." 897 with the comment."
841 :type 'string 898 :type 'string
842 :group 'tumme) 899 :group 'tumme)
843 900
844 (defcustom tumme-external-viewer "qiv -t" 901 (defcustom tumme-external-viewer
902 ;; TODO: use mailcap, dired-guess-shell-alist-default, dired-view-command-alist
903 (cond ((executable-find "display"))
904 ((executable-find "xli"))
905 ((executable-find "qiv") "qiv -t"))
845 "*Name of external viewer. 906 "*Name of external viewer.
846 Including parameters. Used when displaying original image from 907 Including parameters. Used when displaying original image from
847 `tumme-thumbnail-mode'." 908 `tumme-thumbnail-mode'."
848 :type 'string 909 :type 'string
849 :group 'tumme) 910 :group 'tumme)
886 (let ((thumb-file (tumme-thumb-name file))) 947 (let ((thumb-file (tumme-thumb-name file)))
887 (unless (and (file-exists-p thumb-file) 948 (unless (and (file-exists-p thumb-file)
888 (<= (float-time (nth 5 (file-attributes file))) 949 (<= (float-time (nth 5 (file-attributes file)))
889 (float-time (nth 5 (file-attributes thumb-file))))) 950 (float-time (nth 5 (file-attributes thumb-file)))))
890 (tumme-create-thumb file thumb-file)) 951 (tumme-create-thumb file thumb-file))
891 (list 'image :type 'jpeg :file thumb-file 952 (create-image thumb-file)
892 :relief tumme-thumb-relief :margin tumme-thumb-margin))) 953 ;; (list 'image :type 'jpeg
954 ;; :file thumb-file
955 ;; :relief tumme-thumb-relief :margin tumme-thumb-margin)
956 ))
893 957
894 (defun tumme-insert-thumbnail (file original-file-name 958 (defun tumme-insert-thumbnail (file original-file-name
895 associated-dired-buffer) 959 associated-dired-buffer)
896 "Insert thumbnail image FILE. 960 "Insert thumbnail image FILE.
897 Add text properties ORIGINAL-FILE-NAME and ASSOCIATED-DIRED-BUFFER." 961 Add text properties ORIGINAL-FILE-NAME and ASSOCIATED-DIRED-BUFFER."
898 (let (beg end) 962 (let (beg end)
899 (setq beg (point)) 963 (setq beg (point))
900 (tumme-insert-image file 964 (tumme-insert-image file
901 'jpeg 965 ;; TODO: this should depend on the real file type
966 (if (eq 'standard tumme-thumbnail-storage)
967 'png 'jpeg)
902 tumme-thumb-relief 968 tumme-thumb-relief
903 tumme-thumb-margin) 969 tumme-thumb-margin)
904 (setq end (point)) 970 (setq end (point))
905 (add-text-properties 971 (add-text-properties
906 beg end 972 beg end
915 "Return thumbnail file name for FILE. 981 "Return thumbnail file name for FILE.
916 Depending on the value of `tumme-thumbnail-storage', the file 982 Depending on the value of `tumme-thumbnail-storage', the file
917 name will vary. For central thumbnail file storage, make a 983 name will vary. For central thumbnail file storage, make a
918 MD5-hash of the image file's directory name and add that to make 984 MD5-hash of the image file's directory name and add that to make
919 the thumbnail file name unique. For per-directory storage, just 985 the thumbnail file name unique. For per-directory storage, just
920 add a subdirectory." 986 add a subdirectory. For standard storage, produce the file name
921 (let ((f (expand-file-name file)) 987 according to the Thumbnail Managing Standard."
922 md5-hash) 988 (cond ((eq 'standard tumme-thumbnail-storage)
923 (format "%s%s%s.thumb.%s" 989 (expand-file-name
924 (cond ((eq 'use-tumme-dir tumme-thumbnail-storage) 990 (concat "~/.thumbnails/normal/"
925 ;; Is MD5 hashes fast enough? The checksum of a 991 (md5 (concat "file://" (expand-file-name file))) ".png")))
926 ;; thumbnail file name need not be that 992 ((eq 'use-tumme-dir tumme-thumbnail-storage)
927 ;; "cryptographically" good so a faster one could 993 (let* ((f (expand-file-name file))
928 ;; be used here. 994 (md5-hash
929 (setq md5-hash (md5 (file-name-as-directory 995 ;; Is MD5 hashes fast enough? The checksum of a
930 (file-name-directory file)))) 996 ;; thumbnail file name need not be that
931 (file-name-as-directory (expand-file-name (tumme-dir)))) 997 ;; "cryptographically" good so a faster one could
932 ((eq 'per-directory tumme-thumbnail-storage) 998 ;; be used here.
933 (format "%s.tumme/" 999 (md5 (file-name-as-directory (file-name-directory f)))))
934 (file-name-directory f)))) 1000 (format "%s%s%s.thumb.%s"
935 (file-name-sans-extension 1001 (file-name-as-directory (expand-file-name (tumme-dir)))
936 (file-name-nondirectory f)) 1002 (file-name-sans-extension (file-name-nondirectory f))
937 (if md5-hash 1003 (if md5-hash (concat "_" md5-hash) "")
938 (concat "_" md5-hash) 1004 (file-name-extension f))))
939 "") 1005 ((eq 'per-directory tumme-thumbnail-storage)
940 (file-name-extension f)))) 1006 (let ((f (expand-file-name file)))
1007 (format "%s%s%s.thumb.%s"
1008 (format "%s.tumme/" (file-name-directory f))
1009 (file-name-sans-extension (file-name-nondirectory f))
1010 (file-name-extension f))))))
941 1011
942 (defun tumme-create-thumb (original-file thumbnail-file) 1012 (defun tumme-create-thumb (original-file thumbnail-file)
943 "For ORIGINAL-FILE, create thumbnail image named THUMBNAIL-FILE." 1013 "For ORIGINAL-FILE, create thumbnail image named THUMBNAIL-FILE."
944 (let* ((size (int-to-string tumme-thumb-size)) 1014 (let* ((width (int-to-string tumme-thumb-width))
1015 (height (int-to-string tumme-thumb-height))
1016 (modif-time (format "%.0f" (float-time (nth 5 (file-attributes
1017 original-file)))))
1018 (thumbnail-nq8-file (replace-regexp-in-string ".png\\'" "-nq8.png"
1019 thumbnail-file))
945 (command 1020 (command
946 (format-spec 1021 (format-spec
947 tumme-cmd-create-thumbnail-options 1022 (if (eq 'standard tumme-thumbnail-storage)
1023 tumme-cmd-create-standard-thumbnail-command
1024 tumme-cmd-create-thumbnail-options)
948 (list 1025 (list
949 (cons ?p tumme-cmd-create-thumbnail-program) 1026 (cons ?p tumme-cmd-create-thumbnail-program)
950 (cons ?s size) 1027 (cons ?w width)
1028 (cons ?h height)
1029 (cons ?m modif-time)
951 (cons ?f original-file) 1030 (cons ?f original-file)
1031 (cons ?q thumbnail-nq8-file)
952 (cons ?t thumbnail-file)))) 1032 (cons ?t thumbnail-file))))
953 thumbnail-dir) 1033 thumbnail-dir)
954 (when (not (file-exists-p 1034 (when (not (file-exists-p
955 (setq thumbnail-dir (file-name-directory thumbnail-file)))) 1035 (setq thumbnail-dir (file-name-directory thumbnail-file))))
956 (message "Creating thumbnail directory.") 1036 (message "Creating thumbnail directory.")
957 (make-directory thumbnail-dir)) 1037 (make-directory thumbnail-dir))
958 (shell-command command nil))) 1038 (shell-command command nil)))
1039
1040 ;;;###autoload
1041 (defun tumme-dired-insert-marked-thumbs ()
1042 "Insert thumbnails before file names of marked files in the dired buffer."
1043 (interactive)
1044 (dired-map-over-marks
1045 (let* ((image-pos (dired-move-to-filename))
1046 (image-file (dired-get-filename))
1047 (thumb-file (tumme-get-thumbnail-image image-file))
1048 overlay)
1049 ;; If image is not already added, then add it.
1050 (unless (delq nil (mapcar (lambda (o) (overlay-get o 'put-image))
1051 ;; Can't use (overlays-at (point)), BUG?
1052 (overlays-in (point) (1+ (point)))))
1053 (put-image thumb-file image-pos)
1054 (setq overlay (car (delq nil (mapcar (lambda (o) (and (overlay-get o 'put-image) o))
1055 (overlays-in (point) (1+ (point)))))))
1056 (overlay-put overlay 'image-file image-file)
1057 (overlay-put overlay 'thumb-file thumb-file)))
1058 nil)
1059 (add-hook 'dired-after-readin-hook 'tumme-dired-after-readin-hook nil t))
1060
1061 (defun tumme-dired-after-readin-hook ()
1062 "Relocate existing thumbnail overlays in dired buffer after reverting.
1063 Move them to their corresponding files if they are still exist.
1064 Otherwise, delete overlays."
1065 (mapc (lambda (overlay)
1066 (when (overlay-get overlay 'put-image)
1067 (let* ((image-file (overlay-get overlay 'image-file))
1068 (image-pos (dired-goto-file image-file)))
1069 (if image-pos
1070 (move-overlay overlay image-pos image-pos)
1071 (delete-overlay overlay)))))
1072 (overlays-in (point-min) (point-max))))
959 1073
960 (defun tumme-next-line-and-display () 1074 (defun tumme-next-line-and-display ()
961 "Move to next dired line and display thumbnail image." 1075 "Move to next dired line and display thumbnail image."
962 (interactive) 1076 (interactive)
963 (dired-next-line 1) 1077 (dired-next-line 1)
1964 (width (tumme-window-width-pixels (tumme-thumbnail-window))) 2078 (width (tumme-window-width-pixels (tumme-thumbnail-window)))
1965 (tumme-thumbs-per-row 2079 (tumme-thumbs-per-row
1966 (/ width 2080 (/ width
1967 (+ (* 2 tumme-thumb-relief) 2081 (+ (* 2 tumme-thumb-relief)
1968 (* 2 tumme-thumb-margin) 2082 (* 2 tumme-thumb-margin)
1969 tumme-thumb-size char-width)))) 2083 tumme-thumb-width char-width))))
1970 (tumme-line-up))) 2084 (tumme-line-up)))
1971 2085
1972 (defun tumme-line-up-interactive () 2086 (defun tumme-line-up-interactive ()
1973 "Line up thumbnails interactively. 2087 "Line up thumbnails interactively.
1974 Ask user how many thumbnails should be displayed per row." 2088 Ask user how many thumbnails should be displayed per row."
2056 systems it should feel snappy enough. 2170 systems it should feel snappy enough.
2057 2171
2058 If optional argument ORIGINAL-SIZE is non-nil, display image in its 2172 If optional argument ORIGINAL-SIZE is non-nil, display image in its
2059 original size." 2173 original size."
2060 (let ((new-file (expand-file-name tumme-temp-image-file)) 2174 (let ((new-file (expand-file-name tumme-temp-image-file))
2061 size-x size-y command ret) 2175 width height command ret)
2062 (setq file (expand-file-name file)) 2176 (setq file (expand-file-name file))
2063 (if (not original-size) 2177 (if (not original-size)
2064 (progn 2178 (progn
2065 (setq size-x (tumme-display-window-width)) 2179 (setq width (tumme-display-window-width))
2066 (setq size-y (tumme-display-window-height)) 2180 (setq height (tumme-display-window-height))
2067 (setq command 2181 (setq command
2068 (format-spec 2182 (format-spec
2069 tumme-cmd-create-temp-image-options 2183 tumme-cmd-create-temp-image-options
2070 (list 2184 (list
2071 (cons ?p tumme-cmd-create-temp-image-program) 2185 (cons ?p tumme-cmd-create-temp-image-program)
2072 (cons ?x size-x) 2186 (cons ?w width)
2073 (cons ?y size-y) 2187 (cons ?h height)
2074 (cons ?f file) 2188 (cons ?f file)
2075 (cons ?t new-file)))) 2189 (cons ?t new-file))))
2076 (setq ret (shell-command command nil)) 2190 (setq ret (shell-command command nil))
2077 (if (not (= 0 ret)) 2191 (if (not (= 0 ret))
2078 (error "Could not resize image"))) 2192 (error "Could not resize image")))