How to display high resolution image in browser using openlayers

狂风中的少年 提交于 2019-12-02 03:46:50

To use Zoomify you need a server which supports the image served as tiles. The url you are using is a static image on flickr which OpenLayers would need to process as ImageStatic. Here is the code using the highest resolution image from flickr

  var extent = [0, 0, 10000, 7328];
  var resolutions = [64, 32, 16, 8, 4, 2, 1];

  var layer = new ol.layer.Image({
    source: new ol.source.ImageStatic({
      url: 'https://live.staticflickr.com/8173/7993440342_6a1f281898_o_d.jpg',
      imageExtent: extent
    })
  });

  var map = new ol.Map({
    layers: [layer],
    target: 'map',
    view: new ol.View({
      // adjust zoom levels to those provided by the source
      resolutions: resolutions,
      // constrain the center: center cannot be set outside this extent
      extent: extent
    })
  });
  map.getView().fit(extent);
html, body, .map {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
}
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<div id="map" class="map"></div>

Alternatively you could link to the url being used by OpenSeadragon. Sttrangely the zoom levels run from 8 to 14, with one tile at level 8 and a 55 x 41 grid at level 14 where the tiles in the rightmost column are 206px wide and in the bottom row 41px high. Zoomify can be used but a custom tile url function is needed to add 8 to the zoom level expected by OpenLayers.

  var imgWidth = 54*256 + 206;
  var imgHeight = 40*256 + 41;

  var zoomifyUrl = 'https://openseadragon.github.io/example-images/duomo/duomo_files/{z}/{x}_{y}.jpg';

  var layer = new ol.layer.Tile({
    source: new ol.source.Zoomify({
      url: zoomifyUrl,
      size: [imgWidth, imgHeight],
      crossOrigin: 'anonymous'
    })
  });

  layer.getSource().setTileUrlFunction(function(tileCoord) {
    return zoomifyUrl.replace(
      '{z}', tileCoord[0]+8
    ).replace(
      '{x}', tileCoord[1]
    ).replace(
      '{y}', -(tileCoord[2]+1)
    );
  });

  var extent = [0, -imgHeight, imgWidth, 0];

  var map = new ol.Map({
    layers: [layer],
    target: 'map',
    view: new ol.View({
      // adjust zoom levels to those provided by the source
      resolutions: layer.getSource().getTileGrid().getResolutions(),
      // constrain the center: center cannot be set outside this extent
      extent: extent
    })
  });
  map.getView().fit(extent);
html, body, .map {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
}
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<div id="map" class="map"></div>

Looking at the result from that attempt it is apparent some tiles are only 255px instead of the standard 256 which is causing white lines to appear on the output. I added a custom tile load function to stretch 255px widths or heights to 256 (but it must not stretch tiles at the right and bottom edges which can be less than 255px).

  var imgWidth = 54*256 + 206;
  var imgHeight = 40*256 + 41;

  var zoomifyUrl = 'https://openseadragon.github.io/example-images/duomo/duomo_files/{z}/{x}_{y}.jpg';

  var layer = new ol.layer.Tile({
    source: new ol.source.Zoomify({
      url: zoomifyUrl,
      size: [imgWidth, imgHeight],
      crossOrigin: 'anonymous'
    })
  });

  layer.getSource().setTileUrlFunction(function(tileCoord) {
    return zoomifyUrl.replace(
      '{z}', tileCoord[0]+8
    ).replace(
      '{x}', tileCoord[1]
    ).replace(
      '{y}', -(tileCoord[2]+1)
    );
  });

  var tileSize = ol.size.toSize(layer.getSource().getTileGrid().getTileSize(0));

  layer.getSource().setTileLoadFunction(function(imageTile, src) {
    var img = document.createElement('img');
    img.onload = function() {
      var width = img.naturalWidth >= tileSize[0]-1 ? tileSize[0] : img.naturalWidth;
      var height = img.naturalHeight >= tileSize[1]-1 ? tileSize[1] : img.naturalHeight;
      var canvas = document.createElement('canvas');
      canvas.width = width;
      canvas.height = height;
      var ctx = canvas.getContext('2d');
      ctx.drawImage(img, 0, 0, width, height);
      imageTile.getImage().src = canvas.toDataURL();
    };
    img.crossOrigin = 'anonymous';
    img.src = src;
  });

  var extent = [0, -imgHeight, imgWidth, 0];

  var map = new ol.Map({
    layers: [layer],
    target: 'map',
    view: new ol.View({
      // adjust zoom levels to those provided by the source
      resolutions: layer.getSource().getTileGrid().getResolutions(),
      // constrain the center: center cannot be set outside this extent
      extent: extent
    })
  });
  map.getView().fit(extent);
html, body, .map {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
}
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<div id="map" class="map"></div>

Using a dzi XML parser:

var map = new ol.Map({
    target: 'map',
    logo: false
});

var layer = dzi.loadUrl(
    'https://openseadragon.github.io/example-images/duomo/duomo.dzi',
    { attributions: 'Image &copy 2012, <a href="https://www.flickr.com/photos/projectese/" target="_blank">Dario Morelli</a>' }
);

layer.on('change:source', function(evt) {
    map.setView(
      new ol.View({
        resolutions: layer.getSource().getTileGrid().getResolutions(),
        extent: layer.getExtent()
      })
    );
    map.getView().fit(layer.getExtent(), { size: map.getSize() });
});

map.addLayer(layer);
html, body, .map {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
}
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<script>

dzi = function() {

function loadUrl ( url,
                   opt_options  // attributions (defaults to undefined), crossOrigin (defaults to 'anonymous')
) {

    var options = opt_options || {};
    var crossOrigin = options.crossOrigin === undefined ? 'anonymous' : options.crossOrigin;

    var layer = new ol.layer.Tile();

    var last = url.lastIndexOf('.');
    var path = url.slice(0, last);

    var xhr = new XMLHttpRequest();
    xhr.open('GET', url);
    xhr.onload = function() {

        var parser = new DOMParser();
        var xmlDoc = parser.parseFromString(xhr.responseText,'text/xml');

        var elements = xmlDoc.getElementsByTagName('Image');
        var tileSize = Number(elements[0].getAttribute('TileSize'));
        var format = elements[0].getAttribute('Format');
        var width = Number(elements[0].getElementsByTagName('Size')[0].getAttribute('Width'));
        var height = Number(elements[0].getElementsByTagName('Size')[0].getAttribute('Height'));
        var url = path + '_files/{z}/{x}_{y}.' + format;

        var source = new ol.source.Zoomify({
            attributions: options.attributions,
            url: url,
            size: [width, height],
            tileSize: tileSize,
            crossOrigin: crossOrigin
        });

        var offset = Math.ceil(Math.log(tileSize)/Math.LN2);

        source.setTileUrlFunction(function(tileCoord) {
            return url.replace(
                '{z}', tileCoord[0] + offset
            ).replace(
                '{x}', tileCoord[1]
            ).replace(
                '{y}', -(tileCoord[2]+1)
            );
        });

        layer.setExtent([0, -height, width, 0]);
        layer.setSource(source);

    }
    xhr.send();
    return layer;

}

return {
   "loadUrl" : loadUrl
}

} ();

</script>
<div id="map" class="map"></div>

The above answer has two issues:

  • lack of support for deepzoom in zoomify
  • white lines in between the tiles.

I was able to figure it out. Answer: Deepzoom into OpenLayers images using zoomify

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!