🌐 html public

Untitled Paste

Guest 23h ago 21 views Code Paste
Raw
🌐 html
1
<!DOCTYPE html>
2
<html lang="th">
3
<head>
4
    <meta charset="UTF-8">
5
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
    <title>AI Image Detector & Editor (Canva Style)</title>
7
    <script src="https://cdn.tailwindcss.com"></script>
8
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
9
    <!-- āļ™āļģāđ€āļ‚āđ‰āļē Google Fonts āļ āļēāļĐāļēāđ„āļ—āļĒāđāļĨāļ°āļ­āļąāļ‡āļāļĪāļĐāļ—āļĩāđˆāļŦāļĨāļēāļāļŦāļĨāļēāļĒāļ‚āļķāđ‰āļ™ -->
10
    <link href="https://fonts.googleapis.com/css2?family=Kanit:wght@300;400;500;700&family=Prompt:wght@300;400;500;700&family=Sarabun:wght@300;400;500;700&family=Chakra+Petch:wght@300;400;500;700&family=Mali:wght@300;400;500;700&family=Itim&family=Roboto:wght@300;400;500;700&family=Montserrat:wght@300;400;500;700&display=swap" rel="stylesheet">
11
    <!-- āļ™āļģāđ€āļ‚āđ‰āļē Fabric.js āļŠāļģāļŦāļĢāļąāļšāļĢāļ°āļšāļš Layer āđāļĨāļ°āļāļēāļĢāļˆāļąāļ”āļāļēāļĢ Object āđāļšāļš Canva -->
12
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.1/fabric.min.js"></script>
13
    <style>
14
        ::-webkit-scrollbar { width: 8px; }
15
        ::-webkit-scrollbar-track { background: #f1f1f1; }
16
        ::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 4px; }
