Python Drawing Project Using Tkinter

How to Create a Drawing App In Python Tkinter



In this Python tutorial, we will see how to create a drawing application using the Tkinter library for the graphical user interface. 
This application provides a graphical user interface (GUI) where users can draw various shapes on a canvas, choose colors, and save their drawings.
The "Choose Color" button opens a color chooser dialog, allowing the user to select a drawing color.
The application supports three types of shapes: Freehand, Rectangle, and Oval, which users can select using dedicated buttons.
Mouse listeners capture user interactions for drawing shapes on the canvas, with the PaintPanel and the ControlPanel classes handling mouse events for drawing shapes.
The "Clear Canvas" button clears all drawn shapes from the canvas.
The "Save as Image" button allows users to save the current drawing as a PNG image file, using a file chooser dialog to select the destination for saving the image.

What We Are Gonna Use In This Project:

- Python Programming Language.
- Tkinter for GUI.
- VS Code Editor.




Project Source Code:




import tkinter as tk
from tkinter import colorchooser, filedialog, messagebox
from enum import Enum
from io import BytesIO
# pip install Pillow
from PIL import Image, ImageDraw, ImageTk, ImageGrab

# Enum to represent different types of shapes
class ShapeType(Enum):
FREEHAND = 1
RECTANGLE = 2
OVAL = 3
LINE = 4


# Main application class
class DrawingApp:
def __init__(self, root):
# Initialize the DrawingApp.
self.root = root
self.root.title("Drawing App")
self.root.geometry("800x600")

# Create a PaintPanel and ControlPanel
self.paint_panel = PaintPanel(root)
self.paint_panel.pack(fill=tk.BOTH, expand=True)

self.controle_panel = ControlPanel(root, self.paint_panel)
self.controle_panel.pack(fill=tk.X)


# Canvas for drawing
class PaintPanel(tk.Canvas):
def __init__(self, master, *args, **kwargs):
# Initialize the PaintPanel.
super().__init__(master, *args, **kwargs)
# Initialize variables
self.image = Image.new("RGB", (800, 600), "white")
self.shapes = []
self.current_color = "black"
self.current_shape_type = ShapeType.FREEHAND
self.background_color = "white"

# Bind events to methods
self.bind("<Button-1>", self.start_drawing)
self.bind("<B1-Motion>", self.draw)


# Start drawing a shape
def start_drawing(self, event):
start_point = (event.x, event.y)
shape = self.create_shape(self.current_shape_type, self.current_color,
        start_point)
self.shapes.append(shape)


# Continue drawing a shape
def draw(self, event):
if self.shapes:
current_shape = self.shapes[-1]
current_shape.add_point((event.x, event.y))
self.update_canvas()


# Create a shape based on shape type
def create_shape(self, shape_type, color, start_point):
if shape_type == ShapeType.FREEHAND:
return FreehandShape(color, start_point)
elif shape_type == ShapeType.RECTANGLE:
return RectangleShape(color, start_point)

elif shape_type == ShapeType.OVAL:
return OvalShape(color, start_point)

elif shape_type == ShapeType.LINE:
return LineShape(color, start_point)


# Update the canvas with shapes
def update_canvas(self):
self.delete("all")
self.create_rectangle(0, 0, self.winfo_width(), self.winfo_height(),
        fill=self.background_color)

for shape in self.shapes:
shape.draw(self)

self.photo = ImageTk.PhotoImage(self.image)

# Change the background color
def change_background_color(self, color):
self.background_color = color
self.update_canvas()
# Save the drawing as an image
def save_drawing(self):
# problem caused by the video recorder
file_path = filedialog.asksaveasfilename(defaultextension=".png",
        filetypes=[("PNG Files", "*.png")])
x = self.master.winfo_rootx() + self.winfo_x()
y = self.master.winfo_rooty() + self.winfo_y()

x1 = x + self.winfo_width()
y1 = y + self.winfo_height()

ImageGrab.grab(bbox=(x, y, x1, y1)).save(file_path)
print(f"Drawing saved as {file_path}")






