Please bookmark this page to avoid losing your image tool!

Image Alphabet And Translator Tool

(Free & Supports Bulk Upload)

Drag & drop your images here or

The result will appear here...
You can edit the below JavaScript code to customize the image tool.
/**
 * Translates text into a custom alphabet defined by a sprite sheet image.
 * This function renders the translated text onto a new canvas, handling
 * line wrapping and custom character spacing.
 *
 * The character mapping is defined by a JSON string (`mapJson`) which can be
 * in one of two formats: "grid" or "explicit".
 *
 * 1. Grid Format:
 *    Assumes characters are in a uniform grid in the source image.
 *    - `config.type`: Must be "grid".
 *    - `config.charWidth`: The width of a single character cell.
 *    - `config.charHeight`: The height of a single character cell.
 *    - `config.spaceWidth`: (Optional) The width of a space character.
 *    - `map`: An object where keys are characters ('A', 'B', etc.) and
 *             values are [column, row] arrays indicating the character's
 *             position in the grid (e.g., "A": [0, 0]).
 *
 * 2. Explicit Format (default if `config.type` is not "grid"):
 *    Allows each character to have a different size and position.
 *    - `map`: An object where keys are characters and values are objects
 *             with {x, y, w, h} properties defining the source rectangle
 *             in the image (e.g., "A": {"x":0, "y":0, "w":10, "h":12}).
 *
 * @param {Image} originalImg The source image object containing the alphabet sprites.
 * @param {string} textToTranslate The text to be rendered.
 * @param {string} mapJson A JSON string describing the character map. If empty, a default grid-based map is used.
 * @param {number} outputWidth The target width of the canvas. Text will wrap to fit this width.
 * @param {number} letterSpacing The number of pixels of extra space between letters.
 * @param {number} lineHeightMultiplier A multiplier for line height, based on the tallest character. E.g., 1.2 means 20% extra space between lines.
 * @returns {HTMLCanvasElement} A new canvas element with the rendered text.
 */
