Please bookmark this page to avoid losing your image tool!

Image Alphabetical 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.
function processImage(originalImg, sortMode = 'rows', sortKey = 'brightness', sortDirection = 'ascending', thresholdMinStr = '0', thresholdMaxStr = '255') {
    // This function interprets "Image Alphabetical Translator" as a "pixel sorting" utility.
    // "Alphabetical" is interpreted as sorting pixels based on a certain value.
    // This implementation provides various sorting keys, including a 'hex' mode for true 
    // alphabetical (lexicographical) sorting of color values.

    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } is a performance hint for browsers.
    const ctx = canvas.getContext('2d', { willReadFrequently: true });
    canvas.width = originalImg.naturalWidth;
    canvas.height = originalImg.naturalHeight;
    ctx.drawImage(originalImg, 0, 0);

    const thresholdMin = Number(thresholdMinStr);
    let thresholdMax = Number(thresholdMaxStr);

    /**
     * Converts an RGB color value to HSL.
     * @param {number} r The red color value (0-255)
     * @param {number} g The green color value (0-255)
     * @param {number} b The blue color value (0-255)
     * @returns {Array<number>} An array containing the HSL values [h, s, l].
     */
    function rgbToHsl(r, g, b) {
        r /= 255;
        g /= 255;
        b /= 255;
        const max = Math.max(r, g, b);
        const 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 * 360, s * 100, l * 100];
    }

    /**
     * Calculates a sortable value from RGB components based on the specified sortKey.
     * @param {number} r The red color value (0-255)
     * @param {number} g The green color value (0-255)
     * @param {number} b The blue color value (0-255)
     * @param {string} key The sorting key ('hex', 'red', 'green', 'blue', 'hue', etc.)
     * @returns {number|string} The value to be used for sorting.
     */
    function getSortValue(r, g, b, key) {
        switch (key) {
            case 'hex':
                const toHex = c => c.toString(16).padStart(2, '0');
                return `${toHex(r)}${toHex(g)}${toHex(b)}`;
            case 'red': return r;
            case 'green': return g;
            case 'blue': return b;
            case 'hue':
            case 'saturation':
            case 'lightness': {
                const [h, s, l] = rgbToHsl(r, g, b);
                if (key === 'hue') return h;
                if (key === 'saturation') return s;
                return l;
            }
            case 'brightness':
            default:
                // Luma formula (BT.601 standard)
                return (0.299 * r + 0.587 * g + 0.114 * b);
        }
    }

    // Adjust the maximum possible threshold value based on the sort key.
    // Thresholds do not apply to 'hex' mode.
    if (sortKey !== 'hex') {
        let maxVal = 255;
        if (sortKey === 'hue') maxVal = 360;
        if (sortKey === 'saturation' || sortKey === 'lightness') maxVal = 100;
        if (thresholdMax > maxVal) {
            thresholdMax = maxVal;
        }
    }

    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const data = imageData.data;
    const { width, height } = canvas;

    const getPixel = (x, y) => {
        const i = (y * width + x) * 4;
        return [data[i], data[i + 1], data[i + 2], data[i + 3]];
    };

    const setPixel = (x, y, rgba) => {
        const i = (y * width + x) * 4;
        data[i] = rgba[0];
        data[i + 1] = rgba[1];
        data[i + 2] = rgba[2];
        data[i + 3] = rgba[3];
    };
    
    const sortSegment = (start, end, fixedCoord, isRow) => {
        if (start >= end) return; // Nothing to sort for a single pixel or less
        const segmentPixels = [];
        // Extract pixels from the segment
        for (let i = start; i <= end; i++) {
            const [x, y] = isRow ? [i, fixedCoord] : [fixedCoord, i];
            const rgba = getPixel(x, y);
            segmentPixels.push({ rgba, sortValue: getSortValue(rgba[0], rgba[1], rgba[2], sortKey) });
        }

        // Sort the segment
        segmentPixels.sort((a, b) => {
            if (sortKey === 'hex') {
                return sortDirection === 'ascending' 
                    ? a.sortValue.localeCompare(b.sortValue) 
                    : b.sortValue.localeCompare(a.sortValue);
            } else {
                 return sortDirection === 'ascending' 
                    ? a.sortValue - b.sortValue 
                    : b.sortValue - a.sortValue;
            }
        });

        // Write the sorted pixels back to the main image data
        for (let i = start; i <= end; i++) {
            const [x, y] = isRow ? [i, fixedCoord] : [fixedCoord, i];
            setPixel(x, y, segmentPixels[i - start].rgba);
        }
    };

    const processLines = (lineLength, fixedLength, isRow) => {
        for (let i = 0; i < fixedLength; i++) {
            let segmentStart = -1;
            for (let j = 0; j < lineLength; j++) {
                const [x, y] = isRow ? [j, i] : [i, j];
                const rgba = getPixel(x, y);
                // For 'hex' mode, ignore thresholds and sort the entire line.
                const value = sortKey === 'hex' ? 0 : getSortValue(rgba[0], rgba[1], rgba[2], sortKey);
                const inThreshold = sortKey === 'hex' || (value >= thresholdMin && value <= thresholdMax);

                if (inThreshold && segmentStart < 0) {
                    segmentStart = j; // Start of a new sortable segment
                } else if (!inThreshold && segmentStart >= 0) {
                    sortSegment(segmentStart, j - 1, i, isRow); // End of a segment
                    segmentStart = -1;
                }
            }
            // If a segment extends to the end of the line, sort it.
            if (segmentStart >= 0) {
                sortSegment(segmentStart, lineLength - 1, i, isRow);
            }
        }
    };

    if (sortMode === 'rows') {
        processLines(width, height, true);
    } else if (sortMode === 'columns') {
        processLines(height, width, false);
    }

    ctx.putImageData(imageData, 0, 0);
    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 Alphabetical Translator Tool is a pixel sorting utility that allows users to manipulate images by sorting their pixels based on various criteria such as brightness, color channels (red, green, blue), and even hexadecimal values. Users can choose to sort pixels in either rows or columns, and can set thresholds for sorting. This tool can be useful for artists and designers looking to create unique visual effects, for data visualization purposes, or for generating abstract representations of images based on different sorting criteria.

Leave a Reply

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