Display an Image

Can’t believe this is so difficult for me to work out…

So. I want to manipulate an image and display it on the GUI node. Really simple. Or, at least, it should be…

There’s no information (that I could find) on this subject, so I read around the forums. With spotty information, mostly from threads with people arguing, I gleamed that ImageRaster can manipulate the pixels on an Image. Great stuff… except… What the hell am I supposed to do with this Image. I have used Texture and I have used Picture but I’ve never seen a single iota of info about Image and after several hours I can’t even find out how to display it.

So if someone could help me out this issue that would be great…

Also if someone wouldn’t mind telling me how I SHOULD go about learning/finding this information, that would be super helpful as right now I’m jogging into walls every 5 minutes and my forhead can’t take much more.

Depends on what you mean by manipulate an image. For certain things, you can play with shader parameters - things like changing color saturation, brighness, some special effects etc - basically instragram :wink: - can be achieved reasonably easy with that.

If you want to play with modifying actual contents of the image, you will need to do it on java level - BufferedImage and transfer it for display purposes using AWTLoader to jme3 Image/Texture.

ImageRaster appears to manipulate pixel data… I just can’t display the damn thing.

So. I figured out, with much searching and exploring, that I can create a Texture2D from an Image and I can create a Picture from a Texture2D. Great.

Next problem was creating an image to use with the ImageRaster, I wasn’t sure what kind of buffer it expected or how to make an empty one for my needs. During my searching I found the ImagePainter contribution which provides a constructor to create an image and figured I may as well use that or I could be here till next week.

Next, next problem: My image won’t display. I get a random JMonkey specific stack trace

[java]SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.NullPointerException: Geometry: null has null mesh
at com.jme3.scene.Geometry.updateWorldBound(Geometry.java:274)
at com.jme3.scene.Spatial.updateGeometricState(Spatial.java:716)
at com.jme3.scene.Node.updateGeometricState(Node.java:175)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:248)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Unknown Source)[/java]

So the Picture isn’t working right somehow. Here’s the code:

[java]ImagePainter painter = new ImagePainter(Format.RGB16, 512, 512);
Texture texture = new Texture2D(painter.getImage());
Picture picture = new Picture();
picture.setTexture(app.getAssetManager(), texture, false); // Needs assetManager… why?
picture.setQueueBucket(Bucket.Gui);
app.getGuiNode().attachChild(picture);[/java]

Obviously, I tried applying some paint operations first but it makes no difference.

You never gave the picture a size so no mesh was created.

<cite>@pspeed said:</cite> You never gave the picture a size so no mesh was created.

Actually, it looks like Picture cannot be used this way. If you don’t call the constructor that takes an image name then the mesh is never created.

You might just use a Quad and a Geometry and set the material yourself.

I just encountered that nasty NullPointerException. So, would it be possible to remove the empty constructor, or fix it so it does initilize the class properly?

@arpagaus said: I just encountered that nasty NullPointerException. So, would it be possible to remove the empty constructor, or fix it so it does initilize the class properly?

Empty constructors are often required for things like JME’s serialization. We expect that developers can learn how to use them.

Okay, so the constructor is there for JME’s serialization. How does BitmapText handle this? There is no empty constructor.

And even if the public constructor is necessary, wouldn’t it make sense to put the initiliazation code there too? Afterall it’s only the Quad and two calls which could be externalized in a new method.

@arpagaus said: Okay, so the constructor is there for JME's serialization. How does BitmapText handle this? There is no empty constructor.

And even if the public constructor is necessary, wouldn’t it make sense to put the initiliazation code there too? Afterall it’s only the Quad and two calls which could be externalized in a new method.

BitmapText cannot be serialized because of this. BitmapText is a steaming pile for about a dozen other reasons, though.

So, back to the original question… if we initialize things in the empty constructor then we create objects/meshes/etc. that immediately get thrown away when the class is used properly (by actually setting the proper parameters). So, to me that means we make the normal use cases less optimal so that a new developer doesn’t see an NPE and immediately know how to fix their code? Basically, all serialization and proper code that happens to use the empty constructor would now generate extra garbage just to prevent a simple developer mistake.

I don’t think it’s a good trade off. We cannot prevent developers from making mistakes, really. And when it has a negative impact then we shouldn’t even try.

Coming at it from the other direction… what did you expect to happen with a Picture that had nothing set on it?

Okay, thank you for taking your time answering my annoying questions :slight_smile:
My intension were only to save someone else’s time, because I didn’t instantly find the source of the NullPointerException. Obviously there are reasons for the way it is. So would it at least be an option to transform the current comment into JavaDoc?

<cite>@pspeed said:</cite> Coming at it from the other direction... what did you expect to happen with a Picture that had nothing set on it?

Well, I have been using name-less Spatials and haven’t encountered any issues “so far”. But following your suggestion I’ll abandon that practice.

Thanks again!

Hi,
I had the same problem yesterday - and I couldn’t see why one must set a name - nodes work too, without having a name. But I also understand why we need an empty constructor. So here is a very simple idea and I think everyone could live with it. What about adding a small JavaDoc-Note to empty constructors “Only for serialization” or so.

With this thread I figured out how to fix my stuff ^^ thanks.

Most do have this… for the ones that don’t people can feel free to submit PRs. But note that on some objects (like Node) an empty constructor is fine. Picture is a very ugly class and must have its parameters defined up front I guess. (I don’t recommend using it, personally, and I wish it could go away. It hides exactly the wrong stuff from users and provides little benefit.)

We could also modify the serialization code to deal properly with protected constructors and modify the “constructors that are only for serialization” to be protected. I already did this with SpirderMonkey serialization because I got tired of having nasty public constructors all over the place for my game code.

Alright. Thanks for your answer. One funny thing is - you said it’s fine for nodes - but in Node JavaDoc it says “Don’t use - only for serialization” :smiley:
Nevermind. Simply mentioning it in the wiki would suffice I think.

It was probably cut and pasted. There is no reason to require names on a spatial at all. You can pass null to them and they are fine. Since Node’s only non-empty constructor takes nothing but a name (which can be null as already mentioned) then it is reasonable that the empty constructor is fine.

Note: nameless spatials are just fine. Pictureless Pictures are not.

1 Like

The issue wasn’t pictureless pictures but nameless pictures. In my case though.

I think you are mistaken… but since I can’t see your error or your code, I can’t comment further.

…but looking at the source, Picture doesn’t use the name for anything… neither does its superclass or its superclass’s superclass.

Edit: Ah… but you DO have to call one of the real constructors because Picture is a really stupid class.

Actually, just better not to use Picture at all. It’s a horrible class… look at its constructor:

    public Picture(String name, boolean flipY){
        super(name, new Quad(1, 1, flipY));
        setQueueBucket(Bucket.Gui);
        setCullHint(CullHint.Never);
    }

Whole lot of bad in there.