17
        ::-webkit-scrollbar-thumb:hover { background: #94a3b8; }
18
        
19
        /* āļˆāļąāļ”āļāļēāļĢ Container āļ‚āļ­āļ‡ Canvas āļ—āļĩāđˆāļ–āļđāļāļŠāļĢāđ‰āļēāļ‡āđ‚āļ”āļĒ Fabric.js */
20
        .canvas-container {
21
            margin: 0 auto;
22
            box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
23
        }
24
    </style>
25
</head>
26
<body class="bg-slate-50 text-slate-800 font-sans min-h-screen">
27
 
28
    <div class="max-w-7xl mx-auto px-4 py-8">
29
        
30
        <!-- Header -->
31
        <header class="text-center mb-10">
32
            <h1 class="text-3xl md:text-4xl font-bold text-indigo-700 mb-2">
33
                <i class="fa-solid fa-layer-group mr-2"></i> AI Image Detector & Editor
34
            </h1>
35
            <p class="text-slate-500">āļ•āļĢāļ§āļˆāļŠāļ­āļšāļ āļēāļž AI āđāļĨāļ°āļĢāļ°āļšāļšāđāļāđ‰āđ„āļ‚āļ āļēāļžāđāļšāļšāđ€āļĨāđ€āļĒāļ­āļĢāđŒ (Canva Style)</p>
36
        </header>
37
 
38
        <!-- Main Content Grid -->
39
        <div class="grid grid-cols-1 lg:grid-cols-12 gap-6">
40
            
41
            <!-- Left Column: Controls -->
42
            <div class="lg:col-span-4 xl:col-span-3 space-y-6">
43
                
44
                <!-- Upload Section -->
45
                <div class="bg-white p-5 rounded-2xl shadow-sm border border-slate-200">
46
                    <h2 class="text-lg font-semibold mb-4 text-slate-700">1. āļ āļēāļžāļŦāļĨāļąāļ (Background)</h2>
47
                    <label for="imageUpload" class="flex flex-col items-center justify-center w-full h-28 border-2 border-slate-300 border-dashed rounded-xl cursor-pointer bg-slate-50 hover:bg-slate-100 transition">
48
                        <div class="flex flex-col items-center justify-center pt-5 pb-6">
49
                            <i class="fa-solid fa-cloud-arrow-up text-2xl text-indigo-500 mb-2"></i>
50
                            <p class="text-sm text-slate-500"><span class="font-semibold">āļ­āļąāļ›āđ‚āļŦāļĨāļ”āļ āļēāļžāļŦāļĨāļąāļ</span></p>
51
                        </div>
52
                        <input id="imageUpload" type="file" class="hidden" accept="image/*" />
53
                    </label>
54
                </div>
55
 
56
                <!-- Detection Status -->
57
                <div id="detectionPanel" class="bg-white p-5 rounded-2xl shadow-sm border border-slate-200 hidden">
58
                    <h2 class="text-lg font-semibold mb-4 text-slate-700">2. āļœāļĨāļāļēāļĢāļ§āļīāđ€āļ„āļĢāļēāļ°āļŦāđŒāļ āļēāļž</h2>
59
                    
60
                    <div id="detectionLoading" class="flex flex-col items-center py-4">
61
                        <i class="fa-solid fa-circle-notch fa-spin text-4xl text-indigo-500 mb-3"></i>
62
                        <p class="text-sm text-slate-600 font-medium" id="loadingText">āļāļģāļĨāļąāļ‡āļ•āļĢāļ§āļˆāļŠāļ­āļš Metadata...</p>
63
                        <div class="w-full bg-slate-200 rounded-full h-2.5 mt-4">
64
                            <div id="loadingBar" class="bg-indigo-600 h-2.5 rounded-full" style="width: 0%"></div>
65
                        </div>
66
                    </div>
67
 
68
                    <div id="detectionResult" class="hidden text-center">
69
                        <div id="resultIcon" class="text-5xl mb-3"></div>
70
                        <h3 id="resultTitle" class="text-lg font-bold mb-1"></h3>
71
                        <p id="resultDesc" class="text-xs text-slate-500 mb-4"></p>
72
                        
73
                        <div class="bg-slate-50 rounded-lg p-3 text-left text-xs text-slate-600 space-y-2 mb-4">
74
                            <div class="flex justify-between"><span>āđ‚āļ­āļāļēāļŠāđ€āļ›āđ‡āļ™āļ āļēāļž AI:</span> <span id="scoreAi" class="font-semibold"></span></div>
75
                            <div class="flex justify-between"><span>Noise Pattern:</span> <span id="scoreNoise" class="font-semibold"></span></div>
76
                        </div>
77
                        
78
                        <button id="startEditBtn" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-2 px-4 rounded-lg transition">
79
                            <i class="fa-solid fa-wand-magic-sparkles mr-2"></i>āđ€āļ›āļīāļ”āđ€āļ„āļĢāļ·āđˆāļ­āļ‡āļĄāļ·āļ­āđāļāđ‰āđ„āļ‚ (Layers)
80
                        </button>
81
                    </div>
82
                </div>
83
 
84
                <!-- Editor Tools (Layers, Filters, Draw) -->
85
                <div id="editorPanel" class="bg-white p-5 rounded-2xl shadow-sm border border-slate-200 hidden max-h-[800px] overflow-y-auto">
86
                    <h2 class="text-lg font-semibold mb-4 text-slate-700">3. āđ€āļ„āļĢāļ·āđˆāļ­āļ‡āļĄāļ·āļ­āđāļāđ‰āđ„āļ‚ (Canva Style)</h2>
87
                    
88
                    <!-- Add Elements / Layers -->
89
                    <div class="mb-5">
90
                        <label class="block text-sm font-medium text-slate-700 mb-2"><i class="fa-solid fa-shapes mr-1"></i> āđ€āļžāļīāđˆāļĄāļ­āļ‡āļ„āđŒāļ›āļĢāļ°āļāļ­āļš</label>
91
                        <div class="grid grid-cols-2 gap-2">
92
                            <button id="addTextBtn" class="bg-slate-100 hover:bg-slate-200 text-slate-700 py-2 rounded text-sm transition border border-slate-200">
93
                                <i class="fa-solid fa-font"></i> āļ‚āđ‰āļ­āļ„āļ§āļēāļĄ
94
                            </button>
95
                            <label class="bg-slate-100 hover:bg-slate-200 text-slate-700 py-2 rounded text-sm transition border border-slate-200 text-center cursor-pointer">
96
                                <i class="fa-regular fa-image"></i> āđ€āļžāļīāđˆāļĄāļĢāļđāļ›āļ āļēāļž
97
                                <input type="file" id="addLayerImage" class="hidden" accept="image/*">
98
                            </label>
99
                            <button id="addRectBtn" class="bg-slate-100 hover:bg-slate-200 text-slate-700 py-2 rounded text-sm transition border border-slate-200">
100
                                <i class="fa-solid fa-square"></i> āļŠāļĩāđˆāđ€āļŦāļĨāļĩāđˆāļĒāļĄ
101
                            </button>
102
                            <button id="addCircleBtn" class="bg-slate-100 hover:bg-slate-200 text-slate-700 py-2 rounded text-sm transition border border-slate-200">
103
                                <i class="fa-solid fa-circle"></i> āļ§āļ‡āļāļĨāļĄ
104
                            </button>
105
                        </div>
106
                        
107
                        <!-- āđ€āļ„āļĢāļ·āđˆāļ­āļ‡āļĄāļ·āļ­āļĨāļšāđāļĨāļ°āđāļāđ‰āđ„āļ‚āļ‚āđ‰āļ­āļ„āļ§āļēāļĄāļšāļ™āļ āļēāļž -->
108
                        <div class="mt-3">
109
                            <button id="magicTextBtn" class="w-full bg-gradient-to-r from-purple-500 to-indigo-500 hover:from-purple-600 hover:to-indigo-600 text-white py-2 rounded-lg text-sm font-medium transition shadow-sm">
110
                                <i class="fa-solid fa-wand-magic-sparkles mr-1"></i> āđāļāđ‰āđ„āļ‚āļ‚āđ‰āļ­āļ„āļ§āļēāļĄāđ€āļ”āļīāļĄāļšāļ™āļ āļēāļž (Magic Edit)
111
                            </button>
112
                            <p class="text-[10px] text-slate-500 mt-1 text-center">āļ„āļĨāļīāļāļ›āļļāđˆāļĄ āđāļĨāđ‰āļ§āļĨāļēāļāļ„āļĨāļļāļĄāļ‚āđ‰āļ­āļ„āļ§āļēāļĄāđ€āļ”āļīāļĄ āđ€āļžāļ·āđˆāļ­āļĨāļšāđāļĨāļ°āļžāļīāļĄāļžāđŒāđƒāļŦāļĄāđˆ</p>
113
                        </div>
114
                    </div>
115
 
116
                    <!-- Manage Selected Object -->
117
                    <div id="objectControls" class="mb-5 p-3 bg-indigo-50 border border-indigo-100 rounded-lg opacity-50 pointer-events-none transition-opacity">
118
                        <div class="flex justify-between items-center mb-2">
119
                            <label class="block text-sm font-medium text-indigo-900">āļˆāļąāļ”āļāļēāļĢāļ§āļąāļ•āļ–āļļāļ—āļĩāđˆāđ€āļĨāļ·āļ­āļ</label>
120
                            <input type="color" id="objColorPicker" class="w-6 h-6 rounded cursor-pointer border-0 p-0 hidden" title="āđ€āļ›āļĨāļĩāđˆāļĒāļ™āļŠāļĩāļ§āļąāļ•āļ–āļļ/āļ‚āđ‰āļ­āļ„āļ§āļēāļĄ">
121
                        </div>
122
                        <div class="flex space-x-2">
123
                            <button id="bringForwardBtn" class="flex-1 bg-white hover:bg-indigo-100 text-indigo-700 py-1.5 rounded text-xs transition border border-indigo-200" title="āļ™āļģāļĄāļēāđ„āļ§āđ‰āļ‚āđ‰āļēāļ‡āļŦāļ™āđ‰āļē">
124
                                <i class="fa-solid fa-layer-group"></i> āļ‚āļķāđ‰āļ™āļšāļ™
125
                            </button>
126
                            <button id="sendBackwardBtn" class="flex-1 bg-white hover:bg-indigo-100 text-indigo-700 py-1.5 rounded text-xs transition border border-indigo-200" title="āļŠāđˆāļ‡āđ„āļ›āļ‚āđ‰āļēāļ‡āļŦāļĨāļąāļ‡">
127
                                <i class="fa-solid fa-layer-group fa-flip-vertical"></i> āļĨāļ‡āļĨāđˆāļēāļ‡
128
                            </button>
129
                            <button id="deleteObjBtn" class="flex-1 bg-white hover:bg-red-100 text-red-600 py-1.5 rounded text-xs transition border border-red-200">
130
                                <i class="fa-solid fa-trash"></i> āļĨāļš
131
                            </button>
132
                        </div>
133
                        
134
                        <!-- Text Specific Controls -->
135
                        <div id="textControls" class="hidden mt-3 pt-3 border-t border-indigo-200">
136
                            <label class="block text-xs font-medium text-indigo-900 mb-2"><i class="fa-solid fa-font"></i> āļĢāļđāļ›āđāļšāļšāļ‚āđ‰āļ­āļ„āļ§āļēāļĄ</label>
137
                            <div class="grid grid-cols-4 gap-2 items-end">
138
                                <div class="col-span-2">
139
                                    <label class="text-[10px] text-indigo-700">āđāļšāļšāļ­āļąāļāļĐāļĢ</label>
140
                                    <select id="fontFamilySelect" class="w-full text-xs p-1.5 border border-indigo-200 rounded bg-white">
141
                                        <optgroup label="āļĒāļ­āļ”āļ™āļīāļĒāļĄ">
142
                                            <option value="sans-serif">Sans-serif</option>
143
                                            <option value="serif">Serif</option>
144
                                            <option value="Arial">Arial</option>
145
                                        </optgroup>
146
                                        <optgroup label="āļ āļēāļĐāļēāđ„āļ—āļĒ">
147
                                            <option value="Kanit">Kanit</option>
148
                                            <option value="Prompt">Prompt</option>
149
                                            <option value="Sarabun">Sarabun</option>
150
                                            <option value="Chakra Petch">Chakra Petch</option>
151
                                            <option value="Mali">Mali</option>
152
                                            <option value="Itim">Itim</option>
153
                                        </optgroup>
154
                                        <optgroup label="āļ āļēāļĐāļēāļ­āļąāļ‡āļāļĪāļĐ">
155
                                            <option value="Roboto">Roboto</option>
156
                                            <option value="Montserrat">Montserrat</option>
157
                                        </optgroup>
158
                                    </select>
159
                                </div>
160
                                <div>
161
                                    <label class="text-[10px] text-indigo-700">āļ‚āļ™āļēāļ”</label>
162
                                    <input type="number" id="fontSizeInput" min="10" max="200" value="40" class="w-full text-xs p-1.5 border border-indigo-200 rounded bg-white">
163
                                </div>
164
                                <div class="flex flex-col justify-end">
165
                                    <label class="text-[10px] text-indigo-700">āļŠāđ„āļ•āļĨāđŒ/āļŠāļĩ</label>
166
                                    <div class="flex space-x-1">
167
                                        <button id="textBoldBtn" class="w-7 h-[30px] bg-white border border-indigo-200 rounded flex items-center justify-center text-indigo-700 hover:bg-indigo-50 transition" title="āđ€āļ›āļīāļ”/āļ›āļīāļ”āļ•āļąāļ§āļŦāļ™āļē">
168
                                            <i class="fa-solid fa-bold text-xs"></i>
169
                                        </button>
170
                                        <input type="color" id="textColorPicker" value="#333333" class="w-7 h-[30px] p-0 border border-indigo-200 rounded bg-white cursor-pointer" title="āļŠāļĩāļ‚āđ‰āļ­āļ„āļ§āļēāļĄ">
171
                                    </div>
172
                                </div>
173
                            </div>
174
                        </div>
175
                    </div>
176
 
177
                    <hr class="border-slate-100 my-4">
178
 
179
                    <!-- Filters (Applies to selected image or background) -->
180
                    <div class="space-y-3 mb-5">
181
                        <label class="block text-sm font-medium text-slate-700 mb-1"><i class="fa-solid fa-sliders mr-1"></i> āļ›āļĢāļąāļšāđāļ•āđˆāļ‡āļŠāļĩ/āđāļŠāļ‡ (āļ āļēāļžāļ—āļĩāđˆāđ€āļĨāļ·āļ­āļ)</label>
182
                        <div>
183
                            <label class="flex justify-between text-xs text-slate-500 mb-1">
184
                                <span>āļ„āļ§āļēāļĄāļŠāļ§āđˆāļēāļ‡</span> <span id="valBright">0</span>
185
                            </label>
186
                            <input type="range" id="filterBright" min="-100" max="100" value="0" class="w-full h-1.5 bg-slate-200 rounded-lg appearance-none cursor-pointer">
187
                        </div>
188
                        <div>
189
                            <label class="flex justify-between text-xs text-slate-500 mb-1">
190
                                <span>āļ„āļ§āļēāļĄāđ€āļ›āļĢāļĩāļĒāļšāļ•āđˆāļēāļ‡</span> <span id="valContrast">0</span>
191
                            </label>
192
                            <input type="range" id="filterContrast" min="-100" max="100" value="0" class="w-full h-1.5 bg-slate-200 rounded-lg appearance-none cursor-pointer">
193
                        </div>
194
                        <div>
195
                            <label class="flex justify-between text-xs text-slate-500 mb-1">
196
                                <span>āļ„āļ§āļēāļĄāļ­āļīāđˆāļĄāļ•āļąāļ§āļŠāļĩ</span> <span id="valSaturate">0</span>
197
                            </label>
198
                            <input type="range" id="filterSaturate" min="-100" max="100" value="0" class="w-full h-1.5 bg-slate-200 rounded-lg appearance-none cursor-pointer">
199
                        </div>
200
                        <button id="resetFiltersBtn" class="text-xs text-indigo-600 hover:text-indigo-800">āļĢāļĩāđ€āļ‹āđ‡āļ•āļŸāļīāļĨāđ€āļ•āļ­āļĢāđŒ</button>
201
                    </div>
202
 
203
                    <hr class="border-slate-100 my-4">
204
 
205
                    <!-- Drawing -->
206
                    <div class="mb-5">
207
                        <label class="block text-sm font-medium text-slate-700 mb-2"><i class="fa-solid fa-pen mr-1"></i> āļ§āļēāļ”āđ€āļ‚āļĩāļĒāļ™āļ­āļīāļŠāļĢāļ°</label>
208
                        <div class="flex items-center space-x-3 mb-3">
209
                            <input type="color" id="brushColor" value="#ff0000" class="w-8 h-8 rounded cursor-pointer border-0 p-0">
210
                            <input type="range" id="brushSize" min="1" max="50" value="5" class="flex-1 h-1.5 bg-slate-200 rounded-lg appearance-none cursor-pointer">
211
                        </div>
212
                        <button id="toggleDrawBtn" class="w-full bg-slate-100 hover:bg-slate-200 text-slate-700 py-2 rounded-lg text-sm font-medium transition border border-slate-300">
213
                            <i class="fa-solid fa-pen-nib mr-1"></i> āđ€āļ›āļīāļ”āđ‚āļŦāļĄāļ”āļ§āļēāļ”āđ€āļ‚āļĩāļĒāļ™
214
                        </button>
215
                    </div>
216
 
217
                    <!-- Actions -->
218
                    <div class="flex flex-col space-y-2 mt-6">
219
                        <button id="downloadBtn" class="w-full bg-emerald-600 hover:bg-emerald-700 text-white font-medium py-2.5 px-4 rounded-lg transition flex justify-center items-center shadow-sm">
220
                            <i class="fa-solid fa-download mr-2"></i> āļ”āļēāļ§āļ™āđŒāđ‚āļŦāļĨāļ”āļœāļĨāļ‡āļēāļ™
221
                        </button>
222
                    </div>
223
                </div>
224
            </div>
225
 
226
            <!-- Right Column: Canvas Display (Fabric.js) -->
227
            <div class="lg:col-span-8 xl:col-span-9 flex flex-col">
228
                <!-- Toolbar hint -->
229
                <div class="bg-indigo-50 text-indigo-800 text-sm py-2 px-4 rounded-t-xl border border-indigo-100 flex justify-between">
230
                    <span><i class="fa-solid fa-circle-info mr-1"></i> āļ”āļąāļšāđ€āļšāļīāđ‰āļĨāļ„āļĨāļīāļāļ—āļĩāđˆāļ‚āđ‰āļ­āļ„āļ§āļēāļĄāđ€āļžāļ·āđˆāļ­āđāļāđ‰āđ„āļ‚ / āļĨāļēāļāđ€āļžāļ·āđˆāļ­āļĒāđ‰āļēāļĒāļ•āļģāđāļŦāļ™āđˆāļ‡</span>
231
                    <span id="canvasDimInfo" class="font-mono text-xs text-indigo-500"></span>
232
                </div>
233
                
234
                <div id="canvasWrapper" class="bg-slate-200 p-2 rounded-b-xl shadow-inner border border-slate-300 min-h-[500px] flex items-center justify-center overflow-auto flex-1 relative bg-[url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCI+CjxyZWN0IHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0iI2ZmZmZmZiIvPgo8cmVjdCB3aWR0aD0iMTAiIGhlaWdodD0iMTAiIGZpbGw9IiNmM2Y0ZjYiLz4KPHJlY3QgeD0iMTAiIHk9IjEwIiB3aWR0aD0iMTAiIGhlaWdodD0iMTAiIGZpbGw9IiNmM2Y0ZjYiLz4KPC9zdmc+')]">
235
                    
236
                    <!-- Placeholder text before upload -->
237
                    <div id="canvasPlaceholder" class="text-slate-400 text-center pointer-events-none absolute z-10">
238
                        <i class="fa-regular fa-images text-6xl mb-3 opacity-50"></i>
239
                        <p>āļ­āļąāļ›āđ‚āļŦāļĨāļ”āļ āļēāļžāļŦāļĨāļąāļāđ€āļžāļ·āđˆāļ­āđ€āļĢāļīāđˆāļĄāļŠāļĢāđ‰āļēāļ‡āļŠāļīāđ‰āļ™āļ‡āļēāļ™</p>
240
                    </div>
241
 
242
                    <!-- Fabric Canvas Canvas Element -->
243
                    <canvas id="mainCanvas"></canvas>
244
                </div>
245
            </div>
246
            
247
        </div>
248
    </div>
249
 
250
    <script>
251
        // --- Fabric.js Initialization ---
252
        const canvas = new fabric.Canvas('mainCanvas', {
253
            isDrawingMode: false,
254
            preserveObjectStacking: true // Keep objects in order when selected
255
        });
256
        
257
        let baseImage = null; // The background image uploaded first
258
 
259
        // --- DOM Elements ---
260
        const imageUpload = document.getElementById('imageUpload');
261
        const detectionPanel = document.getElementById('detectionPanel');
262
        const editorPanel = document.getElementById('editorPanel');
263
        const canvasPlaceholder = document.getElementById('canvasPlaceholder');
264
        const canvasDimInfo = document.getElementById('canvasDimInfo');
265
 
266
        // Layers & Objects controls
267
        const addTextBtn = document.getElementById('addTextBtn');
268
        const addLayerImage = document.getElementById('addLayerImage');
269
        const addRectBtn = document.getElementById('addRectBtn');
270
        const addCircleBtn = document.getElementById('addCircleBtn');
271
        const magicTextBtn = document.getElementById('magicTextBtn');
272
        const objectControls = document.getElementById('objectControls');
273
        const objColorPicker = document.getElementById('objColorPicker');
274
        const bringForwardBtn = document.getElementById('bringForwardBtn');
275
        const sendBackwardBtn = document.getElementById('sendBackwardBtn');
276
        const deleteObjBtn = document.getElementById('deleteObjBtn');
277
        const textControls = document.getElementById('textControls');
278
        const fontFamilySelect = document.getElementById('fontFamilySelect');
279
        const fontSizeInput = document.getElementById('fontSizeInput');
280
        const textColorPicker = document.getElementById('textColorPicker');
281
        const textBoldBtn = document.getElementById('textBoldBtn');
282
 
283
        // Filter Controls
284
        const filterBright = document.getElementById('filterBright');
285
        const filterContrast = document.getElementById('filterContrast');
286
        const filterSaturate = document.getElementById('filterSaturate');
287
        const resetFiltersBtn = document.getElementById('resetFiltersBtn');
288
 
289
        // Drawing Controls
290
        const toggleDrawBtn = document.getElementById('toggleDrawBtn');
291
        const brushColor = document.getElementById('brushColor');
292
        const brushSize = document.getElementById('brushSize');
293
 
294
        // Action
295
        const downloadBtn = document.getElementById('downloadBtn');
296
 
297
        // Magic Text Variables
298
        let isMagicTextMode = false;
299
        let magicRect = null;
300
        let origX, origY;
301
 
302
        // --- 1. Load Main Image ---
303
        imageUpload.addEventListener('change', function(e) {
304
            const file = e.target.files[0];
305
            if (!file) return;
306
 
307
            const reader = new FileReader();
308
            reader.onload = function(event) {
309
                // Remove placeholder
310
                canvasPlaceholder.classList.add('hidden');
311
                
312
                fabric.Image.fromURL(event.target.result, function(img) {
313
                    // Set canvas dimensions
314
                    // Limit max width to prevent extremely large canvases in browser, scale proportionally
315
                    const MAX_WIDTH = 1000; 
316
                    let scale = 1;
317
                    if (img.width > MAX_WIDTH) {
318
                        scale = MAX_WIDTH / img.width;
319
                    }
320
                    
321
                    const finalWidth = img.width * scale;
322
                    const finalHeight = img.height * scale;
323
 
324
                    canvas.setWidth(finalWidth);
325
                    canvas.setHeight(finalHeight);
326
                    
327
                    // Scale image
328
                    img.scale(scale);
329
                    
330
                    // Set as background image so it acts as the base canvas
331
                    canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas));
332
                    baseImage = img; // Store reference for filters
333
 
334
                    canvasDimInfo.innerText = `${Math.round(finalWidth)} x ${Math.round(finalHeight)} px`;
335
 
336
                    // Trigger fake detection
337
                    startDetectionSimulation();
338
                });
339
            }
340
            reader.readAsDataURL(file);
341
        });
