These are chat archives for openseadragon/openseadragon

25th
Apr 2018
Daniel Rodenberg
@D_Rode92_twitter
Apr 25 2018 16:47

Hi, I am currently coming across a problem with the OSD.open function. Originally in my application we were creating an OSD instance with the tileSource init but now we were wanting to create the tileSource after we had already made a viewer. The OSD instance with the tileSource in the original constructor was working fine but we were running into an issue when you would pan through the images quickly it would cause a double loading issue. That's why we were trying to switch to using open on sending a new tileSource on an already existing Viewer. The issue we're having now is that the getTileUrl is not returning the tiles. It's also not throwing any errors, it's completing as a success.

Here's the code we have for it as of now...

this.osd = OpenSeadragon({
      id: DZIdiv,
      prefixUrl: 'http://openseadragon.github.io/openseadragon/images/',
      showNavigator: true,
      immediateRender: true,
      showFullPageControl: false,
      showHomeControl: false,
      maxZoomPixelRatio: 3,
      navigatorPosition: 'BOTTOM_RIGHT',
      previousButton: 'previous-image',
      nextButton: 'next-image',
      rotateLeftButton: 'dzi-rotate-left',
      rotateRightButton: 'dzi-rotate-right',
      showRotationControl: true,
      zoomInButton: 'zoom-in',
      zoomOutButton: 'zoom-out'
    })

// Separate file
const tileSources = {
    height: parseInt(dziXml.getElementsByTagName('Size')[0].getAttribute('Height'), 10),
    width: parseInt(dziXml.getElementsByTagName('Size')[0].getAttribute('Width'), 10),
    tileSize: parseInt(dziXml.getElementsByTagName('Image')[0].getAttribute('TileSize'), 10),
    format: dziXml.getElementsByTagName('Image')[0].getAttribute('Format'),
    overlap: parseInt(dziXml.getElementsByTagName('Image')[0].getAttribute('Overlap'), 10),
    getTileUrl: (level, x, y) => {
      return getTemporaryUrlForProcessedBucket(`${project}/image/${id}_files/${level}/${x}_${y}.jpeg`, credentials)
    }
  }

  try {
    osd.open(tileSources)
  } catch (err) {
    console.log(err)
  }

osd.viewport.setRotation(rotation).fitHorizontally(true).fitVertically(true)
}

These are in separate files and we are sending the osd viewer instance to the different file.

Ian Gilman
@iangilman
Apr 25 2018 16:51
@tdiprima The setTimeout in https://codepen.io/iangilman/pen/PjdyGv is mostly to keep the frame rate consistent (when the loading times may be different).
Ian Gilman
@iangilman
Apr 25 2018 16:58
@D_Rode92_twitter So everything works fine if you include tileSources: tileSources in the creation of the viewer, but not the way you have it there?
Daniel Rodenberg
@D_Rode92_twitter
Apr 25 2018 16:58
Yup!
Ian Gilman
@iangilman
Apr 25 2018 16:58
Seems strange.
Do you have a link you can share or a codePen?
Daniel Rodenberg
@D_Rode92_twitter
Apr 25 2018 17:17
There isn't a great way for me to drop it into a codepen but I will try and figure out a better way to remove some code to make it easier to follow
Tammy DiPrima
@tdiprima
Apr 25 2018 17:26
@iangilman ok so let’s say I have 5 checkboxes, each corresponding to a transparent overlay tileSource. The collection of tileSource files is about 23064 files, total for 6 levels. I click the first 3 overlays, everything’s fine; I check viewer.world.getItemCount(); to make sure we’re good. I click the 4th overlay (checkbox) to display it, and I get this tile.js:309 [Tile.drawCanvas] attempting to draw tile 2/6_2 when it's not cached output in the developer console. Is there a cache limit I should know about? Or something?
Daniel Rodenberg
@D_Rode92_twitter
Apr 25 2018 17:29

@iangilman So when I create the instance and pass the tileSource like this... it works.

const osd1 = OpenSeadragon({
    id: 'dziDiv',
    prefixUrl: 'http://openseadragon.github.io/openseadragon/images/',
    tileSources: {
      height: 10,
      width: 10,
      tileSize: 10,
      format: dziXml.getElementsByTagName('Image')[0].getAttribute('Format'),
      overlap: 10,
      getTileUrl: (level, x, y) => {
        return getTemporaryUrlForProcessedBucket(`${project}/image/${id}_files/${level}/${x}_${y}.jpeg`, credentials)
      }
    }
  })

but when I do this... it does not retrieve the tiles and shows nothing. There are no errors though.

this.osd = OpenSeadragon({
      id: DZIdiv,
      prefixUrl: 'http://openseadragon.github.io/openseadragon/images/'
})

