Mercurial > emacs
comparison src/image.c @ 109860:c92f5e6103a8
mostly cosmetic, moving { instances, changing indentation accordingly.
author | Joakim <joakim@localhost.localdomain> |
---|---|
date | Mon, 14 Jun 2010 15:57:48 +0200 |
parents | 68616bb3ae25 |
children | 8e0241dfb81c |
comparison
equal
deleted
inserted
replaced
109859:68616bb3ae25 | 109860:c92f5e6103a8 |
---|---|
7567 #endif /* HAVE_GIF */ | 7567 #endif /* HAVE_GIF */ |
7568 | 7568 |
7569 | 7569 |
7570 /*********************************************************************** | 7570 /*********************************************************************** |
7571 imagemagick | 7571 imagemagick |
7572 ***********************************************************************/ | 7572 ***********************************************************************/ |
7573 #if defined (HAVE_IMAGEMAGICK) | 7573 #if defined (HAVE_IMAGEMAGICK) |
7574 Lisp_Object Vimagemagick_render_type; | 7574 Lisp_Object Vimagemagick_render_type; |
7575 /* Function prototypes. */ | |
7576 | |
7577 static int imagemagick_image_p (Lisp_Object object); | |
7578 static int imagemagick_load (struct frame *f, struct image *img); | |
7579 | |
7580 static int imagemagick_load_image (struct frame *, struct image *, | |
7581 unsigned char *, unsigned int, unsigned char *); | |
7582 | 7575 |
7583 /* The symbol `imagemagick' identifying images of this type. */ | 7576 /* The symbol `imagemagick' identifying images of this type. */ |
7584 | 7577 |
7585 Lisp_Object Qimagemagick; | 7578 Lisp_Object Qimagemagick; |
7586 Lisp_Object Vimagemagick_render_type; | 7579 Lisp_Object Vimagemagick_render_type; |
7587 | 7580 |
7588 /* Indices of image specification fields in imagemagick_format, below. */ | 7581 /* Indices of image specification fields in imagemagick_format, below. */ |
7589 | 7582 |
7590 enum imagemagick_keyword_index | 7583 enum imagemagick_keyword_index |
7591 { | 7584 { |
7592 IMAGEMAGICK_TYPE, | 7585 IMAGEMAGICK_TYPE, |
7593 IMAGEMAGICK_DATA, | 7586 IMAGEMAGICK_DATA, |
7594 IMAGEMAGICK_FILE, | 7587 IMAGEMAGICK_FILE, |
7595 IMAGEMAGICK_ASCENT, | 7588 IMAGEMAGICK_ASCENT, |
7596 IMAGEMAGICK_MARGIN, | 7589 IMAGEMAGICK_MARGIN, |
7597 IMAGEMAGICK_RELIEF, | 7590 IMAGEMAGICK_RELIEF, |
7598 IMAGEMAGICK_ALGORITHM, | 7591 IMAGEMAGICK_ALGORITHM, |
7599 IMAGEMAGICK_HEURISTIC_MASK, | 7592 IMAGEMAGICK_HEURISTIC_MASK, |
7600 IMAGEMAGICK_MASK, | 7593 IMAGEMAGICK_MASK, |
7601 IMAGEMAGICK_BACKGROUND, | 7594 IMAGEMAGICK_BACKGROUND, |
7602 IMAGEMAGICK_LAST | 7595 IMAGEMAGICK_LAST |
7603 }; | 7596 }; |
7604 | 7597 |
7605 /* Vector of image_keyword structures describing the format | 7598 /* Vector of image_keyword structures describing the format |
7606 of valid user-defined image specifications. */ | 7599 of valid user-defined image specifications. */ |
7607 | 7600 |
7608 static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] = | 7601 static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] = |
7609 { | 7602 { |
7610 {":type", IMAGE_SYMBOL_VALUE, 1}, | 7603 {":type", IMAGE_SYMBOL_VALUE, 1}, |
7611 {":data", IMAGE_STRING_VALUE, 0}, | 7604 {":data", IMAGE_STRING_VALUE, 0}, |
7612 {":file", IMAGE_STRING_VALUE, 0}, | 7605 {":file", IMAGE_STRING_VALUE, 0}, |
7613 {":ascent", IMAGE_ASCENT_VALUE, 0}, | 7606 {":ascent", IMAGE_ASCENT_VALUE, 0}, |
7614 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, | 7607 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, |
7615 {":relief", IMAGE_INTEGER_VALUE, 0}, | 7608 {":relief", IMAGE_INTEGER_VALUE, 0}, |
7616 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 7609 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
7617 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 7610 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
7618 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 7611 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
7619 {":background", IMAGE_STRING_OR_NIL_VALUE, 0} | 7612 {":background", IMAGE_STRING_OR_NIL_VALUE, 0} |
7620 }; | 7613 }; |
7621 /* Free X resources of imagemagick image IMG which is used on frame F. */ | 7614 /* Free X resources of imagemagick image IMG which is used on frame F. */ |
7622 | 7615 |
7623 static void | 7616 static void |
7624 imagemagick_clear_image (f, img) | 7617 imagemagick_clear_image (struct frame *f, |
7625 struct frame *f; | 7618 struct image *img) |
7626 struct image *img; | |
7627 { | 7619 { |
7628 printf("clearing imagemagick image\n"); | 7620 printf("clearing imagemagick image\n"); |
7629 x_clear_image (f, img); | 7621 x_clear_image (f, img); |
7630 } | 7622 } |
7631 | 7623 |
7632 /* Structure describing the image type `imagemagick'. Its the same type of | |
7633 structure defined for all image formats, handled by Emacs image | |
7634 functions. See struct image_type in dispextern.h. */ | |
7635 | |
7636 static struct image_type imagemagick_type = | |
7637 { | |
7638 /* An identifier showing that this is an image structure for the IMAGEMAGICK format. */ | |
7639 &Qimagemagick, | |
7640 /* Handle to a function that can be used to identify a IMAGEMAGICK file. */ | |
7641 imagemagick_image_p, | |
7642 /* Handle to function used to load a IMAGEMAGICK file. */ | |
7643 imagemagick_load, | |
7644 /* Handle to function to free resources for IMAGEMAGICK. */ | |
7645 imagemagick_clear_image, | |
7646 /* An internal field to link to the next image type in a list of | |
7647 image types, will be filled in when registering the format. */ | |
7648 NULL | |
7649 }; | |
7650 | 7624 |
7651 | 7625 |
7652 /* Return non-zero if OBJECT is a valid IMAGEMAGICK image specification. Do | 7626 /* Return non-zero if OBJECT is a valid IMAGEMAGICK image specification. Do |
7653 this by calling parse_image_spec and supplying the keywords that | 7627 this by calling parse_image_spec and supplying the keywords that |
7654 identify the IMAGEMAGICK format. */ | 7628 identify the IMAGEMAGICK format. */ |
7655 | 7629 |
7656 static int | 7630 static int |
7657 imagemagick_image_p (object) | 7631 imagemagick_image_p (Lisp_Object object) |
7658 Lisp_Object object; | |
7659 { | 7632 { |
7660 struct image_keyword fmt[IMAGEMAGICK_LAST]; | 7633 struct image_keyword fmt[IMAGEMAGICK_LAST]; |
7661 bcopy (imagemagick_format, fmt, sizeof fmt); | 7634 bcopy (imagemagick_format, fmt, sizeof fmt); |
7662 | 7635 |
7663 if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, Qimagemagick)) | 7636 if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, Qimagemagick)) |
7670 /* The GIF library also defines DrawRectangle, but its never used in Emacs. | 7643 /* The GIF library also defines DrawRectangle, but its never used in Emacs. |
7671 Therefore rename the function so it doesnt collide with ImageMagick. */ | 7644 Therefore rename the function so it doesnt collide with ImageMagick. */ |
7672 #define DrawRectangle DrawRectangleGif | 7645 #define DrawRectangle DrawRectangleGif |
7673 #include <wand/MagickWand.h> | 7646 #include <wand/MagickWand.h> |
7674 | 7647 |
7648 /* imagemagick_load_image is a helper function for imagemagick_load, which does the | |
7649 actual loading given contents and size, apart from frame and image | |
7650 structures, passed from imagemagick_load. | |
7651 | |
7652 Uses librimagemagick to do most of the image processing. | |
7653 | |
7654 Returns non-zero when successful. | |
7655 */ | |
7656 | |
7657 static int | |
7658 imagemagick_load_image (struct frame *f, /* Pointer to emacs frame structure. */ | |
7659 struct image *img, /* Pointer to emacs image structure. */ | |
7660 unsigned char *contents,/* String containing the IMAGEMAGICK data to be parsed. */ | |
7661 unsigned int size, /* Size of data in bytes. */ | |
7662 unsigned char *filename)/* Filename, either pass filename or contents/size. */ | |
7663 { | |
7664 long unsigned int width; | |
7665 long unsigned int height; | |
7666 | |
7667 MagickBooleanType | |
7668 status; | |
7669 | |
7670 XImagePtr ximg; | |
7671 Lisp_Object specified_bg; | |
7672 XColor background; | |
7673 int x; | |
7674 int y; | |
7675 | |
7676 MagickWand *image_wand; | |
7677 PixelIterator *iterator; | |
7678 PixelWand **pixels; | |
7679 MagickPixelPacket pixel; | |
7680 Lisp_Object image; | |
7681 Lisp_Object value; | |
7682 Lisp_Object crop, geometry; | |
7683 long ino; | |
7684 int desired_width, desired_height; | |
7685 double rotation; | |
7686 int imagemagick_rendermethod; | |
7687 int pixelwidth; | |
7688 | |
7689 | |
7690 /* image_wand will contain the image. */ | |
7691 image_wand = NewMagickWand(); | |
7692 | |
7693 /* Parse the contents argument and initialize image_wand. */ | |
7694 if(filename != NULL) | |
7695 status = MagickReadImage(image_wand, filename); | |
7696 else | |
7697 status = MagickReadImageBlob(image_wand, contents, size); | |
7698 image_error ("im read failed", Qnil, Qnil); | |
7699 if (status == MagickFalse) goto imagemagick_error; | |
7700 | |
7701 /* Handle image index for image types who can contain more than one image. | |
7702 Interface :index is same as for GIF. */ | |
7703 | |
7704 image = image_spec_value (img->spec, QCindex, NULL); | |
7705 ino = INTEGERP (image) ? XFASTINT (image) : 0; | |
7706 | |
7707 | |
7708 | |
7709 if (ino >= MagickGetNumberImages(image_wand)) | |
7710 { | |
7711 image_error ("Invalid image number `%s' in image `%s'", | |
7712 image, img->spec); | |
7713 UNGCPRO; | |
7714 return 0; | |
7715 } | |
7716 | |
7717 | |
7718 if (MagickGetNumberImages(image_wand) > 1) | |
7719 img->data.lisp_val = Fcons (Qcount, | |
7720 Fcons (make_number (MagickGetNumberImages(image_wand)), | |
7721 img->data.lisp_val)); | |
7722 if(ino == 0) | |
7723 MagickSetFirstIterator(image_wand); | |
7724 else | |
7725 MagickSetIteratorIndex(image_wand, ino); | |
7726 | |
7727 /* | |
7728 If width and/or height is set in the display spec | |
7729 assume we want to scale to those. */ | |
7730 | |
7731 value = image_spec_value (img->spec, QCwidth, NULL); | |
7732 desired_width = (INTEGERP (value) ? XFASTINT (value) : -1); | |
7733 value = image_spec_value (img->spec, QCheight, NULL); | |
7734 desired_height = (INTEGERP (value) ? XFASTINT (value) : -1); | |
7735 if(desired_width != -1 && desired_height != -1) | |
7736 { | |
7737 printf("MagickScaleImage %d %d\n", desired_width, desired_height); | |
7738 status = MagickScaleImage(image_wand, desired_width, desired_height); | |
7739 if (status == MagickFalse) { | |
7740 image_error ("Imagemagick scale failed", Qnil, Qnil); | |
7741 goto imagemagick_error; | |
7742 } | |
7743 } | |
7744 | |
7745 /* Also support :geometry and :crop which are imagemagick specific descriptors. */ | |
7746 | |
7747 crop = image_spec_value (img->spec, QCcrop, NULL); | |
7748 geometry = image_spec_value (img->spec, QCgeometry, NULL); | |
7749 if (STRINGP (crop) && STRINGP (geometry)) | |
7750 { | |
7751 printf("MagickTransformImage %s %s\n", SDATA(crop), SDATA(geometry)); | |
7752 image_wand = MagickTransformImage (image_wand, SDATA (crop), SDATA (geometry)); | |
7753 /* TODO differ between image_wand and transform_wand. */ | |
7754 } | |
7755 | |
7756 /* Furthermore :rotation. we need background color and angle for rotation. */ | |
7757 /* | |
7758 TODO background handling for rotation | |
7759 specified_bg = image_spec_value (img->spec, QCbackground, NULL); | |
7760 if (!STRINGP (specified_bg) | |
7761 */ | |
7762 value = image_spec_value (img->spec, QCrotation, NULL); | |
7763 if (FLOATP (value)) | |
7764 { | |
7765 PixelWand* background = NewPixelWand(); | |
7766 PixelSetColor (background, "#ffffff");/*TODO remove hardcode*/ | |
7767 | |
7768 rotation = extract_float (value); | |
7769 printf ("MagickRotateImage %f\n", rotation); | |
7770 | |
7771 status = MagickRotateImage (image_wand, background, rotation); | |
7772 DestroyPixelWand (background); | |
7773 if (status == MagickFalse) | |
7774 { | |
7775 image_error ("Imagemagick image rotate failed", Qnil, Qnil); | |
7776 goto imagemagick_error; | |
7777 } | |
7778 } | |
7779 | |
7780 /* Finaly we are done manipulating the image, | |
7781 figure out resulting width, height, and then transfer ownerwship to Emacs. | |
7782 */ | |
7783 height = MagickGetImageHeight (image_wand); | |
7784 width = MagickGetImageWidth (image_wand); | |
7785 if (status == MagickFalse) | |
7786 { | |
7787 image_error ("Imagemagick image get size failed", Qnil, Qnil); | |
7788 goto imagemagick_error; | |
7789 } | |
7790 | |
7791 if (! check_image_size (f, width, height)) | |
7792 { | |
7793 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); | |
7794 goto imagemagick_error; | |
7795 } | |
7796 | |
7797 /* We can now get a valid pixel buffer from the imagemagick file, if all | |
7798 went ok. */ | |
7799 | |
7800 | |
7801 init_color_table (); | |
7802 imagemagick_rendermethod = (INTEGERP (Vimagemagick_render_type) ? XFASTINT (Vimagemagick_render_type) : 0); | |
7803 if (imagemagick_rendermethod == 0) | |
7804 { | |
7805 /* Try to create a x pixmap to hold the imagemagick pixmap. */ | |
7806 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) | |
7807 { | |
7808 image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil); | |
7809 goto imagemagick_error; | |
7810 } | |
7811 | |
7812 /* Copy imagegmagick image to x with primitive yet robust pixel | |
7813 pusher loop. This has been tested a lot with many different | |
7814 images, it doesnt work too well with image archive formats though! | |
7815 | |
7816 Also seems slow. | |
7817 */ | |
7818 | |
7819 /* Copy pixels from the imagemagick image structure to the x image map. */ | |
7820 iterator = NewPixelIterator (image_wand); | |
7821 if ((iterator == (PixelIterator *) NULL)) | |
7822 { | |
7823 image_error ("Imagemagick pixel iterator creation failed", Qnil, Qnil); | |
7824 goto imagemagick_error; | |
7825 } | |
7826 | |
7827 for (y = 0; y < (long) MagickGetImageHeight(image_wand); y++) | |
7828 { | |
7829 pixels = PixelGetNextIteratorRow (iterator, &width); | |
7830 if ((pixels == (PixelWand **) NULL)) | |
7831 break; | |
7832 for (x = 0; x < (long) width; x++) | |
7833 { | |
7834 PixelGetMagickColor (pixels[x], &pixel); | |
7835 XPutPixel (ximg, x, y, lookup_rgb_color (f, pixel.red, pixel.green, pixel.blue)); | |
7836 } | |
7837 } | |
7838 DestroyPixelIterator (iterator); | |
7839 } | |
7840 | |
7841 if (imagemagick_rendermethod == 1) | |
7842 { | |
7843 /* Try if magicexportimage is any faster than pixelpushing. */ | |
7844 /* printf("ximg: bitmap_unit:%d format:%d byte_order:%d depth:%d bits_per_pixel:%d\n", */ | |
7845 /* ximg->bitmap_unit,ximg->format,ximg->byte_order,ximg->depth,ximg->bits_per_pixel); */ | |
7846 int imagedepth = 24;/*MagickGetImageDepth(image_wand);*/ | |
7847 char* exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/ | |
7848 /* Try to create a x pixmap to hold the imagemagick pixmap. */ | |
7849 printf("imagedepth:%d exportdepth:%s\n", imagedepth, exportdepth); | |
7850 if (!x_create_x_image_and_pixmap (f, width, height, imagedepth, &ximg, &img->pixmap)){ | |
7851 image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil); | |
7852 goto imagemagick_error; | |
7853 } | |
7854 | |
7855 | |
7856 /* Oddly, the below code doesnt seem to work:*/ | |
7857 /* switch(ximg->bitmap_unit){ */ | |
7858 /* case 8: */ | |
7859 /* pixelwidth=CharPixel; */ | |
7860 /* break; */ | |
7861 /* case 16: */ | |
7862 /* pixelwidth=ShortPixel; */ | |
7863 /* break; */ | |
7864 /* case 32: */ | |
7865 /* pixelwidth=LongPixel; */ | |
7866 /* break; */ | |
7867 /* } */ | |
7868 /* | |
7869 Here im just guessing the format of the bitmap. | |
7870 happens to work fine for: | |
7871 - bw djvu images | |
7872 on rgb display. | |
7873 seems about 3 times as fast as pixel pushing(not carefully measured) | |
7874 with color djvu, the bitplanes are mapped to wrong color(seems fixed). | |
7875 | |
7876 */ | |
7877 pixelwidth = CharPixel;/*??? TODO figure out*/ | |
7878 #ifdef HAVE_MAGICKEXPORTIMAGEPIXELS | |
7879 MagickExportImagePixels(image_wand, | |
7880 0, 0, | |
7881 width, height, | |
7882 exportdepth, | |
7883 pixelwidth, | |
7884 /*&(img->pixmap));*/ | |
7885 ximg->data); | |
7886 #else | |
7887 image_error("You dont have MagickExportImagePixels, upgrade ImageMagick if you want to try it!", | |
7888 Qnil, Qnil); | |
7889 #endif | |
7890 } | |
7891 | |
7892 | |
7893 #ifdef COLOR_TABLE_SUPPORT | |
7894 /* Remember colors allocated for this image. */ | |
7895 img->colors = colors_in_color_table (&img->ncolors); | |
7896 free_color_table (); | |
7897 #endif /* COLOR_TABLE_SUPPORT */ | |
7898 | |
7899 | |
7900 img->width = width; | |
7901 img->height = height; | |
7902 | |
7903 /* Maybe fill in the background field while we have ximg handy. | |
7904 Casting avoids a GCC warning. */ | |
7905 /* IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);*/ | |
7906 | |
7907 /* Put the image into the pixmap, then free the X image and its | |
7908 buffer. */ | |
7909 x_put_x_image (f, ximg, img->pixmap, width, height); | |
7910 | |
7911 x_destroy_x_image (ximg); | |
7912 | |
7913 | |
7914 /* JAVE TODO more cleanup. */ | |
7915 DestroyMagickWand (image_wand); | |
7916 | |
7917 return 1; | |
7918 | |
7919 imagemagick_error: | |
7920 /* TODO more cleanup. */ | |
7921 image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil); | |
7922 printf("Imagemagick error, see *Messages*\n"); | |
7923 return 0; | |
7924 } | |
7925 | |
7926 | |
7675 /* Load IMAGEMAGICK image IMG for use on frame F. Value is non-zero if | 7927 /* Load IMAGEMAGICK image IMG for use on frame F. Value is non-zero if |
7676 successful. this function will go into the imagemagick_type structure, and | 7928 successful. this function will go into the imagemagick_type structure, and |
7677 the prototype thus needs to be compatible with that structure. */ | 7929 the prototype thus needs to be compatible with that structure. */ |
7678 | 7930 |
7679 static int | 7931 static int |
7680 imagemagick_load (f, img) | 7932 imagemagick_load (struct frame *f, |
7681 struct frame *f; | 7933 struct image *img) |
7682 struct image *img; | |
7683 { | 7934 { |
7684 int success_p = 0; | 7935 int success_p = 0; |
7685 Lisp_Object file_name; | 7936 Lisp_Object file_name; |
7686 | 7937 |
7687 /* If IMG->spec specifies a file name, create a non-file spec from it. */ | 7938 /* If IMG->spec specifies a file name, create a non-file spec from it. */ |
7719 else | 7970 else |
7720 { | 7971 { |
7721 Lisp_Object data; | 7972 Lisp_Object data; |
7722 | 7973 |
7723 data = image_spec_value (img->spec, QCdata, NULL); | 7974 data = image_spec_value (img->spec, QCdata, NULL); |
7724 success_p = imagemagick_load_image (f, img, SDATA (data), SBYTES (data),NULL); | 7975 success_p = imagemagick_load_image (f, img, SDATA (data), SBYTES (data), NULL); |
7725 } | 7976 } |
7726 | 7977 |
7727 return success_p; | 7978 return success_p; |
7728 } | 7979 } |
7729 | 7980 |
7730 /* imagemagick_load_image is a helper function for imagemagick_load, which does the | 7981 /* Structure describing the image type `imagemagick'. Its the same type of |
7731 actual loading given contents and size, apart from frame and image | 7982 structure defined for all image formats, handled by Emacs image |
7732 structures, passed from imagemagick_load. | 7983 functions. See struct image_type in dispextern.h. */ |
7733 | 7984 |
7734 Uses librimagemagick to do most of the image processing. | 7985 static struct image_type imagemagick_type = |
7735 | 7986 { |
7736 Returns non-zero when successful. | 7987 /* An identifier showing that this is an image structure for the IMAGEMAGICK format. */ |
7737 */ | 7988 &Qimagemagick, |
7738 | 7989 /* Handle to a function that can be used to identify a IMAGEMAGICK file. */ |
7739 static int | 7990 imagemagick_image_p, |
7740 imagemagick_load_image (f, img, contents, size, filename) | 7991 /* Handle to function used to load a IMAGEMAGICK file. */ |
7741 /* Pointer to emacs frame structure. */ | 7992 imagemagick_load, |
7742 struct frame *f; | 7993 /* Handle to function to free resources for IMAGEMAGICK. */ |
7743 /* Pointer to emacs image structure. */ | 7994 imagemagick_clear_image, |
7744 struct image *img; | 7995 /* An internal field to link to the next image type in a list of |
7745 /* String containing the IMAGEMAGICK data to be parsed. */ | 7996 image types, will be filled in when registering the format. */ |
7746 unsigned char *contents; | 7997 NULL |
7747 /* Size of data in bytes. */ | 7998 }; |
7748 unsigned int size; | 7999 |
7749 /* Filename, either pass filename or contents/size. */ | 8000 |
7750 unsigned char *filename; | 8001 |
7751 { | 8002 |
7752 long unsigned int width; | 8003 DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0, 0, 0, |
7753 long unsigned int height; | |
7754 | |
7755 MagickBooleanType | |
7756 status; | |
7757 | |
7758 XImagePtr ximg; | |
7759 Lisp_Object specified_bg; | |
7760 XColor background; | |
7761 int x; | |
7762 int y; | |
7763 | |
7764 MagickWand *image_wand; | |
7765 PixelIterator *iterator; | |
7766 PixelWand **pixels; | |
7767 MagickPixelPacket pixel; | |
7768 | |
7769 | |
7770 /* image_wand will contain the image. */ | |
7771 image_wand = NewMagickWand(); | |
7772 | |
7773 /* Parse the contents argument and initialize image_wand. */ | |
7774 if(filename!=NULL) | |
7775 status=MagickReadImage(image_wand, filename); | |
7776 else | |
7777 status=MagickReadImageBlob(image_wand, contents, size); | |
7778 image_error ("im read failed", Qnil, Qnil); | |
7779 if (status == MagickFalse) goto imagemagick_error; | |
7780 | |
7781 /* Handle image index for image types who can contain more than one image. | |
7782 Interface :index is same as for GIF. */ | |
7783 Lisp_Object image; | |
7784 long ino; | |
7785 image = image_spec_value (img->spec, QCindex, NULL); | |
7786 ino = INTEGERP (image) ? XFASTINT (image) : 0; | |
7787 | |
7788 | |
7789 | |
7790 if (ino >= MagickGetNumberImages(image_wand)) | |
7791 { | |
7792 image_error ("Invalid image number `%s' in image `%s'", | |
7793 image, img->spec); | |
7794 UNGCPRO; | |
7795 return 0; | |
7796 } | |
7797 | |
7798 | |
7799 if (MagickGetNumberImages(image_wand) > 1) | |
7800 img->data.lisp_val = Fcons (Qcount, | |
7801 Fcons (make_number (MagickGetNumberImages(image_wand)), | |
7802 img->data.lisp_val)); | |
7803 if(ino==0) | |
7804 MagickSetFirstIterator(image_wand); | |
7805 else | |
7806 MagickSetIteratorIndex(image_wand, ino); | |
7807 | |
7808 /* | |
7809 If width and/or height is set in the display spec | |
7810 assume we want to scale to those. */ | |
7811 | |
7812 int desired_width, desired_height; | |
7813 Lisp_Object value; | |
7814 value = image_spec_value (img->spec, QCwidth, NULL); | |
7815 desired_width = (INTEGERP (value) ? XFASTINT (value) : -1); | |
7816 value = image_spec_value (img->spec, QCheight, NULL); | |
7817 desired_height = (INTEGERP (value) ? XFASTINT (value) : -1); | |
7818 if(desired_width != -1 && desired_height != -1){ | |
7819 printf("MagickScaleImage %d %d\n",desired_width, desired_height); | |
7820 status=MagickScaleImage(image_wand, desired_width, desired_height); | |
7821 if (status == MagickFalse) { | |
7822 image_error ("Imagemagick scale failed", Qnil, Qnil); | |
7823 goto imagemagick_error; | |
7824 } | |
7825 | |
7826 } | |
7827 | |
7828 /* Also support :geometry and :crop which are imagemagick specific descriptors. */ | |
7829 | |
7830 Lisp_Object crop, geometry; | |
7831 crop = image_spec_value (img->spec, QCcrop, NULL); | |
7832 geometry = image_spec_value (img->spec, QCgeometry, NULL); | |
7833 if (STRINGP (crop) && STRINGP (geometry)){ | |
7834 printf("MagickTransformImage %s %s\n",SDATA(crop), SDATA(geometry)); | |
7835 image_wand = MagickTransformImage (image_wand, SDATA (crop), SDATA (geometry)); | |
7836 /* TODO differ between image_wand and transform_wand. */ | |
7837 } | |
7838 | |
7839 /* Furthermore :rotation. we need background color and angle for rotation. */ | |
7840 /* | |
7841 TODO background handling for rotation | |
7842 specified_bg = image_spec_value (img->spec, QCbackground, NULL); | |
7843 if (!STRINGP (specified_bg) | |
7844 */ | |
7845 double rotation; | |
7846 value = image_spec_value (img->spec, QCrotation, NULL); | |
7847 if (FLOATP (value)){ | |
7848 PixelWand* background = NewPixelWand(); | |
7849 PixelSetColor (background, "#ffffff");/*TODO remove hardcode*/ | |
7850 | |
7851 rotation = extract_float (value); | |
7852 printf ("MagickRotateImage %f\n",rotation); | |
7853 | |
7854 status=MagickRotateImage (image_wand, background,rotation); | |
7855 DestroyPixelWand (background); | |
7856 if (status == MagickFalse) { | |
7857 image_error ("Imagemagick image rotate failed", Qnil, Qnil); | |
7858 goto imagemagick_error; | |
7859 } | |
7860 } | |
7861 | |
7862 /* Finaly we are done manipulating the image, | |
7863 figure out resulting width, height, and then transfer ownerwship to Emacs. | |
7864 */ | |
7865 height=MagickGetImageHeight (image_wand); | |
7866 width=MagickGetImageWidth (image_wand); | |
7867 if (status == MagickFalse) { | |
7868 image_error ("Imagemagick image get size failed", Qnil, Qnil); | |
7869 goto imagemagick_error; | |
7870 } | |
7871 | |
7872 if (! check_image_size (f, width, height)) | |
7873 { | |
7874 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); | |
7875 goto imagemagick_error; | |
7876 } | |
7877 | |
7878 /* We can now get a valid pixel buffer from the imagemagick file, if all | |
7879 went ok. */ | |
7880 | |
7881 | |
7882 init_color_table (); | |
7883 int imagemagick_rendermethod=(INTEGERP (Vimagemagick_render_type) ? XFASTINT (Vimagemagick_render_type) : 0); | |
7884 if (imagemagick_rendermethod==0){ | |
7885 /* Try to create a x pixmap to hold the imagemagick pixmap. */ | |
7886 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)){ | |
7887 image_error("Imagemagick X bitmap allocation failure",Qnil,Qnil); | |
7888 goto imagemagick_error; | |
7889 } | |
7890 | |
7891 /* Copy imagegmagick image to x with primitive yet robust pixel | |
7892 pusher loop. This has been tested a lot with many different | |
7893 images, it doesnt work too well with image archive formats though! | |
7894 | |
7895 Also seems slow. | |
7896 */ | |
7897 | |
7898 /* Copy pixels from the imagemagick image structure to the x image map. */ | |
7899 iterator = NewPixelIterator (image_wand); | |
7900 if ((iterator == (PixelIterator *) NULL)) { | |
7901 image_error ("Imagemagick pixel iterator creation failed", Qnil, Qnil); | |
7902 goto imagemagick_error; | |
7903 } | |
7904 | |
7905 for (y=0; y < (long) MagickGetImageHeight(image_wand); y++) | |
7906 { | |
7907 pixels = PixelGetNextIteratorRow (iterator, &width); | |
7908 if ((pixels == (PixelWand **) NULL)) | |
7909 break; | |
7910 for (x=0; x < (long) width; x++) | |
7911 { | |
7912 PixelGetMagickColor (pixels[x], &pixel); | |
7913 XPutPixel (ximg, x, y, lookup_rgb_color (f, pixel.red, pixel.green, pixel.blue)); | |
7914 } | |
7915 } | |
7916 DestroyPixelIterator (iterator); | |
7917 } | |
7918 | |
7919 if (imagemagick_rendermethod==1){ | |
7920 /* Try if magicexportimage is any faster than pixelpushing. */ | |
7921 /* printf("ximg: bitmap_unit:%d format:%d byte_order:%d depth:%d bits_per_pixel:%d\n", */ | |
7922 /* ximg->bitmap_unit,ximg->format,ximg->byte_order,ximg->depth,ximg->bits_per_pixel); */ | |
7923 int imagedepth=24;/*MagickGetImageDepth(image_wand);*/ | |
7924 char* exportdepth= imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/ | |
7925 /* Try to create a x pixmap to hold the imagemagick pixmap. */ | |
7926 printf("imagedepth:%d exportdepth:%s\n", imagedepth, exportdepth); | |
7927 if (!x_create_x_image_and_pixmap (f, width, height, imagedepth, &ximg, &img->pixmap)){ | |
7928 image_error("Imagemagick X bitmap allocation failure",Qnil,Qnil); | |
7929 goto imagemagick_error; | |
7930 } | |
7931 | |
7932 | |
7933 /* Oddly, the below code doesnt seem to work:*/ | |
7934 int pixelwidth; | |
7935 /* switch(ximg->bitmap_unit){ */ | |
7936 /* case 8: */ | |
7937 /* pixelwidth=CharPixel; */ | |
7938 /* break; */ | |
7939 /* case 16: */ | |
7940 /* pixelwidth=ShortPixel; */ | |
7941 /* break; */ | |
7942 /* case 32: */ | |
7943 /* pixelwidth=LongPixel; */ | |
7944 /* break; */ | |
7945 /* } */ | |
7946 /* | |
7947 Here im just guessing the format of the bitmap. | |
7948 happens to work fine for: | |
7949 - bw djvu images | |
7950 on rgb display. | |
7951 seems about 3 times as fast as pixel pushing(not carefully measured) | |
7952 with color djvu, the bitplanes are mapped to wrong color(seems fixed). | |
7953 | |
7954 */ | |
7955 pixelwidth=CharPixel;/*??? TODO figure out*/ | |
7956 #ifdef HAVE_MAGICKEXPORTIMAGEPIXELS | |
7957 MagickExportImagePixels(image_wand, | |
7958 0,0, | |
7959 width,height, | |
7960 exportdepth, | |
7961 pixelwidth, | |
7962 /*&(img->pixmap));*/ | |
7963 ximg->data); | |
7964 #else | |
7965 image_error("You dont have MagickExportImagePixels, upgrade ImageMagick if you want to try it!",Qnil,Qnil); | |
7966 #endif | |
7967 } | |
7968 | |
7969 | |
7970 #ifdef COLOR_TABLE_SUPPORT | |
7971 /* Remember colors allocated for this image. */ | |
7972 img->colors = colors_in_color_table (&img->ncolors); | |
7973 free_color_table (); | |
7974 #endif /* COLOR_TABLE_SUPPORT */ | |
7975 | |
7976 | |
7977 img->width = width; | |
7978 img->height = height; | |
7979 | |
7980 /* Maybe fill in the background field while we have ximg handy. | |
7981 Casting avoids a GCC warning. */ | |
7982 /* IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);*/ | |
7983 | |
7984 /* Put the image into the pixmap, then free the X image and its | |
7985 buffer. */ | |
7986 x_put_x_image (f, ximg, img->pixmap, width, height); | |
7987 | |
7988 x_destroy_x_image (ximg); | |
7989 | |
7990 | |
7991 /* JAVE TODO more cleanup. */ | |
7992 DestroyMagickWand (image_wand); | |
7993 | |
7994 return 1; | |
7995 | |
7996 imagemagick_error: | |
7997 /* TODO more cleanup. */ | |
7998 image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil); | |
7999 printf("Imagemagick error, see *Messages*\n"); | |
8000 return 0; | |
8001 } | |
8002 | |
8003 DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0,0,0, | |
8004 doc: /* Return image file types supported by ImageMagick. | 8004 doc: /* Return image file types supported by ImageMagick. |
8005 Since ImageMagick recognizes a lot of file-types that clash with Emacs, | 8005 Since ImageMagick recognizes a lot of file-types that clash with Emacs, |
8006 such as .c, we want to be able to alter the list at the lisp level. */) | 8006 such as .c, we want to be able to alter the list at the lisp level. */) |
8007 () | 8007 () |
8008 { | 8008 { |
8009 Lisp_Object typelist = Qnil; | 8009 Lisp_Object typelist = Qnil; |
8010 unsigned long numf; | 8010 unsigned long numf; |
8011 ExceptionInfo ex; | 8011 ExceptionInfo ex; |
8012 char** imtypes = GetMagickList ("*", &numf, &ex); | 8012 char** imtypes = GetMagickList ("*", &numf, &ex); |
8013 int i; | 8013 int i; |
8014 Lisp_Object Qimagemagicktype; | 8014 Lisp_Object Qimagemagicktype; |
8015 for (i = 0; i < numf; i++) { | 8015 for (i = 0; i < numf; i++) |
8016 Qimagemagicktype = intern (*( imtypes + i)); | 8016 { |
8017 typelist = Fcons (Qimagemagicktype, typelist); | 8017 Qimagemagicktype = intern (imtypes[i]); |
8018 } | 8018 typelist = Fcons (Qimagemagicktype, typelist); |
8019 return typelist; | 8019 } |
8020 return typelist; | |
8020 } | 8021 } |
8021 | 8022 |
8022 #endif /* defined (HAVE_IMAGEMAGICK) */ | 8023 #endif /* defined (HAVE_IMAGEMAGICK) */ |
8023 | 8024 |
8024 | 8025 |
9034 automatically removes it from the image cache. If the cache contains | 9035 automatically removes it from the image cache. If the cache contains |
9035 a large number of images, the actual eviction time may be shorter. | 9036 a large number of images, the actual eviction time may be shorter. |
9036 The value can also be nil, meaning the cache is never cleared. | 9037 The value can also be nil, meaning the cache is never cleared. |
9037 The function `clear-image-cache' disregards this variable. */); | 9038 The function `clear-image-cache' disregards this variable. */); |
9038 Vimage_cache_eviction_delay = make_number (300); | 9039 Vimage_cache_eviction_delay = make_number (300); |
9039 } | |
9040 | |
9041 #ifdef HAVE_IMAGEMAGICK | 9040 #ifdef HAVE_IMAGEMAGICK |
9042 DEFVAR_LISP ("imagemagick-render-type", &Vimagemagick_render_type, | 9041 DEFVAR_LISP ("imagemagick-render-type", &Vimagemagick_render_type, |
9043 doc: /* */); | 9042 doc: /* Choose between ImageMagick render methods. */); |
9044 #endif | 9043 #endif |
9044 | |
9045 } | |
9046 | |
9045 | 9047 |
9046 void | 9048 void |
9047 init_image () | 9049 init_image () |
9048 { | 9050 { |
9049 | 9051 |