[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] trunk r113924: * image.c: Implement an ImageMagick per-ima
From: |
Lars Ingebrigtsen |
Subject: |
[Emacs-diffs] trunk r113924: * image.c: Implement an ImageMagick per-image cache. |
Date: |
Fri, 16 Aug 2013 14:54:51 +0000 |
User-agent: |
Bazaar (2.6b2) |
------------------------------------------------------------
revno: 113924
revision-id: address@hidden
parent: address@hidden
committer: Lars Magne Ingebrigtsen <address@hidden>
branch nick: trunk
timestamp: Fri 2013-08-16 16:54:46 +0200
message:
* image.c: Implement an ImageMagick per-image cache.
modified:
src/ChangeLog changelog-20091113204419-o5vbwnq5f7feedwu-1438
src/image.c image.c-20091113204419-o5vbwnq5f7feedwu-2969
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog 2013-08-16 02:09:08 +0000
+++ b/src/ChangeLog 2013-08-16 14:54:46 +0000
@@ -1,3 +1,7 @@
+2013-08-16 Lars Magne Ingebrigtsen <address@hidden>
+
+ * image.c: Implement an ImageMagick per-image cache.
+
2013-08-16 Xue Fuqiao <address@hidden>
* editfns.c (insert_before_markers): Mention overlay in the doc string.
=== modified file 'src/image.c'
--- a/src/image.c 2013-08-16 05:15:51 +0000
+++ b/src/image.c 2013-08-16 14:54:46 +0000
@@ -7869,10 +7869,91 @@
follow. If following images have non-transparent colors, these are
composed "on top" of the master image. So, in general, one has to
compute ann the preceding images to be able to display a particular
- sub-image. */
-
-static MagickWand *animation_cache = NULL;
-static int animation_index = 0;
+ sub-image.
+
+ Computing all the preceding images is too slow, so we maintain a
+ cache of previously computed images. We have to maintain a cache
+ separate from the image cache, because the images may be scaled
+ before display. */
+
+struct animation_cache
+{
+ char *signature;
+ MagickWand *wand;
+ int index;
+ EMACS_TIME update_time;
+ struct animation_cache *next;
+};
+
+static struct animation_cache *animation_cache = NULL;
+
+struct animation_cache *
+imagemagick_create_cache (char *signature)
+{
+ struct animation_cache *cache = xzalloc (sizeof (struct animation_cache));
+ cache->signature = signature;
+ cache->update_time = current_emacs_time ();
+ return cache;
+}
+
+/* Discard cached images that haven't been used for a minute. */
+void
+imagemagick_prune_animation_cache ()
+{
+ struct animation_cache *cache = animation_cache;
+ struct animation_cache *prev;
+ EMACS_TIME old = sub_emacs_time (current_emacs_time (),
+ EMACS_TIME_FROM_DOUBLE (60));
+
+ while (cache)
+ {
+ if (EMACS_TIME_LT (cache->update_time, old))
+ {
+ struct animation_cache *this_cache = cache;
+ free (cache->signature);
+ if (cache->wand)
+ DestroyMagickWand (cache->wand);
+ if (prev)
+ prev->next = cache->next;
+ else
+ animation_cache = cache->next;
+ cache = cache->next;
+ free (this_cache);
+ }
+ else {
+ prev = cache;
+ cache = cache->next;
+ }
+ }
+}
+
+struct animation_cache *
+imagemagick_get_animation_cache (MagickWand *wand)
+{
+ char *signature = MagickGetImageSignature (wand);
+ struct animation_cache *cache = animation_cache;
+
+ imagemagick_prune_animation_cache ();
+
+ if (! cache)
+ {
+ animation_cache = imagemagick_create_cache (signature);
+ return animation_cache;
+ }
+
+ while (strcmp(signature, cache->signature) &&
+ cache->next)
+ cache = cache->next;
+
+ if (strcmp(signature, cache->signature))
+ {
+ cache->next = imagemagick_create_cache (signature);
+ return cache->next;
+ }
+
+ cache->update_time = current_emacs_time ();
+ return cache;
+}
static MagickWand *
imagemagick_compute_animated_image (MagickWand *super_wand, int ino)
@@ -7880,18 +7961,23 @@
int i;
MagickWand *composite_wand;
size_t dest_width, dest_height;
+ struct animation_cache *cache = imagemagick_get_animation_cache (super_wand);
MagickSetIteratorIndex (super_wand, 0);
- if (ino == 0 || animation_cache == NULL)
- composite_wand = MagickGetImage (super_wand);
+ if (ino == 0 || cache->wand == NULL || cache->index > ino)
+ {
+ composite_wand = MagickGetImage (super_wand);
+ if (cache->wand)
+ DestroyMagickWand (cache->wand);
+ }
else
- composite_wand = animation_cache;
+ composite_wand = cache->wand;
dest_width = MagickGetImageWidth (composite_wand);
dest_height = MagickGetImageHeight (composite_wand);
- for (i = max (1, animation_index + 1); i <= ino; i++)
+ for (i = max (1, cache->index + 1); i <= ino; i++)
{
MagickWand *sub_wand;
PixelIterator *source_iterator, *dest_iterator;
@@ -7916,7 +8002,7 @@
{
DestroyMagickWand (composite_wand);
DestroyMagickWand (sub_wand);
- animation_cache = NULL;
+ cache->wand = NULL;
image_error ("Imagemagick pixel iterator creation failed",
Qnil, Qnil);
return NULL;
@@ -7928,7 +8014,7 @@
DestroyMagickWand (composite_wand);
DestroyMagickWand (sub_wand);
DestroyPixelIterator (source_iterator);
- animation_cache = NULL;
+ cache->wand = NULL;
image_error ("Imagemagick pixel iterator creation failed",
Qnil, Qnil);
return NULL;
@@ -7979,8 +8065,8 @@
/* Cache a copy for the next iteration. The current wand will be
destroyed by the caller. */
- animation_cache = CloneMagickWand (composite_wand);
- animation_index = ino;
+ cache->wand = CloneMagickWand (composite_wand);
+ cache->index = ino;
return composite_wand;
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] trunk r113924: * image.c: Implement an ImageMagick per-image cache.,
Lars Ingebrigtsen <=