Paintable Canvas Repaint Performance

I have been running into issues with the repaint event handler taking up too much of the client resources. This code takes the byte array into an image. Recently the images we have displaying became higher resolution. The byte array expanded from ~80,000 to ~500,000. I have taken some tips from slower/stop repainting but it is still quite slow client side, within my designer it perform well. I am not sure what I can do to improve performance.

Old Code

g = event.graphics
bytes = system.file.readFileAsBytes("C:\\imagefile.PNG")
if bytes:
	from javax.imageio import ImageIO
	from java.io import ByteArrayInputStream
	image = ImageIO.read(ByteArrayInputStream(bytes))
	scaledImage = image.getScaledInstance(700,600,0)
	g.drawImage(scaledImage,0,-15,event.source)

New Code

Repaint

g = event.graphics
filename = "C:\\imagefile.PNG"
image = event.source.getClientProperty("img-cached")

if not event.source.manualTextFieldModified and image:
	g.drawImage(image, 0, 0, 820, 615, event.source)

propertyChange

filename = "C:\\imagefile.PNG"

image = event.source.getClientProperty("img-bytes-cached")

if event.source.manualTextFieldModified or not image:
	from javax.imageio import ImageIO
	from java.io import ByteArrayInputStream
	bytes = system.file.readFileAsBytes(filename)
	image = ImageIO.read(ByteArrayInputStream(bytes))
	event.source.putClientProperty("img-cached",image)
	system.tag.write("manualTextFieldModified", 0)

Hmm. New code looks good overall to me. One note though, please use the preformatted text option (it looks like a laptop in the toolbar above the comment, or press ctrl+shift+C. Its much easier to read.)

I’m wondering why you’re using a paintable canvas for this, though. This looks like a job for the normal image component, uhnless you’re doing more with it. The image filename looks static, perfect for the image component. If not, I believe theres a way to dynamically edit the images in the little image browser that pops up when you select an image. Unfortunately I’m not familiar with that, but hopefully someone else can point out how to do that, if its possible.

Sorry about that, I didn’t realize they have preformatted text.

I am using a path that isn’t reachable with the client. It is located on the host gateway computer.

Try setPath() on the image component (see here). But I was rereading your code, your propertyChange script - does it check for event.propertyName? If not, that’s probably the issue.

Unfortunately, there’s an upper bound to Java Swing’s graphic performance - all operations are CPU-bound, rather than using the GPU for painting related tasks. A large byte array is always going to be “expensive” to draw. You can try enabling hardware acceleration using a command line flag, but your results may vary - this option is disabled by default and not something we test against:
-Dsun.java2d.opengl=true (see the manual for instructions on how to use command line flags)

3 Likes

Also, I don’t know if you just omitted this for copy-pasting, but if your propertyChange script is exactly what you posted, then you can also get an easy performance gain by only actually running your code if the event is relevant, ie:

if event.propertyName == 'manualTextFieldModified':
    # put the rest of your code here

There are so many reasons a propertyChange event can be fired that I consider it a bug if the propertyName is not checked.

4 Likes

I did not notice any performance gain from this code change.

The whole reason I embarked on improving the code was that when I used the old code. It would bog down all the text fields and drop downs. The text fields values are used within the image itself. The new code does not bog down the client but it takes way a while to load.

Transition Time between the new different image sizes.

Old Code
Small Image -> Big Image = Load time 8 secs
Large Image loaded modify text on image = 6 secs
Big Image to Small Image = 6 secs
Down side, everything is slower.

New Code
Small Image -> Big Image = Load time 22 secs
Large Image loaded modify text on image = 4 secs
Big Image to Small Image = 4 secs