342
 
343
        // --- 2. Element / Layer Additions (Canva style) ---
344
        addTextBtn.addEventListener('click', () => {
345
            const text = new fabric.IText('āļ‚āđ‰āļ­āļ„āļ§āļēāļĄāđƒāļŦāļĄāđˆ', {
346
                left: canvas.width / 2,
347
                top: canvas.height / 2,
348
                originX: 'center',
349
                originY: 'center',
350
                fontFamily: 'sans-serif',
351
                fill: '#333333',
352
                fontSize: 40,
353
                fontWeight: 'bold',
354
                transparentCorners: false,
355
                cornerColor: 'blue',
356
                cornerSize: 10
357
            });
358
            canvas.add(text);
359
            canvas.setActiveObject(text);
360
        });
361
 
362
        addRectBtn.addEventListener('click', () => {
363
            const rect = new fabric.Rect({
364
                left: canvas.width / 2,
365
                top: canvas.height / 2,
366
                originX: 'center',
367
                originY: 'center',
368
                fill: '#4f46e5',
369
                width: 100,
370
                height: 100,
371
                rx: 10,
372
                ry: 10,
373
                transparentCorners: false,
374
                cornerColor: 'blue',
375
                cornerSize: 10
376
            });
377
            canvas.add(rect);
378
            canvas.setActiveObject(rect);
379
        });
