From c578eb715d1e316a46ddf058319a9b82fd0e8e59 Mon Sep 17 00:00:00 2001 From: ilan-gold <ilanbassgold@gmail.com> Date: Thu, 25 Aug 2022 15:29:07 +0200 Subject: [PATCH 01/11] try triming. --- .../multiscale-image-layer.js | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js index cdb0fe124..bdc2ee7e1 100644 --- a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js +++ b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js @@ -84,10 +84,29 @@ const MultiscaleImageLayer = class extends CompositeLayer { // The image-tile example works without, this but I have a feeling there is something // going on with our pyramids and/or rendering that is different. const resolution = Math.round(-z); + const planarSize = loader[0].shape.slice(-2); + const [clippedHeight, clippedWidth] = planarSize.map(size => Math.ceil(size / (2 ** resolution))); + const useClippedHeight = clippedHeight < tileSize; + const useClippedWidth = clippedWidth < tileSize; const getTile = selection => { const config = { x, y, selection, signal }; return loader[resolution].getTile(config); }; + const clip = tile => { + if ((useClippedHeight || useClippedWidth) && (clippedHeight * clippedWidth !== tile.length)) { + return tile.filter((data, ind) => { + if ( + (ind % tileSize >= clippedWidth && useClippedWidth) || + (useClippedHeight && + Math.floor(ind / clippedWidth) >= clippedHeight) + ) { + return false; + } + return true; + }); + } + return tile; + } try { /* @@ -101,10 +120,11 @@ const MultiscaleImageLayer = class extends CompositeLayer { const tiles = await Promise.all(selections.map(getTile)); const tile = { - data: tiles.map(d => d.data), - width: tiles[0].width, - height: tiles[0].height + data: tiles.map(d => clip(d.data)), + width: useClippedWidth ? clippedWidth : tiles[0].width, + height: useClippedHeight ? clippedHeight : tiles[0].height }; + console.log(tile, clippedHeight, clippedWidth) if (isInterleaved(loader[resolution].shape)) { // eslint-disable-next-line prefer-destructuring From 3a79102c0beb2f2dc30326af1bf4baba617d583c Mon Sep 17 00:00:00 2001 From: ilan-gold <ilanbassgold@gmail.com> Date: Thu, 25 Aug 2022 16:46:13 +0200 Subject: [PATCH 02/11] (fix): `getTileData` args changed --- .../src/multiscale-image-layer/multiscale-image-layer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js index cdb0fe124..b0d453763 100644 --- a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js +++ b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js @@ -66,12 +66,11 @@ const MultiscaleImageLayer = class extends CompositeLayer { } = this.props; // Get properties from highest resolution const { tileSize, dtype } = loader[0]; - // This is basically to invert: // https://github.com/visgl/deck.gl/pull/4616/files#diff-4d6a2e500c0e79e12e562c4f1217dc80R128 // The z level can be wrong for showing the correct scales because of the calculation deck.gl does // so we need to invert it for fetching tiles and minZoom/maxZoom. - const getTileData = async ({ x, y, z, signal }) => { + const getTileData = async ({ index: { x, y, z }, signal }) => { // Early return if no selections if (!selections || selections.length === 0) { return null; @@ -84,6 +83,7 @@ const MultiscaleImageLayer = class extends CompositeLayer { // The image-tile example works without, this but I have a feeling there is something // going on with our pyramids and/or rendering that is different. const resolution = Math.round(-z); + console.log(resolution, z); const getTile = selection => { const config = { x, y, selection, signal }; return loader[resolution].getTile(config); From f69ef2063688229164537ec0eabf764227b2f977 Mon Sep 17 00:00:00 2001 From: ilan-gold <ilanbassgold@gmail.com> Date: Thu, 25 Aug 2022 17:04:31 +0200 Subject: [PATCH 03/11] Fix clipping. --- .../multiscale-image-layer.js | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js index 555d10a54..a3584f765 100644 --- a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js +++ b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js @@ -83,8 +83,17 @@ const MultiscaleImageLayer = class extends CompositeLayer { // The image-tile example works without, this but I have a feeling there is something // going on with our pyramids and/or rendering that is different. const resolution = Math.round(-z); + + // Here we set up variables for checking whether or not we should cip the black border of incoming tiles + // at low resolutions i.e for zarr tiles. We need to check a few things before trimming: + // 1. The height/width of the full image at the current resolution produces an image smaller than the current tileSize + // 2. The incoming image is not exactly this size (i.e tiles that are not "padded" as in zarr) + // Once these have been confirmed, we trim the tile by going over it in row major order, + // keeping only the data that is not out of the clipped bounds. const planarSize = loader[0].shape.slice(-2); - const [clippedHeight, clippedWidth] = planarSize.map(size => Math.ceil(size / (2 ** resolution))); + const [clippedHeight, clippedWidth] = planarSize.map(size => + Math.floor(size / 2 ** resolution) + ); const useClippedHeight = clippedHeight < tileSize; const useClippedWidth = clippedWidth < tileSize; const getTile = selection => { @@ -92,20 +101,20 @@ const MultiscaleImageLayer = class extends CompositeLayer { return loader[resolution].getTile(config); }; const clip = tile => { - if ((useClippedHeight || useClippedWidth) && (clippedHeight * clippedWidth !== tile.length)) { + if ( + (useClippedHeight || useClippedWidth) && + clippedHeight * clippedWidth !== tile.length + ) { return tile.filter((data, ind) => { - if ( + return !( (ind % tileSize >= clippedWidth && useClippedWidth) || (useClippedHeight && Math.floor(ind / clippedWidth) >= clippedHeight) - ) { - return false; - } - return true; + ); }); } return tile; - } + }; try { /* @@ -117,13 +126,11 @@ const MultiscaleImageLayer = class extends CompositeLayer { * return type, and optional throw for performance. */ const tiles = await Promise.all(selections.map(getTile)); - const tile = { data: tiles.map(d => clip(d.data)), width: useClippedWidth ? clippedWidth : tiles[0].width, height: useClippedHeight ? clippedHeight : tiles[0].height }; - console.log(tile, clippedHeight, clippedWidth) if (isInterleaved(loader[resolution].shape)) { // eslint-disable-next-line prefer-destructuring From 2ea8f61be6d82c25b1ed31ed8d793f64c7cb7142 Mon Sep 17 00:00:00 2001 From: ilan-gold <ilanbassgold@gmail.com> Date: Thu, 25 Aug 2022 17:17:50 +0200 Subject: [PATCH 04/11] [wip] figuring out right condition. --- .../multiscale-image-layer.js | 44 +++++++++++++++---- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js index a3584f765..8dc788e20 100644 --- a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js +++ b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js @@ -100,20 +100,34 @@ const MultiscaleImageLayer = class extends CompositeLayer { const config = { x, y, selection, signal }; return loader[resolution].getTile(config); }; - const clip = tile => { + const clip = ({ data, height, width }) => { + console.log( + tileSize, + useClippedHeight, + useClippedWidth, + clippedHeight, + clippedWidth, + data.length, + resolution, + width, + height + ); if ( (useClippedHeight || useClippedWidth) && - clippedHeight * clippedWidth !== tile.length + width !== clippedHeight && height !== clippedHeight ) { - return tile.filter((data, ind) => { + return data.filter((d, ind) => { return !( - (ind % tileSize >= clippedWidth && useClippedWidth) || + (ind % tileSize >= clippedWidth && + useClippedWidth && + ) || (useClippedHeight && - Math.floor(ind / clippedWidth) >= clippedHeight) + Math.floor(ind / clippedWidth) >= clippedHeight && + height !== clippedHeight) ); }); } - return tile; + return data; }; try { @@ -127,9 +141,21 @@ const MultiscaleImageLayer = class extends CompositeLayer { */ const tiles = await Promise.all(selections.map(getTile)); const tile = { - data: tiles.map(d => clip(d.data)), - width: useClippedWidth ? clippedWidth : tiles[0].width, - height: useClippedHeight ? clippedHeight : tiles[0].height + data: tiles.map(d => + clip({ + data: d.data, + width: tiles[0].width, + height: tiles[0].height + }) + ), + width: + useClippedWidth && tiles[0].height !== tileSize + ? clippedWidth + : tiles[0].width, + height: + useClippedHeight && tiles[0].height !== tileSize + ? clippedHeight + : tiles[0].height }; if (isInterleaved(loader[resolution].shape)) { From 46e3fd380657650140b2d5dad9c0c5243ecc2e69 Mon Sep 17 00:00:00 2001 From: ilan-gold <ilanbassgold@gmail.com> Date: Thu, 25 Aug 2022 17:31:56 +0200 Subject: [PATCH 05/11] Fix conditions --- .../multiscale-image-layer.js | 38 +++++++------------ 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js index 8dc788e20..e2aee9840 100644 --- a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js +++ b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js @@ -86,44 +86,32 @@ const MultiscaleImageLayer = class extends CompositeLayer { // Here we set up variables for checking whether or not we should cip the black border of incoming tiles // at low resolutions i.e for zarr tiles. We need to check a few things before trimming: - // 1. The height/width of the full image at the current resolution produces an image smaller than the current tileSize - // 2. The incoming image is not exactly this size (i.e tiles that are not "padded" as in zarr) + // 1. The height/width of the full image at the current resolution + // produces an image smaller than the current tileSize + // 2. The incoming image is indeed padded out to the tile size + // in some dimension i.e it should be clipped down to the smaller size // Once these have been confirmed, we trim the tile by going over it in row major order, // keeping only the data that is not out of the clipped bounds. const planarSize = loader[0].shape.slice(-2); const [clippedHeight, clippedWidth] = planarSize.map(size => Math.floor(size / 2 ** resolution) ); - const useClippedHeight = clippedHeight < tileSize; - const useClippedWidth = clippedWidth < tileSize; + const isHeightUnderTileSize = clippedHeight < tileSize; + const isWidthUnderTileSize = clippedWidth < tileSize; const getTile = selection => { const config = { x, y, selection, signal }; return loader[resolution].getTile(config); }; const clip = ({ data, height, width }) => { - console.log( - tileSize, - useClippedHeight, - useClippedWidth, - clippedHeight, - clippedWidth, - data.length, - resolution, - width, - height - ); if ( - (useClippedHeight || useClippedWidth) && - width !== clippedHeight && height !== clippedHeight + (isHeightUnderTileSize && height === tileSize) || + (width === tileSize && isWidthUnderTileSize) ) { return data.filter((d, ind) => { return !( - (ind % tileSize >= clippedWidth && - useClippedWidth && - ) || - (useClippedHeight && - Math.floor(ind / clippedWidth) >= clippedHeight && - height !== clippedHeight) + (ind % tileSize >= clippedWidth && isWidthUnderTileSize) || + (isHeightUnderTileSize && + Math.floor(ind / clippedWidth) >= clippedHeight) ); }); } @@ -149,11 +137,11 @@ const MultiscaleImageLayer = class extends CompositeLayer { }) ), width: - useClippedWidth && tiles[0].height !== tileSize + isWidthUnderTileSize && tiles[0].height === tileSize ? clippedWidth : tiles[0].width, height: - useClippedHeight && tiles[0].height !== tileSize + isHeightUnderTileSize && tiles[0].height === tileSize ? clippedHeight : tiles[0].height }; From 914b4f9de211cdb0242a755aa50c7d68bb3b390b Mon Sep 17 00:00:00 2001 From: ilan-gold <ilanbassgold@gmail.com> Date: Tue, 30 Aug 2022 18:30:57 +0200 Subject: [PATCH 06/11] tileSize! --- .../layers/src/multiscale-image-layer/multiscale-image-layer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js index e2aee9840..d119d09e7 100644 --- a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js +++ b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js @@ -111,7 +111,7 @@ const MultiscaleImageLayer = class extends CompositeLayer { return !( (ind % tileSize >= clippedWidth && isWidthUnderTileSize) || (isHeightUnderTileSize && - Math.floor(ind / clippedWidth) >= clippedHeight) + Math.floor(ind / tileSize) >= clippedHeight) ); }); } From b61e5fb040dfead28f323782e08627a586cd17e0 Mon Sep 17 00:00:00 2001 From: ilan-gold <ilanbassgold@gmail.com> Date: Wed, 31 Aug 2022 19:01:29 +0200 Subject: [PATCH 07/11] (refactor): use `getImageSize` --- .../layers/src/multiscale-image-layer/multiscale-image-layer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js index d119d09e7..6e35ebd8f 100644 --- a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js +++ b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js @@ -92,7 +92,7 @@ const MultiscaleImageLayer = class extends CompositeLayer { // in some dimension i.e it should be clipped down to the smaller size // Once these have been confirmed, we trim the tile by going over it in row major order, // keeping only the data that is not out of the clipped bounds. - const planarSize = loader[0].shape.slice(-2); + const planarSize = getImageSize(loader[0]); const [clippedHeight, clippedWidth] = planarSize.map(size => Math.floor(size / 2 ** resolution) ); From f1a49e131552808343dbde23a7d563a34395849b Mon Sep 17 00:00:00 2001 From: ilan-gold <ilanbassgold@gmail.com> Date: Wed, 31 Aug 2022 19:24:11 +0200 Subject: [PATCH 08/11] (refactor): make `createTileClipper` function. --- .../multiscale-image-layer.js | 86 +++++++++++-------- 1 file changed, 50 insertions(+), 36 deletions(-) diff --git a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js index 6e35ebd8f..34b896a77 100644 --- a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js +++ b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js @@ -7,6 +7,50 @@ import ImageLayer from '../image-layer'; import { getImageSize, isInterleaved, SIGNAL_ABORTED } from '@vivjs/loaders'; import { ColorPaletteExtension } from '@vivjs/extensions'; +/** + * Here we create an object for checking clipping the black border of incoming tiles + * at low resolutions i.e for zarr tiles which are padded by zarr. + * We need to check a few things before trimming: + * 1. The height/width of the full image at the current resolution + * produces an image smaller than the current tileSize + * 2. The incoming image is padded to the tile size i.e one of its dimensions matches the tile size + * Once these have been confirmed, we trim the tile by going over it in row major order, + * keeping only the data that is not out of the clipped bounds. + * @param {{ + * loader: PixelSource[], + * resolution: number, + * tileSize: number, + * }} + * @return {{ clip: function, height: number, width: number }} + */ +const createTileClipper = ({ loader, resolution, tileSize }) => { + const planarSize = Object.values(getImageSize(loader[0])); + const [clippedHeight, clippedWidth] = planarSize.map(size => + Math.floor(size / 2 ** resolution) + ); + const isHeightUnderTileSize = clippedHeight < tileSize; + const isWidthUnderTileSize = clippedWidth < tileSize; + return { + clip: ({ data, height, width }) => { + if ( + (isHeightUnderTileSize && height === tileSize) || + (width === tileSize && isWidthUnderTileSize) + ) { + return data.filter((d, ind) => { + return !( + (ind % tileSize >= clippedWidth && isWidthUnderTileSize) || + (isHeightUnderTileSize && + Math.floor(ind / tileSize) >= clippedHeight) + ); + }); + } + return data; + }, + height: clippedHeight, + width: clippedWidth + }; +}; + const defaultProps = { pickable: { type: 'boolean', value: true, compare: true }, onHover: { type: 'function', value: null, compare: false }, @@ -83,41 +127,11 @@ const MultiscaleImageLayer = class extends CompositeLayer { // The image-tile example works without, this but I have a feeling there is something // going on with our pyramids and/or rendering that is different. const resolution = Math.round(-z); - - // Here we set up variables for checking whether or not we should cip the black border of incoming tiles - // at low resolutions i.e for zarr tiles. We need to check a few things before trimming: - // 1. The height/width of the full image at the current resolution - // produces an image smaller than the current tileSize - // 2. The incoming image is indeed padded out to the tile size - // in some dimension i.e it should be clipped down to the smaller size - // Once these have been confirmed, we trim the tile by going over it in row major order, - // keeping only the data that is not out of the clipped bounds. - const planarSize = getImageSize(loader[0]); - const [clippedHeight, clippedWidth] = planarSize.map(size => - Math.floor(size / 2 ** resolution) - ); - const isHeightUnderTileSize = clippedHeight < tileSize; - const isWidthUnderTileSize = clippedWidth < tileSize; const getTile = selection => { const config = { x, y, selection, signal }; return loader[resolution].getTile(config); }; - const clip = ({ data, height, width }) => { - if ( - (isHeightUnderTileSize && height === tileSize) || - (width === tileSize && isWidthUnderTileSize) - ) { - return data.filter((d, ind) => { - return !( - (ind % tileSize >= clippedWidth && isWidthUnderTileSize) || - (isHeightUnderTileSize && - Math.floor(ind / tileSize) >= clippedHeight) - ); - }); - } - return data; - }; - + const clipper = createTileClipper({ loader, resolution, tileSize }); try { /* * Try to request the tile data. The pixels sources can throw @@ -130,19 +144,19 @@ const MultiscaleImageLayer = class extends CompositeLayer { const tiles = await Promise.all(selections.map(getTile)); const tile = { data: tiles.map(d => - clip({ + clipper.clip({ data: d.data, width: tiles[0].width, height: tiles[0].height }) ), width: - isWidthUnderTileSize && tiles[0].height === tileSize - ? clippedWidth + clipper.width < tileSize && tiles[0].width === tileSize + ? clipper.width : tiles[0].width, height: - isHeightUnderTileSize && tiles[0].height === tileSize - ? clippedHeight + clipper.height < tileSize && tiles[0].height === tileSize + ? clipper.height : tiles[0].height }; From 2aa66ad8f7dd87b3a91aa8917198cf0d4a85f1bd Mon Sep 17 00:00:00 2001 From: ilan-gold <ilanbassgold@gmail.com> Date: Wed, 31 Aug 2022 19:25:24 +0200 Subject: [PATCH 09/11] (chore): changelog update --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b289df51..36039d714 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,16 +5,20 @@ ### Added ### Changed + - Upgrade deck.gl to 8.8 - Replace `postversion` script with `version` script for CI release. - Remove `package-lock.json` from root (since we use pnpm) +- Clip low resolution tiles that might be padded by a loader. ## 0.13.1 ### Added + - Added support for loading multiple single channel TIFFs. ### Changed + - Update doc strings for `loadMultiTiff` - Update release notes in `README.md` @@ -23,6 +27,7 @@ ### Added ### Changed + - Migrate to pnpm monorepo - Fix all image URLs in README - Only run CHANGELOG action on pull_requests From 1b7f4b8d8c89400241152ae1bd317bbb8f2ca083 Mon Sep 17 00:00:00 2001 From: ilan-gold <ilanbassgold@gmail.com> Date: Thu, 23 Mar 2023 13:16:08 +0100 Subject: [PATCH 10/11] (feat): refactor for clarity (hopefully) --- .../multiscale-image-layer.js | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js index 34b896a77..272302bad 100644 --- a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js +++ b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js @@ -23,19 +23,31 @@ import { ColorPaletteExtension } from '@vivjs/extensions'; * }} * @return {{ clip: function, height: number, width: number }} */ -const createTileClipper = ({ loader, resolution, tileSize }) => { - const planarSize = Object.values(getImageSize(loader[0])); - const [clippedHeight, clippedWidth] = planarSize.map(size => - Math.floor(size / 2 ** resolution) - ); - const isHeightUnderTileSize = clippedHeight < tileSize; - const isWidthUnderTileSize = clippedWidth < tileSize; +const createTileClipper = ({ loader, resolution }) => { + const { tileSize } = loader[0]; + const planarSize = getImageSize(loader[0]); + const [clippedHeight, clippedWidth] = [ + planarSize.height, + planarSize.width + ].map(size => Math.floor(size / 2 ** resolution)); + const isUnderTileSize = dimSize => dimSize < tileSize; + const shouldClip = ({ clippedDimSize, dataDimSize }) => + isUnderTileSize(clippedDimSize) && dataDimSize === tileSize; + const dimSizeGetterFactory = + ({ clippedDimSize }) => + ({ dataDimSize }) => + shouldClip({ clippedDimSize, dataDimSize }) + ? clippedDimSize + : dataDimSize; + return { clip: ({ data, height, width }) => { if ( - (isHeightUnderTileSize && height === tileSize) || - (width === tileSize && isWidthUnderTileSize) + shouldClip({ clippedDimSize: clippedHeight, dataDimSize: height }) || + shouldClip({ clippedDimSize: clippedWidth, dataDimSize: width }) ) { + const isHeightUnderTileSize = isUnderTileSize(clippedHeight); + const isWidthUnderTileSize = isUnderTileSize(clippedWidth); return data.filter((d, ind) => { return !( (ind % tileSize >= clippedWidth && isWidthUnderTileSize) || @@ -46,8 +58,8 @@ const createTileClipper = ({ loader, resolution, tileSize }) => { } return data; }, - height: clippedHeight, - width: clippedWidth + getHeight: dimSizeGetterFactory({ clippedDimSize: clippedHeight }), + getWidth: dimSizeGetterFactory({ clippedDimSize: clippedWidth }) }; }; @@ -131,7 +143,7 @@ const MultiscaleImageLayer = class extends CompositeLayer { const config = { x, y, selection, signal }; return loader[resolution].getTile(config); }; - const clipper = createTileClipper({ loader, resolution, tileSize }); + const clipper = createTileClipper({ loader, resolution }); try { /* * Try to request the tile data. The pixels sources can throw @@ -143,21 +155,9 @@ const MultiscaleImageLayer = class extends CompositeLayer { */ const tiles = await Promise.all(selections.map(getTile)); const tile = { - data: tiles.map(d => - clipper.clip({ - data: d.data, - width: tiles[0].width, - height: tiles[0].height - }) - ), - width: - clipper.width < tileSize && tiles[0].width === tileSize - ? clipper.width - : tiles[0].width, - height: - clipper.height < tileSize && tiles[0].height === tileSize - ? clipper.height - : tiles[0].height + data: tiles.map(clipper.clip), + width: clipper.getWidth({ dataDimSize: tiles[0].width }), + height: clipper.getHeight({ dataDimSize: tiles[0].height }) }; if (isInterleaved(loader[resolution].shape)) { From 768d01452871d5b79cb092a5cccbceb8dbd111fd Mon Sep 17 00:00:00 2001 From: ilan-gold <ilanbassgold@gmail.com> Date: Thu, 23 Mar 2023 13:27:36 +0100 Subject: [PATCH 11/11] (style): refactor for single function --- .../multiscale-image-layer.js | 69 +++++++++---------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js index 272302bad..6043ef903 100644 --- a/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js +++ b/packages/layers/src/multiscale-image-layer/multiscale-image-layer.js @@ -8,7 +8,7 @@ import { getImageSize, isInterleaved, SIGNAL_ABORTED } from '@vivjs/loaders'; import { ColorPaletteExtension } from '@vivjs/extensions'; /** - * Here we create an object for checking clipping the black border of incoming tiles + * Here we process the clipping of the black border of incoming tiles * at low resolutions i.e for zarr tiles which are padded by zarr. * We need to check a few things before trimming: * 1. The height/width of the full image at the current resolution @@ -21,9 +21,9 @@ import { ColorPaletteExtension } from '@vivjs/extensions'; * resolution: number, * tileSize: number, * }} - * @return {{ clip: function, height: number, width: number }} + * @return {{ data: TypedArray, height: number, width: number }} */ -const createTileClipper = ({ loader, resolution }) => { +const clipTiles = ({ loader, resolution, tiles }) => { const { tileSize } = loader[0]; const planarSize = getImageSize(loader[0]); const [clippedHeight, clippedWidth] = [ @@ -33,34 +33,33 @@ const createTileClipper = ({ loader, resolution }) => { const isUnderTileSize = dimSize => dimSize < tileSize; const shouldClip = ({ clippedDimSize, dataDimSize }) => isUnderTileSize(clippedDimSize) && dataDimSize === tileSize; - const dimSizeGetterFactory = - ({ clippedDimSize }) => - ({ dataDimSize }) => - shouldClip({ clippedDimSize, dataDimSize }) - ? clippedDimSize - : dataDimSize; + const getDimSize = ({ clippedDimSize, dataDimSize }) => + shouldClip({ clippedDimSize, dataDimSize }) ? clippedDimSize : dataDimSize; - return { - clip: ({ data, height, width }) => { - if ( - shouldClip({ clippedDimSize: clippedHeight, dataDimSize: height }) || - shouldClip({ clippedDimSize: clippedWidth, dataDimSize: width }) - ) { - const isHeightUnderTileSize = isUnderTileSize(clippedHeight); - const isWidthUnderTileSize = isUnderTileSize(clippedWidth); - return data.filter((d, ind) => { - return !( - (ind % tileSize >= clippedWidth && isWidthUnderTileSize) || - (isHeightUnderTileSize && - Math.floor(ind / tileSize) >= clippedHeight) - ); - }); - } - return data; - }, - getHeight: dimSizeGetterFactory({ clippedDimSize: clippedHeight }), - getWidth: dimSizeGetterFactory({ clippedDimSize: clippedWidth }) - }; + return tiles.map(({ data, height, width }) => { + let clippedData = data; + if ( + shouldClip({ clippedDimSize: clippedHeight, dataDimSize: height }) || + shouldClip({ clippedDimSize: clippedWidth, dataDimSize: width }) + ) { + const isHeightUnderTileSize = isUnderTileSize(clippedHeight); + const isWidthUnderTileSize = isUnderTileSize(clippedWidth); + clippedData = data.filter((d, ind) => { + return !( + (ind % tileSize >= clippedWidth && isWidthUnderTileSize) || + (isHeightUnderTileSize && Math.floor(ind / tileSize) >= clippedHeight) + ); + }); + } + return { + data: clippedData, + height: getDimSize({ + clippedDimSize: clippedHeight, + dataDimSize: height + }), + width: getDimSize({ clippedDimSize: clippedWidth, dataDimSize: width }) + }; + }); }; const defaultProps = { @@ -143,7 +142,6 @@ const MultiscaleImageLayer = class extends CompositeLayer { const config = { x, y, selection, signal }; return loader[resolution].getTile(config); }; - const clipper = createTileClipper({ loader, resolution }); try { /* * Try to request the tile data. The pixels sources can throw @@ -153,11 +151,12 @@ const MultiscaleImageLayer = class extends CompositeLayer { * This means that our pixels sources _always_ have the same * return type, and optional throw for performance. */ - const tiles = await Promise.all(selections.map(getTile)); + let tiles = await Promise.all(selections.map(getTile)); + tiles = clipTiles({ loader, resolution, tiles }); const tile = { - data: tiles.map(clipper.clip), - width: clipper.getWidth({ dataDimSize: tiles[0].width }), - height: clipper.getHeight({ dataDimSize: tiles[0].height }) + data: tiles.map(d => d.data), + width: tiles[0].width, + height: tiles[0].height }; if (isInterleaved(loader[resolution].shape)) {