Public
Edited
Nov 25, 2024
Importers
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
createSVGFromRGBArrayWithHover(redwoodData, 512, 0.125 * 2)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
filter.matrix
Insert cell
redwood2D = to2DArray(redwoodData)
Insert cell
Insert cell
Insert cell
createSVGFromRGBArrayWithHover(redwood2D.flat(), 512, 0.125 * 2)
Insert cell
filter.matrix
Insert cell
createSVGFromRGBArrayWithHover(transformedRedwood2d.flat(), 512, 0.125 * 2)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
random = generateRandomRGBMatrix()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
inputPixel = [35, 23, 31] // rgb(35, 23, 31)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
rgbArrayToBase64(redwoodData)
Insert cell
function rgbArrayToBase64(rgbArray) {
// Step 1: Flatten the 2D array into a 1D array
const flattenedArray = rgbArray.flat(); // Flattens array of arrays into one big array

// Step 2: Create a Uint8Array from the flattened array
const uint8Array = new Uint8Array(flattenedArray);

return uint8Array;
}
Insert cell
rgbArrayToBase64(redwoodData)
Insert cell
Insert cell
Math.sqrt(redwoodData.length)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function* progressOverTime(duration) {
button;
const startTime = performance.now(); // Get the start time
let currentTime;
let progress;
let counter = 0;

while (true) {
currentTime = performance.now(); // Get current time
progress = (currentTime - startTime) / duration; // Calculate progress

if (progress >= 1) {
progress = 1; // Ensure the final value is exactly 1
yield progress;
return; // Stop the generator once we hit the end
}

counter++;

if (counter === 10) {
// Only yield when counter reaches 5
yield progress; // Yield the current progress value
counter = 0; // Reset counter
}
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import { createRGBAxes } from "@jzhang621/rgb-vector-space-fun"
Insert cell
kenai = FileAttachment("kenai.webp").image()
Insert cell
tetons = FileAttachment("tetons.webp").image()
Insert cell
image = FileAttachment("untitled (1)@1.png").image()
Insert cell
grandCanyon = to2DArray(await getRGBValuesFromImage(image))
Insert cell
renderImageFromRGBMatrix(grandCanyon)
Insert cell
green = renderImageFromRGBMatrix(
applyFilterToRGBMatrix(grandCanyon, getMatrixByName(filters, "darken"))
)
Insert cell
filters.map((d) => d.name)
Insert cell
function getMatrixByName(list, name) {
// Define the identity matrix
const identityMatrix = [
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]
];

// Find the object in the list with the matching name
const found = list.find((item) => item.name === name);

// Return the matrix if found, otherwise return the identity matrix
return found ? found.matrix : identityMatrix;
}
Insert cell
convertToFlatUint8Array(grandCanyon)
Insert cell
Insert cell
function convertToFlatUint8Array(rgbArray) {
// Calculate the total number of pixels
const height = rgbArray.length;
const width = rgbArray[0].length;

// Create a flat Uint8Array to hold the pixel data
// Each pixel has 3 values (r, g, b), so total length is width * height * 3
const flatArray = new Uint8Array(width * height * 3);

// Flatten the 2D rgbArray into the Uint8Array
let index = 0;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const [r, g, b] = rgbArray[y][x];
flatArray[index++] = r;
flatArray[index++] = g;
flatArray[index++] = b;
}
}

return flatArray;
}
Insert cell
renderImageWithSquare(grandCanyon, 1, 150, 200)
Insert cell
function renderImageWithSquare(
rgbMatrix,
squareSize, // The size of the square (outline)
startRow, // Starting row of the square (outline)
startCol, // Starting column of the square (outline)
w = 512, // Width of the canvas
h = 512, // Height of the canvas
canvasId = "canvas" // Optional canvas ID
) {
const canvas = html`<canvas style="height: ${h}px; width: ${w}px"/>`;
const ctx = canvas.getContext("2d");

const height = rgbMatrix.length;
const width = rgbMatrix[0].length;

// Set canvas dimensions based on the matrix size
canvas.width = width;
canvas.height = height;

const imageData = ctx.createImageData(width, height);

// Draw the whole image by iterating through the entire rgbMatrix
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const pixelIndex = (y * width + x) * 4;
const [r, g, b] = rgbMatrix[y][x];

imageData.data[pixelIndex] = r; // Red
imageData.data[pixelIndex + 1] = g; // Green
imageData.data[pixelIndex + 2] = b; // Blue
imageData.data[pixelIndex + 3] = 255 * 0.75; // Alpha (fully opaque)
}
}

// Apply the full image first
ctx.putImageData(imageData, 0, 0);

// Set the color and style for the square outline
ctx.strokeStyle = "white"; // Change to any color you like for the outline
ctx.lineWidth = 3; // Set the thickness of the outline

// Draw the square outline on top of the image
ctx.strokeRect(startCol, startRow, squareSize, squareSize);

return canvas;
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more