380
 
381
        addCircleBtn.addEventListener('click', () => {
382
            const circle = new fabric.Circle({
383
                left: canvas.width / 2,
384
                top: canvas.height / 2,
385
                originX: 'center',
386
                originY: 'center',
387
                fill: '#10b981',
388
                radius: 50,
389
                transparentCorners: false,
390
                cornerColor: 'blue',
391
                cornerSize: 10
392
            });
393
            canvas.add(circle);
394
            canvas.setActiveObject(circle);
395
        });
396
 
397
        addLayerImage.addEventListener('change', function(e) {
398
            const file = e.target.files[0];
399
            if (!file) return;
400
            const reader = new FileReader();
401
            reader.onload = function(event) {
402
                fabric.Image.fromURL(event.target.result, function(img) {
403
                    // scale down if it's too big for the canvas
404
                    if(img.width > canvas.width / 2) {
405
                        img.scaleToWidth(canvas.width / 2);
406
                    }
407
                    img.set({
408
                        left: canvas.width / 2,
409
                        top: canvas.height / 2,
410
                        originX: 'center',
411
                        originY: 'center',
412
                        transparentCorners: false,
413
                        cornerColor: 'blue',
414
                        cornerSize: 10
415
                    });
416
                    canvas.add(img);
417
                    canvas.setActiveObject(img);
418
                });
419
            }
420
            reader.readAsDataURL(file);
421
            this.value = ''; // Reset input
422
        });
