Skip to content

Commit

Permalink
render rgb thumbnail
Browse files Browse the repository at this point in the history
  • Loading branch information
BrianWhitneyAI committed Jun 13, 2024
1 parent a190f13 commit b16d167
Showing 1 changed file with 41 additions and 28 deletions.
69 changes: 41 additions & 28 deletions packages/core/entity/FileDetail/RenderZarrThumbnailURL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ import * as zarr from "@zarrita/core";
import { FetchStore } from "@zarrita/storage";
import { get as zarrGet } from "@zarrita/indexing";

// Function to map grayscale value (0-255) to RGB color
function grayscaleToRGB(value: number): [number, number, number] {
const r = value;
const g = 0 + value;
const b = 255 - value;
return [r, g, b];
}

export async function renderZarrThumbnailURL(zarrUrl: string): Promise<string> {
try {
const store = new FetchStore(zarrUrl);
Expand All @@ -18,45 +26,50 @@ export async function renderZarrThumbnailURL(zarrUrl: string): Promise<string> {
const lowestResolutionDataset = datasets[datasets.length - 1];
const lowestResolutionLocation = root.resolve(lowestResolutionDataset.path);
const lowestResolution = await zarr.open(lowestResolutionLocation, { kind: "array" }); // TODO: check the filesize before slicing
const lowestResolutionView = await zarrGet(lowestResolution, [0, 0, 21, null, null]); // TODO: make this slicing dynamic

const data = lowestResolutionView.data as Uint16Array;
const lowestResolutionView = await zarrGet(lowestResolution, [0, 0, 20, null, null]); // Adjusted slicing for 2D data
console.log("DATA", lowestResolutionView.data);
console.log("SHAPE", lowestResolutionView.shape);
const u16data = lowestResolutionView.data as Uint16Array;

const min = Math.min(...u16data);
const max = Math.max(...u16data);

// Normalize the Uint16Array data to 8-bit
const maxVal = Math.max(...data);
const minVal = Math.min(...data);
const normalizedData = new Uint8ClampedArray(data.length);
for (let i = 0; i < data.length; i++) {
normalizedData[i] = ((data[i] - minVal) / (maxVal - minVal)) * 255;
const normalizedData = new Uint8Array(u16data.length);
for (let i = 0; i < u16data.length; i++) {
normalizedData[i] = Math.round((255 * (u16data[i] - min)) / (max - min));
}

// Create a canvas to draw the image
const width = lowestResolutionView.shape[1];
const height = lowestResolutionView.shape[0];
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
const width = Math.min(100, lowestResolution.shape[3]); // Set to actual data width if less than 100
const height = Math.min(100, lowestResolution.shape[4]); // Set to actual data height if less than 100
canvas.width = width;
canvas.height = height;
const context = canvas.getContext("2d");

if (context) {
const imageData = context.createImageData(width, height);
const imageDataArray = imageData.data;
if (!context) {
throw new Error("Failed to get canvas context");
}

// Populate the ImageData object with the normalized data
for (let i = 0; i < normalizedData.length; i++) {
const value = normalizedData[i];
imageDataArray[i * 4] = value; // Red
imageDataArray[i * 4 + 1] = value; // Green
imageDataArray[i * 4 + 2] = value; // Blue
imageDataArray[i * 4 + 3] = 255; // Alpha
}
context.putImageData(imageData, 0, 0);
const imageData = context.createImageData(width, height);

const dataURL = canvas.toDataURL("image/png");
return dataURL;
} else {
throw new Error("Unable to get 2D context from canvas");
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const idx = (y * width + x) * 4;
const value = normalizedData[y * width + x];
const [r, g, b] = grayscaleToRGB(value);
imageData.data[idx] = r; // Red
imageData.data[idx + 1] = g; // Green
imageData.data[idx + 2] = b; // Blue
imageData.data[idx + 3] = 255; // Alpha
}
}

context.putImageData(imageData, 0, 0);

const dataUrl = canvas.toDataURL("image/png");

return dataUrl;
} else {
throw new Error("Invalid multiscales attribute structure");
}
Expand Down

0 comments on commit b16d167

Please sign in to comment.