openseadragon / html-overlay

An OpenSeadragon plugin that adds HTML overlay capability.
BSD 3-Clause "New" or "Revised" License
13 stars 4 forks source link

Simplest use case: PNG overlay #3

Closed darwinjob closed 2 years ago

darwinjob commented 2 years ago

Hi I was trying to overlay the OSd image with PNG image. The idea is very much similar to SVG overlay I was successfully experimenting before: the PNG should overlay entire OSd image and scale with it - exactly as SVG does. So I tried to reuse the code for SVG substituting it with PNG.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>PNG overlay demo</title>

        <style>
          #openseadragon {
              position: absolute;
              top: 0;
              left: 0;
              bottom: 0;
              right: 0;
          }
        </style>
    </head>
    <body>
        <div id="openseadragon"></div>
        <script src='openseadragon.min.js'></script>

        <script>

          var viewer = OpenSeadragon({
              id:              "openseadragon",
              prefixUrl:       "https://openseadragon.github.io/openseadragon/images/",
              tileSources:     "https://raw.githubusercontent.com/darwinjob/osd-demo/master/resources/NeuN_s4gl4s5_10x/NeuN_s4gl4s5_10x.xml",
          });

          var png_overlay = document.createElement("div");
          png_overlay.id = "png-overlay";
          png_overlay.innerHTML = "<img src='http://upload.wikimedia.org/wikipedia/commons/thumb/4/47/PNG_transparency_demonstration_1.png/280px-PNG_transparency_demonstration_1.png' />";

          viewer.addOverlay({
                  element: png_overlay,
                  location: new OpenSeadragon.Rect(0, 0, 1, 1)
          });

        </script>
    </body>
</html>

The PNG image was added but it doesn't scale ignoring OpenSeadragon.Rect(0, 0, 1, 1) and apparently staying with its original width and height at (0, 0):

image

Then I tried to add PNG via img element:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>PNG overlay demo</title>

        <style>
          #openseadragon {
              position: absolute;
              top: 0;
              left: 0;
              bottom: 0;
              right: 0;
          }
        </style>
    </head>
    <body>
        <div id="openseadragon"></div>
        <script src='openseadragon.min.js'></script>

        <script>

        var img = document.createElement("img");
        img.src = "http://upload.wikimedia.org/wikipedia/commons/thumb/4/47/PNG_transparency_demonstration_1.png/280px-PNG_transparency_demonstration_1.png";

        var viewer = OpenSeadragon({
            id:              "openseadragon",
            prefixUrl:       "https://openseadragon.github.io/openseadragon/images/",
            tileSources:     "https://raw.githubusercontent.com/darwinjob/osd-demo/master/resources/NeuN_s4gl4s5_10x/NeuN_s4gl4s5_10x.xml"
        });

    viewer.addOverlay({
        element: img,
        location: new OpenSeadragon.Rect(0, 0, 1, 1)
    });

        </script>
    </body>
</html>

This time PNG does scale with the OSd (properly sticked to) but in some weird distorted way:

image

Why does it behaves differently?

My next thing to try was the canvas overlay but I found this plugin (btw it isn't listed here https://openseadragon.github.io/examples/ui-overlays/). Is this the official recommended way to create PNG overlays? I just want other people to avoid repeating this investigation for this simple use case.

darwinjob commented 2 years ago

Or there’s a way to achieve this functionality without any plugin (like with SVG)?

iangilman commented 2 years ago

The distortion is because your PNG image doesn't match the aspect ratio of the rectangle you specified when you created the overlay. You used location: new OpenSeadragon.Rect(0, 0, 1, 1) which would work if the PNG was perfectly square, but it doesn't look like it is.

If, for instance, your PNG is 640x480, you could do this: location: new OpenSeadragon.Rect(0, 0, 1, 480 / 640).

In your scenario, that's probably the easiest way to go, so you don't need this plugin. You certainly could achieve the same results with this plugin if you wanted.

darwinjob commented 2 years ago

Thanks for the reply, Ian! My understanding of location: new OpenSeadragon.Rect(0, 0, 1, 1) was more like texture coordinates :) Indeed, setting height/width makes the PNG width aligned keeping the aspect ratio intact:

image

I added red filter to the image and the corner markers to PNG https://darwinjob.github.io/osd-demo/PNG_overlay_test.html to make all this easily visible.

I can't guess what would be the trick to force (ignoring the aspect ratio) PNG to fit OSd image borders. Could you please give me a hint?

iangilman commented 2 years ago

By default, the image in the viewer is width of 1 in viewport coordinates and height of whatever the aspect ratio is. In your case, your image is 19843x12756, so your image height is going to be 12756 / 19843. If you want the PNG to completely cover the DZI, then you use those dimensions. If, instead, you want to honor the PNG's aspect ratio, but center it in the DZI, you would need to do a little math to figure out where to put it. That might look something like this:

const dziWidth = 1;
const dziHeight = 12756 / 19843;
const diceWidth = 280;
const diceHeight = 210;

const scale = dziHeight / diceHeight;
const overlayWidth = diceWidth * scale;
const overlayHeight = diceHeight * scale;
const diceLocation = new OpenSeadragonRect((dziWidth - overlayWidth) / 2, (dziHeight - overlayHeight) / 2,
    overlayWidth, overlayHeight);
darwinjob commented 2 years ago

Perfect!!!

image

Thank you, Ian. Quick and comprehensive as usual :) I'm seriously considering to convince my lab to make a donation https://opencollective.com/create-account?next=%2Fopenseadragon%2Fdonate

darwinjob commented 2 years ago

https://darwinjob.github.io/osd-demo/PNG_overlay.html Try the toggle button 😎

iangilman commented 2 years ago

Looks perfect! Lovely :-)

I'm seriously considering to convince my lab to make a donation

That would be great! Also I'd love to hear if you have any general thoughts on how to convince labs/institutions to support OSD...

darwinjob commented 2 years ago

How do I send a private message here? @iangilman Anyway, the reply from my boss is that we are running on grants thus no official donations are possible. I guess that's a quite common case for research institutes. However, buying services and software are possible. You might think about having a commercial version of your library. Or providing support services.

iangilman commented 2 years ago

@darwinjob I don't think there's a private message feature in GitHub, but you can email me at ian@iangilman.com.

Thank you for the feedback! That's a really interesting point. I'll give that some thought. I may want to ask you more questions about what sort of service your org might want. Thanks again!