File size: 5,603 Bytes
635195b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
// Original image storage
let originalCtxOriginal = document.createElement('canvas').getContext('2d');
let maskCtxOriginal = document.createElement('canvas').getContext('2d');
let isDrawing = false;
let brushSize = 5;
let eraserMode = false;
// Setup event listeners
document.getElementById('imageUpload').addEventListener('change', handleImageUpload);
document.getElementById('brushSize').addEventListener('change', (e) => brushSize = parseInt(e.target.value));
document.getElementById('eraserMode').addEventListener('change', (e) => eraserMode = e.target.checked);
canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stopDrawing);
canvas.addEventListener('mouseout', stopDrawing);
function handleImageUpload(e) {
let file = e.target.files[0];
let reader = new FileReader();
reader.onload = function(event) {
let img = new Image();
img.onload = function() {
// Store original image at full resolution
originalCtxOriginal.canvas.width = img.width;
originalCtxOriginal.canvas.height = img.height;
originalCtxOriginal.drawImage(img, 0, 0);
// Setup mask at original resolution
maskCtxOriginal.canvas.width = img.width;
maskCtxOriginal.canvas.height = img.height;
// Calculate display dimensions
const container = document.getElementById('canvasContainer');
const maxWidth = container.clientWidth;
const maxHeight = container.clientHeight;
let ratio = Math.min(maxWidth / img.width, maxHeight / img.height);
ratio = Math.min(ratio, 1); // Prevent upscaling
const scaledWidth = img.width * ratio;
const scaledHeight = img.height * ratio;
const offsetX = (maxWidth - scaledWidth) / 2;
const offsetY = (maxHeight - scaledHeight) / 2;
// Set display canvas dimensions
canvas.width = maxWidth;
canvas.height = maxHeight;
// Draw initial scaled image
ctx.drawImage(img, offsetX, offsetY, scaledWidth, scaledHeight);
// Store scaling parameters
window.scaleRatio = ratio;
window.offsetX = offsetX;
window.offsetY = offsetY;
};
img.src = event.target.result;
};
reader.readAsDataURL(file);
}
function startDrawing(e) {
isDrawing = true;
draw(e);
}
function stopDrawing() {
isDrawing = false;
ctx.beginPath();
}
function draw(e) {
if (!isDrawing || !window.scaleRatio) return;
const rect = canvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;
// Convert to original coordinates
const originalX = (mouseX - window.offsetX) / window.scaleRatio;
const originalY = (mouseY - window.offsetY) / window.scaleRatio;
const brushRadius = brushSize / window.scaleRatio;
if (eraserMode) {
// Erase from mask
maskCtxOriginal.clearRect(
originalX - brushRadius,
originalY - brushRadius,
brushRadius * 2,
brushRadius * 2
);
} else {
// Draw on mask
maskCtxOriginal.fillStyle = '#FFFFFF';
maskCtxOriginal.beginPath();
maskCtxOriginal.arc(
originalX,
originalY,
brushRadius,
0,
Math.PI * 2
);
maskCtxOriginal.fill();
}
// Redraw display canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(originalCtxOriginal.canvas,
0, 0, originalCtxOriginal.canvas.width, originalCtxOriginal.canvas.height,
window.offsetX, window.offsetY,
originalCtxOriginal.canvas.width * window.scaleRatio,
originalCtxOriginal.canvas.height * window.scaleRatio
);
// Overlay mask
ctx.globalAlpha = 0.5; // For visual feedback
ctx.drawImage(maskCtxOriginal.canvas,
0, 0, maskCtxOriginal.canvas.width, maskCtxOriginal.canvas.height,
window.offsetX, window.offsetY,
maskCtxOriginal.canvas.width * window.scaleRatio,
maskCtxOriginal.canvas.height * window.scaleRatio
);
ctx.globalAlpha = 1;
}
// Download button
document.getElementById('downloadBtn').addEventListener('click', () => {
const binaryCanvas = document.createElement('canvas');
binaryCanvas.width = originalCtxOriginal.canvas.width;
binaryCanvas.height = originalCtxOriginal.canvas.height;
const binaryCtx = binaryCanvas.getContext('2d');
// Create white background
binaryCtx.fillStyle = 'white';
binaryCtx.fillRect(0, 0, binaryCanvas.width, binaryCanvas.height);
// Get mask data
const maskData = maskCtxOriginal.getImageData(0, 0,
binaryCanvas.width, binaryCanvas.height);
// Draw black where mask exists
for (let i = 0; i < maskData.data.length; i += 4) {
if (maskData.data[i + 3] > 0) { // Check alpha channel
const x = (i / 4) % binaryCanvas.width;
const y = Math.floor((i / 4) / binaryCanvas.width);
binaryCtx.fillStyle = 'black';
binaryCtx.fillRect(x, y, 1, 1);
}
}
document.getElementById('downloadBtn').href = binaryCanvas.toDataURL('image/png');
}); |