Please bookmark this page to avoid losing your image tool!

Image Carbon Copy Filter Effect 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, threshold = 128, darkColorString = "0,0,0", lightColorString = "255,255,255") {
    // Clamp threshold to the valid range [0, 255]
    const effectiveThreshold = Math.max(0, Math.min(255, Number(threshold)));

    // Create a canvas element
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // Get image dimensions. Assumes originalImg is a loaded HTMLImageElement.
    // naturalWidth/Height provide the intrinsic dimensions of the image.
    const imgWidth = originalImg.naturalWidth;
    const imgHeight = originalImg.naturalHeight;

    // Helper function to create and return a canvas displaying an error message
    const createErrorCanvas = (width, height, messageLines) => {
        const errCanvas = document.createElement('canvas');
        // Use provided dimensions, or fallback to a default size if dimensions are 0
        errCanvas.width = width > 0 ? width : 150; 
        errCanvas.height = height > 0 ? height : 100;
        const errCtx = errCanvas.getContext('2d');

        // Fill background
        errCtx.fillStyle = 'lightgray';
        errCtx.fillRect(0, 0, errCanvas.width, errCanvas.height);

        // Draw text
        errCtx.fillStyle = 'red';
        errCtx.textAlign = 'center';
        errCtx.textBaseline = 'middle';
        
        const lineHeight = 18; // Adjust as needed for font size
        const FONT_SIZE = 12; // Example font size
        errCtx.font = `${FONT_SIZE}px Arial`;
        
        const totalTextHeight = messageLines.length * lineHeight;
        let startY = (errCanvas.height - totalTextHeight) / 2 + (lineHeight / 2) - (FONT_SIZE / 10) ; // Approximate centering

        messageLines.forEach((line, index) => {
            errCtx.fillText(line, errCanvas.width / 2, startY + index * lineHeight);
        });
        return errCanvas;
    };

    // Validate image dimensions
    if (imgWidth === 0 || imgHeight === 0) {
        return createErrorCanvas(0, 0, ["Image has zero dimensions.", "(Not loaded or invalid?)"]);
    }

    canvas.width = imgWidth;
    canvas.height = imgHeight;

    // Draw the original image onto the canvas
    try {
        ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);
    } catch (e) {
        // This can happen if originalImg is not a valid image source
        return createErrorCanvas(imgWidth, imgHeight, ["Error: Could not draw image."]);
    }
    
    // Get the image data
    let imageData;
    try {
        imageData = ctx.getImageData(0, 0, imgWidth, imgHeight);
    } catch (e) {
        // This typically happens due to cross-origin restrictions
        return createErrorCanvas(imgWidth, imgHeight, ["Error: Cannot process pixels.", "(Image may be cross-origin)"]);
    }
    
    const data = imageData.data;

    // Helper function to parse color strings like "r,g,b"
    // Returns an array [r, g, b] or defaultColor if parsing fails.
    // Clamps color components to [0, 255].
    const parseRgbColor = (colorStr, defaultColor) => {
        if (typeof colorStr !== 'string') {
            return defaultColor; // Ensure input is a string
        }
        const components = colorStr.split(',');
        if (components.length !== 3) {
            return defaultColor; // Expect "r,g,b"
        }
        
        const parts = components.map(s => Number(s.trim()));
        
        if (parts.some(p => isNaN(p))) {
            return defaultColor; // Expect numeric components
        }
        
        // Clamp each component to [0, 255]
        return parts.map(p => Math.max(0, Math.min(255, p)));
    };

    const defaultDarkRgb = [0, 0, 0];    // Default to black
    const defaultLightRgb = [255, 255, 255]; // Default to white

    const darkColor = parseRgbColor(darkColorString, defaultDarkRgb);
    const lightColor = parseRgbColor(lightColorString, defaultLightRgb);

    // Iterate over each pixel (R, G, B, Alpha components)
    for (let i = 0; i < data.length; i += 4) {
        const r = data[i];
        const g = data[i + 1];
        const b = data[i + 2];
        
        // Calculate grayscale value using the luminosity method for perceived brightness
        const gray = 0.299 * r + 0.587 * g + 0.114 * b;
        
        let outputR, outputG, outputB;
        if (gray < effectiveThreshold) {
            // Pixel is darker than threshold, apply dark color
            outputR = darkColor[0];
            outputG = darkColor[1];
            outputB = darkColor[2];
        } else {
            // Pixel is lighter than or equal to threshold, apply light color
            outputR = lightColor[0];
            outputG = lightColor[1];
            outputB = lightColor[2];
        }

        // Apply the new color
        data[i] = outputR;     // Red
        data[i + 1] = outputG; // Green
        data[i + 2] = outputB; // Blue
        // Alpha (data[i + 3]) remains unchanged to preserve transparency
    }

    // Put the modified image data back onto the canvas
    ctx.putImageData(imageData, 0, 0);

    // Return the processed canvas
    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 Carbon Copy Filter Effect Tool allows users to apply a carbon copy filter effect to their images. It converts the original image into a two-tone version based on user-defined threshold settings, replacing dark pixels with one color and light pixels with another. This tool is useful for creating high-contrast designs, artistic effects, or simplifying images for print. Ideal use cases include graphic design, creating unique social media posts, and generating artistic renditions of photographs.

Leave a Reply

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