Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Best practice: Measuring image size off screen

    Hi Isomorphic,

    I'm in the process of developing a feature where the Admin user can configure the logo of his or her instance of our application (in current 6.1p).
    So far, we used to deploy the image with the system setup. We also hardcoded the sizes in the DB and used those for image width/height and positioning.

    Now, image upload to the DB does work, image display in general (PNG, JPG) via IDACall-viewFile as well (right now not in the case of SVG, see here).
    Next is to determine the size from the image itself. I read in many threads that if necessary, such a thing (size determination) is done by the framework offscreen, e.g.
    • generate temp object offscreen, top:-1000, left:-1000
    • read the generated size
    • markForDestroy temp object
    • use read size for calculations
    • draw real object
    I tried to do the same, but did not succeed so far.
    My questions:
    • Is the approach from the testcase correct?
    • Is a Layout needed as container (because of this thread)?
    • Should this be done via SmartGWT APIs (I assume so, because you need to do the same in SmartClient as well) or via GWT (because of this thread)?
    • Is this synchronous or how do I now that the image is drawn and the size final?
    • Why does the click in the window button still display 100/100 (=how do I get the drawn size?)

    BuiltInDS.java:
    Code:
    package com.smartgwt.sample.client;
    
    import com.google.gwt.core.client.EntryPoint;
    import com.smartgwt.client.Version;
    import com.smartgwt.client.core.KeyIdentifier;
    import com.smartgwt.client.types.ImageStyle;
    import com.smartgwt.client.util.Page;
    import com.smartgwt.client.util.PageKeyHandler;
    import com.smartgwt.client.util.SC;
    import com.smartgwt.client.widgets.IButton;
    import com.smartgwt.client.widgets.Img;
    import com.smartgwt.client.widgets.Label;
    import com.smartgwt.client.widgets.Window;
    import com.smartgwt.client.widgets.events.ClickEvent;
    import com.smartgwt.client.widgets.events.ClickHandler;
    import com.smartgwt.client.widgets.events.CloseClickEvent;
    import com.smartgwt.client.widgets.events.CloseClickHandler;
    import com.smartgwt.client.widgets.layout.VLayout;
    
    public class BuiltInDS extends VLayout implements EntryPoint {
        public void onModuleLoad() {
            KeyIdentifier debugKey = new KeyIdentifier();
            debugKey.setCtrlKey(true);
            debugKey.setKeyName("D");
    
            Page.registerKey(debugKey, new PageKeyHandler() {
                public void execute(String keyName) {
                    SC.showConsole();
                }
            });
    
            setWidth100();
            setHeight100();
    
            {
                IButton recreateBtn = new IButton("Recreate big");
                recreateBtn.addClickHandler(new ClickHandler() {
                    @Override
                    public void onClick(ClickEvent event) {
                        new MyWindow("http://edgeblog.jll.com/wp-content/uploads/2015/06/North_America_Skyline_Illustration_2015_High-res.jpg").show();
                    }
                });
                addMember(recreateBtn);
            }
            {
                IButton recreateBtn = new IButton("Recreate small");
                recreateBtn.addClickHandler(new ClickHandler() {
                    @Override
                    public void onClick(ClickEvent event) {
                        new MyWindow("https://img.posterlounge.co.uk/images/wbig/poster-skyline-wien-395529.jpg").show();
                    }
                });
                addMember(recreateBtn);
            }
            new MyWindow("https://img.posterlounge.co.uk/images/wbig/poster-skyline-wien-395529.jpg").show();
            draw();
        }
    
        private class MyWindow extends Window {
            public MyWindow(String src) {
                setWidth(400);
                setHeight(600);
                setTitle("Offscreen drawing test (" + Version.getVersion() + "/" + Version.getSCVersionNumber() + ")");
                setShowMinimizeButton(false);
                setIsModal(true);
                setShowModalMask(true);
                centerInPage();
    
                final Img jpgImg = new Img(src);
                jpgImg.setImageType(ImageStyle.NORMAL); // Needed, as the size is 100x100 otherwise
                jpgImg.setTop(200); // to see an effect, will be a big negative value once it is working
                jpgImg.setLeft(200);// to see an effect, will be a big negative value once it is working
                // final VLayout testContainer = new VLayout();
                // testContainer.setOverflow(Overflow.VISIBLE);
                // testContainer.setHeight(1);
                // testContainer.setWidth(1);
                // testContainer.setMembers(jpgImg);
                // testContainer.draw();
                jpgImg.draw();
    
                // Displays 100x100
                final Label sizeLabel = new Label(jpgImg.getWidth() + "/" + jpgImg.getHeight());
                IButton updateLabelBtn = new IButton("Update", new ClickHandler() {
                    @Override
                    public void onClick(ClickEvent event) {
                        // Still displays 100x100, even though the image is shown as expected
                        sizeLabel.setContents("Current size: " + jpgImg.getWidth() + "/" + jpgImg.getHeight());
                    }
                });
                addItem(sizeLabel);
                addItem(updateLabelBtn);
    
                addCloseClickHandler(new CloseClickHandler() {
                    @Override
                    public void onCloseClick(CloseClickEvent event) {
                        jpgImg.markForDestroy();
                    }
                });
            }
        }
    }
    Thank you & Best regards
    Blama

    #2
    Screenshot:
    Click image for larger version

