[Solved] Unable to produce file with writeImageFile

Hello,

I’ve been stuck for more than an hour on this “basic” issue but I can’t figure it out. I’m writing a function to output a texture file that I will generate. I see that I am able to modify the file passed in argument (i put an image in it initially), but at the end, it has a size 0. I assume that the texture file passed in argument is correct since I can use it later on in the material of an object. What am I doing wrong?

     texture = assetManager.loadTexture("Textures/Atlas.png");
     img = texture.getImage();
    
    String path = "Textures/test.png";
    File f = new File(getClass().getClassLoader().getResource(path).getFile());
    try {        
        writeImageFile(f , img);
    } catch (Exception e) {
        System.out.println(e.getStackTrace());
    }

where the function is defined as

    protected  void writeImageFile( File file , Image img) throws IOException {
         OutputStream outStream = new FileOutputStream(file);
         try {
             JmeSystem.writeImageFile(outStream, "PNG", img.getData(0), img.getWidth(), img.getHeight());
         } finally {
             outStream.close();
         }
    } 

This is run inside the simpleInitApp(). I also tried running it inside the simpleUpdate(tpf) but the file is always empty

Thanks
Adrien

Not sure if this is going to work but try “png” instead of “PNG”.

Just did, same thing

Note that I took the function from another library so I assume the format is also correct

I tried with different formats, including “BMP”, Image.Format.RGBA8.toString() but it always outputs an empty file

“Every way I write this data that I don’t know what it is results in an empty file…”

next step… debug and look at the data to see if it’s sensible.

Edit: though the weird thing is that even for bad data you’d still get SOME file, I guess.

I know … I will look a bit more at the texture image that is returned. I’m also trying to implement an example of the screenshot appState from which I extracted the function to see if it’s an issue with my code or something else …

An aside…

…will print garbage. I think you probably want:
catch (Exception e) {
e.printStackTrace();
}

…not that it matters to your issue, really.

the img object definitely has what seems like consistent data, it has a width, a height, and the getDatat(0) contains a buffer with a lot of data. Not very familiar with the Image class but as far as I can understand, it looks legit

If it’s writing a file of 0 length then that implies an exception was thrown somewhere or the writeImageFile() returned immediately without even writing anything. Thus the only reason your file exists at all is because you created it and closed the stream. (ie: commenting out the JmeSystem.writeImageFile() line would give exactly the same result… as would throwing an exception in its place.)

Put System.out.println()s before and after that call. See if both show up.

Actually you were so right on the e.printStackTrace();

:slight_smile:

I get the following

    java.nio.BufferUnderflowException
    	at java.nio.DirectIntBufferU.get(DirectIntBufferU.java:271)
    	at java.nio.IntBuffer.get(IntBuffer.java:715)
    	at com.jme3.util.Screenshots.convertScreenShot2(Screenshots.java:50)
    	at com.jme3.system.JmeDesktopSystem.writeImageFile(JmeDesktopSystem.java:94)
    	at com.jme3.system.JmeSystem.writeImageFile(JmeSystem.java:137)
    	at Utils.AtlasGenerator.writeImageFile(AtlasGenerator.java:229)
    	at Utils.AtlasGenerator.simpleInitApp(AtlasGenerator.java:199)
    	at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:220)
    	at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:130)
    	at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:211)
    	at java.lang.Thread.run(Thread.java:745)

Which solution I’m trying to read from

writeImageFile is designed to write screenshots that have a specific format. It’s not designed for writing arbitrary images unfortunately

Ok, any suggestion to export the image itself? Should I search for regular java library functions? I will try some but let me know if you have a better solution

I’m trying to export the textures I’m generating in the billboard atlas

I think what you are doing should work in this case.

I believe that momoko_fan was maybe short-circuiting past this thread to suggest why your file might be empty… and also providing the information that this won’t work in all cases.

However, it will work in this one… or any of them where your raw data is predictable like this.

And at the risk of repeating myself, SimArboreal generates imposter atlas textures and even stores them with the tree. The code is on github if you want to poke at it.

It uses a different approach of storing the atlas embedded in the j3o of the tree, though.

This post may help you.

In both cases, make sure your buffers are rewound before writing them, I guess.

Solved with your class

@pspeed: Like you hinted, I realized that I missed DL the main SimArboreal project (I just had the editor piece) and I don’t have access to a good connection yet. And I’m unable to run the executable (seems it requires java 1.5 which I also need to DL) so unable to look at the examples yet

Repeating from the other thread:
java -jar TheNameOfTheExe.exe

…should work with any version of Java.

Ok, I was able to run it, and I see the binary has a way to generate precisely the renders and the normals to png files

Based on that I am looking at the class behind the atlasgeneration, it’s available at

Thanks @pspeed, and sorry it took me so much time

Is the issue solved, then?