const tileSources = {
    height: 10,
    width: 10,
    tileSize: 10,
    format: dziXml.getElementsByTagName('Image')[0].getAttribute('Format'),
    overlap: 10,
    getTileUrl: (level, x, y) => {
      return getTemporaryUrlForProcessedBucket(`${project}/image/${id}_files/${level}/${x}_${y}.jpeg`, credentials)
    }
  }

try {
    osd.open(tileSources)
  } catch (err) {
    console.log(err)
  }

Let me know if that is easier to look at.

Ian Gilman
@iangilman
Apr 25 2018 17:31
@tdiprima Interesting. Does it affect the functionality? Are you also removing tile sources or just adding? There is a cache limit (which you can adjust), but it shouldn't be causing problems...
@tdiprima This is the option for controlling the cache limit, so you can see if it can make a difference maxImageCacheCount
@D_Rode92_twitter What you're doing makes sense, but it doesn't make sense that you're getting different results... They really are functionally identical.
@D_Rode92_twitter The only real difference I'm seeing is id: DZIdiv in one... if you don't manage to connect to an actual div, or if that div is invisible or 0 height or something, it won't bother trying to load anything.
Anyway, the OpenSeadragon constructor literally just calls this.open(options.tileSources) so you're really doing the same thing either way (at least in the cutdown example you're sharing).
Tammy DiPrima
@tdiprima
Apr 25 2018 17:36
@iangilman it does affect the functionality in that the display freezes up a bit. viewer.world.getItemCount() gets interesting. After 1, count is 2 (the overlay, plus the image in the viewer). After 2, count is 3, etc. BUT! After 4, we get 8. We like to see multiple overlays at the same time. I’ll try the maxImageCacheCount.
Ian Gilman
@iangilman
Apr 25 2018 17:40
@tdiprima Hmmm... that sounds like you've got a bug with how you're adding images... The image count should be 4.
Also, somehow accidentally re-adding the same image seems like a much more likely cause of that error. Hitting the tile max, on the other hand, is just normal operation.
Tammy DiPrima
@tdiprima
Apr 25 2018 17:45

@iangilman I go

viewer.addTiledImage(...) // <- with new tileSource

Before that, I remove them

    var i, tiledImage;
    var count = viewer.world.getItemCount();
    // Important: start from index 1.
    for (i = 1; i < count; i++) {
        tiledImage = viewer.world.getItemAt(i);
        setTimeout(function () {
            tiledImage.setOpacity(0);
            viewer.world.removeItem(tiledImage);
        }, 1);
        //viewer.world.removeItem(tiledImage);
    }

So I remove them, and then add them back in. Does it look wrong?

Ian Gilman
@iangilman
Apr 25 2018 17:51
@tdiprima If you want to remove all of them, you should use viewer.world.removeAll(). Of course if you're adding back ones you're removing, it's less disruptive to not remove them in the first place.
I'd keep track of which ones are added and which ones are not, and when it's time to update the state, just remove the ones that need removing and add the ones that need adding.
You'd probably get faster load times that way.
Tammy DiPrima
@tdiprima
Apr 25 2018 17:54
I didn’t do it that way (viewer.world.removeAll()) because we’re not removing the base image. We’re just toggling on/off overlays.
Ian Gilman
@iangilman
Apr 25 2018 17:55
Meaning you didn't do removeAll? I still think that the targeted removal of just the ones that need removing is better anyway.
Tammy DiPrima
@tdiprima
Apr 25 2018 17:56
I’d love to. How do I do that? I tried adding an element to the viewer.world item, but that didn’t work
Ian Gilman
@iangilman
Apr 25 2018 17:56
Also, perhaps an even better plan would be to add every overlay you might want all at once, but give most of them opacity: 0. They won't load any tiles, but will be sitting ready. Then when you want them to appear, just set their opacity to 1.
So, I don't recommend using your removal code above for those reasons, but just to be complete, I can critique it... You have a couple issues there. I think the setTimeout might be causing trouble because you're presumably starting the add process before the setTimeout fires. I can see how the setTimeout worked around a different issue though: by going through the count and removing items, you were modifying the number of items as you were counting through them, so you ended up first removing the first item, which meant the old second item was now the first item, which you skipped over as you were incrementing the count... (Sorry if my explanation is confusing).
Tammy DiPrima
@tdiprima
Apr 25 2018 18:00
Ah. Well, yes, and I did have those concerns. Thanks.
Ian Gilman
@iangilman
Apr 25 2018 18:01
Something like this would avoid that issue:
   var tiledImage;
   while (viewer.world.getItemCount() > 1) {
    tiledImage = viewer.world.getItemAt(1);
    viewer.world.removeItem(tiledImage);
   }
That said, I think your best bet is to add all the overlays at the beginning and show/hide them with opacity.
Tammy DiPrima
@tdiprima
Apr 25 2018 18:02
Good idea. Thanks!