Skip to content

Commit

Permalink
Merge pull request #461 from SitaGanesh/458-coloring-functionality
Browse files Browse the repository at this point in the history
Added coloring functionality
  • Loading branch information
bislara authored Jan 17, 2025
2 parents 1f8ac15 + 759e89a commit 859a192
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 1 deletion.
3 changes: 3 additions & 0 deletions JavaScript/Mini Paint/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mini-paint folder with HTML, CSS, and JS files. which creates a webpage having t
- **Color Selection**: Choose your preferred drawing color.
- **Brush Size**: Adjust the size of the brush for detailed or broad strokes.
- **Eraser Tool**: Erase parts of your drawing with ease.
- **Fill Color**: Use the fill tool to color a specific area by clicking on it.
- **Clear Board**: Reset the entire canvas to start a new drawing.
- **Download Artwork**: Save your creation as a PNG or JPG image file.

Expand All @@ -16,9 +17,11 @@ mini-paint folder with HTML, CSS, and JS files. which creates a webpage having t
2. Use the provided tools to create your artwork:
- Select a color and brush size for drawing.
- Use the eraser tool to remove unwanted parts.
- Use the fill tool to color specific areas.
- Clear the board to start afresh.
- Save your artwork by downloading it as a PNG or JPG file.

![Paint Application Screenshot](output.jpg "Mini Paint Screenshot")
![Paint Application Screenshot](output2.jpg "Mini Paint Screenshot 2")

Enjoy painting with Mini Paint!
1 change: 1 addition & 0 deletions JavaScript/Mini Paint/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<input type="color" id="color-picker" title="Choose Color">
<input type="range" id="brush-size" min="1" max="50" value="5" title="Brush Size">
<button id="eraser">Eraser</button>
<button id="fill-color">Color</button>
<button id="clear-board">Clear Board</button>
<button id="download-png">Download PNG</button>
<button id="download-jpg">Download JPG</button>
Expand Down
Binary file added JavaScript/Mini Paint/output2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
87 changes: 86 additions & 1 deletion JavaScript/Mini Paint/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ let painting = false;
let currentColor = '#000000';
let brushSize = 5;
let isEraser = false;
//fill mode toggler
let isFillMode=false;

// Start drawing
function startDrawing(e) {
Expand All @@ -23,7 +25,7 @@ function stopDrawing() {

// Draw on the canvas
function draw(e) {
if (!painting) return;
if (!painting || isFillMode) return;//prevent drawing when fill mode is on

ctx.lineWidth = brushSize;
ctx.lineCap = 'round';
Expand Down Expand Up @@ -55,6 +57,7 @@ document.getElementById('brush-size').addEventListener('input', (e) => {
// Toggle eraser
document.getElementById('eraser').addEventListener('click', () => {
isEraser = true;
isFillMode=false;//reset fill mode
canvas.style.cursor = 'not-allowed';
});

Expand All @@ -70,9 +73,91 @@ toolbar.insertBefore(pencil, firstButton);

document.getElementById('pencil').addEventListener('click', () => {
isEraser = false;
isFillMode=false;//reset fill mode
canvas.style.cursor = 'crosshair';
})

//Fill color feature
const fillButton = document.getElementById('fill-color');
fillButton.addEventListener('click',()=>{
isFillMode=true;
isEraser=false;//reset eraser
canvas.style.cursor='pointer';
})

//fill color applies, when clicked on canvas
canvas.addEventListener('click',(e)=>{
if(isFillMode){
fillColor(e);
}
})


// Flood Fill logic
function fillColor(e) {
const x = e.clientX - canvas.offsetLeft;
const y = e.clientY - canvas.offsetTop;

const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const targetColor = getPixelColor(imageData, x, y);
const fillColor = hexToRgb(currentColor);

// Only perform flood fill if the color is different
if (!colorsMatch(targetColor, fillColor)) {
floodFill(imageData, x, y, targetColor, fillColor);
ctx.putImageData(imageData, 0, 0);
}

}

// Helper functions for the Flood Fill

function getPixelColor(imageData, x, y) {
const index = (y * imageData.width + x) * 4;
const data = imageData.data;
return [data[index], data[index + 1], data[index + 2], data[index + 3]];
}

function setPixelColor(imageData, x, y, color) {
const index = (y * imageData.width + x) * 4;
const data = imageData.data;
data[index] = color[0]; // R
data[index + 1] = color[1]; // G
data[index + 2] = color[2]; // B
data[index + 3] = 255; // A
}

function colorsMatch(color1, color2) {
return color1[0] === color2[0] &&
color1[1] === color2[1] &&
color1[2] === color2[2] &&
color1[3] === color2[3];
}

function floodFill(imageData, x, y, targetColor, fillColor) {
const stack = [[x, y]];

while (stack.length > 0) {
const [currentX, currentY] = stack.pop();
const currentColor = getPixelColor(imageData, currentX, currentY);

if (colorsMatch(currentColor, targetColor)) {
setPixelColor(imageData, currentX, currentY, fillColor);

// Add neighboring pixels
if (currentX > 0) stack.push([currentX - 1, currentY]); // Left
if (currentX < imageData.width - 1) stack.push([currentX + 1, currentY]); // Right
if (currentY > 0) stack.push([currentX, currentY - 1]); // Top
if (currentY < imageData.height - 1) stack.push([currentX, currentY + 1]); // Bottom
}
}
}

function hexToRgb(hex) {
const bigint = parseInt(hex.slice(1), 16);
return [(bigint >> 16) & 255, (bigint >> 8) & 255, bigint & 255];
}

// Download as PNG
document.getElementById('download-png').addEventListener('click', () => {
const link = document.createElement('a');
Expand Down

0 comments on commit 859a192

Please sign in to comment.