diff --git a/changelog.txt b/changelog.txt index 3ddcd4bd..e416df23 100644 --- a/changelog.txt +++ b/changelog.txt @@ -36,6 +36,7 @@ OPENSEADRAGON CHANGELOG * New Viewport method for managing homeBounds as well as constraints: setHomeBounds * Viewport.open supports positioning config properties * For multi-image open, drawing isn't started until all tileSources have been opened + * You can specify a clip area for each image (only works on browsers that support the HTML5 canvas) (#594) * Margins option to push the home region in from the edges of the Viewer (#505) * Rect and Point toString() functions are now consistent: rounding values to nearest hundredth * Overlays appear in the DOM immediately on open or addOverlay (#507) diff --git a/src/drawer.js b/src/drawer.js index 77f078ad..1f18f102 100644 --- a/src/drawer.js +++ b/src/drawer.js @@ -258,6 +258,35 @@ $.Drawer.prototype = /** @lends OpenSeadragon.Drawer.prototype */{ } }, + // private + saveContext: function() { + if (!this.useCanvas) { + return; + } + + this.context.save(); + }, + + // private + restoreContext: function() { + if (!this.useCanvas) { + return; + } + + this.context.restore(); + }, + + // private + setClip: function(rect) { + if (!this.useCanvas) { + return; + } + + this.context.beginPath(); + this.context.rect(rect.x, rect.y, rect.width, rect.height); + this.context.clip(); + }, + // private drawDebugInfo: function( tile, count, i ){ if ( this.useCanvas ) { diff --git a/src/tiledimage.js b/src/tiledimage.js index 9431502a..405989b7 100644 --- a/src/tiledimage.js +++ b/src/tiledimage.js @@ -52,6 +52,9 @@ * @param {Number} [options.y=0] - Top position, in viewport coordinates. * @param {Number} [options.width=1] - Width, in viewport coordinates. * @param {Number} [options.height] - Height, in viewport coordinates. + * @param {OpenSeadragon.Rect} [options.clip] - An area, in image pixels, to clip to + * (portions of the image outside of this area will not be visible). Only works on + * browsers that support the HTML5 canvas. * @param {Number} [options.springStiffness] - See {@link OpenSeadragon.Options}. * @param {Boolean} [options.animationTime] - See {@link OpenSeadragon.Options}. * @param {Number} [options.minZoomImageRatio] - See {@link OpenSeadragon.Options}. @@ -72,6 +75,8 @@ $.TiledImage = function( options ) { $.console.assert( options.viewer, "[TiledImage] options.viewer is required" ); $.console.assert( options.imageLoader, "[TiledImage] options.imageLoader is required" ); $.console.assert( options.source, "[TiledImage] options.source is required" ); + $.console.assert(!options.clip || options.clip instanceof $.Rect, + "[TiledImage] options.clip must be an OpenSeadragon.Rect if present"); $.EventSource.call( this ); @@ -84,6 +89,12 @@ $.TiledImage = function( options ) { this._imageLoader = options.imageLoader; delete options.imageLoader; + if (options.clip instanceof $.Rect) { + this._clip = options.clip.clone(); + } + + delete options.clip; + var x = options.x || 0; delete options.x; var y = options.y || 0; @@ -443,6 +454,36 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag this._setScale(height / this.normHeight, immediately); }, + /** + * @returns {OpenSeadragon.Rect|null} The TiledImage's current clip rectangle, + * in image pixels, or null if none. + */ + getClip: function() { + if (this._clip) { + return this._clip.clone(); + } + + return null; + }, + + /** + * @param {OpenSeadragon.Rect|null} newClip - An area, in image pixels, to clip to + * (portions of the image outside of this area will not be visible). Only works on + * browsers that support the HTML5 canvas. + */ + setClip: function(newClip) { + $.console.assert(!newClip || newClip instanceof $.Rect, + "[TiledImage.setClip] newClip must be an OpenSeadragon.Rect or null"); + + if (newClip instanceof $.Rect) { + this._clip = newClip.clone(); + } else { + this._clip = null; + } + + this._needsDraw = true; + }, + // private _setScale: function(scale, immediately) { var sameTarget = (this._scaleSpring.target.value === scale); @@ -1116,6 +1157,20 @@ function drawTiles( tiledImage, lastDrawn ){ position, tileSource; + var usedClip = false; + if (tiledImage._clip) { + tiledImage._drawer.saveContext(); + var box = tiledImage.imageToViewportRectangle(tiledImage._clip, true); + var topLeft = tiledImage.viewport.pixelFromPoint(box.getTopLeft(), true); + var size = tiledImage.viewport.deltaPixelsFromPoints(box.getSize(), true); + box = new OpenSeadragon.Rect(topLeft.x * $.pixelDensityRatio, + topLeft.y * $.pixelDensityRatio, + size.x * $.pixelDensityRatio, + size.y * $.pixelDensityRatio); + tiledImage._drawer.setClip(box); + usedClip = true; + } + for ( i = lastDrawn.length - 1; i >= 0; i-- ) { tile = lastDrawn[ i ]; tiledImage._drawer.drawTile( tile, tiledImage._drawingHandler ); @@ -1147,6 +1202,10 @@ function drawTiles( tiledImage, lastDrawn ){ }); } } + + if (usedClip) { + tiledImage._drawer.restoreContext(); + } } }( OpenSeadragon )); diff --git a/src/viewer.js b/src/viewer.js index 155174d4..7b269350 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -1195,6 +1195,9 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, * @param {Number} [options.y=0] The Y position for the image in viewport coordinates. * @param {Number} [options.width=1] The width for the image in viewport coordinates. * @param {Number} [options.height] The height for the image in viewport coordinates. + * @param {OpenSeadragon.Rect} [options.clip] - An area, in image pixels, to clip to + * (portions of the image outside of this area will not be visible). Only works on + * browsers that support the HTML5 canvas. * @param {Function} [options.success] A function that gets called when the image is * successfully added. It's passed the event object which contains a single property: * "item", the resulting TiledImage. @@ -1280,6 +1283,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype, y: queueItem.options.y, width: queueItem.options.width, height: queueItem.options.height, + clip: queueItem.options.clip, springStiffness: _this.springStiffness, animationTime: _this.animationTime, minZoomImageRatio: _this.minZoomImageRatio, diff --git a/test/demo/m2/index.html b/test/demo/m2/index.html index ca46fedd..fc838579 100644 --- a/test/demo/m2/index.html +++ b/test/demo/m2/index.html @@ -7,7 +7,7 @@ - +