Please bookmark this page to avoid losing your image tool!

Image Archaeological Discovery Document 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.
async function processImage(
    originalImg,
    documentTitle = "ARCHAEOLOGICAL FIND RECORD",
    artifactId = "AD-001-XYZ",
    objectName = "Ancient Artifact",
    discoveryDate = "January 1, 2024",
    discoverySite = "Uncharted Territory",
    estimatedAge = "Approx. 2000 Years",
    researcherName = "Dr. E. L. Cortex",
    description = "A remarkable discovery indicating advanced craftsmanship for its era. Further analysis pending examination by experts in the relevant historical and material sciences departments.",
    bgColor = "#f5e8c7", // Parchment like
    textColor = "#3a2e0b", // Dark brown
    accentColor = "#5a4510" // Slightly darker brown for accents
) {

    const titleFontName = "IM Fell English SC";
    const bodyFontName = "IM Fell English";

    const loadFont = async (fontFamily, fontUrl) => {
        try {
            if (document.fonts && typeof document.fonts.check === 'function' && document.fonts.check(`12px "${fontFamily}"`)) {
                return true; // Already loaded or available
            }
            const fontFace = new FontFace(fontFamily, `url(${fontUrl})`);
            await fontFace.load();
            document.fonts.add(fontFace);
            return true;
        } catch (e) {
            console.error(`Failed to load font ${fontFamily}:`, e);
            return false;
        }
    };

    await Promise.all([
        loadFont(titleFontName, "https://fonts.gstatic.com/s/imfellenglishsc/v16/yVT0H4Vd0mBDA2rhohP3428a0cR8KLIg047K.woff2"),
        loadFont(bodyFontName, "https://fonts.gstatic.com/s/imfellenglish/v16/Ktk1ALSLW8zR2viiObOffY220jYJ2oIA4Q.woff2")
    ]);

    const isFontAvailable = (fontName) => {
        if (!document.fonts || typeof document.fonts.check !== 'function') return false;
        return document.fonts.check(`12px "${fontName}"`);
    };

    const fallbackTitleFontFamily = `"Times New Roman", serif`;
    const fallbackBodyFontFamily = `"Times New Roman", serif`;

    const titleActualFontFamily = isFontAvailable(titleFontName) ? `"${titleFontName}"` : fallbackTitleFontFamily;
    const bodyActualFontFamily = isFontAvailable(bodyFontName) ? `"${bodyFontName}"` : fallbackBodyFontFamily;

    const titleFontSize = 36;
    const smallFontSize = 16;
    const lineSpacingFactor = 1.4;

    const fontStyles = {
        title: `bold ${titleFontSize}px ${titleActualFontFamily}`,
        small: `${smallFontSize}px ${bodyActualFontFamily}`,
        smallBold: `bold ${smallFontSize}px ${bodyActualFontFamily}`
    };

    const tempCanvas = document.createElement('canvas');
    const ctx = tempCanvas.getContext('2d');
    
    const fixedWidth = 800;
    const padding = 40;
    const contentWidth = fixedWidth - 2 * padding;
    
    ctx.textBaseline = 'top';

    const drawTextLine = (text, x, y, font, color, align = 'left', maxWidth = contentWidth) => {
        ctx.font = font;
        ctx.fillStyle = color;
        ctx.textAlign = align;
        let textX = x;
        if (align === 'center') {
            textX = fixedWidth / 2;
        } else if (align === 'right') {
            textX = fixedWidth - padding;
        }
        ctx.fillText(text, textX, y, maxWidth);
        const fontSize = parseInt(font.match(/(\d+)px/)[1], 10);
        return y + fontSize * lineSpacingFactor;
    };

    const wrapTextAndDraw = (text, x, y, maxWidth, font, color) => {
        ctx.font = font;
        ctx.fillStyle = color;
        ctx.textAlign = 'left';
        
        const words = text.split(' ');
        let line = '';
        let currentTextY = y;
        const fontSize = parseInt(font.match(/(\d+)px/)[1], 10);
        const lineHeight = fontSize * lineSpacingFactor;

        for (let n = 0; n < words.length; n++) {
            const testLine = line + words[n] + ' ';
            const metrics = ctx.measureText(testLine);
            const testWidth = metrics.width;
            if (testWidth > maxWidth && line.length > 0) { // Ensure line is not empty before breaking
                ctx.fillText(line.trim(), x, currentTextY);
                line = words[n] + ' ';
                currentTextY += lineHeight;
            } else {
                line = testLine;
            }
        }
        if (line.trim().length > 0) {
            ctx.fillText(line.trim(), x, currentTextY);
        }
        return currentTextY + lineHeight;
    };

    const getValueTextLines = (text, maxWidth, font, contextForMeasure) => {
        const words = text.split(' ');
        const lines = [];
        let currentLine = '';
        contextForMeasure.font = font;

        if (maxWidth <= 0) return [text.trim()];
        
        for (let i = 0; i < words.length; i++) {
            let word = words[i];
            let testLine = currentLine + word + ' ';
            if (contextForMeasure.measureText(testLine).width > maxWidth && currentLine.length > 0) {
                lines.push(currentLine.trim());
                currentLine = word + ' ';
            } else {
                currentLine = testLine;
            }
        }
        if (currentLine.trim().length > 0) {
            lines.push(currentLine.trim());
        }
        return lines.length > 0 ? lines : (text.trim() ? [text.trim()] : []); // if text was empty, return empty array
    };

    const maxImgHeight = 350;
    const imgAspectRatio = (originalImg.height > 0 && originalImg.width > 0) ? (originalImg.width / originalImg.height) : 1;
    let imgDisplayWidth = Math.min(originalImg.width > 0 ? originalImg.width : (contentWidth * 0.55) , contentWidth * 0.55);
    let imgDisplayHeight = imgDisplayWidth / imgAspectRatio;

    if (imgDisplayHeight > maxImgHeight) {
        imgDisplayHeight = maxImgHeight;
        imgDisplayWidth = imgDisplayHeight * imgAspectRatio;
    }
     if (imgDisplayWidth <= 0 || !isFinite(imgDisplayWidth)) {
        imgDisplayWidth = contentWidth * 0.55;
    }
    if (imgDisplayHeight <= 0 || !isFinite(imgDisplayHeight)) {
        imgDisplayHeight = maxImgHeight / 1.5;
    }


    tempCanvas.width = fixedWidth;
    tempCanvas.height = 3000; // Temp large height
    ctx.textBaseline = 'top'; 
    ctx.fillStyle = bgColor; // This needs to be on finalCtx later
    ctx.fillRect(0, 0, tempCanvas.width, tempCanvas.height); // Effectively clears temp

    let currentY = padding;

    currentY = drawTextLine(documentTitle, 0, currentY, fontStyles.title, textColor, 'center');
    currentY += 10;

    const artifactIdLineY = currentY;
    ctx.font = fontStyles.small; 
    ctx.fillStyle = textColor; 
    ctx.textAlign = 'left';
    ctx.fillText(`Artifact ID: ${artifactId}`, padding, artifactIdLineY);
    ctx.textAlign = 'right';
    ctx.fillText(`Date: ${discoveryDate}`, fixedWidth - padding, artifactIdLineY);
    currentY += smallFontSize * lineSpacingFactor + 15;

    ctx.strokeStyle = accentColor;
    ctx.lineWidth = 1;
    ctx.beginPath();
    ctx.moveTo(padding, currentY);
    ctx.lineTo(fixedWidth - padding, currentY);
    ctx.stroke();
    currentY += 20;

    const imgSectionStartY = currentY;
    const imgMargin = 20;
    const imgBorder = 5;

    ctx.fillStyle = "#ccc";
    ctx.fillRect(padding - imgBorder, currentY - imgBorder, imgDisplayWidth + 2 * imgBorder, imgDisplayHeight + 2 * imgBorder);
    ctx.fillStyle = "#fff";
    ctx.fillRect(padding, currentY, imgDisplayWidth, imgDisplayHeight);
    if (originalImg.width > 0 && originalImg.height > 0) {
      ctx.drawImage(originalImg, padding, currentY, imgDisplayWidth, imgDisplayHeight);
    } else {
      ctx.font = fontStyles.small;
      ctx.fillStyle = textColor;
      ctx.textAlign = "center";
      ctx.fillText("[Image Unavailable]", padding + imgDisplayWidth/2, currentY + imgDisplayHeight/2 - smallFontSize/2);
    }
    
    const imageBottomY = currentY + imgDisplayHeight;

    let metadataCurrentY = imgSectionStartY;
    const metadataStartX = padding + imgDisplayWidth + imgMargin;
    const metadataBlockAvailableWidth = fixedWidth - padding - metadataStartX;

    const drawMetadataItem = (label, value) => {
        ctx.textAlign = 'left';
        ctx.font = fontStyles.smallBold;
        ctx.fillStyle = textColor;
        ctx.fillText(label, metadataStartX, metadataCurrentY);
        
        const labelWidth = ctx.measureText(label + " ").width;
        
        const valueLines = getValueTextLines(value, metadataBlockAvailableWidth - labelWidth, fontStyles.small, ctx);
        let lineYOffset = 0;
        const valueLineHeight = smallFontSize * lineSpacingFactor;

        ctx.font = fontStyles.small; // Set font for value rendering
        for(const line of valueLines) {
            ctx.fillText(line, metadataStartX + labelWidth, metadataCurrentY + lineYOffset);
            lineYOffset += valueLineHeight;
        }
        metadataCurrentY += (lineYOffset > 0 ? lineYOffset : valueLineHeight);
        metadataCurrentY += 5; 
    };
    
    if (metadataBlockAvailableWidth > 20) {
        drawMetadataItem("Object Name:", objectName);
        drawMetadataItem("Est. Age:", estimatedAge);
        drawMetadataItem("Site:", discoverySite);
        drawMetadataItem("Researcher:", researcherName);
    }
    
    currentY = Math.max(imageBottomY, metadataCurrentY) + 20;

    currentY = drawTextLine("Description:", padding, currentY, fontStyles.smallBold, textColor, 'left');
    currentY += 5; 

    currentY = wrapTextAndDraw(description, padding, currentY, contentWidth, fontStyles.small, textColor);
    
    const finalHeight = currentY + padding;

    const finalCanvas = document.createElement('canvas');
    finalCanvas.width = fixedWidth;
    finalCanvas.height = finalHeight;
    const finalCtx = finalCanvas.getContext('2d');
    finalCtx.textBaseline = 'top';

    finalCtx.fillStyle = bgColor;
    finalCtx.fillRect(0, 0, finalCanvas.width, finalCanvas.height);

    const noiseDensityFactor = 70;
    const numNoiseParticles = Math.floor((finalCanvas.width * finalCanvas.height / (800*600)) * noiseDensityFactor * 100);
    for (let i = 0; i < numNoiseParticles; i++) {
        const x = Math.random() * finalCanvas.width;
        const y = Math.random() * finalCanvas.height;
        const alpha = Math.random() * 0.03 + 0.02; 
        const shade = Math.random() > 0.5 ? 20 : 40; 
        finalCtx.fillStyle = `rgba(${shade},${shade},${shade},${alpha})`; // Darker noise for parchment
        finalCtx.fillRect(x, y, 1, 1);
    }
    
    finalCtx.drawImage(tempCanvas, 0, 0, fixedWidth, finalHeight, 0, 0, fixedWidth, finalHeight);
    
    return finalCanvas;
}

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 Archaeological Discovery Document Creator is a specialized online tool designed to generate visually appealing documents that capture archaeological finds. It allows users to create detailed records of artifacts by incorporating essential information such as artifact ID, object name, discovery date, site, estimated age, researcher’s name, and a descriptive overview. The output document adopts a parchment-style aesthetic to enhance the presentation of the archaeological data, making it suitable for researchers, educators, and enthusiasts in the fields of archaeology and history. This tool is ideal for creating documentation for academic reports, exhibit displays, or educational materials, ensuring that discoveries are well-documented in a professional manner.

Leave a Reply

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