Retrieve and Display a BLOB in Perspective

I’m having trouble converting a blob to an image that I’m pulling from a SQL DB. I’m using an event action on a button to trigger a query to get the Blob. After that, I set the converted blob to the image component source. When executed, the source of the image changes but no image appears. Here’s my code:

from javax.imageio import ImageIO
	from java.io import ByteArrayInputStream

	query = "SELECT image FROM imageStorage"
	bytes = system.db.runScalarQuery(query, "local")		
	image = ImageIO.read(ByteArrayInputStream(bytes))
	self.getSibling("image").props.source = image

Java swing image objects won’t work. You need a URL to the image. You probably need the WebDev module to do this efficiently (for now).

3 Likes

After working with support, we ended up setting up an image path under the Ignition web server folder. This works but requires us to store the images on the machine that runs ignition though. Is it possible in perspective right now to have the database handle all of the storage? From what I understand this is possible in vision with the canvas component.

The better, more dynamic option is to use Webdev. Install the module, then in the designer set up a new Python endpoint with a name like images - this will ultimately “mount” the endpoint at <gateway address>/system/webdev/<projectname>/images.

In the doGet scripting event, run the (named) query you want to to fetch a particular image. You can get the path, ie something.png in a request to images/something.png via request['remainingPath'] - use that as a parameter in your (named) query to fetch the bytes for the appropriate image.

Then, return those bytes using the bytes return type:
return {"bytes": myQueryOutputVar}
And you should be able to use an appropriate URL directly in Perspective’s image component, or anywhere else you can use a direct image path.

1 Like

If you don't have webdev you can do something like this.

2 Likes

New option for image display from a database:

{ /shameless plug }

Hi,
I am having trouble with this method. I am not exactly sure how the image component gets the source path from the web dev script that you mentioned here. Here is what I have in the doGet in the web dev
` code

id = request['params'].get('id',2) 

MP = request['params'].get('MP',2) 

params = {'MP_ID':MP , 'id':id} 

byte = system.db.runNamedQuery('Section Info/Images for Before',params) 
return {'bytes': byte}

`

My namedQuery returns the varbinary(Max) as recommended based on the two parameters passed in.
What does the doGet script actually return?

Thanks!

Can you reformat your code? (Hit the pencil icon below your post.) Select the code and then press the </> code formatting button. Check indentation - if there is any - before saving the edit.

No, it doesn't. It returns a Dataset containing the rows returned by the Named Query. You have to retrieve the row/column value that actually has the bytes from the dataset.

This very moment i was coincidentally working on displaying blob images stored as varbinary as well. I just wanted to share, that @pturmel’s module is wonderful, very easy to use. Thanks Phil!

1 Like

I’ve got both methods working. Thanks for the help!

1 Like

Any reason you could think that this would work for pngs, etc. but not for SVGs?

Would this have to do with what image types the image component can take a byte array for? Because SVGs work fine when they come out of the image management feature, however they don't seem to be showing up for this approach.

You might need to manually add a content-type header; without one bytes sends as application/octet-stream or something like that, and it might be that PNG works incidentally in most browser, but to ensure proper detection on the receiving end you probably want to use a more specific content type.

This was the problem! Thank you for the clarification.

1 Like