# Control panel with buttons for various actions
class ControlPanel(tk.Frame):
def __init__(self, master, paint_panel, *args, **kwargs):
super().__init__(master, *args, **kwargs)
self.paint_panel = paint_panel

# Create buttons and pack them
self.clear_button = self.create_button("Clear Canvas", "red",
        self.clear_canvas)

self.color_button = self.create_button("Choose Color", "#3f51b5",
        self.choose_color)

self.freehand_button = self.create_button("Freehand", "#D35300",
        lambda : self.set_shape_type(ShapeType.FREEHAND))

self.rectangle_button = self.create_button("Rectangle", "#8e44ad",
        lambda : self.set_shape_type(ShapeType.RECTANGLE))

self.oval_button = self.create_button("Oval", "#27ae60",
        lambda : self.set_shape_type(ShapeType.OVAL))

self.line_button = self.create_button("Line", "#FFC107",
        lambda : self.set_shape_type(ShapeType.LINE))

self.bg_color_button = self.create_button("Change BG Color", "#604d8b",
        self.change_bg_color)

self.save_button = self.create_button("Save as image", "green",
        self.paint_panel.save_drawing)

self.pack_buttons()

# Create a button with specified properties
def create_button(self, text, bg_color, command):
button = tk.Button(self, text=text, bg=bg_color, fg="white", command=command)
button.configure(font = ("Arial", 10, "bold"))
button.pack(side = tk.LEFT, padx = 5)
return button

# Pack all buttons
def pack_buttons(self):
buttons = [
self.clear_button,
self.color_button,
self.freehand_button,
self.rectangle_button,
self.oval_button,
self.line_button,
self.bg_color_button,
self.save_button
]

for button in buttons:
button.pack(side = tk.LEFT, padx = 5)


# Change the background color
def change_bg_color(self):
color = colorchooser.askcolor(title="Choose Background Color")[1]
if color:
self.paint_panel.change_background_color(color)


# Choose a drawing color
def choose_color(self):
color = colorchooser.askcolor(title = "Choose Color")[1]
if color:
self.paint_panel.current_color = color


# Set the current shape type
def set_shape_type(self, shape_type):
self.paint_panel.current_shape_type = shape_type


# Clear the canvas
def clear_canvas(self):
self.paint_panel.shapes = []
self.paint_panel.update_canvas()



# Base class for different shapes
class Shape:
def __init__(self, color, start_point):
"""
Initialize a shape.

Args:
color: The color of the shape.
start_point: The starting point of the shape.
"""
self.color = color
self.points = [start_point]

def add_point(self, point):
"""
Add a point to the shape.

Args:
point: The point to add.
"""
self.points.append(point)

def draw(self, canvas):
# Draw the shape on the canvas
# Abstract method for drawing a shape
pass


# Freehand shape class
class FreehandShape(Shape):
def draw(self, canvas):
try:
canvas.create_line(self.points, fill = self.color, width = 2)
except tk.TclError as e:
print(f"Failed to draw freehand shape: {e}")



# Rectangle shape class
class RectangleShape(Shape):
def draw(self, canvas):
start_x, start_y = self.points[0]
end_x, end_y = self.points[-1]
canvas.create_rectangle(start_x, start_y, end_x, end_y,
        outline = self.color, width = 2)


# Oval shape class
class OvalShape(Shape):
def draw(self, canvas):
start_x, start_y = self.points[0]
end_x, end_y = self.points[-1]
canvas.create_oval(start_x, start_y, end_x, end_y, outline = self.color,
        width = 2)

# Line class
class LineShape(Shape):
def draw(self, canvas):
start_x, start_y = self.points[0]
end_x, end_y = self.points[-1]
canvas.create_line(start_x, start_y, end_x, end_y, fill = self.color,
        width = 2)




if __name__ == "__main__":
root = tk.Tk()
app = DrawingApp(root)
root.mainloop()




The Final Result:




PHP - Image Gallery Management System In PHP and MySQL

How to Create an Image Gallery with PHP and MySQL Database

