DigiP-AI commited on
Commit
b839b27
·
verified ·
1 Parent(s): 48687a6

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +291 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Image Flipper
3
- emoji: 🚀
4
  colorFrom: purple
5
- colorTo: indigo
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: image-flipper
3
+ emoji: 🐳
4
  colorFrom: purple
5
+ colorTo: gray
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,291 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Image Flipper App</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <style>
9
+ .image-container {
10
+ transition: transform 0.3s ease;
11
+ }
12
+ .flip-btn:hover {
13
+ transform: translateY(-2px);
14
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
15
+ }
16
+ .file-input-label {
17
+ cursor: pointer;
18
+ transition: all 0.3s ease;
19
+ }
20
+ .file-input-label:hover {
21
+ background-color: #f3f4f6;
22
+ }
23
+ .flip-animation {
24
+ animation: flip 0.5s ease;
25
+ }
26
+ @keyframes flip {
27
+ 0% { transform: scaleX(1); }
28
+ 50% { transform: scaleX(0); }
29
+ 100% { transform: scaleX(1); }
30
+ }
31
+ </style>
32
+ </head>
33
+ <body class="bg-gray-100 min-h-screen flex flex-col items-center py-12">
34
+ <div class="w-full max-w-4xl bg-white rounded-xl shadow-lg overflow-hidden">
35
+ <!-- Header -->
36
+ <div class="bg-indigo-600 py-6 px-8 text-white">
37
+ <h1 class="text-3xl font-bold">Image Flipper</h1>
38
+ <p class="mt-2 opacity-90">Upload an image and flip it horizontally or vertically</p>
39
+ </div>
40
+
41
+ <!-- Main Content -->
42
+ <div class="p-8">
43
+ <!-- File Upload Section -->
44
+ <div class="mb-8">
45
+ <label class="file-input-label flex flex-col items-center justify-center border-2 border-dashed border-gray-300 rounded-lg p-12 text-center cursor-pointer hover:border-indigo-400 transition-colors duration-300" id="drop-area">
46
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 text-indigo-500 mb-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
47
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" />
48
+ </svg>
49
+ <span class="text-xl font-medium text-gray-700">Drag & drop your image here</span>
50
+ <span class="text-gray-500 mt-2">or click to browse files</span>
51
+ <input type="file" id="file-input" accept="image/*" class="hidden">
52
+ </label>
53
+ </div>
54
+
55
+ <!-- Image Display Section -->
56
+ <div class="flex flex-col items-center">
57
+ <div class="relative mb-8 w-full max-w-md" id="image-wrapper">
58
+ <div class="image-container bg-gray-100 rounded-lg overflow-hidden shadow-md" id="image-container">
59
+ <img id="preview-image" class="w-full h-auto object-contain max-h-96" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%239C92AC'%3E%3Cpath d='M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z'/%3E%3C/svg%3E" alt="Preview will appear here">
60
+ </div>
61
+ <div class="absolute -bottom-5 left-0 right-0 flex justify-center space-x-4">
62
+ <button id="reset-btn" class="bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium py-2 px-4 rounded-full transition-all duration-200 opacity-0 pointer-events-none">
63
+ Reset
64
+ </button>
65
+ </div>
66
+ </div>
67
+
68
+ <!-- Flip Controls -->
69
+ <div class="flex flex-wrap justify-center gap-4 mb-8" id="flip-controls">
70
+ <button id="flip-horizontal" class="flip-btn bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-3 px-6 rounded-lg flex items-center transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed" disabled>
71
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
72
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" />
73
+ </svg>
74
+ Flip Horizontal
75
+ </button>
76
+ <button id="flip-vertical" class="flip-btn bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-3 px-6 rounded-lg flex items-center transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed" disabled>
77
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
78
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 17V7m0 10l-4 4m4-4l4 4M8 7v10m0-10l4-4m-4 4l-4 4" />
79
+ </svg>
80
+ Flip Vertical
81
+ </button>
82
+ </div>
83
+
84
+ <!-- Download Button -->
85
+ <div class="w-full flex justify-center">
86
+ <button id="download-btn" class="bg-green-600 hover:bg-green-700 text-white font-medium py-3 px-6 rounded-lg flex items-center transition-all duration-200 opacity-0 pointer-events-none">
87
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
88
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
89
+ </svg>
90
+ Download Flipped Image
91
+ </button>
92
+ </div>
93
+ </div>
94
+ </div>
95
+ </div>
96
+
97
+ <script>
98
+ document.addEventListener('DOMContentLoaded', function() {
99
+ const fileInput = document.getElementById('file-input');
100
+ const dropArea = document.getElementById('drop-area');
101
+ const previewImage = document.getElementById('preview-image');
102
+ const flipHorizontalBtn = document.getElementById('flip-horizontal');
103
+ const flipVerticalBtn = document.getElementById('flip-vertical');
104
+ const resetBtn = document.getElementById('reset-btn');
105
+ const downloadBtn = document.getElementById('download-btn');
106
+ const imageContainer = document.getElementById('image-container');
107
+
108
+ let originalImageSrc = null;
109
+ let currentImageSrc = null;
110
+ let canvas = null;
111
+
112
+ // Handle file selection
113
+ fileInput.addEventListener('change', function(e) {
114
+ if (e.target.files.length) {
115
+ const file = e.target.files[0];
116
+ processImage(file);
117
+ }
118
+ });
119
+
120
+ // Handle drag and drop
121
+ ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
122
+ dropArea.addEventListener(eventName, preventDefaults, false);
123
+ });
124
+
125
+ function preventDefaults(e) {
126
+ e.preventDefault();
127
+ e.stopPropagation();
128
+ }
129
+
130
+ ['dragenter', 'dragover'].forEach(eventName => {
131
+ dropArea.addEventListener(eventName, highlight, false);
132
+ });
133
+
134
+ ['dragleave', 'drop'].forEach(eventName => {
135
+ dropArea.addEventListener(eventName, unhighlight, false);
136
+ });
137
+
138
+ function highlight() {
139
+ dropArea.classList.add('border-indigo-500', 'bg-indigo-50');
140
+ }
141
+
142
+ function unhighlight() {
143
+ dropArea.classList.remove('border-indigo-500', 'bg-indigo-50');
144
+ }
145
+
146
+ dropArea.addEventListener('drop', function(e) {
147
+ const dt = e.dataTransfer;
148
+ const file = dt.files[0];
149
+ if (file && file.type.match('image.*')) {
150
+ processImage(file);
151
+ }
152
+ });
153
+
154
+ // Process the uploaded image
155
+ function processImage(file) {
156
+ const reader = new FileReader();
157
+
158
+ reader.onload = function(e) {
159
+ originalImageSrc = e.target.result;
160
+ currentImageSrc = originalImageSrc;
161
+ previewImage.src = originalImageSrc;
162
+
163
+ // Enable buttons
164
+ flipHorizontalBtn.disabled = false;
165
+ flipVerticalBtn.disabled = false;
166
+
167
+ // Show reset button
168
+ resetBtn.classList.remove('opacity-0', 'pointer-events-none');
169
+ resetBtn.classList.add('opacity-100', 'pointer-events-auto');
170
+
171
+ // Hide download button until flip
172
+ downloadBtn.classList.add('opacity-0', 'pointer-events-none');
173
+ downloadBtn.classList.remove('opacity-100', 'pointer-events-auto');
174
+
175
+ // Create canvas for manipulation
176
+ createCanvas(originalImageSrc);
177
+ };
178
+
179
+ reader.readAsDataURL(file);
180
+ }
181
+
182
+ // Create canvas for image manipulation
183
+ function createCanvas(imageSrc) {
184
+ const img = new Image();
185
+ img.onload = function() {
186
+ if (canvas) {
187
+ document.body.removeChild(canvas);
188
+ }
189
+
190
+ canvas = document.createElement('canvas');
191
+ canvas.style.display = 'none';
192
+ document.body.appendChild(canvas);
193
+
194
+ canvas.width = img.width;
195
+ canvas.height = img.height;
196
+
197
+ const ctx = canvas.getContext('2d');
198
+ ctx.drawImage(img, 0, 0);
199
+ };
200
+ img.src = imageSrc;
201
+ }
202
+
203
+ // Flip image horizontally
204
+ flipHorizontalBtn.addEventListener('click', function() {
205
+ flipImage('horizontal');
206
+ });
207
+
208
+ // Flip image vertically
209
+ flipVerticalBtn.addEventListener('click', function() {
210
+ flipImage('vertical');
211
+ });
212
+
213
+ // Reset image to original
214
+ resetBtn.addEventListener('click', function() {
215
+ previewImage.src = originalImageSrc;
216
+ currentImageSrc = originalImageSrc;
217
+ createCanvas(originalImageSrc);
218
+
219
+ // Hide download button
220
+ downloadBtn.classList.add('opacity-0', 'pointer-events-none');
221
+ downloadBtn.classList.remove('opacity-100', 'pointer-events-auto');
222
+
223
+ // Add animation
224
+ imageContainer.classList.add('flip-animation');
225
+ setTimeout(() => {
226
+ imageContainer.classList.remove('flip-animation');
227
+ }, 500);
228
+ });
229
+
230
+ // Flip the image
231
+ function flipImage(direction) {
232
+ if (!canvas) return;
233
+
234
+ const img = new Image();
235
+ img.onload = function() {
236
+ const ctx = canvas.getContext('2d');
237
+
238
+ // Clear canvas
239
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
240
+
241
+ // Save the current context
242
+ ctx.save();
243
+
244
+ if (direction === 'horizontal') {
245
+ // Flip horizontally
246
+ ctx.translate(canvas.width, 0);
247
+ ctx.scale(-1, 1);
248
+ } else {
249
+ // Flip vertically
250
+ ctx.translate(0, canvas.height);
251
+ ctx.scale(1, -1);
252
+ }
253
+
254
+ // Draw the image
255
+ ctx.drawImage(img, 0, 0);
256
+
257
+ // Restore the context
258
+ ctx.restore();
259
+
260
+ // Update the preview
261
+ currentImageSrc = canvas.toDataURL('image/png');
262
+ previewImage.src = currentImageSrc;
263
+
264
+ // Show download button
265
+ downloadBtn.classList.remove('opacity-0', 'pointer-events-none');
266
+ downloadBtn.classList.add('opacity-100', 'pointer-events-auto');
267
+
268
+ // Add animation
269
+ imageContainer.classList.add('flip-animation');
270
+ setTimeout(() => {
271
+ imageContainer.classList.remove('flip-animation');
272
+ }, 500);
273
+ };
274
+ img.src = currentImageSrc;
275
+ }
276
+
277
+ // Download the flipped image
278
+ downloadBtn.addEventListener('click', function() {
279
+ if (!currentImageSrc) return;
280
+
281
+ const link = document.createElement('a');
282
+ link.download = 'flipped-image.png';
283
+ link.href = currentImageSrc;
284
+ document.body.appendChild(link);
285
+ link.click();
286
+ document.body.removeChild(link);
287
+ });
288
+ });
289
+ </script>
290
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=DigiP-AI/image-flipper" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
291
+ </html>