如何提高抓砖课程的速度?
我正在开发一个 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);
}
}
唯一的问题是,启动期间的主要延迟是加载所有图标时发生的延迟,我不太确定如何使其更快 - 我真的很想让用户不必等待很长时间来启动程序。
有什么方法可以改进我拥有的代码,或者是否有替代的、更快的方法来完成我正在尝试做的事情?
非常感谢您抽出时间。
I'm working on a Java project that involves retrieving a large amount of images for use as icons. Previously, I had a folder containing a large amount of individual .png files - this worked fairly well, but took up a lot of space and was fairly difficult to deal with. Instead, I tried to write a class that would allow me to extract a scaled tile in an ImageIcon format from one larger file.
It took a while, but I managed to make it work using a PixelGrabber and the BufferedImage.setRGB() method, using references that I found here on Stack Overflow. You can see the class below (it's likely that it could use some improvement in places):
/**
* 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);
}
}
The only problem is, the primary delay during startup is the delay that happens when all of the icons are being loaded, and I'm not really sure how to make it faster - I'd really like to make it so that the user won't have to wait very long for the program to start.
Is there any way I could improve the code I have, or, is there an alternate, faster method of doing what I'm attempting to do?
Many thanks for your time.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您是否通过分析器运行代码来尝试找出缓慢的根源?我知道这不是一个立即有用的答案,但尝试在不进行分析的情况下跟踪性能问题可能会浪费大量时间。
另一种可能有帮助的机制是延迟获取图像,直到需要它们为止,显然,如果您需要程序启动时的所有图像,这将无济于事。
Have you run the code through a profiler to try and pinpoint the source of the slowness? Not an immediately helpful answer I know but trying to track performance issues without profiling can waste an awful lot of time.
An alternative mechanism that might help would be to delay getting the images until they are needed, obviously this won't help if you need all images from program startup.
由于您已经有一个 BufferedImage,您可能会看到是否
getSubimage()
更快。附录:这里有一个示例,可以让您使用现有的组合进行测试。
As you already have a
BufferedImage
, you might see ifgetSubimage()
is any faster.Addendum: Here's an example that might let you test with your existing composite.