/***********************************************************************
imagemagick
- ***********************************************************************/
+***********************************************************************/
#if defined (HAVE_IMAGEMAGICK)
Lisp_Object Vimagemagick_render_type;
-/* Function prototypes. */
-
-static int imagemagick_image_p (Lisp_Object object);
-static int imagemagick_load (struct frame *f, struct image *img);
-
-static int imagemagick_load_image (struct frame *, struct image *,
- unsigned char *, unsigned int, unsigned char *);
/* The symbol `imagemagick' identifying images of this type. */
/* 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
-};
+ {
+ 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}
-};
+ {
+ {":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}
+ };
/* Free X resources of imagemagick image IMG which is used on frame F. */
static void
-imagemagick_clear_image (f, img)
- struct frame *f;
- struct image *img;
+imagemagick_clear_image (struct frame *f,
+ struct image *img)
{
printf("clearing imagemagick image\n");
x_clear_image (f, img);
}
-/* 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. */
- imagemagick_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
identify the IMAGEMAGICK format. */
static int
-imagemagick_image_p (object)
- Lisp_Object object;
+imagemagick_image_p (Lisp_Object object)
{
struct image_keyword fmt[IMAGEMAGICK_LAST];
bcopy (imagemagick_format, fmt, sizeof fmt);
#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, 0, 0, SDATA(file_name));
- 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),NULL);
- }
-
- 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.
*/
static int
-imagemagick_load_image (f, img, contents, size, filename)
- /* 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;
- /* Filename, either pass filename or contents/size. */
- unsigned char *filename;
+imagemagick_load_image (struct frame *f, /* Pointer to emacs frame structure. */
+ struct image *img, /* Pointer to emacs image structure. */
+ unsigned char *contents,/* String containing the IMAGEMAGICK data to be parsed. */
+ unsigned int size, /* Size of data in bytes. */
+ unsigned char *filename)/* Filename, either pass filename or contents/size. */
{
long unsigned int width;
long unsigned int height;
PixelIterator *iterator;
PixelWand **pixels;
MagickPixelPacket pixel;
+ Lisp_Object image;
+ Lisp_Object value;
+ Lisp_Object crop, geometry;
+ long ino;
+ int desired_width, desired_height;
+ double rotation;
+ int imagemagick_rendermethod;
+ int pixelwidth;
-
+
/* image_wand will contain the image. */
image_wand = NewMagickWand();
/* Parse the contents argument and initialize image_wand. */
- if(filename!=NULL)
- status=MagickReadImage(image_wand, filename);
+ if(filename != NULL)
+ status = MagickReadImage(image_wand, filename);
else
- status=MagickReadImageBlob(image_wand, contents, size);
+ status = MagickReadImageBlob(image_wand, contents, size);
image_error ("im read failed", Qnil, Qnil);
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;
+ Interface :index is same as for GIF. */
+
image = image_spec_value (img->spec, QCindex, NULL);
ino = INTEGERP (image) ? XFASTINT (image) : 0;
img->data.lisp_val = Fcons (Qcount,
Fcons (make_number (MagickGetNumberImages(image_wand)),
img->data.lisp_val));
- if(ino==0)
+ if(ino == 0)
MagickSetFirstIterator(image_wand);
else
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);
- status=MagickScaleImage(image_wand, desired_width, desired_height);
- if (status == MagickFalse) {
- image_error ("Imagemagick scale failed", Qnil, Qnil);
- goto imagemagick_error;
+ if(desired_width != -1 && desired_height != -1)
+ {
+ printf("MagickScaleImage %d %d\n", desired_width, desired_height);
+ status = MagickScaleImage(image_wand, desired_width, desired_height);
+ if (status == MagickFalse) {
+ image_error ("Imagemagick scale failed", Qnil, Qnil);
+ goto imagemagick_error;
+ }
}
-
- }
/* 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. */
- }
+ 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. */
/*
TODO background handling for rotation
specified_bg = image_spec_value (img->spec, QCbackground, NULL);
- if (!STRINGP (specified_bg)
+ if (!STRINGP (specified_bg)
*/
- double rotation;
- value = image_spec_value (img->spec, QCrotation, NULL);
- if (FLOATP (value)){
+ value = image_spec_value (img->spec, QCrotation, NULL);
+ if (FLOATP (value))
+ {
PixelWand* background = NewPixelWand();
PixelSetColor (background, "#ffffff");/*TODO remove hardcode*/
-
+
rotation = extract_float (value);
- printf ("MagickRotateImage %f\n",rotation);
-
- status=MagickRotateImage (image_wand, background,rotation);
+ printf ("MagickRotateImage %f\n", rotation);
+
+ status = MagickRotateImage (image_wand, background, rotation);
DestroyPixelWand (background);
- if (status == MagickFalse) {
- image_error ("Imagemagick image rotate failed", Qnil, Qnil);
- goto imagemagick_error;
- }
+ if (status == MagickFalse)
+ {
+ image_error ("Imagemagick image rotate failed", Qnil, Qnil);
+ goto imagemagick_error;
+ }
}
/* 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);
- if (status == MagickFalse) {
+ */
+ height = MagickGetImageHeight (image_wand);
+ width = MagickGetImageWidth (image_wand);
+ if (status == MagickFalse)
+ {
image_error ("Imagemagick image get size failed", Qnil, Qnil);
goto imagemagick_error;
- }
+ }
if (! check_image_size (f, width, height))
{
init_color_table ();
- int imagemagick_rendermethod=(INTEGERP (Vimagemagick_render_type) ? XFASTINT (Vimagemagick_render_type) : 0);
- if (imagemagick_rendermethod==0){
- /* 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)){
- image_error("Imagemagick X bitmap allocation failure",Qnil,Qnil);
- goto imagemagick_error;
- }
+ imagemagick_rendermethod = (INTEGERP (Vimagemagick_render_type) ? XFASTINT (Vimagemagick_render_type) : 0);
+ if (imagemagick_rendermethod == 0)
+ {
+ /* 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))
+ {
+ image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil);
+ goto imagemagick_error;
+ }
- /* 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!
+ /* 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.
- */
+ Also seems slow.
+ */
- /* Copy pixels from the imagemagick image structure to the x image map. */
- iterator = NewPixelIterator (image_wand);
- if ((iterator == (PixelIterator *) NULL)) {
+ /* Copy pixels from the imagemagick image structure to the x image map. */
+ iterator = NewPixelIterator (image_wand);
+ if ((iterator == (PixelIterator *) NULL))
+ {
image_error ("Imagemagick pixel iterator creation failed", Qnil, Qnil);
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));
+ }
+ }
+ DestroyPixelIterator (iterator);
}
- 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));
- }
+ 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. */
+ printf("imagedepth:%d exportdepth:%s\n", imagedepth, exportdepth);
+ if (!x_create_x_image_and_pixmap (f, width, height, imagedepth, &ximg, &img->pixmap)){
+ image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil);
+ goto imagemagick_error;
}
- DestroyPixelIterator (iterator);
- }
-
- 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. */
- printf("imagedepth:%d exportdepth:%s\n", imagedepth, exportdepth);
- if (!x_create_x_image_and_pixmap (f, width, height, imagedepth, &ximg, &img->pixmap)){
- image_error("Imagemagick X bitmap allocation failure",Qnil,Qnil);
- goto imagemagick_error;
- }
- /* Oddly, the below code doesnt seem to work:*/
- int pixelwidth;
- /* switch(ximg->bitmap_unit){ */
- /* case 8: */
- /* pixelwidth=CharPixel; */
- /* break; */
- /* case 16: */
- /* pixelwidth=ShortPixel; */
- /* break; */
- /* case 32: */
- /* pixelwidth=LongPixel; */
- /* break; */
- /* } */
- /*
- Here im just guessing the format of the bitmap.
- happens to work fine for:
- - bw djvu images
- on rgb display.
- seems about 3 times as fast as pixel pushing(not carefully measured)
- with color djvu, the bitplanes are mapped to wrong color(seems fixed).
-
- */
- pixelwidth=CharPixel;/*??? TODO figure out*/
+ /* Oddly, the below code doesnt seem to work:*/
+ /* switch(ximg->bitmap_unit){ */
+ /* case 8: */
+ /* pixelwidth=CharPixel; */
+ /* break; */
+ /* case 16: */
+ /* pixelwidth=ShortPixel; */
+ /* break; */
+ /* case 32: */
+ /* pixelwidth=LongPixel; */
+ /* break; */
+ /* } */
+ /*
+ Here im just guessing the format of the bitmap.
+ happens to work fine for:
+ - bw djvu images
+ on rgb display.
+ seems about 3 times as fast as pixel pushing(not carefully measured)
+ with color djvu, the bitplanes are mapped to wrong color(seems fixed).
+
+ */
+ pixelwidth = CharPixel;/*??? TODO figure out*/
#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS
- MagickExportImagePixels(image_wand,
- 0,0,
- width,height,
- exportdepth,
- pixelwidth,
- /*&(img->pixmap));*/
- ximg->data);
+ MagickExportImagePixels(image_wand,
+ 0, 0,
+ width, height,
+ exportdepth,
+ pixelwidth,
+ /*&(img->pixmap));*/
+ ximg->data);
#else
- image_error("You dont have MagickExportImagePixels, upgrade ImageMagick if you want to try it!",Qnil,Qnil);
+ image_error("You dont have MagickExportImagePixels, upgrade ImageMagick if you want to try it!",
+ Qnil, Qnil);
#endif
- }
+ }
#ifdef COLOR_TABLE_SUPPORT
return 0;
}
-DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0,0,0,
+
+/* 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 (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, 0, 0, SDATA(file_name));
+ 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), NULL);
+ }
+
+ return success_p;
+}
+
+/* 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. */
+ imagemagick_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
+ };
+
+
+
+
+DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0, 0, 0,
doc: /* Return image file types supported by ImageMagick.
- Since ImageMagick recognizes a lot of file-types that clash with Emacs,
- such as .c, we want to be able to alter the list at the lisp level. */)
+ Since ImageMagick recognizes a lot of file-types that clash with Emacs,
+ such as .c, we want to be able to alter the list at the lisp level. */)
()
{
Lisp_Object typelist = Qnil;
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;
+ for (i = 0; i < numf; i++)
+ {
+ Qimagemagicktype = intern (imtypes[i]);
+ typelist = Fcons (Qimagemagicktype, typelist);
+}
+return typelist;
}
#endif /* defined (HAVE_IMAGEMAGICK) */
The value can also be nil, meaning the cache is never cleared.
The function `clear-image-cache' disregards this variable. */);
Vimage_cache_eviction_delay = make_number (300);
-}
-
#ifdef HAVE_IMAGEMAGICK
DEFVAR_LISP ("imagemagick-render-type", &Vimagemagick_render_type,
- doc: /* */);
+ doc: /* Choose between ImageMagick render methods. */);
#endif
+}
+
+
void
init_image ()
{