Please bookmark this page to avoid losing your image tool!

Image Wanted Poster Generator

(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,
    headlineText = "WANTED",
    subText = "DEAD OR ALIVE",
    nameText = "UNKNOWN MISCREANT",
    rewardText = "$10,000 REWARD",
    mainFont = "Impact, Charcoal, sans-serif",
    secondaryFont = "'Courier New', Courier, monospace",
    textColor = "#3A2A1B",
    backgroundColor = "#F5E8C7",
    imageBorderColor = "#704214",
    posterBorderWidth = 20,
    posterBorderColor = "#5C3D2E",
    imageEffect = "sepia" // "none", "grayscale", "sepia"
) {

    const CANVAS_WIDTH = 600;
    const CANVAS_HEIGHT = 800;
    const INNER_PADDING = 20; // Padding inside the border for content elements

    const canvas = document.createElement('canvas');
    canvas.width = CANVAS_WIDTH;
    canvas.height = CANVAS_HEIGHT;
    const ctx = canvas.getContext('2d');

    // Helper function for text wrapping
    function _helper_drawWrappedText_internal(context, text, x, y, maxWidth, lineHeight, maxLines = 2) {
        let words = text.split(' ');
        let line = '';
        let currentY = y;
        let linesCount = 0;
        let totalHeight = 0;

        for(let i = 0; i < words.length; i++) {
            let testLine = line + words[i] + ' ';
            // futuros issues: measureText for very long strings or special chars might be slow.
            let metrics = context.measureText(testLine); 
            let testWidth = metrics.width;

            if (testWidth > maxWidth && i > 0) { 
                if (linesCount < maxLines) {
                    context.fillText(line.trim(), x, currentY);
                    currentY += lineHeight;
                    totalHeight += lineHeight;
                    linesCount++;
                    line = words[i] + ' '; 
                } else { 
                    return totalHeight; 
                }
            } else { 
                line = testLine;
            }
        }

        if (linesCount < maxLines && line.trim() !== '') {
            context.fillText(line.trim(), x, currentY);
            totalHeight += lineHeight;
            // linesCount++; // Not strictly needed here as we return totalHeight
        }
        return totalHeight; 
    }


    // 1. Draw Background Color
    ctx.fillStyle = backgroundColor;
    ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);

    // 2. Draw Poster Border
    if (posterBorderWidth > 0) {
        ctx.strokeStyle = posterBorderColor;
        ctx.lineWidth = posterBorderWidth;
        ctx.strokeRect(
            posterBorderWidth / 2,
            posterBorderWidth / 2,
            CANVAS_WIDTH - posterBorderWidth,
            CANVAS_HEIGHT - posterBorderWidth
        );
    }
    
    // Calculate effective Rcontent area boundaries
    const contentAreaX_Start = posterBorderWidth;
    const contentAreaY_Start = posterBorderWidth;
    const contentAreaWidth = CANVAS_WIDTH - 2 * posterBorderWidth;
    const contentAreaHeight = CANVAS_HEIGHT - 2 * posterBorderWidth;
    
    let currentY = contentAreaY_Start + INNER_PADDING;

    ctx.fillStyle = textColor;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'top';

    // 3. Headline Text ("WANTED")
    const HEADLINE_FONT_SIZE = Math.max(20, Math.min(80, contentAreaWidth / 7));
    ctx.font = `bold ${HEADLINE_FONT_SIZE}px ${mainFont}`;
    ctx.fillText(headlineText.toUpperCase(), CANVAS_WIDTH / 2, currentY);
    currentY += HEADLINE_FONT_SIZE + (HEADLINE_FONT_SIZE * 0.15); // Spacing

    // 4. Sub Text ("DEAD OR ALIVE")
    const SUBTEXT_FONT_SIZE = Math.max(14,Math.min(30, contentAreaWidth / 16));
    ctx.font = `${SUBTEXT_FONT_SIZE}px ${secondaryFont}`;
    ctx.fillText(subText.toUpperCase(), CANVAS_WIDTH / 2, currentY);
    currentY += SUBTEXT_FONT_SIZE + (SUBTEXT_FONT_SIZE * 0.5); // Spacing

    // 5. Image Processing & Drawing
    let imageToDraw = originalImg;
    const imgOriginalWidth = originalImg.naturalWidth || originalImg.width;
    const imgOriginalHeight = originalImg.naturalHeight || originalImg.height;

    if (imageEffect !== "none" && imgOriginalWidth > 0 && imgOriginalHeight > 0) {
        const tempCanvas = document.createElement('canvas');
        tempCanvas.width = imgOriginalWidth;
        tempCanvas.height = imgOriginalHeight;
        const tempCtx = tempCanvas.getContext('2d');
        tempCtx.drawImage(originalImg, 0, 0, imgOriginalWidth, imgOriginalHeight);
        const imageData = tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height);
        const data = imageData.data;

        if (imageEffect === "grayscale") {
            for (let i = 0; i < data.length; i += 4) {
                const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
                data[i] = data[i + 1] = data[i + 2] = avg;
            }
        } else if (imageEffect === "sepia") {
            for (let i = 0; i < data.length; i += 4) {
                const r = data[i], g = data[i + 1], b = data[i + 2];
                data[i]     = Math.min(255, (r * 0.393) + (g * 0.769) + (b * 0.189));
                data[i + 1] = Math.min(255, (r * 0.349) + (g * 0.686) + (b * 0.168));
                data[i + 2] = Math.min(255, (r * 0.272) + (g * 0.534) + (b * 0.131));
            }
        }
        tempCtx.putImageData(imageData, 0, 0);
        imageToDraw = tempCanvas;
    }
    
    // Calculate image display dimensions
    const MAX_NAME_LINES = 2;
    const NAME_FONT_SIZE = Math.max(16,Math.min(32, contentAreaWidth / 18));
    const NAME_LINE_HEIGHT_FACTOR = 1.2;
    const nameLineHeight = NAME_FONT_SIZE * NAME_LINE_HEIGHT_FACTOR;
    const spaceForNameText = nameLineHeight * MAX_NAME_LINES + (NAME_FONT_SIZE * 0.5); // Font size + spacing after

    const REWARD_FONT_SIZE = Math.max(18,Math.min(36, contentAreaWidth / 16));
    const spaceForRewardText = REWARD_FONT_SIZE + INNER_PADDING; // Font size + bottom padding

    const topSectionHeight = currentY - (contentAreaY_Start + INNER_PADDING);
    const availableHeightForImageAndLowerText = contentAreaHeight - INNER_PADDING - topSectionHeight - INNER_PADDING; // Top padding already used, Subtract bottom padding too
    
    const IMG_AREA_MAX_HEIGHT = Math.max(50, availableHeightForImageAndLowerText - spaceForNameText - spaceForRewardText);
    const IMG_AREA_MAX_WIDTH = contentAreaWidth - 2 * INNER_PADDING;

    let imgDrawWidth = imageToDraw.width;
    let imgDrawHeight = imageToDraw.height;

    if (imgDrawWidth <= 0 || imgDrawHeight <= 0) { // Handle case of invalid image (e.g. not loaded)
        imgDrawWidth = IMG_AREA_MAX_WIDTH;
        imgDrawHeight = IMG_AREA_MAX_HEIGHT / 2; // Default placeholder size
        ctx.fillStyle = '#CCCCCC';
        ctx.fillRect((CANVAS_WIDTH - imgDrawWidth) / 2, currentY, imgDrawWidth, imgDrawHeight);
        ctx.fillStyle = textColor; // Reset fillStyle
        ctx.fillText("Image Error", CANVAS_WIDTH / 2, currentY + imgDrawHeight/2 - 10);
    } else {
        const imgAspect = imgDrawWidth / imgDrawHeight;
        if (imgDrawWidth > IMG_AREA_MAX_WIDTH) {
            imgDrawWidth = IMG_AREA_MAX_WIDTH;
            imgDrawHeight = imgDrawWidth / imgAspect;
        }
        if (imgDrawHeight > IMG_AREA_MAX_HEIGHT) {
            imgDrawHeight = IMG_AREA_MAX_HEIGHT;
            imgDrawWidth = imgDrawHeight * imgAspect;
        }
        if (imgDrawWidth > IMG_AREA_MAX_WIDTH) { // Re-check width if height adjustment pushed it over
            imgDrawWidth = IMG_AREA_MAX_WIDTH;
            imgDrawHeight = imgDrawWidth / imgAspect;
        }
    }
    
    const imgDrawX = (CANVAS_WIDTH - imgDrawWidth) / 2;
    const imgDrawY = currentY;

    if (imgDrawWidth > 0 && imgDrawHeight > 0 && imageToDraw.width > 0 && imageToDraw.height > 0) { // Check again before drawing
       ctx.drawImage(imageToDraw, imgDrawX, imgDrawY, imgDrawWidth, imgDrawHeight);
    }

    // Image Border
    const IMG_BORDER_WIDTH = Math.max(2, Math.min(6, posterBorderWidth / 4));
    ctx.strokeStyle = imageBorderColor;
    ctx.lineWidth = IMG_BORDER_WIDTH;
    ctx.strokeRect(
        imgDrawX - IMG_BORDER_WIDTH / 2,
        imgDrawY - IMG_BORDER_WIDTH / 2,
        imgDrawWidth + IMG_BORDER_WIDTH,
        imgDrawHeight + IMG_BORDER_WIDTH
    );

    currentY += imgDrawHeight + (NAME_FONT_SIZE * 0.5); // Spacing after image

    // 6. Name Text
    ctx.font = `bold ${NAME_FONT_SIZE}px ${secondaryFont}`;
    const nameTextActualHeight = _helper_drawWrappedText_internal(
        ctx, nameText.toUpperCase(), CANVAS_WIDTH / 2, currentY,
        contentAreaWidth - 2 * INNER_PADDING, // Max width for name
        nameLineHeight, MAX_NAME_LINES
    );
    currentY += nameTextActualHeight + (REWARD_FONT_SIZE * 0.25); // Spacing

    // 7. Reward Text
    ctx.font = `bold ${REWARD_FONT_SIZE}px ${secondaryFont}`;
    // Adjust Y for reward text if currentY is too low, ensuring it's on canvas
    const rewardY = Math.min(currentY, CANVAS_HEIGHT - posterBorderWidth - INNER_PADDING - REWARD_FONT_SIZE);
    ctx.fillText(rewardText.toUpperCase(), CANVAS_WIDTH / 2, rewardY);

    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 Wanted Poster Generator is a fun tool that allows you to create customized wanted posters with your images. Users can upload a photo and add personalized text including a headline, subtext, name, and reward amount. The tool offers various design options like text font styles, colors, and effects such as sepia or grayscale for the image. This utility is useful for creating playful wanted posters for events, parties, or social media, and can be used for personal projects, art, or just for a bit of humorous creativity.

