diff --git a/src/ol/image.js b/src/ol/image.js index 39bfcfe5ac..e0b41e2e20 100644 --- a/src/ol/image.js +++ b/src/ol/image.js @@ -14,7 +14,7 @@ goog.require('ol.extent'); * @constructor * @extends {ol.ImageBase} * @param {ol.Extent} extent Extent. - * @param {number|undefined} resolution Resolution. + * @param {Array.|undefined} resolution Resolution. * @param {number} pixelRatio Pixel ratio. * @param {Array.} attributions Attributions. * @param {string} src Image source URI. @@ -114,7 +114,10 @@ ol.Image.prototype.handleImageError_ = function() { */ ol.Image.prototype.handleImageLoad_ = function() { if (this.resolution === undefined) { - this.resolution = ol.extent.getHeight(this.extent) / this.image_.height; + this.resolution = [ + ol.extent.getWidth(this.extent) / this.image_.width, + ol.extent.getHeight(this.extent) / this.image_.height + ]; } this.state = ol.ImageState.LOADED; this.unlistenImage_(); diff --git a/src/ol/imagebase.js b/src/ol/imagebase.js index e188221977..8f32c0ac9f 100644 --- a/src/ol/imagebase.js +++ b/src/ol/imagebase.js @@ -24,7 +24,9 @@ ol.ImageState = { * @constructor * @extends {goog.events.EventTarget} * @param {ol.Extent} extent Extent. - * @param {number|undefined} resolution Resolution. + * @param {Array.|undefined} resolution Resolution, first value + * is the resolution in the x direction, second value is the resolution + * in the y direction. * @param {number} pixelRatio Pixel ratio. * @param {ol.ImageState} state State. * @param {Array.} attributions Attributions. @@ -53,7 +55,7 @@ ol.ImageBase = function(extent, resolution, pixelRatio, state, attributions) { /** * @protected - * @type {number|undefined} + * @type {Array.|undefined} */ this.resolution = resolution; @@ -107,7 +109,7 @@ ol.ImageBase.prototype.getPixelRatio = function() { /** - * @return {number} Resolution. + * @return {Array.} Resolution. */ ol.ImageBase.prototype.getResolution = function() { goog.asserts.assert(this.resolution !== undefined, 'resolution not yet set'); diff --git a/src/ol/imagecanvas.js b/src/ol/imagecanvas.js index 743af73486..1ee96866c1 100644 --- a/src/ol/imagecanvas.js +++ b/src/ol/imagecanvas.js @@ -30,7 +30,8 @@ ol.ImageCanvas = function(extent, resolution, pixelRatio, attributions, var state = opt_loader !== undefined ? ol.ImageState.IDLE : ol.ImageState.LOADED; - goog.base(this, extent, resolution, pixelRatio, state, attributions); + goog.base(this, extent, [resolution, resolution], pixelRatio, state, + attributions); /** * @private diff --git a/src/ol/renderer/canvas/canvasimagelayerrenderer.js b/src/ol/renderer/canvas/canvasimagelayerrenderer.js index 9346fbc8f2..1afc4ef5b6 100644 --- a/src/ol/renderer/canvas/canvasimagelayerrenderer.js +++ b/src/ol/renderer/canvas/canvasimagelayerrenderer.js @@ -193,15 +193,19 @@ ol.renderer.canvas.ImageLayer.prototype.prepareFrame = var imageExtent = image.getExtent(); var imageResolution = image.getResolution(); var imagePixelRatio = image.getPixelRatio(); - var scale = pixelRatio * imageResolution / + var xImageResolution = imageResolution[0]; + var yImageResolution = imageResolution[1]; + var xScale = pixelRatio * xImageResolution / + (viewResolution * imagePixelRatio); + var yScale = pixelRatio * yImageResolution / (viewResolution * imagePixelRatio); ol.vec.Mat4.makeTransform2D(this.imageTransform_, pixelRatio * frameState.size[0] / 2, pixelRatio * frameState.size[1] / 2, - scale, scale, + xScale, yScale, viewRotation, - imagePixelRatio * (imageExtent[0] - viewCenter[0]) / imageResolution, - imagePixelRatio * (viewCenter[1] - imageExtent[3]) / imageResolution); + imagePixelRatio * (imageExtent[0] - viewCenter[0]) / xImageResolution, + imagePixelRatio * (viewCenter[1] - imageExtent[3]) / yImageResolution); this.imageTransformInv_ = null; this.updateAttributions(frameState.attributions, image.getAttributions()); this.updateLogos(frameState, imageSource); diff --git a/src/ol/reproj/image.js b/src/ol/reproj/image.js index 0292d7168e..9a19424697 100644 --- a/src/ol/reproj/image.js +++ b/src/ol/reproj/image.js @@ -116,8 +116,9 @@ ol.reproj.Image = function(sourceProj, targetProj, attributions = this.sourceImage_.getAttributions(); } - goog.base(this, targetExtent, targetResolution, this.sourcePixelRatio_, - state, attributions); + goog.base(this, targetExtent, [targetResolution, targetResolution], + this.sourcePixelRatio_, state, attributions); + }; goog.inherits(ol.reproj.Image, ol.ImageBase); diff --git a/src/ol/reproj/reproj.js b/src/ol/reproj/reproj.js index fbca15fa90..6ea19f43f4 100644 --- a/src/ol/reproj/reproj.js +++ b/src/ol/reproj/reproj.js @@ -93,7 +93,7 @@ ol.reproj.enlargeClipPoint_ = function(centroidX, centroidY, x, y) { * @param {number} width Width of the canvas. * @param {number} height Height of the canvas. * @param {number} pixelRatio Pixel ratio. - * @param {number} sourceResolution Source resolution. + * @param {Array.} sourceResolution Source resolution. * @param {ol.Extent} sourceExtent Extent of the data source. * @param {number} targetResolution Target resolution. * @param {ol.Extent} targetExtent Target extent. @@ -124,12 +124,14 @@ ol.reproj.render = function(width, height, pixelRatio, var canvasWidthInUnits = ol.extent.getWidth(sourceDataExtent); var canvasHeightInUnits = ol.extent.getHeight(sourceDataExtent); + var sourceResolutionX = sourceResolution[0]; + var sourceResolutionY = sourceResolution[1]; var stitchContext = ol.dom.createCanvasContext2D( - Math.round(pixelRatio * canvasWidthInUnits / sourceResolution), - Math.round(pixelRatio * canvasHeightInUnits / sourceResolution)); + Math.round(pixelRatio * canvasWidthInUnits / sourceResolutionX), + Math.round(pixelRatio * canvasHeightInUnits / sourceResolutionY)); - stitchContext.scale(pixelRatio / sourceResolution, - pixelRatio / sourceResolution); + stitchContext.scale(pixelRatio / sourceResolutionX, + pixelRatio / sourceResolutionY); stitchContext.translate(-sourceDataExtent[0], sourceDataExtent[3]); sources.forEach(function(src, i, arr) { @@ -222,8 +224,8 @@ ol.reproj.render = function(width, height, pixelRatio, context.translate(sourceDataExtent[0] - sourceNumericalShiftX, sourceDataExtent[3] - sourceNumericalShiftY); - context.scale(sourceResolution / pixelRatio, - -sourceResolution / pixelRatio); + context.scale(sourceResolutionX / pixelRatio, + -sourceResolutionY / pixelRatio); context.drawImage(stitchContext.canvas, 0, 0); context.restore(); diff --git a/src/ol/reproj/tile.js b/src/ol/reproj/tile.js index a1c819d620..3324a41cc3 100644 --- a/src/ol/reproj/tile.js +++ b/src/ol/reproj/tile.js @@ -258,7 +258,7 @@ ol.reproj.Tile.prototype.reproject_ = function() { var targetExtent = this.targetTileGrid_.getTileCoordExtent(tileCoord); this.canvas_ = ol.reproj.render(width, height, this.pixelRatio_, - sourceResolution, this.sourceTileGrid_.getExtent(), + [sourceResolution, sourceResolution], this.sourceTileGrid_.getExtent(), targetResolution, targetExtent, this.triangulation_, sources, this.renderEdges_); diff --git a/src/ol/source/imagemapguidesource.js b/src/ol/source/imagemapguidesource.js index 2ff6a92701..efa1de5e73 100644 --- a/src/ol/source/imagemapguidesource.js +++ b/src/ol/source/imagemapguidesource.js @@ -150,7 +150,7 @@ ol.source.ImageMapGuide.prototype.getImageInternal = var imageUrl = this.imageUrlFunction_(extent, size, projection); if (imageUrl !== undefined) { - image = new ol.Image(extent, resolution, pixelRatio, + image = new ol.Image(extent, [resolution, resolution], pixelRatio, this.getAttributions(), imageUrl, this.crossOrigin_, this.imageLoadFunction_); goog.events.listen(image, goog.events.EventType.CHANGE, diff --git a/src/ol/source/imagestaticsource.js b/src/ol/source/imagestaticsource.js index f6e57ce82d..2de9c20945 100644 --- a/src/ol/source/imagestaticsource.js +++ b/src/ol/source/imagestaticsource.js @@ -26,10 +26,12 @@ ol.source.ImageStatic = function(options) { var imageExtent = options.imageExtent; - var resolution, resolutions; + var xResolution, yResolution, resolutions, imgResolution; if (options.imageSize !== undefined) { - resolution = ol.extent.getHeight(imageExtent) / options.imageSize[1]; - resolutions = [resolution]; + xResolution = ol.extent.getWidth(imageExtent) / options.imageSize[0]; + yResolution = ol.extent.getHeight(imageExtent) / options.imageSize[1]; + imgResolution = [xResolution, yResolution]; + resolutions = [yResolution]; } var crossOrigin = options.crossOrigin !== undefined ? @@ -50,8 +52,8 @@ ol.source.ImageStatic = function(options) { * @private * @type {ol.Image} */ - this.image_ = new ol.Image(imageExtent, resolution, 1, attributions, - options.url, crossOrigin, imageLoadFunction); + this.image_ = new ol.Image(imageExtent, imgResolution, 1, + attributions, options.url, crossOrigin, imageLoadFunction); goog.events.listen(this.image_, goog.events.EventType.CHANGE, this.handleImageChange, false, this); diff --git a/src/ol/source/imagewmssource.js b/src/ol/source/imagewmssource.js index 1d63972269..3efc41c936 100644 --- a/src/ol/source/imagewmssource.js +++ b/src/ol/source/imagewmssource.js @@ -217,7 +217,7 @@ ol.source.ImageWMS.prototype.getImageInternal = var image = this.image_; if (image && this.renderedRevision_ == this.getRevision() && - image.getResolution() == resolution && + image.getResolution()[0] == resolution && image.getPixelRatio() == pixelRatio && ol.extent.containsExtent(image.getExtent(), extent)) { return image; @@ -247,7 +247,7 @@ ol.source.ImageWMS.prototype.getImageInternal = var url = this.getRequestUrl_(extent, this.imageSize_, pixelRatio, projection, params); - this.image_ = new ol.Image(extent, resolution, pixelRatio, + this.image_ = new ol.Image(extent, [resolution, resolution], pixelRatio, this.getAttributions(), url, this.crossOrigin_, this.imageLoadFunction_); this.renderedRevision_ = this.getRevision(); diff --git a/test_rendering/spec/ol/data/dem.jpg b/test_rendering/spec/ol/data/dem.jpg new file mode 100644 index 0000000000..ddd2b6b990 Binary files /dev/null and b/test_rendering/spec/ol/data/dem.jpg differ diff --git a/test_rendering/spec/ol/layer/expected/image-canvas-resxy.png b/test_rendering/spec/ol/layer/expected/image-canvas-resxy.png new file mode 100644 index 0000000000..a11beb752c Binary files /dev/null and b/test_rendering/spec/ol/layer/expected/image-canvas-resxy.png differ diff --git a/test_rendering/spec/ol/layer/image.test.js b/test_rendering/spec/ol/layer/image.test.js index 8c3c6bbdc7..cad54bea49 100644 --- a/test_rendering/spec/ol/layer/image.test.js +++ b/test_rendering/spec/ol/layer/image.test.js @@ -4,16 +4,16 @@ describe('ol.rendering.layer.Image', function() { var target, map; - function createMap(renderer) { + function createMap(renderer, center, zoom) { target = createMapDiv(50, 50); map = new ol.Map({ target: target, renderer: renderer, view: new ol.View({ - center: ol.proj.transform( + center: center ? center : ol.proj.transform( [-122.416667, 37.783333], 'EPSG:4326', 'EPSG:3857'), - zoom: 5 + zoom: zoom ? zoom : 5 }) }); return map; @@ -82,6 +82,35 @@ describe('ol.rendering.layer.Image', function() { }); }); }); + + describe('single image layer with different x and y resolutions', function() { + var source; + + beforeEach(function() { + source = new ol.source.ImageStatic({ + url: 'spec/ol/data/dem.jpg', + projection: ol.proj.get('EPSG:3857'), + alwaysInRange: true, + imageSize: [373, 350], + imageExtent: [2077922.782144, 5744637.392734, 2082074.999150, + 5750225.419064] + }); + }); + + afterEach(function() { + disposeMap(map); + }); + + it('tests the canvas renderer', function(done) { + map = createMap('canvas', [2080687.2732495, 5747435.594262], 10); + waitForImages([source], {}, function() { + expectResemble(map, 'spec/ol/layer/expected/image-canvas-resxy.png', + IMAGE_TOLERANCE, done); + }); + }); + + }); + }); goog.require('goog.object');