423
 
424
        // --- 3. Manage Object State (Enable/Disable tools) ---
425
        function updateObjectControls() {
426
            const activeObj = canvas.getActiveObject();
427
            if (activeObj) {
428
                // Enable layer tools
429
                objectControls.classList.remove('opacity-50', 'pointer-events-none');
430
                
431
                // Show/hide text controls
432
                if (activeObj.type === 'i-text' || activeObj.type === 'text') {
433
                    textControls.classList.remove('hidden');
434
                    fontFamilySelect.value = activeObj.fontFamily || 'sans-serif';
435
                    fontSizeInput.value = activeObj.fontSize || 40;
436
                    
437
                    // Update bold button visual state
438
                    if (activeObj.fontWeight === 'bold') {
439
                        textBoldBtn.classList.replace('bg-white', 'bg-indigo-100');
440
                        textBoldBtn.classList.replace('border-indigo-200', 'border-indigo-400');
441
                    } else {
442
                        textBoldBtn.classList.replace('bg-indigo-100', 'bg-white');
443
                        textBoldBtn.classList.replace('border-indigo-400', 'border-indigo-200');
444
                    }
445
 
446
                    // Update text color picker
447
                    if (activeObj.fill && typeof activeObj.fill === 'string') {
448
                        if (activeObj.fill.startsWith('#')) {
449
                            textColorPicker.value = activeObj.fill.substring(0, 7);
450
                        } else if (activeObj.fill.startsWith('rgb')) {
451
                           const rgb = activeObj.fill.match(/\d+/g);
452
                           if(rgb && rgb.length >= 3) {
453
                               const hex = "#" + (1 << 24 | rgb[0] << 16 | rgb[1] << 8 | rgb[2]).toString(16).slice(1);
454
                               textColorPicker.value = hex;
455
                           }
456
                        }
457
                    }
458
                } else {
459
                    textControls.classList.add('hidden');
460
                }
461
 
462
                // Update filter sliders if an image is selected
463
                if (activeObj.type === 'image') {
464
                    updateFilterSlidersFromObject(activeObj);
465
                    objColorPicker.classList.add('hidden');
466
                } else {
467
                    // Show color picker for text and shapes
468
                    objColorPicker.classList.remove('hidden');
469
                    if (activeObj.fill && typeof activeObj.fill === 'string') {
470
                        if (activeObj.fill.startsWith('#')) {
471
                            objColorPicker.value = activeObj.fill.substring(0, 7);
472
                        } else if (activeObj.fill.startsWith('rgb')) {
473
                           const rgb = activeObj.fill.match(/\d+/g);
474
                           if(rgb && rgb.length >= 3) {
475
                               const hex = "#" + (1 << 24 | rgb[0] << 16 | rgb[1] << 8 | rgb[2]).toString(16).slice(1);
476
                               objColorPicker.value = hex;
477
                           }
478
                        }
479
                    }
480
                }
481
            } else {
482
                // Disable layer tools
483
                objectControls.classList.add('opacity-50', 'pointer-events-none');
484
                objColorPicker.classList.add('hidden');
485
                textControls.classList.add('hidden');
486
                
487
                // If nothing selected, show filters of the background image
488
                if (baseImage) {
489
                    updateFilterSlidersFromObject(baseImage);
490
                }
491
            }
492
        }
493
 
