From 16dbfc62bee7abaf86460d1c390356de2fe5499d Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 13 Nov 2024 16:43:46 -0500 Subject: [PATCH 1/4] Add support for imageSmoothingEnabled to WebGLDrawer --- src/webgldrawer.js | 41 +++++++++++++++++++++++++---------- test/demo/drawercomparison.js | 6 +++++ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/webgldrawer.js b/src/webgldrawer.js index 0489eecb..bd712f28 100644 --- a/src/webgldrawer.js +++ b/src/webgldrawer.js @@ -92,6 +92,8 @@ this._renderingCanvas = null; this._backupCanvasDrawer = null; + this._imageSmoothingEnabled = true; // will be updated by setImageSmoothingEnabled + // Add listeners for events that require modifying the scene or camera this._boundToTileReady = ev => this._tileReadyHandler(ev); this._boundToImageUnloaded = ev => this._imageUnloadedHandler(ev); @@ -135,10 +137,7 @@ gl.bindRenderbuffer(gl.RENDERBUFFER, null); gl.bindFramebuffer(gl.FRAMEBUFFER, null); - let canvases = Array.from(this._TextureMap.keys()); - canvases.forEach(canvas => { - this._cleanupImageData(canvas); // deletes texture, removes from _TextureMap - }); + this._unloadTextures(); // Delete all our created resources gl.deleteBuffer(this._secondPass.bufferOutputPosition); @@ -486,11 +485,18 @@ // Public API required by all Drawer implementations /** - * Required by DrawerBase, but has no effect on WebGLDrawer. - * @param {Boolean} enabled + * Sets whether image smoothing is enabled or disabled + * @param {Boolean} enabled If true, uses gl.LINEAR as the TEXTURE_MIN_FILTER and TEXTURE_MAX_FILTER, otherwise gl.NEAREST. */ setImageSmoothingEnabled(enabled){ - // noop - this property does not impact WebGLDrawer + const changed = this._imageSmoothingEnabled !== enabled; + this._imageSmoothingEnabled = enabled; + if( changed ){ + // We need to unload all existing textures so they can be recreated with the new filter + this._unloadTextures(); + } + // trigger a re-draw + this.viewer.world.draw(); } /** @@ -600,6 +606,11 @@ } + // private + _textureFilter(){ + return this._imageSmoothingEnabled ? this._gl.LINEAR : this._gl.NEAREST; + } + // private _setupRenderer(){ let gl = this._gl; @@ -616,7 +627,7 @@ gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, this._renderToTexture); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this._renderingCanvas.width, this._renderingCanvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this._textureFilter()); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); @@ -815,7 +826,7 @@ gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, this._renderToTexture); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this._textureFilter()); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); @@ -955,8 +966,8 @@ // Set the parameters so we can render any size image. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this._textureFilter()); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this._textureFilter()); // Upload the image into the texture. this._uploadImageData(tileContext); @@ -980,6 +991,14 @@ }; } + // private + _unloadTextures(){ + let canvases = Array.from(this._TextureMap.keys()); + canvases.forEach(canvas => { + this._cleanupImageData(canvas); // deletes texture, removes from _TextureMap + }); + } + // private _uploadImageData(tileContext){ diff --git a/test/demo/drawercomparison.js b/test/demo/drawercomparison.js index bb96219b..16acc74e 100644 --- a/test/demo/drawercomparison.js +++ b/test/demo/drawercomparison.js @@ -193,6 +193,11 @@ function updateTiledImage(tiledImage, data, value, item){ tiledImage.setOpacity(Number(value)); } else if (field == 'flipped'){ tiledImage.setFlip($(item).prop('checked')); + } else if (field == 'smoothing'){ + const checked = $(item).prop('checked'); + viewer1.drawer.setImageSmoothingEnabled(checked); + viewer2.drawer.setImageSmoothingEnabled(checked); + $('[data-field=smoothing]').prop('checked', checked); } else if (field == 'cropped'){ if( $(item).prop('checked') ){ let scale = tiledImage.source.width; @@ -355,6 +360,7 @@ function makeImagePickerElement(key, label){ + `.replaceAll('data-image=""', `data-image="${key}"`).replace('__title__', label)); From 4163a46a244322b155356a26bb15d87392a0c327 Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 13 Nov 2024 16:49:54 -0500 Subject: [PATCH 2/4] Update docs --- src/openseadragon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openseadragon.js b/src/openseadragon.js index 64595c28..eab9841a 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -214,7 +214,7 @@ * For complete list of modes, please @see {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation/ globalCompositeOperation} * * @property {Boolean} [imageSmoothingEnabled=true] - * Image smoothing for canvas rendering (only if the canvas drawer is used). Note: Ignored + * Image smoothing for rendering (only if the canvas or webgl drawer is used). Note: Ignored * by some (especially older) browsers which do not support this canvas property. * This property can be changed in {@link Viewer.DrawerBase.setImageSmoothingEnabled}. * From 02805226d46e72370078d26b0861b9403c51ef54 Mon Sep 17 00:00:00 2001 From: Tom Date: Thu, 14 Nov 2024 13:13:13 -0500 Subject: [PATCH 3/4] only redraw after setImageSmoothingEnabled() when changed --- src/webgldrawer.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/webgldrawer.js b/src/webgldrawer.js index bd712f28..fa61afbc 100644 --- a/src/webgldrawer.js +++ b/src/webgldrawer.js @@ -489,14 +489,11 @@ * @param {Boolean} enabled If true, uses gl.LINEAR as the TEXTURE_MIN_FILTER and TEXTURE_MAX_FILTER, otherwise gl.NEAREST. */ setImageSmoothingEnabled(enabled){ - const changed = this._imageSmoothingEnabled !== enabled; - this._imageSmoothingEnabled = enabled; - if( changed ){ - // We need to unload all existing textures so they can be recreated with the new filter + if( this._imageSmoothingEnabled !== enabled ){ + this._imageSmoothingEnabled = enabled; this._unloadTextures(); + this.viewer.world.draw(); } - // trigger a re-draw - this.viewer.world.draw(); } /** From 0e3abe16f4849365ec0b5b0673bc37ce47c0cdc0 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Fri, 15 Nov 2024 09:32:07 -0800 Subject: [PATCH 4/4] Changelog for #2615 --- changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.txt b/changelog.txt index e8778d25..f8d2cfec 100644 --- a/changelog.txt +++ b/changelog.txt @@ -4,6 +4,7 @@ OPENSEADRAGON CHANGELOG 5.0.1: (in progress...) * Improved overlay handling so it plays better with other libraries (#2582 @BeebBenjamin) +* WebGLDrawer now supports the imageSmoothingEnabled option (#2615 @pearcetm) * Fixed: If you switched from WebGL drawer to canvas drawer, it didn't clean up properly (#2570 @pearcetm) * Fixed: TiledImage.setClip would sometimes leave tiles unloaded (#2590 @pearcetm) * Fixed: The WebGL drawer didn't support viewportMargins (#2600, #2606 @pearcetm)