Image Gallery Management System In PHP and MySQL


In this PHP tutorial we will see how to create a basic image gallery management system with mysql database.
Users can log in, view, rate, and comment on images.
The system includes functionality for admin users to add, delete, and manage images, as well as user authentication.
It provides an interface for users to interact with the image gallery, allowing them to leave comments, rate images.









Project Source Code:


------------ Create A Class "db_connect" To Connect Our Form With Database

This file sets up a PDO database connection and configures the error mode, enabling the PHP application to connect to the database.


<?php

$servername = "localhost";
$username = "root";
$password = "";
$dbname = "image_gallery_db";

try
{
$conn = new PDO("mysql: host=$servername;dbname=$dbname", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $ex){
echo"connection failed: " . $ex->getMessage();
die();
}

?>




------------ On The Login Page ------------

This file handles user authentication by retrieving submitted username and password via a form, validating these credentials against the database, and initiating a session to store user data upon successful login.


login form

login form error


<?php

// Include the database connection file
require_once 'db_connect.php';

// Check if the login form was submitted
if(isset($_POST['submit']))
{
// Get the submitted username and password
$usernsme = $_POST['username'];
$password = $_POST['password'];
// Prepare and execute a SELECT query to fetch the user by username
$stmt = $conn->prepare("SELECT * FROM `user` WHERE `username`=:uname");
$stmt->bindParam('uname',$usernsme);
$stmt->execute();

// Fetch the user record as an associative array
$result = $stmt->fetch(PDO::FETCH_ASSOC);

// Check if a user with the given username exists in the database
if($result){
// Verify the submitted password with the hashed password stored in the database
if(password_verify($password, $result['password']))
{
// Start a new session and store user data in session variables
session_start();
$_SESSION['id'] = $result['id'];
$_SESSION['username'] = $result['username'];

// Redirect to the "manage.php" page after successful login
header('Location: manage.php');
}
else
{
// If the password does not match, set an error message
$error_msg = "Incorrect Username Or Password";
}
}
else
{
// If no user with the given username is found, set an error message
$error_msg = "Incorrect Username";
}

}

?>



<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/
font-awesome/5.15.2/css/all.min.css"/>
<link rel="stylesheet" href="login-style.css">
<title>Login Form</title>
</head>
<body>

<form action="login.php" method="post" class="login-form">
<h1>Admin Login</h1>
<div class="input-container">
<i class="fa fa-user"></i>
<input type="text" name="username" placeholder="Username">
</div>
<div class="input-container">
<i class="fa fa-lock"></i>
<input type="password" name="password" placeholder="Password">
</div>
<button type="submit" name="submit">Login</button>

<?php

if(isset($error_msg)){
echo "<span class='error'>".$error_msg."</span>";
}

?>

</form>

</body>
</html>





------------ The Logout Page ------------

This file logs the user out by ending their session and redirecting them to the login page.


<?php

session_start();
session_unset();
session_destroy();

header('Location: login.php');

?>

                                                     

------------ The Redirect File ------------

This file is responsible for checking the user's login status and redirects them to the login page if they are not logged in.


<?php

// redirect the user to the login page if not logged
session_start();

if(!isset($_SESSION['username'])){
header('Location: login.php');
}

?>


                                                     

------------ The Gallery Page ------------

This page displays an image gallery, retrieving images and their details from the database and presenting them, including descriptions, to the user.

gallery page




<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/
font-awesome/5.15.2/css/all.min.css"/>
<link rel="stylesheet" href="gallery-style.css">
<title>Gallery</title>
</head>
<body>

<h1>Gallery</h1>
<div class="grid">
<!-- images will be generated from database -->
<?php

// Include the database connection file
require_once 'db_connect.php';

$stmt = $conn->prepare("SELECT * FROM images");
$stmt->execute();
$results=$stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($results as $row){
echo'<div class="image">';
echo'<img src="'.$row['image_path'].'">';
echo'<div class="overlay">';
echo'<h3>'.$row['title'].'</h3>';
echo'<p>'.$row['description'].'</p>';
echo' <a href="view.php?id='.$row['id'].'">View</a>';
echo'</div>';
echo'</div>';
}

?>
<!-- <div class="image">
<img src="pic1.jpg">
<div class="overlay">
<h3>Image Title</h3>
<p>Image Description</p>
<a href="">View Details</a>
</div>
</div> -->

</div>

</body>
</html>



                                                     

------------ The Manage Page ------------

This page serves as a user interface for managing images, enabling users to add new images and delete existing ones. 
It displays a comprehensive list of images in an HTML table, including their titles and descriptions. 
The interface handles form submissions for both image addition and deletion, providing users with immediate success or error feedback.

gallery management page

gallery management page





<?php

// Include a file for redirecting to the login page (if not logged in)
include 'redirect_file.php';

// Include the database connection file
require_once "db_connect.php";

// Check if the form was submitted with the 'delete_image' button.
if(isset($_POST['delete_image']))
{
// Get the image ID and image file path from the submitted form data.
$image_id = $_POST['image_id'];
$image_file = $_POST['image_file'];

// Prepare a DELETE query to delete the image
// with the specified ID from the 'images' table.
$stmt = $conn->prepare("DELETE FROM images WHERE id = ?");

// Execute the DELETE query with the image ID as the parameter.
if($stmt->execute([$image_id])){

// If the database operation was successful,
// try to delete the associated image file from the server / database.
if(file_exists($image_file))
{
// If the image file exists on the server, delete it using the 'unlink()' function.
unlink($image_file);
$_SESSION['success'] = "Image Deleted";
}
else{
// If the image file does not exist, set an error message.
$_SESSION['error'] = "Image Not Deleted";
}
}
else{
// If the database operation failed, set an error message.
$_SESSION['error'] = "Image Not Deleted";
}
}

// Fetch all rows from the 'images' table and store them in the $images array.
$stmt = $conn->query("SELECT * FROM `images`");
$images = $stmt->fetchAll();

?>

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs
/font-awesome/5.15.2/css/all.min.css"/>
<link rel="stylesheet" href="manage-style.css">
<title>Manage Images</title>
</head>
<body>

<?php

if(isset($_SESSION['error']))
{
echo'<div class="alert-box error-msg"><p>' . $_SESSION['error']
. '</p> <span class="close-alert">&times</span> </div>';
}
elseif(isset($_SESSION['success']))
{
echo'<div class="alert-box success-msg"><p>' . $_SESSION['success']
. '</p> <span class="close-alert">&times</span> </div>';
}

unset($_SESSION['error']);
unset($_SESSION['success']);


?>


<h1>Gallery Manager</h1>
<a href="add_image.php" class="add-btn">Add New Image</a>
<table>
<tr>
<th>ID</th>
<th>Image</th>
<th>Title</th>
<th>Description</th>
<th>Action</th>
</tr>
<!-- images will be generated from database -->
<!--<tr>
<td>1</td>
<td><img src="pic1.jpg" width="100"></td>
<td>Image Title</td>
<td>Image Description</td>
<td>
<button type="submit" name="delete_image" class="delete-btn">
Delete
</button>
</td>
</tr>-->
<?php
foreach($images as $image){

echo'<tr>
<td>'.$image['id'].'</td>
<td><img src="'.$image['image_path'].'" width="100"></td>
<td>'.$image['title'].'</td>
<td>'.$image['description'].'</td>
<td>
<form action="" method="post"
onsubmit="return
confirm(\' Are you sure you want to delete this image \')">
<input type="hidden" name="image_id" value="'.$image['id'].'">
<input type="hidden"
name="image_file" value="'.$image['image_path'].'">
<button type="submit" name="delete_image" class="delete-btn">
Delete
</button>
</form
</td>
</tr>';

}
?>

</table>


<script>

// close the alert box
document.querySelectorAll(".close-alert").forEach(function(closeButton)
{
closeButton.addEventListener("click", function()
{
closeButton.parentElement.style.display = "none";
});
});

</script>



</body>
</html>



                                                 
    

------------ The Add Image Page ------------

This page enables users to upload new images to the gallery, manages file uploads, and stores image details in the database while providing user-friendly success or error messages for feedback.

add a new image



<?php

// Include a file for redirecting to the login page (if not logged in)
include 'redirect_file.php';

// Include the database connection file
require_once 'db_connect.php';

// Check if the form has been submitted
if(isset($_POST['submit']))
{

// Get the form data
$title = $_POST['title'];
$description = $_POST['description'];

// Get the image file information from the $_FILES array
$file = $_FILES['image'];
$filename = $file['name']; // Original file name
$tmp_name = $file['tmp_name']; // Temporary file location
$extension = pathinfo($filename, PATHINFO_EXTENSION); // Get the file extension

// Create a unique filename for the uploaded image
$unique_filename = 'pic_'.uniqid().'.'. $extension;
// Set the directory where the uploaded images will be stored
$upload_dir = "images/";
// Set the complete path for the uploaded image
$upload_path = $upload_dir.$unique_filename;
// SQL query to insert data into the database
$sql = "INSERT INTO `images`(`title`, `image_path`, `description`)
VALUES (:title,:image_path,:description)";
$stmt = $conn->prepare($sql); // Prepare the SQL statement

// Check if the uploaded file has a valid image extension
if(!in_array($extension, ['png','jpg','jpeg','gif'])){
$_SESSION['error'] = "Wrong File Type";
// Redirect to the same page in case of an error
header('Location: add_image.php');
// Stop further execution of the script
exit();
}

// Check if the 'title' field is not empty
if(!empty(trim($title))){
// Move the uploaded file to the specified directory
if(move_uploaded_file($tmp_name, $upload_path)){
// Bind the form data to the prepared statement
$stmt->bindParam(':title', $title);
$stmt->bindParam(':description', $description);
$stmt->bindParam(':image_path', $upload_path);

// Execute the prepared statement to insert data into the database
if($stmt->execute()){
$_SESSION['success'] = "New Image Added";
header('Location: add_image.php');
exit();
}
else{
$_SESSION['error'] = "Image Not Added";
header('Location: add_image.php');
}
}
}

}

?>

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs
/font-awesome/5.15.2/css/all.min.css"/>
<link rel="stylesheet" href="add-style.css">
<title>Add Image</title>
</head>
<body>

<?php

if(isset($_SESSION['error']))
{
echo'<div class="alert-box error-msg"><p>' . $_SESSION['error']
. '</p> <span class="close-alert">&times</span> </div>';
}
elseif(isset($_SESSION['success']))
{
echo'<div class="alert-box success-msg"><p>' . $_SESSION['success']
. '</p> <span class="close-alert">&times</span> </div>';
}
unset($_SESSION['error']);
unset($_SESSION['success']);


?>

<h1>Add New Image</h1>
<form action="" method="post" enctype="multipart/form-data">
<label for="image">Select Image:</label>
<input type="file" name="image" id="image" required>
<label for="title">Title:</label>
<input type="text" name="title" id="title" required>
<label for="description">Description:</label>
<textarea name="description" id="description" rows="4"></textarea>
<button type="submit" name="submit">Add</button>
</form>

<script>

// close the alert box
document.querySelectorAll(".close-alert").forEach(function(closeButton)
{
closeButton.addEventListener("click", function()
{
closeButton.parentElement.style.display = "none";
});
});

</script>

</body>
</html>


                                                     

------------ The View Image Page ------------

This page displays a single image along with its details, including user comments and ratings. 
Users can rate the image and leave comments, and the page retrieves and showcases these user-generated comments and ratings for the displayed image.

view image page




<?php

// Include the database connection file
require_once 'db_connect.php';
// Get the 'id' parameter from the URL
$id = $_GET['id'];

// Fetch image details from the 'images' table using the provided 'id'
$stmt = $conn->prepare("SELECT * FROM `images` WHERE `id`=".$id);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);

// Check if the form was submitted
if(isset($_POST['submit']))
{
// Get the submitted form data
$image_id = $_POST['image_id'];
$username = $_POST['username'];
$comment = $_POST['comment'];
$rating = $_POST['rating'];
// Insert the user comment and rating into the 'comments_ratings_tbl' table
$sql = "INSERT INTO `comments_ratings_tbl`(`image_id`, `user_name`, `comment`,
`rating`) VALUES (:image_id,:user_name,:comment,:rating)";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':image_id',$image_id);
$stmt->bindParam(':user_name',$username);
$stmt->bindParam(':comment',$comment);
$stmt->bindParam(':rating',$rating);
// Execute the insert query
$stmt->execute();

// Redirect back to the 'view.php' page with the 'id' (image) parameter
header('Location: view.php?id='.$id);

}


