您可以将每个位图转换为Shape
(或多个),然后绘制Shape
。有关获得Shape
的过程,请参见平滑不规则路径。
例如
![500+ FPS?!?](https://istack.dev59.com/fjzLX.webp)
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import java.util.Random;
class ImageShape {
private BufferedImage image;
private BufferedImage ImageShape;
private Area areaOutline = null;
private JLabel labelOutline;
private JLabel output;
private BufferedImage anim;
private Random random = new Random();
private int count = 0;
private long time = System.currentTimeMillis();
private String rate = "";
public ImageShape(BufferedImage image) {
this.image = image;
}
public void drawOutline() {
if (areaOutline!=null) {
Graphics2D g = ImageShape.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0,0,ImageShape.getWidth(),ImageShape.getHeight());
g.setColor(Color.RED);
g.setClip(areaOutline);
g.fillRect(0,0,ImageShape.getWidth(),ImageShape.getHeight());
g.setColor(Color.BLACK);
g.setClip(null);
g.draw(areaOutline);
g.dispose();
}
}
public Area getOutline(Color target, BufferedImage bi) {
GeneralPath gp = new GeneralPath();
boolean cont = false;
int targetRGB = target.getRGB();
for (int xx=0; xx<bi.getWidth(); xx++) {
for (int yy=0; yy<bi.getHeight(); yy++) {
if (bi.getRGB(xx,yy)==targetRGB) {
if (cont) {
gp.lineTo(xx,yy);
gp.lineTo(xx,yy+1);
gp.lineTo(xx+1,yy+1);
gp.lineTo(xx+1,yy);
gp.lineTo(xx,yy);
} else {
gp.moveTo(xx,yy);
}
cont = true;
} else {
cont = false;
}
}
cont = false;
}
gp.closePath();
return new Area(gp);
}
public JPanel getGui() {
JPanel images = new JPanel(new GridLayout(1,2,2,2));
JPanel gui = new JPanel(new BorderLayout(3,3));
JPanel originalImage = new JPanel(new BorderLayout(2,2));
final JLabel originalLabel = new JLabel(new ImageIcon(image));
originalImage.add(originalLabel);
images.add(originalImage);
ImageShape = new BufferedImage(
image.getWidth(),
image.getHeight(),
BufferedImage.TYPE_INT_RGB
);
labelOutline = new JLabel(new ImageIcon(ImageShape));
images.add(labelOutline);
anim = new BufferedImage(
image.getWidth()*2,
image.getHeight()*2,
BufferedImage.TYPE_INT_RGB);
output = new JLabel(new ImageIcon(anim));
gui.add(output, BorderLayout.CENTER);
updateImages();
gui.add(images, BorderLayout.NORTH);
animate();
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
animate();
}
};
Timer timer = new Timer(1,al);
timer.start();
return gui;
}
private void updateImages() {
areaOutline = getOutline(Color.BLACK, image);
drawOutline();
}
private void animate() {
Graphics2D gr = anim.createGraphics();
gr.setColor(Color.BLUE);
gr.fillRect(0,0,anim.getWidth(),anim.getHeight());
count++;
if (count%100==0) {
long now = System.currentTimeMillis();
long duration = now-time;
double fraction = (double)duration/1000;
rate = "" + (double)100/fraction;
time = now;
}
gr.setColor(Color.WHITE);
gr.translate(0,0);
gr.drawString(rate, 20, 20);
int x = random.nextInt(image.getWidth());
int y = random.nextInt(image.getHeight());
gr.translate(x,y);
int r = 128+random.nextInt(127);
int g = 128+random.nextInt(127);
int b = 128+random.nextInt(127);
gr.setColor(new Color(r,g,b));
gr.draw(areaOutline);
gr.dispose();
output.repaint();
}
public static void main(String[] args) throws Exception {
int size = 150;
final BufferedImage outline = javax.imageio.ImageIO.read(new java.io.File("img.gif"));
ImageShape io = new ImageShape(outline);
JFrame f = new JFrame("Image Outline");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(io.getGui());
f.pack();
f.setResizable(false);
f.setLocationByPlatform(true);
f.setVisible(true);
}
}
我认为左上角蓝色图片中FPS计数器存在十倍误差。50 FPS还可以理解,但500 FPS则显得不对。