diff options
| author | Joakim Verona | 2010-04-02 23:09:13 +0200 |
|---|---|---|
| committer | Joakim Verona | 2010-04-02 23:09:13 +0200 |
| commit | 3de25479216a2ecec509df8933047873d084f708 (patch) | |
| tree | 55a93b61a20914cff6afe0c9f40d3bd0f8680ed7 /src/image.c | |
| parent | 796bb9364a5244a089769f4c92daab1835b618c7 (diff) | |
| download | emacs-3de25479216a2ecec509df8933047873d084f708.tar.gz emacs-3de25479216a2ecec509df8933047873d084f708.zip | |
imagemagick patch5 + minor mods
Diffstat (limited to 'src/image.c')
| -rw-r--r-- | src/image.c | 478 |
1 files changed, 477 insertions, 1 deletions
diff --git a/src/image.c b/src/image.c index 030e06ad77a..8159575e640 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -606,7 +606,7 @@ extern Lisp_Object QCdata, QCtype; | |||
| 606 | extern Lisp_Object Qcenter; | 606 | extern Lisp_Object Qcenter; |
| 607 | Lisp_Object QCascent, QCmargin, QCrelief, Qcount, Qextension_data; | 607 | Lisp_Object QCascent, QCmargin, QCrelief, Qcount, Qextension_data; |
| 608 | Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask; | 608 | Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask; |
| 609 | Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask; | 609 | Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask, QCgeometry, QCcrop, QCrotation; |
| 610 | 610 | ||
| 611 | /* Other symbols. */ | 611 | /* Other symbols. */ |
| 612 | 612 | ||
| @@ -7538,6 +7538,449 @@ gif_load (struct frame *f, struct image *img) | |||
| 7538 | #endif /* HAVE_GIF */ | 7538 | #endif /* HAVE_GIF */ |
| 7539 | 7539 | ||
| 7540 | 7540 | ||
| 7541 | /*********************************************************************** | ||
| 7542 | imagemagick | ||
| 7543 | ***********************************************************************/ | ||
| 7544 | #if defined (HAVE_IMAGEMAGICK) | ||
| 7545 | Lisp_Object Vimagemagick_render_type; | ||
| 7546 | /* Function prototypes. */ | ||
| 7547 | |||
| 7548 | static int imagemagick_image_p (Lisp_Object object); | ||
| 7549 | static int imagemagick_load (struct frame *f, struct image *img); | ||
| 7550 | |||
| 7551 | static int imagemagick_load_image (struct frame *, struct image *, | ||
| 7552 | unsigned char *, unsigned int, unsigned char *); | ||
| 7553 | |||
| 7554 | /* The symbol `imagemagick' identifying images of this type. */ | ||
| 7555 | |||
| 7556 | Lisp_Object Qimagemagick; | ||
| 7557 | Lisp_Object Vimagemagick_render_type; | ||
| 7558 | |||
| 7559 | /* Indices of image specification fields in imagemagick_format, below. */ | ||
| 7560 | |||
| 7561 | enum imagemagick_keyword_index | ||
| 7562 | { | ||
| 7563 | IMAGEMAGICK_TYPE, | ||
| 7564 | IMAGEMAGICK_DATA, | ||
| 7565 | IMAGEMAGICK_FILE, | ||
| 7566 | IMAGEMAGICK_ASCENT, | ||
| 7567 | IMAGEMAGICK_MARGIN, | ||
| 7568 | IMAGEMAGICK_RELIEF, | ||
| 7569 | IMAGEMAGICK_ALGORITHM, | ||
| 7570 | IMAGEMAGICK_HEURISTIC_MASK, | ||
| 7571 | IMAGEMAGICK_MASK, | ||
| 7572 | IMAGEMAGICK_BACKGROUND, | ||
| 7573 | IMAGEMAGICK_LAST | ||
| 7574 | }; | ||
| 7575 | |||
| 7576 | /* Vector of image_keyword structures describing the format | ||
| 7577 | of valid user-defined image specifications. */ | ||
| 7578 | |||
| 7579 | static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] = | ||
| 7580 | { | ||
| 7581 | {":type", IMAGE_SYMBOL_VALUE, 1}, | ||
| 7582 | {":data", IMAGE_STRING_VALUE, 0}, | ||
| 7583 | {":file", IMAGE_STRING_VALUE, 0}, | ||
| 7584 | {":ascent", IMAGE_ASCENT_VALUE, 0}, | ||
| 7585 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, | ||
| 7586 | {":relief", IMAGE_INTEGER_VALUE, 0}, | ||
| 7587 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | ||
| 7588 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | ||
| 7589 | {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | ||
| 7590 | {":background", IMAGE_STRING_OR_NIL_VALUE, 0} | ||
| 7591 | }; | ||
| 7592 | /* Free X resources of imagemagick image IMG which is used on frame F. */ | ||
| 7593 | |||
| 7594 | static void | ||
| 7595 | imagemagick_clear_image (f, img) | ||
| 7596 | struct frame *f; | ||
| 7597 | struct image *img; | ||
| 7598 | { | ||
| 7599 | printf("clearing imagemagick image\n"); | ||
| 7600 | x_clear_image (f, img); | ||
| 7601 | } | ||
| 7602 | |||
| 7603 | /* Structure describing the image type `imagemagick'. Its the same type of | ||
| 7604 | structure defined for all image formats, handled by Emacs image | ||
| 7605 | functions. See struct image_type in dispextern.h. */ | ||
| 7606 | |||
| 7607 | static struct image_type imagemagick_type = | ||
| 7608 | { | ||
| 7609 | /* An identifier showing that this is an image structure for the IMAGEMAGICK format. */ | ||
| 7610 | &Qimagemagick, | ||
| 7611 | /* Handle to a function that can be used to identify a IMAGEMAGICK file. */ | ||
| 7612 | imagemagick_image_p, | ||
| 7613 | /* Handle to function used to load a IMAGEMAGICK file. */ | ||
| 7614 | imagemagick_load, | ||
| 7615 | /* Handle to function to free resources for IMAGEMAGICK. */ | ||
| 7616 | imagemagick_clear_image, | ||
| 7617 | /* An internal field to link to the next image type in a list of | ||
| 7618 | image types, will be filled in when registering the format. */ | ||
| 7619 | NULL | ||
| 7620 | }; | ||
| 7621 | |||
| 7622 | |||
| 7623 | /* Return non-zero if OBJECT is a valid IMAGEMAGICK image specification. Do | ||
| 7624 | this by calling parse_image_spec and supplying the keywords that | ||
| 7625 | identify the IMAGEMAGICK format. */ | ||
| 7626 | |||
| 7627 | static int | ||
| 7628 | imagemagick_image_p (object) | ||
| 7629 | Lisp_Object object; | ||
| 7630 | { | ||
| 7631 | struct image_keyword fmt[IMAGEMAGICK_LAST]; | ||
| 7632 | bcopy (imagemagick_format, fmt, sizeof fmt); | ||
| 7633 | |||
| 7634 | if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, Qimagemagick)) | ||
| 7635 | return 0; | ||
| 7636 | |||
| 7637 | /* Must specify either the :data or :file keyword. */ | ||
| 7638 | return fmt[IMAGEMAGICK_FILE].count + fmt[IMAGEMAGICK_DATA].count == 1; | ||
| 7639 | } | ||
| 7640 | |||
| 7641 | /* The GIF library also defines DrawRectangle, but its never used in Emacs. | ||
| 7642 | Therefore rename the function so it doesnt collide with ImageMagick. */ | ||
| 7643 | #define DrawRectangle DrawRectangleGif | ||
| 7644 | #include <wand/MagickWand.h> | ||
| 7645 | |||
| 7646 | /* Load IMAGEMAGICK image IMG for use on frame F. Value is non-zero if | ||
| 7647 | successful. this function will go into the imagemagick_type structure, and | ||
| 7648 | the prototype thus needs to be compatible with that structure. */ | ||
| 7649 | |||
| 7650 | static int | ||
| 7651 | imagemagick_load (f, img) | ||
| 7652 | struct frame *f; | ||
| 7653 | struct image *img; | ||
| 7654 | { | ||
| 7655 | int success_p = 0; | ||
| 7656 | Lisp_Object file_name; | ||
| 7657 | |||
| 7658 | /* If IMG->spec specifies a file name, create a non-file spec from it. */ | ||
| 7659 | file_name = image_spec_value (img->spec, QCfile, NULL); | ||
| 7660 | if (STRINGP (file_name)) | ||
| 7661 | { | ||
| 7662 | Lisp_Object file; | ||
| 7663 | unsigned char *contents; | ||
| 7664 | int size; | ||
| 7665 | struct gcpro gcpro1; | ||
| 7666 | |||
| 7667 | file = x_find_image_file (file_name); | ||
| 7668 | GCPRO1 (file); | ||
| 7669 | if (!STRINGP (file)) | ||
| 7670 | { | ||
| 7671 | image_error ("Cannot find image file `%s'", file_name, Qnil); | ||
| 7672 | UNGCPRO; | ||
| 7673 | return 0; | ||
| 7674 | } | ||
| 7675 | |||
| 7676 | /* Read the entire file into memory. */ | ||
| 7677 | /* contents = slurp_file (SDATA (file), &size); */ | ||
| 7678 | /* if (contents == NULL) */ | ||
| 7679 | /* { */ | ||
| 7680 | /* image_error ("Error loading IMAGEMAGICK image `%s'", img->spec, Qnil); */ | ||
| 7681 | /* UNGCPRO; */ | ||
| 7682 | /* return 0; */ | ||
| 7683 | /* } */ | ||
| 7684 | /* If the file was slurped into memory properly, parse it. */ | ||
| 7685 | success_p = imagemagick_load_image (f, img, 0, 0, SDATA(file_name)); | ||
| 7686 | UNGCPRO; | ||
| 7687 | } | ||
| 7688 | /* Else its not a file, its a lisp object. Load the image from a | ||
| 7689 | lisp object rather than a file. */ | ||
| 7690 | else | ||
| 7691 | { | ||
| 7692 | Lisp_Object data; | ||
| 7693 | |||
| 7694 | data = image_spec_value (img->spec, QCdata, NULL); | ||
| 7695 | success_p = imagemagick_load_image (f, img, SDATA (data), SBYTES (data),NULL); | ||
| 7696 | } | ||
| 7697 | |||
| 7698 | return success_p; | ||
| 7699 | } | ||
| 7700 | |||
| 7701 | /* imagemagick_load_image is a helper function for imagemagick_load, which does the | ||
| 7702 | actual loading given contents and size, apart from frame and image | ||
| 7703 | structures, passed from imagemagick_load. | ||
| 7704 | |||
| 7705 | Uses librimagemagick to do most of the image processing. | ||
| 7706 | |||
| 7707 | Returns non-zero when successful. | ||
| 7708 | */ | ||
| 7709 | |||
| 7710 | static int | ||
| 7711 | imagemagick_load_image (f, img, contents, size, filename) | ||
| 7712 | /* Pointer to emacs frame structure. */ | ||
| 7713 | struct frame *f; | ||
| 7714 | /* Pointer to emacs image structure. */ | ||
| 7715 | struct image *img; | ||
| 7716 | /* String containing the IMAGEMAGICK data to be parsed. */ | ||
| 7717 | unsigned char *contents; | ||
| 7718 | /* Size of data in bytes. */ | ||
| 7719 | unsigned int size; | ||
| 7720 | /* Filename, either pass filename or contents/size. */ | ||
| 7721 | unsigned char *filename; | ||
| 7722 | { | ||
| 7723 | long unsigned int width; | ||
| 7724 | long unsigned int height; | ||
| 7725 | |||
| 7726 | MagickBooleanType | ||
| 7727 | status; | ||
| 7728 | |||
| 7729 | XImagePtr ximg; | ||
| 7730 | Lisp_Object specified_bg; | ||
| 7731 | XColor background; | ||
| 7732 | int x; | ||
| 7733 | int y; | ||
| 7734 | |||
| 7735 | MagickWand *image_wand; | ||
| 7736 | PixelIterator *iterator; | ||
| 7737 | PixelWand **pixels; | ||
| 7738 | MagickPixelPacket pixel; | ||
| 7739 | |||
| 7740 | |||
| 7741 | /* image_wand will contain the image. */ | ||
| 7742 | image_wand = NewMagickWand(); | ||
| 7743 | |||
| 7744 | /* Parse the contents argument and initialize image_wand. */ | ||
| 7745 | if(filename!=NULL) | ||
| 7746 | status=MagickReadImage(image_wand, filename); | ||
| 7747 | else | ||
| 7748 | status=MagickReadImageBlob(image_wand, contents, size); | ||
| 7749 | image_error ("im read failed", Qnil, Qnil); | ||
| 7750 | if (status == MagickFalse) goto imagemagick_error; | ||
| 7751 | |||
| 7752 | /* Handle image index for image types who can contain more than one image. | ||
| 7753 | Interface :index is same as for GIF. */ | ||
| 7754 | Lisp_Object image; | ||
| 7755 | long ino; | ||
| 7756 | image = image_spec_value (img->spec, QCindex, NULL); | ||
| 7757 | ino = INTEGERP (image) ? XFASTINT (image) : 0; | ||
| 7758 | |||
| 7759 | /* if (ino >= ) */ | ||
| 7760 | /* { */ | ||
| 7761 | /* image_error ("Invalid image number `%s' in image `%s'", */ | ||
| 7762 | /* image, img->spec); */ | ||
| 7763 | /* UNGCPRO; */ | ||
| 7764 | /* return 0; */ | ||
| 7765 | /* } */ | ||
| 7766 | |||
| 7767 | if(ino==0) | ||
| 7768 | MagickSetFirstIterator(image_wand); | ||
| 7769 | else | ||
| 7770 | MagickSetIteratorIndex(image_wand, ino); | ||
| 7771 | |||
| 7772 | /* | ||
| 7773 | If width and/or height is set in the display spec | ||
| 7774 | assume we want to scale to those. */ | ||
| 7775 | |||
| 7776 | int desired_width, desired_height; | ||
| 7777 | Lisp_Object value; | ||
| 7778 | value = image_spec_value (img->spec, QCwidth, NULL); | ||
| 7779 | desired_width = (INTEGERP (value) ? XFASTINT (value) : -1); | ||
| 7780 | value = image_spec_value (img->spec, QCheight, NULL); | ||
| 7781 | desired_height = (INTEGERP (value) ? XFASTINT (value) : -1); | ||
| 7782 | if(desired_width != -1 && desired_height != -1){ | ||
| 7783 | printf("MagickScaleImage %d %d\n",desired_width, desired_height); | ||
| 7784 | status=MagickScaleImage(image_wand, desired_width, desired_height); | ||
| 7785 | if (status == MagickFalse) { | ||
| 7786 | image_error ("Imagemagick scale failed", Qnil, Qnil); | ||
| 7787 | goto imagemagick_error; | ||
| 7788 | } | ||
| 7789 | |||
| 7790 | } | ||
| 7791 | |||
| 7792 | /* Also support :geometry and :crop which are imagemagick specific descriptors. */ | ||
| 7793 | |||
| 7794 | Lisp_Object crop, geometry; | ||
| 7795 | crop = image_spec_value (img->spec, QCcrop, NULL); | ||
| 7796 | geometry = image_spec_value (img->spec, QCgeometry, NULL); | ||
| 7797 | if (STRINGP (crop) && STRINGP (geometry)){ | ||
| 7798 | printf("MagickTransformImage %s %s\n",SDATA(crop), SDATA(geometry)); | ||
| 7799 | image_wand = MagickTransformImage (image_wand, SDATA (crop), SDATA (geometry)); | ||
| 7800 | /* TODO differ between image_wand and transform_wand. */ | ||
| 7801 | } | ||
| 7802 | |||
| 7803 | /* Furthermore :rotation. we need background color and angle for rotation. */ | ||
| 7804 | /* | ||
| 7805 | TODO background handling for rotation | ||
| 7806 | specified_bg = image_spec_value (img->spec, QCbackground, NULL); | ||
| 7807 | if (!STRINGP (specified_bg) | ||
| 7808 | */ | ||
| 7809 | double rotation; | ||
| 7810 | value = image_spec_value (img->spec, QCrotation, NULL); | ||
| 7811 | if (FLOATP (value)){ | ||
| 7812 | PixelWand* background = NewPixelWand(); | ||
| 7813 | PixelSetColor (background, "#ffffff");/*TODO remove hardcode*/ | ||
| 7814 | |||
| 7815 | rotation = extract_float (value); | ||
| 7816 | printf ("MagickRotateImage %f\n",rotation); | ||
| 7817 | |||
| 7818 | status=MagickRotateImage (image_wand, background,rotation); | ||
| 7819 | DestroyPixelWand (background); | ||
| 7820 | if (status == MagickFalse) { | ||
| 7821 | image_error ("Imagemagick image rotate failed", Qnil, Qnil); | ||
| 7822 | goto imagemagick_error; | ||
| 7823 | } | ||
| 7824 | } | ||
| 7825 | |||
| 7826 | /* Finaly we are done manipulating the image, | ||
| 7827 | figure out resulting width, height, and then transfer ownerwship to Emacs. | ||
| 7828 | */ | ||
| 7829 | height=MagickGetImageHeight (image_wand); | ||
| 7830 | width=MagickGetImageWidth (image_wand); | ||
| 7831 | if (status == MagickFalse) { | ||
| 7832 | image_error ("Imagemagick image get size failed", Qnil, Qnil); | ||
| 7833 | goto imagemagick_error; | ||
| 7834 | } | ||
| 7835 | |||
| 7836 | if (! check_image_size (f, width, height)) | ||
| 7837 | { | ||
| 7838 | image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); | ||
| 7839 | goto imagemagick_error; | ||
| 7840 | } | ||
| 7841 | |||
| 7842 | /* We can now get a valid pixel buffer from the imagemagick file, if all | ||
| 7843 | went ok. */ | ||
| 7844 | |||
| 7845 | |||
| 7846 | init_color_table (); | ||
| 7847 | int imagemagick_rendermethod=(INTEGERP (Vimagemagick_render_type) ? XFASTINT (Vimagemagick_render_type) : 0); | ||
| 7848 | if (imagemagick_rendermethod==0){ | ||
| 7849 | /* Try to create a x pixmap to hold the imagemagick pixmap. */ | ||
| 7850 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)){ | ||
| 7851 | image_error("Imagemagick X bitmap allocation failure",Qnil,Qnil); | ||
| 7852 | goto imagemagick_error; | ||
| 7853 | } | ||
| 7854 | |||
| 7855 | /* Copy imagegmagick image to x with primitive yet robust pixel | ||
| 7856 | pusher loop. This has been tested a lot with many different | ||
| 7857 | images, it doesnt work too well with image archive formats though! | ||
| 7858 | |||
| 7859 | Also seems slow. | ||
| 7860 | */ | ||
| 7861 | |||
| 7862 | /* Copy pixels from the imagemagick image structure to the x image map. */ | ||
| 7863 | iterator = NewPixelIterator (image_wand); | ||
| 7864 | if ((iterator == (PixelIterator *) NULL)) { | ||
| 7865 | image_error ("Imagemagick pixel iterator creation failed", Qnil, Qnil); | ||
| 7866 | goto imagemagick_error; | ||
| 7867 | } | ||
| 7868 | |||
| 7869 | for (y=0; y < (long) MagickGetImageHeight(image_wand); y++) | ||
| 7870 | { | ||
| 7871 | pixels = PixelGetNextIteratorRow (iterator, &width); | ||
| 7872 | if ((pixels == (PixelWand **) NULL)) | ||
| 7873 | break; | ||
| 7874 | for (x=0; x < (long) width; x++) | ||
| 7875 | { | ||
| 7876 | PixelGetMagickColor (pixels[x], &pixel); | ||
| 7877 | XPutPixel (ximg, x, y, lookup_rgb_color (f, pixel.red, pixel.green, pixel.blue)); | ||
| 7878 | } | ||
| 7879 | } | ||
| 7880 | DestroyPixelIterator (iterator); | ||
| 7881 | } | ||
| 7882 | |||
| 7883 | if (imagemagick_rendermethod==1){ | ||
| 7884 | /* Try if magicexportimage is any faster than pixelpushing. */ | ||
| 7885 | /* printf("ximg: bitmap_unit:%d format:%d byte_order:%d depth:%d bits_per_pixel:%d\n", */ | ||
| 7886 | /* ximg->bitmap_unit,ximg->format,ximg->byte_order,ximg->depth,ximg->bits_per_pixel); */ | ||
| 7887 | int imagedepth=24;/*MagickGetImageDepth(image_wand);*/ | ||
| 7888 | char* exportdepth= imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/ | ||
| 7889 | /* Try to create a x pixmap to hold the imagemagick pixmap. */ | ||
| 7890 | printf("imagedepth:%d exportdepth:%s\n", imagedepth, exportdepth); | ||
| 7891 | if (!x_create_x_image_and_pixmap (f, width, height, imagedepth, &ximg, &img->pixmap)){ | ||
| 7892 | image_error("Imagemagick X bitmap allocation failure",Qnil,Qnil); | ||
| 7893 | goto imagemagick_error; | ||
| 7894 | } | ||
| 7895 | |||
| 7896 | |||
| 7897 | /* Oddly, the below code doesnt seem to work:*/ | ||
| 7898 | int pixelwidth; | ||
| 7899 | /* switch(ximg->bitmap_unit){ */ | ||
| 7900 | /* case 8: */ | ||
| 7901 | /* pixelwidth=CharPixel; */ | ||
| 7902 | /* break; */ | ||
| 7903 | /* case 16: */ | ||
| 7904 | /* pixelwidth=ShortPixel; */ | ||
| 7905 | /* break; */ | ||
| 7906 | /* case 32: */ | ||
| 7907 | /* pixelwidth=LongPixel; */ | ||
| 7908 | /* break; */ | ||
| 7909 | /* } */ | ||
| 7910 | /* | ||
| 7911 | Here im just guessing the format of the bitmap. | ||
| 7912 | happens to work fine for: | ||
| 7913 | - bw djvu images | ||
| 7914 | on rgb display. | ||
| 7915 | seems about 3 times as fast as pixel pushing(not carefully measured) | ||
| 7916 | with color djvu, the bitplanes are mapped to wrong color(seems fixed). | ||
| 7917 | |||
| 7918 | */ | ||
| 7919 | pixelwidth=CharPixel;/*??? TODO figure out*/ | ||
| 7920 | MagickExportImagePixels(image_wand, | ||
| 7921 | 0,0, | ||
| 7922 | width,height, | ||
| 7923 | exportdepth, | ||
| 7924 | pixelwidth, | ||
| 7925 | /*&(img->pixmap));*/ | ||
| 7926 | ximg->data); | ||
| 7927 | } | ||
| 7928 | |||
| 7929 | #ifdef COLOR_TABLE_SUPPORT | ||
| 7930 | /* Remember colors allocated for this image. */ | ||
| 7931 | img->colors = colors_in_color_table (&img->ncolors); | ||
| 7932 | free_color_table (); | ||
| 7933 | #endif /* COLOR_TABLE_SUPPORT */ | ||
| 7934 | |||
| 7935 | |||
| 7936 | img->width = width; | ||
| 7937 | img->height = height; | ||
| 7938 | |||
| 7939 | /* Maybe fill in the background field while we have ximg handy. | ||
| 7940 | Casting avoids a GCC warning. */ | ||
| 7941 | /* IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);*/ | ||
| 7942 | |||
| 7943 | /* Put the image into the pixmap, then free the X image and its | ||
| 7944 | buffer. */ | ||
| 7945 | x_put_x_image (f, ximg, img->pixmap, width, height); | ||
| 7946 | |||
| 7947 | x_destroy_x_image (ximg); | ||
| 7948 | |||
| 7949 | |||
| 7950 | /* JAVE TODO more cleanup. */ | ||
| 7951 | DestroyMagickWand (image_wand); | ||
| 7952 | |||
| 7953 | return 1; | ||
| 7954 | |||
| 7955 | imagemagick_error: | ||
| 7956 | /* TODO more cleanup. */ | ||
| 7957 | image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil); | ||
| 7958 | printf("Imagemagick error, see *Messages*\n"); | ||
| 7959 | return 0; | ||
| 7960 | } | ||
| 7961 | |||
| 7962 | DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0,0,0, | ||
| 7963 | doc: /* Return image file types supported by ImageMagick. | ||
| 7964 | Since ImageMagic recognizes a lot of file-types that clash with Emacs, | ||
| 7965 | such as .c, we want to be able to alter the list at the lisp level. */) | ||
| 7966 | () | ||
| 7967 | { | ||
| 7968 | Lisp_Object typelist = Qnil; | ||
| 7969 | unsigned long numf; | ||
| 7970 | ExceptionInfo ex; | ||
| 7971 | char** imtypes = GetMagickList ("*", &numf, &ex); | ||
| 7972 | int i; | ||
| 7973 | Lisp_Object Qimagemagicktype; | ||
| 7974 | for (i = 0; i < numf; i++) { | ||
| 7975 | Qimagemagicktype = intern (*( imtypes + i)); | ||
| 7976 | typelist = Fcons (Qimagemagicktype, typelist); | ||
| 7977 | } | ||
| 7978 | return typelist; | ||
| 7979 | } | ||
| 7980 | |||
| 7981 | #endif /* defined (HAVE_IMAGEMAGICK) */ | ||
| 7982 | |||
| 7983 | |||
| 7541 | 7984 | ||
| 7542 | /*********************************************************************** | 7985 | /*********************************************************************** |
| 7543 | SVG | 7986 | SVG |
| @@ -8335,6 +8778,14 @@ of `image-library-alist', which see). */) | |||
| 8335 | return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries); | 8778 | return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries); |
| 8336 | #endif | 8779 | #endif |
| 8337 | 8780 | ||
| 8781 | #if defined (HAVE_IMAGEMAGICK) | ||
| 8782 | if (EQ (type, Qimagemagick)){ | ||
| 8783 | /* MagickWandGenesis() initalizes the imagemagick library. */ | ||
| 8784 | MagickWandGenesis(); | ||
| 8785 | return CHECK_LIB_AVAILABLE (&imagemagick_type, init_imagemagick_functions, libraries); | ||
| 8786 | } | ||
| 8787 | #endif | ||
| 8788 | |||
| 8338 | #ifdef HAVE_GHOSTSCRIPT | 8789 | #ifdef HAVE_GHOSTSCRIPT |
| 8339 | if (EQ (type, Qpostscript)) | 8790 | if (EQ (type, Qpostscript)) |
| 8340 | return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries); | 8791 | return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries); |
| @@ -8345,6 +8796,7 @@ of `image-library-alist', which see). */) | |||
| 8345 | return Qnil; | 8796 | return Qnil; |
| 8346 | } | 8797 | } |
| 8347 | 8798 | ||
| 8799 | |||
| 8348 | void | 8800 | void |
| 8349 | syms_of_image () | 8801 | syms_of_image () |
| 8350 | { | 8802 | { |
| @@ -8422,7 +8874,14 @@ non-numeric, there is no explicit limit on the size of images. */); | |||
| 8422 | staticpro (&QCheuristic_mask); | 8874 | staticpro (&QCheuristic_mask); |
| 8423 | QCindex = intern_c_string (":index"); | 8875 | QCindex = intern_c_string (":index"); |
| 8424 | staticpro (&QCindex); | 8876 | staticpro (&QCindex); |
| 8877 | QCgeometry = intern (":geometry"); | ||
| 8878 | staticpro (&QCgeometry); | ||
| 8879 | QCcrop = intern (":crop"); | ||
| 8880 | staticpro (&QCcrop); | ||
| 8881 | QCrotation = intern (":rotation"); | ||
| 8882 | staticpro (&QCrotation); | ||
| 8425 | QCmatrix = intern_c_string (":matrix"); | 8883 | QCmatrix = intern_c_string (":matrix"); |
| 8884 | |||
| 8426 | staticpro (&QCmatrix); | 8885 | staticpro (&QCmatrix); |
| 8427 | QCcolor_adjustment = intern_c_string (":color-adjustment"); | 8886 | QCcolor_adjustment = intern_c_string (":color-adjustment"); |
| 8428 | staticpro (&QCcolor_adjustment); | 8887 | staticpro (&QCcolor_adjustment); |
| @@ -8482,6 +8941,12 @@ non-numeric, there is no explicit limit on the size of images. */); | |||
| 8482 | ADD_IMAGE_TYPE (Qpng); | 8941 | ADD_IMAGE_TYPE (Qpng); |
| 8483 | #endif | 8942 | #endif |
| 8484 | 8943 | ||
| 8944 | #if defined (HAVE_IMAGEMAGICK) | ||
| 8945 | Qimagemagick = intern ("imagemagick"); | ||
| 8946 | staticpro (&Qimagemagick); | ||
| 8947 | ADD_IMAGE_TYPE (Qimagemagick); | ||
| 8948 | #endif | ||
| 8949 | |||
| 8485 | #if defined (HAVE_RSVG) | 8950 | #if defined (HAVE_RSVG) |
| 8486 | Qsvg = intern_c_string ("svg"); | 8951 | Qsvg = intern_c_string ("svg"); |
| 8487 | staticpro (&Qsvg); | 8952 | staticpro (&Qsvg); |
| @@ -8498,6 +8963,9 @@ non-numeric, there is no explicit limit on the size of images. */); | |||
| 8498 | #endif /* HAVE_RSVG */ | 8963 | #endif /* HAVE_RSVG */ |
| 8499 | 8964 | ||
| 8500 | defsubr (&Sinit_image_library); | 8965 | defsubr (&Sinit_image_library); |
| 8966 | #ifdef HAVE_IMAGEMAGICK | ||
| 8967 | defsubr (&Simagemagick_types); | ||
| 8968 | #endif | ||
| 8501 | defsubr (&Sclear_image_cache); | 8969 | defsubr (&Sclear_image_cache); |
| 8502 | defsubr (&Simage_refresh); | 8970 | defsubr (&Simage_refresh); |
| 8503 | defsubr (&Simage_size); | 8971 | defsubr (&Simage_size); |
| @@ -8525,12 +8993,20 @@ When an image has not been displayed this many seconds, remove it | |||
| 8525 | from the image cache. Value must be an integer or nil with nil | 8993 | from the image cache. Value must be an integer or nil with nil |
| 8526 | meaning don't clear the cache. */); | 8994 | meaning don't clear the cache. */); |
| 8527 | Vimage_cache_eviction_delay = make_number (30 * 60); | 8995 | Vimage_cache_eviction_delay = make_number (30 * 60); |
| 8996 | |||
| 8997 | #ifdef HAVE_IMAGEMAGICK | ||
| 8998 | DEFVAR_LISP ("imagemagick-render-type", &Vimagemagick_render_type, | ||
| 8999 | doc: /* */); | ||
| 9000 | #endif | ||
| 8528 | } | 9001 | } |
| 8529 | 9002 | ||
| 8530 | void | 9003 | void |
| 8531 | init_image () | 9004 | init_image () |
| 8532 | { | 9005 | { |
| 9006 | |||
| 8533 | } | 9007 | } |
| 8534 | 9008 | ||
| 9009 | |||
| 9010 | |||
| 8535 | /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9 | 9011 | /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9 |
| 8536 | (do not change this comment) */ | 9012 | (do not change this comment) */ |