I think that resizing an image to a given dimension in pixels to show it at the wanted size is more expensive than using that image as background of a Label
that has the wanted preferred size. Could you confirm that it's true? And, if so, why is it true?
I mean that using a class like the following is better (in terms of performance) than resizing the contained image. Do you think that a faster approach is possible? I need to display a lot of photos at a fixed size, but my app is not as faster as the native gallery app of the smartphone.
/**
* Button useful to show the given Image at the given size, without the need to
* resize it.
*
* @author Francesco Galgani
*/
public class FixedSizeButton extends Button {
private final int imageWidth;
private final int imageHeight;
private Image image;
/**
* Creates a Button displaying an Image at the given fixed size; at least
* one of imageWidth or imageHeight must be specified.
*
* @param image
* @param imageWidth in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
* @param imageHeight in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
*/
public FixedSizeButton(Image image, int imageWidth, int imageHeight) {
this(image, imageWidth, imageHeight, null);
}
/**
* Creates a Button displaying an Image at the given fixed size; at least
* one of imageWidth or imageHeight must be specified.
*
* @param image
* @param imageWidth in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
* @param imageHeight in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
* @param uiid
*/
public FixedSizeButton(Image image, int imageWidth, int imageHeight, String uiid) {
this(image, imageWidth, imageHeight, false, uiid);
}
/**
* Creates a Button displaying an Image at the given fixed size; at least
* one of imageWidth or imageHeight must be specified.
*
* @param image
* @param imageWidth in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
* @param imageHeight in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
* @param scaledSmallerRatio force the image to maintain the aspect ratio
* within the given dimension (it requires that both imageWidth and
* imageHeight are specified)
* @param uiid
*/
public FixedSizeButton(Image image, int imageWidth, int imageHeight, boolean scaledSmallerRatio, String uiid) {
if (image == null) {
throw new IllegalArgumentException("image cannot be null");
}
if (imageWidth <= 0 && imageHeight <= 0) {
throw new IllegalArgumentException("invalid imageWidth and imageHeight");
}
this.image = image;
setShowEvenIfBlank(true);
if (uiid != null) {
super.setUIID(uiid);
}
if (imageWidth < 1) {
imageWidth = image.getWidth() * imageHeight / image.getHeight();
} else if (imageHeight < 1) {
imageHeight = image.getHeight() * imageWidth / image.getWidth();
}
if (scaledSmallerRatio) {
float hRatio = ((float) imageHeight) / ((float) image.getHeight());
float wRatio = ((float) imageWidth) / ((float) image.getWidth());
if (hRatio < wRatio) {
imageWidth = (int) (image.getWidth() * hRatio);
} else {
imageHeight = (int) (image.getHeight() * wRatio);
}
}
this.getAllStyles().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FIT);
this.getAllStyles().setBgImage(image);
this.imageWidth = imageWidth;
this.imageHeight = imageHeight;
}
@Override
public Dimension calcPreferredSize() {
int width = imageWidth + this.getStyle().getPaddingLeftNoRTL() + this.getStyle().getPaddingRightNoRTL();
int height = imageHeight + this.getStyle().getPaddingTop() + this.getStyle().getPaddingBottom();
return new Dimension(width, height);
}
/**
* Returns the background image
*
* @return the bg image
*/
@Override
public Image getIcon() {
return image;
}
@Override
public void setText(String text) {
throw new IllegalStateException("Not supported");
}
@Override
public void setUIID(String id) {
super.setUIID(id);
this.getAllStyles().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FIT);
this.getAllStyles().setBgImage(image);
}
}
The performance footprint/overhead varies. When you do Image.scaled
(which I assume is what you meant by resizing...), the image might be traversed pixel by pixel and shrunk to a new smaller byte array. Then it might be re-encoded as PNG or JPEG. All of those are expensive tasks.
Note that I used the word "might" as iOS doesn't always do it and uses hardware scaling in some cases...
When you use drawing the image is loaded as a texture into the GPU which draws/scales the image. This has zero overhead and is pretty darn fast.The big drawback here is RAM which is taken up both in regular heap and GPU memory. So it's a trade-off you need to make.