Skip to content

Instantly share code, notes, and snippets.

@ArnoldsK
Last active September 16, 2024 10:21
Show Gist options
  • Save ArnoldsK/32db6b30a535461a9bc59042b30905ae to your computer and use it in GitHub Desktop.
Save ArnoldsK/32db6b30a535461a9bc59042b30905ae to your computer and use it in GitHub Desktop.
Use Node canvas to crop to image non-transparent content, or return the content rect
import { createCanvas, loadImage } from "@napi-rs/canvas"
import fs from "fs"
const ALPHA_THRESHOLD = 255 * 0.1 // 1%
const cropImageToContent = async (src: string, newSrc: string) => {
const canvas = createCanvas(256, 256)
const ctx = canvas.getContext("2d")
const img = await loadImage(src)
ctx.drawImage(img, 0, 0)
// Helper fn to check for transparency
const isOpaque = (x: number, y: number): boolean => {
const [, , , a] = ctx.getImageData(x, y, 1, 1).data
return a > ALPHA_THRESHOLD
}
// Find the opaque content rect
const rect = {
x: canvas.width - 1,
y: canvas.height - 1,
width: 0,
height: 0,
}
for (let x = 0; x < canvas.width; x++) {
for (let y = 0; y < canvas.width; y++) {
if (isOpaque(x, y)) {
if (x < rect.x) rect.x = x
if (y < rect.y) rect.y = y
if (x > rect.width) rect.width = x
if (y > rect.height) rect.height = y
}
}
}
rect.width = rect.width - rect.x
rect.height = rect.height - rect.y
// #############################################################################
// Option A - crop and save the image
// #############################################################################
// Remove the existing content
ctx.clearRect(0, 0, canvas.width, canvas.height)
// Change the size so it matches the content
canvas.width = rect.width
canvas.height = rect.height
// Redraw the image with the content at 0;0
ctx.drawImage(img, -rect.x, -rect.y)
// Save the image
const buffer = canvas.toBuffer("image/png")
fs.writeFileSync(newSrc, buffer)
// #############################################################################
// Option B - return the rect and handle the rest with CSS (tbh not great)
// #############################################################################
console.log(src, rect)
}
cropImageToContent("./example.png", "./example-cropped.png")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment