Reputation: 115
Can anyone explain the following behavior? This method is supposed to scale the loaded picture so that it is as large as it can be within certain bounds without going over.
private final File imageFile;
private final ImageLoaderListener listener;
private final int idealWidth;
private final int idealHeight;
private final float idealRatio;
@Override
protected BufferedImage doInBackground() throws Exception {
BufferedImage origImage;
BufferedImage scaledImage;
int origHeight;
int origWidth;
float imgRatio;
// Load the image.
try {
origImage = ImageIO.read( imageFile );
origHeight = origImage.getHeight();
origWidth = origImage.getWidth();
imgRatio = origWidth / origHeight;
//imgRatio = 5/7;
} catch (Exception e){
JOptionPane.showMessageDialog( AppFrame.getAppFrame(),
"Could not load the image.", "Error Loading Image",
JOptionPane.ERROR_MESSAGE );
return null;
}
// Scale the image
double scaleFactor = (imgRatio >= idealRatio) ? idealWidth/origWidth
: idealHeight/origHeight;
int scaledWidth = (int) Math.floor( scaleFactor * origWidth );
int scaledHeight = (int) Math.floor( scaleFactor * origHeight );
scaledImage = new BufferedImage( scaledWidth, scaledHeight, BufferedImage.TYPE_INT_ARGB );
AffineTransform at = new AffineTransform();
at.scale(scaleFactor, scaleFactor);
AffineTransformOp scaleOp = new AffineTransformOp(
at, AffineTransformOp.TYPE_BICUBIC );
scaledImage = scaleOp.filter(origImage, scaledImage);
return scaledImage;
}
This is the unexpected result: All of the division is rounding without my telling it to. So if I run this with idealWidth=1920
and idealHeight=925
, the debug variable list shows idealHeight = (float) 2.0
. Likewise, my test picture is 532x783, and imgRatio = (float) 0.0
. ScaleFactor is doing the same thing: the 532x783 image results in ScaleFactor = (double) 1.0
When I originally started to bugfix this, I had inadvertently declared the ratio variables (idealRatio
and imgRatio
) as int
s. I saw this, changed them to doubles, and did a clean build, thinking it was fixed. Then I changed them to floats after doubles didn't work. Now I'm stumped. Why on earth would Java still be acting as if they were int
s?
Upvotes: 1
Views: 5499
Reputation: 2842
FYI, you can't just assign the result to a double and have Java perform double precision division, you need to cast each of your integer terms to doubles as follows:
int x=4;
int y=19;
double z = (double)x/(double)y;
Upvotes: 1
Reputation: 1328
This is standard Java (and most statically typed languages, thanks Daniel) behavior. What you are doing here is integer division which will always return an integer (same type as values in division operation) unless you take measures to prevent it. You could either make the variables into floats/doubles or cast one to a float/double to have the division expression return a float/double with standard rounding.
Upvotes: 6
Reputation: 47749
Well, to start with, 5/7
is an integer expression.
(And so, apparently, are the other divisions, after a very brief review.)
Upvotes: 3