494
        canvas.on('selection:created', updateObjectControls);
495
        canvas.on('selection:updated', updateObjectControls);
496
        canvas.on('selection:cleared', updateObjectControls);
497
 
498
        objColorPicker.addEventListener('input', (e) => {
499
            const activeObj = canvas.getActiveObject();
500
            if (activeObj) {
501
                activeObj.set('fill', e.target.value);
502
                canvas.renderAll();
503
            }
504
        });
505
 
506
        deleteObjBtn.addEventListener('click', () => {
507
            const activeObjects = canvas.getActiveObjects();
508
            if (activeObjects.length) {
509
                activeObjects.forEach(obj => canvas.remove(obj));
510
                canvas.discardActiveObject();
511
            }
512
        });
513
 
514
        fontFamilySelect.addEventListener('change', (e) => {
515
            const activeObj = canvas.getActiveObject();
516
            if (activeObj && (activeObj.type === 'i-text' || activeObj.type === 'text')) {
517
                activeObj.set('fontFamily', e.target.value);
518
                canvas.renderAll();
519
            }
520
        });
521
 
522
        fontSizeInput.addEventListener('input', (e) => {
523
            const activeObj = canvas.getActiveObject();
524
            if (activeObj && (activeObj.type === 'i-text' || activeObj.type === 'text')) {
525
                const size = parseInt(e.target.value, 10);
526
                if (!isNaN(size) && size > 0) {
527
                    activeObj.set('fontSize', size);
528
                    canvas.renderAll();
529
                }
530
            }
531
        });
532
 
533
        textColorPicker.addEventListener('input', (e) => {
534
            const activeObj = canvas.getActiveObject();
535
            if (activeObj && (activeObj.type === 'i-text' || activeObj.type === 'text')) {
536
                activeObj.set('fill', e.target.value);
537
                canvas.renderAll();
538
                // āļ­āļąāļ›āđ€āļ”āļ•āļāļĨāđˆāļ­āļ‡āļŠāļĩāļŦāļĨāļąāļāđƒāļŦāđ‰āļ•āļĢāļ‡āļāļąāļ™āļ”āđ‰āļ§āļĒ
539
                objColorPicker.value = e.target.value;
540
            }
541
        });
542
 
543
        textBoldBtn.addEventListener('click', () => {
544
            const activeObj = canvas.getActiveObject();
545
            if (activeObj && (activeObj.type === 'i-text' || activeObj.type === 'text')) {
546
                const isBold = activeObj.fontWeight === 'bold';
547
                activeObj.set('fontWeight', isBold ? 'normal' : 'bold');
548
                canvas.renderAll();
549
                updateObjectControls(); // āļ­āļąāļ›āđ€āļ”āļ•āļŠāļ–āļēāļ™āļ°āļ›āļļāđˆāļĄāļ•āļąāļ§āļŦāļ™āļēāļ—āļąāļ™āļ—āļĩ
550
            }
551
        });
552
 
553
        bringForwardBtn.addEventListener('click', () => {
554
            const activeObj = canvas.getActiveObject();
555
            if (activeObj) canvas.bringForward(activeObj);
556
        });
557
 
558
        sendBackwardBtn.addEventListener('click', () => {
559
            const activeObj = canvas.getActiveObject();
560
            if (activeObj) canvas.sendBackwards(activeObj);
561
        });
562
 
563
        // --- 3.5 Magic Text Editor (Masking Old Text & Replace) ---
564
        magicTextBtn.addEventListener('click', () => {
565
            isMagicTextMode = true;
566
            canvas.isDrawingMode = false;
567
            canvas.defaultCursor = 'crosshair';
568
            canvas.discardActiveObject();
569
            canvas.renderAll();
570
            
571
            // Highlight button to show it's active
572
            magicTextBtn.classList.replace('from-purple-500', 'from-pink-500');
573
            magicTextBtn.classList.replace('to-indigo-500', 'to-rose-500');
574
            magicTextBtn.innerHTML = '<i class="fa-solid fa-check mr-1"></i> āļĨāļēāļāļ„āļĨāļļāļĄāļ‚āđ‰āļ­āļ„āļ§āļēāļĄāļšāļ™āļ āļēāļžāđ€āļĨāļĒ...';
575
        });
576
 
577
        canvas.on('mouse:down', function(o) {
578
            if (!isMagicTextMode) return;
579
            var pointer = canvas.getPointer(o.e);
580
            origX = pointer.x;
581
            origY = pointer.y;
582
            
583
            magicRect = new fabric.Rect({
584
                left: origX,
585
                top: origY,
586
                width: 0,
587
                height: 0,
588
                fill: 'rgba(236, 72, 153, 0.3)', // Pinkish selection box
589
                stroke: '#ec4899',
590
                strokeWidth: 2,
591
                selectable: false
592
            });
593
            canvas.add(magicRect);
594
        });
595
 
596
        canvas.on('mouse:move', function(o) {
597
            if (!isMagicTextMode || !magicRect) return;
598
            var pointer = canvas.getPointer(o.e);
599
            
600
            if (origX > pointer.x) {
601
                magicRect.set({ left: Math.abs(pointer.x) });
602
            }
603
            if (origY > pointer.y) {
604
                magicRect.set({ top: Math.abs(pointer.y) });
605
            }
606
            
607
            magicRect.set({ width: Math.abs(origX - pointer.x) });
608
            magicRect.set({ height: Math.abs(origY - pointer.y) });
609
            canvas.renderAll();
610
        });
611
 
612
        canvas.on('mouse:up', function(o) {
613
            if (!isMagicTextMode || !magicRect) return;
614
 
615
            // Ensure selection is big enough
616
            if (magicRect.width < 10 || magicRect.height < 10) {
617
                canvas.remove(magicRect);
618
                resetMagicMode();
619
                return;
620
            }
621
 
622
            // 1. Hide selection box temporarily to read actual background pixels
623
            magicRect.set('visible', false);
624
            canvas.renderAll();
625
            
626
            // 2. Read background color from the Top-Left of the selection
627
            const ctx = canvas.getContext('2d');
628
            const multiplier = canvas.getRetinaScaling();
629
            const pixel = ctx.getImageData(magicRect.left * multiplier, magicRect.top * multiplier, 1, 1).data;
630
            const bgColor = `rgb(${pixel[0]}, ${pixel[1]}, ${pixel[2]})`;
631
            
632
            // 3. Make the box visible again, filled with background color to "Erase" old text
633
            magicRect.set({
634
                visible: true,
635
                fill: bgColor,
636
                strokeWidth: 0,
637
                selectable: true // allow user to resize mask later if needed
638
            });
639
 
640
            // 4. Create new editable text over the erased area
641
            const text = new fabric.IText('āļ‚āđ‰āļ­āļ„āļ§āļēāļĄāđƒāļŦāļĄāđˆ', {
642
                left: magicRect.left + (magicRect.width * 0.05),
643
                top: magicRect.top + (magicRect.height * 0.1),
644
                fontFamily: 'sans-serif',
645
                fill: '#333333', // Default text color
646
                fontSize: Math.max(16, magicRect.height * 0.6),
647
                fontWeight: 'bold',
648
                transparentCorners: false,
649
                cornerColor: 'blue',
650
                cornerSize: 10
651
            });
652
            canvas.add(text);
653
            
654
            // 5. Select the new text and open edit mode automatically
655
            canvas.setActiveObject(text);
656
            text.enterEditing();
657
            text.selectAll();
658
 
659
            resetMagicMode();
660
        });
