Here is a snippet of code that generates a thumbnail from a given file. It works well, but is much slower than desired. Without using an external library (which I'm trying to avoid for learning purposes), is there anything that can be done to increase the speed?
I know the fastest way would be to retrieve the stored thumbnail. I've looked into reading for any EXIF thumbnail data by parsing out the embedded information, but gave up since it was taking me a lot of effort with no finished end result. Again, I'd prefer not to rely on a library specifically because I want to learn more about the format itself.
I know many will state right away I shouldn't be messing with EXIF data unless I use an external library, so as an alternative, what can be done specifically with this snippet to make things (significantly) faster?
Feel free to give me feedback about my coding style as well, except for the use of JavaDoc comments.
class ThumbIcon extends ImageIcon implements Runnable {
public int thumbWidth;
public int thumbHeight;
Image image;
Graphics2D g2dBuffer;
ThumbButton parent;
BufferedImage scaledImage;
public ThumbIcon(final ThumbButton theParent) {
super();
parent = theParent;
} // End ThumbIcon(ThumbButton, String)
public void run() {
image = Toolkit.getDefaultToolkit().getImage(filePath);
final MediaTracker tracker = new MediaTracker(new Container());
tracker.addImage(image, 0);
try {
tracker.waitForID(0);
} catch (InterruptedException e) {
System.out.println("Interrupted getting thumb");
} // End try
// Get dimensions from the now-loaded image
final int width = image.getWidth(null);
final int height = image.getHeight(null);
// Use the width to determine if the image is legitimate and loaded
// Limit importable images to <54MiB or <51.5MP (9000px x 6000px)
if ((width > 0) && (width * height < 54000000)) {
// This is an actual image, so display on screen
// Set the thumbnail size depending on image orientation
// We are assuming a square thumbnail
if (width > height) { // Landscape
thumbWidth = THUMBS_SIZE;
thumbHeight = (int)((double)height / (double)width * THUMBS_SIZE);
} else { // Portrait
thumbWidth = (int)((double)width / (double)height * THUMBS_SIZE);
thumbHeight = THUMBS_SIZE;
} // End if
scaledImage = new BufferedImage(thumbWidth, thumbHeight,
BufferedImage.TYPE_INT_RGB);
// Simultaneously load image into g2d buffer and scale to desired size
g2dBuffer = scaledImage.createGraphics();
g2dBuffer.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
//g2dBuffer.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
// RenderingHints.VALUE_ANTIALIAS_ON);
// Size image (no matter initial size) to destWidth x destHeight
g2dBuffer.drawImage(image, 0, 0, thumbWidth, thumbHeight, null);
...
// Create the thumbnail
setImage(Toolkit.getDefaultToolkit().createImage(scaledImage.getSource()));
scaledImage.flush();
image.flush();
//g2dBuffer.finalize();
g2dBuffer = null;
} else {
...
} // End if
} // End run()
...
} // End ThumbIcon
I shaved off some time by disabling anti-aliasing. It looks nasty, but it serves its purpose.
image.getScaledInstance(thumbWidth, thumbHeight, Image.SCALE_FAST);
? \$\endgroup\$