unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* imagemagick patch v3
@ 2009-08-04 19:55 joakim
  2009-08-05  0:43 ` joakim
  0 siblings, 1 reply; 8+ messages in thread
From: joakim @ 2009-08-04 19:55 UTC (permalink / raw)
  To: Emacs Development

[-- Attachment #1: Type: text/plain, Size: 931 bytes --]

Hello,

This is the third stab at native imagemagick support for emacs.

New features:
- :rotation image spec, to rotate image arbitrarily
- :width and :height, if you specify them image will be scaled to these
sizes
- :geometry and :crop, imagemagick specifyers for size and croping, see
imagemagick docs
- :index, show a particular image within an image archive format(its
possible to see a particular page in a pdf for instance)

Ok, those features work somewhat well. What doesnt work, and which I
would like some help with, is how to make emacs automagically recognize
that a image file type is handled by the imagemagick loader. There is
some half-baked code in the patch that doesnt work for this.

Heres some test code:

make && src/emacs -q --eval "(progn (insert \"mupp\")(put-text-property 1 2 'display (list 'image :file \"/tmp/24725.pdf\" :type 'imagemagick :index 0  :geometry \"50%\" :crop \"\" :rotation 90.0) ))"


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: imagemagick3.patch --]
[-- Type: text/x-patch, Size: 17983 bytes --]

diff --git a/configure.in b/configure.in
index f4096db..c4207d8 100644
--- a/configure.in
+++ b/configure.in
@@ -132,6 +132,8 @@ OPTION_DEFAULT_ON([tiff],[don't compile with TIFF image support])
 OPTION_DEFAULT_ON([gif],[don't compile with GIF image support])
 OPTION_DEFAULT_ON([png],[don't compile with PNG image support])
 OPTION_DEFAULT_ON([rsvg],[don't compile with SVG image support])
+OPTION_DEFAULT_OFF([imagemagick],[compile with ImageMagick image support])
+
 
 OPTION_DEFAULT_ON([xft],[don't use XFT for anti aliased fonts])
 OPTION_DEFAULT_ON([libotf],[don't use libotf for OpenType font support])
@@ -142,6 +144,8 @@ OPTION_DEFAULT_ON([xaw3d],[don't use Xaw3d])
 OPTION_DEFAULT_ON([xim],[don't use X11 XIM])
 OPTION_DEFAULT_OFF([ns],[use nextstep (Cocoa or GNUstep) windowing system])
 
+
+
 OPTION_DEFAULT_ON([gpm],[don't use -lgpm for mouse support on a GNU/Linux console])
 OPTION_DEFAULT_ON([dbus],[don't compile with D-Bus support])
 
@@ -1589,6 +1593,24 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes"; then
   fi
 fi
 
+HAVE_IMAGEMAGICK=no
+if test "${HAVE_X11}" = "yes" ; then
+  if test "${with_imagemagick}" != "no"; then
+    IMAGEMAGICK_REQUIRED=1
+    IMAGEMAGICK_MODULE="MagickWand >= $IMAGEMAGICK_REQUIRED"
+
+    PKG_CHECK_MODULES(IMAGEMAGICK, $IMAGEMAGICK_MODULE, :, :)
+    AC_SUBST(IMAGEMAGICK_CFLAGS)
+    AC_SUBST(IMAGEMAGICK_LIBS)
+
+    if test ".${IMAGEMAGICK_CFLAGS}" != "."; then
+      HAVE_IMAGEMAGICK=yes
+      AC_DEFINE(HAVE_IMAGEMAGICK, 1, [Define to 1 if using imagemagick.])
+      CFLAGS="$CFLAGS $IMAGEMAGICK_CFLAGS"
+      LIBS="$IMAGEMAGICK_LIBS $LIBS"
+    fi    
+  fi
+fi
 
 HAVE_GTK=no
 if test "${with_gtk}" = "yes" || test "$USE_X_TOOLKIT" = "maybe"; then
@@ -2952,6 +2974,7 @@ echo "  Does Emacs use -ltiff?                                  ${HAVE_TIFF}"
 echo "  Does Emacs use a gif library?                           ${HAVE_GIF} $ac_gif_lib_name"
 echo "  Does Emacs use -lpng?                                   ${HAVE_PNG}"
 echo "  Does Emacs use -lrsvg-2?                                ${HAVE_RSVG}"
+echo "  Does Emacs use imagemagick?                             ${HAVE_IMAGEMAGICK}"
 echo "  Does Emacs use -lgpm?                                   ${HAVE_GPM}"
 echo "  Does Emacs use -ldbus?                                  ${HAVE_DBUS}"
 
diff --git a/lisp/image.el b/lisp/image.el
index 076a969..a102ffb 100644
--- a/lisp/image.el
+++ b/lisp/image.el
@@ -70,6 +70,7 @@ a non-nil value, TYPE is the image's type.")
     ("\\.ps\\'" . postscript)
     ("\\.tiff?\\'" . tiff)
     ("\\.svgz?\\'" . svg)
+    ("\\.xcf?\\'" . imagemagick)
     )
   "Alist of (REGEXP . IMAGE-TYPE) pairs used to identify image files.
 When the name of an image file match REGEXP, it is assumed to
diff --git a/src/Makefile.in b/src/Makefile.in
index 425cf98..797d6fb 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -253,7 +253,7 @@ DBUS_OBJ = dbusbind.o
 
 /* C_SWITCH_X_SITE must come before C_SWITCH_X_MACHINE and C_SWITCH_X_SYSTEM
    since it may have -I options that should override those two.  */
-ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(MYCPPFLAGS) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM C_SWITCH_SYSTEM_TEMACS ${CFLAGS_SOUND} ${RSVG_CFLAGS} ${DBUS_CFLAGS} ${CFLAGS} @FREETYPE_CFLAGS@ @FONTCONFIG_CFLAGS@ @LIBOTF_CFLAGS@ @M17N_FLT_CFLAGS@
+ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(MYCPPFLAGS) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM C_SWITCH_SYSTEM_TEMACS ${CFLAGS_SOUND} ${RSVG_CFLAGS} ${IMAGEMAGICK_CFLAGS}  ${DBUS_CFLAGS} ${CFLAGS} @FREETYPE_CFLAGS@ @FONTCONFIG_CFLAGS@ @LIBOTF_CFLAGS@ @M17N_FLT_CFLAGS@
 ALL_OBJC_CFLAGS=$(ALL_CFLAGS) @GNU_OBJC_CFLAGS@
 
 .SUFFIXES: .m
@@ -425,6 +425,9 @@ CFLAGS_SOUND= @CFLAGS_SOUND@
 RSVG_LIBS= @RSVG_LIBS@
 RSVG_CFLAGS= @RSVG_CFLAGS@
 
+IMAGEMAGICK_LIBS= @IMAGEMAGICK_LIBS@
+IMAGEMAGICK_CFLAGS= @IMAGEMAGICK_CFLAGS@
+
 #ifndef ORDINARY_LINK
 /* Fix linking if compiled with GCC.  */
 #ifdef __GNUC__
@@ -878,7 +881,7 @@ SOME_MACHINE_LISP = ../lisp/mouse.elc \
    duplicated symbols.  If the standard libraries were compiled
    with GCC, we might need gnulib again after them.  */
 
-LIBES = $(LOADLIBES) $(LIBS) $(LIBX) $(LIBSOUND) $(RSVG_LIBS) $(DBUS_LIBS) \
+LIBES = $(LOADLIBES) $(LIBS) $(LIBX) $(LIBSOUND) $(RSVG_LIBS) ${IMAGEMAGICK_LIBS} $(DBUS_LIBS) \
    LIBGPM LIBRESOLV LIBS_SYSTEM LIBS_MACHINE LIBS_TERMCAP \
    LIBS_DEBUG $(GETLOADAVG_LIBS) \
    @FREETYPE_LIBS@ @FONTCONFIG_LIBS@ @LIBOTF_LIBS@ @M17N_FLT_LIBS@ \
diff --git a/src/config.in b/src/config.in
index 404e00b..111de5d 100644
--- a/src/config.in
+++ b/src/config.in
@@ -547,6 +547,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 /* Define to 1 if using librsvg. */
 #undef HAVE_RSVG
 
+/* Define to 1 if using imagemagick. */
+#undef HAVE_IMAGEMAGICK
+
 /* Define to 1 if you have the `select' function. */
 #undef HAVE_SELECT
 