Name:	Console.PNG
Views:	275
Size:	63.7 KB
ID:	253350

    Comment


      #3
      Hi Blama,
      This what we are using to get image dimensions: https://code.google.com/archive/p/gwt-image-loader/
      In short:
      Code:
          private Img image;
      
              ImagePreloader.load(url, new ImageLoadHandler() {
      
                  public void imageLoaded(ImageLoadEvent event) {
                      if (event.isLoadFailed()) {
                          image.setVisible(false);
                      } else {
                          image.setWidth(event.getDimensions().getWidth() * image.getHeight() / event.getDimensions().getHeight());
                          image.setSrc(url);
                      }
                  }
              });
      HTH
      MichalG

      Comment


        #4
        For loading and measuring image sizes, use GWT approaches such as the one michalg posted above.

        For measuring HTML content (with perhaps some inline images) you would use the approach that the framework uses above.

        Your attempt to measure an image size failed above for two reasons:

        1. you didn't ensure the images were loaded first

        2. you stuck it in an Img component, which sizes the image according to whatever you set the Img component's dimensions too. Generally, for measuring HTML content, use a Canvas.

        Comment


          #5
          Hi michalg, Hi Isomorphic,

          thanks for the hint. This does look simple enough.
          If possible, I'd like to do this without a 3rd party library, though (and also without mixing of GWT and SmartGWT widgets, which you suggest not to do generally).

          I assume this is possible as you must do such a thing in SmartClient as well and SmartClient users must be able to such a thing as well.

          How would I put an PNG/SVG image into a Canvas? It does not have a setSrc()-API.
          How would I do a "wait for loaded and rendered"?

          If you say "not worth the effort, that 3rd party lib is simple enough and does not contradict the "do not mix", this is fine for me as well.

          Thank you & Best regards
          Blama

          Comment


            #6
            Hi Blama,
            No mixing widgets - just preloading. Img in the example should be type of com.smartgwt.client.widgets.Img.
            MichalG

            Comment


              #7
              MichalG is correct, this is not widget usage. For context, in SmartClient, image loading with a callback is achieved via FileLoader APIs.

              And again, a Canvas measures HTML content - you can put an image into HTML by using the <img> HTML tag.

              Comment


                #8
                Hi all,

                Originally posted by Isomorphic View Post
                MichalG is correct, this is not widget usage.
                OK perfect, will do it this way then with the JAR michalg pointed to.

                Originally posted by Isomorphic View Post
                And again, a Canvas measures HTML content - you can put an image into HTML by using the <img> HTML tag.
                OK, thanks. Good to know that there would be this possibility.

                Best regards
                Blama

                Comment

                Working...
                X