22

Changing the size of an Image Widget in GWT changes the size of the image element, but does not rescale the image on the screen. Therefore, the following will not work:

Image image = new Image(myImageResource);
image.setHeight(newHeight);
image.setWidth(newWidth);
image.setPixelSize(newWidth, newHeight);

This is because GWT implements its Image widget by setting the background-image of the HTML <img... /> element as the image, using CSS.

How does one get the actual image to resize?

Daniel
  • 10,115
  • 3
  • 44
  • 62

7 Answers7

34

I saw this blog entry, which solves the problem by using a GWT DataResource instead of ImageResource. It turns out that the same technique will actually work with ImageResource, if you use it as follows:

Image image = new Image(myImageResource.getURL());
image.setPixelSize(getLength(), getHeight());

To keep aspect ratio calculate it like:

Image image = new Image(myImageResource.getURL());
image.setPixelSize(newWidth, myImageResource.getHeight() * newWidth / myImageResource.getWidth());

As of GWT 2.4, use (see here):

Image image = new Image(myImageResource.getSafeUri());
image.setPixelSize(newWidth, myImageResource.getHeight() * newWidth / myImageResource.getWidth());
David
  • 1,101
  • 5
  • 19
  • 38
Daniel
  • 10,115
  • 3
  • 44
  • 62
  • 1
    This will resize the image but will not maintain its aspect ratio. – adranale Oct 21 '10 at 09:32
  • 2
    @adranale: you can allways calculate correct ration (added as this is community wiki) – Hurda Aug 03 '11 at 14:10
  • I can't resize image this method. Does nothing for me :/ – Jacek Kwiecień Jul 03 '12 at 12:25
  • Only ImageResource.getURL() is required, then you can set image size also with CSS. – djjeck Sep 21 '12 at 12:57
  • 2
    My problem with this is that I think it sort of defeats the purpose of `ImageResource`, doesn't it? Wouldn't this mean you're loading the image from the server every time you call this method? – Marconius Jul 07 '13 at 09:03
  • Make sure to cast the ratio as a double and then cast the resulting height as an int. image.setPixelSize(newWidth, (int) (myImageResource.getHeight() * ((double) newWidth / myImageResource.getWidth()))); – jazz Jun 22 '15 at 22:44
11

If we want to do the same in UIbinder. From an external resource then :

For example we have in recource

@Source("images/logo.png")
ImageResource getLogo();

In UiBinder template declare the <ui:with> element:

<ui:with field='res' type='com.myapp.client.Resources'/>

and below:

<g:Image url='{res.getLogo.getSafeUri.asString}'  pixelSize="Width, Height" />

in older GWT version:

<g:Image url='{res.getLogo.getURL}'  pixelSize="Width, Height" />

but now - Deprecated.

Do not use:

<g:Image resource='{res.getLogo}' pixelSize="Width, Height" />

becouse it doesn't scale images

Hussar
  • 89
  • 2
  • 4
3

Try the image loader widget http://code.google.com/p/gwt-image-loader The FitImage class provides what you are looking for.

PS: apply also patches from issues, as there are some minor bugs which I have fixed

Drejc
  • 14,196
  • 16
  • 71
  • 106
3

my final solution was to add a load handler on the image to resize it according to the dimensions of the loaded image (i.e. respectnig the ratio).

image.addLoadHandler(new LoadHandler() {
        @Override
        public void onLoad(LoadEvent event) {
            Element element = event.getRelativeElement();
            if (element == image.getElement()) {
                int originalHeight = image.getOffsetHeight();
                int originalWidth = image.getOffsetWidth();
                if (originalHeight > originalWidth) {
                    image.setHeight(MAX_IMAGE_HEIGHT + "px");
                } else {
                    image.setWidth(MAX_IMAGE_WIDTH + "px");
                }
            }
        }
    });

where MAX_IMAGE_WIDTH and MAX_IMAGE_HEIGHT are constants that determine the maximum allowed size of the image.

adranale
  • 2,835
  • 1
  • 21
  • 39
1

I wrote a class which accepts a ImageResource object, and you can set the wanted Pixel size of the Image. It uses CSS background-Position and CSS background-size to achive the aim:

The source code of the class ScalableImage is:

package de.tu_freiberg.informatik.vonwenckstern.client;
// class is written by Michael von Wenckstern, and is also used in ist diploma Thesis
// (this is only for my super visor, that he does not think I copied it from stackoverflow
// without mention the source) - this class is free to use for every body

import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Image;

public class ScalableImage extends Image {
    private int width;
    private int height;
    private ImageResource res;

    public ScalableImage(ImageResource res, int width, int height) {
        this.setUrl(res.getSafeUri());
        this.res = res;
        this.width = width;
        this.height = height;
    }

    @Override
    public void onLoad() {
        int widthOfBigImage = this.getOffsetWidth();
        int heightOfBigImage = this.getOffsetHeight();
        double scaleX = width / res.getWidth();
        double scaleY = height / res.getHeight();
        this.setResource(res);
        DOM.setStyleAttribute(getElement(), "backgroundPosition", Integer.toString((int) (res.getLeft() * -1 * scaleX))+"px "+
                Integer.toString((int) (res.getTop() * -1 * scaleY))+"px ");
        DOM.setStyleAttribute(getElement(), "backgroundSize", Integer.toString((int) (widthOfBigImage * scaleX))+"px "+
                Integer.toString((int) (heightOfBigImage * scaleY))+"px ");
        this.setPixelSize((int) (res.getWidth()* scaleX), (int) (res.getHeight() * scaleY));
    }
}

You can use this class as followed:

rootPanel.add(new ScalableImage(Images.Util.getImages().img0(), 60, 60));

If you use this class together with a PushButton, than you have to add the PushButton to the RootPanel, because otherwise the onLoad() function is not called. An example source code would look like:

for(ImageResource imRes: latexIconsClientBundle) {
            ScalableImage im = new ScalableImage(imRes, 60, 60);
            RootPanel.get().add(im); // PushButton class does not fire onAttach event, so we need to attach the image to the RootPanel
            PushButton btn = new PushButton(im);
            btn.setPixelSize(60, 60);
            if(++col > 9) {
                row++;
                col = 0;
            }
            this.setWidget(row, col, btn);
        }
  • not useful if one has to pass an `ImageResource`, e.g. using some `com.sencha.gxt.data.shared.IconProvider` for some `Tree` component with icons – Andreas Covidiot Mar 25 '14 at 12:03
0

From all my test, safeURI work only if you have ONE image in your bundle...So useless to use it because you have one cache.png by Bundle, so it is optimize nothing !

Fabi Fabi
  • 21
  • 2
0

Here is how I use the canvas element to scale images using HTML5.

http://code.google.com/p/gwt-examples/wiki/gwt_hmtl5

Brandon Donnelson http://gwt-examples.googlecode.com http://c.gawkat.com

Brandon
  • 2,034
  • 20
  • 25