SVG view in Perspective

Hello all!

I am using some Cognex cameras that store (through FTP) images and SVG files in the same computer Ignition is installed on. Cognex configuration program allows to choose the image format between .bmp and jpg.

The SVG file saved, is somehow referencing to the image with the same name in the same folder. The SVG contains some coloured and arrows squares that indicate status and position about the inspections. Please see an example below of opening the SVG file in the browser:

I want to show this SVG (image + overlayed graphics) in a Perspective view, dynamically via script. Currently, I am successfully able to show an image in an Image component using this script:

import base64

import os

mainFolder = system.tag.readBlocking("[NOMAD_TAGS]main_dir")[0].value
fileName = "CAM4_Omega6.bmp" #It also works for png and jpg formats
path = os.path.join(mainFolder, fileName)
path

if os.path.exists(path):

	bytes = system.file.readFileAsBytes(path)
	base64EncodedStr = base64.b64encode(bytes)
	b64Image = "data:imagef;base64,"+ base64EncodedStr
	
	system.tag.writeBlocking("[NOMAD_TAGS]Borrar", [b64Image]) #this tag is binded to the source prop of the Image component

else:

	print("Path does not exist.")

But I am struggling to show the SVG file similarly. Please find attached two files as an example (SVG and its corresponding bmp image).

One interesting thing is that, if I open the SVG with notepad (seems XML) and insert a comment where the image is referenced (line 3), the view is just exactly the graphics:

What can I do to correctly process through script the SVG file and show it in a perspective component?

I am in contact with support (@Dechen_Chuteng ) and we are not finding a solution for now. But I am sure there must be some workaround, that is why we agreed to ask the forum.

Approaches we have tried/thought:

  1. Use the same script above, but pointing directly to the .svg file. Nothing shown in the Image component, although something is written into the tag.

  2. Use a third-party library like CairoSVG, pyvips, inkscape, wand, svglib. Please see link1 and link2. Dee only checked CairoSVG library, and she discovered that it is not valid for Ignition. The idea here may be to save/export a temporary file that it is the PNG/JPG conversion result of the SVG file, and run the same script pointing to this temporary file. Or even better, from any function of above libraries, get the data and transform in something that can be shown directly in a perspective view (similarly of what I have done with base64 encoding), so I do not have to play with files.

  3. Throwing the SVG (with or without the line comment above mentioned) manually into a perspective view (creates a "Drawing") results in the following:

image

  1. Importing manually the SVG file, into the Image Management Tool, and updating the source prop in the Image component:

*Please note the graphics look different than 3.

  1. Importing manually the SVG file with the line comment, into the Image Management Tool, and updating the source prop in the Image component:

*Please note the graphics look different than 3.

  1. Check webdev module trial.

Looking at points 5 and 6, is there a way to upload files into the Image Management Tool through script?

Could anybody more experienced carry out some tests or give us some tips?

Thank you so much in advance!

what is written here?

you could try storing your image here:

C:\Program Files\Inductive Automation\Ignition\webserver\webapps\main\xx.svg

and call it in your imgcomponent directly with /xx.svg

(note igntion will lock this file (on windows?) so you wont be able to just delete/update it. Unless you use this:
Unblock and Delete files that have been locked by Java)

Or there is a module that could be interesting to check, to store it in a db

Hi @victordcq , thanks for your reply.

For the first question, what is written is this:

