我正在开发一个涉及检索大量图像以用作图标的Java项目。以前,我有一个包含大量单个.png文件的文件夹 - 这个工作得相当好,但占用了大量空间并且相当难以处理。相反,我尝试编写一个类,允许我从一个更大的文件中提取ImageIcon格式的缩放图块。
花了一段时间,但我设法使用PixelGrabber和BufferedImage.setRGB()方法,使用我在Stack Overflow上找到的引用。你可以看到下面的课程(它可能会在某些地方使用一些改进):
/**
* Java tile grabbing class: Create ImageIcons from coordinates out of an image
*
* @author Protractor Ninja
* @version 1.00 2011/2/21
*/
import javax.swing.ImageIcon;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
import java.awt.image.ImageObserver;
import java.awt.Image;
import java.io.File;
import java.lang.Exception;
import javax.swing.*;
import java.awt.image.WritableRaster;
import java.util.*;
public class TileGrabber {
private BufferedImage image;
private File imageFile;
private PixelGrabber grabber;
private int tileWidth;
private int tileHeight;
private int[] pixels;
/*
* Creates a tile grabber object using a filepath and tile heights.
* Tiles should start at zero pixels.
*/
public TileGrabber(String path, int tWidth, int tHeight) {
try {
image = ImageIO.read(this.getClass().getResourceAsStream("/" + path.replaceAll("^/", "")));
pixels = new int[tWidth*tHeight];
tileWidth = tWidth;
tileHeight = tHeight;
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* Same as before, but uses an already-created BufferedImage file.
*/
public TileGrabber(BufferedImage img, int tWidth, int tHeight) {
try {
image = img;
pixels = new int[tWidth*tHeight];
tileWidth = tWidth;
tileHeight = tHeight;
} catch (Exception e) {
e.printStackTrace();
}
}
public void setImagePath(String path) {
try {
image = ImageIO.read(this.getClass().getResourceAsStream("/" + path.replaceAll("^/", "")));
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* Creates an ImageIcon object from tile coordinates on an image.
*/
public ImageIcon grabTile(int x, int y, int scale) {
x = x*tileWidth;
y = y*tileHeight;
grabber = new PixelGrabber(image, x, y, tileWidth, tileHeight, pixels, 0, tileWidth);
try {
grabber.grabPixels();
} catch (Exception e) {
e.printStackTrace();
}
Image i = getImageFromArray(pixels, tileWidth, tileHeight).getScaledInstance(tileWidth*scale, tileHeight*scale, Image.SCALE_FAST);
return new ImageIcon(i);
}
/*
* Creates an Image from an array of pixels and specified heights.
* Retrieved and modified from a stackoverflow.com question
*/
public Image getImageFromArray(int[] pixels, int width, int height) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
image.setRGB(0,0,width,height,pixels,0, width);
return image;
}
/**
* For testing purposes.
*/
public static void main(String[] args) {
JFrame window = new JFrame("Hello, this is a test");
window.setBounds(0,0,550,500);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TileGrabber grabber = new TileGrabber("terrain.png", 16, 16);
JLabel label = new JLabel(grabber.grabTile(12,8,5));
window.getContentPane().add(label);
window.setVisible(true);
}
}
唯一的问题是,启动过程中的主要延迟是加载所有图标时发生的延迟,而我真的不确定如何让它更快 - 我真的很想让它变得如此用户不必等待很长时间才能启动程序。
我有什么方法可以改进我的代码,或者,是否有另一种更快的方法来做我正在尝试做的事情?
非常感谢你的时间。
答案 0 :(得分:1)
您是否通过分析器运行代码以尝试查明缓慢的来源?我知道这不是一个直接有用的答案,但是如果没有分析就试图跟踪性能问题会浪费很多时间。
可能有帮助的替代机制是延迟获取图像直到需要它们,显然如果您需要程序启动时的所有图像,这将无济于事。
答案 1 :(得分:0)
由于您已经有BufferedImage
,因此您可能会看到getSubimage()
是否更快。
附录:这是一个example,可以让您使用现有的复合材料进行测试。