changeset 109866:73512e4aa257

image-mode changes. removed the imagemagick specific :geometry and :crop interface that wasnt very good.
author Joakim <joakim@localhost.localdomain>
date Sat, 26 Jun 2010 23:17:02 +0200
parents 131c45ff9c34
children 7b3550d93e3a
files README.imagemagick lisp/image-mode.el src/image.c
diffstat 3 files changed, 98 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/README.imagemagick	Mon Jun 21 20:19:25 2010 +0200
+++ b/README.imagemagick	Sat Jun 26 23:17:02 2010 +0200
@@ -27,11 +27,21 @@
   the bundle. This feature is not the primary usecase for the
   imagemagick patch though.
 
+- optimize number of pages calculation for bundles as suggested by
+  imagemagick forum: "set the density to something low like 2 and use
+  MagickPingImage()"
+  
 - zooming the image like what is done for fonts in face-remap.el would
-  be a useful and demo friendly addition.
+  be a useful and demo friendly addition. Some work has been done on
+  image-mode.el to acihieve this.
 
-- figure out what to do with the experimental features noted below.  
+- look for optimizations for handling images with low depth
+  
+- it would be neat if the graphicsmagick fork of imagemagick could
+  optionaly be used.
 
+
+  
 * TODO
 #B _ complete documentation drafts below
 
@@ -120,41 +130,6 @@
 The image-metadata function can be used to retrieve the total number
 of images in an image bundle. This is simmilar to how GIF files work.
 
-* experimental
-
-- :crop is used to specify a croping area: (width height x y).  This
-is similar to the slice image specification, but has a different
-purpose. :crop removes the croped areas from memory, so its memory
-efficient if you only need to view a certain part of the image. The
-slice specification can be used to pick diferent parts of the same
-image, so its more disk and display efficient. :crop works well, but
-it would still be better to find a way to have :splice do the same
-thing.
-
-- :geometry takes a geometry string as defined by ImageMagick:
-
-scale%            
-scale-x%xscale-y% 
-width             
-xheight           
-widthxheight      
-widthxheight^     
-widthxheight!     
-widthxheight>     
-widthxheight<     
-area@             
-{size}{offset}
-{size}{+-}x{+-}y
-
-See the ImageMagick manual for more information.
-
-- :crop is used to specify a croping area, with the "{size}{offset}" syntax.
-
-:geometry and :crop with a string argument, are both particular to
-ImageMagick, whereas the lisp interface is more general. Currently it
-seems like the lisp interface is good enough, so the string argument
-interface will probably be removed.
-
 * Changelog entry
 2010-06-12 Joakim Verona <joakim@verona.se>
            * image.c: Add support for ImageMagick. When HAVE_IMAGEMAGICK is
--- a/lisp/image-mode.el	Mon Jun 21 20:19:25 2010 +0200
+++ b/lisp/image-mode.el	Sat Jun 26 23:17:02 2010 +0200
@@ -471,7 +471,10 @@
 			    (buffer-substring-no-properties (point-min) (point-max)))
 			 filename))
 	 (type (image-type file-or-data nil data-p))
