Leaflet.js(或其他解决方案)将图像放大到没有模糊的像素

问题描述 投票:0回答:2

我最近一直在使用Leaflet显示栅格图像。

我想为特定项目做的是能够放大图像,以使像素以清晰的方式在屏幕上放大,例如在Photoshop或喜欢。我还想在最大缩放比例之前将图像像素与屏幕像素之间保持1:1对应。

我尝试按照herehere的描述超越maxNativeZoom,但可以,但是插值会导致像素模糊。

我想到了一种替代方法,即使用“最近邻点”内插法将每个像素扩展到更大的正方形,从而使源图像更大:当放大到maxNativeZoom时,正方形看起来像被急剧放大的像素,即使不是。

问题是:

  • 图像尺寸和图块计数很快就失控了(原始图像为4096 x 4096)
  • 您永远不会获得图像像素与屏幕像素之间1:1对应的'流行'

我曾考虑过使用两个图块集:第一个从原始图像到最大maxNativeZoom,然后是更大的“最近邻”插值图像,其后跟随this

但是,这更加复杂,无法避免大图块数的问题,并且看起来不太优雅。

所以:

  • Leaflet可以执行我需要的操作吗,如果可以,怎么办?
  • 如果不能的话,您可以向我指出正确的方向(例如,知道如何实现this会很有趣)?

非常感谢

leaflet zoom interpolation pixel raster
2个回答
0
投票

一种方法是利用image-rendering CSS property。这可以暗示浏览器在image-rendering元素(如Leaflet地图图块)上使用最近邻插值。

例如:

<img>

请参见img.leaflet-tile { image-rendering: pixelated; } 。当心working demo


0
投票

更复杂的方法(但可以在更多浏览器上使用的方法是利用incomplete browser support;特别是WebGL

这涉及一些Leaflet.TileLayer.GL,最关键的是在每个图块渲染中将统一值设置为图块坐标...

internal changes to Leaflet.TileLayer.GL to support a per-tile uniform

...具有gl.uniform3f(this._uTileCoordsPosition, coords.x, coords.y, coords.z); ,用于“显示”未缩放的图块以显示缩放的图块坐标(而不是仅跳过不存在的图块)...

L.TileLayer

...加上片段着色器,该片段着色器在获取texel之前先四舍五入texel坐标(再加上依赖于tile坐标的模相关偏移),以实际执行最近邻居的过采样...

    var hackishTilelayer = new L.TileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        'attribution': 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors',
        maxNonPixelatedZoom: 3
    });

    hackishTilelayer.getTileUrl = function(coords) {
        if (coords.z > this.options.maxNonPixelatedZoom) {
            return this.getTileUrl({
                x: Math.floor(coords.x / 2),
                y: Math.floor(coords.y / 2),
                z: coords.z - 1
            });
        }

        // Skip L.TileLayer.prototype.getTileUrl.call(this, coords), instead
        // apply the URL template directly to avoid maxNativeZoom shenanigans
        var data = {
            r: L.Browser.retina ? '@2x' : '',
            s: this._getSubdomain(coords),
            x: coords.x,
            y: coords.y,
            z: coords.z // *not* this._getZoomForUrl() !
        };
        var url = L.Util.template(this._url, L.Util.extend(data, this.options));
        return url;
    }

...在var fragmentShader = ` highp float factor = max(1., pow(2., uTileCoords.z - uPixelatedZoomLevel)); vec2 subtileOffset = mod(uTileCoords.xy, factor); void main(void) { vec2 texelCoord = floor(vTextureCoords.st * uTileSize / factor ) / uTileSize; texelCoord.xy += subtileOffset / factor; vec4 texelColour = texture2D(uTexture0, texelCoord); // This would output the image colours "as is" gl_FragColor = texelColour; } `; 的实例中全部绑在一起(它为周围的制服同步一些数字):

L.TileLayer.GL

您可以看到所有内容协同工作 var pixelated = L.tileLayer.gl({ fragmentShader: fragmentShader, tileLayers: [hackishTilelayer], uniforms: { // The shader will need the zoom level as a uniform... uPixelatedZoomLevel: hackishTilelayer.options.maxNonPixelatedZoom, // ...as well as the tile size in pixels. uTileSize: [hackishTilelayer.getTileSize().x, hackishTilelayer.getTileSize().y] } }).addTo(map);

© www.soinside.com 2019 - 2024. All rights reserved.