emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: imagemagick patch v1


From: joakim
Subject: Re: imagemagick patch v1
Date: Sat, 01 Aug 2009 23:29:46 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.94 (gnu/linux)

Eli Zaretskii <address@hidden> writes:

>> From: address@hidden
>> Date: Sat, 01 Aug 2009 21:47:04 +0200
>> 
>> The attached patch is a 1st stab at making it possible to use the
>> imagemagick library to load images in emacs.
>
> Thanks.
>
>> (The 1st part of the patch are merely changes to "configure", ignore
>> those please.
>
> Could you please not post the hunks for `configure' at all?

I removed the configure hunks manually this time.
Do you know of a way to do it automatically?

>> The patch was generated with "git diff imagemagick master
>> >imagemagick1.patch" and configure is a managed file for some reason.)
>
> The patch looks backwards, i.e. "diff NEW OLD" rather than the other
> way around.
>

git diff  master imagemagick >imagemagick2.patch
should be better then.
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/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..80035cb 100644
--- a/src/image.c
+++ b/src/image.c
@@ -7771,6 +7771,281 @@ 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 renamethe 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.
+
+JAVE TODO: almost all imagemagick code will go here
+*/
+
+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;
+
+  
+  /*   MagickWandGenesis() initalizes the imagemagick library */
+  MagickWandGenesis();
+  /* 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;
+
+  //  status=MagickGetSize(image_wand, &width, &height);
+  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 ();
+
+
+  /* This loop handles opacity values, since Emacs assumes
+     non-transparent images.  Each pixel must be "flattened" by
+     calculating the resulting color, given the transparency of the
+     pixel, and the image background color.  */
+  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) */
+
+
 
 /***********************************************************************
                                 SVG
@@ -8568,6 +8843,11 @@ 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))
+    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);
@@ -8713,6 +8993,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);
-- 
Joakim Verona

reply via email to

[Prev in Thread] Current Thread [Next in Thread]