data:imagef;base64,PHN2ZyAgICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAgICAgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiICAgICB2ZXJzaW9uPSIxLjEiICAgICBmb250LWZhbWlseT0iYXJpYWwiICAgICA+CjwhLS1pbWFnZSBDQU0yX09tZWdhNi5ibXA6IC9jYW0wL2ltZy8wMDAwMDAwMDAwMDAwMTY/c3o9MTQ0MCwxMDgwIC0tPg0KPGltYWdlIHg9IjAiIHk9IjAiIHdpZHRoPSIxNDQwcHgiIGhlaWdodD0iMTA4MHB4IiB4bGluazpocmVmPSJDQU0yX09tZWdhNi5ibXAiLz4KPGRlZnM+CjxtYXJrZXIgaWQ9ImNhbTAwMDAwMDAwMDAxNEFkMCIgdmlld0JveD0iMCAwIDE1IDE1IiByZWZYPSIxNSIgcmVmWT0iNy41IiBtYXJrZXJVbml0cz0idXNlclNwYWNlT25Vc2UiIG1hcmtlcldpZHRoPSIzMC4wMDAwMDAiIG1hcmtlckhlaWdodD0iMzAuMDAwMDAwIiBvcmllbnQ9ImF1dG8iPgo8cGF0aCBkPSJNIDAgMCBMIDE1IDcuNSBMIDAgMTUgeiIgZmlsbD0iIzMyQ0QzMiIvPgo8L21hcmtlcj4KCjxtYXJrZXIgaWQ9ImNhbTAwMDAwMDAwMDAxNDFkMSIgdmlld0JveD0iMCAwIDE1IDE1IiByZWZYPSIwIiByZWZZPSI3LjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjMwLjAwMDAwMCIgbWFya2VySGVpZ2h0PSIzMC4wMDAwMDAiIG9yaWVudD0iYXV0byI+CjxwYXRoIGQ9Ik0gMTUgMCBMIDAgNy41IEwgMTUgMTUgeiIgZmlsbD0iIzMyQ0QzMiIvPgo8L21hcmtlcj4KCjxwYXR0ZXJuIGlkPSJjYW0wMDAwMDAwMDAwMTQ2ZDIiIHBhdHRlcm5Vbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjAiIHk9IjAiIHdpZHRoPSIxMC4wMDAwMDAiIGhlaWdodD0iMTAuMDAwMDAwIiB2aWV3Qm94PSIwIDAgMTAuMDAwMDAwIDEwLjAwMDAwMCIgPgo8cGF0aCBkPSJNIDAgMTAuMDAwMDAwIDEwLjAwMDAwMCAwIiBzdHJva2Utd2lkdGg9IjEuMDAwMDAwIiBzdHJva2U9IiMwMDAwRkYiIC8+CjwvcGF0dGVybj4KCjwvZGVmcz4KPHN0eWxlPgoJLnMtY2FtMDAwMDAwMDAwMDEzRgl7IGZvbnQtc2l6ZToyNC4wMHB0O2ZvbnQtZmFtaWx5OkFyaWFsOyB9CgkuZHMtY2FtMDAwMDAwMDAwMDEzRQl7IGZvbnQtc2l6ZTo5LjAwcHQ7c3Ryb2tlLXdpZHRoOjIuMDA7IH0KPC9zdHlsZT4KPGcgZGF0YS1jPSJQYXR0ZXJuXzEuSW5wdXRGaXh0dXJlIiBjbGFzcz0iZHMtY2FtMDAwMDAwMDAwMDEzRSI+PC9nPgo8ZyBkYXRhLWM9IlBhdHRlcm5fMS5TZWFyY2hSZWdpb24iIGNsYXNzPSJlZGl0YWJsZSBkcy1jYW0wMDAwMDAwMDAwMTNFIj48L2c+CjxnIGRhdGEtYz0iUGF0dGVybl8xLlBhdHRlcm4iIGNsYXNzPSJkcy1jYW0wMDAwMDAwMDAwMTNFIj48L2c+CjxnIGRhdGEtYz0iUGF0dGVybl8xLlBhdHRlcm5JbWFnZSIgY2xhc3M9ImRzLWNhbTAwMDAwMDAwMDAxM0UiPjwvZz4KPGcgZGF0YS1jPSJQYXR0ZXJuXzEuRmluZFBhdHRlcm5zIiBjbGFzcz0iZHMtY2FtMDAwMDAwMDAwMDEzRSI+PGc+CjxsaW5lIHgxPSI3MzEuMiIgeTE9IjUxMS4zIiB4Mj0iNzM1LjQiIHkyPSI0MDMuNCIgc3Ryb2tlPSIjMzJDRDMyIiAgbWFya2VyLXN0YXJ0PSJ1cmwoI2NhbTAwMDAwMDAwMDAxNDFkMSkiLz4KPGxpbmUgeDE9Ijc3Ny4zIiB5MT0iNDU5LjEiIHgyPSI2ODkuMyIgeTI9IjQ1NS43IiBzdHJva2U9IiMzMkNEMzIiICBtYXJrZXItc3RhcnQ9InVybCgjY2FtMDAwMDAwMDAwMDE0MWQxKSIvPgo8L2c+CjxkZWZzPgo8ZyBpZD0iY2FtMDAwMDAwMDAwMDE0M3MwIj4KPHBhdGggZD0iIE0gNTUxLjQsMTczIGggNDg2LjEgdiA3MzcgaCAtNDg2LjF6IiBzdHJva2U9IiNGRjAwMDAiLz4KPC9nPgo8dXNlIHhsaW5rOmhyZWY9IiNjYW0wMDAwMDAwMDAwMTQzczAiIGZpbGw9Im5vbmUiLz4KPC9kZWZzPgo8ZyBkYXRhLWNvZ25leC1jb21wb3NpdGVyZWdpb249ImZpbGwiPgo8cGF0aCBkPSIgTSA1NTEuNCwxNzMgaCA0ODYuMSB2IDczNyBoIC00ODYuMXoiIHN0cm9rZT0iI0ZGMDAwMCIgZmlsbD0ibm9uZSIvPgo8L2c+CjxnIGRhdGEtY29nbmV4LWNvbXBvc2l0ZXJlZ2lvbj0iYWRkIj4KPHBhdGggZD0iIE0gNTUxLjQsMTczIGggNDg2LjEgdiA3MzcgaCAtNDg2LjF6IiBzdHJva2U9IiNGRjAwMDAiIGZpbGw9Im5vbmUiLz4KPC9nPgo8L2c+CjxnIGRhdGEtYz0iQjciIGNsYXNzPSJkcy1jYW0wMDAwMDAwMDAwMTNFIj48ZGVmcz4KPGcgaWQ9ImNhbTAwMDAwMDAwMDAxNDdzMCI+CjxwYXRoIGQ9IiBNIDU1MS40LDE3MyBoIDQ4Ni4xIHYgNzM3IGggLTQ4Ni4xeiIgc3Ryb2tlPSIjMzJDRDMyIi8+CjwvZz4KPHVzZSB4bGluazpocmVmPSIjY2FtMDAwMDAwMDAwMDE0N3MwIiBmaWxsPSJub25lIi8+CjwvZGVmcz4KPGcgZGF0YS1jb2duZXgtY29tcG9zaXRlcmVnaW9uPSJmaWxsIj4KPHBhdGggZD0iIE0gNTUxLjQsMTczIGggNDg2LjEgdiA3MzcgaCAtNDg2LjF6IiBzdHJva2U9IiMzMkNEMzIiIGZpbGw9Im5vbmUiLz4KPC9nPgo8ZyBkYXRhLWNvZ25leC1jb21wb3NpdGVyZWdpb249ImFkZCI+CjxwYXRoIGQ9IiBNIDU1MS40LDE3MyBoIDQ4Ni4xIHYgNzM3IGggLTQ4Ni4xeiIgc3Ryb2tlPSIjMzJDRDMyIiBmaWxsPSJub25lIi8+CjwvZz4KPC9nPgo8ZyBkYXRhLWM9IlBhdHRlcm5fMS5GaXh0dXJlTG9jYXRpb25zIiBjbGFzcz0iZHMtY2FtMDAwMDAwMDAwMDEzRSI+PC9nPgo8ZyBkYXRhLWM9IkU3IiBjbGFzcz0iZHMtY2FtMDAwMDAwMDAwMDEzRSI+PC9nPgo8ZyBkYXRhLWM9IkJvbHQuSW5wdXRGaXh0dXJlIiBjbGFzcz0iZHMtY2FtMDAwMDAwMDAwMDEzRSI+PC9nPgo8ZyBkYXRhLWM9IkJvbHQuUmVnaW9uIiBjbGFzcz0iZWRpdGFibGUgZHMtY2FtMDAwMDAwMDAwMDEzRSI+PC9nPgo8ZyBkYXRhLWM9IloxNiIgY2xhc3M9ImRzLWNhbTAwMDAwMDAwMDAxM0UiPjxsaW5lIHgxPSIwIiB5MT0iMCIgeDI9IjE0MzkiIHkyPSIwIiBzdHJva2U9IiMzMkNEMzIiIC8+CjwvZz4KPGcgZGF0YS1jPSJaMTciIGNsYXNzPSJkcy1jYW0wMDAwMDAwMDAwMTNFIj48bGluZSB4MT0iMTQzOSIgeTE9IjAiIHgyPSIxNDM5IiB5Mj0iMTA3OSIgc3Ryb2tlPSIjMzJDRDMyIiAvPgo8L2c+CjxnIGRhdGEtYz0iQm9sdC5FTENsYXNzaWZ5VG9vbCIgY2xhc3M9ImRzLWNhbTAwMDAwMDAwMDAxM0UiPjwvZz4KPGcgZGF0YS1jPSJaMTgiIGNsYXNzPSJkcy1jYW0wMDAwMDAwMDAwMTNFIj48bGluZSB4MT0iMTQzOSIgeTE9IjEwNzkiIHgyPSIwIiB5Mj0iMTA3OSIgc3Ryb2tlPSIjMzJDRDMyIiAvPgo8L2c+CjxnIGRhdGEtYz0iWjE5IiBjbGFzcz0iZHMtY2FtMDAwMDAwMDAwMDEzRSI+PGxpbmUgeDE9IjAiIHkxPSIxMDc5IiB4Mj0iMCIgeTI9IjAiIHN0cm9rZT0iIzMyQ0QzMiIgLz4KPC9nPgo8ZyBkYXRhLWM9IkEyMCIgY2xhc3M9InMtY2FtMDAwMDAwMDAwMDEzRiI+PHRleHQgeD0iNjM3IiB5PSIzNjkiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMzMkNEMzI7c3Ryb2tlLXdpZHRoOjAuNSU7c3Ryb2tlLWxpbmVqb2luOmJldmVsOyIgPk9LPC90ZXh0Pgo8dGV4dCB4PSI2MzciIHk9IjM2OSIgc3R5bGU9ImZpbGw6IzAwMDAwMDtzdHJva2U6bm9uZTsiID5PSzwvdGV4dD4KPC9nPgo8ZyBkYXRhLWM9IkEyMSIgY2xhc3M9ImRzLWNhbTAwMDAwMDAwMDAxM0UiPjxwYXRoIG1hcmtlci1lbmQ9InVybCgjY2FtMDAwMDAwMDAwMDE0QWQwKSIgZD0iIE0gNjMyLjUsMzY0LjkgbCAxMDAsMS40IiBzdHJva2U9InRyYW5zcGFyZW50IiBmaWxsPSJub25lIi8+CjxwYXRoIG1hcmtlci1lbmQ9InVybCgjY2FtMDAwMDAwMDAwMDE0QWQwKSIgZD0iIE0gNjMyLjUsMzY0LjkgbCAtMS40LDEwMCIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0ibm9uZSIvPgo8dGV4dCB4PSI3MzIuNiIgeT0iMzU2LjMiIHN0eWxlPSJmaWxsOiMzMkNEMzIiICB0ZXh0LWFuY2hvcj0ibWlkZGxlIiA+PHRzcGFuIGR5PSItMC41ZW0iID5YPC90c3Bhbj48L3RleHQ+Cjx0ZXh0IHg9IjYyMS4xIiB5PSI0NjQuOCIgc3R5bGU9ImZpbGw6IzMyQ0QzMiIgIHRleHQtYW5jaG9yPSJlbmQiID48dHNwYW4gZHk9IjAuNWVtIiA+WTwvdHNwYW4+PC90ZXh0Pgo8cGF0aCBkPSIgTSA2MzIuNSwzNjQuOSBsIDIwMCwyLjggbCAtMi44LDIwMCBsIC0xOTkuOSwtMi44eiIgc3Ryb2tlPSIjMzJDRDMyIiBmaWxsPSJub25lIi8+CjwvZz4KPGcgZGF0YS1jPSJSaXZldC5JbnB1dEZpeHR1cmUiIGNsYXNzPSJkcy1jYW0wMDAwMDAwMDAwMTNFIj48L2c+CjxnIGRhdGEtYz0iUml2ZXQuUmVnaW9uIiBjbGFzcz0iZWRpdGFibGUgZHMtY2FtMDAwMDAwMDAwMDEzRSI+PC9nPgo8ZyBkYXRhLWM9IlczMiIgY2xhc3M9ImRzLWNhbTAwMDAwMDAwMDAxM0UiPjwvZz4KPGcgZGF0YS1jPSJSaXZldC5FTENsYXNzaWZ5VG9vbCIgY2xhc3M9ImRzLWNhbTAwMDAwMDAwMDAxM0UiPjwvZz4KPGcgZGF0YS1jPSJBMzUiIGNsYXNzPSJzLWNhbTAwMDAwMDAwMDAxM0YiPjx0ZXh0IHg9IjQ2OCIgeT0iNTcyIiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMzJDRDMyO3N0cm9rZS13aWR0aDowLjUlO3N0cm9rZS1saW5lam9pbjpiZXZlbDsiID5PSzwvdGV4dD4KPHRleHQgeD0iNDY4IiB5PSI1NzIiIHN0eWxlPSJmaWxsOiMwMDAwMDA7c3Ryb2tlOm5vbmU7IiA+T0s8L3RleHQ+CjwvZz4KPGcgZGF0YS1jPSJBMzYiIGNsYXNzPSJkcy1jYW0wMDAwMDAwMDAwMTNFIj48cGF0aCBtYXJrZXItZW5kPSJ1cmwoI2NhbTAwMDAwMDAwMDAxNEFkMCkiIGQ9IiBNIDQ2My4zLDU2Ny43IGwgMTE1LjYsMi42IiBzdHJva2U9InRyYW5zcGFyZW50IiBmaWxsPSJub25lIi8+CjxwYXRoIG1hcmtlci1lbmQ9InVybCgjY2FtMDAwMDAwMDAwMDE0QWQwKSIgZD0iIE0gNDYzLjMsNTY3LjcgbCAtMi44LDEyMi4xIiBzdHJva2U9InRyYW5zcGFyZW50IiBmaWxsPSJub25lIi8+Cjx0ZXh0IHg9IjU3OS4xIiB5PSI1NjAuMyIgc3R5bGU9ImZpbGw6IzMyQ0QzMiIgIHRleHQtYW5jaG9yPSJtaWRkbGUiID48dHNwYW4gZHk9Ii0wLjVlbSIgPlg8L3RzcGFuPjwvdGV4dD4KPHRleHQgeD0iNDUwLjUiIHk9IjY4OS42IiBzdHlsZT0iZmlsbDojMzJDRDMyIiAgdGV4dC1hbmNob3I9ImVuZCIgPjx0c3BhbiBkeT0iMC41ZW0iID5ZPC90c3Bhbj48L3RleHQ+CjxwYXRoIGQ9IiBNIDQ2My4zLDU2Ny43IGwgMjMxLjEsNS4yIGwgLTUuNSwyNDQuMiBsIC0yMzEuMSwtNS4xeiIgc3Ryb2tlPSIjMzJDRDMyIiBmaWxsPSJub25lIi8+CjwvZz4KPGcgZGF0YS1jPSJZNTkiIGNsYXNzPSJkcy1jYW0wMDAwMDAwMDAwMTNFIj48L2c+CjxnIGRhdGEtYz0iRmFjdG9yeVByb3RvY29sLklucHV0QnVmZmVyIiBjbGFzcz0iZHMtY2FtMDAwMDAwMDAwMDEzRSI+PC9nPgo8ZyBkYXRhLWM9Ilo4MiIgY2xhc3M9ImRzLWNhbTAwMDAwMDAwMDAxM0UiPjwvZz4KPC9zdmc+Cg==

