🌐 html public

Untitled Paste

Guest 34m ago 7 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
7
Created
34m 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";