Please bookmark this page to avoid losing your image tool!

Image Quadtone Effect Adder

(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, color1 = '#000000', color2 = '#554433', color3 = '#aa9977', color4 = '#fff8f0') {

    /**
     * Helper function to parse a hex color string to an RGB object.
     * @param {string} hex - The hex color string (e.g., "#RRGGBB" or "#RGB").
     * @returns {{r: number, g: number, b: number}|null} An object with r, g, b properties or null if invalid.
     */
    function hexToRgb(hex) {
        // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
        const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
        hex = hex.replace(shorthandRegex, (m, r, g, b) => {
            return r + r + g + g + b + b;
        });

        const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
        return result ? {
            r: parseInt(result[1], 16),
            g: parseInt(result[2], 16),
            b: parseInt(result[3], 16)
        } : null;
    }
    
    /**
     * Helper function to linearly interpolate between two colors.
     * @param {{r: number, g: number, b: number}} c1 - The starting color object.
     * @param {{r: number, g: number, b: number}} c2 - The ending color object.
     * @param {number} amount - The interpolation amount (0.0 to 1.0).
     * @returns {{r: number, g: number, b: number}} The interpolated color object.
     */
    function lerpColor(c1, c2, amount) {
        // Clamp amount to be between 0 and 1
        amount = Math.max(0, Math.min(1, amount)); 
        const r = c1.r + (c2.r - c1.r) * amount;
        const g = c1.g + (c2.g - c1.g) * amount;
        const b = c1.b + (c2.b - c1.b) * amount;
        return { r, g, b };
    }

    // Create a canvas element
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    
    // Set canvas dimensions to the image's intrinsic dimensions
    canvas.width = originalImg.naturalWidth;
    canvas.height = originalImg.naturalHeight;

    // Parse the input colors from hex to RGB objects
    const rgb1 = hexToRgb(color1); // Shadows
    const rgb2 = hexToRgb(color2); // Dark mid-tones
    const rgb3 = hexToRgb(color3); // Light mid-tones
    const rgb4 = hexToRgb(color4); // Highlights

    // Fallback: If any color is invalid, draw the original image and return
    if (!rgb1 || !rgb2 || !rgb3 || !rgb4) {
        console.error("One or more invalid hex color codes provided. Returning original image.");
        ctx.drawImage(originalImg, 0, 0);
        return canvas;
    }

    // Draw the original image onto the canvas
    ctx.drawImage(originalImg, 0, 0);

    // Get the pixel data from the canvas
    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const data = imageData.data;
    
    // Define the brightness thresholds for the quadtone mapping
    const threshold1 = 255 / 3;
    const threshold2 = 255 * 2 / 3;

    // Iterate over each pixel (which is 4 bytes: R, G, B, A)
    for (let i = 0; i < data.length; i += 4) {
        const r = data[i];
        const g = data[i + 1];
        const b = data[i + 2];
        
        // Calculate the grayscale value (luminance) for the current pixel
        const gray = 0.299 * r + 0.587 * g + 0.114 * b;
        
        let newColor;

        // Determine the new color by interpolating between the quadtone colors based on brightness
        if (gray < threshold1) {
            // In the darkest range, blend between color1 and color2
            const amount = gray / threshold1;
            newColor = lerpColor(rgb1, rgb2, amount);
        } else if (gray < threshold2) {
            // In the mid-tone range, blend between color2 and color3
            const amount = (gray - threshold1) / (threshold2 - threshold1);
            newColor = lerpColor(rgb2, rgb3, amount);
        } else {
            // In the lightest range, blend between color3 and color4
            const amount = (gray - threshold2) / (255 - threshold2);
            newColor = lerpColor(rgb3, rgb4, amount);
        }
        
        // Update the pixel data with the new color values
        data[i] = newColor.r;     // Red
        data[i + 1] = newColor.g; // Green
        data[i + 2] = newColor.b; // Blue
        // Alpha channel (data[i + 3]) is preserved
    }

    // Put the modified image data back onto the canvas
    ctx.putImageData(imageData, 0, 0);
    
    // Return the final canvas element with the quadtone effect
    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 Quadtone Effect Adder is a tool that allows users to apply a quadtone color effect to their images. By enabling the transformation of standard images into artistic versions featuring up to four distinct colors, this tool enhances images with a creative and stylized appearance. It is particularly useful for photographers, graphic designers, and artists looking to give their digital images a unique touch or a vintage feel. Users can customize the color tones used in the effect, enabling a wide range of artistic possibilities for personal or professional projects.

Leave a Reply

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