Going From Component to Buffered Image in headless environment.

Discussion in 'Java' started by Sandman, Jul 12, 2003.

  1. Sandman

    Sandman Guest

    Hello all,

    I've been working on this problem for about 2 days now. Here it is:
    I have a servlet programmed up that will operate in a headless environment.
    I'm using j2sdk1.4.2 and apache tomcat 4.1.24. I have x-windows installed
    on my linux server but it does not run all the time (only when i really need
    it). What i want my servlet to do is to create a JButton (or any swing
    Component--heavy or lightweight) and convert it to a Buffered Image and then
    output that image as a image/png. Here is the code that I have currently
    that works fine when I have x-windows running and isHeadless=false:


    package graphics;


    import java.io.*;

    import javax.servlet.*;
    import javax.servlet.http.*;

    import java.awt.*;
    import java.awt.image.*;
    import javax.imageio.*;

    import javax.swing.*;


    public class SwingGeneratorServlet extends HttpServlet
    {

    // this is the converter method. it throws the exception
    public static BufferedImage createImage(Component cmp) {
    Dimension d = cmp.getSize();
    d.setSize(100, 100);

    BufferedImage bi = new BufferedImage((int) d.getWidth(),
    (int) d.getHeight(),
    BufferedImage.TYPE_INT_RGB);
    Graphics2D g2d = bi.createGraphics();

    //temporary container
    JFrame jf = new JFrame();
    jf.getContentPane().add(cmp);
    jf.pack();

    SwingUtilities.paintComponent(g2d, cmp, jf.getContentPane(),
    0, 0, (int) d.getWidth(), (int)
    d.getHeight());
    return bi;
    }



    // this is the servlet's io method. it generates, converts, then
    outputs the image
    public void doGet(HttpServletRequest request,
    HttpServletResponse response)
    throws ServletException, IOException
    {
    JButton bu = new JButton("Swing Servlet");
    BufferedImage bi = createImage(bu);

    response.setContentType("image/png");
    ServletOutputStream out = response.getOutputStream();
    ImageIO.write(bi, "png", out);
    out.close();
    }



    // this just directs to doGet(...); nothing interesting here
    public void doPost(HttpServletRequest request,
    HttpServletResponse response)
    throws ServletException, IOException
    {
    doGet(request, response);
    }

    }



    Now, when isHeadless=true (regardless of whether I am running x-windows or
    not), an exception gets thrown:

    HTTP Status 500 -

    ----------------------------------------------------------------------------
    ----

    type Exception report

    message

    description The server encountered an internal error () that prevented it
    from fulfilling this request.

    exception

    java.awt.HeadlessException
    at java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:121)
    at java.awt.Window.(Window.java:274)
    at java.awt.Frame.(Frame.java:401)
    at java.awt.Frame.(Frame.java:366)
    at javax.swing.JFrame.(JFrame.java:154)
    at
    graphics.SwingGeneratorServlet.createImage(SwingGeneratorServlet.java:26)
    at graphics.SwingGeneratorServlet.doGet(SwingGeneratorServlet.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:740)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
    at
    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Application
    FilterChain.java:247)
    at
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterCh
    ain.java:193)
    at
    org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.ja
    va:256)
    at
    org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
    eNext(StandardPipeline.java:643)
    at
    org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
    at
    org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.ja
    va:191)
    at
    org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
    eNext(StandardPipeline.java:643)
    at
    org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
    at
    org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2415)
    at
    org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180
    )
    at
    org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
    eNext(StandardPipeline.java:643)
    at
    org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.
    java:171)
    at
    org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
    eNext(StandardPipeline.java:641)
    at
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172
    )
    at
    org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
    eNext(StandardPipeline.java:641)
    at
    org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
    at
    org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java
    :174)
    at
    org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
    eNext(StandardPipeline.java:643)
    at
    org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
    at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:223)
    at
    org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:594)
    at
    org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConne
    ction(Http11Protocol.java:392)
    at
    org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:565)
    at
    org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.jav
    a:619)
    at java.lang.Thread.run(Thread.java:534)


    ----------------------------------------------------------------------------
    ----

    Apache Tomcat/4.1.24

    This is to be expected, since Sun's new additions to 1.4.1 specify that the
    isHeadless() check will be done on all heavyweight Components that do not
    have lightweight peers (the last part of that statement I only somewhat
    understand). Now, I have looked into many suggestions (such as the PJA
    Toolkit -- which doesn't support java 1.4.2), but none have worked. My
    thinking is that if Sun is going to add a special case for Java programmers
    who wish to generate images in a headless environment, then they should've
    also made a way for Java programmers who wish to generate images from Swing
    components (such as realtime charts and graphs) in a headless environment.
    I know of no such way, though. And while I have given it the old college
    try for the past two-three days, I have yielded no results. Is there
    anybody that can connect the dots for me? Show me the way to bypass the
    HeadlessException problem and generate a BufferedImage out of a Component?
    In this case, code is the best explanation--I've already reviewed the java
    tutorials, the sdk specs, the javadocs, and many websites that talk about it
    in general. It's the specifics that I am having trouble with.

    THANKS TO ALL WHO HELP IN ANY WAY.
    --sandman
     
    Sandman, Jul 12, 2003
    #1
    1. Advertising

  2. You cannot use a heavyweight component such as a JFrame in a headless
    environment. Use a lightweight component instead such as a JPanel.
    You must explicitly call "addNotify()" on the component to get it to
    render: e.g.

    (I call this in the event dispatch thread via
    SwingUtilities.invokeAndWait())

    JPanel panel = new JPanel();
    panel.addNotify();
    panel.setOpaque(true);
    panel.setDoubleBuffered(false); // for better performance
    // add your subcomponents here via panel.add(whatever);

    Later on, I call this, again in the event dispatch thread:

    public static BufferedImage componentToBufferedImage(JComponent
    component,
    Dimension dim) throws IOException {

    BufferedImage backBuffer = new BufferedImage (dim.width,
    dim.height, BufferedImage.TYPE_INT_ARGB);
    Graphics g = backBuffer.createGraphics();

    // g.setColor(java.awt.Color.white); // if want a white bg
    g.fillRect(0, 0, dim.width, dim.height);
    g.setClip(0, 0, dim.width, dim.height);
    component.validate(); // this might not be necessary
    component.printAll(g); // this might not be necessary
    return backBuffer;

    } // end componentToBufferedImage method


    Later, I call this method which uses the Acme GIF package (I call it
    outside the event dispatch thread and I haven't had problems so far):

    public static byte[] imageToGif(BufferedImage backBuffer)
    throws IOException {

    ByteArrayOutputStream byteStream = new ByteArrayOutputStream();

    encoder.GifEncoder ge = new encoder.GifEncoder(backBuffer,
    byteStream);
    ge.encode();
    byte [] gifBytes = byteStream.toByteArray();
    byteStream.close();

    // this assumes we are done using this BufferedImage
    Graphics g = backBuffer.getGraphics();
    if (g != null) g.dispose();

    return (gifBytes);

    } // end imageToGif method



    This works for me to render my Swing components in my headless servlet
    (which I translate into BufferedImages and then to GIFs to send to a
    browser).

    Hope this helps,
    Lynn


    "Sandman" <> wrote in message news:<bep6je$4v4$>...
    > Hello all,
    >
    > I've been working on this problem for about 2 days now. Here it is:
    > I have a servlet programmed up that will operate in a headless environment.
    > I'm using j2sdk1.4.2 and apache tomcat 4.1.24. I have x-windows installed
    > on my linux server but it does not run all the time (only when i really need
    > it). What i want my servlet to do is to create a JButton (or any swing
    > Component--heavy or lightweight) and convert it to a Buffered Image and then
    > output that image as a image/png. Here is the code that I have currently
    > that works fine when I have x-windows running and isHeadless=false:
    >
    >
     
    Lynn Robinson, Jul 14, 2003
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. tochaotic4u
    Replies:
    2
    Views:
    4,096
    tochaotic4u
    Jul 3, 2003
  2. Marco Schmidt
    Replies:
    2
    Views:
    448
    Marco Schmidt
    Sep 4, 2003
  3. Andres Medina
    Replies:
    3
    Views:
    5,265
    Mark Scott
    Nov 11, 2004
  4. Replies:
    9
    Views:
    719
    Michael Wojcik
    Aug 23, 2005
  5. Ex1991

    Image to Buffered Image?

    Ex1991, Mar 25, 2009, in forum: Java
    Replies:
    0
    Views:
    383
    Ex1991
    Mar 25, 2009
Loading...

Share This Page