async function processImage(
    originalImg,
    textToTranslate = 'The quick brown fox jumps over the lazy dog. 1234567890.',
    mapJson = '',
    outputWidth = 800,
    letterSpacing = 1,
    lineHeightMultiplier = 1.2
) {
    const defaultMapJson = `{
      "config": {
        "type": "grid",
        "charWidth": 32,
        "charHeight": 32,
        "spaceWidth": 16
      },
      "map": {
        "A": [0,0], "B": [1,0], "C": [2,0], "D": [3,0], "E": [4,0], "F": [5,0], "G": [6,0], "H": [7,0], "I": [8,0], "J": [9,0],
        "K": [0,1], "L": [1,1], "M": [2,1], "N": [3,1], "O": [4,1], "P": [5,1], "Q": [6,1], "R": [7,1], "S": [8,1], "T": [9,1],
        "U": [0,2], "V": [1,2], "W": [2,2], "X": [3,2], "Y": [4,2], "Z": [5,2],
        "a": [0,3], "b": [1,3], "c": [2,3], "d": [3,3], "e": [4,3], "f": [5,3], "g": [6,3], "h": [7,3], "i": [8,3], "j": [9,3],
        "k": [0,4], "l": [1,4], "m": [2,4], "n": [3,4], "o": [4,4], "p": [5,4], "q": [6,4], "r": [7,4], "s": [8,4], "t": [9,4],
        "u": [0,5], "v": [1,5], "w": [2,5], "x": [3,5], "y": [4,5], "z": [5,5],
        "0": [0,6], "1": [1,6], "2": [2,6], "3": [3,6], "4": [4,6], "5": [5,6], "6": [6,6], "7": [7,6], "8": [8,6], "9": [9,6],
        ".": [0,7], ",": [1,7], "!": [2,7], "?": [3,7], "'": [4,7], "\\"": [5,7], "(": [6,7], ")": [7,7], "-": [8,7], ":": [9,7]
      }
    }`;

    if (mapJson.trim() === '') {
        mapJson = defaultMapJson;
    }

    let charMap;
    try {
        charMap = JSON.parse(mapJson);
    } catch (e) {
        const errorCanvas = document.createElement('canvas');
        errorCanvas.width = Math.max(300, outputWidth);
        errorCanvas.height = 120;
        const ctx = errorCanvas.getContext('2d');
        ctx.fillStyle = '#f8f8f8';
        ctx.fillRect(0, 0, errorCanvas.width, errorCanvas.height);
        ctx.fillStyle = 'red';
        ctx.font = 'bold 16px sans-serif';
        ctx.fillText('Error: Invalid Character Map JSON', 10, 25);
        ctx.fillStyle = 'black';
        ctx.font = '14px monospace';
        ctx.fillText(e.message, 10, 50);
        ctx.fillText('Please correct the JSON syntax and try again.', 10, 75);
        return errorCanvas;
    }

    const fallbackCharSymbol = charMap.map ?. ['?'] ? '?' : null;

    const getCharData = (char) => {
        const mapConfig = charMap.config || {};
        const mapData = charMap.map || {};

        let charInfo = mapData[char];
        if (!charInfo && fallbackCharSymbol) {
            charInfo = mapData[fallbackCharSymbol];
        }
        if (!charInfo) return null;

        if (mapConfig.type === 'grid') {
            const cw = mapConfig.charWidth || 32;
            const ch = mapConfig.charHeight || 32;
            return {
                sx: charInfo[0] * cw,
                sy: charInfo[1] * ch,
                sw: cw,
                sh: ch
            };
        } else {
            return {
                sx: charInfo.x,
                sy: charInfo.y,
                sw: charInfo.w,
                sh: charInfo.h
            };
        }
    };

    let maxCharHeight = 0;
    if (charMap.config ?.type === 'grid' && charMap.config.charHeight) {
        maxCharHeight = charMap.config.charHeight;
    } else {
        Object.keys(charMap.map || {}).forEach(char => {
            const data = getCharData(char);
            if (data && data.sh > maxCharHeight) maxCharHeight = data.sh;
        });
    }
    if (maxCharHeight === 0) maxCharHeight = 32;

    const lineHeight = Math.round(maxCharHeight * lineHeightMultiplier);
    const spaceWidth = charMap.config ?.spaceWidth || Math.round(maxCharHeight / 2);

    // --- Prepare characters for layout ---
    const layoutItems = [];
    for (const char of textToTranslate) {
        if (char === '\n') {
            layoutItems.push({
                isNewline: true
            });
            continue;
        }
        if (/\s/.test(char)) {
            layoutItems.push({
                isSpace: true,
                sw: spaceWidth
            });
            continue;
        }
        const data = getCharData(char);
        if (data) {
            layoutItems.push(data);
        }
    }

    // --- Arrange characters into wrapped lines ---
    const linesToDraw = [
        []
    ];
    let currentLineIndex = 0;
    let x = 0;

    layoutItems.forEach(item => {
        if (item.isNewline) {
            linesToDraw.push([]);
            currentLineIndex++;
            x = 0;
            return;
        }

        const itemWidth = item.sw + letterSpacing;
        if (x > 0 && x + itemWidth > outputWidth && !item.isSpace) {
            linesToDraw.push([]);
            currentLineIndex++;
            x = 0;
        }
        linesToDraw[currentLineIndex].push(item);
        x += itemWidth;
    });

    // --- Create canvas and render lines ---
    const canvasHeight = Math.max(1, linesToDraw.length) * lineHeight;
    const canvas = document.createElement('canvas');
    canvas.width = outputWidth;
    canvas.height = canvasHeight;
    const ctx = canvas.getContext('2d');

    let currentY = 0;
    linesToDraw.forEach(line => {
        let drawX = 0;
        line.forEach(item => {
            if (item.isSpace || item.isNewline) {
                drawX += item.sw + letterSpacing;
            } else {
                const yOffset = Math.floor((lineHeight - item.sh) / 2);
                ctx.drawImage(originalImg, item.sx, item.sy, item.sw, item.sh, drawX, currentY + yOffset, item.sw, item.sh);
                drawX += item.sw + letterSpacing;
            }
        });
        currentY += lineHeight;
    });

    return canvas;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

The Image Alphabet and Translator Tool allows users to translate text into a visually appealing representation using custom alphabets defined by sprite sheet images. This tool can be utilized for creating unique textual graphics for various applications such as graphic design, game development, or artistic projects. It handles text rendering smartly, accommodating line wrapping and custom spacing to ensure proper layout based on the specified character mappings. Users can define character mappings in either grid or explicit formats, making it flexible for different sprite sheet designs.

Leave a Reply

Your email address will not be published. Required fields are marked *