简体   繁体   English

Java:最快的文字绘制方法?

[英]Java: Fastest way to draw text?

I'm trying to write a program that just creates an image out of text (eg write "hello" on a white square and store the image), which sounds simple but it must be done quickly. 我正在尝试编写一个仅用文本创建图像的程序(例如,在白色正方形上写“ hello”并存储图像),这听起来很简单,但是必须尽快完成。 I tried the Java2D library but drawing onto a BufferedImage takes ~2 seconds to just draw the image, not even save or display it. 我尝试了Java2D库,但是绘制到BufferedImage上只需要2秒钟即可绘制图像,甚至不保存或显示图像。 I also tried Java-based CAPTCHA generators but they take much too long (5 seconds). 我还尝试了基于Java的CAPTCHA生成器,但是它们花费的时间太长(5秒)。

This seems like simple enough task to just draw text, but I'm frustrated that I can't do this faster than 2 seconds. 这看起来很简单,只需要绘制文本即可,但是令我沮丧的是我不能快于2秒。

Is there a way I can do this faster on my machine by some command line options (eg allocating more memory or priority)? 有什么办法可以通过某些命令行选项(例如分配更多的内存或优先级)在我的计算机上更快地完成此操作? Is there a particular Java library I ought to use, or some weird quirk to Java2D I should be aware of to make things faster? 有没有我应该使用的特定Java库,或者我应该意识到对Java2D的一些怪异的怪癖才能使事情变得更快?

This is my entire program. 这是我的整个程序。 I run this in Eclipse: 我在Eclipse中运行此命令:

import java.awt.*;
import java.awt.image.BufferedImage;

public class SimpleGraphics {
    public static void main(String[] args) {
        long time = System.currentTimeMillis();

        String message = "Hello world";
        int width = 100;
        int height = 100;
        BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);

        Graphics2D graphics = img.createGraphics();
        graphics.setColor(Color.black);
        graphics.setFont(new Font("TimesRoman", Font.BOLD, 12));

        FontMetrics fontMetrics = graphics.getFontMetrics();
        int stringWidth = fontMetrics.stringWidth(message);
        int stringHeight = fontMetrics.getAscent();

        graphics.drawString(message, (width - stringWidth) / 2, height / 2 + stringHeight / 4);
        System.out.println(System.currentTimeMillis() - time); //consistently ~2 seconds
    }
}

I run my code from the command line (using JDK8 on Windows 7) and I get around 300ms. 我从命令行运行代码(在Windows 7上使用JDK8),大约需要300毫秒。

I modified your code to the following: 我将您的代码修改为以下内容:

import java.awt.*;
import java.awt.image.BufferedImage;

public class SimpleGraphics {
    public static void main(String[] args) {
        long time = System.currentTimeMillis();

        for (int i = 0; i < 100; i++)
            createImage();

        System.out.println(System.currentTimeMillis() - time); //consistently ~2 seconds
    }

    public static void createImage()
    {
        String message = "Hello world";
        int width = 100;
        int height = 100;
        BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);

        Graphics2D graphics = img.createGraphics();
        graphics.setColor(Color.black);
        graphics.setFont(new Font("TimesRoman", Font.BOLD, 12));

        FontMetrics fontMetrics = graphics.getFontMetrics();
        int stringWidth = fontMetrics.stringWidth(message);
        int stringHeight = fontMetrics.getAscent();

        graphics.drawString(message, (width - stringWidth) / 2, height / 2 + stringHeight / 4);
    }
}

I still get around 300ms. 我仍然有300毫秒左右的时间。

So the problem is not with the painting code. 因此,问题不在于绘画代码。

I don't know why you get 2 seconds, but there is obviously some overhead to loading the class. 我不知道为什么会花2秒,但是加载类显然有一些开销。 So all I can suggest is to do your image creation in batches to minimize the time. 因此,我只能建议分批创建映像,以最大程度地减少时间。

Timing each line individually gives a big jump at fontMetrics - so there is your culprit. 对每一行单独计时会极大地提高fontMetrics的效率-因此有罪魁祸首。 I dont know if other measuring classes (lineMetrics) will give you shorter time 我不知道其他测量类别(lineMetrics)是否会缩短您的时间

import java.awt.*;
import java.awt.image.BufferedImage;

public class SimpleGraphics {
public static void main(String[] args) {
    long time = System.currentTimeMillis();

    String message = "Hello world";
    int width = 100;
    int height = 100;
    BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
    System.out.println(System.currentTimeMillis() - time); //consistently ~2 seconds

    Graphics2D graphics = img.createGraphics();
    graphics.setColor(Color.black);
    graphics.setFont(new Font("TimesRoman", Font.BOLD, 12));
    System.out.println("1 "+(System.currentTimeMillis() - time)); //consistently ~2 seconds

    FontMetrics fontMetrics = graphics.getFontMetrics();
    System.out.println("2 "+(System.currentTimeMillis() - time)); //consistently ~2 seconds
    int stringWidth = fontMetrics.stringWidth(message);
    System.out.println("3 "+(System.currentTimeMillis() - time)); //consistently ~2 seconds
    int stringHeight = fontMetrics.getAscent();
    System.out.println(System.currentTimeMillis() - time); //consistently ~2 seconds

    graphics.drawString(message, (width - stringWidth) / 2, height / 2 + stringHeight / 4);
    System.out.println(System.currentTimeMillis() - time); //consistently ~2 seconds
}
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM