Patch for ImageJ that fixes a HeadlessException error

Posted by Victor Petrov on
URL: http://imagej.273.s1.nabble.com/Patch-for-ImageJ-that-fixes-a-HeadlessException-error-tp3698809.html

Dear all,

I would like to submit a patch that corrects ImageJ's behavior when running
in headless mode (i.e. with java -Djava.awt.headless=true).

Symptoms:
   When operating in headless mode ( i.e. java - Djava.awt.headless=true-jar
MyConverter.jar ), ImageJ is unable to perform a successful call to
ij.processor.ImageProcessor.drawString() because drawString() calls the
setupFrame() function, which in turn attempts to instanciate a
java.awt.Frame object.
This attempt results in a HeadlessException error being thrown by the
java.awt.Frame constructor (there isn't much sense for Java to create a
frame if a display server is not present, so it throws an exception error).
The mistake here is that functions that do image manipulation, like
drawString(), and do not require the ImageJ GUI, should not call
setupFrame() if Java is running in headless mode.

Solution:
   The only reason drawString() calls setupFrame() is to create valid Font
and FontMetrics objects, and the only reason setupFrame() creates a Frame
object is to get a Graphics object that is used to create the FontMetrics
object. If it were possible to get the Graphics object from a different
source, not java.awt.Frame, then there would be no need to create the Frame.
And thus, I have modified the setupFrame() function to use a BufferedImage
object, only in case the java.awt.headless property is true.
Below is a modified version of the setupFrame() function, contained in
ij.process.ImageProcessor.java (revision 1.37v):

-------------- v.137v ----------------------
private void setupFrame() {

        if (System.getProperty("java.awt.headless").equalsIgnoreCase("true"))

        {
            if (image==null)
                image=new BufferedImage(img.getWidth(null),img.getHeight
(null),BufferedImage.TYPE_INT_RGB);

            if (font==null)
                font = new Font("SansSerif", Font.PLAIN, 12);
            if (fontMetrics==null)
            {
                Graphics g=image.getGraphics();
                fontMetrics=g.getFontMetrics(font);
            }
            return;
        }
        if (frame==null) {
            frame = new Frame();
            frame.pack();
            frame.setBackground(Color.white);
        }
        if (font==null)
            font = new Font("SansSerif", Font.PLAIN, 12);
        if (fontMetrics==null) {
            frame.setFont(font);
            fontMetrics = frame.getFontMetrics(font);
        }
    }
----------------------------------------------------------

I have attached the modified source code of ImageProcessor.java.

Conclusion:
   This approach allowed us, the developers at the Center for Brain Science
and Neuroimaging at Harvard, to continue using our image viewer/converter on
Linux computers that do not have the X server installed.
Currently, we are forced to maintain a separate version of ImageJ that
incorporates the changes explained above.
We would like this fix to be applied by the ImageJ maintainers, or, at
least, for the setupFrame() problem to be resolved, so that we could use new
versions of ImageJ in the future, without worrying about modifying and
rebuilding from source.

Sincerely,
Victor Petrov

ImageProcessor.java.txt (66K) Download Attachment