-	 (image (create-animated-image file-or-data type data-p))
+         (image0 (create-animated-image file-or-data type data-p))
+	 (image (append image0
+                        (image-transform-properties image0)
+                        ))
 	 (props
 	  `(display ,image
 		    intangible ,image
@@ -534,6 +537,72 @@
     (when (not (string= image-type (bookmark-prop-get bmk 'image-type)))
       (image-toggle-display))))
 
+
+(defvar image-transform-minor-mode-map
+  (let ((map (make-sparse-keymap)))
+;    (define-key map  [(control ?+)] 'image-scale-in)
+;    (define-key map  [(control ?-)] 'image-scale-out)
+;    (define-key map  [(control ?=)] 'image-scale-none)
+;;    (define-key map "c f h" 'image-scale-fit-height)    
+;;    (define-key map "c ]" 'image-rotate-right)            
+    map)
+  "Minor mode keymap for transforming the view of images Image mode.")
+
+(define-minor-mode image-transform-mode
+  "minor mode for scaleing and rotation"
+  nil "image-transform"
+  image-transform-minor-mode-map)
+
+;;these are supposed to be buffer local
+;(defvar image-transform-height 100);;nil should mean 100%
+;;the interface could rather be:
+(defvar image-transform-resize
+  nil
+  "values: fit-height  number=scale nil=scale100% TODO fit-width fit-page"
+  )
+
+;;TODO 0 90 180 270 degrees are the only reasonable angles here
+;;otherwise combining with rescaling will get very awkward
+(defvar image-transform-rotation 0.0)
+
+;;then it would be nice with a bunch of globals like:
+;; image-transform-always-resize values: 'fit-height nil=100% number=scale TODO  'fit-width 'fit-page
+;; image-transform-always-rotate value: angle
+
+(defun image-transform-properties (display)
+  (let*
+      ((size (image-size display t))
+       (height
+        (cond
+         ((and (numberp image-transform-resize) (eq 100 image-transform-resize))
+          nil)
+         ((numberp image-transform-resize)
+          (* image-transform-resize (cdr size)))
+         ((eq image-transform-resize 'fit-height)
+          (nth 3 (window-inside-pixel-edges)))
+         )))
+       `(,@(if height (list :height height))
+         ,@(if (not (equal 0.0 image-transform-rotation))
+               (list :rotation image-transform-rotation))
+        )))
+
+(defun image-transform-set-scale (scale)
+  (interactive "nscale:")
+  (image-transform-set-resize (float scale)))
+
+(defun image-transform-fit-to-height ()
+  (interactive)
+  (image-transform-set-resize 'fit-height))
+
+(defun image-transform-set-resize (resize)
+  (setq image-transform-resize resize)
+  (image-toggle-display-image))
+
+(defun image-transform-set-rotation (rotation)
+  (interactive "nrotation:")
+  (setq image-transform-rotation (float rotation))
+  (image-toggle-display-image))
+
 (provide 'image-mode)
 
 ;; arch-tag: b5b2b7e6-26a7-4b79-96e3-1546b5c4c6cb
--- a/src/image.c	Mon Jun 21 20:19:25 2010 +0200
+++ b/src/image.c	Sat Jun 26 23:17:02 2010 +0200
@@ -7592,6 +7592,10 @@
     IMAGEMAGICK_HEURISTIC_MASK,
     IMAGEMAGICK_MASK,
     IMAGEMAGICK_BACKGROUND,
+    IMAGEMAGICK_HEIGHT,
+    IMAGEMAGICK_WIDTH,
+    IMAGEMAGICK_ROTATION,
+    IMAGEMAGICK_CROP,
     IMAGEMAGICK_LAST
   };
 
@@ -7609,7 +7613,11 @@
     {":conversion",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
     {":heuristic-mask",	IMAGE_DONT_CHECK_VALUE_TYPE,		0},
     {":mask",		IMAGE_DONT_CHECK_VALUE_TYPE,		0},
-    {":background",	IMAGE_STRING_OR_NIL_VALUE,		0}
+    {":background",	IMAGE_STRING_OR_NIL_VALUE,		0},
+    {":height",		IMAGE_INTEGER_VALUE,			0},    
+    {":width",		IMAGE_INTEGER_VALUE,			0},    
+    {":rotation",	IMAGE_NUMBER_VALUE,     		0},    
+    {":crop",		IMAGE_DONT_CHECK_VALUE_TYPE,		0}
   };
 /* Free X resources of imagemagick image IMG which is used on frame F.  */
 
@@ -7733,14 +7741,15 @@
     MagickSetIteratorIndex(image_wand, ino);
 
   /* If width and/or height is set in the display spec assume we want
-    to scale to those.  */
+    to scale to those values.  if either h or w is unspecified, the
+    unspecified should be calculated from the specified to preserve
+    aspect ratio. */
 
   value = image_spec_value (img->spec, QCwidth, NULL);
   desired_width = (INTEGERP (value)  ? XFASTINT (value) : -1);
   value = image_spec_value (img->spec, QCheight, NULL);
   desired_height = (INTEGERP (value) ? XFASTINT (value) : -1);
-  /* TODO if h or w is left out, it should be calculated to preserve aspect ratio */
-  /* get original w and h, these will be recalculated before final blit*/
+
   height = MagickGetImageHeight (image_wand);
   width = MagickGetImageWidth (image_wand);
 
@@ -7796,15 +7805,6 @@
       MagickCropImage(image_wand, w,h, x,y);
     }
   
-  if (STRINGP (crop) && STRINGP (geometry))
-    {
-      printf("MagickTransformImage %s %s\n", SDATA(crop), SDATA(geometry));
-      image_wand = MagickTransformImage (image_wand, SDATA (crop),
-                                         SDATA (geometry));
-      /* TODO differ between image_wand and transform_wand. */
-    }
-
-  
   /* Furthermore :rotation. we need background color and angle for
      rotation.  */
   /*
@@ -7830,8 +7830,8 @@
         }
     }
   
-  /* Finaly we are done manipulating the image,
-     figure out resulting width, height, and then transfer ownerwship to Emacs.
+  /* Finaly we are done manipulating the image, figure out resulting
+     width, height, and then transfer ownerwship to Emacs.
   */
   height = MagickGetImageHeight (image_wand);
   width = MagickGetImageWidth (image_wand);
@@ -7866,9 +7866,7 @@
     
       /* Copy imagegmagick image to x with primitive yet robust pixel
          pusher loop.  This has been tested a lot with many different
-         images, it doesnt work too well with image archive formats though!
-
-         Also seems slow.
+         images.
       */
   
       /* Copy pixels from the imagemagick image structure to the x image map. */
@@ -7901,10 +7899,6 @@
   if (imagemagick_rendermethod == 1)
     {
       /* Try if magicexportimage is any faster than pixelpushing. */
-      /* printf("ximg: bitmap_unit:%d format:%d byte_order:%d depth:%d
-         bits_per_pixel:%d\n", */
-      /*        ximg->bitmap_unit,ximg->format,ximg->byte_order,
-                ximg->depth,ximg->bits_per_pixel); */
       int imagedepth = 24;/*MagickGetImageDepth(image_wand);*/
       char* exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/
       /* Try to create a x pixmap to hold the imagemagick pixmap.  */