I am working on an application that requires the reading of images from client files and displaying images in the interface. Later these images can be inserted into a MySQL database. I have working scripts for all required functions - reading bytes from file, visualizing in either a label or image component (I tried both methods to see if there would be any differnce in the memory issue), and then inserting into a database. In this case, I would like to focus solely on the image component and its code.
The problem that I am experiencing is when I load the bytes into the image or label component the memory gets incrementally higher until I reach the 1024MB limit. Smaller images such as 720 X 1280 will cause used memory increase up to 4MB increases while 3000X4000 images will cause used memory increases up to 40MB. These values never decrease; so ultimately, I will get this error. The following graph demonstrates how the memory is consumed every time I select a new file.
I use the file explorer component to select a file, then I read the data and write to a temp file which is than written to the path property of the image component. Here is the interface:
The error that is thrown is:
Traceback (most recent call last):
File "<event:propertyChange>", line 18, in <module>
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2216)
at com.google.common.cache.LocalCache.get(LocalCache.java:4147)
at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:4151)
at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:5140)
at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:5146)
at com.inductiveautomation.ignition.client.images.ImageLoader.getImageData(ImageLoader.java:239)
at com.inductiveautomation.ignition.client.images.ImageLoader.loadImageMemCache(ImageLoader.java:213)
at com.inductiveautomation.ignition.client.images.ImageLoader.loadImage(ImageLoader.java:160)
at jdk.internal.reflect.GeneratedMethodAccessor117.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
com.google.common.util.concurrent.ExecutionError: com.google.common.util.concurrent.ExecutionError: java.lang.OutOfMemoryError: Java heap space
at org.python.core.Py.JavaError(Py.java:552)
at org.python.core.Py.JavaError(Py.java:543)
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:190)
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:206)
at org.python.core.PyObject.__call__(PyObject.java:497)
at org.python.core.PyObject.__call__(PyObject.java:501)
at org.python.core.PyMethod.__call__(PyMethod.java:141)
at org.python.pycode._pyx42.f$0(<event:propertyChange>:42)
at org.python.pycode._pyx42.call_function(<event:propertyChange>)
at org.python.core.PyTableCode.call(PyTableCode.java:171)
at org.python.core.PyCode.call(PyCode.java:18)
at org.python.core.Py.runCode(Py.java:1614)
at com.inductiveautomation.ignition.common.script.ScriptManager.runCode(ScriptManager.java:770)
at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter.runActions(ActionAdapter.java:200)
at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter$ActionRunner.run(ActionAdapter.java:306)
at java.desktop/java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)
Caused by: com.google.common.util.concurrent.ExecutionError: java.lang.OutOfMemoryError: Java heap space
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2216)
at com.google.common.cache.LocalCache.get(LocalCache.java:4147)
at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:4151)
at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:5140)
at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:5146)
at com.inductiveautomation.ignition.client.images.ImageLoader.getImageData(ImageLoader.java:239)
at com.inductiveautomation.ignition.client.images.ImageLoader.loadImageMemCache(ImageLoader.java:213)
at com.inductiveautomation.ignition.client.images.ImageLoader.loadImage(ImageLoader.java:160)
at jdk.internal.reflect.GeneratedMethodAccessor117.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:188)
... 25 more
Caused by: java.lang.OutOfMemoryError: Java heap space
at java.desktop/java.awt.image.DataBufferByte.<init>(Unknown Source)
at java.desktop/java.awt.image.ComponentSampleModel.createDataBuffer(Unknown Source)
at java.desktop/java.awt.image.Raster.createWritableRaster(Unknown Source)
at java.desktop/javax.imageio.ImageTypeSpecifier.createBufferedImage(Unknown Source)
at java.desktop/javax.imageio.ImageReader.getDestination(Unknown Source)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(Unknown Source)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.read(Unknown Source)
at com.inductiveautomation.ignition.client.images.ImageLoader$ImageInfo.loadImage(ImageLoader.java:427)
at com.inductiveautomation.ignition.client.images.ImageLoader$ImageInfo.<init>(ImageLoader.java:377)
at com.inductiveautomation.ignition.client.images.ImageLoader$1.load(ImageLoader.java:72)
at com.inductiveautomation.ignition.client.images.ImageLoader$1.load(ImageLoader.java:68)
at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3708)
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2416)
at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2299)
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2212)
at com.google.common.cache.LocalCache.get(LocalCache.java:4147)
at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:4151)
at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:5140)
at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:5146)
at com.inductiveautomation.ignition.client.images.ImageLoader.getImageData(ImageLoader.java:239)
at com.inductiveautomation.ignition.client.images.ImageLoader.loadImageMemCache(ImageLoader.java:213)
at com.inductiveautomation.ignition.client.images.ImageLoader.loadImage(ImageLoader.java:170)
at com.inductiveautomation.ignition.client.images.PathIcon$LoadImageTask.doInBackground(PathIcon.java:317)
at com.inductiveautomation.ignition.client.images.PathIcon$LoadImageTask.doInBackground(PathIcon.java:298)
at java.desktop/javax.swing.SwingWorker$1.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at java.desktop/javax.swing.SwingWorker.run(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
Ignition v8.0.9 (b2020021812)
Java: Azul Systems, Inc. 11.0.5
I have included all of the event code below, but this is the line that will ultimately cause the error:
img = ImageLoader.getInstance().loadImage(filename). Please note that I have isolated the memory usage increase to this part of the code.
if event.propertyName == 'path':
from com.inductiveautomation.ignition.client.images import ImageLoader
imgComponent = event.source
imgComponent.rotation = 0
imgComponent.imgRotationValue = 0
# Get image component size from Custom Properties
initImgCompWidth = imgComponent.initImgCompWidth
initImgCompHeight = imgComponent.initImgCompHeight
#resize image component to initial values in custom properties
system.gui.transform(component=imgComponent, newWidth=initImgCompWidth, newHeight=initImgCompHeight)
#Find Aspect Ratio of Original Image
filename = imgComponent.getPath()
img = ImageLoader.getInstance().loadImage(filename) #this line causes the JVM heap error in the client or designer
imgW = img.getWidth()
imgH = img.getHeight()
imgRatio = float(imgW) / float(imgH)
if imgRatio > 1: # means that picture has more pixels in the x (width) than y (height)
modImgCompWidth = initImgCompWidth
modImgCompHeight = int(initImgCompHeight / imgRatio)
else:
modImgCompWidth = int(initImgCompWidth * imgRatio)
modImgCompHeight = initImgCompHeight
event.source.modImgCompWidth = modImgCompWidth
event.source.modImgCompHeight = modImgCompHeight
#resize the image component to maintain image perspective
system.gui.transform(component=imgComponent, newWidth=modImgCompWidth, newHeight=modImgCompHeight)
# Set Strech Mode to "Parameters"
imgComponent.setStretchMode(2)
#Set Component Image Bounds
imgComponent.setStretchHeight(modImgCompHeight)
imgComponent.setStretchWidth(modImgCompWidth)
Additional information showing the designer “About” page, designer performance, gateway performace (not an issue), and project properties:
Finally, my development machine has 64bit architecture with more than 32GB of RAM.
What, if any solutions are available for this issue?
Thank you in advance.