I’m trying to load a texture from a java.awt.Image, and then apply it on a surface (let’s start simple : a flat rectangle).
I made a simple example so that you get my problem :
here is a link to an example image of the java.awt.Image I would like to put on a texture (a white backgound with 3 black rectangles in 3 corners) : Image
Here is the code (actually some others objects are generated, I am focusing on the one that doesn’t work) :
// Geometry, Material
Vector3f[] pos = new Vector3f[4];
pos[0] = new Vector3f(0, 0, 0);
pos[1] = new Vector3f(10, 0, 0);
pos[2] = new Vector3f(10, 10, 0);
pos[3] = new Vector3f(0, 10, 0);
Vector2f[] texCoord = new Vector2f[4];
texCoord[0] = new Vector2f(0, 0);
texCoord[1] = new Vector2f(1, 0);
texCoord[2] = new Vector2f(1, 1);
texCoord[3] = new Vector2f(0, 1);
Geometry geo = new Geometry(“BgTest”, mesh);
Material mat = new Material(
getAssetManager(),
“Common/MatDefs/Misc/Unshaded.j3md”);
geo.setMaterial(mat);
parentNode.attachChild(geo);
// [For this example] Loading the image from the file I described above
BufferedImage bi = ImageIO.read(new File(“PathToFile\BG.jpg”));
// Applying the image as a Texture to the object
Image image = new AWTLoader().load(bi, false);
Texture texture = new Texture2D(image);
mat.setTexture(“ColorMap”, texture);
And here is the result :
It looks like there is an “weird offset” when the texture reads the image data, but as far as I looked, I couldn’t find out why…
I tried with other images (varying type (grayscale image, color image), dimensions…), and it rarely works (the applied texture looks like the original JPG file), and most often doesn’t work (the offset is present, and varies : the angle of the blocks aren’t always the same).
After having spent one day on the matter, I decided to ask you all : do you have any idea why I have that kind of “offset” ?
Thanks a lot !
It isn’t the same result as my first image, because I have the flip option of AWTLoader to false, in my first example.
I then tried to run my first code again with the flip option to true, and it produces exactly the same result :
// [For this example] Loading the image from the file I described above
BufferedImage bi = ImageIO.read(new File(“PathToFile\BG.jpg”));
// Applying the image as a Texture to the object
Image image = new AWTLoader().load(bi, true);
ImageIO does not seem to be the cause of my issue…
(actually, I hadn’t much hope since my code in the first post is inspired from the Quad class file)
Here is the code :
Mesh mesh = new Quad(100, 50);
Geometry geo = new Geometry(“BgTest”, mesh);
Material mat = new Material(
getAssetManager(),
“Common/MatDefs/Misc/Unshaded.j3md”);
geo.setMaterial(mat);
parentNode.attachChild(geo);
// [For this example] Loading the image from the file I described above
BufferedImage bi = ImageIO.read(new File(“PathToFile\BG.jpg”));
// Applying the image as a Texture to the object
Image image = new AWTLoader().load(bi, false);
Texture texture = new Texture2D(image);
mat.setTexture(“ColorMap”, texture);
Mesh mesh = new Quad(100, 50);
Geometry geo = new Geometry(“BgTest”, mesh);
Material mat = new Material(
getAssetManager(),
“Common/MatDefs/Misc/Unshaded.j3md”);
geo.setMaterial(mat);
parentNode.attachChild(geo);
// [For this example] Loading the image from the file I described above
Texture texture = this.getAssetManager().loadTexture("BG.jpg")
mat.setTexture(“ColorMap”, texture);
I’m afraid I can’t change the image I’m trying to display : I’m getting the AWT Image as is (actually the image isn’t read from disk, but directly generated in Java).
My goal is then to put it on a surface in JMonkeyEngine. It turns out I have the same problem with an image loaded from disk, hence the questions above.
I’m pretty sure that I could understand my initial problem (pure Java) by solving this new one (image from file).
OK I’ll explain the full story then. I’m connecting images loaded in ImageJ (ImageJ) to a 3D view in JMonkeyEngine.
In ImageJ, every 3D image is an ImagePlus, which itself is made of several ImageProcessor, containing the 2D slices of the image. I’m working with a specific type of ImageProcessor called ShortProcessor, containing a 16-bit unsigned 2D image.
This ImageProcessor class has a getBufferedImage method, that returns the image as a BufferedImage. That is the real way I’m getting the BufferedImage.
If I write the BufferedImage to disk, and then open it with ImageJ, or any image viewer (like the Windows one), it works fine, I see my picture as it should be.
However, transferring the BufferedImage to JMonkeyEngine produces the kind of weird images I showed above, with the “offset impression”.
The actual code is :
Mesh mesh = new Quad(100, 50);
Geometry geo = new Geometry(“BgTest”, mesh);
Material mat = new Material(
getAssetManager(),
“Common/MatDefs/Misc/Unshaded.j3md”);
geo.setMaterial(mat);
parentNode.attachChild(geo);
// Getting the current displayed ImageProcessor in IJ
BufferedImage bi = IJ.getImage().getProcessor().getBufferedImage();
// Applying the image as a Texture to the object
Image image = new AWTLoader().load(bi, false);
Texture texture = new Texture2D(image);
mat.setTexture(“ColorMap”, texture);
In my first post, I didn’t want to bother you with the ImageJ part, I used ImageIO.write(bi, "jpg", new File("BG.jpg")); to write my ImageJ processor down to disk and then loaded it from disk.
I’ve got something new, that shifts the problem from a texture problem to another topic, I think…
Some context to start : I’m integrating JMonkeyEngine to an existing frame in Swing. I used the “Swing integration” tutorial. In all my previous posts, I was thinking I was doing something wrong with the way I was using textures.
After discussing with you, I understood it might be something else. So I decided to create the simpliest possible code, and created a SimpleApplication displaying a Quad with my example texture… And it worked fine !
I then added the Swing integration, and it went back wrong.
Here is the whole code I tested (and the texture file here); put the inSwing boolean to false, and the texture will be displayed all right; put it to true, and it fails :
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeCanvasContext;
import com.jme3.texture.Texture;
public class TestTexture extends SimpleApplication {
public static void main(String[] args) {
/*
* JMonkeyEngine as an independant program if false, or integrated
* to a Swing frame if true
*/
boolean inSwing = true;
TestTexture app = new TestTexture();
if (inSwing) {
AppSettings settings = new AppSettings(true);
settings.setWidth(640);
settings.setHeight(480);
app.setSettings(settings);
app.createCanvas();
JmeCanvasContext ctx = (JmeCanvasContext) app.getContext();
ctx.setSystemListener(app);
Dimension dim = new Dimension(640, 480);
ctx.getCanvas().setPreferredSize(dim);
JFrame window = new JFrame("Texture");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new FlowLayout());
panel.add(ctx.getCanvas());
window.add(panel);
window.pack();
window.setVisible(true);
app.startCanvas();
} else {
app.start();
}
}
@Override
public void simpleInitApp() {
/*
* Just a quad with the texture applied on it
*/
Quad q = new Quad(5, 10);
Geometry geom = new Geometry("Plane", q);
Material mat = new Material(this.assetManager,
"Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.White);
Texture texture = this.getAssetManager().loadTexture("BG.png");
mat.setTexture("ColorMap", texture);
geom.setMaterial(mat);
this.rootNode.attachChild(geom);
}
}
Have you already seen something like this ? I tried some searches with “JMonkeyEngine swing texture”, but haven’t found anything useful yet.
I’ve found another way but it is far from the perfect solution regarding what I wanted to do : I’m just using JMonkeyEngine in its standard way, with an external frame, and no integration in my Swing canvas.
I’m still interested in solutions or ideas you might have.