Repository: kivy/kivy

Issue:
loading an image with both kivy.uix.image and kivy.core.image -> bugs
apparently, if you load an image with kivy.uix.image.Image, and then load the same image with kivy.core.image.Image, you can't then do yourimage.read_pixel() on the one you loaded with kivy.core.image.Image



Discussion:
for completness:
assuming you have a 'circle.png' image

```
from kivy.uix.image import Image
from kivy.core.image import Image as CoreImage
from kivy.app import App

class TestApp(App):
    #--- look into reordering widget tree
    def build(self):
        circle = Image(source='circle.png', pos=(0,0))
        im = CoreImage('circle.png',keep_data=True)
        print "PXL_READ: ", im.read_pixel(15,15)

TestApp().run()
```

you get 

```
File "/home/gaby/kivy/kivy/core/image/__init__.py", line 613, in read_pixel
   raise EOFError('Image data is missing, make sure that image is'
EOFError: Image data is missing, make sure that image isloaded with keep_data=True keyword.
```

But if you don't load that same image, with Image before, the read_pixel works fine.


Resolving patch:
diff --git a/kivy/core/image/__init__.py b/kivy/core/image/__init__.py
--- a/kivy/core/image/__init__.py
+++ b/kivy/core/image/__init__.py
@@ -400,6 +400,29 @@ def __init__(self, arg, **kwargs):
         # check if the image hase sequences for animation in it
         self._img_iterate()
 
+    def remove_from_cache(self):
+        '''Remove the Image from cache. This facilitates re-loading of
+        image from disk in case of contents having been changed.
+
+        .. versionadded:: 1.3.0
+
+        Usage::
+
+            im = CoreImage('1.jpg')
+            # -- do something --
+            im.remove_from_cache()
+            im = CoreImage('1.jpg')
+            # this time image will be re-loaded from disk
+
+        '''
+        count = 0
+        uid = '%s|%s|%s' % (self.filename, self._mipmap, count)
+        Cache.remove("kv.image", uid)
+        while Cache.get("kv.texture", uid):
+            Cache.remove("kv.texture", uid)
+            count += 1
+            uid = '%s|%s|%s' % (self.filename, self._mipmap, count)
+
     def _anim(self, *largs):
         if not self._image:
             return
@@ -536,8 +559,13 @@ def _set_filename(self, value):
         if image:
             # we found an image, yeah ! but reset the texture now.
             self.image = image
-            self._texture = None
-            self._img_iterate()
+            if not image.keep_data and self._keep_data:
+                self.remove_from_cache()
+                self._filename = ''
+                self._set_filename(value)
+            else:
+                self._texture = None
+                self._img_iterate()
             return
         else:
             # if we already got a texture, it will be automatically reloaded.
diff --git a/kivy/uix/image.py b/kivy/uix/image.py
--- a/kivy/uix/image.py
+++ b/kivy/uix/image.py
@@ -224,6 +224,25 @@ def _on_tex_change(self, *largs):
         # update texture from core image
         self.texture = self._coreimage.texture
 
+    def reload(self):
+        '''Reload image from disk. This facilitates re-loading of
+        image from disk in case of contents having been changed.
+
+        .. versionadded:: 1.3.0
+
+        Usage::
+
+            im = Image(source = '1.jpg')
+            # -- do something --
+            im.reload()
+            # image will be re-loaded from disk
+
+        '''
+        self._coreimage.remove_from_cache()
+        olsource = self.source
+        self.source = ''
+        self.source = olsource
+
 
 class AsyncImage(Image):
     '''Asynchronous Image class, see module documentation for more information.


Test patch:
diff --git a/kivy/tests/test_image.py b/kivy/tests/test_image.py
new file mode 100644
--- /dev/null
+++ b/kivy/tests/test_image.py
@@ -0,0 +1,16 @@
+import unittest
+
+
+class ImageTestCase(unittest.TestCase):
+
+    def setUp(self):
+        from kivy.core.image import Image
+        self.cls = Image
+        self.root = Image('test_button.png')
+
+    def test_keep_data(self):
+        root = self.root
+        self.assertEqual(root._image._data[0].data, None)
+        i1 = self.cls('test_button.png', keep_data = True)
+        if not i1._image._data[0].data:
+            self.fail('Image has no data even with keep_data = True')