Почему Java Graphics DrawImage в первый раз медленно - PullRequest
2 голосов
/ 18 апреля 2019

Я хочу смешать несколько изображений в java.awt.Graphics, поэтому я пишу утилиты для этого. Я нахожу, что так медленно звонить graphics.drawImage(); в первый раз это занимает 2 секунды. Я думаю, что нужно что-то инициализировать, и это очень медленно.

Итак, я запустил бенчмарк, чтобы найти причину, и я получил такой результат, я обнаружил, что вызов step3 в первый раз медленный, я нахожу, что каждый поток в первый раз будет медленным. Я буду продолжать идти.

StopWatch '0': running time (millis) = 1631
-----------------------------------------
ms     %     Task name
-----------------------------------------
00005  000%  create canvas
00095  006%  draw picture
00003  000%  step 1
00025  002%  step 2
01373  084%  step 3
00000  000%  step 4
00000  000%  step 5
00130  008%  save picture

StopWatch '2': running time (millis) = 1632
-----------------------------------------
ms     %     Task name
-----------------------------------------
00005  000%  create canvas
00093  006%  draw picture
00004  000%  step 1
00022  001%  step 2
01378  084%  step 3
00000  000%  step 4
00000  000%  step 5
00130  008%  save picture

StopWatch '1': running time (millis) = 1633
-----------------------------------------
ms     %     Task name
-----------------------------------------
00005  000%  create canvas
00095  006%  draw picture
00003  000%  step 1
00031  002%  step 2
01370  084%  step 3
00000  000%  step 4
00000  000%  step 5
00129  008%  save picture

StopWatch '1': running time (millis) = 115
-----------------------------------------
ms     %     Task name
-----------------------------------------
00001  001%  create canvas
00000  000%  draw picture
00000  000%  step 1
00005  004%  step 2
00000  000%  step 3
00000  000%  step 4
00000  000%  step 5
00109  095%  save picture

StopWatch '0': running time (millis) = 123
-----------------------------------------
ms     %     Task name
-----------------------------------------
00001  001%  create canvas
00000  000%  draw picture
00000  000%  step 1
00009  007%  step 2
00000  000%  step 3
00000  000%  step 4
00000  000%  step 5
00113  092%  save picture

StopWatch '2': running time (millis) = 127
-----------------------------------------
ms     %     Task name
-----------------------------------------
00001  001%  create canvas
00000  000%  draw picture
00000  000%  step 1
00014  011%  step 2
00000  000%  step 3
00000  000%  step 4
00000  000%  step 5
00112  088%  save picture

StopWatch '1': running time (millis) = 116
-----------------------------------------
ms     %     Task name
-----------------------------------------
00000  000%  create canvas
00001  001%  draw picture
00000  000%  step 1
00004  003%  step 2
00000  000%  step 3
00000  000%  step 4
00000  000%  step 5
00111  096%  save picture

StopWatch '0': running time (millis) = 113
-----------------------------------------
ms     %     Task name
-----------------------------------------
00001  001%  create canvas
00000  000%  draw picture
00001  001%  step 1
00004  004%  step 2
00000  000%  step 3
00000  000%  step 4
00000  000%  step 5
00107  095%  save picture

StopWatch '2': running time (millis) = 111
-----------------------------------------
ms     %     Task name
-----------------------------------------
00001  001%  create canvas
00000  000%  draw picture
00000  000%  step 1
00006  005%  step 2
00000  000%  step 3
00000  000%  step 4
00000  000%  step 5
00104  094%  save picture

Я проверял много раз, и результаты совпадают.

Мой контрольный код:

import java.awt.Color;
import java.awt.Font;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import org.springframework.util.StopWatch;

public class ImageTest {

  static final Font roman = new Font("inherit", Font.PLAIN, 40);
  static final String basePath = "/Users/shiheng/Desktop/";

  public static void main(String[] args) throws Exception {
    final BufferedImage image = ImageIO.read(new File(basePath, "download.jpeg"));
    final BufferedImage overlay = ImageIO.read(new File(basePath, "images.jpeg"));
    List<Thread> threadList = new ArrayList<>();
    for (int i = 0; i < 3; i++) {
      final int id = i;
      Runnable runnable = () -> {
        try {
          for (int j = 0; j < 3; j++) {
            benchmark(id, j, basePath, image, overlay);
          }
        } catch (Exception e) {
          e.printStackTrace();
        }
      };
      Thread thread = new Thread(runnable);
      thread.start();
      threadList.add(thread);
    }
    for (Thread thread : threadList) {
      thread.join();
    }
  }

  static void mark(StopWatch stopWatch, String note) {
    if (stopWatch.isRunning()) {
      stopWatch.stop();
    }
    stopWatch.start(note);
  }

  static void benchmark(int id, int i, String basePath, BufferedImage image, BufferedImage overlay)
      throws Exception {
    StopWatch stopWatch = new StopWatch(String.valueOf(id));

    mark(stopWatch, "create canvas");
    int w = Math.max(image.getWidth(), overlay.getWidth());
    int h = Math.max(image.getHeight(), overlay.getHeight());
    BufferedImage combined = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);

    mark(stopWatch, "draw picture");
    int cw = overlay.getWidth() / 4 * 3;
    int ch = overlay.getHeight() / 4 * 3;
    ImageUtil imageUtil = ImageUtil.getInstance(combined);
    mark(stopWatch, "step 1");
    imageUtil.drawImage(image, i, i);
    mark(stopWatch, "step 2");
    imageUtil.drawImage(overlay.getScaledInstance(cw, ch, Image.SCALE_FAST), i, i);
    mark(stopWatch, "step 3");
    imageUtil.drawText("意大利炮!", 23 + i, 100 + i, roman, Color.PINK);
    mark(stopWatch, "step 4");
    imageUtil.drawText("意大利炮!", 29 + i, 100 + i, roman, Color.BLUE);
    mark(stopWatch, "step 5");
    imageUtil.drawText("意大利炮!", 26 + i, 100 + i, roman, Color.WHITE);

    mark(stopWatch, "save picture");
    ImageIO.write(combined, "PNG", new File(basePath, "combined.png"));
    stopWatch.stop();
    System.out.println(stopWatch.prettyPrint());
  }

}


Мой код утилиты:

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;

public class ImageUtil {

  private final Graphics graphics;
  private final BufferedImage canvas;

  private ImageUtil(BufferedImage canvas) {
    this.canvas = canvas;
    this.graphics = canvas.getGraphics();
  }

  public static ImageUtil getInstance(BufferedImage canvas) {
    return new ImageUtil(canvas);
  }

  public ImageUtil drawText(String text, int x, int y, Font font, Color color) {
    graphics.setFont(font);
    graphics.setColor(color);
    graphics.drawString(text, x, y);
    return this;
  }

  public ImageUtil drawImage(Image image, int x, int y) {
    graphics.drawImage(image, x, y, null);
    return this;
  }

}

Я хочу найти ресурс, который нужно инициализировать, чтобы я мог инициализировать его вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...