diff --git a/src/image.c b/src/image.c
index fa8c3ea..e9ed2c6 100644
--- a/src/image.c
+++ b/src/image.c
@@ -838,7 +838,7 @@ extern Lisp_Object QCdata, QCtype;
 extern Lisp_Object Qcenter;
 Lisp_Object QCascent, QCmargin, QCrelief, Qcount;
 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
-Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
+Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask, QCgeometry, QCcrop, QCrotation;
 
 /* Other symbols.  */
 
@@ -7771,6 +7771,339 @@ gif_load (struct frame *f, struct image *img)
 #endif /* HAVE_GIF */
 
 
+/***********************************************************************
+				 imagemagick
+ ***********************************************************************/
+#if defined (HAVE_IMAGEMAGICK)
+
+/* Function prototypes.  */
+
+static int imagemagick_image_p P_ ((Lisp_Object object));
+static int imagemagick_load P_ ((struct frame *f, struct image *img));
+
+static int imagemagick_load_image P_ ((struct frame *, struct image *,
+			       unsigned char *, unsigned int));
+
+/* The symbol `imagemagick' identifying images of this type. */
+
+Lisp_Object Qimagemagick;
+
+/* Indices of image specification fields in imagemagick_format, below.  */
+
+enum imagemagick_keyword_index
+{
+  IMAGEMAGICK_TYPE,
+  IMAGEMAGICK_DATA,
+  IMAGEMAGICK_FILE,
+  IMAGEMAGICK_ASCENT,
+  IMAGEMAGICK_MARGIN,
+  IMAGEMAGICK_RELIEF,
+  IMAGEMAGICK_ALGORITHM,
+  IMAGEMAGICK_HEURISTIC_MASK,
+  IMAGEMAGICK_MASK,
+  IMAGEMAGICK_BACKGROUND,
+  IMAGEMAGICK_LAST
+};
+
+/* Vector of image_keyword structures describing the format
+   of valid user-defined image specifications.  */
+
+static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] =
+{
+  {":type",		IMAGE_SYMBOL_VALUE,			1},
+  {":data",		IMAGE_STRING_VALUE,			0},
+  {":file",		IMAGE_STRING_VALUE,			0},
+  {":ascent",		IMAGE_ASCENT_VALUE,			0},
+  {":margin",		IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,	0},
+  {":relief",		IMAGE_INTEGER_VALUE,			0},
+  {":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}
+};
+
+/* Structure describing the image type `imagemagick'.  Its the same type of
+   structure defined for all image formats, handled by emacs image
+   functions.  See struct image_type in dispextern.h.  */
+
+static struct image_type imagemagick_type =
+{
+  /* An identifier showing that this is an image structure for the IMAGEMAGICK format.  */
+  &Qimagemagick,
+  /* Handle to a function that can be used to identify a IMAGEMAGICK file.  */
+  imagemagick_image_p,
+  /* Handle to function used to load a IMAGEMAGICK file.  */
+  imagemagick_load,
+  /* Handle to function to free resources for IMAGEMAGICK.  */
+  x_clear_image,
+  /* An internal field to link to the next image type in a list of
+     image types, will be filled in when registering the format.  */
+  NULL
+};
+
+
+/* Return non-zero if OBJECT is a valid IMAGEMAGICK image specification.  Do
+   this by calling parse_image_spec and supplying the keywords that
+   identify the IMAGEMAGICK format.   */
+
+static int
+imagemagick_image_p (object)
+     Lisp_Object object;
+{
+  struct image_keyword fmt[IMAGEMAGICK_LAST];
+  bcopy (imagemagick_format, fmt, sizeof fmt);
+
+  if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, Qimagemagick))
+    return 0;
+
+  /* Must specify either the :data or :file keyword.  */
+  return fmt[IMAGEMAGICK_FILE].count + fmt[IMAGEMAGICK_DATA].count == 1;
+}
+
+/* The GIF library also defines DrawRectangle, but its never used in Emacs.
+   Therefore rename the function so it doesnt collide with ImageMagick */
+#define DrawRectangle DrawRectangleGif
+#include <wand/MagickWand.h>
+
+/* Load IMAGEMAGICK image IMG for use on frame F.  Value is non-zero if
+   successful. this function will go into the imagemagick_type structure, and
+   the prototype thus needs to be compatible with that structure.  */
+
+static int
+imagemagick_load (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  int success_p = 0;
+  Lisp_Object file_name;
+
+  /* If IMG->spec specifies a file name, create a non-file spec from it.  */
+  file_name = image_spec_value (img->spec, QCfile, NULL);
+  if (STRINGP (file_name))
+    {
+      Lisp_Object file;
+      unsigned char *contents;
+      int size;
+      struct gcpro gcpro1;
+
+      file = x_find_image_file (file_name);
+      GCPRO1 (file);
+      if (!STRINGP (file))
+	{
+	  image_error ("Cannot find image file `%s'", file_name, Qnil);
+	  UNGCPRO;
+	  return 0;
+	}
+
+      /* Read the entire file into memory.  */
+      contents = slurp_file (SDATA (file), &size);
+      if (contents == NULL)
+	{
+	  image_error ("Error loading IMAGEMAGICK image `%s'", img->spec, Qnil);
+	  UNGCPRO;
+	  return 0;
+	}
+      /* If the file was slurped into memory properly, parse it.  */
+      success_p = imagemagick_load_image (f, img, contents, size);
+      xfree (contents);
+      UNGCPRO;
+    }
+  /* Else its not a file, its a lisp object.  Load the image from a
+     lisp object rather than a file.  */
+  else
+    {
+      Lisp_Object data;
+
+      data = image_spec_value (img->spec, QCdata, NULL);
+      success_p = imagemagick_load_image (f, img, SDATA (data), SBYTES (data));
+    }
+
+  return success_p;
+}
+
+/* imagemagick_load_image is a helper function for imagemagick_load, which does the
+   actual loading given contents and size, apart from frame and image
+   structures, passed from imagemagick_load.
+
+   Uses librimagemagick to do most of the image processing.
+
+   Returns non-zero when successful.
+*/
+
+static int
+imagemagick_load_image (f, img, contents, size)
+    /* Pointer to emacs frame structure.  */
+     struct frame *f;
+     /* Pointer to emacs image structure.  */
+     struct image *img;
+     /* String containing the IMAGEMAGICK  data to be parsed.  */
+     unsigned char *contents;
+     /* Size of data in bytes.  */
+     unsigned int size;
+{
+  long unsigned int width;
+  long unsigned int height;
+
+  MagickBooleanType
+    status;
+
+  XImagePtr ximg;
+  Lisp_Object specified_bg;
+  XColor background;
+  int x;
+  int y;
+
+  MagickWand  *image_wand;
+  PixelIterator *iterator;
+  PixelWand  **pixels;
+  MagickPixelPacket  pixel;
+
+  
+  /* image_wand will contain the image  */
+  image_wand=NewMagickWand();  
+
+  /* Parse the contents argument and fill in the rimagemagick_handle.  */
+  //status=MagickReadImage(image_wand, "/tmp/tst.djvu");
+  status=MagickReadImageBlob(image_wand, contents, size);
+  if (status == MagickFalse) goto imagemagick_error;
+
+  /* handle image index for image types who can contain more than one image.
+   interface :index is same as for GIF */
+  Lisp_Object image;
+  long ino;
+  image = image_spec_value (img->spec, QCindex, NULL);
+  ino = INTEGERP (image) ? XFASTINT (image) : 0;
+  
+  /* if (ino >= ) */
+  /*   { */
+  /*     image_error ("Invalid image number `%s' in image `%s'", */
+  /*       	   image, img->spec); */
+  /*     UNGCPRO; */
+  /*     return 0; */
+  /*   } */
+
+  MagickSetIteratorIndex(image_wand, ino);
+
+  /*
+    if width and/or height is set in the display spec
+    assume we want to scale to those */
+
+  int desired_width, desired_height;
+  Lisp_Object value;  
+  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);
+  if(desired_width != -1 && desired_height != -1){
+    printf("MagickScaleImage %d %d\n",desired_width, desired_height);
+    MagickScaleImage(image_wand, desired_width, desired_height);
+  }
+
+  /* also support :geometry and :crop which are imagemagick specific descriptors */
+
+  Lisp_Object crop, geometry;
+  crop     = image_spec_value (img->spec, QCcrop, NULL);
+  geometry = image_spec_value (img->spec, QCgeometry, NULL);
+  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 */
+
+  /*
+    specified_bg = image_spec_value (img->spec, QCbackground, NULL);
+  if (!STRINGP (specified_bg)
+  */
+    double rotation;
+    value = image_spec_value (img->spec, QCrotation, NULL);
+    if(FLOATP(value)){
+      PixelWand* background = NewPixelWand();
+      PixelSetColor(background,"#ffffff");
+
+      rotation=extract_float(value);
+      printf("MagickRotateImage %f\n",rotation);
+      
+      status=MagickRotateImage(image_wand, background,rotation);
+    }
+  
+  /* finaly we are done manipulating the image,
+     figure resulting width, height, and then transfer ownerwship to emacs
+   */
+  height=MagickGetImageHeight(image_wand);
+  width=MagickGetImageWidth(image_wand);
+  if (status == MagickFalse) goto imagemagick_error;
+
+  
+
+    
+  if (! check_image_size (f, width, height))
+    {
+      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+      goto imagemagick_error;
+    }
+  
+  /* We can now get a valid pixel buffer from the imagemagick file, if all
+     went ok.  */
+
+
+  
+  /* Try to create a x pixmap to hold the imagemagick pixmap.  */
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
+    {
+      return 0;
+    }
+
+  init_color_table ();
+
+  /* copy pixels from the imagemagick image structure to the x image map */
+  iterator=NewPixelIterator(image_wand);
+  if ((iterator == (PixelIterator *) NULL)) goto imagemagick_error;
+
+  for (y=0; y < (long) MagickGetImageHeight(image_wand); y++)
+  {
+    pixels=PixelGetNextIteratorRow(iterator,&width);
+    if ((pixels == (PixelWand **) NULL))
+      break;
+    for (x=0; x < (long) width; x++)
+    {
+      PixelGetMagickColor(pixels[x],&pixel);
+      XPutPixel (ximg, x, y, lookup_rgb_color (f, pixel.red, pixel.green, pixel.blue));      
+    }
+  }
+  
+#ifdef COLOR_TABLE_SUPPORT
+  /* Remember colors allocated for this image.  */
+  img->colors = colors_in_color_table (&img->ncolors);
+  free_color_table ();
+#endif /* COLOR_TABLE_SUPPORT */
+
+
+  img->width  = width;
+  img->height = height;
+
+  /* Maybe fill in the background field while we have ximg handy.
+     Casting avoids a GCC warning.  */
+  IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
+
+  /* Put the image into the pixmap, then free the X image and its
+     buffer.  */
+  x_put_x_image (f, ximg, img->pixmap, width, height);
+  x_destroy_x_image (ximg);
+
+  //JAVE TODO lots of cleanup
+  
+  return 1;
+
+ imagemagick_error:
+  image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil);
+  return 0;
+}
+
+#endif	/* defined (HAVE_IMAGEMAGICK) */
+
+
 \f
 /***********************************************************************
 				 SVG
@@ -8568,6 +8901,14 @@ of `image-library-alist', which see).  */)
     return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries);
 #endif
 
+#if defined (HAVE_IMAGEMAGICK)
+  if (EQ (type, Qimagemagick)){
+    /*   MagickWandGenesis() initalizes the imagemagick library */
+    MagickWandGenesis(); 
+    return CHECK_LIB_AVAILABLE (&imagemagick_type, init_imagemagick_functions, libraries);
+  }
+#endif
+
 #ifdef HAVE_GHOSTSCRIPT
   if (EQ (type, Qpostscript))
     return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries);
@@ -8653,6 +8994,12 @@ non-numeric, there is no explicit limit on the size of images.  */);
   staticpro (&QCheuristic_mask);
   QCindex = intern (":index");
   staticpro (&QCindex);
+  QCgeometry = intern (":geometry");
+  staticpro (&QCgeometry);
+  QCcrop = intern (":crop");
+  staticpro (&QCcrop);
+  QCrotation = intern (":rotation");
+  staticpro (&QCrotation);
   QCmatrix = intern (":matrix");
   staticpro (&QCmatrix);
   QCcolor_adjustment = intern (":color-adjustment");
@@ -8713,6 +9060,12 @@ non-numeric, there is no explicit limit on the size of images.  */);
   ADD_IMAGE_TYPE (Qpng);
 #endif
 
+#if defined (HAVE_IMAGEMAGICK)
+  Qimagemagick = intern ("imagemagick");
+  staticpro (&Qimagemagick);
+  ADD_IMAGE_TYPE (Qimagemagick);
+#endif
+  
 #if defined (HAVE_RSVG)
   Qsvg = intern ("svg");
   staticpro (&Qsvg);
