diff options
| author | Lars Magne Ingebrigtsen | 2013-08-15 17:10:12 +0200 |
|---|---|---|
| committer | Lars Magne Ingebrigtsen | 2013-08-15 17:10:12 +0200 |
| commit | 6e856b69ffea045be4efe029ecbb44df7fd4da21 (patch) | |
| tree | 879a1aa007a10e5fc4135ffb96dc3e2428c19839 /src | |
| parent | d5a1acfaa5671f09cbb8da211a5283394d8b907f (diff) | |
| download | emacs-6e856b69ffea045be4efe029ecbb44df7fd4da21.tar.gz emacs-6e856b69ffea045be4efe029ecbb44df7fd4da21.zip | |
* image.c (imagemagick_compute_animated_image): Implement animated images.
Fixes: debbugs:14700
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 5 | ||||
| -rw-r--r-- | src/image.c | 79 |
2 files changed, 80 insertions, 4 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 1ad3e1cff24..5131f666c6e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2013-08-15 Lars Magne Ingebrigtsen <larsi@gnus.org> | ||
| 2 | |||
| 3 | * image.c (imagemagick_compute_animated_image): Implement animated | ||
| 4 | images (bug#14700). | ||
| 5 | |||
| 1 | 2013-08-15 Dmitry Antipov <dmantipov@yandex.ru> | 6 | 2013-08-15 Dmitry Antipov <dmantipov@yandex.ru> |
| 2 | 7 | ||
| 3 | * lisp.h (FOR_EACH_ALIST_VALUE): New macro | 8 | * lisp.h (FOR_EACH_ALIST_VALUE): New macro |
diff --git a/src/image.c b/src/image.c index 8d969a6f9c6..c534f181e5c 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -7864,6 +7864,75 @@ imagemagick_filename_hint (Lisp_Object spec, char hint_buffer[MaxTextExtent]) | |||
| 7864 | return hint_buffer; | 7864 | return hint_buffer; |
| 7865 | } | 7865 | } |
| 7866 | 7866 | ||
| 7867 | /* Animated images (e.g., GIF89a) are composed from one "master image" | ||
| 7868 | (which is the first one, and then there's a number of images that | ||
| 7869 | follow. If following images have non-transparent colors, these are | ||
| 7870 | composed "on top" of the master image. So, in general, one has to | ||
| 7871 | compute ann the preceding images to be able to display a particular | ||
| 7872 | sub-image. */ | ||
| 7873 | |||
| 7874 | static MagickWand * | ||
| 7875 | imagemagick_compute_animated_image (MagickWand *super_wand, int ino) | ||
| 7876 | { | ||
| 7877 | MagickWand *composite_wand; | ||
| 7878 | |||
| 7879 | MagickSetIteratorIndex (super_wand, 0); | ||
| 7880 | composite_wand = MagickGetImage (super_wand); | ||
| 7881 | |||
| 7882 | for (int i = 1; i <= ino; i++) { | ||
| 7883 | MagickWand *sub_wand; | ||
| 7884 | PixelIterator *source_iterator, *dest_iterator; | ||
| 7885 | PixelWand **source, **dest; | ||
| 7886 | long source_width, dest_width; | ||
| 7887 | MagickPixelPacket pixel; | ||
| 7888 | |||
| 7889 | MagickSetIteratorIndex (super_wand, i); | ||
| 7890 | sub_wand = MagickGetImage (super_wand); | ||
| 7891 | |||
| 7892 | source_iterator = NewPixelIterator (sub_wand); | ||
| 7893 | if (! source_iterator) | ||
| 7894 | { | ||
| 7895 | DestroyMagickWand (composite_wand); | ||
| 7896 | DestroyMagickWand (sub_wand); | ||
| 7897 | image_error ("Imagemagick pixel iterator creation failed", | ||
| 7898 | Qnil, Qnil); | ||
| 7899 | return NULL; | ||
| 7900 | } | ||
| 7901 | |||
| 7902 | dest_iterator = NewPixelIterator (composite_wand); | ||
| 7903 | if (! dest_iterator) | ||
| 7904 | { | ||
| 7905 | DestroyMagickWand (composite_wand); | ||
| 7906 | DestroyMagickWand (sub_wand); | ||
| 7907 | DestroyPixelIterator (source_iterator); | ||
| 7908 | image_error ("Imagemagick pixel iterator creation failed", | ||
| 7909 | Qnil, Qnil); | ||
| 7910 | return NULL; | ||
| 7911 | } | ||
| 7912 | |||
| 7913 | while (source = PixelGetNextIteratorRow (source_iterator, &source_width)) { | ||
| 7914 | dest = PixelGetNextIteratorRow (dest_iterator, &dest_width); | ||
| 7915 | for (int x = 0; x < source_width; x++) | ||
| 7916 | { | ||
| 7917 | /* Copy over non-transparent pixels. */ | ||
| 7918 | if (PixelGetAlpha (source[x])) | ||
| 7919 | { | ||
| 7920 | PixelGetMagickColor (source[x], &pixel); | ||
| 7921 | PixelSetMagickColor (dest[x], &pixel); | ||
| 7922 | } | ||
| 7923 | } | ||
| 7924 | PixelSyncIterator(dest_iterator); | ||
| 7925 | } | ||
| 7926 | |||
| 7927 | DestroyPixelIterator (source_iterator); | ||
| 7928 | DestroyPixelIterator (dest_iterator); | ||
| 7929 | DestroyMagickWand (sub_wand); | ||
| 7930 | } | ||
| 7931 | |||
| 7932 | return composite_wand; | ||
| 7933 | } | ||
| 7934 | |||
| 7935 | |||
| 7867 | /* Helper function for imagemagick_load, which does the actual loading | 7936 | /* Helper function for imagemagick_load, which does the actual loading |
| 7868 | given contents and size, apart from frame and image structures, | 7937 | given contents and size, apart from frame and image structures, |
| 7869 | passed from imagemagick_load. Uses librimagemagick to do most of | 7938 | passed from imagemagick_load. Uses librimagemagick to do most of |
| @@ -7965,12 +8034,14 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7965 | 8034 | ||
| 7966 | /* If we have an animated image, get the new wand based on the | 8035 | /* If we have an animated image, get the new wand based on the |
| 7967 | "super-wand". */ | 8036 | "super-wand". */ |
| 7968 | if (ino > 0) | 8037 | if (MagickGetNumberImages (image_wand) > 1) |
| 7969 | { | 8038 | { |
| 7970 | MagickWand *super_wand = image_wand; | 8039 | MagickWand *super_wand = image_wand; |
| 7971 | MagickSetIteratorIndex (super_wand, ino); | 8040 | image_wand = imagemagick_compute_animated_image (super_wand, ino); |
| 7972 | image_wand = MagickGetImage (super_wand); | 8041 | if (! image_wand) |
| 7973 | DestroyMagickWand (super_wand); | 8042 | image_wand = super_wand; |
| 8043 | else | ||
| 8044 | DestroyMagickWand (super_wand); | ||
| 7974 | } | 8045 | } |
| 7975 | 8046 | ||
| 7976 | /* Retrieve the frame's background color, for use later. */ | 8047 | /* Retrieve the frame's background color, for use later. */ |