# Updating Image component based off of newest image in a directory

**URL:** <https://forum.inductiveautomation.com/t/updating-image-component-based-off-of-newest-image-in-a-directory/14972>\
**Category:** Ignition\
**Tags:** scripting, ignition79\
**Created:** [August 2, 2017, 9:24pm UTC](https://forum.inductiveautomation.com/t/updating-image-component-based-off-of-newest-image-in-a-directory/14972 "2017-08-02T21:24:04Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![lautry](https://avatars.discourse-cdn.com/v4/letter/l/a8b319/32.png) [@lautry](https://forum.inductiveautomation.com/u/lautry)\
**Post date:** [August 2, 2017, 9:24pm UTC](https://forum.inductiveautomation.com/t/updating-image-component-based-off-of-newest-image-in-a-directory/14972/1 "2017-08-02T21:24:04Z")

</div>

Hello all,

I’m working with a Cognex camera currently, it isn’t an In-Sight series, so it doesn’t have the simple FTP push to server functionality. It uses VisionPro and Cognex Designer which do not allow this as easy.

So, a work around I am trying to perform is to have a directory of images on the same system that Ignition is hosted on be the source location for an Image component. I would want it to be updated via the one that is most recently put into the source pathway.

I found a post by Travis that appears to be on the correct track. ([How can I create a picture slider?](http://forum.inductiveautomation.com/t/how-can-i-create-a-picture-slider/3276))

I would essentially just want it to read in the newest file every time a tag value is changed. However, I am not quite sure how to go about scripting this to show the newest file, as the name is different per file.

---

<div class="post-metadata">

**Author:** ![lautry](https://avatars.discourse-cdn.com/v4/letter/l/a8b319/32.png) [@lautry](https://forum.inductiveautomation.com/u/lautry)\
**Post date:** [August 7, 2017, 1:12pm UTC](https://forum.inductiveautomation.com/t/updating-image-component-based-off-of-newest-image-in-a-directory/14972/2 "2017-08-07T13:12:33Z")

</div>

No one has any idea how I would go about doing this? I would compare this idea to the filmstrip idea that a lot of vision HMI’s use.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [August 7, 2017, 3:34pm UTC](https://forum.inductiveautomation.com/t/updating-image-component-based-off-of-newest-image-in-a-directory/14972/3 "2017-08-07T15:34:50Z")

</div>

Are these images saved with sequential filenames (`0001.jpg`, `0002.jpg`) or are they timestamps (`2017-08-07 08:30:10.jpg`)?

In either case - you’ll probably want to look at the [os.path](http://www.jython.org/docs/library/os.path.html) module (built in to the Jython standard library), specifically `os.path.walk()`, which returns a sequence of paths and filenames inside of a directory. You would then need to sort that return path to get the most recent timestamp, or highest index, or whatever.  
Or, a more generic solution, you could use `os.path.getmtime(path)` to get the last modified time of each file in the directory.

---

<div class="post-metadata">

**Author:** ![lautry](https://avatars.discourse-cdn.com/v4/letter/l/a8b319/32.png) [@lautry](https://forum.inductiveautomation.com/u/lautry)\
**Post date:** [August 7, 2017, 7:25pm UTC](https://forum.inductiveautomation.com/t/updating-image-component-based-off-of-newest-image-in-a-directory/14972/5 "2017-08-07T19:25:31Z")

</div>

So I’ve essentially figured it all out except for one thing… How can I make the Image component read the file from the local drive, rather than uploading through File Browser for each image?

The solution so far:

1.) I linked the Image Path to a string tag.  
2.) The tag for the image path is written to when a trigger is called.  
3.) When the trigger’s bool value is changed, a Tag Event (Value Changed) is performed:

```auto
import os
import os.path
import glob

newest = max(glob.iglob('C:\\Users\\me\\Documents\\blah\\blah\\blah\\imagename\\*.[Pp][Nn][Gg]'), key=os.path.getctime)
value = newest
system.tag.write('Vision/imagePath', value)

value = system.gui.getParentWindow(event).getComponentForPath('_parent').title"

```

Now when I toggle the trigger, it writes to the Image Path field for the Image component… however, I have a feeling there is one more step to get it to auto upload, or bypass… I saw some reference to a paintable canvas?

---

<div class="post-metadata">

**Author:** ![lautry](https://avatars.discourse-cdn.com/v4/letter/l/a8b319/32.png) [@lautry](https://forum.inductiveautomation.com/u/lautry)\
**Post date:** [August 7, 2017, 8:31pm UTC](https://forum.inductiveautomation.com/t/updating-image-component-based-off-of-newest-image-in-a-directory/14972/6 "2017-08-07T20:31:29Z")

</div>

Well, I’ve got it to work for the Paintable Canvas!

All that’s left is to figure out how to make the image scale down to fit in the window… This is done using Java2D, so hopefully it will be easy to “zoom out” so to speak as the images are 3840x2748px in size and they’re going to a screen with a resolution of 800x600!

The code I used in the Paintable Canvas is:

```auto
from java.net import URL
from javax.imageio import ImageIO

url = system.tag.read("Vision/imagePath").value
# Use this for a local file
url2 = URL(url)
#url2 = globals()['url']
icon = ImageIO.read(url2)
event.graphics.drawImage(icon, 0, 0, event.source)

```

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [August 7, 2017, 9:36pm UTC](https://forum.inductiveautomation.com/t/updating-image-component-based-off-of-newest-image-in-a-directory/14972/7 "2017-08-07T21:36:43Z")

</div>

Here’s some code to display an image, scaled, on the paintable canvas. Also caches the read image to avoid a little bit of extra load:

```auto
g = event.graphics
filename = r"path/to/file.png"

cachedName = event.source.getClientProperty("img-bytes-cached-name")
bytes = event.source.getClientProperty("img-bytes-cached")
if filename!=cachedName or not bytes:
	# Image not cached - load from database
	#bytes = system.db.runScalarQuery("SELECT data FROM image_test WHERE imgname='%s'"%name)
	bytes = system.file.readFileAsBytes(filename)
	event.source.putClientProperty("img-bytes-cached",bytes)
	event.source.putClientProperty("img-bytes-cached-name",filename)

if bytes:
	from javax.imageio import ImageIO
	from java.io import ByteArrayInputStream
#	from java.awt.geom import AffineTransform
#	scale = AffineTransform()
	image = ImageIO.read(ByteArrayInputStream(bytes))
	
	g.drawImage(image, 0, 0, event.width, event.height, event.source)

```

---

<div class="post-metadata">

**Author:** ![lautry](https://avatars.discourse-cdn.com/v4/letter/l/a8b319/32.png) [@lautry](https://forum.inductiveautomation.com/u/lautry)\
**Post date:** [August 8, 2017, 3:50am UTC](https://forum.inductiveautomation.com/t/updating-image-component-based-off-of-newest-image-in-a-directory/14972/8 "2017-08-08T03:50:39Z")

</div>

Wow! Thank you.

So, it seems that when trying to interface what you gave me and what I wrote, it doesn’t quite come out right, probably due to image = ImageIO.read(ByteArrayInputStream(bytes)) ?

It was giving me OutOfMem errors when using your method… I just realize that the arguments I needed were only event.width, event.height… simple oversight from me and I can’t believe I didn’t see that…

If I don’t use all the code you gave me, and just load the file the way I wrote the code, should I ever worry about OutOfMem errors?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [August 8, 2017, 3:53pm UTC](https://forum.inductiveautomation.com/t/updating-image-component-based-off-of-newest-image-in-a-directory/14972/9 "2017-08-08T15:53:33Z")

</div>

Yeah, there’s no reason to avoid using your code - ultimately it’s ending up at the same step. Out Of Memory is probably just due to the very large images - you could also bump up the client memory if it’s at the fairly low initial setting (256mB).

---

<div class="post-metadata">

**Author:** ![lautry](https://avatars.discourse-cdn.com/v4/letter/l/a8b319/32.png) [@lautry](https://forum.inductiveautomation.com/u/lautry)\
**Post date:** [August 8, 2017, 4:10pm UTC](https://forum.inductiveautomation.com/t/updating-image-component-based-off-of-newest-image-in-a-directory/14972/10 "2017-08-08T16:10:11Z")

</div>

The computer this will be running on will be fairly under-utilized memory wise, so this is great. I will set the max to at least 1 or 2 GB’s.

Just wondering how Ignition clears memory to make room for the next loaded image? It seems as if every time I added a new image to the directory it loads the file from and then triggered it to find the next one, that it only increased the memory and it never went down at all.

I’ll do some more testing to try and reduce it, but I did have the allocated memory set to default, which is low for what I’m trying to do.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [August 8, 2017, 4:35pm UTC](https://forum.inductiveautomation.com/t/updating-image-component-based-off-of-newest-image-in-a-directory/14972/11 "2017-08-08T16:35:04Z")

</div>

Ignition’s memory cleanup is all driven by Java/the Java virtual machine’s garbage collection. This happens automatically in the background, and is difficult to predict - generally speaking, an unused object will be marked for removal then purged in the next GC cycle, whenever that occurs.