About the second aspect, yes, I would give it a try. But the "negative" point of this solution is that I have to copy every file to that folder and then delete it.

Eventually, for the third point, I am not sure if it will solve the problem at all. I will still have to convert the svg to png or upload both files to the database.

its not an img uri. you are getting a data:text/html;base64, uri.
change it to that.
This also means the image componet wont do and you'll need to use the inline frame component.

Furthermore, your svg has no scaling attributes in the header meaning it wont show up nice. you should add in a viewBox="0 0 1440 1080" (judging form the img component size)

Idk why the position of the sqaures doesnt match your example though, is it the same image? i do see a bunch of redundant elements in the svg, so idk how you generated this?
Its nothing to do with igntion because decoding it back from base64 gives the same result

edit: seems it was not the same image(?) (or your encoding is wrong)
i downloaded your svg from transfer and encoded it and this one does work nice (after adding in the viewBox)

Summary
[
  {
    "type": "ia.container.coord",
    "version": 0,
    "props": {},
    "meta": {
      "name": "root"
    },
    "position": {},
    "custom": {},
    "children": [
      {
        "type": "ia.display.iframe",
        "version": 0,
        "props": {
          "src": "data:text/html;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIGZvbnQtZmFtaWx5PSJhcmlhbCIgdmlld0JveD0iMCAwIDE0NDAgMTA4MCI+CjwhLS1pbWFnZSBDQU00X09tZWdhNi5ibXA6IC9jYW0wL2ltZy8wMDAwMDAwMDAwMDAwMTI/c3o9MTQ0MCwxMDgwIC0tPgo8aW1hZ2UgeD0iMCIgeT0iMCIgd2lkdGg9IjE0NDBweCIgaGVpZ2h0PSIxMDgwcHgiIHhsaW5rOmhyZWY9IkNBTTRfT21lZ2E2LmJtcCIvPgo8ZGVmcz4KPG1hcmtlciBpZD0iY2FtMDAwMDAwMDAwMDA1NWQwIiB2aWV3Qm94PSIwIDAgMTUgMTUiIHJlZlg9IjE1IiByZWZZPSI3LjUiIG1hcmtlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgbWFya2VyV2lkdGg9IjMwLjAwMDAwMCIgbWFya2VySGVpZ2h0PSIzMC4wMDAwMDAiIG9yaWVudD0iYXV0byI+CjxwYXRoIGQ9Ik0gMCAwIEwgMTUgNy41IEwgMCAxNSB6IiBmaWxsPSIjMzJDRDMyIi8+CjwvbWFya2VyPgoKPG1hcmtlciBpZD0iY2FtMDAwMDAwMDAwMDA1NmQxIiB2aWV3Qm94PSIwIDAgMTUgMTUiIHJlZlg9IjAiIHJlZlk9IjcuNSIgbWFya2VyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBtYXJrZXJXaWR0aD0iMzAuMDAwMDAwIiBtYXJrZXJIZWlnaHQ9IjMwLjAwMDAwMCIgb3JpZW50PSJhdXRvIj4KPHBhdGggZD0iTSAxNSAwIEwgMCA3LjUgTCAxNSAxNSB6IiBmaWxsPSIjMzJDRDMyIi8+CjwvbWFya2VyPgoKPHBhdHRlcm4gaWQ9ImNhbTAwMDAwMDAwMDAwNUJkMiIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeD0iMCIgeT0iMCIgd2lkdGg9IjEwLjAwMDAwMCIgaGVpZ2h0PSIxMC4wMDAwMDAiIHZpZXdCb3g9IjAgMCAxMC4wMDAwMDAgMTAuMDAwMDAwIj4KPHBhdGggZD0iTSAwIDEwLjAwMDAwMCAxMC4wMDAwMDAgMCIgc3Ryb2tlLXdpZHRoPSIxLjAwMDAwMCIgc3Ryb2tlPSIjMDAwMEZGIi8+CjwvcGF0dGVybj4KCjwvZGVmcz4KPHN0eWxlPgoJLnMtY2FtMDAwMDAwMDAwMDA1Mwl7IGZvbnQtc2l6ZToyNC4wMHB0O2ZvbnQtZmFtaWx5OkFyaWFsOyB9CgkuZHMtY2FtMDAwMDAwMDAwMDA1Mgl7IGZvbnQtc2l6ZTo5LjAwcHQ7c3Ryb2tlLXdpZHRoOjIuMDA7IH0KPC9zdHlsZT4KPGcgZGF0YS1jPSJCb2x0LklucHV0Rml4dHVyZSIgY2xhc3M9ImRzLWNhbTAwMDAwMDAwMDAwNTIiLz4KPGcgZGF0YS1jPSJCb2x0LlJlZ2lvbiIgY2xhc3M9ImVkaXRhYmxlIGRzLWNhbTAwMDAwMDAwMDAwNTIiLz4KPGcgZGF0YS1jPSJCb2x0LkVMQ2xhc3NpZnlUb29sIiBjbGFzcz0iZHMtY2FtMDAwMDAwMDAwMDA1MiIvPgo8ZyBkYXRhLWM9IkE4IiBjbGFzcz0icy1jYW0wMDAwMDAwMDAwMDUzIj48dGV4dCB4PSI1NjIiIHk9IjQzMCIgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6IzMyQ0QzMjtzdHJva2Utd2lkdGg6MC41JTtzdHJva2UtbGluZWpvaW46YmV2ZWw7Ij5PSzwvdGV4dD4KPHRleHQgeD0iNTYyIiB5PSI0MzAiIHN0eWxlPSJmaWxsOiMwMDAwMDA7c3Ryb2tlOm5vbmU7Ij5PSzwvdGV4dD4KPC9nPgo8ZyBkYXRhLWM9IkE5IiBjbGFzcz0iZHMtY2FtMDAwMDAwMDAwMDA1MiI+PHBhdGggbWFya2VyLWVuZD0idXJsKCNjYW0wMDAwMDAwMDAwMDU1ZDApIiBkPSIgTSA1NTcuOCw0MjUuNyBoIDg5LjMiIHN0cm9rZT0idHJhbnNwYXJlbnQiIGZpbGw9Im5vbmUiLz4KPHBhdGggbWFya2VyLWVuZD0idXJsKCNjYW0wMDAwMDAwMDAwMDU1ZDApIiBkPSIgTSA1NTcuOCw0MjUuNyB2IDgzLjIiIHN0cm9rZT0idHJhbnNwYXJlbnQiIGZpbGw9Im5vbmUiLz4KPHRleHQgeD0iNjQ3LjEiIHk9IjQxNS43IiBzdHlsZT0iZmlsbDojMzJDRDMyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj48dHNwYW4gZHk9Ii0wLjVlbSI+WDwvdHNwYW4+PC90ZXh0Pgo8dGV4dCB4PSI1NDcuOCIgeT0iNTA4LjkiIHN0eWxlPSJmaWxsOiMzMkNEMzIiIHRleHQtYW5jaG9yPSJlbmQiPjx0c3BhbiBkeT0iMC41ZW0iPlk8L3RzcGFuPjwvdGV4dD4KPHBhdGggZD0iIE0gNTU3LjgsNDI1LjcgaCAxNzguNyBsIC0wLjEsMTY2LjQgaCAtMTc4LjZ6IiBzdHJva2U9IiMzMkNEMzIiIGZpbGw9Im5vbmUiLz4KPC9nPgo8ZyBkYXRhLWM9IloxNiIgY2xhc3M9ImRzLWNhbTAwMDAwMDAwMDAwNTIiPjxsaW5lIHgxPSIwIiB5MT0iMCIgeDI9IjE0MzkiIHkyPSIwIiBzdHJva2U9IiMzMkNEMzIiLz4KPC9nPgo8ZyBkYXRhLWM9IloxNyIgY2xhc3M9ImRzLWNhbTAwMDAwMDAwMDAwNTIiPjxsaW5lIHgxPSIxNDM5IiB5MT0iMCIgeDI9IjE0MzkiIHkyPSIxMDc5IiBzdHJva2U9IiMzMkNEMzIiLz4KPC9nPgo8ZyBkYXRhLWM9IlBhdHRlcm5fMS5JbnB1dEZpeHR1cmUiIGNsYXNzPSJkcy1jYW0wMDAwMDAwMDAwMDUyIi8+CjxnIGRhdGEtYz0iUGF0dGVybl8xLlNlYXJjaFJlZ2lvbiIgY2xhc3M9ImVkaXRhYmxlIGRzLWNhbTAwMDAwMDAwMDAwNTIiLz4KPGcgZGF0YS1jPSJaMTgiIGNsYXNzPSJkcy1jYW0wMDAwMDAwMDAwMDUyIj48bGluZSB4MT0iMTQzOSIgeTE9IjEwNzkiIHgyPSIwIiB5Mj0iMTA3OSIgc3Ryb2tlPSIjMzJDRDMyIi8+CjwvZz4KPGcgZGF0YS1jPSJQYXR0ZXJuXzEuUGF0dGVybiIgY2xhc3M9ImRzLWNhbTAwMDAwMDAwMDAwNTIiLz4KPGcgZGF0YS1jPSJaMTkiIGNsYXNzPSJkcy1jYW0wMDAwMDAwMDAwMDUyIj48bGluZSB4MT0iMCIgeTE9IjEwNzkiIHgyPSIwIiB5Mj0iMCIgc3Ryb2tlPSIjMzJDRDMyIi8+CjwvZz4KPGcgZGF0YS1jPSJQYXR0ZXJuXzEuUGF0dGVybkltYWdlIiBjbGFzcz0iZHMtY2FtMDAwMDAwMDAwMDA1MiIvPgo8ZyBkYXRhLWM9IlBhdHRlcm5fMS5GaW5kUGF0dGVybnMiIGNsYXNzPSJkcy1jYW0wMDAwMDAwMDAwMDUyIj48Zz4KPGxpbmUgeDE9IjY0Ni43IiB5MT0iNTYwLjgiIHgyPSI2NDYuNyIgeTI9IjQ2Mi44IiBzdHJva2U9IiMzMkNEMzIiIG1hcmtlci1zdGFydD0idXJsKCNjYW0wMDAwMDAwMDAwMDU2ZDEpIi8+CjxsaW5lIHgxPSI2ODYuNyIgeTE9IjUxMS44IiB4Mj0iNjA2LjciIHkyPSI1MTEuOCIgc3Ryb2tlPSIjMzJDRDMyIiBtYXJrZXItc3RhcnQ9InVybCgjY2FtMDAwMDAwMDAwMDA1NmQxKSIvPgo8L2c+CjxkZWZzPgo8ZyBpZD0iY2FtMDAwMDAwMDAwMDA1OHMwIj4KPHBhdGggZD0iIE0gMzM0LjYsMTExLjIgaCA2NDkuOCB2IDgxMC40IGggLTY0OS44eiIgc3Ryb2tlPSIjRkYwMDAwIi8+CjwvZz4KPHVzZSB4bGluazpocmVmPSIjY2FtMDAwMDAwMDAwMDA1OHMwIiBmaWxsPSJub25lIi8+CjwvZGVmcz4KPGcgZGF0YS1jb2duZXgtY29tcG9zaXRlcmVnaW9uPSJmaWxsIj4KPHBhdGggZD0iIE0gMzM0LjYsMTExLjIgaCA2NDkuOCB2IDgxMC40IGggLTY0OS44eiIgc3Ryb2tlPSIjRkYwMDAwIiBmaWxsPSJub25lIi8+CjwvZz4KPGcgZGF0YS1jb2duZXgtY29tcG9zaXRlcmVnaW9uPSJhZGQiPgo8cGF0aCBkPSIgTSAzMzQuNiwxMTEuMiBoIDY0OS44IHYgODEwLjQgaCAtNjQ5Ljh6IiBzdHJva2U9IiNGRjAwMDAiIGZpbGw9Im5vbmUiLz4KPC9nPgo8L2c+CjxnIGRhdGEtYz0iQjIyIiBjbGFzcz0iZHMtY2FtMDAwMDAwMDAwMDA1MiI+PGRlZnM+CjxnIGlkPSJjYW0wMDAwMDAwMDAwMDVDczAiPgo8cGF0aCBkPSIgTSAzMzQuNiwxMTEuMiBoIDY0OS44IHYgODEwLjQgaCAtNjQ5Ljh6IiBzdHJva2U9IiMzMkNEMzIiLz4KPC9nPgo8dXNlIHhsaW5rOmhyZWY9IiNjYW0wMDAwMDAwMDAwMDVDczAiIGZpbGw9Im5vbmUiLz4KPC9kZWZzPgo8ZyBkYXRhLWNvZ25leC1jb21wb3NpdGVyZWdpb249ImZpbGwiPgo8cGF0aCBkPSIgTSAzMzQuNiwxMTEuMiBoIDY0OS44IHYgODEwLjQgaCAtNjQ5Ljh6IiBzdHJva2U9IiMzMkNEMzIiIGZpbGw9Im5vbmUiLz4KPC9nPgo8ZyBkYXRhLWNvZ25leC1jb21wb3NpdGVyZWdpb249ImFkZCI+CjxwYXRoIGQ9IiBNIDMzNC42LDExMS4yIGggNjQ5LjggdiA4MTAuNCBoIC02NDkuOHoiIHN0cm9rZT0iIzMyQ0QzMiIgZmlsbD0ibm9uZSIvPgo8L2c+CjwvZz4KPGcgZGF0YS1jPSJQYXR0ZXJuXzEuRml4dHVyZUxvY2F0aW9ucyIgY2xhc3M9ImRzLWNhbTAwMDAwMDAwMDAwNTIiLz4KPGcgZGF0YS1jPSJFMjIiIGNsYXNzPSJkcy1jYW0wMDAwMDAwMDAwMDUyIi8+CjxnIGRhdGEtYz0iUml2ZXQuSW5wdXRGaXh0dXJlIiBjbGFzcz0iZHMtY2FtMDAwMDAwMDAwMDA1MiIvPgo8ZyBkYXRhLWM9IlJpdmV0LlJlZ2lvbiIgY2xhc3M9ImVkaXRhYmxlIGRzLWNhbTAwMDAwMDAwMDAwNTIiLz4KPGcgZGF0YS1jPSJXMzIiIGNsYXNzPSJkcy1jYW0wMDAwMDAwMDAwMDUyIi8+CjxnIGRhdGEtYz0iUml2ZXQuRUxDbGFzc2lmeVRvb2wiIGNsYXNzPSJkcy1jYW0wMDAwMDAwMDAwMDUyIi8+CjxnIGRhdGEtYz0iQTM1IiBjbGFzcz0icy1jYW0wMDAwMDAwMDAwMDUzIj48dGV4dCB4PSI2NzgiIHk9IjY0MiIgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6IzMyQ0QzMjtzdHJva2Utd2lkdGg6MC41JTtzdHJva2UtbGluZWpvaW46YmV2ZWw7Ij5PSzwvdGV4dD4KPHRleHQgeD0iNjc4IiB5PSI2NDIiIHN0eWxlPSJmaWxsOiMwMDAwMDA7c3Ryb2tlOm5vbmU7Ij5PSzwvdGV4dD4KPC9nPgo8ZyBkYXRhLWM9IkEzNiIgY2xhc3M9ImRzLWNhbTAwMDAwMDAwMDAwNTIiPjxwYXRoIG1hcmtlci1lbmQ9InVybCgjY2FtMDAwMDAwMDAwMDA1NWQwKSIgZD0iIE0gNjczLDYzNy4zIGwgMTEzLjEsMC4yIiBzdHJva2U9InRyYW5zcGFyZW50IiBmaWxsPSJub25lIi8+CjxwYXRoIG1hcmtlci1lbmQ9InVybCgjY2FtMDAwMDAwMDAwMDA1NWQwKSIgZD0iIE0gNjczLDYzNy4zIGwgLTAuMSwxMDYiIHN0cm9rZT0idHJhbnNwYXJlbnQiIGZpbGw9Im5vbmUiLz4KPHRleHQgeD0iNzg2LjEiIHk9IjYyNy41IiBzdHlsZT0iZmlsbDojMzJDRDMyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj48dHNwYW4gZHk9Ii0wLjVlbSI+WDwvdHNwYW4+PC90ZXh0Pgo8dGV4dCB4PSI2NjIuOSIgeT0iNzQzLjMiIHN0eWxlPSJmaWxsOiMzMkNEMzIiIHRleHQtYW5jaG9yPSJlbmQiPjx0c3BhbiBkeT0iMC41ZW0iPlk8L3RzcGFuPjwvdGV4dD4KPHBhdGggZD0iIE0gNjczLDYzNy4zIGwgMjI2LjIsMC40IGwgLTAuNCwyMTIgbCAtMjI2LjEsLTAuNHoiIHN0cm9rZT0iIzMyQ0QzMiIgZmlsbD0ibm9uZSIvPgo8L2c+CjxnIGRhdGEtYz0iWTU5IiBjbGFzcz0iZHMtY2FtMDAwMDAwMDAwMDA1MiIvPgo8ZyBkYXRhLWM9IkZhY3RvcnlQcm90b2NvbC5JbnB1dEJ1ZmZlciIgY2xhc3M9ImRzLWNhbTAwMDAwMDAwMDAwNTIiLz4KPGcgZGF0YS1jPSJaODIiIGNsYXNzPSJkcy1jYW0wMDAwMDAwMDAwMDUyIi8+Cjwvc3ZnPg=="
        },
        "meta": {
          "name": "IFrame"
        },
        "position": {
          "x": -0.5,
          "height": "100%",
          "width": "100%"
        },
        "custom": {}
      }
    ]
  }
]
1 Like

