Added switch to smoothly or unsmoothly render images on the canvas: imageSmoothingEnabled (true (default), false). Medical images can thus be displayed in more pixelated, unsmoothed manner.

This commit is contained in:
Peter 2018-07-30 20:00:58 -04:00
parent d353580471
commit 19f7b80dca
5 changed files with 69 additions and 6 deletions

View File

@ -300,12 +300,13 @@ $.Drawer.prototype = {
* @param {Float} [scale=1] - Apply a scale to tile position and size. Defaults to 1. * @param {Float} [scale=1] - Apply a scale to tile position and size. Defaults to 1.
* @param {OpenSeadragon.Point} [translate] A translation vector to offset tile position * @param {OpenSeadragon.Point} [translate] A translation vector to offset tile position
*/ */
drawTile: function(tile, drawingHandler, useSketch, scale, translate) { drawTile: function(tile, drawingHandler, useSketch, scale, translate, imageSmoothingEnabled) {
$.console.assert(tile, '[Drawer.drawTile] tile is required'); $.console.assert(tile, '[Drawer.drawTile] tile is required');
$.console.assert(drawingHandler, '[Drawer.drawTile] drawingHandler is required'); $.console.assert(drawingHandler, '[Drawer.drawTile] drawingHandler is required');
if (this.useCanvas) { if (this.useCanvas) {
var context = this._getContext(useSketch); var context = this._getContext(useSketch);
context.imageSmoothingEnabled = imageSmoothingEnabled;
scale = scale || 1; scale = scale || 1;
tile.drawCanvas(context, drawingHandler, scale, translate); tile.drawCanvas(context, drawingHandler, scale, translate);
} else { } else {
@ -399,18 +400,22 @@ $.Drawer.prototype = {
* @param {String} [options.compositeOperation] - How the image is * @param {String} [options.compositeOperation] - How the image is
* composited onto other images; see compositeOperation in * composited onto other images; see compositeOperation in
* {@link OpenSeadragon.Options} for possible values. * {@link OpenSeadragon.Options} for possible values.
* @param {Boolean} [options.imageSmoothingEnabled] - Wether or not the image is
* drawn smoothly on the canvas; see imageSmoothingEnabled in
* {@link OpenSeadragon.Options} for more explanation.
* @param {OpenSeadragon.Rect} [options.bounds] The part of the sketch * @param {OpenSeadragon.Rect} [options.bounds] The part of the sketch
* canvas to blend in the main canvas. If specified, options.scale and * canvas to blend in the main canvas. If specified, options.scale and
* options.translate get ignored. * options.translate get ignored.
*/ */
blendSketch: function(opacity, scale, translate, compositeOperation) { blendSketch: function(opacity, scale, translate, compositeOperation, imageSmoothingEnabled) {
var options = opacity; var options = opacity;
if (!$.isPlainObject(options)) { if (!$.isPlainObject(options)) {
options = { options = {
opacity: opacity, opacity: opacity,
scale: scale, scale: scale,
translate: translate, translate: translate,
compositeOperation: compositeOperation compositeOperation: compositeOperation,
imageSmoothingEnabled: imageSmoothingEnabled
}; };
} }
if (!this.useCanvas || !this.sketchCanvas) { if (!this.useCanvas || !this.sketchCanvas) {
@ -418,10 +423,12 @@ $.Drawer.prototype = {
} }
opacity = options.opacity; opacity = options.opacity;
compositeOperation = options.compositeOperation; compositeOperation = options.compositeOperation;
imageSmoothingEnabled = options.imageSmoothingEnabled;
var bounds = options.bounds; var bounds = options.bounds;
this.context.save(); this.context.save();
this.context.globalAlpha = opacity; this.context.globalAlpha = opacity;
this.context.imageSmoothingEnabled = imageSmoothingEnabled;
if (compositeOperation) { if (compositeOperation) {
this.context.globalCompositeOperation = compositeOperation; this.context.globalCompositeOperation = compositeOperation;
} }

View File

@ -377,10 +377,15 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /*
_this._matchCompositeOperation(myItem, original); _this._matchCompositeOperation(myItem, original);
} }
function matchImageSmoothingEnabled() {
_this._matchImageSmoothingEnabled(myItem, original);
}
original.addHandler('bounds-change', matchBounds); original.addHandler('bounds-change', matchBounds);
original.addHandler('clip-change', matchBounds); original.addHandler('clip-change', matchBounds);
original.addHandler('opacity-change', matchOpacity); original.addHandler('opacity-change', matchOpacity);
original.addHandler('composite-operation-change', matchCompositeOperation); original.addHandler('composite-operation-change', matchCompositeOperation);
original.addHandler('image-rendering-change', matchImageSmoothingEnabled);
} }
}); });
@ -418,6 +423,11 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /*
// private // private
_matchCompositeOperation: function(myItem, theirItem) { _matchCompositeOperation: function(myItem, theirItem) {
myItem.setCompositeOperation(theirItem.compositeOperation); myItem.setCompositeOperation(theirItem.compositeOperation);
},
// private
_matchImageSmoothingEnabled: function(myItem, theirItem) {
myItem.setImageSmoothingEnabled(theirItem.imageSmoothingEnabled);
} }
}); });

View File

@ -198,6 +198,10 @@
* 'destination-over', 'destination-atop', 'destination-in', * 'destination-over', 'destination-atop', 'destination-in',
* 'destination-out', 'lighter', 'copy' or 'xor' * 'destination-out', 'lighter', 'copy' or 'xor'
* *
* @property {Boolean} [imageSmoothingEnabled=true]
* Image smoothing for canvas rendering (only if canvas is used). Not every browser
* is compatible with this option. Valid values are true (default) and false.
*
* @property {String|CanvasGradient|CanvasPattern|Function} [placeholderFillStyle=null] * @property {String|CanvasGradient|CanvasPattern|Function} [placeholderFillStyle=null]
* Draws a colored rectangle behind the tile if it is not loaded yet. * Draws a colored rectangle behind the tile if it is not loaded yet.
* You can pass a CSS color value like "#FF8800". * You can pass a CSS color value like "#FF8800".
@ -1178,6 +1182,7 @@ function OpenSeadragon( options ){
opacity: 1, opacity: 1,
preload: false, preload: false,
compositeOperation: null, compositeOperation: null,
imageSmoothingEnabled: true,
placeholderFillStyle: null, placeholderFillStyle: null,
//REFERENCE STRIP SETTINGS //REFERENCE STRIP SETTINGS

View File

@ -73,6 +73,7 @@
* @param {Number} [options.opacity=1] - Set to draw at proportional opacity. If zero, images will not draw. * @param {Number} [options.opacity=1] - Set to draw at proportional opacity. If zero, images will not draw.
* @param {Boolean} [options.preload=false] - Set true to load even when the image is hidden by zero opacity. * @param {Boolean} [options.preload=false] - Set true to load even when the image is hidden by zero opacity.
* @param {String} [options.compositeOperation] - How the image is composited onto other images; see compositeOperation in {@link OpenSeadragon.Options} for possible values. * @param {String} [options.compositeOperation] - How the image is composited onto other images; see compositeOperation in {@link OpenSeadragon.Options} for possible values.
* @param {Boolean} [options.imageSmoothingEnabled] - How the image is rendered on the canvas; see imageSmoothingEnabled in {@link OpenSeadragon.Options} for more explanation.
* @param {Boolean} [options.debugMode] - See {@link OpenSeadragon.Options}. * @param {Boolean} [options.debugMode] - See {@link OpenSeadragon.Options}.
* @param {String|CanvasGradient|CanvasPattern|Function} [options.placeholderFillStyle] - See {@link OpenSeadragon.Options}. * @param {String|CanvasGradient|CanvasPattern|Function} [options.placeholderFillStyle] - See {@link OpenSeadragon.Options}.
* @param {String|Boolean} [options.crossOriginPolicy] - See {@link OpenSeadragon.Options}. * @param {String|Boolean} [options.crossOriginPolicy] - See {@link OpenSeadragon.Options}.
@ -177,7 +178,8 @@ $.TiledImage = function( options ) {
placeholderFillStyle: $.DEFAULT_SETTINGS.placeholderFillStyle, placeholderFillStyle: $.DEFAULT_SETTINGS.placeholderFillStyle,
opacity: $.DEFAULT_SETTINGS.opacity, opacity: $.DEFAULT_SETTINGS.opacity,
preload: $.DEFAULT_SETTINGS.preload, preload: $.DEFAULT_SETTINGS.preload,
compositeOperation: $.DEFAULT_SETTINGS.compositeOperation compositeOperation: $.DEFAULT_SETTINGS.compositeOperation,
imageSmoothingEnabled: $.DEFAULT_SETTINGS.imageSmoothingEnabled
}, options ); }, options );
this._preload = this.preload; this._preload = this.preload;
@ -899,6 +901,39 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
}); });
}, },
/**
* @returns {Boolean} Weather of not the current TiledImage is smoothed on the canvas.
*/
getImageSmoothingEnabled: function() {
return this.imageSmoothingEnabled;
},
/**
* @param {Boolean} imageSmoothingEnabled if the tiled image should be drawn smoothly or not.
* @fires OpenSeadragon.TiledImage.event:image-rendering-change
*/
setImageSmoothingEnabled: function(imageSmoothingEnabled) {
if (imageSmoothingEnabled === this.imageSmoothingEnabled) {
return;
}
this.imageSmoothingEnabled = imageSmoothingEnabled;
this._needsDraw = true;
/**
* Raised when the TiledImage's rendering option has changed.
* @event image-rendering-change
* @memberOf OpenSeadragon.TiledImage
* @type {object}
* @property {Boolean} imageSmoothingEnabled - The new image smoothing value (true or false).
* @property {OpenSeadragon.TiledImage} eventSource - A reference to the
* TiledImage which raised the event.
* @property {?Object} userData - Arbitrary subscriber-defined object.
*/
this.raiseEvent('image-rendering-change', {
imageSmoothingEnabled: this.imageSmoothingEnabled
});
},
// private // private
_setScale: function(scale, immediately) { _setScale: function(scale, immediately) {
var sameTarget = (this._scaleSpring.target.value === scale); var sameTarget = (this._scaleSpring.target.value === scale);
@ -1946,7 +1981,7 @@ function drawTiles( tiledImage, lastDrawn ) {
for (var i = lastDrawn.length - 1; i >= 0; i--) { for (var i = lastDrawn.length - 1; i >= 0; i--) {
tile = lastDrawn[i]; tile = lastDrawn[i];
tiledImage._drawer.drawTile( tile, tiledImage._drawingHandler, useSketch, sketchScale, sketchTranslate ); tiledImage._drawer.drawTile(tile, tiledImage._drawingHandler, useSketch, sketchScale, sketchTranslate, tiledImage.imageSmoothingEnabled);
tile.beingDrawn = true; tile.beingDrawn = true;
if( tiledImage.viewer ){ if( tiledImage.viewer ){
@ -2007,6 +2042,7 @@ function drawTiles( tiledImage, lastDrawn ) {
scale: sketchScale, scale: sketchScale,
translate: sketchTranslate, translate: sketchTranslate,
compositeOperation: tiledImage.compositeOperation, compositeOperation: tiledImage.compositeOperation,
imageSmoothingEnabled: tiledImage.imageSmoothingEnabled,
bounds: bounds bounds: bounds
}); });
if (sketchScale) { if (sketchScale) {

View File

@ -1265,6 +1265,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
* @param {Number} [options.degrees=0] Initial rotation of the tiled image around * @param {Number} [options.degrees=0] Initial rotation of the tiled image around
* its top left corner in degrees. * its top left corner in degrees.
* @param {String} [options.compositeOperation] How the image is composited onto other images. * @param {String} [options.compositeOperation] How the image is composited onto other images.
* @param {String} [options.imageSmoothingEnabled] If the image is drawn smoothly or not on the canvas.
* @param {String} [options.crossOriginPolicy] The crossOriginPolicy for this specific image, * @param {String} [options.crossOriginPolicy] The crossOriginPolicy for this specific image,
* overriding viewer.crossOriginPolicy. * overriding viewer.crossOriginPolicy.
* @param {Boolean} [options.ajaxWithCredentials] Whether to set withCredentials on tile AJAX * @param {Boolean} [options.ajaxWithCredentials] Whether to set withCredentials on tile AJAX
@ -1314,6 +1315,9 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
if (options.compositeOperation === undefined) { if (options.compositeOperation === undefined) {
options.compositeOperation = this.compositeOperation; options.compositeOperation = this.compositeOperation;
} }
if (options.imageSmoothingEnabled === undefined) {
options.imageSmoothingEnabled = this.imageSmoothingEnabled;
}
if (options.crossOriginPolicy === undefined) { if (options.crossOriginPolicy === undefined) {
options.crossOriginPolicy = options.tileSource.crossOriginPolicy !== undefined ? options.tileSource.crossOriginPolicy : this.crossOriginPolicy; options.crossOriginPolicy = options.tileSource.crossOriginPolicy !== undefined ? options.tileSource.crossOriginPolicy : this.crossOriginPolicy;
} }
@ -1427,6 +1431,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
preload: queueItem.options.preload, preload: queueItem.options.preload,
degrees: queueItem.options.degrees, degrees: queueItem.options.degrees,
compositeOperation: queueItem.options.compositeOperation, compositeOperation: queueItem.options.compositeOperation,
imageSmoothingEnabled: queueItem.options.imageSmoothingEnabled,
springStiffness: _this.springStiffness, springStiffness: _this.springStiffness,
animationTime: _this.animationTime, animationTime: _this.animationTime,
minZoomImageRatio: _this.minZoomImageRatio, minZoomImageRatio: _this.minZoomImageRatio,