Skip to content

Instantly share code, notes, and snippets.

@jarbitlira
Last active May 30, 2025 03:14
Show Gist options
  • Select an option

  • Save jarbitlira/956b8a509617ba4ea3f7fcfdc572c82c to your computer and use it in GitHub Desktop.

Select an option

Save jarbitlira/956b8a509617ba4ea3f7fcfdc572c82c to your computer and use it in GitHub Desktop.
Trace frames from image
const { Jimp, intToRGBA, colorDiff, RGBColor } = require('jimp');
(async () => {
const frames = [];
let backgroundColor;
const image = await Jimp.read('./draw.jpg');
const imageWidth = image.width;
const imageHeight = image.height;
const getBackgroundColor = () => {
let colors = new Map();
for (let x = 0; x < imageWidth; x++) {
for (let y = 0; y < imageHeight; y++) {
const pixelColor = image.getPixelColor(x, y);
let counter = colors.get(pixelColor) ?? 0;
counter++;
colors.set(pixelColor, counter);
}
}
let highestCounter = 0;
let bgColor;
for (let color of colors.keys()) {
const currentColorCounter = colors.get(color);
if (currentColorCounter >= highestCounter) {
highestCounter = currentColorCounter;
bgColor = color;
}
}
return bgColor;
}
backgroundColor = getBackgroundColor();
const isBackgroundColor = (x, y) => {
const result = colorDiff(intToRGBA(backgroundColor), intToRGBA(image.getPixelColor(x, y)));
return !result;
}
const isInsideAFrame = (x, y) => {
const frame = frames.find((frame) => {
return (
x >= frame.x1 &&
x < frame.x2 &&
y >= frame.y1 &&
y < frame.y2
);
});
return !!frame;
}
const tracedPixels = new Set();
const getFrame = (initialX, initialY) => {
const nearbyPixels = [[initialX, initialY]];
let minX = initialX;
let maxX = initialX;
let minY = initialY;
let maxY = initialY;
while (nearbyPixels.length > 0) {
const [x, y] = nearbyPixels.pop();
const pixelKey = `${ x },${ y }`;
if (
x < 0 ||
y < 0 ||
x >= imageWidth
||
y >= imageHeight ||
tracedPixels.has(pixelKey)
) {
continue;
}
tracedPixels.add(pixelKey);
if (isBackgroundColor(x, y)) {
continue;
}
minX = Math.min(minX, x);
maxX = Math.max(maxX, x);
minY = Math.min(minY, y);
maxY = Math.max(maxY, y);
nearbyPixels.push(
[x + 1, y],
[x - 1, y],
[x, y + 1],
[x, y - 1],
[x - 1, y - 1],
[x - 1, y + 1],
[x + 1, y - 1],
[x + 1, y + 1],
);
}
return {
x1: minX,
y1: minY,
x2: maxX,
y2: maxY,
width: maxX - minX + 1,
height: maxY - minY + 1,
}
}
for (let y = 0; y < imageHeight; y++) {
for (let x = 0; x < imageWidth; x++) {
const key = `${ x },${ y }`;
if (!tracedPixels.has(key) &&
!isBackgroundColor(x, y) &&
!isInsideAFrame(x, y)
) {
const frame = getFrame(x, y);
frames.push(frame);
}
}
}
return frames;
})()
@jarbitlira
Copy link
Author

Image used for testing draw

@jarbitlira
Copy link
Author

Screenshot from 2025-05-29 21-12-51

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment