使用java绘制JFrame和jpeg

时间:2014-02-02 00:54:43

标签: java jframe bufferedimage

所以,我碰到了一堵墙。我试图抓取JFrame的内容或整个JFrame转换为或将其绘制到BufferedImage然后将该图像写入jpeg文件。我得到了写入文件位才能正常工作。麻烦的是我找不到一种方法可以让我在没有一些奇怪问题的情况下获取JFrame的内容。

我尝试使用机器人但是出现了大量问题,例如导致程序挂起而alpha图层无法正常工作。

我发现似乎表现出最大希望的方法并没有改善。它不会导致我的程序挂起,但不幸的是,当我使用此方法获取JFrame的内容时,生成的图像与JFrame的大小相同,但只包含一个灰色面板,顶部有25个像素的黑色边框,所有其他方面都有3个像素。这对应于JFrame本身的边界大小。

我想知道是否与BufferStrategy有关。或者我可能只得到JFrame的后窗格,在这种情况下我需要知道如何抓住前面或整个东西。但实际上我不知道从哪里开始,我从搜索得到的大部分结果都是将图像放入JFrame而不是将JFrame转换为图像。

我尽可能地减少了我写的文件,并将在那里发布。

现在可行了,有一些奇怪的怪癖从它的众多修订中挥之不去

import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Scanner;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;

public class Window extends JFrame {

    private static final long serialVersionUID = 1L;
    private BufferStrategy graphicBuffer;
    int frame = 0;

    public static void main(String[] cats) {
        new Window("Testing", 600, 400);
    }

    public Window(String title, int sizeX, int sizeY) {
        setTitle(title);
        setSize(sizeX, sizeY);

        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setResizable(false);
        this.setUndecorated(false);
        this.setVisible(true);

        System.out.print("New Input: ");
        Scanner scanner = new Scanner(System.in);
        scanner.nextLine();
        String input = scanner.nextLine();

        while (scanner.hasNext()) {
            input = scanner.next();
            if (input.equals("end")) {
                scanner.close();
                break;
            } else {
                System.out.println("Working " + input);
                render();
                System.out.print("New Input: ");
            }
        }
        System.out.println("End of Loop");
    }

    public void render(boolean toImg)
    {
        if( toImg ){
            renderToImage();
        } else {
            renderToScreen();
        }
    }

    public void render() {
        if (graphicBuffer == null) {
            createBufferStrategy(3);
            graphicBuffer = getBufferStrategy();
        }
        Graphics g = graphicBuffer.getDrawGraphics();
        Graphics2D g2 = (Graphics2D) g;

        Rectangle bounds = g2.getDeviceConfiguration().getBounds();
        int h = (int) bounds.getHeight();
        int w = (int) bounds.getWidth();

        Insets insets = this.getInsets();
        int t = insets.top;
        int l = insets.right;
        int r = insets.left;
        int b = insets.bottom;

        int areaW = w - (l + r);
        int areaH = h - (t + b);

        g2.setColor(new Color(100, 0, 0));
        g2.fillRect(0, 0, w, h);

        flicker(g2, l, t, areaW, areaH);

        g2.dispose();
        g.dispose();
        graphicBuffer.show();

        grabFrame();
    }

    public void renderToImage( ) 
    {
        frame++;
        if (graphicBuffer == null) {
            createBufferStrategy(3);
            graphicBuffer = getBufferStrategy();
        }

        Rectangle bounds = this.getBounds();
        int h = (int) bounds.getHeight();
        int w = (int) bounds.getWidth();

        BufferedImage image = new BufferedImage( this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB );
        Graphics g = image.getGraphics();
        Graphics2D g2 = (Graphics2D) g;

        Insets insets = this.getInsets();
        int t = insets.top;
        int l = insets.right;
        int r = insets.left;
        int b = insets.bottom;

        int areaW = w - (l + r);
        int areaH = h - (t + b);

        g2.setColor(new Color(100, 0, 0));
        g2.fillRect(0, 0, w, h);

        flicker(g2, l, t, areaW, areaH);

        g2.dispose();
        g.dispose();
        g = graphicBuffer.getDrawGraphics();
        g2 = (Graphics2D) g;
        g2.drawImage( image, 0, 0, null );
        g2.dispose();
        g.dispose();
        graphicBuffer.show();

        testPrintToJpeg( image, frame );
    }

    public void testPrintToJpeg(BufferedImage frame, int frNum) {
        try {
            String userHome = System.getProperty("user.home");
            File outputFile = new File(userHome + "/Desktop/JavaOutput/EOL" + frNum + ".jpg");

            if (outputFile.getParentFile().mkdirs()) {
                System.out.println("[FrameToFile] Missing Folders Probably Added");
            }

            IIOImage outputImage = new IIOImage(frame, null, null);

            ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next();
            writer.setOutput(new FileImageOutputStream(outputFile));
            ImageWriteParam writeParam = writer.getDefaultWriteParam();
            writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            writeParam.setCompressionQuality(1.0f);
            writer.write(null, outputImage, writeParam);

        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Fail at Image Writer");
        }
    }
}

1 个答案:

答案 0 :(得分:0)

在grabFrame中,您调用内容窗格组件的paint方法,要求它将自己绘制到图像的图形上下文中。但是内容窗格上没有任何内容,这是一个单独的组件。您的渲染方法忽略内容窗格并直接绘制到框架。

第二个问题是,即使您调用了框架的paint方法,paint方法也会忽略提供的图形上下文,而是绘制到缓冲区策略中。图像既不知道也不关心这种情况发生过。帧的缓冲策略与图像无关。

要绘制到图像,您必须使用图像的图形上下文而不是缓冲策略中的图形上下文。