I have set up Docker and implemented Node.js Canvas to render an image and font. It generates fine when running locally using Docker, but on AWS EC2, when running in Docker, the canvas image is being generated differently.
This is the code
export async function generateEmailSignature(id: string, folder: string, uploadKey: string, logoImagePath: string, qrImagePath: string, name: string) {
try {
registerFont('./src/common/open-sans-condensed/OpenSans-Light.ttf', { family: 'Open Sans Condensed', weight: 'light' });
registerFont('./src/common/open-sans-condensed/OpenSans-Bold.ttf', { family: 'Open Sans Condensed', weight: 'bold' });
const dpi = process.platform === 'darwin' ? 2 : 1; // Use a higher DPI for high-res displays
// The requested dimensions in pixels
const width = 544; // Width in pixels
const height = 237; // Height in pixels
// Create a canvas with the specified dimensions
const canvas = createCanvas(width * dpi, height * dpi);
const ctx = canvas.getContext('2d');
ctx.scale(dpi, dpi);
// Background color
ctx.fillStyle = '#FFFAFF'; // Light background color
ctx.fillRect(0, 0, width, height);
// QR image
const qrMinHeight = 200;
const qrMinWidth = 200;
// logo image
const logoMinHeight = 55;
const logoMinWidth = 55;
// Draw border
ctx.strokeStyle = '#092B4A'; // Blue border
ctx.lineWidth = 4;
ctx.strokeRect(2, 2, width - 4, height - 4);
// Add title text
const titleTextPositionX = 30;
const titleTextPositionY = 80;
// Set the font style for the "Click" part
ctx.font = 'bold 26pt "Open Sans Condensed"'; // Set font size and family
ctx.fillStyle = '#0000ff'; // Set text color to blue
// Draw "Click" with blue and underlined
ctx.fillText("Click", titleTextPositionX, titleTextPositionY);
// Draw the underline for "Click"
const textWidth = ctx.measureText("Click").width;
ctx.beginPath();
ctx.moveTo(titleTextPositionX, titleTextPositionY + 2); // Starting position of underline
ctx.lineTo(titleTextPositionX + textWidth, titleTextPositionY + 2); // Ending position of underline
ctx.strokeStyle = '#0000ff'; // Set underline color to blue
ctx.lineWidth = 2; // Set the underline thickness
ctx.stroke();
// Add "or Scan to" in bold
ctx.fillStyle = '#092B4A'; // Navy blue
ctx.font = 'bold 26pt "Open Sans Condensed"';
ctx.fillText('or Scan to', titleTextPositionX + textWidth + 10, titleTextPositionY);
const titleX = 68;
const titleY = 122;
ctx.fillStyle = '#092B4A';
ctx.font = 'bold 28pt "Open Sans Condensed"';
ctx.fillText('Helloo', titleX, titleY);
// Load and draw the logo
const logoPath = logoImagePath;
const logo = await loadImage(logoPath);
// logo position
const positionX = 26;
const positionY = 155;
ctx.drawImage(logo, positionX, positionY, logoMinWidth, logoMinHeight); // Position and resize logo
const produlySuppportedTextPositionX = 86;
const produlySuppportedTextPositionY = 180;
ctx.fillStyle = '#092B4A';
ctx.font = 'Light 12pt "Open Sans Condensed"';
ctx.fillText('by', produlySuppportedTextPositionX, produlySuppportedTextPositionY);
const nameTextPositionX = 86;
const nameTextPositionY = 200;
ctx.fillText(name, nameTextPositionX, nameTextPositionY);
// Generate a QR code
const qrCodePositionX = 315;
const qrCodePositionY = 23;
const qrCodeImage = await loadImage(qrImagePath);
ctx.drawImage(qrCodeImage, qrCodePositionX, qrCodePositionY, qrMinWidth, qrMinHeight); // Position and resize QR code
// Set the stroke color and line width
ctx.strokeStyle = '#092B4A'; // Blue color for the border
ctx.lineWidth = 8; // 4pt line width
// Draw the curved border around the QR code
ctx.beginPath();
const borderRadius = 5; // Radius for the curved corners
// Top-left corner
ctx.moveTo(qrCodePositionX + borderRadius, qrCodePositionY);
// Top side
ctx.arcTo(qrCodePositionX + qrMinWidth, qrCodePositionY, qrCodePositionX + qrMinWidth, qrCodePositionY + qrMinHeight, borderRadius);
// Right side
ctx.arcTo(qrCodePositionX + qrMinWidth, qrCodePositionY + qrMinHeight, qrCodePositionX, qrCodePositionY + qrMinHeight, borderRadius);
// Bottom side
ctx.arcTo(qrCodePositionX, qrCodePositionY + qrMinHeight, qrCodePositionX, qrCodePositionY, borderRadius);
// Left side (closing the loop)
ctx.arcTo(qrCodePositionX, qrCodePositionY, qrCodePositionX + qrMinWidth, qrCodePositionY, borderRadius);
// Complete the path and draw
ctx.closePath();
ctx.stroke();
// Add footer copyright text
// Set up the context for drawing
const copyrightTextPositionX = 532;
const copyrightTextPositionY = 222;
ctx.fillStyle = '#092B4A';
ctx.font = 'Light 7.5pt "Open Sans Condensed"';
// Rotate the context for vertical text
ctx.save(); // Save the current context state
ctx.translate(copyrightTextPositionX, copyrightTextPositionY); // Move the origin to where you want the vertical text
ctx.rotate(-Math.PI / 2); // Rotate the context 90 degrees counterclockwise
// Draw the copyright symbol
ctx.fillText('Copyright', 0, 0); // Draw at the new origin
ctx.restore(); // Restore the context to its original state
// Save the generated image
const fileName = `emailBanner.png`;
const filePath = `assets/emailBanner/${fileName}`;
const folderName = `assets/emailBanner`;
const buffer = canvas.toBuffer('image/png');
await fs.writeFile(fileName, buffer);
console.log('Email banner created');
return;
}
catch (err) {
console.log(err);
throw err;
}
}