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 designer. 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.