如何使用openlayers在浏览器中显示高分辨率图像
How to display high resolution image in browser using openlayers
我正在尝试使用 openlayers 5 在浏览器中显示高分辨率图像。我找到了一个关于如何使用 zoomify 创建图像块并使用 openlayers 地图渲染它的示例。但我无法将它用于我自己的形象。我对此完全陌生。我问的问题可能很琐碎。请原谅我的无知
Example code - This is the example from openlayers website. I am trying to do the same with this image。
我尝试用我的图像替换 zoomifyUrl 和 iipUrl url 但它没有用。
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import TileLayer from 'ol/layer/Tile.js';
import Zoomify from 'ol/source/Zoomify.js';
var imgWidth = 799;
var imgHeight = 586;
var zoomifyUrl = 'https://live.staticflickr.com/8173/7993440342_5d9c68faec_c.jpg';
var iipUrl = 'https://live.staticflickr.com/8173/7993440342_5d9c68faec_c.jpg' + '&JTL={z},{tileIndex}';
var layer = new TileLayer({
source: new Zoomify({
url: zoomifyUrl,
size: [imgWidth, imgHeight],
crossOrigin: 'anonymous'
})
});
var extent = [0, -imgHeight, imgWidth, 0];
var map = new Map({
layers: [layer],
target: 'map',
view: new 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);
var control = document.getElementById('zoomifyProtocol');
control.addEventListener('change', function(event) {
var value = event.currentTarget.value;
if (value === 'iip') {
layer.setSource(new Zoomify({
url: iipUrl,
size: [imgWidth, imgHeight],
crossOrigin: 'anonymous'
}));
} else if (value === 'zoomify') {
layer.setSource(new Zoomify({
url: zoomifyUrl,
size: [imgWidth, imgHeight],
crossOrigin: 'anonymous'
}));
}
});
我想实现类似 openseadragon website 中的演示的东西。更改上述代码后,我得到了一个重复了一部分图像的网格。
要使用 Zoomify,您需要一个支持图像作为图块的服务器。您正在使用的 url 是 flickr 上的静态图像,OpenLayers 需要将其作为 ImageStatic 进行处理。这是使用来自 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>
或者您可以 link 到 OpenSeadragon 使用的 url。奇怪的是,缩放级别 运行 从 8 到 14,一个图块在第 8 层,一个 55 x 41 的网格在第 14 层,其中最右边一列的图块宽 206 像素,底行的图块高 41 像素。可以使用 Zoomify,但需要自定义平铺 url 函数才能将 8 添加到 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>
查看该尝试的结果,很明显有些图块只有 255px 而不是标准的 256,这导致输出中出现白线。我添加了一个自定义的图块加载函数,将 255px 的宽度或高度拉伸到 256(但它不能在右侧和底部边缘拉伸图块,这可能小于 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>
使用天珠 XML 解析器:
var map = new ol.Map({
target: 'map',
logo: false
});
var layer = dzi.loadUrl(
'https://openseadragon.github.io/example-images/duomo/duomo.dzi',
{ attributions: 'Image © 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>
以上回答有两个问题:
- zoomify 中不支持 deepzoom
- 瓷砖之间的白线。
我想通了。答案:Deepzoom into OpenLayers images using zoomify
我正在尝试使用 openlayers 5 在浏览器中显示高分辨率图像。我找到了一个关于如何使用 zoomify 创建图像块并使用 openlayers 地图渲染它的示例。但我无法将它用于我自己的形象。我对此完全陌生。我问的问题可能很琐碎。请原谅我的无知
Example code - This is the example from openlayers website. I am trying to do the same with this image。
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import TileLayer from 'ol/layer/Tile.js';
import Zoomify from 'ol/source/Zoomify.js';
var imgWidth = 799;
var imgHeight = 586;
var zoomifyUrl = 'https://live.staticflickr.com/8173/7993440342_5d9c68faec_c.jpg';
var iipUrl = 'https://live.staticflickr.com/8173/7993440342_5d9c68faec_c.jpg' + '&JTL={z},{tileIndex}';
var layer = new TileLayer({
source: new Zoomify({
url: zoomifyUrl,
size: [imgWidth, imgHeight],
crossOrigin: 'anonymous'
})
});
var extent = [0, -imgHeight, imgWidth, 0];
var map = new Map({
layers: [layer],
target: 'map',
view: new 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);
var control = document.getElementById('zoomifyProtocol');
control.addEventListener('change', function(event) {
var value = event.currentTarget.value;
if (value === 'iip') {
layer.setSource(new Zoomify({
url: iipUrl,
size: [imgWidth, imgHeight],
crossOrigin: 'anonymous'
}));
} else if (value === 'zoomify') {
layer.setSource(new Zoomify({
url: zoomifyUrl,
size: [imgWidth, imgHeight],
crossOrigin: 'anonymous'
}));
}
});
我想实现类似 openseadragon website 中的演示的东西。更改上述代码后,我得到了一个重复了一部分图像的网格。
要使用 Zoomify,您需要一个支持图像作为图块的服务器。您正在使用的 url 是 flickr 上的静态图像,OpenLayers 需要将其作为 ImageStatic 进行处理。这是使用来自 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>
或者您可以 link 到 OpenSeadragon 使用的 url。奇怪的是,缩放级别 运行 从 8 到 14,一个图块在第 8 层,一个 55 x 41 的网格在第 14 层,其中最右边一列的图块宽 206 像素,底行的图块高 41 像素。可以使用 Zoomify,但需要自定义平铺 url 函数才能将 8 添加到 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>
查看该尝试的结果,很明显有些图块只有 255px 而不是标准的 256,这导致输出中出现白线。我添加了一个自定义的图块加载函数,将 255px 的宽度或高度拉伸到 256(但它不能在右侧和底部边缘拉伸图块,这可能小于 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>
使用天珠 XML 解析器:
var map = new ol.Map({
target: 'map',
logo: false
});
var layer = dzi.loadUrl(
'https://openseadragon.github.io/example-images/duomo/duomo.dzi',
{ attributions: 'Image © 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>
以上回答有两个问题:
- zoomify 中不支持 deepzoom
- 瓷砖之间的白线。
我想通了。答案:Deepzoom into OpenLayers images using zoomify