diff options
| -rw-r--r-- | README.imagemagick | 49 | ||||
| -rw-r--r-- | lisp/image-mode.el | 71 | ||||
| -rw-r--r-- | src/image.c | 38 |
3 files changed, 98 insertions, 60 deletions
diff --git a/README.imagemagick b/README.imagemagick index e9d6a4166ea..80c665e0cef 100644 --- a/README.imagemagick +++ b/README.imagemagick | |||
| @@ -27,11 +27,21 @@ jpegs. | |||
| 27 | the bundle. This feature is not the primary usecase for the | 27 | the bundle. This feature is not the primary usecase for the |
| 28 | imagemagick patch though. | 28 | imagemagick patch though. |
| 29 | 29 | ||
| 30 | - optimize number of pages calculation for bundles as suggested by | ||
| 31 | imagemagick forum: "set the density to something low like 2 and use | ||
| 32 | MagickPingImage()" | ||
| 33 | |||
| 30 | - zooming the image like what is done for fonts in face-remap.el would | 34 | - zooming the image like what is done for fonts in face-remap.el would |
| 31 | be a useful and demo friendly addition. | 35 | be a useful and demo friendly addition. Some work has been done on |
| 36 | image-mode.el to acihieve this. | ||
| 32 | 37 | ||
| 33 | - figure out what to do with the experimental features noted below. | 38 | - look for optimizations for handling images with low depth |
| 39 | |||
| 40 | - it would be neat if the graphicsmagick fork of imagemagick could | ||
| 41 | optionaly be used. | ||
| 34 | 42 | ||
| 43 | |||
| 44 | |||
| 35 | * TODO | 45 | * TODO |
| 36 | #B _ complete documentation drafts below | 46 | #B _ complete documentation drafts below |
| 37 | 47 | ||
| @@ -120,41 +130,6 @@ as TIFF or DJVM, to view. | |||
| 120 | The image-metadata function can be used to retrieve the total number | 130 | The image-metadata function can be used to retrieve the total number |
| 121 | of images in an image bundle. This is simmilar to how GIF files work. | 131 | of images in an image bundle. This is simmilar to how GIF files work. |
| 122 | 132 | ||
| 123 | * experimental | ||
| 124 | |||
| 125 | - :crop is used to specify a croping area: (width height x y). This | ||
| 126 | is similar to the slice image specification, but has a different | ||
| 127 | purpose. :crop removes the croped areas from memory, so its memory | ||
| 128 | efficient if you only need to view a certain part of the image. The | ||
| 129 | slice specification can be used to pick diferent parts of the same | ||
| 130 | image, so its more disk and display efficient. :crop works well, but | ||
| 131 | it would still be better to find a way to have :splice do the same | ||
| 132 | thing. | ||
| 133 | |||
| 134 | - :geometry takes a geometry string as defined by ImageMagick: | ||
| 135 | |||
| 136 | scale% | ||
| 137 | scale-x%xscale-y% | ||
| 138 | width | ||
| 139 | xheight | ||
| 140 | widthxheight | ||
| 141 | widthxheight^ | ||
| 142 | widthxheight! | ||
| 143 | widthxheight> | ||
| 144 | widthxheight< | ||
| 145 | area@ | ||
| 146 | {size}{offset} | ||
| 147 | {size}{+-}x{+-}y | ||
| 148 | |||
| 149 | See the ImageMagick manual for more information. | ||
| 150 | |||
| 151 | - :crop is used to specify a croping area, with the "{size}{offset}" syntax. | ||
| 152 | |||
| 153 | :geometry and :crop with a string argument, are both particular to | ||
| 154 | ImageMagick, whereas the lisp interface is more general. Currently it | ||
| 155 | seems like the lisp interface is good enough, so the string argument | ||
| 156 | interface will probably be removed. | ||
| 157 | |||
| 158 | * Changelog entry | 133 | * Changelog entry |
| 159 | 2010-06-12 Joakim Verona <joakim@verona.se> | 134 | 2010-06-12 Joakim Verona <joakim@verona.se> |
| 160 | * image.c: Add support for ImageMagick. When HAVE_IMAGEMAGICK is | 135 | * image.c: Add support for ImageMagick. When HAVE_IMAGEMAGICK is |
diff --git a/lisp/image-mode.el b/lisp/image-mode.el index 585d82e9beb..a278c47a555 100644 --- a/lisp/image-mode.el +++ b/lisp/image-mode.el | |||
| @@ -471,7 +471,10 @@ was inserted." | |||
| 471 | (buffer-substring-no-properties (point-min) (point-max))) | 471 | (buffer-substring-no-properties (point-min) (point-max))) |
| 472 | filename)) | 472 | filename)) |
| 473 | (type (image-type file-or-data nil data-p)) | 473 | (type (image-type file-or-data nil data-p)) |
| 474 | (image (create-animated-image file-or-data type data-p)) | 474 | (image0 (create-animated-image file-or-data type data-p)) |
| 475 | (image (append image0 | ||
| 476 | (image-transform-properties image0) | ||
| 477 | )) | ||
| 475 | (props | 478 | (props |
| 476 | `(display ,image | 479 | `(display ,image |
| 477 | intangible ,image | 480 | intangible ,image |
| @@ -534,6 +537,72 @@ the image file and `image-mode' showing the image as an image." | |||
| 534 | (when (not (string= image-type (bookmark-prop-get bmk 'image-type))) | 537 | (when (not (string= image-type (bookmark-prop-get bmk 'image-type))) |
| 535 | (image-toggle-display)))) | 538 | (image-toggle-display)))) |
| 536 | 539 | ||
| 540 | |||
| 541 | (defvar image-transform-minor-mode-map | ||
| 542 | (let ((map (make-sparse-keymap))) | ||
| 543 | ; (define-key map [(control ?+)] 'image-scale-in) | ||
| 544 | ; (define-key map [(control ?-)] 'image-scale-out) | ||
| 545 | ; (define-key map [(control ?=)] 'image-scale-none) | ||
| 546 | ;; (define-key map "c f h" 'image-scale-fit-height) | ||
| 547 | ;; (define-key map "c ]" 'image-rotate-right) | ||
| 548 | map) | ||
| 549 | "Minor mode keymap for transforming the view of images Image mode.") | ||
| 550 | |||
| 551 | (define-minor-mode image-transform-mode | ||
| 552 | "minor mode for scaleing and rotation" | ||
| 553 | nil "image-transform" | ||
| 554 | image-transform-minor-mode-map) | ||
| 555 | |||
| 556 | ;;these are supposed to be buffer local | ||
| 557 | ;(defvar image-transform-height 100);;nil should mean 100% | ||
| 558 | ;;the interface could rather be: | ||
| 559 | (defvar image-transform-resize | ||
| 560 | nil | ||
| 561 | "values: fit-height number=scale nil=scale100% TODO fit-width fit-page" | ||
| 562 | ) | ||
| 563 | |||
| 564 | ;;TODO 0 90 180 270 degrees are the only reasonable angles here | ||
| 565 | ;;otherwise combining with rescaling will get very awkward | ||
| 566 | (defvar image-transform-rotation 0.0) | ||
| 567 | |||
| 568 | ;;then it would be nice with a bunch of globals like: | ||
| 569 | ;; image-transform-always-resize values: 'fit-height nil=100% number=scale TODO 'fit-width 'fit-page | ||
| 570 | ;; image-transform-always-rotate value: angle | ||
| 571 | |||
| 572 | (defun image-transform-properties (display) | ||
| 573 | (let* | ||
| 574 | ((size (image-size display t)) | ||
| 575 | (height | ||
| 576 | (cond | ||
| 577 | ((and (numberp image-transform-resize) (eq 100 image-transform-resize)) | ||
| 578 | nil) | ||
| 579 | ((numberp image-transform-resize) | ||
| 580 | (* image-transform-resize (cdr size))) | ||
| 581 | ((eq image-transform-resize 'fit-height) | ||
| 582 | (nth 3 (window-inside-pixel-edges))) | ||
| 583 | ))) | ||
| 584 | `(,@(if height (list :height height)) | ||
| 585 | ,@(if (not (equal 0.0 image-transform-rotation)) | ||
| 586 | (list :rotation image-transform-rotation)) | ||
| 587 | ))) | ||
| 588 | |||
| 589 | (defun image-transform-set-scale (scale) | ||
| 590 | (interactive "nscale:") | ||
| 591 | (image-transform-set-resize (float scale))) | ||
| 592 | |||
| 593 | (defun image-transform-fit-to-height () | ||
| 594 | (interactive) | ||
| 595 | (image-transform-set-resize 'fit-height)) | ||
| 596 | |||
| 597 | (defun image-transform-set-resize (resize) | ||
| 598 | (setq image-transform-resize resize) | ||
| 599 | (image-toggle-display-image)) | ||
| 600 | |||
| 601 | (defun image-transform-set-rotation (rotation) | ||
| 602 | (interactive "nrotation:") | ||
| 603 | (setq image-transform-rotation (float rotation)) | ||
| 604 | (image-toggle-display-image)) | ||
| 605 | |||
| 537 | (provide 'image-mode) | 606 | (provide 'image-mode) |
| 538 | 607 | ||
| 539 | ;; arch-tag: b5b2b7e6-26a7-4b79-96e3-1546b5c4c6cb | 608 | ;; arch-tag: b5b2b7e6-26a7-4b79-96e3-1546b5c4c6cb |
diff --git a/src/image.c b/src/image.c index 7c6f5645097..217f9221841 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -7592,6 +7592,10 @@ enum imagemagick_keyword_index | |||
| 7592 | IMAGEMAGICK_HEURISTIC_MASK, | 7592 | IMAGEMAGICK_HEURISTIC_MASK, |
| 7593 | IMAGEMAGICK_MASK, | 7593 | IMAGEMAGICK_MASK, |
| 7594 | IMAGEMAGICK_BACKGROUND, | 7594 | IMAGEMAGICK_BACKGROUND, |
| 7595 | IMAGEMAGICK_HEIGHT, | ||
| 7596 | IMAGEMAGICK_WIDTH, | ||
| 7597 | IMAGEMAGICK_ROTATION, | ||
| 7598 | IMAGEMAGICK_CROP, | ||
| 7595 | IMAGEMAGICK_LAST | 7599 | IMAGEMAGICK_LAST |
| 7596 | }; | 7600 | }; |
| 7597 | 7601 | ||
| @@ -7609,7 +7613,11 @@ static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] = | |||
| 7609 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 7613 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 7610 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 7614 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 7611 | {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 7615 | {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 7612 | {":background", IMAGE_STRING_OR_NIL_VALUE, 0} | 7616 | {":background", IMAGE_STRING_OR_NIL_VALUE, 0}, |
| 7617 | {":height", IMAGE_INTEGER_VALUE, 0}, | ||
| 7618 | {":width", IMAGE_INTEGER_VALUE, 0}, | ||
| 7619 | {":rotation", IMAGE_NUMBER_VALUE, 0}, | ||
| 7620 | {":crop", IMAGE_DONT_CHECK_VALUE_TYPE, 0} | ||
| 7613 | }; | 7621 | }; |
| 7614 | /* Free X resources of imagemagick image IMG which is used on frame F. */ | 7622 | /* Free X resources of imagemagick image IMG which is used on frame F. */ |
| 7615 | 7623 | ||
| @@ -7733,14 +7741,15 @@ imagemagick_load_image (/* Pointer to emacs frame structure. */ | |||
| 7733 | MagickSetIteratorIndex(image_wand, ino); | 7741 | MagickSetIteratorIndex(image_wand, ino); |
| 7734 | 7742 | ||
| 7735 | /* If width and/or height is set in the display spec assume we want | 7743 | /* If width and/or height is set in the display spec assume we want |
| 7736 | to scale to those. */ | 7744 | to scale to those values. if either h or w is unspecified, the |
| 7745 | unspecified should be calculated from the specified to preserve | ||
| 7746 | aspect ratio. */ | ||
| 7737 | 7747 | ||
| 7738 | value = image_spec_value (img->spec, QCwidth, NULL); | 7748 | value = image_spec_value (img->spec, QCwidth, NULL); |
| 7739 | desired_width = (INTEGERP (value) ? XFASTINT (value) : -1); | 7749 | desired_width = (INTEGERP (value) ? XFASTINT (value) : -1); |
| 7740 | value = image_spec_value (img->spec, QCheight, NULL); | 7750 | value = image_spec_value (img->spec, QCheight, NULL); |
| 7741 | desired_height = (INTEGERP (value) ? XFASTINT (value) : -1); | 7751 | desired_height = (INTEGERP (value) ? XFASTINT (value) : -1); |
| 7742 | /* TODO if h or w is left out, it should be calculated to preserve aspect ratio */ | 7752 | |
| 7743 | /* get original w and h, these will be recalculated before final blit*/ | ||
| 7744 | height = MagickGetImageHeight (image_wand); | 7753 | height = MagickGetImageHeight (image_wand); |
| 7745 | width = MagickGetImageWidth (image_wand); | 7754 | width = MagickGetImageWidth (image_wand); |
| 7746 | 7755 | ||
| @@ -7796,15 +7805,6 @@ imagemagick_load_image (/* Pointer to emacs frame structure. */ | |||
| 7796 | MagickCropImage(image_wand, w,h, x,y); | 7805 | MagickCropImage(image_wand, w,h, x,y); |
| 7797 | } | 7806 | } |
| 7798 | 7807 | ||
| 7799 | if (STRINGP (crop) && STRINGP (geometry)) | ||
| 7800 | { | ||
| 7801 | printf("MagickTransformImage %s %s\n", SDATA(crop), SDATA(geometry)); | ||
| 7802 | image_wand = MagickTransformImage (image_wand, SDATA (crop), | ||
| 7803 | SDATA (geometry)); | ||
| 7804 | /* TODO differ between image_wand and transform_wand. */ | ||
| 7805 | } | ||
| 7806 | |||
| 7807 | |||
| 7808 | /* Furthermore :rotation. we need background color and angle for | 7808 | /* Furthermore :rotation. we need background color and angle for |
| 7809 | rotation. */ | 7809 | rotation. */ |
| 7810 | /* | 7810 | /* |
| @@ -7830,8 +7830,8 @@ imagemagick_load_image (/* Pointer to emacs frame structure. */ | |||
| 7830 | } | 7830 | } |
| 7831 | } | 7831 | } |
| 7832 | 7832 | ||
| 7833 | /* Finaly we are done manipulating the image, | 7833 | /* Finaly we are done manipulating the image, figure out resulting |
| 7834 | figure out resulting width, height, and then transfer ownerwship to Emacs. | 7834 | width, height, and then transfer ownerwship to Emacs. |
| 7835 | */ | 7835 | */ |
| 7836 | height = MagickGetImageHeight (image_wand); | 7836 | height = MagickGetImageHeight (image_wand); |
| 7837 | width = MagickGetImageWidth (image_wand); | 7837 | width = MagickGetImageWidth (image_wand); |
| @@ -7866,9 +7866,7 @@ imagemagick_load_image (/* Pointer to emacs frame structure. */ | |||
| 7866 | 7866 | ||
| 7867 | /* Copy imagegmagick image to x with primitive yet robust pixel | 7867 | /* Copy imagegmagick image to x with primitive yet robust pixel |
| 7868 | pusher loop. This has been tested a lot with many different | 7868 | pusher loop. This has been tested a lot with many different |
| 7869 | images, it doesnt work too well with image archive formats though! | 7869 | images. |
| 7870 | |||
| 7871 | Also seems slow. | ||
| 7872 | */ | 7870 | */ |
| 7873 | 7871 | ||
| 7874 | /* Copy pixels from the imagemagick image structure to the x image map. */ | 7872 | /* Copy pixels from the imagemagick image structure to the x image map. */ |
| @@ -7901,10 +7899,6 @@ imagemagick_load_image (/* Pointer to emacs frame structure. */ | |||
| 7901 | if (imagemagick_rendermethod == 1) | 7899 | if (imagemagick_rendermethod == 1) |
| 7902 | { | 7900 | { |
| 7903 | /* Try if magicexportimage is any faster than pixelpushing. */ | 7901 | /* Try if magicexportimage is any faster than pixelpushing. */ |
| 7904 | /* printf("ximg: bitmap_unit:%d format:%d byte_order:%d depth:%d | ||
| 7905 | bits_per_pixel:%d\n", */ | ||
| 7906 | /* ximg->bitmap_unit,ximg->format,ximg->byte_order, | ||
| 7907 | ximg->depth,ximg->bits_per_pixel); */ | ||
| 7908 | int imagedepth = 24;/*MagickGetImageDepth(image_wand);*/ | 7902 | int imagedepth = 24;/*MagickGetImageDepth(image_wand);*/ |
| 7909 | char* exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/ | 7903 | char* exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/ |
| 7910 | /* Try to create a x pixmap to hold the imagemagick pixmap. */ | 7904 | /* Try to create a x pixmap to hold the imagemagick pixmap. */ |