|
// Core javascript used for Brody Smith's image to social media thumbnail web tool: |
|
// https://brody.fyi/tools/image-to-social-media-thumbnail |
|
|
|
import ColorThief from "colorthief/dist/color-thief.mjs" |
|
|
|
let inputElement |
|
let outputImage |
|
let showDownloadText |
|
let colorPalette |
|
let colorPrimary |
|
|
|
const colorThief = new ColorThief() |
|
|
|
// Run on file input onchange event |
|
function handleFileChange() { |
|
const file = inputElement.files[0] |
|
handleImageFile(file) |
|
} |
|
|
|
function handleImageFile(file = inputElement?.files[0], paletteIndex = 0) { |
|
// Create a FileReader instance to read the file |
|
var reader = new FileReader() |
|
|
|
// Set up the FileReader onload event |
|
reader.onload = function (event) { |
|
// Create an image element to load the source image |
|
var image = new Image() |
|
|
|
// Set up the image onload event |
|
image.onload = function () { |
|
colorPalette = getPaletteColors(image) |
|
colorPrimary = colorPalette[paletteIndex] |
|
|
|
// Create a new canvas with the specified dimensions |
|
var canvas = document.createElement("canvas") |
|
canvas.width = 1280 |
|
canvas.height = 720 |
|
var ctx = canvas.getContext("2d") |
|
|
|
// Fill the canvas with the primary color |
|
ctx.fillStyle = colorPrimary |
|
ctx.fillRect(0, 0, canvas.width, canvas.height) |
|
|
|
// Calculate the height and width for the centered image |
|
var imgHeight = 500 |
|
var imgWidth = imgHeight * (image.width / image.height) |
|
|
|
// Calculate the position for centering the image |
|
var xPos = (canvas.width - imgWidth) / 2 |
|
var yPos = (canvas.height - imgHeight) / 2 |
|
|
|
// Add a border radius |
|
const drawCurvedRect = (r = 30) => { |
|
const path = new Path2D() |
|
|
|
path.moveTo(xPos + r, yPos) |
|
path.lineTo(xPos + imgWidth - r, yPos) |
|
path.quadraticCurveTo( |
|
xPos + imgWidth, |
|
yPos, |
|
xPos + imgWidth, |
|
yPos + r |
|
) |
|
path.lineTo(xPos + imgWidth, yPos + imgHeight - r) |
|
path.quadraticCurveTo( |
|
xPos + imgWidth, |
|
yPos + imgHeight, |
|
xPos + imgWidth - r, |
|
yPos + imgHeight |
|
) |
|
path.lineTo(xPos + r, yPos + imgHeight) |
|
path.quadraticCurveTo( |
|
xPos, |
|
yPos + imgHeight, |
|
xPos, |
|
yPos + imgHeight - r |
|
) |
|
path.lineTo(xPos, yPos + r) |
|
path.quadraticCurveTo(xPos, yPos, xPos + r, yPos) |
|
path.closePath() |
|
return path |
|
} |
|
|
|
// Apply a dark box-shadow to the image |
|
ctx.shadowColor = "rgba(0, 0, 0, 0.25)" |
|
ctx.shadowBlur = 50 |
|
ctx.fill(drawCurvedRect()) |
|
|
|
// Draw the clipped source image on the canvas |
|
ctx.save() |
|
ctx.clip(drawCurvedRect()) |
|
ctx.drawImage(image, xPos, yPos, imgWidth, imgHeight) |
|
ctx.restore() |
|
|
|
// Convert the canvas to a JPEG image and output it |
|
// Example usage in HTML: <img src={outputImage} alt="..." /> |
|
outputImage = canvas.toDataURL("image/jpeg") |
|
} |
|
|
|
// Set the source of the image element to the loaded file |
|
image.src = event.target.result |
|
} |
|
|
|
// Read the image file as a data URL |
|
reader.readAsDataURL(file) |
|
} |
|
|
|
function downloadImage() { |
|
var outputLink = document.createElement("a") |
|
outputLink.href = outputImage |
|
outputLink.download = "output.jpg" |
|
outputLink.click() |
|
} |
|
|
|
function rgbArrayToHex(array) { |
|
return "#" + array.map(c => c.toString(16).padStart(2, "0")).join("") |
|
} |
|
|
|
function getPaletteColors(image) { |
|
const colors = colorThief.getPalette(image) |
|
return colors.map(rgbArrayToHex) |
|
} |