Reputation: 36299
I am trying to resize an Image, the save it as a BufferedImage. If I do not scale the image, I works fine.
With the following code, a filename is passed in and converted to a BufferedImage this works fine Using g.drawImage(img, x, y, null);
where img is the BufferedImage
public Sprite(String filename){
ImageIcon imgIcon = new ImageIcon(filename);
int width = imgIcon.getIconWidth();
int height = imgIcon.getIconHeight();
BufferedImage bimg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics bg = bimg.getGraphics();
bg.drawImage(imgIcon.getImage(), 0, 0, null);
bg.dispose();
this.sprite = bimg;
}
The following method here does not work, it takes a filename, and a resize width. It resizes it, then converts it to a BufferedImage, but it does not work using g.drawImage(img, x, y, null);
again where img is the BufferedImage.
public Sprite(String filename, int width){
ImageIcon imgIcon = new ImageIcon(filename);
Image img = imgIcon.getImage();
float h = (float)img.getHeight(null);
float w = (float)img.getWidth(null);
int height = (int)(h * (width / w));
Image imgScaled = img.getScaledInstance(width, height, Image.SCALE_SMOOTH);
BufferedImage bimg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics bg = bimg.getGraphics();
bg.drawImage(imgScaled, 0, 0, null);
bg.dispose();
this.sprite = bimg;
}
So my question is, why isn't the second block working?
Upvotes: 1
Views: 1127
Reputation: 347194
You have a rounding issue...
Java will return result of a division based on the values you provide it...
For example...
int width = 100;
int w = 5;
int result = width / w
// result = 0, but it should be 0.5
Java has done an internal conversion, converting the value back to an int
, which simply truncates the decimal values.
Instead, you need to encourage Java to return the result as decimal value...
int result = width / (float)w
// result = 0.5
So, you scale calculation int height = (int)(h * (width / w))
is actually returning 0
I would use a calculation more along the lines of
int height = Math.round((h * (width / (float)w)))
I'm sorry, I don't quite remember the "technical" babble for all of this, but this is the general jest of the idea ;)
Updated
ImageIcon
uses a background thread to actually load the image pixels, but returns immediately after you call the constructor. This means that the image data may not be available for some time into the future.
Use ImageIO.read(new File(filename))
instead. This will block until the image data has been read and will return a BufferedImage
, which is significantly easier to deal with.
Upvotes: 1
Reputation:
check the:
Image imgScaled = img.getScaledInstance(width, height, Image.SCALE_SMOOTH);
if is null
the imgScaled
or not, For me it sem you have a null
.
Forgot which case, is but there is one, when the image loading is a blocking and other a none blocking method, which means the API function will return and the image is not loaded yet. Usually need to use an observer. Like I told I forgot when is that, but I met those situations!
Upvotes: 1