Alex
Alex

Reputation: 87

generating an image in java

for background of my question, I am working with COMSOL, a finite element software, which you can run with java without ever opening the software. Because of this, I am trying to couple it with another software written in java and run in Eclipse. My problem is having COMSOL generate an image file, say on my desktop of a 2D simulation. The code for exporting a *.txt file is almost identical and works, but it does not work for images and I wanted to see if someone could help get me thinking of where to look to figure out how to accomplish this.

I have attached ## snippets of code that I think explain enough of what I am trying to do without bogging all of you down.

import com.comsol.model.*;
import com.comsol.model.util.*;

/** Model exported on Jul 24 2012, 13:33 by COMSOL 4.2.1.110. */
public class COMSOL_Model {

  public static Model run() {
    Model model = ModelUtil.create("Model");

    //code to set up and solve the model
    // and then at the end, you tell COMSOL what to export...


        //this code works...
        model.result("pg1").feature("glob1").set("data", "dset"+i);
    model.result().export("plot1").set("filename",  C:\\Users\\Alex\\Desktop\\temp_data_"+i+".txt");
    model.result().export("plot1").run();


       //this code does NOT work
    model.result("pg2").feature("surf1").set("data", "dset"+i);
    model.result("pg2").set("window", "window"+i);
    model.result("pg2").run();
    model.result().export().create("img"+i, "Image2D");
    model.result("pg2").set("window", "graphics");
    model.result("pg2").set("windowtitle", "");
    model.result().export("img"+i)
         .set("pngfilename", "C:\\Users\\Alex\\Desktop\\surface.png");
    model.result().export("img1").run();

So my first question is, can someone maybe explain why, theoretically or with code as to why this does not work? I'm guessing because I would need a special method like "ImageIO.write". Any hints or thoughts would be greatly appreciated.

I tried getting around this by COMSOL provides code to create a GUI that shows the progress of the simulation and then prints, for example, a 2D/3D image on the GUI. I have used this in a big 'for' loop where java creates a GUI and a new plot for each iteration. The problem is, I can get java to copy the frame and progress bar and everything of the GUI except the picture that is printed on it and I wanted to see if anyone had any suggestions. My one idea was have java take a screenshot but and then crop the image. Any thoughts?

The following is most of the code with comments where I thought was necessary:

import com.comsol.model.*;
import com.comsol.model.util.*;
import com.comsol.modelguiswing.SwingGraphicsPanel;
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.*;


public class reuse_solver {

//paste this into configurations
//C:\Program Files\COMSOL\COMSOL42a\lib\win64

private Model model;

public static void main(String[] args) {
    reuse_solver recycler= new reuse_solver();
    recycler.init();
    recycler.looper();
}

public void looper() {
    model = original.run();
    for (int iSimul = 1; iSimul<5; iSimul++){
            start(iSimul);
        }
    }

   //this is the code to have eclipse run comsol    
private void init() {
    ModelUtil.initStandalone(true);     
}

private void start(int iSimul) {

    if (iSimul==1){     
        Progress(iSimul);
        synchronized(model){
            try {
                model.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            }
    }else{
        Studier(iSimul);
        Progress(iSimul);
        synchronized(model){
            try {
                model.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            }
        }
}

/this creates the GUI and then runs COMSOL, showing the progress
private void Progress(int i){
    final String sol = "sol"+i;
    final int k = i;
    lookandfeel();
    final JFrame frame = new JFrame("This is an example GUI for Frying");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(1000, 730);
    final JPanel mainPanel = new JPanel();
    frame.getContentPane().add(mainPanel);
    mainPanel.setLayout(new BorderLayout());
    final SwingGraphicsPanel graphicsPanel = new SwingGraphicsPanel("window"+i, "Window"+i);
    mainPanel.add(graphicsPanel, BorderLayout.CENTER);
    SwingProgressPanel progressPanel =new SwingProgressPanel();
    mainPanel.add(progressPanel, BorderLayout.PAGE_END);
    progressPanel.updateProgressLog("Starting\n"+i+"\n");
    ProgressWorker.setContext(new SwingDemoProgressContext(progressPanel)); 
    final int pWidth = frame.getWidth();
    final int pHeight = frame.getHeight();
    frame.setVisible(true);

    ProgressWorker.run(new Runnable() {
        public void run() {
            model.sol(sol).feature().create("t1","PlotWhileSolving");
            model.sol(sol).runAll();

            exporter(k, pHeight, pWidth, frame);    

        }

    });



}

//code to help COMSOL run in a loop
private void Studier(int i) {
    //COMSOL code goes here     
}

private void exporter(int i, int pHeight, int pWidth, JFrame frame) {

            //this code will tell java to put the image in the GUI window once the simulation is done

            model.result("pg2").feature("surf1").set("data", "dset"+i);
    model.result("pg2").set("window", "window"+i);
    model.result("pg2").run();

    // this will generate an image on my desktop, but it will not put the image that was put in the GUI

    BufferedImage bi = new BufferedImage(pWidth,pHeight, BufferedImage.TYPE_INT_RGB); 
    Graphics g = bi.createGraphics();
    frame.paint(g);  //this == JComponent
    g.dispose();
    try{ImageIO.write(bi,"png",new File("C:\\Users\\Alex\\Desktop\\surf_"+i+".png"));}catch (Exception e) {}

    synchronized(model){
        model.notify();
    }
}   

private void lookandfeel() {
    try {
    UIManager.setLookAndFeel(
    UIManager.getSystemLookAndFeelClassName());
    }
    catch (Exception e) {
    }
    }
}   

Upvotes: 0

Views: 1810

Answers (2)

Eph
Eph

Reputation: 1321

COMSOL uses the graphics window to create images for export. When COMSOL is started in standalone mode the graphics engine is not loaded in a way that allows exports. However, it is possible to get around this issue while running COMSOL from Java by using the client server model instead of using the standalone version and enabling graphics on the server instance.

Here's some code that I use to run from the COMSOL desktop or by calling the java directly.

public static void main(String[] args) throws IOException {
    String tag1 = System.getProperty("cs.currentmodel");
    if (tag1 == null) {
        // ModelUtil.initStandalone(true);
        ModelUtil.connect();
        ModelUtil.showProgress(false);
        model = ModelUtil.load("ModelTag", args[0]);
        run();
        ModelUtil.clear();
        ModelUtil.disconnect();
        System.exit(0);
    }
    else {
        model = ModelUtil.model(tag1);
        run();
    }
}

Then you can start the COMSOL server using the graphics option:

comsolserver -graphics

This will allow your export to work. I'm sure there's a way to start the COMSOL server instance in java, but I didn't have to do that for my project.

Upvotes: 0

Andrew Thompson
Andrew Thompson

Reputation: 168825

See ComponentImageCapture.java to capture an image of a Swing component. That code apparently has problems with AWT components.

In that case use the Robot to capture the image, but capture only the area of the component, rather than the entire screen.

Upvotes: 1

Related Questions