Leave a Reply

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

Other Image Tools:

Image To ASCII Art Converter

Image To The Pink Panther Show Episode Details Finder

Image To Pink Panther Show Episode Details Finder

Image To Big Hero 6 The Series 2017-2021 Show Details Finder

Image To Illumination Entertainment Movie Details Finder

Image To Walt Disney Animation Studios Movie Details Finder

Image To THX Logo History 1983-2023 Search Tool

Image To Thx 1983-2023 Search Tool

20th Century Fox 1935-2020 Variants Image Viewer

Image To Detailed Audio Description Generator

Detailed Dreamworks Image Variant Generator

Image To The Pink Panther Show Episode 1-124 Search Tool

Image To Tubi September 2026 Coming Soon Movie Search Tool

Image To Tubi Sep 2026 Movie Search Tool

Image To Dottie Chicken Movie Search Tool

Image To Gahlina Pintadinha Movie Search Tool

Image and Video Big Hero 6 The Series Search Tool

Image To Illumination Entertainment Movie Search Tool

Image Soft Bubble Overlay Adder

Image Aspect Ratio 20:9 Stretch Tool

Image To Music Search Finder

Image To Movie Details Finder

Image To Walt Disney Animation Studios Movie Search Tool

Beauty and the Beast Special Extended Edition 1991 Movie Info Tool

Image Information Extractor for Movie Details

Stretch Image To 9:16 Aspect Ratio

Image Aspect Ratio 2.55:1 Resizer

Image To 20:9 Aspect Ratio Converter

Big Hero 6 2014 Wonder Project Amazon Channel Video Image Tool

Android Ringtone MP3 Photo Player

Image To Low Voice Converter

Image Metadata Extractor for Big Hero 6 Video File

No description provided for an image utility tool

Image Information Extractor for Big Hero 6 Video Metadata

No descriptive tool purpose provided in the input

See All →