Crop an Image object to create smaller images from it...
Hi all,
I am trying to figure out which one of the following 2 methods of loading several images will be faster, or is it going to be the same...
1. Load 50 PNGs in 50 Image object (an array of Images), or
2. Load 1 large PNG (which has all these 50 objects/ regions) and then use CropImageFilter to create smaller image objects out of the ONE PNG loaded.
The only difference I see is, instead of storing 50 files in my resources folder I will store just one file...
Also, is there a way to load this ONE big PNG into an Image obj (say imgObj) and then draw only a part of this imgObj, say x,y - 10, 10 width, height 30,30?
Its kinda confusing but I'd appreciate any ideas/ comments/ suggestions..
Thanks!
[755 byte] By [
insomniaca] at [2007-11-26 21:07:50]

# 1
is there a way to load this ONE big PNG into an Image obj (say imgObj) and then draw only a part of this imgObj, say x,y - 10, 10 width, height 30,30?
To take any part of an image and draw it anywhere on a component? Yes.
Here's an attempt at showing two ways of doing this.
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class ClippedDrawing {
private JPanel getContent() {
BufferedImage image = makeImage();
ClippedDrawingPanel cdp = new ClippedDrawingPanel(image);
// Display components at their preferredSize.
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5,5,5,5);
panel.add(new JLabel(new ImageIcon(image)), gbc);
panel.add(cdp, gbc);
return panel;
}
private BufferedImage makeImage() {
int w = 240;
int h = 240;
int type = BufferedImage.TYPE_INT_RGB;
BufferedImage image = new BufferedImage(w, h, type);
Graphics2D g2 = image.createGraphics();
g2.setPaint(new GradientPaint(0, 0, new Color(200,220,200),
w, h, new Color(240,200,220)));
g2.fillRect(0,0,w,h);
int size = 8;
int inc = w/size;
System.out.println("inc = " + inc);
g2.setPaint(Color.blue);
for(int j = 0, y = inc; j < size; j++, y+=inc)
g2.drawLine(0,y,w,y);
for(int j = 0, x = inc; j < size; j++, x+=inc)
g2.drawLine(x,0,x,h);
Font font = g2.getFont().deriveFont(14f);
g2.setFont(font);
FontRenderContext frc = g2.getFontRenderContext();
g2.setPaint(Color.red);
for(int j = 0; j < size; j++) {
for(int k = 0; k < size; k++) {
String s = String.valueOf(j*size + k+1);
float width = (float)font.getStringBounds(s, frc).getWidth();
LineMetrics lm = font.getLineMetrics(s, frc);
float height = lm.getAscent() + lm.getDescent();
float x = k*inc + (inc - width)/2;
float y = j*inc + (inc + height)/2 - lm.getDescent();
g2.drawString(s, x, y);
}
}
g2.dispose();
return image;
}
public static void main(String[] args) {
ClippedDrawing test = new ClippedDrawing();
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(test.getContent());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class ClippedDrawingPanel extends JPanel {
BufferedImage image;
Rectangle clip;
public ClippedDrawingPanel(BufferedImage image) {
this.image = image;
clip = new Rectangle(50, 50);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
int w = getWidth();
int h = getHeight();
// Save the original clip for later.
Shape origClip = g2.getClip();
// Mark the boundry of this component.
g2.setPaint(Color.magenta);
g2.draw(new Rectangle(0,0,w-1,h-1));
//// Technique 1: manipulate the clip and the image ////
// Draw the rectangular section [x, y, 50, 50] of image.
// Choose an arbitrary location in the image:
int x = 40;
int y = 60;
// Locate this section at clipX, clipY on this component.
// We can render this small image section anywhere we want
// within this component. Choose an arbitrary location:
int clipX = (w - clip.width)/2;
int clipY = 25;
// Move clip to this location. The image section specified above
// will be rendered at this location in this component.
clip.setLocation(clipX, clipY);
// Set the clip to restrict the next drawing operation.
g2.setClip(clip);
// Move the image so that our selected section appears
// in the clip set in this components coordinate system.
// Comment out the setClip call above and un-comment the
// draw(clip) call below to see this.
double tx = clipX - x;
double ty = clipY - y;
AffineTransform at = AffineTransform.getTranslateInstance(tx, ty);
g2.drawRenderedImage(image, at);
//g2.draw(clip);
// Reset the clip to its original value.
g2.setClip(origClip);
//// Technique 2: use a subimage ////
// Draw the rectangular section [x, y, 50, 50] of image.
// Choose an arbitrary location in the image:
x = 150;
y = 120;
// Reuse clip for obtaining the subImage
// which will be drawn on this component.
clip.setLocation(x, y);
BufferedImage subImage = getSubimage(clip);
// Choose an arbitrary location to draw this subImage
// into this component.
int locX = (w - clip.width)/2;
int locY = h - clip.height - 40;
// Draw the subImage at this location.
g2.drawImage(subImage, locX, locY, this);
}
private BufferedImage getSubimage(Rectangle r) {
// Boundry checking is advisable here.
BufferedImage subImage = null;
try {
subImage = image.getSubimage(r.x, r.y, r.width, r.height);
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("AIOOBE: " + e.getMessage());
}
return subImage;
}
public Dimension getPreferredSize() {
return new Dimension(160, 200);
}
}