-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
202 lines (180 loc) · 8.71 KB
/
index.html
File metadata and controls
202 lines (180 loc) · 8.71 KB
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PixelCraft - Image Editor</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet">
</head>
<body class="bg-gray-50 text-gray-800 font-sans">
<!-- Hero Section -->
<section class="bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500 text-white py-20 px-6 text-center">
<div class="max-w-4xl mx-auto">
<h1 class="text-5xl font-bold mb-4">Welcome to PixelCraft</h1>
<p class="text-lg mb-6">A powerful web-based image editor — Grayscale, Crop, Flip, Resize, and more!</p>
<a href="#tools"
class="bg-white text-indigo-600 font-semibold px-6 py-3 rounded-full shadow hover:shadow-lg transition">
Start Editing <i class="fas fa-arrow-right ml-2"></i>
</a>
</div>
</section>
<!-- Tools Section -->
<section id="tools" class="py-16 bg-white">
<div class="max-w-6xl mx-auto px-4">
<h2 class="text-3xl font-bold text-center text-indigo-700 mb-10">Image Processing Features</h2>
<div class="grid grid-cols-2 sm:grid-cols-4 gap-6 text-center mb-10">
<button onclick="applyEdit('grayscale')" class="bg-gray-100 p-6 rounded-xl shadow hover:shadow-lg transition">
<i class="fas fa-adjust text-3xl text-indigo-600 mb-2"></i>
<h3 class="text-lg font-semibold">Grayscale</h3>
</button>
<button onclick="applyEdit('flip-horizontal')"
class="bg-gray-100 p-6 rounded-xl shadow hover:shadow-lg transition">
<i class="fas fa-arrows-alt-h text-3xl text-indigo-600 mb-2"></i>
<h3 class="text-lg font-semibold">Flip Horizontal</h3>
</button>
<button onclick="applyEdit('flip-vertical')"
class="bg-gray-100 p-6 rounded-xl shadow hover:shadow-lg transition">
<i class="fas fa-arrows-alt-v text-3xl text-indigo-600 mb-2"></i>
<h3 class="text-lg font-semibold">Flip Vertical</h3>
</button>
<button onclick="applyEdit('resize')" class="bg-gray-100 p-6 rounded-xl shadow hover:shadow-lg transition">
<i class="fas fa-expand-arrows-alt text-3xl text-indigo-600 mb-2"></i>
<h3 class="text-lg font-semibold">Resize (200x200)</h3>
</button>
</div>
<!-- Custom Resize -->
<div class="text-center mb-8">
<h4 class="text-lg font-semibold text-indigo-700 mb-2">Custom Resize</h4>
<div class="flex flex-wrap justify-center gap-4">
<input type="number" id="resizeWidth" placeholder="Width" class="border p-2 rounded w-32" min="1">
<input type="number" id="resizeHeight" placeholder="Height" class="border p-2 rounded w-32" min="1">
<button onclick="applyCustomResize()"
class="bg-indigo-600 text-white px-4 py-2 rounded hover:bg-indigo-700 transition">
Apply Custom Resize
</button>
</div>
</div>
</div>
</section>
<!-- Crop Section -->
<section id="crop" class="py-16 bg-gray-100">
<div class="max-w-4xl mx-auto text-center">
<h2 class="text-3xl font-bold text-indigo-700 mb-6">Crop Your Image</h2>
<p class="text-lg text-gray-600 mb-8">Provide the crop area dimensions and coordinates.</p>
<form id="crop-form" class="bg-white shadow-lg rounded-lg p-8">
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6 mb-6">
<input type="number" id="x" placeholder="X" required class="border p-3 rounded w-full">
<input type="number" id="y" placeholder="Y" required class="border p-3 rounded w-full">
<input type="number" id="width" placeholder="Width" required class="border p-3 rounded w-full">
<input type="number" id="height" placeholder="Height" required class="border p-3 rounded w-full">
</div>
<button type="button" onclick="applyCrop()"
class="bg-indigo-600 text-white font-semibold py-3 rounded-lg w-full hover:bg-indigo-700 transition">
Crop Image
</button>
</form>
</div>
</section>
<!-- Preview + Upload Section -->
<section class="bg-gray-50 py-16">
<div class="max-w-5xl mx-auto px-4 text-center">
<h2 class="text-2xl font-bold mb-6 text-indigo-700">Live Preview</h2>
<form id="uploadForm" enctype="multipart/form-data" class="mb-8">
<label for="imageInput"
class="bg-indigo-600 text-white px-6 py-3 rounded-full shadow-md hover:bg-indigo-700 cursor-pointer inline-flex items-center">
<i class="fas fa-upload text-lg mr-2"></i> Choose a file
<input type="file" id="imageInput" name="image" accept="image/*" class="hidden" onchange="showFileName()"
required />
</label>
<p id="fileName" class="mt-2 text-sm text-gray-600"></p>
<button type="submit" class="mt-4 bg-indigo-600 text-white px-6 py-2 rounded hover:bg-indigo-700 transition">
Upload Image
</button>
</form>
<div class="border-2 border-dashed border-indigo-300 bg-white p-10 rounded-xl shadow-md">
<p class="text-gray-500" id="previewText">Your edited image will appear here...</p>
<img id="previewImage" class="mt-6 mx-auto hidden max-w-full rounded" src="#" alt="Image Preview">
<a id="downloadBtn" href="#" download
class="hidden mt-4 inline-block bg-green-600 text-white px-4 py-2 rounded hover:bg-green-700 transition">
Download Edited Image
</a>
</div>
</div>
</section>
<footer class="bg-gray-800 text-white py-6 text-center text-sm">
© 2025 PixelCraft | All Rights Reserved
</footer>
<script>
let currentFilename = '';
// Handle image upload
document.getElementById('uploadForm').onsubmit = async function (e) {
e.preventDefault();
const formData = new FormData(this);
try {
const response = await fetch('/upload', {
method: 'POST',
body: formData,
});
if (!response.ok) throw new Error('Failed to upload image.');
const result = await response.json();
currentFilename = result.filename;
const previewImage = document.getElementById('previewImage');
previewImage.src = `/static/uploads/${currentFilename}?t=` + new Date().getTime();
previewImage.classList.remove('hidden');
document.getElementById('previewText').style.display = 'none';
document.getElementById('downloadBtn').href = previewImage.src;
document.getElementById('downloadBtn').classList.remove('hidden');
} catch (error) {
alert(error.message);
}
};
// Show file name
function showFileName() {
const fileInput = document.getElementById('imageInput');
const fileName = fileInput.files[0]?.name || 'No file selected';
document.getElementById('fileName').textContent = fileName;
}
// Edit actions (grayscale, flip, resize)
async function applyEdit(action) {
if (!currentFilename) return alert("Please upload an image first.");
const response = await fetch(`/edit/${action}/${currentFilename}`);
const result = await response.json();
currentFilename = result.filename;
updatePreviewImage();
}
// Custom resize
async function applyCustomResize() {
if (!currentFilename) return alert("Upload an image first.");
const width = document.getElementById('resizeWidth').value;
const height = document.getElementById('resizeHeight').value;
if (!width || !height || width <= 0 || height <= 0) {
return alert("Enter valid width and height.");
}
const response = await fetch(`/resize/${currentFilename}/${width}/${height}`);
const result = await response.json();
currentFilename = result.filename;
updatePreviewImage();
}
// Crop image
async function applyCrop() {
if (!currentFilename) return alert("Upload an image first.");
const x = document.getElementById('x').value;
const y = document.getElementById('y').value;
const width = document.getElementById('width').value;
const height = document.getElementById('height').value;
const response = await fetch(`/crop/${currentFilename}/${x}/${y}/${width}/${height}`);
const result = await response.json();
currentFilename = result.filename;
updatePreviewImage();
}
// Update preview and download
function updatePreviewImage() {
const previewImage = document.getElementById('previewImage');
previewImage.src = `/static/uploads/${currentFilename}?t=` + new Date().getTime();
previewImage.classList.remove('hidden');
document.getElementById('downloadBtn').href = previewImage.src;
}
</script>
</body>
</html>