You can edit the below JavaScript code to customize the image tool.
/**
* Generates a fictional "language code name" based on the dominant colors of an image.
* This function analyzes the input image to find its primary colors, then translates
* the properties of each color (hue, saturation, lightness) into phonetic syllables
* to construct a unique name. The result is rendered on a new canvas featuring the
* original image as a backdrop, the generated name, and the color palette used.
*
* @param {Image} originalImg The original source image object.
* @param {number} [numberOfWords=1] The number of words to generate in the name.
* @param {number} [syllablesPerWord=3] The number of syllables each word should have.
* @returns {HTMLCanvasElement} A canvas element displaying the generated name and color palette.
*/
function processImage(originalImg, numberOfWords = 1, syllablesPerWord = 3) {
// Helper function to convert RGB to HSL color space.
// HSL is more intuitive for mapping color properties to phonetic elements.
const rgbToHsl = (r, g, b) => {
r /= 255;
g /= 255;
b /= 255;
const max = Math.max(r, g, b),
min = Math.min(r, g, b);
let h = 0,
s = 0,
l = (max + min) / 2;
if (max !== min) {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return {
h: h * 360,
s,
l
};
};
// Helper function to find the most frequent (dominant) colors in an image
// using a fast color quantization method.
const findDominantColors = (img, count) => {
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d', {
willReadFrequently: true
});
// Downscale image for much faster processing
const scale = Math.min(1, 100 / Math.max(img.width, img.height));
const w = img.width * scale;
const h = img.height * scale;
tempCanvas.width = w;
tempCanvas.height = h;
tempCtx.drawImage(img, 0, 0, w, h);
const imageData = tempCtx.getImageData(0, 0, w, h).data;
const colorBins = {};
// Quantize colors to reduce the color space (e.g., 24-bit to 12-bit).
// This groups similar colors together into "bins".
const quantizeShift = 4; // 8-bit -> 4-bit per channel
for (let i = 0; i < imageData.length; i += 4) {
// Skip transparent or semi-transparent pixels
if (imageData[i + 3] < 128) continue;
const r_quant = imageData[i] >> quantizeShift;
const g_quant = imageData[i + 1] >> quantizeShift;
const b_quant = imageData[i + 2] >> quantizeShift;
// Create a single numeric key for the quantized color bin
const key = (r_quant << 8) | (g_quant << 4) | b_quant;
if (!colorBins[key]) {
colorBins[key] = {
r: 0,
g: 0,
b: 0,
count: 0
};
}
// Sum the original color values to calculate an accurate average later
colorBins[key].r += imageData[i];
colorBins[key].g += imageData[i + 1];
colorBins[key].b += imageData[i + 2];
colorBins[key].count++;
}
// Sort bins by the number of pixels they represent
const sortedBins = Object.values(colorBins).sort((a, b) => b.count - a.count);
// Calculate the average color for the top `count` bins
const dominantPalette = sortedBins.slice(0, count).map(bin => ({
r: Math.round(bin.r / bin.count),
g: Math.round(bin.g / bin.count),
b: Math.round(bin.b / bin.count),
}));
return dominantPalette;
};
// Helper function to generate a name from a palette of colors by creating
// syllables based on the HSL values of each color.
const generateNameFromColors = (colors, wordCount, syllPerWord) => {
const consonants = ['k', 't', 's', 'n', 'r', 'l', 'm', 'p', 'b', 'g', 'd', 'f', 'v', 'h', 'j', 'z', 'x', 'c'];
const vowels = ['a', 'e', 'i', 'o', 'u'];
let syllables = colors.map(color => {
const {
h,
s,
l
} = rgbToHsl(color.r, color.g, color.b);
// Map HSL properties to phonetic components
const c1_idx = Math.floor((h / 360) * consonants.length);
const v_idx = Math.floor(s * vowels.length);
const c2_idx = Math.floor(l * consonants.length);
const c1 = consonants[c1_idx % consonants.length];
const v = vowels[Math.min(v_idx, vowels.length - 1)];
const c2 = consonants[Math.min(c2_idx, consonants.length - 1)];
// Form a syllable (e.g., CV for bright/desaturated, CVC for others)
return (l > 0.7 || s < 0.2) ? (c1 + v) : (c1 + v + c2);
});
// Ensure we have enough syllables for the requested name structure
const requiredSyllables = wordCount * syllPerWord;
while (syllables.length < requiredSyllables) {
syllables.push('ix'); // Add a default, neutral syllable
}
let words = [];
for (let i = 0; i < wordCount; i++) {
const wordSyllables = syllables.slice(i * syllPerWord, (i + 1) * syllPerWord);
const word = wordSyllables.join('');
words.push(word.charAt(0).toUpperCase() + word.slice(1));
}
return words.join(' ');
};
// --- Main Execution ---
// 1. Analyze the image to find its most dominant colors
const totalSyllables = Math.max(1, numberOfWords * syllablesPerWord);
const dominantColors = findDominantColors(originalImg, totalSyllables);
// 2. Generate a name based on the extracted color palette
const generatedName = generateNameFromColors(dominantColors, numberOfWords, syllablesPerWord);
// 3. Create the output canvas to display the final result
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const {
width,
height
} = originalImg;
canvas.width = width;
canvas.height = height;
// Draw the original image as a blurred and darkened background
ctx.filter = 'blur(4px) brightness(0.6)';
ctx.drawImage(originalImg, 0, 0, width, height);
ctx.filter = 'none';
// Draw the generated name over the background
ctx.fillStyle = 'white';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.shadowColor = 'rgba(0, 0, 0, 0.7)';
ctx.shadowBlur = 10;
// Dynamically adjust font size to fit the canvas
const estCharWidth = 0.7; // Estimated avg character width for a monospace font
const maxFontSize = height / 5;
const fontSizeForWidth = width / (generatedName.length * estCharWidth);
const fontSize = Math.min(maxFontSize, Math.max(24, fontSizeForWidth));
ctx.font = `bold ${fontSize}px 'Courier New', monospace`;
ctx.fillText(generatedName, width / 2, height / 2);
// Draw the derived color palette at the bottom
if (dominantColors.length > 0) {
const paletteHeight = Math.max(20, Math.floor(height / 12));
const paletteMargin = paletteHeight / 2;
const totalPaletteWidth = Math.min(width * 0.8, dominantColors.length * (paletteHeight + 5));
const startX = (width - totalPaletteWidth) / 2;
const startY = height - paletteHeight - paletteMargin;
const swatchWidth = totalPaletteWidth / dominantColors.length;
dominantColors.forEach((color, index) => {
ctx.fillStyle = `rgb(${color.r}, ${color.g}, ${color.b})`;
ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
ctx.lineWidth = 1;
const swatchX = startX + index * swatchWidth;
const swatchInnerWidth = swatchWidth - 5;
ctx.fillRect(swatchX, startY, swatchInnerWidth, paletteHeight);
ctx.strokeRect(swatchX, startY, swatchInnerWidth, paletteHeight);
});
}
return canvas;
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
The Image Language Code Name Generator is a creative tool that generates unique, fictional names based on the dominant colors of an input image. By analyzing the primary colors in the image, it constructs names using phonetic syllables derived from the properties of each color. The result is a visually appealing canvas that showcases the original image as a backdrop, displays the generated name, and includes a color palette of the dominant hues. This tool can be useful for artists, designers, and content creators looking to create memorable and thematic names for their projects, artwork, or products inspired by color schemes. Additionally, it serves as a fun way to engage with color theory and creativity.