Open jtleniger opened 4 years ago
const sharp = require('sharp')
async function run() {
let rawData
let metadata
try {
const img = await sharp('input.jpg')
metadata = await img.metadata()
rawData = await img
.greyscale()
.median()
.normalise()
.threshold()
.raw()
.toBuffer()
} catch (error) {
console.log(error)
return
}
let i = 0
let whitePixels = []
console.log(`Width: ${metadata.width} Height: ${metadata.height} Total Pixels: ${metadata.width * metadata.height}`)
console.log(`Raw Buffer Lengths: ${rawData.length}`)
for (pixel of rawData.values()) {
if (!!pixel) {
whitePixels.push({
x: i % metadata.width,
y: Math.floor(i / metadata.width)
})
}
i++
}
console.log(`Total pixels: ${rawData.length}`)
console.log(`White pixels: ${whitePixels.length}`)
let stars = []
while (whitePixels.length) {
let first = whitePixels[0]
let star = {
pixels: [first]
}
checkNeighbors(whitePixels, star, first)
stars.push(star)
}
console.log(`Stars found: ${stars.length}`)
stars.forEach((star) => {
determineCenter(star)
})
let blankRaw = await sharp({
create: {
width: metadata.width,
height: metadata.height,
channels: 3,
background: 'rgb(0, 0, 0)'
}
})
.greyscale()
.raw()
.toBuffer()
stars.forEach(star => {
blankRaw[getIndexFromCoordinates(metadata, star.center)] = 255
})
await sharp(blankRaw, {
raw: {
width: metadata.width,
height: metadata.height,
channels: 1
}
})
.toFile('overlay.jpg')
}
function getIndexFromCoordinates(metadata, coords) {
return (coords.y * metadata.width) + coords.x
}
function checkNeighbors(whitePixels, star, first) {
let neighbors = []
for (var i = 0; i < whitePixels.length; i++) {
let pixel = whitePixels[i];
if (pixel.x <= first.x + 1
&& pixel.x >= first.x - 1
&& pixel.y <= first.y + 1
&& pixel.y >= first.y - 1) {
neighbors.push(pixel)
}
}
for (var i = 0; i < neighbors.length; i++) {
whitePixels.splice(whitePixels.indexOf(neighbors[i]), 1)
}
star.pixels = star.pixels.concat(neighbors)
for (var i = 0; i < neighbors.length; i++) {
checkNeighbors(whitePixels, star, neighbors[i])
}
}
function determineCenter(star) {
let sumX = 0
let sumY = 0
for (i = 0; i < star.pixels.length; i++) {
sumX += star.pixels[i].x
sumY += star.pixels[i].y
}
star.center = {
x: Math.round(sumX / star.pixels.length),
y: Math.round(sumY / star.pixels.length)
}
}
run()