Java копирование буферизованной проблемы с производительностью изображения - PullRequest
4 голосов
/ 01 ноября 2011

он чел!

я пишу игру. так как со временем ничего не меняется, я перешел к буферизации частей доски (на которой игра ведется) и просто копирую ее время от времени. Я меняю контент на переднем плане, поэтому мне все еще нужен высокий fps. Я также хочу увеличить масштаб, и вот тут начинается самое интересное: для экономии памяти я снова использую буферы. Всякий раз, когда я масштабирую приложение, оно отстает, а затем работает нормально.

После профилирования я пришел с двумя убийцами производительности:

  • очистка заднего буфера (4000x4000 пикселей, занимает около 29 мс. Для сохранения прозрачности я использую g.fillRect)

  • Копирование буфера обратно в реальное изображение (которое, конечно, не является живым, но снова из getBufferStrategy ()). Это займет 300 мс, в следующий раз около 150, а затем, начиная с третьего кадра, будет работать плавно.

Чтобы уточнить, где проблема может быть немного кода. Я создаю свои собственные буферы следующим образом:

GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice device = env.getDefaultScreenDevice();
GraphicsConfiguration config = device.getDefaultConfiguration();
image = config.createCompatibleImage(width, height,Transparency.TRANSLUCENT);

А теперь та часть, где я копирую буфер в образ. Обратите внимание, что мне нужно вырезать некоторые части буфера, поэтому я пошел на вызов максимального параметра.

g.drawImage(image, vs.boardOffsetX, vs.boardOffsetY, targetWidth, targetHeight, 0, 0, sourceWidth, sourceHeight, null);

Наконец, для моей другой проблемы: я очищаю изображения следующим образом:

Graphics2D g = (Graphics2D) image.getGraphics();
Color transparent = new Color(0, 0, 0, 0);
g.setColor(transparent);
g.setComposite(AlphaComposite.Src);
g.fillRect(0, 0, image.getWidth(null), image.getHeight(null));

спасибо большое! застрял на этом довольно долго. И не стесняйтесь давать мне стилистический совет относительно моего подхода: это моя первая честная попытка в графике.

Спасибо!

edit: Часть, которую я действительно не понимаю, состоит в том, что та же самая операция занимает совсем другое количество раз. когда работает только AWT-Thread, кроме моей нити, я получаю два раза ~ 300 мс, а затем до 10 мкс !!!! и это ужасно быстро для копирования 16 миллионов пикселей. Кто-нибудь понимает этот эффект? а может знает способ «предварительно оптимизировать» это поведение?

Ответы [ 2 ]

2 голосов
/ 02 ноября 2011

Возможно, вас заинтересует, что я не смог решить проблему. Вместо этого я отменил последний шаг масштабирования, ограничив размер самого большого буфера размером 2000x2000 и устранив наихудшую часть проблемы. Масштабирование теперь происходит довольно плавно (я измерил 80 мс для первого вызова drawImage. Это все еще довольно много, но, поскольку вид меняется быстро, вы его не замечаете).

В своем исследовании я также обнаружил, что не могу явно заставить java создавать ускоренные VolatileImage требуемого размера. Это могло быть проблемой - бог знает почему. Я все еще хотел бы узнать, хотя ...

Но, чтобы дать людям с аналогичными проблемами еще одно последнее слово: кругосветное плавание.

спасибо за вашу помощь!

1 голос
/ 01 ноября 2011

Не знаю, поможет ли это вам, но мое приложение копируется немного быстрее с System.arraycopy () .

BufferedImage tmp = (BufferedImage) img;
int[] src = ((DataBufferInt) tmp.getRaster().getDataBuffer()).getData();
int[] dst = ((DataBufferInt) bi.getRaster().getDataBuffer()).getData();
System.arraycopy(src, 0, dst, 0, dst.length);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...