diff options
| author | Chong Yidong | 2012-06-11 22:42:55 +0800 |
|---|---|---|
| committer | Chong Yidong | 2012-06-11 22:42:55 +0800 |
| commit | 1b9b4cf4c1152f06153ac9c141fb9f724b984884 (patch) | |
| tree | c058db7e9bf646a7e40ffefa4c4894665876e821 /src | |
| parent | 05ecb497393551e8bb65fb07fbdc4bbb5f61765a (diff) | |
| download | emacs-1b9b4cf4c1152f06153ac9c141fb9f724b984884.tar.gz emacs-1b9b4cf4c1152f06153ac9c141fb9f724b984884.zip | |
Support transparency for ImageMagick images.
* src/image.c (imagemagick_load_image): Implement transparency.
* doc/lispref/display.texi (ImageMagick Images): ImageMagick now supports the
:background property.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 4 | ||||
| -rw-r--r-- | src/image.c | 113 |
2 files changed, 61 insertions, 56 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 919dcc10098..1aba1913f46 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | 2012-06-11 Chong Yidong <cyd@gnu.org> | ||
| 2 | |||
| 3 | * image.c (imagemagick_load_image): Implement transparency. | ||
| 4 | |||
| 1 | 2012-06-10 Andreas Schwab <schwab@linux-m68k.org> | 5 | 2012-06-10 Andreas Schwab <schwab@linux-m68k.org> |
| 2 | 6 | ||
| 3 | * regex.c (at_begline_loc_p): Also recognize `(?N:' and correctly | 7 | * regex.c (at_begline_loc_p): Also recognize `(?N:' and correctly |
diff --git a/src/image.c b/src/image.c index b6cdb6c8290..15fd7bbeab7 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -7599,19 +7599,14 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7599 | unsigned char *contents, unsigned int size, | 7599 | unsigned char *contents, unsigned int size, |
| 7600 | char *filename) | 7600 | char *filename) |
| 7601 | { | 7601 | { |
| 7602 | size_t width; | 7602 | size_t width, height; |
| 7603 | size_t height; | ||
| 7604 | |||
| 7605 | MagickBooleanType status; | 7603 | MagickBooleanType status; |
| 7606 | |||
| 7607 | XImagePtr ximg; | 7604 | XImagePtr ximg; |
| 7608 | int x; | 7605 | int x, y; |
| 7609 | int y; | 7606 | MagickWand *image_wand; |
| 7610 | 7607 | MagickWand *ping_wand; | |
| 7611 | MagickWand *image_wand; | ||
| 7612 | MagickWand *ping_wand; | ||
| 7613 | PixelIterator *iterator; | 7608 | PixelIterator *iterator; |
| 7614 | PixelWand **pixels; | 7609 | PixelWand **pixels, *bg_wand = NULL; |
| 7615 | MagickPixelPacket pixel; | 7610 | MagickPixelPacket pixel; |
| 7616 | Lisp_Object image; | 7611 | Lisp_Object image; |
| 7617 | Lisp_Object value; | 7612 | Lisp_Object value; |
| @@ -7620,10 +7615,6 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7620 | int desired_width, desired_height; | 7615 | int desired_width, desired_height; |
| 7621 | double rotation; | 7616 | double rotation; |
| 7622 | int pixelwidth; | 7617 | int pixelwidth; |
| 7623 | ImageInfo *image_info; | ||
| 7624 | ExceptionInfo *exception; | ||
| 7625 | Image * im_image; | ||
| 7626 | |||
| 7627 | 7618 | ||
| 7628 | /* Handle image index for image types who can contain more than one image. | 7619 | /* Handle image index for image types who can contain more than one image. |
| 7629 | Interface :index is same as for GIF. First we "ping" the image to see how | 7620 | Interface :index is same as for GIF. First we "ping" the image to see how |
| @@ -7637,14 +7628,9 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7637 | ping_wand = NewMagickWand (); | 7628 | ping_wand = NewMagickWand (); |
| 7638 | /* MagickSetResolution (ping_wand, 2, 2); (Bug#10112) */ | 7629 | /* MagickSetResolution (ping_wand, 2, 2); (Bug#10112) */ |
| 7639 | 7630 | ||
| 7640 | if (filename != NULL) | 7631 | status = filename |
| 7641 | { | 7632 | ? MagickPingImage (ping_wand, filename) |
| 7642 | status = MagickPingImage (ping_wand, filename); | 7633 | : MagickPingImageBlob (ping_wand, contents, size); |
| 7643 | } | ||
| 7644 | else | ||
| 7645 | { | ||
| 7646 | status = MagickPingImageBlob (ping_wand, contents, size); | ||
| 7647 | } | ||
| 7648 | 7634 | ||
| 7649 | if (status == MagickFalse) | 7635 | if (status == MagickFalse) |
| 7650 | { | 7636 | { |
| @@ -7653,7 +7639,7 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7653 | return 0; | 7639 | return 0; |
| 7654 | } | 7640 | } |
| 7655 | 7641 | ||
| 7656 | if (! (0 <= ino && ino < MagickGetNumberImages (ping_wand))) | 7642 | if (ino < 0 || ino >= MagickGetNumberImages (ping_wand)) |
| 7657 | { | 7643 | { |
| 7658 | image_error ("Invalid image number `%s' in image `%s'", | 7644 | image_error ("Invalid image number `%s' in image `%s'", |
| 7659 | image, img->spec); | 7645 | image, img->spec); |
| @@ -7670,39 +7656,46 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7670 | DestroyMagickWand (ping_wand); | 7656 | DestroyMagickWand (ping_wand); |
| 7671 | 7657 | ||
| 7672 | /* Now we know how many images are inside the file. If it's not a | 7658 | /* Now we know how many images are inside the file. If it's not a |
| 7673 | bundle, the number is one. */ | 7659 | bundle, the number is one. Load the image data. */ |
| 7674 | |||
| 7675 | if (filename != NULL) | ||
| 7676 | { | ||
| 7677 | image_info = CloneImageInfo ((ImageInfo *) NULL); | ||
| 7678 | (void) strcpy (image_info->filename, filename); | ||
| 7679 | image_info->number_scenes = 1; | ||
| 7680 | image_info->scene = ino; | ||
| 7681 | exception = AcquireExceptionInfo (); | ||
| 7682 | 7660 | ||
| 7683 | im_image = ReadImage (image_info, exception); | 7661 | image_wand = NewMagickWand (); |
| 7684 | DestroyExceptionInfo (exception); | ||
| 7685 | 7662 | ||
| 7686 | if (im_image == NULL) | 7663 | if ((filename |
| 7687 | goto imagemagick_no_wand; | 7664 | ? MagickReadImage (image_wand, filename) |
| 7688 | image_wand = NewMagickWandFromImage (im_image); | 7665 | : MagickReadImageBlob (image_wand, contents, size)) |
| 7689 | DestroyImage (im_image); | 7666 | == MagickFalse) |
| 7690 | } | ||
| 7691 | else | ||
| 7692 | { | 7667 | { |
| 7693 | image_wand = NewMagickWand (); | 7668 | imagemagick_error (image_wand); |
| 7694 | if (MagickReadImageBlob (image_wand, contents, size) == MagickFalse) | 7669 | goto imagemagick_error; |
| 7695 | { | ||
| 7696 | imagemagick_error (image_wand); | ||
| 7697 | goto imagemagick_error; | ||
| 7698 | } | ||
| 7699 | } | 7670 | } |
| 7700 | 7671 | ||
| 7672 | /* Retrieve the frame's background color, for use later. */ | ||
| 7673 | { | ||
| 7674 | XColor bgcolor; | ||
| 7675 | Lisp_Object specified_bg; | ||
| 7676 | |||
| 7677 | specified_bg = image_spec_value (img->spec, QCbackground, NULL); | ||
| 7678 | if (!STRINGP (specified_bg) | ||
| 7679 | || !x_defined_color (f, SSDATA (specified_bg), &bgcolor, 0)) | ||
| 7680 | { | ||
| 7681 | #ifndef HAVE_NS | ||
| 7682 | bgcolor.pixel = FRAME_BACKGROUND_PIXEL (f); | ||
| 7683 | x_query_color (f, &bgcolor); | ||
| 7684 | #else | ||
| 7685 | ns_query_color (FRAME_BACKGROUND_COLOR (f), &bgcolor, 1); | ||
| 7686 | #endif | ||
| 7687 | } | ||
| 7688 | |||
| 7689 | bg_wand = NewPixelWand (); | ||
| 7690 | PixelSetRed (bg_wand, (double) bgcolor.red / 65535); | ||
| 7691 | PixelSetGreen (bg_wand, (double) bgcolor.green / 65535); | ||
| 7692 | PixelSetBlue (bg_wand, (double) bgcolor.blue / 65535); | ||
| 7693 | } | ||
| 7694 | |||
| 7701 | /* If width and/or height is set in the display spec assume we want | 7695 | /* If width and/or height is set in the display spec assume we want |
| 7702 | to scale to those values. If either h or w is unspecified, the | 7696 | to scale to those values. If either h or w is unspecified, the |
| 7703 | unspecified should be calculated from the specified to preserve | 7697 | unspecified should be calculated from the specified to preserve |
| 7704 | aspect ratio. */ | 7698 | aspect ratio. */ |
| 7705 | |||
| 7706 | value = image_spec_value (img->spec, QCwidth, NULL); | 7699 | value = image_spec_value (img->spec, QCwidth, NULL); |
| 7707 | desired_width = (INTEGERP (value) ? XFASTINT (value) : -1); | 7700 | desired_width = (INTEGERP (value) ? XFASTINT (value) : -1); |
| 7708 | value = image_spec_value (img->spec, QCheight, NULL); | 7701 | value = image_spec_value (img->spec, QCheight, NULL); |
| @@ -7768,13 +7761,8 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7768 | value = image_spec_value (img->spec, QCrotation, NULL); | 7761 | value = image_spec_value (img->spec, QCrotation, NULL); |
| 7769 | if (FLOATP (value)) | 7762 | if (FLOATP (value)) |
| 7770 | { | 7763 | { |
| 7771 | PixelWand* background = NewPixelWand (); | ||
| 7772 | PixelSetColor (background, "#ffffff");/*TODO remove hardcode*/ | ||
| 7773 | |||
| 7774 | rotation = extract_float (value); | 7764 | rotation = extract_float (value); |
| 7775 | 7765 | status = MagickRotateImage (image_wand, bg_wand, rotation); | |
| 7776 | status = MagickRotateImage (image_wand, background, rotation); | ||
| 7777 | DestroyPixelWand (background); | ||
| 7778 | if (status == MagickFalse) | 7766 | if (status == MagickFalse) |
| 7779 | { | 7767 | { |
| 7780 | image_error ("Imagemagick image rotate failed", Qnil, Qnil); | 7768 | image_error ("Imagemagick image rotate failed", Qnil, Qnil); |
| @@ -7788,6 +7776,18 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7788 | height = MagickGetImageHeight (image_wand); | 7776 | height = MagickGetImageHeight (image_wand); |
| 7789 | width = MagickGetImageWidth (image_wand); | 7777 | width = MagickGetImageWidth (image_wand); |
| 7790 | 7778 | ||
| 7779 | /* Set the canvas background color to the frame or specified | ||
| 7780 | background, and flatten the image. Note: as of ImageMagick | ||
| 7781 | 6.6.0, SVG image transparency is not handled properly | ||
| 7782 | (e.g. etc/images/splash.svg shows a white background always). */ | ||
| 7783 | { | ||
| 7784 | MagickWand *new_wand; | ||
| 7785 | MagickSetImageBackgroundColor (image_wand, bg_wand); | ||
| 7786 | new_wand = MagickMergeImageLayers (image_wand, MergeLayer); | ||
| 7787 | DestroyMagickWand (image_wand); | ||
| 7788 | image_wand = new_wand; | ||
| 7789 | } | ||
| 7790 | |||
| 7791 | if (! (width <= INT_MAX && height <= INT_MAX | 7791 | if (! (width <= INT_MAX && height <= INT_MAX |
| 7792 | && check_image_size (f, width, height))) | 7792 | && check_image_size (f, width, height))) |
| 7793 | { | 7793 | { |
| @@ -7895,7 +7895,6 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7895 | width, height, | 7895 | width, height, |
| 7896 | exportdepth, | 7896 | exportdepth, |
| 7897 | pixelwidth, | 7897 | pixelwidth, |
| 7898 | /*&(img->pixmap));*/ | ||
| 7899 | ximg->data); | 7898 | ximg->data); |
| 7900 | #else | 7899 | #else |
| 7901 | image_error ("You don't have MagickExportImagePixels, upgrade ImageMagick!", | 7900 | image_error ("You don't have MagickExportImagePixels, upgrade ImageMagick!", |
| @@ -7910,7 +7909,6 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7910 | free_color_table (); | 7909 | free_color_table (); |
| 7911 | #endif /* COLOR_TABLE_SUPPORT */ | 7910 | #endif /* COLOR_TABLE_SUPPORT */ |
| 7912 | 7911 | ||
| 7913 | |||
| 7914 | img->width = width; | 7912 | img->width = width; |
| 7915 | img->height = height; | 7913 | img->height = height; |
| 7916 | 7914 | ||
| @@ -7919,9 +7917,10 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7919 | x_put_x_image (f, ximg, img->pixmap, width, height); | 7917 | x_put_x_image (f, ximg, img->pixmap, width, height); |
| 7920 | x_destroy_x_image (ximg); | 7918 | x_destroy_x_image (ximg); |
| 7921 | 7919 | ||
| 7922 | |||
| 7923 | /* Final cleanup. image_wand should be the only resource left. */ | 7920 | /* Final cleanup. image_wand should be the only resource left. */ |
| 7924 | DestroyMagickWand (image_wand); | 7921 | DestroyMagickWand (image_wand); |
| 7922 | if (bg_wand) DestroyPixelWand (bg_wand); | ||
| 7923 | |||
| 7925 | /* `MagickWandTerminus' terminates the imagemagick environment. */ | 7924 | /* `MagickWandTerminus' terminates the imagemagick environment. */ |
| 7926 | MagickWandTerminus (); | 7925 | MagickWandTerminus (); |
| 7927 | 7926 | ||
| @@ -7929,6 +7928,8 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7929 | 7928 | ||
| 7930 | imagemagick_error: | 7929 | imagemagick_error: |
| 7931 | DestroyMagickWand (image_wand); | 7930 | DestroyMagickWand (image_wand); |
| 7931 | if (bg_wand) DestroyPixelWand (bg_wand); | ||
| 7932 | |||
| 7932 | imagemagick_no_wand: | 7933 | imagemagick_no_wand: |
| 7933 | MagickWandTerminus (); | 7934 | MagickWandTerminus (); |
| 7934 | /* TODO more cleanup. */ | 7935 | /* TODO more cleanup. */ |