- #0000743: OutOfMemoryError caused by image ResampleOp in FImagePanel. (http://www.cardforge.org/bugz/view.php?id=743)

This commit is contained in:
spr
2013-09-25 10:15:05 +00:00
parent 12fd77953f
commit d38898b1dd

View File

@@ -41,7 +41,7 @@ import com.mortennobel.imagescaling.ResampleOp;
* <p>
* Options to scale and rotate the image are available if required.
*
* @version $Id:$
* @version $Id$
*
*/
@SuppressWarnings("serial")
@@ -55,6 +55,11 @@ public class FImagePanel extends JPanel {
// Remains the same regardless of any transformations that might be applied to it.
private BufferedImage sourceImage = null;
// Resampling is an expensive operation so keep a copy of last resampled image and
// use this for repaints if image has not been resized or changed.
private BufferedImage scaledImage = null;
private boolean isResampleEnabled = true;
private double imageScale = 1;
private int degreesOfRotation = 0;
@@ -69,12 +74,6 @@ public class FImagePanel extends JPanel {
setResizeListener();
};
public void clearImage() {
this.sourceImage = null;
this.imageScale = 1;
repaint();
}
/**
* This timer is used to identify when resizing has finished.
* <p>
@@ -95,6 +94,7 @@ public class FImagePanel extends JPanel {
private void doResizedFinished() {
this.resizingTimer.stop();
this.isResizing = false;
this.isResampleEnabled = true;
this.repaint();
}
@@ -118,11 +118,11 @@ public class FImagePanel extends JPanel {
* This means the image can only have either a vertical or horizontal orientation.
*/
public void setImage(BufferedImage image, int initialRotation, AutoSizeImageMode autoSizeMode) {
if (this.sourceImage != image) {
if (this.sourceImage != image || this.degreesOfRotation != initialRotation || this.autoSizeMode != autoSizeMode) {
isResampleEnabled = true;
this.autoSizeMode = autoSizeMode;
if (initialRotation > 0) { setRotation(initialRotation); }
this.sourceImage = image;
setImageScale();
repaint();
}
}
@@ -165,10 +165,12 @@ public class FImagePanel extends JPanel {
* This means the image can only have either a vertical or horizontal orientation.
*/
public void setRotation(int degrees) {
if (this.degreesOfRotation != degrees) {
this.degreesOfRotation = ImageUtil.getRotationToNearest(degrees, 90);
setImageScale();
isResampleEnabled = true;
repaint();
}
}
/**
* Gets the rotation of the displayed image relative to the original image.
@@ -217,19 +219,26 @@ public class FImagePanel extends JPanel {
/**
* Uses Morten Nobel's java-image-scaling library to resize image.
* <p>
* This produces superior quality to affine scaling as image sizes
* are reduced but at the cost of performance.
* This produces superior quality to affine scaling especially as
* image sizes are reduced but at the cost of performance.
* <p>
* You cannot legislate for when this will be called since it depends
* on how often paintComponent() is invoked and any number of external
* events can cause this to happen. But resampling is an expensive operation
* so use an existing copy if the image has not changed or been resized.
*/
private BufferedImage getResampledImage() {
BufferedImage scaledImage = null;
if (this.imageScale != 1) {
if (isResampleEnabled) {
isResampleEnabled = false;
DimensionConstrain constrain = DimensionConstrain.createRelativeDimension((float)this.imageScale);
ResampleOp resampler = new ResampleOp(constrain);
scaledImage = resampler.filter(sourceImage, null);
} else {
scaledImage = sourceImage;
this.scaledImage = resampler.filter(sourceImage, null);
}
return scaledImage;
} else {
this.scaledImage = sourceImage;
}
return this.scaledImage;
}
/**
@@ -319,13 +328,17 @@ public class FImagePanel extends JPanel {
private void setImageScale() {
if (this.sourceImage != null) {
if (this.autoSizeMode != AutoSizeImageMode.OFF) {
this.imageScale = ImageUtil.getBestFitScale(getSourceImageSize(), this.getSize());
if (this.imageScale == 0) { this.imageScale = 1; };
if (this.autoSizeMode == AutoSizeImageMode.SOURCE && this.imageScale > 1) {
Double newScale = ImageUtil.getBestFitScale(getSourceImageSize(), this.getSize());
if (newScale != this.imageScale) {
isResampleEnabled = true;
this.imageScale = newScale;
if (newScale == 0) { this.imageScale = 1; };
if (this.autoSizeMode == AutoSizeImageMode.SOURCE && newScale > 1) {
this.imageScale = 1;
}
}
}
}
}
}