@victordcq thanks for your response. But now I am getting a little confused.

Please note that in the script shared above I am forcing the "header":

b64Image = "data:imagef;base64,"+ base64EncodedStr

The SVG file is generated by the Cognex cameras. I only modified (as mentioned above, and for testing purposes) line 3 of the XML code.

Not sure to understand the rest of what you mention. Could you try to explain another way? Starting from having the file in a directory (not the C:\Program Files\Inductive Automation\Ignition\webserver\webapps\main).

How did you manage to convert the SVG into something encoded ( data:text/html;base64,)? Forcing it via script, right? And using and Inline Frame perspective component?

PS: I always used the images initially uploaded and shared.

@Dechen_Chuteng FYI

This should get you where you want to be
Note this will only work for svgs, not for other img types

[
  {
    "type": "ia.display.iframe",
    "version": 0,
    "props": {},
    "meta": {
      "name": "IFrame"
    },
    "position": {
      "x": -0.5,
      "height": "100%",
      "width": "100%"
    },
    "custom": {},
    "propConfig": {
      "props.src": {
        "binding": {
          "type": "expr",
          "config": {
            "expression": "\"C:/Users/victor/Downloads/CAM4_Omega6.svg\""
          },
          "transforms": [
            {
              "code": "\tfrom java.util import Base64 \n\timport os\n\tpath = value\n\tif os.path.exists(path):\t\n\t\tsvgString = system.file.readFileAsString(path)\n\t\tsvgStringWithViewBox = svgString[:4] + ' viewBox=\"0 0 1440 1080\"' + svgString[4:]\n\t\tbase64_string = Base64.getEncoder().encodeToString(svgStringWithViewBox)\n\t\treturn u\"data:text/html;base64,\"+ base64_string",
              "type": "script"
            }
          ]
        }
      }
    }
  }
]

