Please bookmark this page to avoid losing your image tool!

Image Cleaning Guide

(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.
async function processImage(originalImg, textColor = '#FFFFFF', shadowColor = '#000000', guideCount = 5) {

    /**
     * Helper function to draw an arrow on a 2D canvas context.
     * @param {CanvasRenderingContext2D} ctx - The canvas context.
     * @param {number} fromx - The x-coordinate of the arrow's starting point.
     * @param {number} fromy - The y-coordinate of the arrow's starting point.
     * @param {number} tox - The x-coordinate of the arrow's end point (tip).
     * @param {number} toy - The y-coordinate of the arrow's end point (tip).
     */
    const drawArrow = (ctx, fromx, fromy, tox, toy) => {
        const headlen = Math.max(10, ctx.lineWidth * 5); // Length of the arrowhead
        const dx = tox - fromx;
        const dy = toy - fromy;
        const angle = Math.atan2(dy, dx);

        ctx.beginPath();
        ctx.moveTo(fromx, fromy);
        ctx.lineTo(tox, toy); // Main line of the arrow

        // Draw the first side of the arrowhead
        ctx.lineTo(tox - headlen * Math.cos(angle - Math.PI / 6), toy - headlen * Math.sin(angle - Math.PI / 6));
        
        // Move back to the tip to draw the second side
        ctx.moveTo(tox, toy);
        ctx.lineTo(tox - headlen * Math.cos(angle + Math.PI / 6), toy - headlen * Math.sin(angle + Math.PI / 6));
        
        ctx.stroke();
    };

    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // Set canvas size to the original image's dimensions
    canvas.width = originalImg.naturalWidth;
    canvas.height = originalImg.naturalHeight;

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

    // A list of cleaning-related phrases, inspired by the Russian description "Про уборку" (About cleaning)
    const phrases = [
        "Почистить здесь",
        "Протереть, не откладывая",
        "Отмыть пятно",
        "Не забыть уголки",
        "Побрызгать средством",
        "Тщательно отполировать",
        "Убрать пыль",
        "Смахнуть паутину",
        "Вывести грязь",
        "Главное - начать!"
    ];
    
    // Set up drawing styles for the guide elements
    const fontSize = Math.max(16, Math.min(canvas.width, canvas.height) / 30);
    ctx.font = `bold ${fontSize}px "Segoe UI", Arial, sans-serif`;
    ctx.fillStyle = textColor;
    ctx.strokeStyle = textColor; // Arrow color
    ctx.lineWidth = Math.max(2, fontSize / 12);
    
    // Add a shadow for better visibility of text and arrows against any background
    ctx.shadowColor = shadowColor;
    ctx.shadowBlur = 7;
    ctx.shadowOffsetX = 2;
    ctx.shadowOffsetY = 2;

    const numGuides = Math.max(0, Math.min(20, guideCount)); // Clamp guide count for performance and readability

    for (let i = 0; i < numGuides; i++) {
        // Pick a random phrase
        const phrase = phrases[Math.floor(Math.random() * phrases.length)];
        const metrics = ctx.measureText(phrase);
        const textWidth = metrics.width;
        const textHeight = fontSize; // Use font size as a stable approximation for height

        // Position the center of the text (cx, cy) ensuring it's fully visible
        const margin = 10;
        const cx = (textWidth / 2) + margin + Math.random() * (canvas.width - textWidth - 2 * margin);
        const cy = (textHeight / 2) + margin + Math.random() * (canvas.height - textHeight - 2 * margin);

        // Position the arrow's target point (tx, ty) on the image
        let tx, ty;
        do {
            tx = canvas.width * 0.1 + Math.random() * canvas.width * 0.8;
            ty = canvas.height * 0.1 + Math.random() * canvas.height * 0.8;
        } while (Math.sqrt(Math.pow(tx - cx, 2) + Math.pow(ty - cy, 2)) < textWidth); // Ensure target is not too close to the text

        // Calculate the arrow's starting point (sx, sy) on the edge of the text's bounding box
        const dx = tx - cx;
        const dy = ty - cy;
        const angle = Math.atan2(dy, dx);

        const halfW = textWidth / 2 + 5; // Add a small padding
        const halfH = textHeight / 2 + 5;

        // Safely calculate the intersection of a ray from the center to the target with the bounding box
        const cosAngle = Math.cos(angle);
        const sinAngle = Math.sin(angle);

        // Distance to vertical edge and horizontal edge along the ray
        const t_h = (cosAngle === 0) ? Infinity : Math.abs(halfW / cosAngle);
        const t_v = (sinAngle === 0) ? Infinity : Math.abs(halfH / sinAngle);
        
        // The actual distance to the box edge is the minimum of the two
        const t = Math.min(t_h, t_v);
        
        const sx = cx + t * Math.cos(angle);
        const sy = cy + t * Math.sin(angle);
        
        // Set text alignment for drawing
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";

        // Draw the "cleaning" instruction
        ctx.fillText(phrase, cx, cy);

        // Draw the guide arrow pointing from the text's edge to the target
        drawArrow(ctx, sx, sy, tx, ty);
    }

    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 Cleaning Guide is an online tool that allows users to enhance images by overlaying cleaning instructions on them. The tool randomly selects phrases related to cleaning and positions them on the image alongside directional arrows that indicate specific areas or actions. This utility can be particularly useful for professionals in cleaning services, educators teaching cleanliness techniques, or anyone looking to provide visual instructions for cleaning tasks in photos or presentations.

Leave a Reply

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