From 56a1b9e3e644180584863f4cd5949fcb9126a434 Mon Sep 17 00:00:00 2001 From: Alex Pickering Date: Mon, 2 Dec 2024 13:35:14 -0800 Subject: [PATCH] factor out getImageUrls Signed-off-by: Alex Pickering --- .../plots/SpatialCategoricalPlot.jsx | 51 +----------------- src/components/plots/SpatialFeaturePlot.jsx | 51 +----------------- src/components/plots/getImageUrls.js | 52 +++++++++++++++++++ 3 files changed, 54 insertions(+), 100 deletions(-) create mode 100644 src/components/plots/getImageUrls.js diff --git a/src/components/plots/SpatialCategoricalPlot.jsx b/src/components/plots/SpatialCategoricalPlot.jsx index e6ee5de13..621f3e55f 100644 --- a/src/components/plots/SpatialCategoricalPlot.jsx +++ b/src/components/plots/SpatialCategoricalPlot.jsx @@ -9,62 +9,13 @@ import { loadEmbedding } from 'redux/actions/embedding'; import { loadProcessingSettings } from 'redux/actions/experimentSettings'; import { getCellSets } from 'redux/selectors'; import { generateSpec, generateData } from 'utils/plotSpecs/generateSpatialCategoricalSpec'; -import { loadOmeZarr } from 'components/data-exploration/spatial/loadOmeZarr'; -import { root as zarrRoot } from 'zarrita'; -import { ZipFileStore } from '@zarrita/storage'; import { getSampleFileUrls } from 'utils/data-management/downloadSampleFile'; +import getImageUrls from './getImageUrls'; import PlatformError from '../PlatformError'; import Loader from '../Loader'; const EMBEDDING_TYPE = 'images'; -// Load OME-Zarr and return the pyramid and loader (an example) -const getImageUrls = async (omeZarrUrl) => { - const omeZarrRoot = zarrRoot(ZipFileStore.fromUrl(omeZarrUrl)); - - const { data } = await loadOmeZarr(omeZarrRoot); - const base = data[0]; - - const imageUrl = await imageDataToUrl(base); - return imageUrl; -}; - -const imageDataToUrl = async (base) => { - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - - // Extract dimensions from the first channel - const { data, width, height } = await base.getRaster({ selection: { c: 0, x: 0, y: 0 } }); - - canvas.width = width; - canvas.height = height; - - const rgbaData = new Uint8ClampedArray(width * height * 4); - - // Process each RGB channel - await Promise.all([0, 1, 2].map(async (c) => { - const selection = { c, x: 0, y: 0 }; - const { data: pixelData } = await base.getRaster({ selection }); - - pixelData.forEach((value, i) => { - rgbaData[i * 4 + c] = value; - }); - })); - - // Set alpha channel to fully opaque - rgbaData.forEach((_, i) => { - if ((i + 1) % 4 === 0) { - rgbaData[i] = 255; - } - }); - - const imageDataObject = new ImageData(rgbaData, width, height); - ctx.putImageData(imageDataObject, 0, 0); - - const imageUrl = canvas.toDataURL(); - return { imageUrl, imageWidth: width, imageHeight: height }; -}; - const SpatialCategoricalPlot = (props) => { const { experimentId, diff --git a/src/components/plots/SpatialFeaturePlot.jsx b/src/components/plots/SpatialFeaturePlot.jsx index 49d012a29..03775c5de 100644 --- a/src/components/plots/SpatialFeaturePlot.jsx +++ b/src/components/plots/SpatialFeaturePlot.jsx @@ -9,62 +9,13 @@ import { loadEmbedding } from 'redux/actions/embedding'; import { loadProcessingSettings } from 'redux/actions/experimentSettings'; import { getCellSets } from 'redux/selectors'; import { generateSpec, generateData } from 'utils/plotSpecs/generateSpatialFeatureSpec'; -import { loadOmeZarr } from 'components/data-exploration/spatial/loadOmeZarr'; -import { root as zarrRoot } from 'zarrita'; -import { ZipFileStore } from '@zarrita/storage'; import { getSampleFileUrls } from 'utils/data-management/downloadSampleFile'; +import getImageUrls from './getImageUrls'; import PlatformError from '../PlatformError'; import Loader from '../Loader'; const EMBEDDING_TYPE = 'images'; -// Load OME-Zarr and return the pyramid and loader (an example) -const getImageUrls = async (omeZarrUrl) => { - const omeZarrRoot = zarrRoot(ZipFileStore.fromUrl(omeZarrUrl)); - - const { data } = await loadOmeZarr(omeZarrRoot); - const base = data[0]; - - const imageUrl = await imageDataToUrl(base); - return imageUrl; -}; - -const imageDataToUrl = async (base) => { - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - - // Extract dimensions from the first channel - const { data, width, height } = await base.getRaster({ selection: { c: 0, x: 0, y: 0 } }); - - canvas.width = width; - canvas.height = height; - - const rgbaData = new Uint8ClampedArray(width * height * 4); - - // Process each RGB channel - await Promise.all([0, 1, 2].map(async (c) => { - const selection = { c, x: 0, y: 0 }; - const { data: pixelData } = await base.getRaster({ selection }); - - pixelData.forEach((value, i) => { - rgbaData[i * 4 + c] = value; - }); - })); - - // Set alpha channel to fully opaque - rgbaData.forEach((_, i) => { - if ((i + 1) % 4 === 0) { - rgbaData[i] = 255; - } - }); - - const imageDataObject = new ImageData(rgbaData, width, height); - ctx.putImageData(imageDataObject, 0, 0); - - const imageUrl = canvas.toDataURL(); - return { imageUrl, imageWidth: width, imageHeight: height }; -}; - const SpatialFeaturePlot = (props) => { const { experimentId, diff --git a/src/components/plots/getImageUrls.js b/src/components/plots/getImageUrls.js new file mode 100644 index 000000000..b987ab9bc --- /dev/null +++ b/src/components/plots/getImageUrls.js @@ -0,0 +1,52 @@ +import { loadOmeZarr } from 'components/data-exploration/spatial/loadOmeZarr'; +import { root as zarrRoot } from 'zarrita'; +import { ZipFileStore } from '@zarrita/storage'; + +// Load OME-Zarr and return the pyramid and loader (an example) +const getImageUrls = async (omeZarrUrl) => { + const omeZarrRoot = zarrRoot(ZipFileStore.fromUrl(omeZarrUrl)); + + const { data } = await loadOmeZarr(omeZarrRoot); + const base = data[0]; + + const imageUrl = await imageDataToUrl(base); + return imageUrl; +}; + +const imageDataToUrl = async (base) => { + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + + // Extract dimensions from the first channel + const { data, width, height } = await base.getRaster({ selection: { c: 0, x: 0, y: 0 } }); + + canvas.width = width; + canvas.height = height; + + const rgbaData = new Uint8ClampedArray(width * height * 4); + + // Process each RGB channel + await Promise.all([0, 1, 2].map(async (c) => { + const selection = { c, x: 0, y: 0 }; + const { data: pixelData } = await base.getRaster({ selection }); + + pixelData.forEach((value, i) => { + rgbaData[i * 4 + c] = value; + }); + })); + + // Set alpha channel to fully opaque + rgbaData.forEach((_, i) => { + if ((i + 1) % 4 === 0) { + rgbaData[i] = 255; + } + }); + + const imageDataObject = new ImageData(rgbaData, width, height); + ctx.putImageData(imageDataObject, 0, 0); + + const imageUrl = canvas.toDataURL(); + return { imageUrl, imageWidth: width, imageHeight: height }; +}; + +export default getImageUrls;