i used the java one as the python one needs bytes(?) idk if that made a difference

	from java.util import Base64 
	import os
	path = value
	if os.path.exists(path):	
		svgString = system.file.readFileAsString(path)
		svgStringWithViewBox = svgString[:4] + ' viewBox="0 0 1440 1080"' + svgString[4:]
		base64_string = Base64.getEncoder().encodeToString(svgStringWithViewBox)
		return u"data:text/html;base64,"+ base64_string


This method doesnt require you to move the svg somewhere else.
The link to the image inside the svg will never work though. but you can just put an image component underneath the iframe, should work with the scaling now.

Eh i guess its not easy to adjust then, it would be better if you could add in the viewbox right there instead of having to change the string in script, but ahwell it works too.

then something went wrong encoding the svg, converting it to bytes first probably messed up some string utf encoding idk, but my method works fine now, you want to read it in a string first anyways to add in the viewbox.

Also note: datauri's (base64encoded) have a max lenght... this might case issues with bigger files (why i asked why it has so many redunant lines). if that ever happens you'll have to find a way to clean up the svg before encoding it... idk any easy way to do that if you have no control of the generator, so lets hope it never happens for your usecase. might also happen for your image, so dont give it a to high resolution xd

1 Like

Hi @victordcq,

Thank you so much.

