Please bookmark this page to avoid losing your image tool!

Image To Pen Conversion 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.
/**
 * Converts an image into a simulated pen sketch using a cross-hatching technique.
 * The function analyzes the brightness of different regions of the image and applies
 * layers of hatch lines to darker areas, creating a hand-drawn effect.
 *
 * @param {HTMLImageElement} originalImg The source image object to be converted.
 * @param {string} lineColor The color of the pen lines in a valid CSS format (e.g., '#000000', 'blue').
 * @param {string} backgroundColor The color of the paper background.
 * @param {number} hatchSpacing The spacing of the grid used for hatching. Smaller values create more detail but take longer to process.
 * @param {number} darkness A multiplier affecting the density of the lines. Values greater than 1.0 make the sketch darker, while values less than 1.0 make it lighter.
 * @returns {Promise<HTMLCanvasElement>} A promise that resolves with a canvas element containing the pen sketch.
 */
async function processImage(originalImg, lineColor = '#000000', backgroundColor = '#FFFFFF', hatchSpacing = 4, darkness = 1.0) {
    // 1. Setup Canvas
    const canvas = document.createElement('canvas');
    // Using { alpha: false } can be a performance optimization since the background is always opaque.
    const ctx = canvas.getContext('2d', {
        alpha: false
    });
    canvas.width = originalImg.naturalWidth;
    canvas.height = originalImg.naturalHeight;

    // Create a temporary canvas for efficient pixel data access
    const tempCanvas = document.createElement('canvas');
    const tempCtx = tempCanvas.getContext('2d', {
        willReadFrequently: true
    });
    tempCanvas.width = canvas.width;
    tempCanvas.height = canvas.height;

    // 2. Create a Grayscale Map
    // Draw the image to the temporary canvas to get its pixel data
    tempCtx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
    const imageData = tempCtx.getImageData(0, 0, canvas.width, canvas.height);
    const data = imageData.data;

    // Create a 2D array to store the brightness of each pixel for faster lookups
    const grayData = [];
    for (let y = 0; y < canvas.height; y++) {
        grayData[y] = [];
        for (let x = 0; x < canvas.width; x++) {
            const i = (y * canvas.width + x) * 4;
            // Use the standard luminance formula to calculate brightness
            const brightness = 0.299 * data[i] + 0.587 * data[i + 1] + 0.114 * data[i + 2];
            grayData[y][x] = brightness;
        }
    }

    // 3. Render the Pen Effect
    // Fill the background with the paper color
    ctx.fillStyle = backgroundColor;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // Configure the 'pen' properties
    ctx.strokeStyle = lineColor;
    ctx.lineWidth = 0.8;
    ctx.lineCap = 'round'; // Use round line caps for a softer, more pen-like stroke

    // Define brightness thresholds for applying different layers of hatching.
    // The 'darkness' parameter adjusts these thresholds to control the overall effect.
    const d = Math.max(0.1, parseFloat(darkness) || 1.0);
    const thresholds = [220 / d, 180 / d, 120 / d, 80 / d, 40 / d];

    // Ensure hatchSpacing is a valid integer
    const s = Math.max(1, parseInt(hatchSpacing, 10) || 4);

    // Begin a single path to batch all line drawings, which is much more performant
    ctx.beginPath();

    // Iterate over the image in a grid defined by the hatchSpacing
    for (let y = 0; y < canvas.height; y += s) {
        for (let x = 0; x < canvas.width; x += s) {
            // Calculate the average brightness of the current grid cell
            let totalBrightness = 0;
            let count = 0;
            for (let j = 0; j < s && y + j < canvas.height; j++) {
                for (let i = 0; i < s && x + i < canvas.width; i++) {
                    totalBrightness += grayData[y + j][x + i];
                    count++;
                }
            }
            const avgBrightness = count > 0 ? totalBrightness / count : 255;

            // Add slight randomness to the center of the cell to make it look more hand-drawn
            const randX = x + s / 2 + (Math.random() - 0.5) * s * 0.4;
            const randY = y + s / 2 + (Math.random() - 0.5) * s * 0.4;
            const halfS = s / 2;

            // Add layers of hatching based on the cell's average brightness
            if (avgBrightness < thresholds[0]) {
                // Layer 1: Diagonal lines (\) for the lightest dark areas
                ctx.moveTo(randX - halfS, randY - halfS);
                ctx.lineTo(randX + halfS, randY + halfS);
            }
            if (avgBrightness < thresholds[1]) {
                // Layer 2: Cross-hatching with opposite diagonal lines (/)
                ctx.moveTo(randX + halfS, randY - halfS);
                ctx.lineTo(randX - halfS, randY + halfS);
            }
            if (avgBrightness < thresholds[2]) {
                // Layer 3: Add horizontal lines (-) for darker areas
                ctx.moveTo(randX - halfS, randY);
                ctx.lineTo(randX + halfS, randY);
            }
            if (avgBrightness < thresholds[3]) {
                // Layer 4: Add vertical lines (|) for even darker areas
                ctx.moveTo(randX, randY - halfS);
                ctx.lineTo(randX, randY + halfS);
            }
            if (avgBrightness < thresholds[4]) {
                // Layer 5: Add slightly tilted lines for the darkest areas to increase density
                ctx.moveTo(randX - halfS, randY + halfS / 2);
                ctx.lineTo(randX + halfS, randY - halfS / 2);
            }
        }
    }

    // Stroke the entire path at once to draw all the lines
    ctx.stroke();

    // 4. Return the final 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 To Pen Conversion Tool allows users to transform their images into a hand-drawn pen sketch effect using a cross-hatching technique. This tool is ideal for artists, designers, or anyone looking to create unique artistic representations of photographs or digital images. Users can customize aspects such as line color, background color, hatch spacing, and darkness to enhance the sketch’s depth and visual style. Suitable applications include creating illustrations for personal projects, enhancing graphic designs, or adding a creative touch to promotional materials.

Leave a Reply

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