661
 
662
        function resetMagicMode() {
663
            isMagicTextMode = false;
664
            magicRect = null;
665
            canvas.defaultCursor = 'default';
666
            magicTextBtn.classList.replace('from-pink-500', 'from-purple-500');
667
            magicTextBtn.classList.replace('to-rose-500', 'to-indigo-500');
668
            magicTextBtn.innerHTML = '<i class="fa-solid fa-wand-magic-sparkles mr-1"></i> āđāļāđ‰āđ„āļ‚āļ‚āđ‰āļ­āļ„āļ§āļēāļĄāđ€āļ”āļīāļĄāļšāļ™āļ āļēāļž (Magic Edit)';
669
            canvas.renderAll();
670
        }
671
 
672
        // --- 4. Filters (Fabric Image Filters) ---
673
        // Range slider value is -100 to 100. Fabric expects -1 to 1.
674
        function applyImageFilters() {
675
            // Apply to active image object, or background baseImage if none selected
676
            const target = canvas.getActiveObject() && canvas.getActiveObject().type === 'image' 
677
                           ? canvas.getActiveObject() 
678
                           : baseImage;
679
            
680
            if (!target) return;
681
 
682
            document.getElementById('valBright').innerText = filterBright.value;
683
            document.getElementById('valContrast').innerText = filterContrast.value;
684
            document.getElementById('valSaturate').innerText = filterSaturate.value;
685
 
686
            // Fabric 5 filter API
687
            target.filters[0] = new fabric.Image.filters.Brightness({ brightness: parseFloat(filterBright.value) / 100 });
688
            target.filters[1] = new fabric.Image.filters.Contrast({ contrast: parseFloat(filterContrast.value) / 100 });
689
            target.filters[2] = new fabric.Image.filters.Saturation({ saturation: parseFloat(filterSaturate.value) / 100 });
690
            
691
            target.applyFilters();
692
            canvas.renderAll();
693
        }
694
 
695
        function updateFilterSlidersFromObject(obj) {
696
            if (!obj.filters || obj.filters.length === 0) {
697
                filterBright.value = 0; filterContrast.value = 0; filterSaturate.value = 0;
698
            } else {
699
                filterBright.value = (obj.filters[0] && obj.filters[0].brightness) ? Math.round(obj.filters[0].brightness * 100) : 0;
700
                filterContrast.value = (obj.filters[1] && obj.filters[1].contrast) ? Math.round(obj.filters[1].contrast * 100) : 0;
701
                filterSaturate.value = (obj.filters[2] && obj.filters[2].saturation) ? Math.round(obj.filters[2].saturation * 100) : 0;
702
            }
703
            document.getElementById('valBright').innerText = filterBright.value;
704
            document.getElementById('valContrast').innerText = filterContrast.value;
705
            document.getElementById('valSaturate').innerText = filterSaturate.value;
706
        }
707
 
708
        filterBright.addEventListener('input', applyImageFilters);
709
        filterContrast.addEventListener('input', applyImageFilters);
710
        filterSaturate.addEventListener('input', applyImageFilters);
711
 
712
        resetFiltersBtn.addEventListener('click', () => {
713
            filterBright.value = 0; filterContrast.value = 0; filterSaturate.value = 0;
714
            applyImageFilters();
715
        });
716
 
717
        // --- 5. Free Drawing ---
718
        // Setup brush
719
        canvas.freeDrawingBrush = new fabric.PencilBrush(canvas);
720
        canvas.freeDrawingBrush.color = brushColor.value;
721
        canvas.freeDrawingBrush.width = parseInt(brushSize.value, 10) || 5;
722
 
723
        brushColor.addEventListener('change', (e) => {
724
            canvas.freeDrawingBrush.color = e.target.value;
725
        });
726
 
727
        brushSize.addEventListener('input', (e) => {
728
            canvas.freeDrawingBrush.width = parseInt(e.target.value, 10);
729
        });
730
 
731
        toggleDrawBtn.addEventListener('click', () => {
732
            canvas.isDrawingMode = !canvas.isDrawingMode;
733
            if (canvas.isDrawingMode) {
734
                toggleDrawBtn.classList.replace('bg-slate-100', 'bg-indigo-600');
735
                toggleDrawBtn.classList.replace('text-slate-700', 'text-white');
736
                canvas.discardActiveObject();
737
                canvas.requestRenderAll();
738
            } else {
739
                toggleDrawBtn.classList.replace('bg-indigo-600', 'bg-slate-100');
740
                toggleDrawBtn.classList.replace('text-white', 'text-slate-700');
741
            }
742
        });
743
 
744
        // --- 6. Download ---
745
        downloadBtn.addEventListener('click', () => {
746
            // Unselect everything before export so bounding boxes aren't visible
747
            canvas.discardActiveObject();
748
            canvas.renderAll();
749
            
750
            const link = document.createElement('a');
751
            link.download = 'ai-canvas-edited.png';
752
            link.href = canvas.toDataURL({ format: 'png', quality: 1 });
753
            link.click();
754
        });
755
 
756
        // --- 7. Detection Simulation ---
757
        const startEditBtn = document.getElementById('startEditBtn');
758
        startEditBtn.addEventListener('click', () => {
759
            detectionPanel.classList.add('hidden');
760
            editorPanel.classList.remove('hidden');
761
        });
762
 
