You can edit the below JavaScript code to customize the image tool.
function processImage(
originalImg,
padding = 10,
mainBorderWidth = 30,
goldLineWidth = 3,
parchmentColor = '#FAF0E6', // A light, parchment-like color (Linen)
mainBorderColor = '#800020', // A deep, rich color (Burgundy)
goldColor = '#DAA520' // A color resembling gold (Goldenrod)
) {
// Ensure numeric parameters are actual numbers and have valid fallback values
padding = Number(padding);
mainBorderWidth = Number(mainBorderWidth);
goldLineWidth = Number(goldLineWidth);
// Validate numeric parameters to ensure they are sensible
if (isNaN(padding) || padding < 0) padding = 10;
if (isNaN(mainBorderWidth) || mainBorderWidth <= 0) mainBorderWidth = 30; // Must be positive
if (isNaN(goldLineWidth) || goldLineWidth <= 0) goldLineWidth = 3; // Must be positive
// Factor to determine the size of corner decorations relative to the main border width
const cornerDecorationSizeFactor = 0.7;
// Calculate the total offset from the canvas edge to where the actual image content is drawn.
// This offset includes all border elements (outer gold line, main border, inner gold line) and padding.
const imageActualStartOffset = goldLineWidth + // Space for the outer gold line
mainBorderWidth + // Space for the main colored border
goldLineWidth + // Space for the inner gold line
padding; // Space for padding around the image
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Set canvas dimensions to accommodate the original image and the full frame structure
canvas.width = originalImg.width + 2 * imageActualStartOffset;
canvas.height = originalImg.height + 2 * imageActualStartOffset;
// Initialize drawing coordinates for the outermost layer (the entire canvas)
let currentX = 0;
let currentY = 0;
let currentW = canvas.width;
let currentH = canvas.height;
// Layer 1: Fill the entire canvas with the parchment color. This serves as the base background.
ctx.fillStyle = parchmentColor;
ctx.fillRect(currentX, currentY, currentW, currentH);
// Layer 2: Draw the Outer Gold Stroke. This is a thin gold line at the very edge of the canvas.
ctx.strokeStyle = goldColor;
ctx.lineWidth = goldLineWidth;
// For strokeRect, the path (x,y,w,h) is stroked with the line centered on this path.
// To ensure the stroke lies entirely within the current rectangle (currentX, currentY, currentW, currentH),
// we inset the path by half the lineWidth.
ctx.strokeRect(
currentX + goldLineWidth / 2,
currentY + goldLineWidth / 2,
currentW - goldLineWidth,
currentH - goldLineWidth
);
// Shrink the current drawing rectangle for the next layer, moving inwards past the outer gold line.
currentX += goldLineWidth;
currentY += goldLineWidth;
currentW -= 2 * goldLineWidth;
currentH -= 2 * goldLineWidth;
// Layer 3: Fill the Main Border Area with the main border color.
ctx.fillStyle = mainBorderColor;
ctx.fillRect(currentX, currentY, currentW, currentH);
// Store the coordinates of this main border area, as corner decorations will be placed here.
const mainBorderAreaX = currentX; // X-coordinate of the main border's top-left corner
const mainBorderAreaY = currentY; // Y-coordinate of the main border's top-left corner
// Shrink the current drawing rectangle for the next layer, moving inwards past the main border.
currentX += mainBorderWidth;
currentY += mainBorderWidth;
currentW -= 2 * mainBorderWidth;
currentH -= 2 * mainBorderWidth;
// Layer 4: Fill the Central Area with parchment color again.
// This area will eventually contain the inner gold line, padding, and the image itself.
// This fill effectively "carves out" the main border from Layer 3's fill, leaving a colored band.
ctx.fillStyle = parchmentColor;
ctx.fillRect(currentX, currentY, currentW, currentH);
// Layer 5: Draw the Inner Gold Stroke. This line borders the central parchment area.
ctx.strokeStyle = goldColor;
ctx.lineWidth = goldLineWidth;
ctx.strokeRect(
currentX + goldLineWidth / 2,
currentY + goldLineWidth / 2,
currentW - goldLineWidth,
currentH - goldLineWidth
);
// Shrink the current drawing rectangle for the next layer, moving inwards past the inner gold line.
currentX += goldLineWidth;
currentY += goldLineWidth;
// currentW and currentH now represent the dimensions of the area designated for padding on each side.
// Layer 6: Draw the Original Image.
// (currentX, currentY) now marks the top-left of the padding area.
// The image is drawn inset by `padding` within this area.
ctx.drawImage(originalImg, currentX + padding, currentY + padding, originalImg.width, originalImg.height);
// Layer 7: Add Corner Embellishments onto the Main Border Area (created in Layer 3).
const cornerDecorationSize = mainBorderWidth * cornerDecorationSizeFactor;
function drawCornerElement(centerX, centerY, rotation = 0) {
ctx.save(); // Save the current canvas state (transformations, styles)
ctx.translate(centerX, centerY); // Move the origin to the center of the decoration
ctx.rotate(rotation); // Rotate the decoration
ctx.beginPath();
ctx.fillStyle = goldColor; // Decorations are typically gold or a contrasting color
const s = cornerDecorationSize / 2; // 's' is half the size of the decoration, simplifying point calculations
// Define a simple, symmetrical 4-point shape (like a stylized petal, star, or cross)
ctx.moveTo(0, -s); // Top point of the shape
ctx.quadraticCurveTo(s * 0.6, -s * 0.6, s, 0); // Control point towards right point, then right point
ctx.quadraticCurveTo(s * 0.6, s * 0.6, 0, s); // Control point towards bottom point, then bottom point
ctx.quadraticCurveTo(-s * 0.6, s * 0.6, -s, 0); // Control point towards left point, then left point
ctx.quadraticCurveTo(-s * 0.6, -s * 0.6, 0, -s); // Control point towards top point, completing the shape
ctx.closePath();
ctx.fill(); // Fill the shape
ctx.restore(); // Restore the canvas state
}
// Calculate the center points for the corner decorations.
// These decorations should be centered within the main border band.
// The main border band's top-left corner is at (mainBorderAreaX, mainBorderAreaY).
// The width of this band is `mainBorderWidth`.
// So, the center of the band (offset from its edge) is `mainBorderWidth / 2`.
const decorationCenterOffsetWithinBand = mainBorderWidth / 2;
const decorationCenterX = mainBorderAreaX + decorationCenterOffsetWithinBand;
const decorationCenterY = mainBorderAreaY + decorationCenterOffsetWithinBand;
// Place decorations in each of the four corners, with appropriate rotations
// Top-left corner decoration
drawCornerElement(decorationCenterX, decorationCenterY, Math.PI / 4); // Rotated 45 degrees
// Top-right corner decoration
drawCornerElement(canvas.width - decorationCenterX, decorationCenterY, -Math.PI / 4); // Rotated -45 degrees
// Bottom-left corner decoration
drawCornerElement(decorationCenterX, canvas.height - decorationCenterY, (3 * Math.PI) / 4); // Rotated 135 degrees
// Bottom-right corner decoration
drawCornerElement(canvas.width - decorationCenterX, canvas.height - decorationCenterY, (-3 * Math.PI) / 4); // Rotated -135 degrees
return canvas;
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
The Image Medieval Manuscript Frame Creator is an online tool designed to enhance your images by framing them with a decorative medieval-style border. Users can upload an image and customize various aspects of the frame, including padding, border widths, and colors reminiscent of traditional manuscripts. This tool is ideal for creating visually appealing graphics for artistic projects, invitations, poetry presentations, or digital storytelling, where a historical or elegant aesthetic is desired.