// Fetch all ratings from the 'comments_ratings_tbl' table for the current image
$stmt = $conn->prepare('SELECT rating FROM `comments_ratings_tbl`
WHERE `image_id`=:id AND rating IS NOT NULL');
$stmt -> execute(['id'=>$id]);

// Get all the ratings as an array of values
$ratings = $stmt->fetchAll(PDO::FETCH_COLUMN);

// Calculate the average rating for the image
if(count($ratings) > 0){
$sum = array_sum($ratings);
$average = $sum / count($ratings);
}else{
$average = 0;
}

// echo'Average Rating: ' . round($average,1);



?>


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome
/5.15.2/css/all.min.css"/>
<link rel="stylesheet" href="view-style.css">
<title>View</title>
</head>
<body>

<div class="container">
<h1>Image</h1>
<div class="image-wrapper">
<img src="<?php echo $result['image_path'] ?>">
<div class="overlay">
<h3><?php echo $result['title'] ?></h3>
<p><?php echo $result['description'] ?></p>
</div>
</div>
<form action="#" method="post" class="rating-wrapper">
<h3>Rate this Image</h3>
<div class="rating">
<span class="stars"></span>
<span class="rating-value"><?php echo round($average,1); ?>/5</span>
</div>
<div class="rating-stars">
<input type="radio" name="rating" id="star1" value="1">
<label for="star1"></label>

<input type="radio" name="rating" id="star2" value="2">
<label for="star2"></label>

<input type="radio" name="rating" id="star3" value="3">
<label for="star3"></label>

<input type="radio" name="rating" id="star4" value="4">
<label for="star4"></label>

<input type="radio" name="rating" id="star5" value="5">
<label for="star5"></label>
</div>
<div class="comment-form">
<input type="hidden" name="image_id" value="<?php echo $result['id']; ?>">
<label for="username">Your Username:</label>
<input type="text" name="username" id="username" required>
<label for="comment">Leave a Comment:</label>
<textarea name="comment" id="comment" cols="30" rows="5"></textarea>
<button type="submit" name="submit">Submit</button>
</div>
</form>
<!-- show comments -->

<?php

$stmt = $conn->query("SELECT * FROM `comments_ratings_tbl` WHERE `image_id`=".$id);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);

echo '<ul>';

foreach($results as $comment)
{
echo '<li class="comment">';
echo '<div class="comment-info">';
echo '<span class="comment-name">'.$comment['user_name'].'</span>';
echo '</div>';
echo '<div class="comment-text">'.$comment['comment'].'</div>';
echo '</li>';
}

echo '</ul>';

?>


</div>


<script>

// Select all radio input elements within the "rating-stars" class
const stars = document.querySelectorAll('.rating-stars input[type="radio"]');

// Add a click event listener to each star element
stars.forEach((s)=>{
s.addEventListener('click',()=>{

// Get the value of the clicked star
const rating = s.value;
// Update the color of stars up to the clicked rating
for(let i=1; i<=rating; i++){
document.querySelector(`#star${i}+label`).style.color='#ffc107';
}
// Reset the color of stars beyond the clicked rating
for(let i=parseInt(rating)+1; i<=5; i++){
document.querySelector(`#star${i}+label`).style.color='#333';
}
});
});

</script>

</body>
</html>







PHP - Image Gallery Management System In PHP and MySQL







if you want the source code click on the download button below