You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, resolution = 50, paletteType = "squares", bgColor = "#ffffff") {
// 1. Validate and clamp resolution (number of emojis horizontally)
let res = parseInt(resolution, 10);
if (isNaN(res) || res <= 0) res = 50;
// Cap resolution to avoid excessive canvas sizes and memory issues
res = Math.min(Math.max(res, 10), 200);
// 2. Calculate dimensions to maintain aspect ratio
const width = originalImg.width;
const height = originalImg.height;
const aspectRatio = height / width;
const cols = res;
// Assume emojis are roughly 1:1, map 1 pixel from small representation to 1 emoji
const rows = Math.floor(cols * aspectRatio);
// 3. Draw original image to a small canvas to extract pixel color data
const smallCanvas = document.createElement('canvas');
smallCanvas.width = cols;
smallCanvas.height = rows;
const smallCtx = smallCanvas.getContext('2d');
// Draw scaled down image
smallCtx.drawImage(originalImg, 0, 0, cols, rows);
const imgData = smallCtx.getImageData(0, 0, cols, rows).data;
// 4. Define Emoji Palettes
// We provide standard colors matching roughly the usual rendered colors of these emojis.
const palettes = {
"squares": [
{r: 237, g: 41, b: 57, e: "๐ฅ"},
{r: 255, g: 140, b: 0, e: "๐ง"},
{r: 253, g: 216, b: 53, e: "๐จ"},
{r: 76, g: 175, b: 80, e: "๐ฉ"},
{r: 33, g: 150, b: 243, e: "๐ฆ"},
{r: 156, g: 39, b: 176, e: "๐ช"},
{r: 121, g: 85, b: 72, e: "๐ซ"},
{r: 33, g: 33, b: 33, e: "โฌ"},
{r: 245, g: 245, b: 245, e: "โฌ"}
],
"circles": [
{r: 237, g: 41, b: 57, e: "๐ด"},
{r: 255, g: 140, b: 0, e: "๐ "},
{r: 253, g: 216, b: 53, e: "๐ก"},
{r: 76, g: 175, b: 80, e: "๐ข"},
{r: 33, g: 150, b: 243, e: "๐ต"},
{r: 156, g: 39, b: 176, e: "๐ฃ"},
{r: 121, g: 85, b: 72, e: "๐ค"},
{r: 33, g: 33, b: 33, e: "โซ"},
{r: 245, g: 245, b: 245, e: "โช"}
],
"hearts": [
{r: 237, g: 41, b: 57, e: "โค๏ธ"},
{r: 255, g: 140, b: 0, e: "๐งก"},
{r: 253, g: 216, b: 53, e: "๐"},
{r: 76, g: 175, b: 80, e: "๐"},
{r: 33, g: 150, b: 243, e: "๐"},
{r: 156, g: 39, b: 176, e: "๐"},
{r: 121, g: 85, b: 72, e: "๐ค"},
{r: 33, g: 33, b: 33, e: "๐ค"},
{r: 245, g: 245, b: 245, e: "๐ค"}
],
"moons": ["๐", "๐", "๐", "๐", "๐"],
"weather": ["โ๏ธ", "๐ง๏ธ", "โ๏ธ", "โ
", "๐ค๏ธ", "โ๏ธ"]
};
const selectedPalette = palettes[paletteType] || palettes["squares"];
const isColorPalette = Array.isArray(selectedPalette) && selectedPalette[0].r !== undefined;
// Helper: Find closest colored emoji using Euclidean distance in RGB color space
const findClosestEmoji = (r, g, b) => {
let minDistance = Infinity;
let closest = selectedPalette[0].e;
for (let i = 0; i < selectedPalette.length; i++) {
const color = selectedPalette[i];
const dist = (r - color.r) ** 2 + (g - color.g) ** 2 + (b - color.b) ** 2;
if (dist < minDistance) {
minDistance = dist;
closest = color.e;
}
}
return closest;
};
// Helper: Map luminance/brightness to an emoji progression
const findBrightnessEmoji = (r, g, b) => {
const luminance = 0.299 * r + 0.587 * g + 0.114 * b;
const index = Math.floor((luminance / 256) * selectedPalette.length);
return selectedPalette[Math.min(index, selectedPalette.length - 1)];
};
// 5. Setup output canvas
const emojiSize = 16;
const outputCanvas = document.createElement('canvas');
outputCanvas.width = cols * emojiSize;
outputCanvas.height = rows * emojiSize;
const ctx = outputCanvas.getContext('2d');
// Render underlying background if specified
if (bgColor && bgColor.toLowerCase() !== "transparent" && bgColor.toLowerCase() !== "none") {
ctx.fillStyle = bgColor;
ctx.fillRect(0, 0, outputCanvas.width, outputCanvas.height);
}
// Set font optimized for drawing standard emojis
ctx.font = `${emojiSize}px "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
let rawEmojiText = "";
// 6. Iterate mapped pixels, determine the emoji, and draw to canvas
for (let y = 0; y < rows; y++) {
let rowStr = "";
for (let x = 0; x < cols; x++) {
const idx = (y * cols + x) * 4;
const r = imgData[idx];
const g = imgData[idx + 1];
const b = imgData[idx + 2];
const a = imgData[idx + 3];
let emoji = " "; // Empty spaces for fully transparent pixels
if (a > 10) {
if (isColorPalette) {
emoji = findClosestEmoji(r, g, b);
} else {
emoji = findBrightnessEmoji(r, g, b);
}
// Draw onto canvas
ctx.fillText(emoji, x * emojiSize + (emojiSize / 2), y * emojiSize + (emojiSize / 2));
}
rowStr += emoji;
}
rawEmojiText += rowStr + "\n";
}
// Embed the text representation as a dataset attribute so developers/tools
// can extract it for copy-pasting functionality if required.
outputCanvas.dataset.emojiText = rawEmojiText.trimEnd();
return outputCanvas;
}
Apply Changes