Please bookmark this page to avoid losing your image tool!

Image Style Or Website Changer

(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.
/**
 * Applies various styles or frames an image in a browser mockup.
 * Interprets "Image Style or Website Changer" by providing two modes:
 * 1. "Style" Changer: Applies filters like grayscale, sepia, vintage, or maps image colors to a custom palette.
 * 2. "Website" Changer: Places the image inside a decorative, realistic browser window mockup.
 *
 * @param {Image} originalImg The original image object to process.
 * @param {string} [style='browser-mockup'] The style to apply. Can be 'browser-mockup', 'grayscale', 'sepia', 'invert', 'vintage', 'palette-map'.
 * @param {string} [option1] First option, its meaning depends on the selected style.
 *  - For 'browser-mockup': theme ('light' or 'dark'). Default: 'light'.
 *  - For 'palette-map': A comma-separated list of hex colors (e.g., '#ff0000,#00ff00,#0000ff'). Default: '#e63946,#f1faee,#a8dadc,#457b9d,#1d3557'.
 * @param {string} [option2] Second option, for 'browser-mockup' style only. The URL to display in the address bar. Default: 'https://example.com'.
 * @param {string} [option3] Third option, for 'browser-mockup' style only. This parameter is not used in the current implementation but is reserved for future features like a tab title.
 * @returns {HTMLCanvasElement} A canvas element containing the processed image.
 */
function processImage(originalImg, style = 'browser-mockup', option1, option2, option3) {
    const canvas = document.createElement('canvas');
    // Add willReadFrequently hint for performance in palette-map mode
    const ctx = canvas.getContext('2d', { willReadFrequently: style === 'palette-map' });

    // Helper to draw rounded rectangles, defined once for use in multiple cases.
    const roundRect = (x, y, w, h, r) => {
        if (w < 2 * r) r = w / 2;
        if (h < 2 * r) r = h / 2;
        ctx.beginPath();
        ctx.moveTo(x + r, y);
        ctx.arcTo(x + w, y, x + w, y + h, r);
        ctx.arcTo(x + w, y + h, x, y + h, r);
        ctx.arcTo(x, y + h, x, y, r);
        ctx.arcTo(x, y, x + w, y, r);
        ctx.closePath();
    };

    switch (style) {
        case 'browser-mockup': {
            const theme = option1 === undefined ? 'light' : option1;
            const url = option2 === undefined ? 'https://example.com' : option2;

            // --- Configuration ---
            const PADDING = 40;
            const HEADER_HEIGHT = 40;
            const BORDER_RADIUS = 10;
            const SHADOW_BLUR = 30;
            const SHADOW_OFFSET_Y = 10;
            const FONT_SIZE = 13;
            const FONT_FAMILY = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif';

            // --- Colors based on theme ---
            const colors = theme === 'dark' ? {
                header: '#3c3c3c',
                body: '#2e2e2e',
                urlBg: '#505050',
                text: '#e0e0e0',
                shadow: 'rgba(0, 0, 0, 0.6)',
            } : {
                header: '#e8e8e8',
                body: '#ffffff',
                urlBg: '#ffffff',
                text: '#444444',
                shadow: 'rgba(0, 0, 0, 0.2)',
            };
            const btnColors = { red: '#ff5f57', yellow: '#febc2e', green: '#28c840' };

            // --- Canvas and element dimensions ---
            const { naturalWidth: imgWidth, naturalHeight: imgHeight } = originalImg;
            const frameWidth = imgWidth;
            const frameHeight = imgHeight + HEADER_HEIGHT;

            canvas.width = frameWidth + PADDING * 2;
            canvas.height = frameHeight + PADDING * 2;

            const frameX = PADDING;
            const frameY = PADDING;

            // --- Drawing ---
            ctx.translate(0.5, 0.5); // For crisp lines

            // 1. Shadow
            ctx.shadowColor = colors.shadow;
            ctx.shadowBlur = SHADOW_BLUR;
            ctx.shadowOffsetY = SHADOW_OFFSET_Y;
            
            // 2. Main frame body (this provides the rounded corners)
            roundRect(frameX, frameY, frameWidth, frameHeight, BORDER_RADIUS);
            ctx.fillStyle = colors.body;
            ctx.fill();
            
            // Reset shadow for inner elements
            ctx.shadowColor = 'transparent';

            // 3. Header
            ctx.fillStyle = colors.header;
            ctx.beginPath();
            ctx.moveTo(frameX, frameY + HEADER_HEIGHT);
            ctx.lineTo(frameX, frameY + BORDER_RADIUS);
            ctx.arcTo(frameX, frameY, frameX + BORDER_RADIUS, frameY, BORDER_RADIUS);
            ctx.lineTo(frameX + frameWidth - BORDER_RADIUS, frameY);
            ctx.arcTo(frameX + frameWidth, frameY, frameX + frameWidth, frameY + BORDER_RADIUS, BORDER_RADIUS);
            ctx.lineTo(frameX + frameWidth, frameY + HEADER_HEIGHT);
            ctx.closePath();
            ctx.fill();

            // 4. Traffic light buttons
            const btnRadius = 6;
            const btnY = frameY + HEADER_HEIGHT / 2;
            ctx.fillStyle = btnColors.red;
            ctx.beginPath();
            ctx.arc(frameX + 20, btnY, btnRadius, 0, Math.PI * 2);
            ctx.fill();

            ctx.fillStyle = btnColors.yellow;
            ctx.beginPath();
            ctx.arc(frameX + 45, btnY, btnRadius, 0, Math.PI * 2);
            ctx.fill();

            ctx.fillStyle = btnColors.green;
            ctx.beginPath();
            ctx.arc(frameX + 70, btnY, btnRadius, 0, Math.PI * 2);
            ctx.fill();

            // 5. Address Bar
            const urlBarHeight = 24;
            const urlBarY = frameY + (HEADER_HEIGHT - urlBarHeight) / 2;
            const urlBarX = frameX + 95;
            const urlBarWidth = frameWidth - 110;
            ctx.fillStyle = colors.urlBg;
            roundRect(urlBarX, urlBarY, urlBarWidth, urlBarHeight, 6);
            ctx.fill();

            ctx.font = `400 ${FONT_SIZE}px ${FONT_FAMILY}`;
            ctx.fillStyle = colors.text;
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText(url, urlBarX + urlBarWidth / 2, urlBarY + urlBarHeight / 2 + 1, urlBarWidth - 20);

            // 6. Draw the image content
            ctx.drawImage(originalImg, frameX, frameY + HEADER_HEIGHT, imgWidth, imgHeight);
            break;
        }

        case 'palette-map': {
            const paletteStr = option1 === undefined ? '#e63946,#f1faee,#a8dadc,#457b9d,#1d3557' : option1;

            const hexToRgb = (hex) => {
                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;
            };

            const colorDistanceSq = (c1, c2) => Math.pow(c1.r - c2.r, 2) + Math.pow(c1.g - c2.g, 2) + Math.pow(c1.b - c2.b, 2);

            const palette = paletteStr.split(',').map(hex => hexToRgb(hex.trim())).filter(Boolean);

            canvas.width = originalImg.naturalWidth;
            canvas.height = originalImg.naturalHeight;
            ctx.drawImage(originalImg, 0, 0);

            if (palette.length === 0) break; // If palette is invalid, return original image.

            const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            const data = imageData.data;

            for (let i = 0; i < data.length; i += 4) {
                const pixelColor = { r: data[i], g: data[i + 1], b: data[i + 2] };
                let closestColor = palette[0];
                let minDistance = colorDistanceSq(pixelColor, closestColor);
                for (let j = 1; j < palette.length; j++) {
                    const distance = colorDistanceSq(pixelColor, palette[j]);
                    if (distance < minDistance) {
                        minDistance = distance;
                        closestColor = palette[j];
                    }
                }
                data[i] = closestColor.r;
                data[i + 1] = closestColor.g;
                data[i + 2] = closestColor.b;
            }
            ctx.putImageData(imageData, 0, 0);
            break;
        }

        case 'vintage':
        case 'grayscale':
        case 'sepia':
        case 'invert': {
            canvas.width = originalImg.naturalWidth;
            canvas.height = originalImg.naturalHeight;
            const filters = {
                grayscale: 'grayscale(1)',
                sepia: 'sepia(1)',
                invert: 'invert(1)',
                vintage: 'sepia(0.6) contrast(1.1) brightness(0.9) saturate(1.2)'
            };
            ctx.filter = filters[style];
            ctx.drawImage(originalImg, 0, 0);
            break;
        }

        default: {
            // Fallback for unknown style: return the original image on the canvas
            canvas.width = originalImg.naturalWidth;
            canvas.height = originalImg.naturalHeight;
            ctx.drawImage(originalImg, 0, 0);
            break;
        }
    }
    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 Style or Website Changer tool allows users to apply various styles to images or frame them within a realistic browser mockup. Users can choose from different effects such as grayscale, sepia, vintage, or color palette mapping to enhance images. Alternatively, images can be embedded in a decorative browser window, featuring customizable themes and a display URL. This tool is useful for creating visually appealing images for presentations, social media graphics, or website mockups.

Leave a Reply

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