763
        function startDetectionSimulation() {
764
            editorPanel.classList.add('hidden');
765
            detectionPanel.classList.remove('hidden');
766
            document.getElementById('detectionLoading').classList.remove('hidden');
767
            document.getElementById('detectionResult').classList.add('hidden');
768
            
769
            const loadingBar = document.getElementById('loadingBar');
770
            const loadingText = document.getElementById('loadingText');
771
            loadingBar.style.width = '0%';
772
            
773
            setTimeout(() => { loadingBar.style.width = '30%'; loadingText.innerText = 'āļ•āļĢāļ§āļˆāļŠāļ­āļš Noise Pattern...'; }, 800);
774
            setTimeout(() => { loadingBar.style.width = '60%'; loadingText.innerText = 'āļ§āļīāđ€āļ„āļĢāļēāļ°āļŦāđŒāļ‚āļ­āļšāđ€āļ‚āļ•āđ€āļĨāđ€āļĒāļ­āļĢāđŒ (Edge Analysis)...'; }, 1600);
775
            setTimeout(() => { loadingBar.style.width = '90%'; loadingText.innerText = 'āļ›āļĢāļ°āļĄāļ§āļĨāļœāļĨāļœāļĨāļĨāļąāļžāļ˜āđŒ...'; }, 2400);
776
            
777
            setTimeout(() => {
778
                showDetectionResult();
779
            }, 3000);
780
        }
781
 
782
        function showDetectionResult() {
783
            document.getElementById('detectionLoading').classList.add('hidden');
784
            document.getElementById('detectionResult').classList.remove('hidden');
785
            
786
            const isLikelyAI = Math.random() > 0.4;
787
            const resultIcon = document.getElementById('resultIcon');
788
            const resultTitle = document.getElementById('resultTitle');
789
            const resultDesc = document.getElementById('resultDesc');
790
            const scoreAi = document.getElementById('scoreAi');
791
            const scoreNoise = document.getElementById('scoreNoise');
792
 
793
            if (isLikelyAI) {
794
                resultIcon.innerHTML = '<i class="fa-solid fa-robot text-orange-500"></i>';
795
                resultTitle.innerText = 'āđ‚āļ­āļāļēāļŠāļŠāļđāļ‡āļ—āļĩāđˆāđ€āļ›āđ‡āļ™āļ āļēāļžāļŠāļĢāđ‰āļēāļ‡āļˆāļēāļ AI';
796
                resultTitle.className = 'text-lg font-bold mb-1 text-orange-600';
797
                resultDesc.innerText = 'āļžāļšāļĢāđˆāļ­āļ‡āļĢāļ­āļĒāļāļēāļĢāļāļĢāļ°āļˆāļēāļĒāļžāļīāļāđ€āļ‹āļĨāļœāļīāļ”āļ›āļāļ•āļī (Generative Artifacts)';
798
                scoreAi.innerText = (85 + Math.floor(Math.random() * 14)) + '%';
799
                scoreAi.className = 'font-semibold text-orange-600';
800
                scoreNoise.innerText = 'āļŠāļąāļ‡āđ€āļ„āļĢāļēāļ°āļŦāđŒ (Synthetic)';
801
            } else {
802
                resultIcon.innerHTML = '<i class="fa-solid fa-camera text-emerald-500"></i>';
803
                resultTitle.innerText = 'āļ™āđˆāļēāļˆāļ°āđ€āļ›āđ‡āļ™āļ āļēāļžāļ–āđˆāļēāļĒāļˆāļĢāļīāļ‡';
804
                resultTitle.className = 'text-lg font-bold mb-1 text-emerald-600';
805
                resultDesc.innerText = 'āđ„āļĄāđˆāļžāļšāļĢāđˆāļ­āļ‡āļĢāļ­āļĒāļāļēāļĢāļŠāļąāļ‡āđ€āļ„āļĢāļēāļ°āļŦāđŒāļ‚āļ­āļ‡ AI āđƒāļ™āļĢāļ°āļ”āļąāļšāļ—āļĩāđˆāļœāļīāļ”āļŠāļąāļ‡āđ€āļāļ•';
806
                scoreAi.innerText = (2 + Math.floor(Math.random() * 20)) + '%';
807
                scoreAi.className = 'font-semibold text-emerald-600';
808
                scoreNoise.innerText = 'āļ›āļāļ•āļī (Natural)';
809
            }
810
        }
811
    </script>
812
</body>
813
</html>

Paste Info

ID
ahJFUb
Type
Code Paste
Size
42.0 KB
Lines
813
Views
21
Created
23h ago

Share This Paste

\n \n \n \n \n \n \n\n\n\n
\n \n \n
\n

\n AI Image Detector & Editor\n

\n

āļ•āļĢāļ§āļˆāļŠāļ­āļšāļ āļēāļž AI āđāļĨāļ°āļĢāļ°āļšāļšāđāļāđ‰āđ„āļ‚āļ āļēāļžāđāļšāļšāđ€āļĨāđ€āļĒāļ­āļĢāđŒ (Canva Style)

\n
\n\n \n
\n \n \n
\n \n \n
\n

1. āļ āļēāļžāļŦāļĨāļąāļ (Background)

\n \n
\n\n \n
\n

2. āļœāļĨāļāļēāļĢāļ§āļīāđ€āļ„āļĢāļēāļ°āļŦāđŒāļ āļēāļž

\n \n
\n \n

āļāļģāļĨāļąāļ‡āļ•āļĢāļ§āļˆāļŠāļ­āļš Metadata...

\n
\n
\n
\n
\n\n
\n
\n

\n

\n \n
\n
āđ‚āļ­āļāļēāļŠāđ€āļ›āđ‡āļ™āļ āļēāļž AI:
\n
Noise Pattern:
\n
\n \n \n
\n
\n\n \n \n
\n\n \n
\n \n
\n āļ”āļąāļšāđ€āļšāļīāđ‰āļĨāļ„āļĨāļīāļāļ—āļĩāđˆāļ‚āđ‰āļ­āļ„āļ§āļēāļĄāđ€āļžāļ·āđˆāļ­āđāļāđ‰āđ„āļ‚ / āļĨāļēāļāđ€āļžāļ·āđˆāļ­āļĒāđ‰āļēāļĒāļ•āļģāđāļŦāļ™āđˆāļ‡\n \n
\n \n
\n \n \n
\n \n

āļ­āļąāļ›āđ‚āļŦāļĨāļ”āļ āļēāļžāļŦāļĨāļąāļāđ€āļžāļ·āđˆāļ­āđ€āļĢāļīāđˆāļĄāļŠāļĢāđ‰āļēāļ‡āļŠāļīāđ‰āļ™āļ‡āļēāļ™

\n
\n\n \n \n
\n
\n \n
\n
\n\n \n\n"; const PASTE_SHORT_ID = 'ahJFUb'; const PASTE_TITLE = "Untitled Paste";