Please bookmark this page to avoid losing your image tool!

Image Steampunk Invention Blueprint Creator

(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,
    bgColor = "#283593", // Indigo-like blue for background
    lineColor = "#E1F5FE", // Light Cyan for lines
    lineThreshold = 80, // 0-255; defines how dark original part (after inversion) becomes a line
    enableGrid = "true",
    gridSpacing = 30, // Pixels
    gridColor = "rgba(176,190,197,0.2)", // Faint Blue Grey for grid
    enableBorder = "true",
    borderWidth = 5, // Pixels for border stroke
    borderColor = "#B0BEC5", // Blue Grey for border lines
    borderTextColor = "#CFD8DC", // Lighter Blue Grey for text in border
    enableVignette = "true",
    vignetteIntensity = 0.6 // 0-1; controls darkness of vignette edges
) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    const width = originalImg.naturalWidth || originalImg.width;
    const height = originalImg.naturalHeight || originalImg.height;
    canvas.width = width;
    canvas.height = height;

    // Parse string "true"/"false" to boolean
    const E_GRID = String(enableGrid).toLowerCase() === "true";
    const E_BORDER = String(enableBorder).toLowerCase() === "true";
    const E_VIGNETTE = String(enableVignette).toLowerCase() === "true";

    // Convert numeric parameters from string if necessary, or use as number
    const numLineThreshold = parseFloat(lineThreshold);
    const numGridSpacing = parseFloat(gridSpacing);
    const numBorderWidth = parseFloat(borderWidth);
    const numVignetteIntensity = parseFloat(vignetteIntensity);

    // 1. Fill Background Color
    ctx.fillStyle = bgColor;
    ctx.fillRect(0, 0, width, height);

    // 2. Draw Grid Lines (if enabled)
    if (E_GRID && numGridSpacing > 0) {
        ctx.strokeStyle = gridColor;
        ctx.lineWidth = 1; // Grid lines are thin
        for (let x = numGridSpacing; x < width; x += numGridSpacing) {
            ctx.beginPath();
            ctx.moveTo(x + 0.5, 0); // +0.5 for sharper lines
            ctx.lineTo(x + 0.5, height);
            ctx.stroke();
        }
        for (let y = numGridSpacing; y < height; y += numGridSpacing) {
            ctx.beginPath();
            ctx.moveTo(0, y + 0.5);
            ctx.lineTo(width, y + 0.5);
            ctx.stroke();
        }
    }

    // 3. Draw Processed Image Lines
    // Use a temporary canvas to draw the original image and access its pixel data
    const tempCanvas = document.createElement('canvas');
    tempCanvas.width = width;
    tempCanvas.height = height;
    const tempCtx = tempCanvas.getContext('2d', { willReadFrequently: true }); // Important for getImageData performance
    tempCtx.drawImage(originalImg, 0, 0, width, height);
    const imgData = tempCtx.getImageData(0, 0, width, height);
    const pixels = imgData.data;

    ctx.fillStyle = lineColor; // Set fill style for the blueprint lines

    for (let i = 0; i < pixels.length; i += 4) {
        const r = pixels[i];
        const g = pixels[i + 1];
        const b = pixels[i + 2];
        const a = pixels[i + 3];

        if (a < 128) { // Skip transparent or mostly transparent pixels from original
            continue;
        }

        // Convert pixel to grayscale
        const gray = 0.299 * r + 0.587 * g + 0.114 * b;
        // Invert grayscale (darker original parts become lighter in inverted scale)
        const invertedGray = 255 - gray;

        // If inverted gray value is above threshold, draw it as part of the "line"
        if (invertedGray > numLineThreshold) {
            const x = (i / 4) % width;
            const y = Math.floor((i / 4) / width);
            ctx.fillRect(x, y, 1, 1); // Draw a 1x1 pixel for the line
        }
    }
    
    // 4. Draw Border and Title Block (if enabled)
    if (E_BORDER && numBorderWidth > 0) {
        ctx.strokeStyle = borderColor;
        ctx.lineWidth = numBorderWidth;
        const bwHalf = numBorderWidth / 2;

        // Outer border rectangle
        ctx.strokeRect(bwHalf, bwHalf, width - numBorderWidth, height - numBorderWidth);

        // Simple title block area at the bottom
        const titleBlockHeight = Math.min(80, Math.max(40, height * 0.15)); // Responsive height
        const titleBlockY = height - titleBlockHeight - bwHalf;
        
        // Draw dividing line for title block from main content
        ctx.beginPath();
        ctx.moveTo(bwHalf, titleBlockY);
        ctx.lineTo(width - bwHalf, titleBlockY);
        ctx.stroke();

        // Placeholder text for Title Block
        ctx.fillStyle = borderTextColor;
        
        let fontSize = Math.floor(titleBlockHeight * 0.22); // Base font size on block height
        fontSize = Math.min(fontSize, Math.floor(width / 20)); // Limit by width also
        fontSize = Math.max(8, Math.min(18, fontSize)); // Clamp font size (8px to 18px)


        ctx.font = `bold ${fontSize}px 'Courier New', monospace`;
        ctx.textBaseline = "middle";
        
        const textVPadding = titleBlockHeight * 0.33; // Vertical padding for text lines
        const textHPadding = numBorderWidth + fontSize * 0.8; // Horizontal padding from border edge

        const randomId = "ID-" + Math.floor(Math.random() * 8999 + 1000);
        const randomRev = String.fromCharCode(65 + Math.floor(Math.random() * 5)); // Revision A-E

        ctx.textAlign = "left";
        ctx.fillText(randomId, textHPadding, titleBlockY + textVPadding);
        ctx.fillText("TYPE: SCHEMATIC", textHPadding, titleBlockY + titleBlockHeight - textVPadding);

        ctx.textAlign = "right";
        const currentDate = new Date();
        const dateString = `${currentDate.getFullYear()}-${String(currentDate.getMonth() + 1).padStart(2, '0')}-${String(currentDate.getDate()).padStart(2, '0')}`;
        ctx.fillText(`REV: ${randomRev}`, width - textHPadding, titleBlockY + textVPadding);
        ctx.fillText(`DATE: ${dateString}`, width - textHPadding, titleBlockY + titleBlockHeight - textVPadding);
    }

    // 5. Draw Vignette (if enabled)
    if (E_VIGNETTE && numVignetteIntensity > 0) {
        const vigIntensity = Math.min(1, Math.max(0, numVignetteIntensity)); // Clamp 0-1
        const centerX = width / 2;
        const centerY = height / 2;
        const outerRadius = Math.sqrt(Math.pow(centerX, 2) + Math.pow(centerY, 2));
        
        // Vignette starts fading further from the center if intensity is lower
        const innerRadiusRatio = Math.max(0.1, 1 - vigIntensity); 
        const innerRadius = outerRadius * innerRadiusRatio;

        const gradient = ctx.createRadialGradient(
            centerX, centerY, innerRadius,
            centerX, centerY, outerRadius
        );
        gradient.addColorStop(0, "rgba(0,0,0,0)"); // Center is transparent
        gradient.addColorStop(1, `rgba(0,0,0,${vigIntensity})`); // Edge is dark
        
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, width, height);
    }

    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 Steampunk Invention Blueprint Creator is a versatile online tool designed to transform standard images into stylized blueprint designs. It allows users to upload an image and apply customizable features such as a unique background color, grid lines, and title blocks. The tool is ideal for artists, designers, and engineers looking to create schematic-like illustrations or presentations of concepts and inventions. Users can also add a touch of realism with vignette effects and customize border styles, making it suitable for professional and creative projects alike.

Leave a Reply

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