Предположим, у меня есть BufferedImage типа TYPE_4BYTE_ABGR
в Swing, и я хочу нарисовать только его часть. Например, я хотел бы рисовать только левую половину или какую-то треугольную форму или что-то более сложное.Как эффективно нарисовать подчасти изображения в Swing
Причина в том, что окончательное изображение должно быть составлено из частей отдельных изображений, которые у меня есть.
Каков наилучший способ сделать это?
Я бы предпочел определить многоугольник, а затем использовать эту форму в качестве маски для рисования, если это возможно.
Моя текущая идея: сделайте копию отдельного изображения и сделайте все пиксели за пределами желаемой формы прозрачными, затем нарисуйте все изображение. Я думаю, что это может сработать, но может быть слишком медленным с копированием и всеми.
редактировать:
Я проверил решение Гийома и обнаружил, что она работает и не очень замедлит картину. Использование клипа привело к увеличению времени рисования с 14 мс до 35 мс, но эти времена очень неточно. Я использовал профилирование EDT от here. Вот код.
import java.awt.AWTEvent;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
*
*/
public class ClipTilesTest {
// tile size and number of tiles in each row/column
private static int TILE_SIZE = 100;
private static int TILE_NUM = 6;
// taken from https://stackoverflow.com/questions/5541493/how-do-i-profile-the-edt-in-java-swing
public static class TimedEventQueue extends EventQueue {
@Override
protected void dispatchEvent(AWTEvent event) {
long startNano = System.nanoTime();
super.dispatchEvent(event);
long endNano = System.nanoTime();
if (endNano - startNano > 5000000) {
System.out.println(((endNano - startNano)/1000000) + "ms : " + event);
}
}
}
private static void initUI() {
Toolkit.getDefaultToolkit().getSystemEventQueue().push(new TimedEventQueue());
// download image
BufferedImage image;
try {
image = ImageIO.read(new URL("http://download.chip.eu//ii/163859211_4b28e1e687.jpg"));
} catch (IOException ex) {
ex.printStackTrace();
return;
}
// take out small chunk
final BufferedImage tile = image.getSubimage(0, 0, TILE_SIZE, TILE_SIZE);
JFrame frame = new JFrame();
frame.setTitle(ClipTilesTest.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// the panel containing some tiles
JPanel view = new JPanel() {
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
for (int i = 0; i < TILE_NUM; i++) {
for (int j = 0; j < TILE_NUM; j++) {
// version 1
/*
g2d.setClip(i * TILE_SIZE, j * TILE_SIZE , (i+1)*TILE_SIZE, (j+1)*TILE_SIZE);
g2d.drawImage(tile, i * TILE_SIZE, j * TILE_SIZE, null);
*/
// version 2
g2d.setClip(i * TILE_SIZE, j * TILE_SIZE , i*TILE_SIZE + TILE_SIZE/2, (j+1)*TILE_SIZE);
g2d.drawImage(tile, i * TILE_SIZE, j * TILE_SIZE, null);
g2d.setClip(i * TILE_SIZE + TILE_SIZE/2, j * TILE_SIZE , (i+1)*TILE_SIZE , (j+1)*TILE_SIZE);
g2d.drawImage(tile, i * TILE_SIZE, j * TILE_SIZE, null);
}
}
}
};
view.setPreferredSize(new Dimension(TILE_SIZE * TILE_NUM, TILE_SIZE * TILE_NUM));
// add, pack, set visible
frame.add(view);
frame.pack();
frame.setVisible(true);
// now make a repaint event, so we can start measuring
view.repaint();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
ClipTilesTest.initUI();
}
});
}
}
ты пытался getSubimage (заметьте, что я никогда не использовал) – mKorbel
нет, но может быть полезно в сочетании с другими вещами, чтобы получить непрямоугольные подразделы – Trilarion
В этом [примере] (http://stackoverflow.com/a/3078354/230513) используется 'getSubimage()', который «Возвращает субимость, определенную указанной прямоугольной областью». – trashgod