I am able now to process the svg and show it in an IFrame. My problem now is that I am not able to match the Image and IFrame components.

image

The closest I could get is this:

Props:

[
  {
    "type": "ia.container.flex",
    "version": 0,
    "props": {
      "direction": "column",
      "wrap": "wrap",
      "justify": "space-evenly",
      "style": {
        "textAlign": "center"
      }
    },
    "meta": {
      "name": "root"
    },
    "position": {},
    "custom": {},
    "children": [
      {
        "type": "ia.display.label",
        "version": 0,
        "props": {},
        "meta": {
          "name": "Label"
        },
        "position": {
          "basis": "32px"
        },
        "custom": {}
      },
      {
        "type": "ia.container.coord",
        "version": 0,
        "props": {},
        "meta": {
          "name": "Images"
        },
        "position": {
          "grow": 1,
          "basis": "200px"
        },
        "custom": {},
        "children": [
          {
            "type": "ia.display.image",
            "version": 0,
            "props": {
              "source": "it was too long to copy",
              "fit": {
                "mode": "contain"
              }
            },
            "meta": {
              "name": "Image"
            },
            "position": {
              "x": -7.5,
              "y": 7.5,
              "height": 500,
              "width": 700
            },
            "custom": {}
          },
          {
            "type": "ia.display.iframe",
            "version": 0,
            "props": {
              "src": "it was too long to copy 2"
            },
            "meta": {
              "name": "IFrame"
            },
            "position": {
              "height": "100%",
              "width": "100%"
            },
            "custom": {}
          }
        ]
      }
    ]
  }
]

PS: You were right. I may have confused some images :slight_smile: But no problem anymore, as long as the svg and the image have the same name. It is very clear visually.

1 Like

there are many ways to fit an image on your screen... scale, scroll, fill/stretch... what are you looking for?
i just gave it a viewbox that i thought was the right size, but maybe your image is different idk.

Edit use this for contain:
instead of just inserting in viewBox="0 0 1440 1080" you could also add in width="100%" height="100%"
svgStringWithViewBox = svgString[:4] + ' viewBox="0 0 1440 1080" width="100%" height="100%"' + svgString[4:]
then you can keep the image at 100% 100% too. this seems to work even better

2 Likes

Thanks @victordcq,

but from what I see opening the svg in a web browser, I would say that both borders should match (border of the image with the big square).

I have tried several configurations and I could not get to this. About the way of fitting, I do not really care. If it helps, I am going to show all of this in a popup inside a 10.1" tablet.

ah i see.
there seems to be a margin inside the iframe. idk how that got there, you could just add a margin on the image to compensate
use these for width and height of the image calc( 100% - 16px) (you can ignore the warning the designer gives)
and a margin of 8px

1 Like

@victordcq not sure what you have different than me, but I am still getting some margin at the left and at the bottom:

Image component:

IFrame component:

Both components are inside a coordinate container, and this inside a flex column container. I am kind of experiencing that when modifying the Image component, the IFrame component also moves.

Sorry for disturbing,

you need to put spaces in the calc around the minus sign

5 Likes