Does anyone have an example of using the Image Management Tool to upload images from a client? Currently using version 7.9. I found the post below, but have not been even close to successful in getting it to work.
Thanks!
Does anyone have an example of using the Image Management Tool to upload images from a client? Currently using version 7.9. I found the post below, but have not been even close to successful in getting it to work.
Thanks!
from java.awt import Toolkit
from java.io import File
from org.apache.commons.io import FilenameUtils
from com.inductiveautomation.ignition.designer.gateway import DTGatewayInterface
gi = DTGatewayInterface.instance
filepath = system.file.openFile()
if filepath is not None:
name = File(filepath).name
javaImage = Toolkit.defaultToolkit.getImage(filepath)
gi.uploadImage(event.source, name, "Script uploaded image", FilenameUtils.getExtension(filepath), "", javaImage.width, javaImage.height, system.file.readFileAsBytes(filepath))
Something like this might do it.
very close, after a couple minor mods, I am getting TypeError: uploadImage(): expected 9 args; got 8
from java.awt import Toolkit
from java.io import File
from org.apache.commons.io import FilenameUtils
from com.inductiveautomation.ignition.designer.gateway import DTGatewayInterface
# gi = DTGatewayInterface.instance
gi = DTGatewayInterface
filepath = system.file.openFile()
if filepath is not None:
name = File(filepath).name
# javaImage = Toolkit.defaultToolkit.getImage(filepath)
javaImage = Toolkit.getDefaultToolkit().getImage(filepath)
gi.uploadImage(event.source, name, "Script uploaded image", FilenameUtils.getExtension(filepath), "", javaImage.width, javaImage.height, system.file.readFileAsBytes(filepath))
Any stack trace on the TypeError? The call you’re using lines up with the signature I’m expecting. What Ignition version?
Version 7.9.13
Traceback (most recent call last):
File "<event:actionPerformed>", line 18, in <module>
TypeError: uploadImage(): expected 9 args; got 8
at org.python.core.Py.TypeError(Py.java:235)
at org.python.core.PyReflectedFunction.throwError(PyReflectedFunction.java:209)
at org.python.core.PyReflectedFunction.throwArgCountError(PyReflectedFunction.java:262)
at org.python.core.PyReflectedFunction.throwError(PyReflectedFunction.java:319)
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:167)
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:204)
at org.python.core.PyObject.__call__(PyObject.java:357)
at org.python.core.PyObject.__call__(PyObject.java:361)
at org.python.pycode._pyx4.f$0(<event:actionPerformed>:18)
at org.python.pycode._pyx4.call_function(<event:actionPerformed>)
at org.python.core.PyTableCode.call(PyTableCode.java:165)
at org.python.core.PyCode.call(PyCode.java:18)
at org.python.core.Py.runCode(Py.java:1275)
at com.inductiveautomation.ignition.common.script.ScriptManager.runCode(ScriptManager.java:636)
at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter.runActions(ActionAdapter.java:180)
at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter.invoke(ActionAdapter.java:271)
at com.inductiveautomation.factorypmi.application.binding.action.RelayInvocationHandler.invoke(RelayInvocationHandler.java:57)
at com.sun.proxy.$Proxy35.actionPerformed(Unknown Source)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at java.desktop/javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.desktop/java.awt.Component.processMouseEvent(Unknown Source)
at java.desktop/javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.desktop/java.awt.Component.processEvent(Unknown Source)
at java.desktop/java.awt.Container.processEvent(Unknown Source)
at java.desktop/java.awt.Component.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Window.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.desktop/java.awt.EventQueue.access$500(Unknown Source)
at java.desktop/java.awt.EventQueue$3.run(Unknown Source)
at java.desktop/java.awt.EventQueue$3.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(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)
Ignition v7.9.13 (b2019120915)
Java: Azul Systems, Inc. 9.0.7.4
# gi = DTGatewayInterface.instance
gi = DTGatewayInterface
That changes the semantics. uploadImage()
is an instance method on the DTGatewayInterface class - but you’re calling it as DTGatewayInterface.uploadImage()
- which is technically allowed in Python, but only if you provide an instance of self
, which you don’t have in this case.
Change that line to:
gi = DTGatewayInterface.getInstance()
.
That fixed it…
I am working on a windows computer, tried to upload a file with extension “jpg” and it failed. Hardcoded “JPEG” instead of FilenameUtils.getExtension(filepath) and it worked.
Thanks.
Ah, yeah, there’s constants on the gateway that are matched against. In 7.9 the only valid formats are:
PNG
JPEG
GIF
BMP
You’ll have trouble with the code I posted with .bmp, I think - the width/height code won’t work, I’m pretty sure.
You got me over a big hump…
With your assistance, I got it working great in the designer, but it fails when run from a client.
Error message is
com.inductiveautomation.ignition.common.script.JythonExecException: Traceback (most recent call last):
File "<event:actionPerformed>", line 4, in <module>
ImportError: No module named designer
Following is the script, line 4 imports DTGatewayInterface:
from java.awt import Toolkit
from java.io import File
from org.apache.commons.io import FilenameUtils
from com.inductiveautomation.ignition.designer.gateway import DTGatewayInterface
#from com.inductiveautomation.ignition.client.gateway_interface import DTGatewayInterface
import imghdr
gi = DTGatewayInterface.getInstance()
filepath = event.source.parent.getComponent('File Explorer').selectedPath
image_name = File(filepath).name
image_data = system.file.readFileAsBytes(filepath)
javaImage = Toolkit.getDefaultToolkit().getImage(filepath)
#valid image types PNG, JPEG, GIF, BMP
image_type = imghdr.what(str(filepath)).upper()
folder = "%s/" % event.source.parent.sop_id
images = gi.getImageList(event.source, folder)
new_image = True
for i in range(images.rowCount):
if '%s%s' % (folder,image_name) == images.getValueAt(i, 'path'):
new_image = False
break
if new_image or system.gui.confirm('Image %s already exists for this SOP. Overwrite?' % image_name, 'Image Exists'):
gi.uploadImage(event.source, image_name, "Image Description", image_type, folder, javaImage.width, javaImage.height, image_data)
project.procedure.item_add(system.gui.getWindow('sop_edit').getRootContainer().getComponent('procedure'), event.source.parent.index, 20400, event.source.parent.level, '%s%s' % (folder,image_name))
system.nav.closeParentWindow(event)
DTGatewayInterface only exists in the client. Technically you could try sending a message over our interface from a client, but I’m not positive it’ll be allowed from the client scope…
A perhaps better option that would work on both scopes would be a gateway level function in a message handler - look around this forum for IgnitionGateway/SRContext, then call getImageManager()
, from which you can call the uploadImage method directly with basically the same arguments you were already supplying:
public void insertImage(String name, String desc, ImageFormat type, final String dir, byte[] input, int width, int height, int size) {
I do not understand your response “DTGatewayInterface only exists in the client”. The script is attached to a button press. In the designer, the button press works fine. It does not work when pressed from a client. Any chance I can speak to someone about this?
Support really isn’t equipped to deal with low level hacking like this. In case I didn’t make it clear enough - this isn’t a “supported” feature. You can technically make it work, using techniques I’ve described, but you’re entirely on your own if it doesn’t work.
DTGatewayInterface
is a Java class that literally doesn’t exist when you’re in a client. It’s not part of the required collection of Java code to run a Vision client, so it’s not available.
Ok, I’m very close again…
I am passing all the parameters to a Gateway Message Handler, it is blowing up because I am putting the string ‘JPEG’ in the 3rd parameter which wants an ImageFormat. Can you tell me how to convert from the string to an ImageFormat, including any using or import. Thanks!
Got it.
First,
from com.inductiveautomation.ignition.gateway.images import ImageFormat
Then use: ImageFormat.JPEG
(exactly like that - no quotes, etc) as the third parameter.
You cannot believe how many variations of that I attempted. I’ll post the full solution after I clean it up.
The following works in versin 7.9.13, but any suggestions for improvement are greatly appreciated:
Gateway Event Script \ Message named image_upload:
from com.inductiveautomation.ignition.gateway import SRContext
from com.inductiveautomation.ignition.gateway.images import ImageFormat
context = SRContext.get()
image = context.getImageManager()
# 1 Valid image types PNG, JPEG, GIF, BMP
image_type = {
'PNG' : ImageFormat.PNG,
'JPG' : ImageFormat.JPEG,
'JPEG': ImageFormat.JPEG,
'GIF' : ImageFormat.GIF,
'BMP' : ImageFormat.BMP}[payload['image_type']]
image.insertImage(payload['image_name'], payload['image_desc'], image_type, payload['folder'], payload['image_data'], payload['width'], payload['height'], payload['size'])
return
Script on the “Upload” button on the Vision Window:
from java.awt import Toolkit
from java.io import File
from org.apache.commons.io import FilenameUtils
import imghdr
filepath = event.source.parent.getComponent('File Explorer').selectedPath
payload = {}
payload['image_name'] = File(filepath).name
payload['image_desc'] = None
# Valid image types PNG, JPEG, GIF, BMP, fix this in the message handler
payload['image_type'] = imghdr.what(str(filepath)).upper()
# Foward slash is necessary part of folder name
payload['folder'] = "folder/"
javaImage = Toolkit.getDefaultToolkit().getImage(filepath)
payload['width'] = javaImage.width
payload['height'] = javaImage.height
size = File(filepath).length()
payload['size'] = size
payload['image_data'] = system.file.readFileAsBytes(filepath)
# Call the gateway event script message handler, named image_upload on this project
proj = system.tag.read("[System]Client/System/ProjectName").value
status = system.util.sendRequest(proj, 'image_upload', payload)
The imageformat stuff could be simplified a little bit:
image_type = ImageFormat.valueOf(payload["image_type"].upper())
Java enum classes automatically get a valueOf
method that does a case sensitive string comparison and throws an exception if the value is not found.