@@ -8761,6 +9114,20 @@ meaning don't clear the cache.  */);
 void
 init_image ()
 {
+  //register imagegemagick types here, they are dynamic
+  unsigned long numf;
+  ExceptionInfo ex;
+  char** imtypes = GetMagickList("*", &numf,&ex);
+  int i;
+  Lisp_Object Qimagemagicktype;
+  for (i = 0; i < numf; i++) {
+    printf("immagick format::%s\n", *(imtypes+i));
+    Qimagemagicktype = intern ( *(imtypes+i)) ;
+    //staticpro (&Qpng);
+    ADD_IMAGE_TYPE (Qimagemagicktype);
+  }
+
+
 }
 
 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9

[-- Attachment #3: Type: text/plain, Size: 18 bytes --]

-- 
Joakim Verona

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: imagemagick patch v3
  2009-08-04 19:55 imagemagick patch v3 joakim
@ 2009-08-05  0:43 ` joakim
  2009-08-05  2:15   ` Stefan Monnier
  0 siblings, 1 reply; 8+ messages in thread
From: joakim @ 2009-08-05  0:43 UTC (permalink / raw)
  To: Emacs Development

[-- Attachment #1: Type: text/plain, Size: 1138 bytes --]

joakim@verona.se writes:

> Hello,
>
> This is the third stab at native imagemagick support for emacs.
>
> New features:
> - :rotation image spec, to rotate image arbitrarily
> - :width and :height, if you specify them image will be scaled to these
> sizes
> - :geometry and :crop, imagemagick specifyers for size and croping, see
> imagemagick docs
> - :index, show a particular image within an image archive format(its
> possible to see a particular page in a pdf for instance)
>
> Ok, those features work somewhat well. What doesnt work, and which I
> would like some help with, is how to make emacs automagically recognize
> that a image file type is handled by the imagemagick loader. There is
> some half-baked code in the patch that doesnt work for this.

Attached is v4, which has better support for the above issue.
Call (imagemagick-register-types) to register all types handled by imagemagick.

> Heres some test code:
>
> make && src/emacs -q --eval "(progn (insert \"mupp\")(put-text-property 1 2 'display (list 'image :file \"/tmp/24725.pdf\" :type 'imagemagick :index 0  :geometry \"50%\" :crop \"\" :rotation 90.0) ))"
>


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: imagemagick4.patch --]
[-- Type: text/x-patch, Size: 19621 bytes --]

diff --git a/configure.in b/configure.in
index f4096db..c4207d8 100644
--- a/configure.in
+++ b/configure.in
@@ -132,6 +132,8 @@ OPTION_DEFAULT_ON([tiff],[don't compile with TIFF image support])
 OPTION_DEFAULT_ON([gif],[don't compile with GIF image support])
 OPTION_DEFAULT_ON([png],[don't compile with PNG image support])
 OPTION_DEFAULT_ON([rsvg],[don't compile with SVG image support])
+OPTION_DEFAULT_OFF([imagemagick],[compile with ImageMagick image support])
+
 
 OPTION_DEFAULT_ON([xft],[don't use XFT for anti aliased fonts])
 OPTION_DEFAULT_ON([libotf],[don't use libotf for OpenType font support])
@@ -142,6 +144,8 @@ OPTION_DEFAULT_ON([xaw3d],[don't use Xaw3d])
 OPTION_DEFAULT_ON([xim],[don't use X11 XIM])
 OPTION_DEFAULT_OFF([ns],[use nextstep (Cocoa or GNUstep) windowing system])
 
+
+
 OPTION_DEFAULT_ON([gpm],[don't use -lgpm for mouse support on a GNU/Linux console])
 OPTION_DEFAULT_ON([dbus],[don't compile with D-Bus support])
 
@@ -1589,6 +1593,24 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes"; then
   fi
 fi
 
+HAVE_IMAGEMAGICK=no
+if test "${HAVE_X11}" = "yes" ; then
+  if test "${with_imagemagick}" != "no"; then
+    IMAGEMAGICK_REQUIRED=1
+    IMAGEMAGICK_MODULE="MagickWand >= $IMAGEMAGICK_REQUIRED"
+
+    PKG_CHECK_MODULES(IMAGEMAGICK, $IMAGEMAGICK_MODULE, :, :)
+    AC_SUBST(IMAGEMAGICK_CFLAGS)
+    AC_SUBST(IMAGEMAGICK_LIBS)
+
+    if test ".${IMAGEMAGICK_CFLAGS}" != "."; then
+      HAVE_IMAGEMAGICK=yes
+      AC_DEFINE(HAVE_IMAGEMAGICK, 1, [Define to 1 if using imagemagick.])
+      CFLAGS="$CFLAGS $IMAGEMAGICK_CFLAGS"
+      LIBS="$IMAGEMAGICK_LIBS $LIBS"
+    fi    
+  fi
+fi
 
 HAVE_GTK=no
 if test "${with_gtk}" = "yes" || test "$USE_X_TOOLKIT" = "maybe"; then
@@ -2952,6 +2974,7 @@ echo "  Does Emacs use -ltiff?                                  ${HAVE_TIFF}"
 echo "  Does Emacs use a gif library?                           ${HAVE_GIF} $ac_gif_lib_name"
 echo "  Does Emacs use -lpng?                                   ${HAVE_PNG}"
 echo "  Does Emacs use -lrsvg-2?                                ${HAVE_RSVG}"
+echo "  Does Emacs use imagemagick?                             ${HAVE_IMAGEMAGICK}"
 echo "  Does Emacs use -lgpm?                                   ${HAVE_GPM}"
 echo "  Does Emacs use -ldbus?                                  ${HAVE_DBUS}"
 
diff --git a/lisp/image.el b/lisp/image.el
index 076a969..8b989fa 100644
--- a/lisp/image.el
+++ b/lisp/image.el
@@ -70,6 +70,8 @@ a non-nil value, TYPE is the image's type.")
     ("\\.ps\\'" . postscript)
     ("\\.tiff?\\'" . tiff)
     ("\\.svgz?\\'" . svg)
+    ("\\.xcf?\\'" . imagemagick)
+    ("\\.djvu?\\'" . imagemagick)
     )
   "Alist of (REGEXP . IMAGE-TYPE) pairs used to identify image files.
 When the name of an image file match REGEXP, it is assumed to
@@ -586,6 +588,23 @@ Example:
   `(defvar ,symbol (find-image ',specs) ,doc))
 
 
+(defun imagemagic-register-types ()
+  "Register file types that imagemagick is able to handle."
+  (let ((im-types (imagemagick-types)))
+    (while im-types
+      (let
+	  ((extension (downcase (symbol-name (car im-types)))))
+	(push
+	 (cons  (concat "\\." extension "$") 'image-mode)
+	 auto-mode-alist)
+	(push
+	 (cons  (concat "\\." extension "\\'") 'imagemagick)
+	 image-type-file-name-regexps)
+
+	(setq im-types (cdr im-types))
+    )
+  )))
+
 (provide 'image)
 
 ;; arch-tag: 8e76a07b-eb48-4f3e-a7a0-1a7ba9f096b3
diff --git a/src/Makefile.in b/src/Makefile.in
index 425cf98..797d6fb 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -253,7 +253,7 @@ DBUS_OBJ = dbusbind.o
 
 /* C_SWITCH_X_SITE must come before C_SWITCH_X_MACHINE and C_SWITCH_X_SYSTEM
    since it may have -I options that should override those two.  */
-ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(MYCPPFLAGS) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM C_SWITCH_SYSTEM_TEMACS ${CFLAGS_SOUND} ${RSVG_CFLAGS} ${DBUS_CFLAGS} ${CFLAGS} @FREETYPE_CFLAGS@ @FONTCONFIG_CFLAGS@ @LIBOTF_CFLAGS@ @M17N_FLT_CFLAGS@
+ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(MYCPPFLAGS) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM C_SWITCH_SYSTEM_TEMACS ${CFLAGS_SOUND} ${RSVG_CFLAGS} ${IMAGEMAGICK_CFLAGS}  ${DBUS_CFLAGS} ${CFLAGS} @FREETYPE_CFLAGS@ @FONTCONFIG_CFLAGS@ @LIBOTF_CFLAGS@ @M17N_FLT_CFLAGS@
 ALL_OBJC_CFLAGS=$(ALL_CFLAGS) @GNU_OBJC_CFLAGS@
 
 .SUFFIXES: .m
@@ -425,6 +425,9 @@ CFLAGS_SOUND= @CFLAGS_SOUND@
 RSVG_LIBS= @RSVG_LIBS@
 RSVG_CFLAGS= @RSVG_CFLAGS@
 
+IMAGEMAGICK_LIBS= @IMAGEMAGICK_LIBS@
+IMAGEMAGICK_CFLAGS= @IMAGEMAGICK_CFLAGS@
+
 #ifndef ORDINARY_LINK
 /* Fix linking if compiled with GCC.  */
 #ifdef __GNUC__
@@ -878,7 +881,7 @@ SOME_MACHINE_LISP = ../lisp/mouse.elc \
    duplicated symbols.  If the standard libraries were compiled
    with GCC, we might need gnulib again after them.  */
 
-LIBES = $(LOADLIBES) $(LIBS) $(LIBX) $(LIBSOUND) $(RSVG_LIBS) $(DBUS_LIBS) \
+LIBES = $(LOADLIBES) $(LIBS) $(LIBX) $(LIBSOUND) $(RSVG_LIBS) ${IMAGEMAGICK_LIBS} $(DBUS_LIBS) \
    LIBGPM LIBRESOLV LIBS_SYSTEM LIBS_MACHINE LIBS_TERMCAP \
    LIBS_DEBUG $(GETLOADAVG_LIBS) \
    @FREETYPE_LIBS@ @FONTCONFIG_LIBS@ @LIBOTF_LIBS@ @M17N_FLT_LIBS@ \
diff --git a/src/config.in b/src/config.in
index 404e00b..111de5d 100644
--- a/src/config.in
+++ b/src/config.in
@@ -547,6 +547,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 /* Define to 1 if using librsvg. */
 #undef HAVE_RSVG
 
+/* Define to 1 if using imagemagick. */
+#undef HAVE_IMAGEMAGICK
+
 /* Define to 1 if you have the `select' function. */
 #undef HAVE_SELECT
 
diff --git a/src/image.c b/src/image.c
index fa8c3ea..02e0792 100644
--- a/src/image.c
+++ b/src/image.c
@@ -838,7 +838,7 @@ extern Lisp_Object QCdata, QCtype;
 extern Lisp_Object Qcenter;
 Lisp_Object QCascent, QCmargin, QCrelief, Qcount;
 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
-Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
+Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask, QCgeometry, QCcrop, QCrotation;
 
 /* Other symbols.  */
 
@@ -7771,6 +7771,339 @@ gif_load (struct frame *f, struct image *img)
 #endif /* HAVE_GIF */
 
 
+/***********************************************************************
+				 imagemagick
+ ***********************************************************************/
+#if defined (HAVE_IMAGEMAGICK)
+
+/* Function prototypes.  */
+
+static int imagemagick_image_p P_ ((Lisp_Object object));
+static int imagemagick_load P_ ((struct frame *f, struct image *img));
+
+static int imagemagick_load_image P_ ((struct frame *, struct image *,
+			       unsigned char *, unsigned int));
+
+/* The symbol `imagemagick' identifying images of this type. */
+
+Lisp_Object Qimagemagick;
+
+/* Indices of image specification fields in imagemagick_format, below.  */
+
+enum imagemagick_keyword_index
+{
+  IMAGEMAGICK_TYPE,
+  IMAGEMAGICK_DATA,
+  IMAGEMAGICK_FILE,
+  IMAGEMAGICK_ASCENT,
+  IMAGEMAGICK_MARGIN,
+  IMAGEMAGICK_RELIEF,
+  IMAGEMAGICK_ALGORITHM,
+  IMAGEMAGICK_HEURISTIC_MASK,
+  IMAGEMAGICK_MASK,
+  IMAGEMAGICK_BACKGROUND,
+  IMAGEMAGICK_LAST
+};
+
+/* Vector of image_keyword structures describing the format
+   of valid user-defined image specifications.  */
+
+static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] =
+{
+  {":type",		IMAGE_SYMBOL_VALUE,			1},
+  {":data",		IMAGE_STRING_VALUE,			0},
+  {":file",		IMAGE_STRING_VALUE,			0},
+  {":ascent",		IMAGE_ASCENT_VALUE,			0},
+  {":margin",		IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,	0},
+  {":relief",		IMAGE_INTEGER_VALUE,			0},
+  {":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}
+};
+
+/* Structure describing the image type `imagemagick'.  Its the same type of
+   structure defined for all image formats, handled by emacs image
+   functions.  See struct image_type in dispextern.h.  */
+
+static struct image_type imagemagick_type =
+{
+  /* An identifier showing that this is an image structure for the IMAGEMAGICK format.  */
+  &Qimagemagick,
+  /* Handle to a function that can be used to identify a IMAGEMAGICK file.  */
+  imagemagick_image_p,
+  /* Handle to function used to load a IMAGEMAGICK file.  */
+  imagemagick_load,
+  /* Handle to function to free resources for IMAGEMAGICK.  */
+  x_clear_image,
+  /* An internal field to link to the next image type in a list of
+     image types, will be filled in when registering the format.  */
+  NULL
+};
+
+
+/* Return non-zero if OBJECT is a valid IMAGEMAGICK image specification.  Do
+   this by calling parse_image_spec and supplying the keywords that
+   identify the IMAGEMAGICK format.   */
+
+static int
+imagemagick_image_p (object)
+     Lisp_Object object;
+{
+  struct image_keyword fmt[IMAGEMAGICK_LAST];
+  bcopy (imagemagick_format, fmt, sizeof fmt);
+
+  if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, Qimagemagick))
+    return 0;
+
+  /* Must specify either the :data or :file keyword.  */
+  return fmt[IMAGEMAGICK_FILE].count + fmt[IMAGEMAGICK_DATA].count == 1;
+}
+
+/* The GIF library also defines DrawRectangle, but its never used in Emacs.
+   Therefore rename the function so it doesnt collide with ImageMagick */
+#define DrawRectangle DrawRectangleGif
+#include <wand/MagickWand.h>
+
+/* Load IMAGEMAGICK image IMG for use on frame F.  Value is non-zero if
+   successful. this function will go into the imagemagick_type structure, and
+   the prototype thus needs to be compatible with that structure.  */
+
+static int
+imagemagick_load (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  int success_p = 0;
+  Lisp_Object file_name;
+
+  /* If IMG->spec specifies a file name, create a non-file spec from it.  */
+  file_name = image_spec_value (img->spec, QCfile, NULL);
+  if (STRINGP (file_name))
+    {
+      Lisp_Object file;
+      unsigned char *contents;
+      int size;
+      struct gcpro gcpro1;
+
+      file = x_find_image_file (file_name);
+      GCPRO1 (file);
+      if (!STRINGP (file))
+	{
+	  image_error ("Cannot find image file `%s'", file_name, Qnil);
+	  UNGCPRO;
+	  return 0;
+	}
+
+      /* Read the entire file into memory.  */
+      contents = slurp_file (SDATA (file), &size);
+      if (contents == NULL)
+	{
+	  image_error ("Error loading IMAGEMAGICK image `%s'", img->spec, Qnil);
+	  UNGCPRO;
+	  return 0;
+	}
+      /* If the file was slurped into memory properly, parse it.  */
+      success_p = imagemagick_load_image (f, img, contents, size);
+      xfree (contents);
+      UNGCPRO;
+    }
+  /* Else its not a file, its a lisp object.  Load the image from a
+     lisp object rather than a file.  */
+  else
+    {
+      Lisp_Object data;
+
+      data = image_spec_value (img->spec, QCdata, NULL);
+      success_p = imagemagick_load_image (f, img, SDATA (data), SBYTES (data));
+    }
+
+  return success_p;
+}
+
+/* imagemagick_load_image is a helper function for imagemagick_load, which does the
+   actual loading given contents and size, apart from frame and image
+   structures, passed from imagemagick_load.
+
+   Uses librimagemagick to do most of the image processing.
+
+   Returns non-zero when successful.
+*/
+
+static int
+imagemagick_load_image (f, img, contents, size)
+    /* Pointer to emacs frame structure.  */
+     struct frame *f;
+     /* Pointer to emacs image structure.  */
+     struct image *img;
+     /* String containing the IMAGEMAGICK  data to be parsed.  */
+     unsigned char *contents;
+     /* Size of data in bytes.  */
+     unsigned int size;
+{
+  long unsigned int width;
+  long unsigned int height;
+
+  MagickBooleanType
+    status;
+
+  XImagePtr ximg;
+  Lisp_Object specified_bg;
+  XColor background;
+  int x;
+  int y;
+
+  MagickWand  *image_wand;
+  PixelIterator *iterator;
+  PixelWand  **pixels;
+  MagickPixelPacket  pixel;
+
+  
+  /* image_wand will contain the image  */
+  image_wand=NewMagickWand();  
+
+  /* Parse the contents argument and fill in the rimagemagick_handle.  */
+  //status=MagickReadImage(image_wand, "/tmp/tst.djvu");
+  status=MagickReadImageBlob(image_wand, contents, size);
+  if (status == MagickFalse) goto imagemagick_error;
+
+  /* handle image index for image types who can contain more than one image.
+   interface :index is same as for GIF */
+  Lisp_Object image;
+  long ino;
+  image = image_spec_value (img->spec, QCindex, NULL);
+  ino = INTEGERP (image) ? XFASTINT (image) : 0;
+  
+  /* if (ino >= ) */
+  /*   { */
+  /*     image_error ("Invalid image number `%s' in image `%s'", */
+  /*       	   image, img->spec); */
+  /*     UNGCPRO; */
+  /*     return 0; */
+  /*   } */
+
+  MagickSetIteratorIndex(image_wand, ino);
+
+  /*
+    if width and/or height is set in the display spec
+    assume we want to scale to those */
+
+  int desired_width, desired_height;
+  Lisp_Object value;  
+  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);
+  if(desired_width != -1 && desired_height != -1){
+    printf("MagickScaleImage %d %d\n",desired_width, desired_height);
+    MagickScaleImage(image_wand, desired_width, desired_height);
+  }
+
+  /* also support :geometry and :crop which are imagemagick specific descriptors */
+
+  Lisp_Object crop, geometry;
+  crop     = image_spec_value (img->spec, QCcrop, NULL);
+  geometry = image_spec_value (img->spec, QCgeometry, NULL);
+  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 */
+
+  /*
+    specified_bg = image_spec_value (img->spec, QCbackground, NULL);
+  if (!STRINGP (specified_bg)
+  */
+    double rotation;
+    value = image_spec_value (img->spec, QCrotation, NULL);
+    if(FLOATP(value)){
+      PixelWand* background = NewPixelWand();
+      PixelSetColor(background,"#ffffff");
+
+      rotation=extract_float(value);
+      printf("MagickRotateImage %f\n",rotation);
+      
+      status=MagickRotateImage(image_wand, background,rotation);
+    }
+  
+  /* finaly we are done manipulating the image,
+     figure resulting width, height, and then transfer ownerwship to emacs
+   */
+  height=MagickGetImageHeight(image_wand);
+  width=MagickGetImageWidth(image_wand);
+  if (status == MagickFalse) goto imagemagick_error;
+
+  
+
+    
+  if (! check_image_size (f, width, height))
+    {
+      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+      goto imagemagick_error;
+    }
+  
+  /* We can now get a valid pixel buffer from the imagemagick file, if all
+     went ok.  */
+
+
+  
+  /* Try to create a x pixmap to hold the imagemagick pixmap.  */
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
+    {
+      return 0;
+    }
+
+  init_color_table ();
+
+  /* copy pixels from the imagemagick image structure to the x image map */
+  iterator=NewPixelIterator(image_wand);
+  if ((iterator == (PixelIterator *) NULL)) goto imagemagick_error;
+
+  for (y=0; y < (long) MagickGetImageHeight(image_wand); y++)
+  {
+    pixels=PixelGetNextIteratorRow(iterator,&width);
+    if ((pixels == (PixelWand **) NULL))
+      break;
+    for (x=0; x < (long) width; x++)
+    {
+      PixelGetMagickColor(pixels[x],&pixel);
+      XPutPixel (ximg, x, y, lookup_rgb_color (f, pixel.red, pixel.green, pixel.blue));      
+    }
+  }
+  
+#ifdef COLOR_TABLE_SUPPORT
+  /* Remember colors allocated for this image.  */
+  img->colors = colors_in_color_table (&img->ncolors);
+  free_color_table ();
+#endif /* COLOR_TABLE_SUPPORT */
+
+
+  img->width  = width;
+  img->height = height;
+
+  /* Maybe fill in the background field while we have ximg handy.
+     Casting avoids a GCC warning.  */
+  IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
+
+  /* Put the image into the pixmap, then free the X image and its
+     buffer.  */
+  x_put_x_image (f, ximg, img->pixmap, width, height);
+  x_destroy_x_image (ximg);
+
+  //JAVE TODO lots of cleanup
+  
+  return 1;
+
+ imagemagick_error:
+  image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil);
+  return 0;
+}
+
+#endif	/* defined (HAVE_IMAGEMAGICK) */
+
+
 \f
 /***********************************************************************
 				 SVG
@@ -8568,6 +8901,14 @@ of `image-library-alist', which see).  */)
     return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries);
 #endif
 
+#if defined (HAVE_IMAGEMAGICK)
+  if (EQ (type, Qimagemagick)){
+    /*   MagickWandGenesis() initalizes the imagemagick library */
+    MagickWandGenesis(); 
+    return CHECK_LIB_AVAILABLE (&imagemagick_type, init_imagemagick_functions, libraries);
+  }
+#endif
+
 #ifdef HAVE_GHOSTSCRIPT
   if (EQ (type, Qpostscript))
     return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries);
@@ -8577,6 +8918,24 @@ of `image-library-alist', which see).  */)
   CACHE_IMAGE_TYPE (type, Qnil);
   return Qnil;
 }
+DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0,0,0,
+       doc: /*return image file types supportedby imagemagick */)
+  ()
+{
+  //get imagemagick filetypes from lisp
+  Lisp_Object typelist=Qnil;
+  unsigned long numf;
+  ExceptionInfo ex;
+  char** imtypes = GetMagickList("*", &numf,&ex);
+  int i;
+  Lisp_Object Qimagemagicktype;
+  for (i = 0; i < numf; i++) {
+    Qimagemagicktype = intern ( *(imtypes+i)) ;
+    typelist=Fcons(Qimagemagicktype,typelist);
+  }
+  return typelist;
+}
+  
 
 void
 syms_of_image ()
@@ -8653,6 +9012,12 @@ non-numeric, there is no explicit limit on the size of images.  */);
   staticpro (&QCheuristic_mask);
   QCindex = intern (":index");
   staticpro (&QCindex);
+  QCgeometry = intern (":geometry");
+  staticpro (&QCgeometry);
+  QCcrop = intern (":crop");
+  staticpro (&QCcrop);
+  QCrotation = intern (":rotation");
+  staticpro (&QCrotation);
   QCmatrix = intern (":matrix");
   staticpro (&QCmatrix);
   QCcolor_adjustment = intern (":color-adjustment");
@@ -8713,6 +9078,12 @@ non-numeric, there is no explicit limit on the size of images.  */);
   ADD_IMAGE_TYPE (Qpng);
 #endif
 
+#if defined (HAVE_IMAGEMAGICK)
+  Qimagemagick = intern ("imagemagick");
+  staticpro (&Qimagemagick);
+  ADD_IMAGE_TYPE (Qimagemagick);
+#endif
+  
 #if defined (HAVE_RSVG)
   Qsvg = intern ("svg");
   staticpro (&Qsvg);
@@ -8729,6 +9100,7 @@ non-numeric, there is no explicit limit on the size of images.  */);
 #endif /* HAVE_RSVG  */
 
   defsubr (&Sinit_image_library);
+  defsubr (&Simagemagick_types);  
   defsubr (&Sclear_image_cache);
   defsubr (&Simage_refresh);
   defsubr (&Simage_size);
@@ -8761,7 +9133,21 @@ meaning don't clear the cache.  */);
 void
 init_image ()
 {
+  //register imagegemagick types here, they are dynamic
+  //TODO is this really necessary?
+  unsigned long numf;
+  ExceptionInfo ex;
+  char** imtypes = GetMagickList("*", &numf,&ex);
+  int i;
+  Lisp_Object Qimagemagicktype;
+  for (i = 0; i < numf; i++) {
+    printf("immagick format::%s\n", *(imtypes+i));
+    Qimagemagicktype = intern ( *(imtypes+i)) ;
+    ADD_IMAGE_TYPE (Qimagemagicktype);
+  }
 }
 
+
+
 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
    (do not change this comment) */

[-- Attachment #3: Type: text/plain, Size: 20 bytes --]



-- 
Joakim Verona

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: imagemagick patch v3
  2009-08-05  0:43 ` joakim
@ 2009-08-05  2:15   ` Stefan Monnier
  2009-08-05  8:10     ` joakim
  0 siblings, 1 reply; 8+ messages in thread
From: Stefan Monnier @ 2009-08-05  2:15 UTC (permalink / raw)
  To: joakim; +Cc: Emacs Development

>> - :width and :height, if you specify them image will be scaled to these
>> sizes

It would be good to make it possible to specify zoom factors as well
rather than resulting size (maybe if those parameters are floats rather
than ints?).

> +	(push
> +	 (cons  (concat "\\." extension "$") 'image-mode)
> +	 auto-mode-alist)

The "$" should be replaced with "\\'".


        Stefan




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: imagemagick patch v3
  2009-08-05  2:15   ` Stefan Monnier
@ 2009-08-05  8:10     ` joakim
  2009-08-05 17:23       ` Eli Zaretskii
  0 siblings, 1 reply; 8+ messages in thread
From: joakim @ 2009-08-05  8:10 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Emacs Development

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>>> - :width and :height, if you specify them image will be scaled to these
>>> sizes
>
> It would be good to make it possible to specify zoom factors as well
> rather than resulting size (maybe if those parameters are floats rather
> than ints?).

This is already supported by the :geometry option which is quite
powerful. You can do things like "50%" or "200x100" or "x100" etc.

I tried to use existing keywords were available, but :geometry and :crop
are very imagemagick specific.

Anyway, I think rotation, scaling, and croping is sufficient. There are
hundreds of operations in the imagemagick api, and I dont plan on adding
more for now. I have toyed with the idea of providing a keyword like
:operations, that would contain a list of image operations to be
performed, but that will have to wait.


>> +	(push
>> +	 (cons  (concat "\\." extension "$") 'image-mode)
>> +	 auto-mode-alist)
>
> The "$" should be replaced with "\\'".

Ok, but I dont get why?

>
>
>         Stefan
-- 
Joakim Verona




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: imagemagick patch v3
  2009-08-05  8:10     ` joakim
@ 2009-08-05 17:23       ` Eli Zaretskii
  2009-08-05 18:19         ` Tassilo Horn
  0 siblings, 1 reply; 8+ messages in thread
From: Eli Zaretskii @ 2009-08-05 17:23 UTC (permalink / raw)
  To: joakim; +Cc: monnier, emacs-devel

> From: joakim@verona.se
> Date: Wed, 05 Aug 2009 10:10:23 +0200
> Cc: Emacs Development <emacs-devel@gnu.org>
> 
> >> +	(push
> >> +	 (cons  (concat "\\." extension "$") 'image-mode)
> >> +	 auto-mode-alist)
> >
> > The "$" should be replaced with "\\'".
> 
> Ok, but I dont get why?

Because a file name on Posix platforms can include a newline
character.




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: imagemagick patch v3
  2009-08-05 17:23       ` Eli Zaretskii
@ 2009-08-05 18:19         ` Tassilo Horn
  2009-08-05 18:53           ` Eli Zaretskii
  0 siblings, 1 reply; 8+ messages in thread
From: Tassilo Horn @ 2009-08-05 18:19 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: monnier, joakim, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

Hi!

>> From: joakim@verona.se
>> Date: Wed, 05 Aug 2009 10:10:23 +0200
>> Cc: Emacs Development <emacs-devel@gnu.org>
>> 
>> >> +	(push
>> >> +	 (cons  (concat "\\." extension "$") 'image-mode)
>> >> +	 auto-mode-alist)
>> >
>> > The "$" should be replaced with "\\'".
>> 
>> Ok, but I dont get why?
>
> Because a file name on Posix platforms can include a newline
> character.

I tried that on GNU/Linux, and indeed it does work.  The `ls' command
lists the file as "multi?line?file", where the question marks represent
the newlines.

Unfortunately, dired doesn't work with those files.  Here's a
"screenshot":

--8<---------------cut here---------------start------------->8---
  drwxr-xr-x  2 horn horn  4.0K 2009-06-30 22:32 kvm
  drwxr-xr-x  4 horn horn  4.0K 2009-08-05 19:30 Mail
  -rw-r--r--  1 horn horn     4 2009-08-05 20:05 multi
line
file
  drwxr-xr-x  7 horn horn   12K 2009-08-05 20:04 News
  drwxr-xr-x  6 horn horn  4.0K 2009-07-27 20:59 opt
--8<---------------cut here---------------end--------------->8---

The listing itself is ok, I'd say.  But hitting RET on "multi" says
"File no longer exists; type `g' to update dired buffer", and RET on
"line" or "file" say "No file on this line".

Well, not really a problem, though...

Bye,
Tassilo




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: imagemagick patch v3
  2009-08-05 18:19         ` Tassilo Horn
@ 2009-08-05 18:53           ` Eli Zaretskii
  2009-08-05 19:49             ` Tassilo Horn
  0 siblings, 1 reply; 8+ messages in thread
From: Eli Zaretskii @ 2009-08-05 18:53 UTC (permalink / raw)
  To: Tassilo Horn; +Cc: monnier, joakim, emacs-devel

> From: Tassilo Horn <tassilo@member.fsf.org>
> Cc: joakim@verona.se,  monnier@iro.umontreal.ca,  emacs-devel@gnu.org
> Date: Wed, 05 Aug 2009 20:19:00 +0200
> 
> Unfortunately, dired doesn't work with those files.  Here's a
> "screenshot":
> 
> --8<---------------cut here---------------start------------->8---
>   drwxr-xr-x  2 horn horn  4.0K 2009-06-30 22:32 kvm
>   drwxr-xr-x  4 horn horn  4.0K 2009-08-05 19:30 Mail
>   -rw-r--r--  1 horn horn     4 2009-08-05 20:05 multi
> line
> file
>   drwxr-xr-x  7 horn horn   12K 2009-08-05 20:04 News
>   drwxr-xr-x  6 horn horn  4.0K 2009-07-27 20:59 opt
> --8<---------------cut here---------------end--------------->8---
> 
> The listing itself is ok, I'd say.  But hitting RET on "multi" says
> "File no longer exists; type `g' to update dired buffer", and RET on
> "line" or "file" say "No file on this line".

Please file a bug report about these problems in Dired.




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: imagemagick patch v3
  2009-08-05 18:53           ` Eli Zaretskii
@ 2009-08-05 19:49             ` Tassilo Horn
  0 siblings, 0 replies; 8+ messages in thread
From: Tassilo Horn @ 2009-08-05 19:49 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> Unfortunately, dired doesn't work with those files.  Here's a
>> "screenshot":
>> 
>> --8<---------------cut here---------------start------------->8---
>>   drwxr-xr-x  2 horn horn  4.0K 2009-06-30 22:32 kvm
>>   drwxr-xr-x  4 horn horn  4.0K 2009-08-05 19:30 Mail
>>   -rw-r--r--  1 horn horn     4 2009-08-05 20:05 multi
>> line
>> file
>>   drwxr-xr-x  7 horn horn   12K 2009-08-05 20:04 News
>>   drwxr-xr-x  6 horn horn  4.0K 2009-07-27 20:59 opt
>> --8<---------------cut here---------------end--------------->8---
>> 
>> The listing itself is ok, I'd say.  But hitting RET on "multi" says
>> "File no longer exists; type `g' to update dired buffer", and RET on
>> "line" or "file" say "No file on this line".
>
> Please file a bug report about these problems in Dired.

Done: #4049

Bye,
Tassilo




^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2009-08-05 19:49 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-08-04 19:55 imagemagick patch v3 joakim
2009-08-05  0:43 ` joakim
2009-08-05  2:15   ` Stefan Monnier
2009-08-05  8:10     ` joakim
2009-08-05 17:23       ` Eli Zaretskii
2009-08-05 18:19         ` Tassilo Horn
2009-08-05 18:53           ` Eli Zaretskii
2009-08-05 19:49             ` Tassilo Horn

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).