Published
Edited
Sep 14, 2020
Importers
12 stars
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
extractHSL = (colorMatrix) => {
const range = d3.range(0, 1, 1 / 40);
const bins = ({
h: d3.scaleQuantize().domain([0, 360]).range(range),
s: d3.scaleQuantize().domain([0, 1]).range(range),
l: d3.scaleQuantize().domain([0, 1]).range(range),
})
const nestedColor = d3.nest()
.key(d => `s${bins.s(d.s)}-l${bins.l(d.l)}`)
.key(d => `h${bins.h(d.h)}`)
.rollup(d => d.length)
.entries(colorMatrix)
const allValues = [];
nestedColor.forEach(parent => {
const highFreq = parent.values.reduce(function(a, b) {
return { values: (a.value == undefined ? 0 : a.value) + (b.value == undefined ? 0 : b.value) }
}).values
const sBin = +parent.key.split("-")[0].slice(1)
, lBin = +parent.key.split("-")[1].slice(1)
, s = d3.mean(bins.s.invertExtent(sBin))
, l = d3.mean(bins.l.invertExtent(lBin))
parent.values.forEach(child => {
const hBin = +child.key.split("-")[0].slice(1)
, h = d3.mean(bins.h.invertExtent(hBin))
allValues.push({h: h,
s: s,
l: l,
freq: child.value,
highFreq: highFreq,
color: d3.hsl(h,s,l).toString()});
})
})
return allValues.sort((a,b) => b.freq - a.freq)[0]
}

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
getArtworks = (Artist) => {
const selectedArtworks = artworks.filter(d => d.Artist == Artist & d.ThumbnailURL != "")
return selectedArtworks
}
Insert cell
Art = getArtworks("Fernand Léger")
Insert cell
Insert cell
async function analyzeArtworks(Art) {
const imageData = await linkToImageData(Art.ThumbnailURL);
const colorMatrix = imageDataToColorMatrix(imageData.data);
const primaryColor = extractHSL(colorMatrix);
Art.h = primaryColor != undefined ? primaryColor.h : 0
Art.s = primaryColor != undefined ? primaryColor.s : 0
Art.l = primaryColor != undefined ? primaryColor.l : 0
Art.height = imageData.height;
Art.width = imageData.width;
Art.ratio = imageData.width / imageData.height
Art.color = d3.hsl(Art.h,Art.s,Art.l).toString()
return Art
}
Insert cell
promises = Art.map(d => analyzeArtworks(d))
Insert cell
images = Promise.all(promises)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
async function imageQuilt(Artist) {
const Art = getArtworks(Artist)
const promises = Art.map(d => analyzeArtworks(d))
const results = await Promise.all(promises)
const div = html`<div></div>`
const nestedImages = d3.nest()
.key(d => Math.round(d.ratio / 2.5))
.entries(results);
nestedImages.forEach(d => {
d3.select(div)
.append("div")
.style("display", "inline-block")
.style("font-size", "0px")
.style("line-height", "0px")
.style("padding-top", "50px")
.style("padding-bottom", "50px")
.style("text-align", "center")
.selectAll(`img-${d.key}`)
.data(sortByColor(d.values))
.join("img")
.attr("src", d => d.ThumbnailURL)
.style("width", d => `${d.width / 3}px`)
.style("height", d => `${d.height / 3}px`)
.style("padding", "0px !important")
.style("margin", "0px !important")
})
return div
}
Insert cell
imageQuilt("Philip Guston")
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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