ccookie commited on
Commit
5109da1
·
verified ·
1 Parent(s): 8eb1407

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +620 -19
  3. prompts.txt +2 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Pic Generate
3
- emoji: 🚀
4
- colorFrom: pink
5
- colorTo: gray
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: pic-generate
3
+ emoji: 🐳
4
+ colorFrom: red
5
+ colorTo: yellow
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,620 @@
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>图片色卡提取工具</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ .color-card {
11
+ transition: all 0.3s ease;
12
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
13
+ }
14
+ .color-card:hover {
15
+ transform: translateY(-5px);
16
+ box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
17
+ }
18
+ .color-value {
19
+ font-family: 'Courier New', monospace;
20
+ cursor: pointer;
21
+ }
22
+ .copied-message {
23
+ opacity: 0;
24
+ transition: opacity 0.3s ease;
25
+ }
26
+ .show-copied {
27
+ opacity: 1;
28
+ }
29
+ .color-preview {
30
+ height: 120px;
31
+ border-top-left-radius: 0.5rem;
32
+ border-top-right-radius: 0.5rem;
33
+ }
34
+ #imagePreview {
35
+ max-height: 400px;
36
+ max-width: 100%;
37
+ border-radius: 0.5rem;
38
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
39
+ }
40
+ #dropZone {
41
+ border: 2px dashed #cbd5e0;
42
+ transition: all 0.3s ease;
43
+ }
44
+ #dropZone.drag-over {
45
+ border-color: #4299e1;
46
+ background-color: #ebf8ff;
47
+ }
48
+ .progress-bar {
49
+ height: 6px;
50
+ background-color: #e2e8f0;
51
+ border-radius: 3px;
52
+ overflow: hidden;
53
+ }
54
+ .progress-fill {
55
+ height: 100%;
56
+ background-color: #4299e1;
57
+ transition: width 0.3s ease;
58
+ }
59
+ </style>
60
+ </head>
61
+ <body class="bg-gray-100 min-h-screen">
62
+ <div class="container mx-auto px-4 py-8">
63
+ <header class="mb-8 text-center">
64
+ <h1 class="text-4xl font-bold text-gray-800 mb-2">图片色卡提取工具</h1>
65
+ <p class="text-gray-600 max-w-2xl mx-auto">上传图片自动提取主要颜色,生成美观的色卡</p>
66
+ </header>
67
+
68
+ <div class="bg-white rounded-xl shadow-md p-6 mb-8">
69
+ <div id="dropZone" class="flex flex-col items-center justify-center p-8 rounded-lg mb-4">
70
+ <i class="fas fa-cloud-upload-alt text-4xl text-blue-500 mb-3"></i>
71
+ <p class="text-gray-700 mb-2">拖放图片到此处或</p>
72
+ <label for="imageUpload" class="cursor-pointer bg-blue-500 hover:bg-blue-600 text-white px-6 py-2 rounded-lg font-medium transition-colors inline-block">
73
+ <i class="fas fa-folder-open mr-2"></i>选择图片
74
+ </label>
75
+ <input type="file" id="imageUpload" accept="image/*" class="hidden">
76
+ <p class="text-gray-500 text-sm mt-3">支持 JPG, PNG, GIF 等格式</p>
77
+ </div>
78
+
79
+ <div class="flex items-center mb-4 hidden" id="progressContainer">
80
+ <div class="progress-bar flex-1 mr-2">
81
+ <div class="progress-fill" id="progressFill" style="width: 0%"></div>
82
+ </div>
83
+ <span class="text-sm text-gray-600" id="progressText">0%</span>
84
+ </div>
85
+
86
+ <div class="flex flex-col md:flex-row gap-6">
87
+ <div class="flex-1">
88
+ <h3 class="text-lg font-semibold mb-3 text-gray-800">图片预览</h3>
89
+ <div class="flex items-center justify-center bg-gray-100 rounded-lg p-4 min-h-48">
90
+ <img id="imagePreview" class="hidden" alt="图片预览">
91
+ <p id="noImageText" class="text-gray-500">图片将显示在这里</p>
92
+ </div>
93
+ </div>
94
+ <div class="flex-1">
95
+ <h3 class="text-lg font-semibold mb-3 text-gray-800">提取设置</h3>
96
+ <div class="space-y-4">
97
+ <div>
98
+ <label for="colorCount" class="block text-sm font-medium text-gray-700 mb-1">提取颜色数量</label>
99
+ <select id="colorCount" class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500">
100
+ <option value="5">5种</option>
101
+ <option value="8" selected>8种</option>
102
+ <option value="12">12种</option>
103
+ <option value="16">16种</option>
104
+ </select>
105
+ </div>
106
+ <div>
107
+ <label for="algorithm" class="block text-sm font-medium text-gray-700 mb-1">提取算法</label>
108
+ <select id="algorithm" class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500">
109
+ <option value="kmeans">K-means聚类</option>
110
+ <option value="medianCut" selected>中值切割</option>
111
+ <option value="simple">简单采样</option>
112
+ </select>
113
+ </div>
114
+ <div class="flex items-center">
115
+ <input type="checkbox" id="ignoreWhite" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
116
+ <label for="ignoreWhite" class="ml-2 block text-sm text-gray-700">忽略白色/接近白色</label>
117
+ </div>
118
+ <div class="flex items-center">
119
+ <input type="checkbox" id="ignoreBlack" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
120
+ <label for="ignoreBlack" class="ml-2 block text-sm text-gray-700">忽略黑色/接近黑色</label>
121
+ </div>
122
+ <button id="extractBtn" class="w-full bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded-lg font-medium transition-colors flex items-center justify-center disabled:opacity-50" disabled>
123
+ <i class="fas fa-palette mr-2"></i>提取颜色
124
+ </button>
125
+ </div>
126
+ </div>
127
+ </div>
128
+ </div>
129
+
130
+ <div id="resultsSection" class="hidden">
131
+ <div class="flex justify-between items-center mb-6">
132
+ <h2 class="text-2xl font-bold text-gray-800">提取的颜色</h2>
133
+ <div class="flex gap-2">
134
+ <button id="copyAllBtn" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg flex items-center transition-colors">
135
+ <i class="fas fa-copy mr-2"></i>复制全部
136
+ </button>
137
+ <button id="exportBtn" class="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded-lg flex items-center transition-colors">
138
+ <i class="fas fa-file-export mr-2"></i>导出色卡
139
+ </button>
140
+ </div>
141
+ </div>
142
+
143
+ <div id="colorGrid" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-6">
144
+ <!-- 颜色卡片将在这里生成 -->
145
+ </div>
146
+ </div>
147
+
148
+ <div id="toast" class="fixed bottom-4 right-4 bg-green-500 text-white px-4 py-2 rounded-lg shadow-lg hidden">
149
+ 颜色已复制到剪贴板!
150
+ </div>
151
+ </div>
152
+
153
+ <script>
154
+ document.addEventListener('DOMContentLoaded', function() {
155
+ const dropZone = document.getElementById('dropZone');
156
+ const imageUpload = document.getElementById('imageUpload');
157
+ const imagePreview = document.getElementById('imagePreview');
158
+ const noImageText = document.getElementById('noImageText');
159
+ const extractBtn = document.getElementById('extractBtn');
160
+ const colorGrid = document.getElementById('colorGrid');
161
+ const resultsSection = document.getElementById('resultsSection');
162
+ const colorCount = document.getElementById('colorCount');
163
+ const algorithm = document.getElementById('algorithm');
164
+ const ignoreWhite = document.getElementById('ignoreWhite');
165
+ const ignoreBlack = document.getElementById('ignoreBlack');
166
+ const copyAllBtn = document.getElementById('copyAllBtn');
167
+ const exportBtn = document.getElementById('exportBtn');
168
+ const toast = document.getElementById('toast');
169
+ const progressContainer = document.getElementById('progressContainer');
170
+ const progressFill = document.getElementById('progressFill');
171
+ const progressText = document.getElementById('progressText');
172
+
173
+ let uploadedImage = null;
174
+ let extractedColors = [];
175
+
176
+ // 拖放功能
177
+ ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
178
+ dropZone.addEventListener(eventName, preventDefaults, false);
179
+ });
180
+
181
+ function preventDefaults(e) {
182
+ e.preventDefault();
183
+ e.stopPropagation();
184
+ }
185
+
186
+ ['dragenter', 'dragover'].forEach(eventName => {
187
+ dropZone.addEventListener(eventName, highlight, false);
188
+ });
189
+
190
+ ['dragleave', 'drop'].forEach(eventName => {
191
+ dropZone.addEventListener(eventName, unhighlight, false);
192
+ });
193
+
194
+ function highlight() {
195
+ dropZone.classList.add('drag-over');
196
+ }
197
+
198
+ function unhighlight() {
199
+ dropZone.classList.remove('drag-over');
200
+ }
201
+
202
+ dropZone.addEventListener('drop', handleDrop, false);
203
+
204
+ function handleDrop(e) {
205
+ const dt = e.dataTransfer;
206
+ const files = dt.files;
207
+ if (files.length > 0 && files[0].type.match('image.*')) {
208
+ handleImageUpload(files[0]);
209
+ }
210
+ }
211
+
212
+ // 文件上传处理
213
+ imageUpload.addEventListener('change', function() {
214
+ if (this.files && this.files[0]) {
215
+ handleImageUpload(this.files[0]);
216
+ }
217
+ });
218
+
219
+ function handleImageUpload(file) {
220
+ const reader = new FileReader();
221
+
222
+ reader.onload = function(e) {
223
+ imagePreview.src = e.target.result;
224
+ imagePreview.classList.remove('hidden');
225
+ noImageText.classList.add('hidden');
226
+
227
+ // 创建新的Image对象以便后续处理
228
+ uploadedImage = new Image();
229
+ uploadedImage.onload = function() {
230
+ extractBtn.disabled = false;
231
+ };
232
+ uploadedImage.src = e.target.result;
233
+ };
234
+
235
+ reader.readAsDataURL(file);
236
+ }
237
+
238
+ // 提取颜色按钮点击事件
239
+ extractBtn.addEventListener('click', function() {
240
+ if (!uploadedImage) return;
241
+
242
+ const count = parseInt(colorCount.value);
243
+ const algo = algorithm.value;
244
+ const ignoreW = ignoreWhite.checked;
245
+ const ignoreB = ignoreBlack.checked;
246
+
247
+ progressContainer.classList.remove('hidden');
248
+ progressFill.style.width = '0%';
249
+ progressText.textContent = '0%';
250
+
251
+ // 使用setTimeout让UI有时间更新
252
+ setTimeout(() => {
253
+ extractedColors = extractColorsFromImage(uploadedImage, count, algo, ignoreW, ignoreB);
254
+ displayColorCards(extractedColors);
255
+ resultsSection.classList.remove('hidden');
256
+ progressContainer.classList.add('hidden');
257
+ }, 100);
258
+ });
259
+
260
+ // 从图片中提取颜色的函数
261
+ function extractColorsFromImage(image, colorCount, algorithm, ignoreWhite, ignoreBlack) {
262
+ const canvas = document.createElement('canvas');
263
+ const ctx = canvas.getContext('2d');
264
+ const width = Math.min(image.width, 200); // 缩小尺寸以提高性能
265
+ const height = Math.min(image.height, 200);
266
+ canvas.width = width;
267
+ canvas.height = height;
268
+
269
+ // 绘制图片到canvas
270
+ ctx.drawImage(image, 0, 0, width, height);
271
+
272
+ // 获取像素数据
273
+ const imageData = ctx.getImageData(0, 0, width, height).data;
274
+ const pixels = [];
275
+
276
+ // 收集所有像素颜色
277
+ for (let i = 0; i < imageData.length; i += 4) {
278
+ const r = imageData[i];
279
+ const g = imageData[i + 1];
280
+ const b = imageData[i + 2];
281
+ const a = imageData[i + 3];
282
+
283
+ // 忽略透明度低的像素
284
+ if (a < 128) continue;
285
+
286
+ // 检查是否忽略白色/黑色
287
+ if (ignoreWhite && isNearWhite(r, g, b)) continue;
288
+ if (ignoreBlack && isNearBlack(r, g, b)) continue;
289
+
290
+ pixels.push([r, g, b]);
291
+
292
+ // 更新进度
293
+ if (i % 400 === 0) {
294
+ const progress = Math.min(100, Math.floor((i / imageData.length) * 100));
295
+ progressFill.style.width = `${progress}%`;
296
+ progressText.textContent = `${progress}%`;
297
+ }
298
+ }
299
+
300
+ // 根据选择的算法提取主要颜色
301
+ let colors;
302
+ switch (algorithm) {
303
+ case 'kmeans':
304
+ colors = kMeansClustering(pixels, colorCount);
305
+ break;
306
+ case 'medianCut':
307
+ colors = medianCut(pixels, colorCount);
308
+ break;
309
+ case 'simple':
310
+ colors = simpleSampling(pixels, colorCount);
311
+ break;
312
+ default:
313
+ colors = medianCut(pixels, colorCount);
314
+ }
315
+
316
+ // 转换为十六进制并命名
317
+ return colors.map(color => {
318
+ const hex = rgbToHex(color[0], color[1], color[2]);
319
+ return {
320
+ name: `Color ${hex}`,
321
+ value: hex
322
+ };
323
+ });
324
+ }
325
+
326
+ // 辅助函数:判断是否接近白色
327
+ function isNearWhite(r, g, b, threshold = 220) {
328
+ return r > threshold && g > threshold && b > threshold;
329
+ }
330
+
331
+ // 辅助函数:判断是否接近黑色
332
+ function isNearBlack(r, g, b, threshold = 30) {
333
+ return r < threshold && g < threshold && b < threshold;
334
+ }
335
+
336
+ // RGB转十六进制
337
+ function rgbToHex(r, g, b) {
338
+ return '#' + [r, g, b].map(x => {
339
+ const hex = x.toString(16);
340
+ return hex.length === 1 ? '0' + hex : hex;
341
+ }).join('');
342
+ }
343
+
344
+ // 简单采样算法
345
+ function simpleSampling(pixels, count) {
346
+ const step = Math.floor(pixels.length / count);
347
+ const colors = [];
348
+
349
+ for (let i = 0; i < pixels.length && colors.length < count; i += step) {
350
+ colors.push(pixels[i]);
351
+ }
352
+
353
+ return colors;
354
+ }
355
+
356
+ // 中值切割算法
357
+ function medianCut(pixels, count) {
358
+ let buckets = [pixels];
359
+
360
+ while (buckets.length < count) {
361
+ const newBuckets = [];
362
+
363
+ for (const bucket of buckets) {
364
+ if (bucket.length === 0) continue;
365
+
366
+ // 找到颜色范围最大的通道
367
+ let rMin = 255, rMax = 0;
368
+ let gMin = 255, gMax = 0;
369
+ let bMin = 255, bMax = 0;
370
+
371
+ for (const [r, g, b] of bucket) {
372
+ rMin = Math.min(rMin, r);
373
+ rMax = Math.max(rMax, r);
374
+ gMin = Math.min(gMin, g);
375
+ gMax = Math.max(gMax, g);
376
+ bMin = Math.min(bMin, b);
377
+ bMax = Math.max(bMax, b);
378
+ }
379
+
380
+ const rRange = rMax - rMin;
381
+ const gRange = gMax - gMin;
382
+ const bRange = bMax - bMin;
383
+
384
+ const maxRange = Math.max(rRange, gRange, bRange);
385
+ const channel = maxRange === rRange ? 0 : (maxRange === gRange ? 1 : 2);
386
+
387
+ // 按选定通道排序
388
+ bucket.sort((a, b) => a[channel] - b[channel]);
389
+
390
+ // 找到中值并分割
391
+ const medianIndex = Math.floor(bucket.length / 2);
392
+ newBuckets.push(bucket.slice(0, medianIndex));
393
+ newBuckets.push(bucket.slice(medianIndex));
394
+ }
395
+
396
+ buckets = newBuckets;
397
+ if (buckets.length >= count) break;
398
+ }
399
+
400
+ // 计算每个桶的平均颜色
401
+ return buckets.map(bucket => {
402
+ if (bucket.length === 0) return [0, 0, 0];
403
+
404
+ let rSum = 0, gSum = 0, bSum = 0;
405
+ for (const [r, g, b] of bucket) {
406
+ rSum += r;
407
+ gSum += g;
408
+ bSum += b;
409
+ }
410
+
411
+ return [
412
+ Math.round(rSum / bucket.length),
413
+ Math.round(gSum / bucket.length),
414
+ Math.round(bSum / bucket.length)
415
+ ];
416
+ });
417
+ }
418
+
419
+ // K-means聚类算法
420
+ function kMeansClustering(pixels, k, maxIterations = 10) {
421
+ // 随机选择初始中心点
422
+ let centroids = [];
423
+ const step = Math.floor(pixels.length / k);
424
+ for (let i = 0; i < k; i++) {
425
+ centroids.push(pixels[i * step]);
426
+ }
427
+
428
+ let clusters;
429
+
430
+ for (let iter = 0; iter < maxIterations; iter++) {
431
+ // 分配每个点到最近的中心点
432
+ clusters = Array(k).fill().map(() => []);
433
+
434
+ for (const pixel of pixels) {
435
+ let minDist = Infinity;
436
+ let closestCentroid = 0;
437
+
438
+ for (let i = 0; i < centroids.length; i++) {
439
+ const dist = colorDistance(pixel, centroids[i]);
440
+ if (dist < minDist) {
441
+ minDist = dist;
442
+ closestCentroid = i;
443
+ }
444
+ }
445
+
446
+ clusters[closestCentroid].push(pixel);
447
+ }
448
+
449
+ // 计算新的中心点
450
+ const newCentroids = [];
451
+ for (const cluster of clusters) {
452
+ if (cluster.length === 0) {
453
+ // 如果集群为空,保留旧的中心点
454
+ newCentroids.push(centroids[newCentroids.length]);
455
+ continue;
456
+ }
457
+
458
+ let rSum = 0, gSum = 0, bSum = 0;
459
+ for (const [r, g, b] of cluster) {
460
+ rSum += r;
461
+ gSum += g;
462
+ bSum += b;
463
+ }
464
+
465
+ newCentroids.push([
466
+ Math.round(rSum / cluster.length),
467
+ Math.round(gSum / cluster.length),
468
+ Math.round(bSum / cluster.length)
469
+ ]);
470
+ }
471
+
472
+ // 检查是否收敛
473
+ let converged = true;
474
+ for (let i = 0; i < centroids.length; i++) {
475
+ if (colorDistance(centroids[i], newCentroids[i]) > 5) {
476
+ converged = false;
477
+ break;
478
+ }
479
+ }
480
+
481
+ centroids = newCentroids;
482
+ if (converged) break;
483
+ }
484
+
485
+ return centroids;
486
+ }
487
+
488
+ // 计算两个颜色之间的距离
489
+ function colorDistance(c1, c2) {
490
+ const dr = c1[0] - c2[0];
491
+ const dg = c1[1] - c2[1];
492
+ const db = c1[2] - c2[2];
493
+ return Math.sqrt(dr * dr + dg * dg + db * db);
494
+ }
495
+
496
+ // 显示颜色卡片
497
+ function displayColorCards(colors) {
498
+ colorGrid.innerHTML = '';
499
+
500
+ colors.forEach(color => {
501
+ const colorCard = document.createElement('div');
502
+ colorCard.className = 'color-card bg-white rounded-lg overflow-hidden';
503
+
504
+ // 计算文本颜色基于背景亮度
505
+ const hex = color.value.replace('#', '');
506
+ const r = parseInt(hex.substring(0, 2), 16);
507
+ const g = parseInt(hex.substring(2, 4), 16);
508
+ const b = parseInt(hex.substring(4, 6), 16);
509
+ const brightness = (r * 299 + g * 587 + b * 114) / 1000;
510
+ const textColor = brightness > 128 ? 'text-gray-900' : 'text-white';
511
+
512
+ colorCard.innerHTML = `
513
+ <div class="color-preview" style="background-color: ${color.value};"></div>
514
+ <div class="p-4">
515
+ <h3 class="font-semibold text-lg mb-1">${color.name}</h3>
516
+ <div class="flex items-center justify-between mt-2">
517
+ <span class="color-value ${textColor} bg-black bg-opacity-20 px-2 py-1 rounded" data-value="${color.value}">${color.value}</span>
518
+ <div class="copied-message text-sm text-gray-600">已复制!</div>
519
+ </div>
520
+ </div>
521
+ `;
522
+ colorGrid.appendChild(colorCard);
523
+ });
524
+
525
+ // 添加点击事件到所有颜色值
526
+ document.querySelectorAll('.color-value').forEach(el => {
527
+ el.addEventListener('click', function() {
528
+ const colorValue = this.getAttribute('data-value');
529
+ navigator.clipboard.writeText(colorValue).then(() => {
530
+ // 显示通知
531
+ toast.classList.remove('hidden');
532
+ setTimeout(() => {
533
+ toast.classList.add('hidden');
534
+ }, 2000);
535
+
536
+ // 显示特定卡片上的复制消息
537
+ const copiedMsg = this.nextElementSibling;
538
+ copiedMsg.classList.add('show-copied');
539
+ setTimeout(() => {
540
+ copiedMsg.classList.remove('show-copied');
541
+ }, 1000);
542
+ });
543
+ });
544
+ });
545
+ }
546
+
547
+ // 复制全部按钮
548
+ copyAllBtn.addEventListener('click', function() {
549
+ const allColors = extractedColors.map(c => c.value).join('\n');
550
+ navigator.clipboard.writeText(allColors).then(() => {
551
+ toast.textContent = '所有颜色已复制到剪贴板!';
552
+ toast.classList.remove('hidden');
553
+ setTimeout(() => {
554
+ toast.classList.add('hidden');
555
+ }, 2000);
556
+ });
557
+ });
558
+
559
+ // 导出色卡按钮
560
+ exportBtn.addEventListener('click', function() {
561
+ if (!extractedColors.length) return;
562
+
563
+ const canvas = document.createElement('canvas');
564
+ const ctx = canvas.getContext('2d');
565
+ const cardWidth = 200;
566
+ const cardHeight = 150;
567
+ const margin = 10;
568
+
569
+ // 计算画布大小
570
+ const cols = Math.min(4, extractedColors.length);
571
+ const rows = Math.ceil(extractedColors.length / cols);
572
+ canvas.width = cols * (cardWidth + margin) + margin;
573
+ canvas.height = rows * (cardHeight + margin) + margin + 40; // 额外空间用于标题
574
+
575
+ // 绘制背景
576
+ ctx.fillStyle = '#ffffff';
577
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
578
+
579
+ // 添加标题
580
+ ctx.fillStyle = '#333333';
581
+ ctx.font = 'bold 20px Arial';
582
+ ctx.textAlign = 'center';
583
+ ctx.fillText('提取的颜色色卡', canvas.width / 2, 30);
584
+
585
+ // 绘制颜色卡片
586
+ ctx.font = '14px Arial';
587
+ ctx.textAlign = 'left';
588
+
589
+ for (let i = 0; i < extractedColors.length; i++) {
590
+ const color = extractedColors[i];
591
+ const col = i % cols;
592
+ const row = Math.floor(i / cols);
593
+
594
+ const x = margin + col * (cardWidth + margin);
595
+ const y = 40 + margin + row * (cardHeight + margin);
596
+
597
+ // 绘制颜色块
598
+ ctx.fillStyle = color.value;
599
+ ctx.fillRect(x, y, cardWidth, cardHeight * 0.7);
600
+
601
+ // 绘制信息区域
602
+ ctx.fillStyle = '#f8f8f8';
603
+ ctx.fillRect(x, y + cardHeight * 0.7, cardWidth, cardHeight * 0.3);
604
+
605
+ // 绘制颜色信息
606
+ ctx.fillStyle = '#333333';
607
+ ctx.fillText(color.name, x + 10, y + cardHeight * 0.7 + 25);
608
+ ctx.fillText(color.value, x + 10, y + cardHeight * 0.7 + 45);
609
+ }
610
+
611
+ // 导出为PNG
612
+ const link = document.createElement('a');
613
+ link.download = 'color-palette.png';
614
+ link.href = canvas.toDataURL('image/png');
615
+ link.click();
616
+ });
617
+ });
618
+ </script>
619
+ <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=ccookie/pic-generate" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
620
+ </html>
prompts.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ https://github.com/userElaina/color-card/blob/main/archive/color_card_old.hpp这篇网页实现了什么功能,复现,不能偷懒
2
+ 设计一个自动提取图片色卡的程序