Please bookmark this page to avoid losing your image tool!

Image LCH Color Viewer

(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) {
    // Constants for sRGB to XYZ conversion (D65 illuminant)
    const SRGB_TO_XYZ_MATRIX = [
        [0.4124564, 0.3575761, 0.1804375],
        [0.2126729, 0.7151522, 0.0721750],
        [0.0193339, 0.1191920, 0.9503041]
    ];

    // D65 reference white for XYZ to Lab conversion (Yn = 1.0 normalized)
    const D65_REF_X = 0.95047;
    const D65_REF_Y = 1.00000;
    const D65_REF_Z = 1.08883;

    // Constants for XYZ to Lab conversion (CIELAB standard)
    const LAB_E = 216 / 24389;  // (6/29)^3
    // f(t) = K_TERM_COEFF * t + 4/29  for t <= E
    // K_TERM_COEFF = (1/3) * (29/6)^2 = 841 / 108
    const LAB_K_TERM_COEFF = 841 / 108; 
    const LAB_4_29 = 4/29;

    // Helper function to convert sRGB channel to linear RGB
    function srgbToLinear(c_srgb) {
        // Input c_srgb is in range [0, 1]
        if (c_srgb <= 0.04045) {
            return c_srgb / 12.92;
        }
        return Math.pow((c_srgb + 0.055) / 1.055, 2.4);
    }

    // Helper function to convert RGB (0-255) to XYZ
    function rgbToXyz(r_srgb, g_srgb, b_srgb) {
        const r_linear = srgbToLinear(r_srgb / 255);
        const g_linear = srgbToLinear(g_srgb / 255);
        const b_linear = srgbToLinear(b_srgb / 255);

        const X = r_linear * SRGB_TO_XYZ_MATRIX[0][0] + g_linear * SRGB_TO_XYZ_MATRIX[0][1] + b_linear * SRGB_TO_XYZ_MATRIX[0][2];
        const Y = r_linear * SRGB_TO_XYZ_MATRIX[1][0] + g_linear * SRGB_TO_XYZ_MATRIX[1][1] + b_linear * SRGB_TO_XYZ_MATRIX[1][2];
        const Z = r_linear * SRGB_TO_XYZ_MATRIX[2][0] + g_linear * SRGB_TO_XYZ_MATRIX[2][1] + b_linear * SRGB_TO_XYZ_MATRIX[2][2];
        
        // Resulting X, Y, Z are D65-adapted, with Y_nominal_white = 1.0
        return { x: X, y: Y, z: Z };
    }

    // Helper function 'f' for XYZ to Lab conversion
    function xyzToLab_f(t) {
        if (t > LAB_E) {
            return Math.cbrt(t); // Cube root
        }
        return (LAB_K_TERM_COEFF * t) + LAB_4_29;
    }

    // Helper function to convert XYZ to CIELAB
    function xyzToLab(x, y, z) {
        const fx = xyzToLab_f(x / D65_REF_X);
        const fy = xyzToLab_f(y / D65_REF_Y); // y / 1.0 for D65_REF_Y = 1.0
        const fz = xyzToLab_f(z / D65_REF_Z);

        const L = (116 * fy) - 16;
        const a = 500 * (fx - fy);
        const b = 200 * (fy - fz);

        return { l: L, a: a, b: b };
    }

    // Helper function to convert CIELAB to CIELCH
    function labToLch(l, a, b) {
        const C = Math.sqrt(a * a + b * b);
        let H_rad = Math.atan2(b, a); // Result is in radians, range [-PI, PI]
        let H_deg = H_rad * (180 / Math.PI);

        // Ensure hue is in [0, 360)
        if (H_deg < 0) {
            H_deg += 360;
        }
        // For achromatic colors (C=0), hue is conventionally 0. atan2(0,0) returns 0, so H_deg will be 0.

        return { l: l, c: C, h: H_deg };
    }

    // Main conversion pipeline: RGB to LCH
    function rgbToLch(r, g, b) {
        const xyz = rgbToXyz(r, g, b);
        const lab = xyzToLab(xyz.x, xyz.y, xyz.z);
        return labToLch(lab.l, lab.a, lab.b);
    }

    // Create the main container element
    const container = document.createElement('div');
    
    // Create canvas to draw the image
    const canvas = document.createElement('canvas');
    canvas.width = originalImg.width;
    canvas.height = originalImg.height;
    canvas.style.cursor = 'crosshair'; // Indicate interactivity
    const ctx = canvas.getContext('2d');
    ctx.drawImage(originalImg, 0, 0, originalImg.width, originalImg.height);

    // Create div to display LCH values
    const lchDisplay = document.createElement('div');
    lchDisplay.textContent = 'Hover over the image to see LCH values.';
    lchDisplay.style.padding = '10px';
    lchDisplay.style.fontFamily = 'monospace, sans-serif'; // Monospace for numbers
    lchDisplay.style.textAlign = 'center';
    lchDisplay.style.minHeight = '1.5em'; // Prevent layout shift
    lchDisplay.style.marginTop = '5px';

    // Event listener for mouse movement over the canvas
    canvas.addEventListener('mousemove', function(event) {
        const rect = canvas.getBoundingClientRect();
        let x = Math.floor(event.clientX - rect.left);
        let y = Math.floor(event.clientY - rect.top);

        // Clamp coordinates to be within canvas bounds
        x = Math.max(0, Math.min(x, canvas.width - 1));
        y = Math.max(0, Math.min(y, canvas.height - 1));
        
        // In case mouse somehow reports outside despite listener being on canvas (e.g. rápido movements / browser quirks)
        if (x < 0 || x >= canvas.width || y < 0 || y >= canvas.height) {
            lchDisplay.textContent = 'Hover over the image to see LCH values.';
            return;
        }

        const pixelData = ctx.getImageData(x, y, 1, 1).data; // [R, G, B, A]
        const [r, g, b] = pixelData;

        const lch = rgbToLch(r, g, b);

        lchDisplay.textContent = `L: ${lch.l.toFixed(2)}, C: ${lch.c.toFixed(2)}, H: ${lch.h.toFixed(2)}° (at ${x},${y})`;
    });

    // Event listener for mouse leaving the canvas
    canvas.addEventListener('mouseleave', function() {
        lchDisplay.textContent = 'Hover over the image to see LCH values.';
    });

    // Append canvas and LCH display to the container
    container.appendChild(canvas);
    container.appendChild(lchDisplay);

    return container;
}

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 LCH Color Viewer is a tool designed for visual analysis of colors in images. By hovering over the image, users can see the LCH (Lightness, Chroma, Hue) values of individual pixels. This tool can be beneficial for artists, designers, and color enthusiasts who want to understand the color composition of images, perform color grading, or explore color relationships in their work. It allows for precise color identification and adjustment, aiding in various creative and professional tasks.

Leave a Reply

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