JME - Rendering in BufferedImage

Status
Nicht offen für weitere Antworten.

Zapp_Branigan

Aktives Mitglied
Hallo ich hoffe hier ist jemand der sich mit der jmonkeyengine auskennt - im ofiziellen englischen Forum wurde mir leider nicht so richtig weiter geholfen...

Mit Mühe habe ich es geschaft eine Landschaft so auf den Bildschirm zu rendern wie ich es für mein kleines Projekt wollte. Problem: Eigentlich will ich die Landschaft nicht auf meinem Bildschirm sondern möglichst in einem BufferedImage das ich dann weiter verarbeiten kann...

Ich denke ich habe in den tiefen der JME-Wiki auch schon einen =offscreenrenderer] Ansatz gefunden aber den bekomme ich nicht so recht zum laufen und spätestens hier:

Code:
ImageData imgData = new ImageData(width, height, 32, new PaletteData(0xFF0000, 0x00FF00, 0x0000FF));
for (int x = 0; x < width; x++) {
    for (int y = 0; y < height; y++) {
        imgData.setPixel(x, y, buffer.get((height - y - 1) * width + x));
    }
}
org.eclipse.swt.graphics.Image image = new Image (org.eclipse.swt.widgets.Display.getCurrent(), imgData);

Verstehe ich nicht mehr was das soll... ich Programmiere in Netbeans und nicht in Eclipse und es kommt sowiso kein BufferedImage raus...

Ich hoffe wirklich wirklich sehr das hier irgendjemand ist der sich die Mühe macht mir ein bisschen zu helfen!
 

EgonOlsen

Bekanntes Mitglied
JME nutzt doch auch LWJGL, oder? Dann kannst du mit einem direkten GL-Aufruf arbeiten. Ich habe jetzt keine Zeit, das komplett zu bauen, aber du erzeugst dir ein BufferedImage in der gewünschte n Größe, lässt dir davon die Pixel als int[] geben:

Code:
BufferedImage output = new BufferedImage(x, y, BufferedImage.TYPE_INT_ARGB);
int[] pixels = ((DataBufferInt) (output.getRaster().getDataBuffer()).getData();

Dann den aktuellen Bildschirminhalt über GL holen:

Code:
IntBuffer pixelBuf = ByteBuffer.allocateDirect((x*y)<<2).order(ByteOrder.nativeOrder()).asIntBuffer();
GL11.glReadPixels(0, 0, x, y, GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, pixelBuf);

Dann vom Buffer in das BI kopieren:

Code:
for (int i = 0; i < pixels.length; i++) {
	pixels[i] = pixelBuf.get(i);
}

Evtl. musst du das BI noch irgendwie spiegeln oder so...musst du mal gucken. Aber irgendwie so sollte es gehen, sofern JME nicht selber eine entsprechende Funktionalität mitbringt. Weiß ich aber nicht, ich benutze das logischerweise nicht.
 

Illuvatar

Top Contributor
Der Codeausschnitt, mit dem du Probleme hast, ist auch in SWT geschrieben. Für ein BufferedImage probier mal:

Code:
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
for (int x = 0; x < width; x++) { 
    for (int y = 0; y < height; y++) { 
        img.setRGB (x, y, buffer.get((height - y - 1) * width + x)); 
    } 
}
 

Zapp_Branigan

Aktives Mitglied
Es hat sich leider doch noch ein Problem ergeben und ich finde den Fehler nicht :-(
Die Landschaft wird auf dem Bildschirm richtig angezeigt, aber die exportierte Landschaft bleibt schwarz.
Ich vermute es liegt daran das das "Bild" nicht fertig erzeugt ist bevor das Bild gemacht wird. Es kann aber genauso gut ein Fehler in der Programmierung sein.
Ich habe echt keine Ahnung wie ich das Lösen kann :-( daher hoffe ich sehr ihr könnt mir wieder helfen.


Hier ist mein Code - ich weiß er ist bestimmt ganz fürchterlich geschrieben, aber ich kanns nocht nicht besser.
Code:
import com.jme.app.SimpleGame;
import com.jme.renderer.ColorRGBA;
import com.jmex.terrain.TerrainBlock;
import com.jmex.terrain.util.ImageBasedHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;
import com.jme.math.Vector3f;
import com.jme.bounding.BoundingBox;
import com.jme.scene.state.TextureState;
import com.jme.util.TextureManager;
import com.jme.image.Texture;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.*;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;

public class Engine extends SimpleGame  {

   
    public static void main(String[] args) {
        Engine app = new Engine();
        
        app.start();
       
        
    }
    
    protected void simpleInitGame() {

        cam.setParallelProjection(true);
        float aspect = (float) display.getWidth() / display.getHeight();
        cam.setFrustum( -100, 1000, -50 * aspect, 50 * aspect, -50, 50 );
        cam.setLocation(new Vector3f(0, 0,0)); 
        cam.setDirection(new Vector3f(-1, -1, -1));
        cam.update();
  
        display.getRenderer().setBackgroundColor(ColorRGBA.white);
      
        complexTerrain();
        
        
        saveImageFile();
        //System.exit(0);
    
}
    
    public void saveImageFile()
            {
        
        int width = 1024; int height = 768;
       
        
        IntBuffer pixelBuf =    ByteBuffer.allocateDirect((width*height)<<2).order(ByteOrder.nativeOrder()).asIntBuffer(); 
        GL11.glReadPixels(0, 0, width, height, GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, pixelBuf);


        BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
        for (int x = 0; x < width; x++) { 
        for (int y = 0; y < height; y++) { 
        img.setRGB (x, y, pixelBuf.get((height - y - 1) * width + x)); 
            } 
        } 
   
        
        
         
        System.out.println(img.toString());
             String filename = "map//MapPattern_Test.jpg";

	 try
             {
                System.out.println("Schreibe Pattern Datei: "+filename);
                OutputStream out = new BufferedOutputStream(new FileOutputStream(filename));
		ImageIO.write(img, "jpeg", out);
             }
	 catch(IOException e)
	    {
		System.out.println("Fehler beim schreiben der Pattern-Datei: "+filename);
	    }
    }

    /**
     * 
     * Läd ein Bild (jpeg) als Buffered Image und konvertiert es anschließend in Byte Code
     * @param Path
     * @return
     */
    byte[] loadImageFile(String Path)
    {
        
        String formatName = "jpeg"; //gif...
        
        File imageFile = new File (Path);
        BufferedImage image = null;
         
			try {
                            System.out.println("Wird eingelesen...");
		    	image = ImageIO.read(imageFile);
				}
                        
                        catch (IOException e) {
                            System.out.println("Fehler beim Einlesen der Datei \""+Path+"\"");
				}

        System.out.println("File \""+Path+"\" eingelesen");
                                
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        
        BufferedImage smallImage = image.getSubimage(0, 0, 50, 50);
    //    BufferedImage smallImage = image;
        
        try
        {
            ImageIO.write(smallImage, formatName, baos);
        } 
        catch (IOException ex)
        {
            Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, null, ex);
            System.out.println("Fehler beim Konvertieren der Bilddatei!");
        }
       
        byte[] imageData = baos.toByteArray();
        
        return imageData;
    }
    
    private void complexTerrain() {
        // This grayscale image will be our terrain
       
        // Create an image height map based on the gray scale of our image.
        ImageBasedHeightMap ib = new ImageBasedHeightMap(
              
                  
              
                 new ImageIcon(loadImageFile("TestLandscape.jpg")).getImage()
                  
                  );
        
        // Create a terrain block from the image's grey scale
        TerrainBlock tb = new TerrainBlock("image icon", ib.getSize(),
                new Vector3f(.5f, .05f, .5f), ib.getHeightMap(),
                
                new Vector3f(0, 0, 0), false);
        // Create an object to generate textured terrain from the
        // image based height map.
        ProceduralTextureGenerator pg = new ProceduralTextureGenerator(ib);
        // Look like water from height 0-60 with the strongest
        // "water look" at 30
        pg.addTexture(new ImageIcon(loadImageFile("textures"+File.separator+"textures"+File.separator+"wl_wasser_01.jpg")), 0, 30, 60);
        // Look like dirt from height 40-120 with the strongest
        // "dirt look" at 80
        pg.addTexture(new ImageIcon(loadImageFile("textures"+File.separator+"textures"+File.separator+"wl_wiese1_00.jpg")), 40, 80, 120); // Look like highest (pure white) from height 110-256
        // with the strongest "white look" at 130

        pg.addTexture(new ImageIcon(loadImageFile("textures"+File.separator+"textures"+File.separator+"wl_wiese4_00.jpg")), 110, 130, 256);
        // Tell pg to create a texture from the ImageIcon's it has recieved.
        pg.createTexture(256);
        TextureState ts = display.getRenderer().createTextureState();
        
        
        // Load the texture and assign it.
        ts.setTexture(
                TextureManager.loadTexture(
                pg.getImageIcon().getImage(),
                Texture.MM_LINEAR_LINEAR,
                Texture.FM_LINEAR,
                true));
        tb.setRenderState(ts);
        // Give the terrain a bounding box
        tb.setModelBound(new BoundingBox());
        tb.updateModelBound();
        // Move the terrain in front of the camera
       // tb.setLocalTranslation(new Vector3f(0, 0, 75));
         tb.setLocalTranslation(new Vector3f(0, 0, 0));
        
        // Attach the terrain to our rootNode.
        rootNode.attachChild(tb);
        
    }

}
 

Illuvatar

Top Contributor
Ich kenn mich mit dem SimpleGame nicht so aus weil ich normal StandardGame verwende, aber es gibt doch in jedem Spiel eigentlich immer update und render-Methoden. Die werden für jedes Frame aus dem OpenGL-Thread aufgerufen und können den Scene Graph verändern bzw. zeichnen. In der init-Methode läuft der OGL-Thread doch glaub noch gar nicht, also wird auch noch nichts dargestellt. Wahrscheinlich wäre es das sinnvollste, das Bild am Ende der render-Methode zu machen. Du musst nur eben aufpassen, dass du das Bild nur einmal machst, nicht in jedem Frame.
 

Zapp_Branigan

Aktives Mitglied
leider macht das aus dem schwarzen hintergrund nur einen roten
;-) ich habe auch alle anderen Typs mal getestet - hilft nicht.
 

EgonOlsen

Bekanntes Mitglied
So schlecht ist rot doch gar nicht. Vielleicht sind die Farbwerte nur vertauscht. Wie sieht denn die Fläche in dem Fall aus? Wieder komplett weiß?
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
E Rendering order auf einem ismetrischen Grid Spiele- und Multimedia-Programmierung 8
T Game-Rendering Spiele- und Multimedia-Programmierung 5
T Java3D Rendering Problem Spiele- und Multimedia-Programmierung 7
E Active Rendering im FSEM auf ein JPanel? Spiele- und Multimedia-Programmierung 4
Steev Software Rendering Spiele- und Multimedia-Programmierung 3
S Spline Rendering? Spiele- und Multimedia-Programmierung 4
R Offscreen Rendering Spiele- und Multimedia-Programmierung 2
B BufferedImage Position Spiele- und Multimedia-Programmierung 8
B BufferStrategy zu BufferedImage? Irgendwie? Spiele- und Multimedia-Programmierung 2
D getsubimage aus BufferedImage und Rueckwandlung in ein ImagePlus bild Spiele- und Multimedia-Programmierung 0
V BufferedImage[] aus anderer Classe auslesen Spiele- und Multimedia-Programmierung 2
F [JMyron] Bild von int[] zu BufferedImage Spiele- und Multimedia-Programmierung 2
Q BufferedImage vs. Heap Space ‒ Warum wird der Speicher nicht freigegeben? Spiele- und Multimedia-Programmierung 6
M Performance Problem bei BufferedImage Spiele- und Multimedia-Programmierung 7
R BufferedImage > Integer.MAX_VALUE Spiele- und Multimedia-Programmierung 9
M Pixel eines BufferedImage bearbeiten (Performance) Spiele- und Multimedia-Programmierung 23
G BufferedImage -> Farbe wechselt willkürlich Spiele- und Multimedia-Programmierung 15
P int-Array zu BufferedImage (performance?) Spiele- und Multimedia-Programmierung 14
agentone BufferedImage transparent löschen Spiele- und Multimedia-Programmierung 12
radiac Stringtext mit BufferedImage Textur. Spiele- und Multimedia-Programmierung 6
kowa BufferedImage und Antialias Spiele- und Multimedia-Programmierung 2
T BufferedImage#setRGB #getRGB zu langsam Spiele- und Multimedia-Programmierung 4
J Zeichnen in BufferedImage und dieses in Datei speichern Spiele- und Multimedia-Programmierung 2
A Image in BufferedImage konvertieren Spiele- und Multimedia-Programmierung 2
Z Transparenz in BufferedImage Spiele- und Multimedia-Programmierung 8
A Bildbereich als BufferedImage Spiele- und Multimedia-Programmierung 3
M BufferedImage blass machen Spiele- und Multimedia-Programmierung 5
Lulumann6 BufferedImage in VolatileImage casten Spiele- und Multimedia-Programmierung 10
F BufferedImage verursacht OutOfMemoryError Spiele- und Multimedia-Programmierung 11
P Rotation von BufferedImage (Affine Transformation) Spiele- und Multimedia-Programmierung 7
S Image to BufferedImage Spiele- und Multimedia-Programmierung 3

Ähnliche Java Themen

Neue Themen


Oben