| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>AI Adult Content Creator | OnlyFans Toolkit</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| <script src="https://cdn.jsdelivr.net/npm/face-api.js"></script> |
| <style> |
| .editor-container { |
| background: linear-gradient(135deg, #2b2d42 0%, #1a1a2e 100%); |
| } |
| .tool-btn { |
| transition: all 0.3s ease; |
| } |
| .tool-btn:hover { |
| transform: translateY(-3px); |
| box-shadow: 0 10px 20px rgba(255, 20, 147, 0.3); |
| } |
| .preview-box { |
| box-shadow: 0 20px 25px -5px rgba(0,0,0,0.3), 0 10px 10px -5px rgba(0,0,0,0.1); |
| } |
| .slider-thumb::-webkit-slider-thumb { |
| -webkit-appearance: none; |
| appearance: none; |
| width: 20px; |
| height: 20px; |
| border-radius: 50%; |
| background: #ff1493; |
| cursor: pointer; |
| } |
| .tab-active { |
| border-bottom: 3px solid #ff1493; |
| } |
| .image-thumbnail { |
| transition: all 0.2s ease; |
| } |
| .image-thumbnail:hover { |
| transform: scale(1.05); |
| box-shadow: 0 4px 6px rgba(255, 20, 147, 0.3); |
| } |
| .image-thumbnail.active { |
| border: 2px solid #ff1493; |
| } |
| .prompt-box { |
| min-height: 100px; |
| resize: vertical; |
| } |
| .pose-preview { |
| background-size: contain; |
| background-repeat: no-repeat; |
| background-position: center; |
| } |
| .processing-overlay { |
| position: absolute; |
| top: 0; |
| left: 0; |
| right: 0; |
| bottom: 0; |
| background: rgba(0,0,0,0.8); |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| justify-content: center; |
| color: white; |
| z-index: 10; |
| } |
| .face-landmarks { |
| position: absolute; |
| width: 20px; |
| height: 20px; |
| background: rgba(255, 20, 147, 0.7); |
| border-radius: 50%; |
| transform: translate(-50%, -50%); |
| } |
| .selection-box { |
| position: absolute; |
| border: 2px dashed #ff1493; |
| background: rgba(255, 20, 147, 0.2); |
| z-index: 5; |
| } |
| .predictive-options { |
| position: absolute; |
| background: #2b2d42; |
| border-radius: 4px; |
| box-shadow: 0 2px 10px rgba(0,0,0,0.3); |
| z-index: 20; |
| padding: 5px; |
| border: 1px solid #ff1493; |
| } |
| .predictive-option { |
| padding: 8px 12px; |
| cursor: pointer; |
| border-radius: 3px; |
| color: white; |
| } |
| .predictive-option:hover { |
| background: #ff1493; |
| } |
| .effect-thumb { |
| background-size: cover; |
| background-position: center; |
| } |
| .nsfw-badge { |
| position: absolute; |
| top: 10px; |
| right: 10px; |
| background: #ff1493; |
| color: white; |
| padding: 2px 8px; |
| border-radius: 12px; |
| font-size: 10px; |
| font-weight: bold; |
| } |
| .category-tag { |
| display: inline-block; |
| background: rgba(255, 20, 147, 0.2); |
| color: #ff1493; |
| padding: 2px 8px; |
| border-radius: 12px; |
| font-size: 12px; |
| margin-right: 5px; |
| margin-bottom: 5px; |
| } |
| .face-detection-box { |
| position: absolute; |
| border: 2px solid #00ff00; |
| background: rgba(0, 255, 0, 0.1); |
| z-index: 5; |
| } |
| .face-swap-preview { |
| position: relative; |
| overflow: hidden; |
| } |
| .face-swap-canvas { |
| position: absolute; |
| top: 0; |
| left: 0; |
| } |
| </style> |
| </head> |
| <body class="bg-gray-900 text-gray-100"> |
| |
| <header class="bg-gray-800 shadow-sm"> |
| <div class="container mx-auto px-4 py-4 flex justify-between items-center"> |
| <div class="flex items-center space-x-2"> |
| <i class="fas fa-venus-mars text-pink-600 text-2xl"></i> |
| <h1 class="text-xl font-bold">AI Adult Content Creator</h1> |
| </div> |
| <nav class="hidden md:flex space-x-8"> |
| <a href="#" class="text-gray-400 hover:text-pink-500 font-medium">Dashboard</a> |
| <a href="#" class="text-gray-400 hover:text-pink-500 font-medium">Templates</a> |
| <a href="#" class="text-gray-400 hover:text-pink-500 font-medium">Analytics</a> |
| <a href="#" class="text-gray-400 hover:text-pink-500 font-medium">Monetization</a> |
| </nav> |
| <div class="flex items-center space-x-4"> |
| <button class="px-4 py-2 rounded-md text-gray-400 hover:bg-gray-700"> |
| <i class="fas fa-bell text-xl"></i> |
| </button> |
| <button class="px-4 py-2 bg-pink-600 text-white rounded-md hover:bg-pink-700"> |
| <i class="fas fa-rocket mr-2"></i> Premium |
| </button> |
| </div> |
| </div> |
| </header> |
|
|
| |
| <main class="container mx-auto px-4 py-8"> |
| <div class="flex flex-col lg:flex-row gap-8"> |
| |
| <div class="w-full lg:w-1/4 bg-gray-800 rounded-xl shadow-md p-6 h-fit"> |
| <div class="flex border-b border-gray-700 mb-6"> |
| <button id="image-tab" class="tab-active px-4 py-2 font-medium text-pink-500">Photo</button> |
| <button id="video-tab" class="px-4 py-2 font-medium text-gray-400 hover:text-pink-500">Video</button> |
| </div> |
|
|
| <div id="image-tools"> |
| |
| <div class="mb-6"> |
| <h3 class="font-medium text-gray-300 mb-3">Upload Content</h3> |
| <div class="border-2 border-dashed border-gray-700 rounded-lg p-4 text-center cursor-pointer hover:bg-gray-700 mb-3" id="upload-area"> |
| <i class="fas fa-cloud-upload-alt text-3xl text-gray-500 mb-2"></i> |
| <p class="text-gray-400">Drag & drop NSFW content</p> |
| <p class="text-sm text-gray-500 mt-1">or click to browse</p> |
| <input type="file" id="file-upload" class="hidden" accept="image/*,video/*" multiple> |
| </div> |
| <div id="thumbnail-container" class="grid grid-cols-3 gap-2 mt-2 max-h-40 overflow-y-auto"></div> |
| </div> |
|
|
| |
| <div class="mb-6"> |
| <h3 class="font-medium text-gray-300 mb-3">AI Enhancement Prompts</h3> |
| <div class="relative"> |
| <textarea id="ai-prompt" class="w-full border border-gray-700 bg-gray-700 rounded-md p-2 text-sm prompt-box" placeholder="Describe your desired enhancements (e.g. 'make ass bigger', 'enhance curves', 'add toy')"></textarea> |
| <div class="absolute right-2 bottom-2 text-gray-400 text-xs"> |
| <span id="char-count">0</span>/200 |
| </div> |
| </div> |
| <div class="mt-2 grid grid-cols-2 gap-2"> |
| <button onclick="applyPrompt('Enhance curves, make ass bigger, smooth skin, perfect lighting')" class="px-2 py-1 bg-gray-700 text-xs rounded hover:bg-pink-600 hover:text-white">Body Enhance</button> |
| <button onclick="applyPrompt('Add realistic dildo, perfect lighting, professional look')" class="px-2 py-1 bg-gray-700 text-xs rounded hover:bg-pink-600 hover:text-white">Add Toy</button> |
| <button onclick="showFaceSwapModal()" class="px-2 py-1 bg-gray-700 text-xs rounded hover:bg-pink-600 hover:text-white">Face Swap</button> |
| <button onclick="applyPrompt('Smooth skin, remove blemishes, perfect lighting, professional retouch')" class="px-2 py-1 bg-gray-700 text-xs rounded hover:bg-pink-600 hover:text-white">Skin Perfect</button> |
| </div> |
| </div> |
|
|
| |
| <div class="mb-6"> |
| <h3 class="font-medium text-gray-300 mb-3">Content Categories</h3> |
| <div class="flex flex-wrap"> |
| <span class="category-tag cursor-pointer" onclick="applyPrompt('Solo female, teasing, implied nudity, perfect lighting')">Solo Tease</span> |
| <span class="category-tag cursor-pointer" onclick="applyPrompt('Explicit solo, legs spread, close-up, wet look')">Explicit Solo</span> |
| <span class="category-tag cursor-pointer" onclick="applyPrompt('Butt plug, anal play, bent over, high resolution')">Anal Play</span> |
| <span class="category-tag cursor-pointer" onclick="applyPrompt('Dildo play, penetration, wet look, professional lighting')">Toy Play</span> |
| <span class="category-tag cursor-pointer" onclick="applyPrompt('Lingerie, stockings, high heels, seductive pose')">Lingerie</span> |
| <span class="category-tag cursor-pointer" onclick="applyPrompt('Outdoor, risky, public flash, natural lighting')">Outdoor</span> |
| <span class="category-tag cursor-pointer" onclick="applyPrompt('BDSM, restraints, domination, professional setup')">BDSM</span> |
| <span class="category-tag cursor-pointer" onclick="applyPrompt('Cosplay, fantasy, roleplay, perfect costume')">Cosplay</span> |
| </div> |
| </div> |
|
|
| |
| <div class="mb-6"> |
| <h3 class="font-medium text-gray-300 mb-3">Body Enhancements</h3> |
| <div class="space-y-4"> |
| <div> |
| <label class="block text-sm text-gray-400 mb-1">Breast Size <span class="text-pink-500" id="breast-value">0%</span></label> |
| <input type="range" class="w-full slider-thumb" id="breast-slider" min="-30" max="50" value="0" oninput="updateBodyParam('breast', this.value)"> |
| <div class="flex justify-between text-xs text-gray-500"> |
| <span>Smaller</span> |
| <span>Larger</span> |
| </div> |
| </div> |
| <div> |
| <label class="block text-sm text-gray-400 mb-1">Ass Size <span class="text-pink-500" id="ass-value">0%</span></label> |
| <input type="range" class="w-full slider-thumb" id="ass-slider" min="-20" max="60" value="0" oninput="updateBodyParam('ass', this.value)"> |
| <div class="flex justify-between text-xs text-gray-500"> |
| <span>Smaller</span> |
| <span>Bubble</span> |
| </div> |
| </div> |
| <div> |
| <label class="block text-sm text-gray-400 mb-1">Waist Slimness <span class="text-pink-500" id="waist-value">0%</span></label> |
| <input type="range" class="w-full slider-thumb" id="waist-slider" min="-30" max="40" value="0" oninput="updateBodyParam('waist', this.value)"> |
| <div class="flex justify-between text-xs text-gray-500"> |
| <span>Thicker</span> |
| <span>Slimmer</span> |
| </div> |
| </div> |
| <div> |
| <label class="block text-sm text-gray-400 mb-1">Pussy Plumpness <span class="text-pink-500" id="pussy-value">0%</span></label> |
| <input type="range" class="w-full slider-thumb" id="pussy-slider" min="-20" max="40" value="0" oninput="updateBodyParam('pussy', this.value)"> |
| <div class="flex justify-between text-xs text-gray-500"> |
| <span>Less</span> |
| <span>More</span> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="mb-6"> |
| <h3 class="font-medium text-gray-300 mb-3">Toys & Props</h3> |
| <div class="grid grid-cols-3 gap-3"> |
| <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Add realistic pink dildo to scene, perfect lighting, professional look')"> |
| <i class="fas fa-dildo text-pink-500 text-xl mb-1"></i> |
| <span class="text-xs">Dildo</span> |
| </button> |
| <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Add jeweled butt plug, make it look realistic, perfect lighting')"> |
| <i class="fas fa-gem text-pink-500 text-xl mb-1"></i> |
| <span class="text-xs">Butt Plug</span> |
| </button> |
| <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Add vibrator to hand, make it look realistic, perfect lighting')"> |
| <i class="fas fa-vibrate text-pink-500 text-xl mb-1"></i> |
| <span class="text-xs">Vibrator</span> |
| </button> |
| <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Add realistic cum effect on body, perfect lighting, professional look')"> |
| <i class="fas fa-tint text-pink-500 text-xl mb-1"></i> |
| <span class="text-xs">Cum Effect</span> |
| </button> |
| <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Add rope bondage to wrists and ankles, realistic texture, perfect lighting')"> |
| <i class="fas fa-hands-bound text-pink-500 text-xl mb-1"></i> |
| <span class="text-xs">Bondage</span> |
| </button> |
| <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Add lace lingerie set, make it look realistic, perfect lighting')"> |
| <i class="fas fa-tshirt text-pink-500 text-xl mb-1"></i> |
| <span class="text-xs">Lingerie</span> |
| </button> |
| </div> |
| </div> |
|
|
| |
| <div class="mb-6"> |
| <h3 class="font-medium text-gray-300 mb-3">Pose Generator</h3> |
| <div class="grid grid-cols-3 gap-2 mb-3"> |
| <div class="pose-preview h-16 bg-gray-700 rounded cursor-pointer hover:ring-2 hover:ring-pink-500" onclick="applyPose('bent-over')" style="background-image: url('https://i.imgur.com/JQlE0gP.png')"></div> |
| <div class="pose-preview h-16 bg-gray-700 rounded cursor-pointer hover:ring-2 hover:ring-pink-500" onclick="applyPose('legs-spread')" style="background-image: url('https://i.imgur.com/5XkJQqG.png')"></div> |
| <div class="pose-preview h-16 bg-gray-700 rounded cursor-pointer hover:ring-2 hover:ring-pink-500" onclick="applyPose('doggy')" style="background-image: url('https://i.imgur.com/8zJqWQk.png')"></div> |
| <div class="pose-preview h-16 bg-gray-700 rounded cursor-pointer hover:ring-2 hover:ring-pink-500" onclick="applyPose('missionary')" style="background-image: url('https://i.imgur.com/3mJQkqG.png')"></div> |
| <div class="pose-preview h-16 bg-gray-700 rounded cursor-pointer hover:ring-2 hover:ring-pink-500" onclick="applyPose('squat')" style="background-image: url('https://i.imgur.com/7XkJQqG.png')"></div> |
| <div class="pose-preview h-16 bg-gray-700 rounded cursor-pointer hover:ring-2 hover:ring-pink-500" onclick="applyPose('standing-tease')" style="background-image: url('https://i.imgur.com/9zJqWQk.png')"></div> |
| </div> |
| <button class="w-full py-2 bg-pink-900 text-pink-300 rounded-md text-sm hover:bg-pink-700 hover:text-white" onclick="showCustomPoseModal()"> |
| <i class="fas fa-plus mr-1"></i> Custom Pose |
| </button> |
| </div> |
|
|
| |
| <div class="mb-6"> |
| <h3 class="font-medium text-gray-300 mb-3">Background</h3> |
| <div class="grid grid-cols-3 gap-3"> |
| <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Change background to luxury bedroom, perfect lighting, professional setup')"> |
| <i class="fas fa-bed text-pink-500 text-xl mb-1"></i> |
| <span class="text-xs">Bedroom</span> |
| </button> |
| <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Change background to hotel room, perfect lighting, professional setup')"> |
| <i class="fas fa-hotel text-pink-500 text-xl mb-1"></i> |
| <span class="text-xs">Hotel</span> |
| </button> |
| <button class="tool-btn flex flex-col items-center p-3 bg-gray-700 rounded-lg hover:bg-pink-600 hover:text-white" onclick="applyPrompt('Change background to outdoor pool, perfect lighting, professional setup')"> |
| <i class="fas fa-umbrella-beach text-pink-500 text-xl mb-1"></i> |
| <span class="text-xs">Outdoor</span> |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| <div id="video-tools" class="hidden"> |
| |
| <div class="text-center py-8 text-gray-500"> |
| <i class="fas fa-video text-3xl mb-2"></i> |
| <p>Video editing coming soon!</p> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="w-full lg:w-2/4 editor-container rounded-xl p-6"> |
| <div class="preview-box bg-gray-800 rounded-lg overflow-hidden relative" style="height: 600px;"> |
| <div class="absolute inset-0 flex items-center justify-center" id="placeholder"> |
| <div class="text-center"> |
| <i class="fas fa-image text-gray-600 text-5xl mb-3"></i> |
| <p class="text-gray-500">Upload NSFW content to start editing</p> |
| </div> |
| </div> |
| <div id="preview-container" class="relative w-full h-full hidden"> |
| <img id="preview-image" src="" alt="" class="w-full h-full object-contain"> |
| <video id="preview-video" controls class="hidden w-full h-full object-contain"></video> |
| <canvas id="face-swap-canvas" class="face-swap-canvas"></canvas> |
| </div> |
| <div id="processing-overlay" class="processing-overlay hidden"> |
| <i class="fas fa-spinner fa-spin text-4xl mb-4 text-pink-500"></i> |
| <p id="processing-text" class="text-xl">Processing your content...</p> |
| <div class="w-full bg-gray-700 rounded-full h-2.5 mt-4 max-w-md"> |
| <div id="progress-bar" class="bg-pink-500 h-2.5 rounded-full" style="width: 0%"></div> |
| </div> |
| <div id="ai-suggestions" class="mt-6 text-center max-w-md hidden"> |
| <h4 class="font-medium mb-2">AI Suggestions</h4> |
| <div class="grid grid-cols-2 gap-2"> |
| <button class="px-3 py-1 bg-pink-700 text-white rounded text-sm hover:bg-pink-600" onclick="applySuggestion('enhance-curves')">Enhance Curves</button> |
| <button class="px-3 py-1 bg-pink-700 text-white rounded text-sm hover:bg-pink-600" onclick="applySuggestion('add-toy')">Add Toy</button> |
| <button class="px-3 py-1 bg-pink-700 text-white rounded text-sm hover:bg-pink-600" onclick="applySuggestion('smooth-skin')">Smooth Skin</button> |
| <button class="px-3 py-1 bg-pink-700 text-white rounded text-sm hover:bg-pink-600" onclick="applySuggestion('sexier-pose')">Sexier Pose</button> |
| </div> |
| </div> |
| </div> |
| <div class="nsfw-badge hidden">NSFW</div> |
| </div> |
|
|
| <div class="mt-6 flex flex-wrap justify-center gap-3"> |
| <button id="undo-btn" class="px-4 py-2 bg-gray-700 text-gray-300 rounded-md hover:bg-gray-600 disabled:opacity-50" disabled> |
| <i class="fas fa-undo mr-2"></i> Undo |
| </button> |
| <button id="redo-btn" class="px-4 py-2 bg-gray-700 text-gray-300 rounded-md hover:bg-gray-600 disabled:opacity-50" disabled> |
| <i class="fas fa-redo mr-2"></i> Redo |
| </button> |
| <button id="reset-btn" class="px-4 py-2 bg-gray-700 text-gray-300 rounded-md hover:bg-gray-600" onclick="resetEditor()"> |
| <i class="fas fa-trash-alt mr-2"></i> Reset |
| </button> |
| <button id="auto-enhance-btn" class="px-6 py-2 bg-pink-800 text-pink-200 rounded-md hover:bg-pink-700 hover:text-white" onclick="autoEnhance()"> |
| <i class="fas fa-magic mr-2"></i> Auto-Enhance |
| </button> |
| <button id="process-btn" class="px-6 py-2 bg-pink-600 text-white rounded-md hover:bg-pink-700" onclick="processImage()"> |
| <i class="fas fa-cogs mr-2"></i> Process |
| </button> |
| <button id="save-btn" class="px-6 py-2 bg-purple-600 text-white rounded-md hover:bg-purple-700" onclick="saveImage()"> |
| <i class="fas fa-download mr-2"></i> Save |
| </button> |
| </div> |
|
|
| |
| <div id="predictive-suggestions" class="mt-6 bg-gray-800 rounded-lg p-4 hidden"> |
| <h3 class="font-medium text-gray-300 mb-3 flex justify-between items-center"> |
| <span>AI Suggestions</span> |
| <button onclick="hidePredictiveSuggestions()" class="text-gray-400 hover:text-white"> |
| <i class="fas fa-times"></i> |
| </button> |
| </h3> |
| <div class="grid grid-cols-2 md:grid-cols-4 gap-3"> |
| <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white flex items-center" onclick="applySuggestion('enhance-curves')"> |
| <i class="fas fa-venus mr-2"></i> Enhance Curves |
| </button> |
| <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white flex items-center" onclick="applySuggestion('bigger-ass')"> |
| <i class="fas fa-pepper-hot mr-2"></i> Bigger Ass |
| </button> |
| <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white flex items-center" onclick="applySuggestion('add-toy')"> |
| <i class="fas fa-dildo mr-2"></i> Add Toy |
| </button> |
| <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white flex items-center" onclick="applySuggestion('sexier-pose')"> |
| <i class="fas fa-fire mr-2"></i> Sexier Pose |
| </button> |
| <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white flex items-center" onclick="applySuggestion('smooth-skin')"> |
| <i class="fas fa-spa mr-2"></i> Smooth Skin |
| </button> |
| <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white flex items-center" onclick="applySuggestion('better-lighting')"> |
| <i class="fas fa-lightbulb mr-2"></i> Better Lighting |
| </button> |
| <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white flex items-center" onclick="applySuggestion('add-lingerie')"> |
| <i class="fas fa-tshirt mr-2"></i> Add Lingerie |
| </button> |
| <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white flex items-center" onclick="applySuggestion('add-plug')"> |
| <i class="fas fa-gem mr-2"></i> Add Plug |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="w-full lg:w-1/4 bg-gray-800 rounded-xl shadow-md p-6 h-fit"> |
| <div class="flex justify-between items-center mb-4"> |
| <h3 class="font-medium text-gray-300">Content Library</h3> |
| <button class="text-pink-500 hover:text-pink-300" onclick="document.getElementById('file-upload').click()"> |
| <i class="fas fa-plus"></i> |
| </button> |
| </div> |
|
|
| <div id="reference-container" class="space-y-3 max-h-64 overflow-y-auto"> |
| |
| </div> |
|
|
| <div class="mt-6"> |
| <h3 class="font-medium text-gray-300 mb-3">Quick Edits</h3> |
| <div class="grid grid-cols-2 gap-3"> |
| <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white" onclick="quickEdit('blur-background')"> |
| <i class="fas fa-eye-slash mr-1"></i> Blur BG |
| </button> |
| <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white" onclick="quickEdit('enhance-nipples')"> |
| <i class="fas fa-dot-circle mr-1"></i> Enhance Nipples |
| </button> |
| <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white" onclick="quickEdit('plump-lips')"> |
| <i class="fas fa-lips mr-1"></i> Plump Lips |
| </button> |
| <button class="px-3 py-2 bg-gray-700 rounded text-sm hover:bg-pink-600 hover:text-white" onclick="quickEdit('smooth-skin')"> |
| <i class="fas fa-spa mr-1"></i> Smooth Skin |
| </button> |
| </div> |
| </div> |
|
|
| <div class="mt-6"> |
| <h3 class="font-medium text-gray-300 mb-3">OnlyFans Tools</h3> |
| <div class="space-y-3"> |
| <button class="w-full py-2 bg-pink-700 text-white rounded-md text-sm hover:bg-pink-600 flex items-center justify-center" onclick="addWatermark()"> |
| <i class="fas fa-copyright mr-2"></i> Add Watermark |
| </button> |
| <button class="w-full py-2 bg-purple-700 text-white rounded-md text-sm hover:bg-purple-600 flex items-center justify-center" onclick="generateTeaser()"> |
| <i class="fas fa-lock-open mr-2"></i> Create Teaser |
| </button> |
| <button class="w-full py-2 bg-gray-700 text-white rounded-md text-sm hover:bg-gray-600 flex items-center justify-center" onclick="showSocialModal()"> |
| <i class="fas fa-share-alt mr-2"></i> Social Preview |
| </button> |
| </div> |
| </div> |
|
|
| <div class="mt-6"> |
| <h3 class="font-medium text-gray-300 mb-3">Export Options</h3> |
| <div class="space-y-3"> |
| <div class="flex items-center"> |
| <input type="radio" id="format-jpg" name="export-format" class="mr-2" checked> |
| <label for="format-jpg" class="text-sm">JPG (Recommended)</label> |
| </div> |
| <div class="flex items-center"> |
| <input type="radio" id="format-png" name="export-format" class="mr-2"> |
| <label for="format-png" class="text-sm">PNG (Lossless)</label> |
| </div> |
| <div class="flex items-center"> |
| <input type="radio" id="format-webp" name="export-format" class="mr-2"> |
| <label for="format-webp" class="text-sm">WebP (Smaller)</label> |
| </div> |
| </div> |
| <div class="mt-3"> |
| <label class="block text-sm text-gray-400 mb-1">Quality</label> |
| <input type="range" id="export-quality" class="w-full slider-thumb" min="50" max="100" value="90"> |
| <div class="flex justify-between text-xs text-gray-500"> |
| <span>Low</span> |
| <span>High</span> |
| </div> |
| </div> |
| <div class="mt-3"> |
| <label class="block text-sm text-gray-400 mb-1">Resolution</label> |
| <select id="export-resolution" class="w-full p-2 border border-gray-700 bg-gray-700 rounded-md text-sm"> |
| <option value="original">Original</option> |
| <option value="1080">1080p (HD)</option> |
| <option value="720">720p</option> |
| <option value="4k">4K (UHD)</option> |
| </select> |
| </div> |
| </div> |
|
|
| <div class="mt-6"> |
| <h3 class="font-medium text-gray-300 mb-3">Content Stats</h3> |
| <div class="bg-gray-700 rounded-md p-3 text-sm"> |
| <div class="flex justify-between mb-1"> |
| <span class="text-gray-400">Engagement Score:</span> |
| <span class="text-pink-400" id="engagement-score">--</span> |
| </div> |
| <div class="flex justify-between mb-1"> |
| <span class="text-gray-400">Spicy Level:</span> |
| <span class="text-pink-400" id="spicy-level">--</span> |
| </div> |
| <div class="flex justify-between mb-1"> |
| <span class="text-gray-400">Market Value:</span> |
| <span class="text-pink-400" id="market-value">--</span> |
| </div> |
| <div class="flex justify-between"> |
| <span class="text-gray-400">AI Rating:</span> |
| <span class="text-pink-400" id="ai-rating">--</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </main> |
|
|
| |
| <div id="face-swap-modal" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center hidden z-50"> |
| <div class="bg-gray-800 rounded-lg p-6 w-full max-w-2xl border border-pink-500"> |
| <div class="flex justify-between items-center mb-4"> |
| <h3 class="text-lg font-medium text-white">Face Swap</h3> |
| <button onclick="hideFaceSwapModal()" class="text-gray-400 hover:text-white"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| <div class="grid grid-cols-2 gap-4 mb-4"> |
| <div> |
| <h4 class="text-sm font-medium mb-2 text-gray-300">Source Face</h4> |
| <select id="modal-source-face" class="w-full p-2 border border-gray-700 bg-gray-700 rounded-md text-sm mb-2 text-white" onchange="updateFacePreview('source')"> |
| <option value="" class="text-gray-400">Select reference image</option> |
| </select> |
| <div class="border border-gray-700 rounded-md h-40 bg-gray-700 flex items-center justify-center relative face-swap-preview" id="source-face-preview"> |
| <span class="text-gray-500">No image selected</span> |
| </div> |
| </div> |
| <div> |
| <h4 class="text-sm font-medium mb-2 text-gray-300">Target Face</h4> |
| <select id="modal-target-face" class="w-full p-2 border border-gray-700 bg-gray-700 rounded-md text-sm mb-2 text-white" onchange="updateFacePreview('target')"> |
| <option value="" class="text-gray-400">Select reference image</option> |
| </select> |
| <div class="border border-gray-700 rounded-md h-40 bg-gray-700 flex items-center justify-center relative face-swap-preview" id="target-face-preview"> |
| <span class="text-gray-500">No image selected</span> |
| </div> |
| </div> |
| </div> |
| <div class="mb-4"> |
| <label class="block text-sm text-gray-400 mb-1">Face Alignment Strength</label> |
| <input type="range" id="face-align-strength" class="w-full slider-thumb" min="0" max="100" value="75"> |
| </div> |
| <div class="mb-4"> |
| <label class="block text-sm text-gray-400 mb-1">Skin Tone Matching</label> |
| <input type="range" id="skin-tone-match" class="w-full slider-thumb" min="0" max="100" value="50"> |
| </div> |
| <div class="mb-4"> |
| <label class="block text-sm text-gray-400 mb-1">Blending Intensity</label> |
| <input type="range" id="blend-intensity" class="w-full slider-thumb" min="0" max="100" value="80"> |
| </div> |
| <div class="flex justify-end space-x-3"> |
| <button onclick="hideFaceSwapModal()" class="px-4 py-2 bg-gray-700 text-gray-300 rounded-md hover:bg-gray-600"> |
| Cancel |
| </button> |
| <button onclick="applyModalFaceSwap()" class="px-4 py-2 bg-pink-600 text-white rounded-md hover:bg-pink-700"> |
| Apply Face Swap |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="custom-pose-modal" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center hidden z-50"> |
| <div class="bg-gray-800 rounded-lg p-6 w-full max-w-2xl border border-pink-500"> |
| <div class="flex justify-between items-center mb-4"> |
| <h3 class="text-lg font-medium text-white">Create Custom Pose</h3> |
| <button onclick="hideCustomPoseModal()" class="text-gray-400 hover:text-white"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| <div class="mb-4"> |
| <label class="block text-sm text-gray-400 mb-1">Pose Description</label> |
| <textarea id="pose-description" class="w-full border border-gray-700 bg-gray-700 rounded-md p-2 text-sm text-white" placeholder="Describe the pose you want (e.g. 'bent over, ass up, looking back')"></textarea> |
| </div> |
| <div class="mb-4"> |
| <label class="block text-sm text-gray-400 mb-1">Pose Strength</label> |
| <input type="range" id="pose-strength" class="w-full slider-thumb" min="0" max="100" value="50"> |
| </div> |
| <div class="mb-4"> |
| <label class="block text-sm text-gray-400 mb-1">Suggestions</label> |
| <div class="grid grid-cols-2 gap-2"> |
| <button class="px-2 py-1 bg-gray-700 text-xs rounded hover:bg-pink-600 hover:text-white" onclick="document.getElementById('pose-description').value = 'bent over, ass up, looking back'">Bent Over</button> |
| <button class="px-2 py-1 bg-gray-700 text-xs rounded hover:bg-pink-600 hover:text-white" onclick="document.getElementById('pose-description').value = 'legs spread, touching self'">Legs Spread</button> |
| <button class="px-2 py-1 bg-gray-700 text-xs rounded hover:bg-pink-600 hover:text-white" onclick="document.getElementById('pose-description').value = 'on knees, chest up, mouth open'">Kneeling</button> |
| <button class="px-2 py-1 bg-gray-700 text-xs rounded hover:bg-pink-600 hover:text-white" onclick="document.getElementById('pose-description').value = 'squatting, showing everything'">Squatting</button> |
| </div> |
| </div> |
| <div class="flex justify-end space-x-3"> |
| <button onclick="hideCustomPoseModal()" class="px-4 py-2 bg-gray-700 text-gray-300 rounded-md hover:bg-gray-600"> |
| Cancel |
| </button> |
| <button onclick="applyCustomPose()" class="px-4 py-2 bg-pink-600 text-white rounded-md hover:bg-pink-700"> |
| Create Pose |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="social-modal" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center hidden z-50"> |
| <div class="bg-gray-800 rounded-lg p-6 w-full max-w-2xl border border-pink-500"> |
| <div class="flex justify-between items-center mb-4"> |
| <h3 class="text-lg font-medium text-white">Social Media Preview</h3> |
| <button onclick="hideSocialModal()" class="text-gray-400 hover:text-white"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| <div class="grid grid-cols-3 gap-4 mb-4"> |
| <div class="bg-gray-900 p-2 rounded text-center"> |
| <div class="h-32 bg-gray-700 rounded mb-2 flex items-center justify-center"> |
| <i class="fas fa-instagram text-2xl text-pink-500"></i> |
| </div> |
| <p class="text-xs text-gray-400">Instagram</p> |
| </div> |
| <div class="bg-gray-900 p-2 rounded text-center"> |
| <div class="h-32 bg-gray-700 rounded mb-2 flex items-center justify-center"> |
| <i class="fas fa-twitter text-2xl text-blue-400"></i> |
| </div> |
| <p class="text-xs text-gray-400">Twitter</p> |
| </div> |
| <div class="bg-gray-900 p-2 rounded text-center"> |
| <div class="h-32 bg-gray-700 rounded mb-2 flex items-center justify-center"> |
| <i class="fas fa-tiktok text-2xl text-white"></i> |
| </div> |
| <p class="text-xs text-gray-400">TikTok</p> |
| </div> |
| </div> |
| <div class="mb-4"> |
| <label class="block text-sm text-gray-400 mb-1">Preview Text</label> |
| <input type="text" class="w-full p-2 border border-gray-700 bg-gray-700 rounded-md text-sm text-white" value="New content coming soon! 🔥"> |
| </div> |
| <div class="flex justify-end space-x-3"> |
| <button onclick="hideSocialModal()" class="px-4 py-2 bg-gray-700 text-gray-300 rounded-md hover:bg-gray-600"> |
| Close |
| </button> |
| <button onclick="copySocialPreview()" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"> |
| Copy Preview |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| |
| let uploadedImages = []; |
| let currentImageIndex = 0; |
| let editHistory = []; |
| let currentHistoryIndex = -1; |
| let bodyParams = { |
| breast: 0, |
| ass: 0, |
| waist: 0, |
| pussy: 0 |
| }; |
| let faceDetectionModelsLoaded = false; |
| |
| |
| document.addEventListener('DOMContentLoaded', async function() { |
| |
| const promptBox = document.getElementById('ai-prompt'); |
| const charCount = document.getElementById('char-count'); |
| |
| promptBox.addEventListener('input', function() { |
| charCount.textContent = this.value.length; |
| |
| |
| if(this.value.length > 10 && !this.value.includes('ass') && !this.value.includes('toy') && !this.value.includes('plug')) { |
| showPredictiveSuggestions(); |
| } |
| }); |
| |
| |
| const sliders = ['breast', 'ass', 'waist', 'pussy']; |
| sliders.forEach(slider => { |
| const sliderElement = document.getElementById(`${slider}-slider`); |
| const valueElement = document.getElementById(`${slider}-value`); |
| |
| sliderElement.addEventListener('input', function() { |
| valueElement.textContent = `${this.value}%`; |
| }); |
| }); |
| |
| |
| document.getElementById('undo-btn').addEventListener('click', undo); |
| document.getElementById('redo-btn').addEventListener('click', redo); |
| |
| |
| await loadFaceDetectionModels(); |
| |
| |
| let firstUpload = true; |
| }); |
| |
| |
| async function loadFaceDetectionModels() { |
| try { |
| await faceapi.nets.tinyFaceDetector.loadFromUri('/models'); |
| await faceapi.nets.faceLandmark68Net.loadFromUri('/models'); |
| await faceapi.nets.faceRecognitionNet.loadFromUri('/models'); |
| faceDetectionModelsLoaded = true; |
| console.log('Face detection models loaded successfully'); |
| } catch (error) { |
| console.error('Error loading face detection models:', error); |
| } |
| } |
| |
| |
| const fileUpload = document.getElementById('file-upload'); |
| const uploadArea = document.getElementById('upload-area'); |
| const thumbnailContainer = document.getElementById('thumbnail-container'); |
| const referenceContainer = document.getElementById('reference-container'); |
| const previewImage = document.getElementById('preview-image'); |
| const previewVideo = document.getElementById('preview-video'); |
| const placeholder = document.getElementById('placeholder'); |
| const previewContainer = document.getElementById('preview-container'); |
| const nsfwBadge = document.querySelector('.nsfw-badge'); |
| |
| |
| uploadArea.addEventListener('dragover', (e) => { |
| e.preventDefault(); |
| uploadArea.classList.add('bg-pink-900', 'border-pink-500'); |
| }); |
| |
| uploadArea.addEventListener('dragleave', () => { |
| uploadArea.classList.remove('bg-pink-900', 'border-pink-500'); |
| }); |
| |
| uploadArea.addEventListener('drop', (e) => { |
| e.preventDefault(); |
| uploadArea.classList.remove('bg-pink-900', 'border-pink-500'); |
| if (e.dataTransfer.files.length > 0) { |
| fileUpload.files = e.dataTransfer.files; |
| handleFileUpload(); |
| } |
| }); |
| |
| uploadArea.addEventListener('click', () => fileUpload.click()); |
| |
| fileUpload.addEventListener('change', handleFileUpload); |
| |
| function handleFileUpload() { |
| const files = fileUpload.files; |
| if (!files || files.length === 0) return; |
| |
| for (let i = 0; i < files.length; i++) { |
| const file = files[i]; |
| if (!file.type.startsWith('image/') && !file.type.startsWith('video/')) continue; |
| |
| const reader = new FileReader(); |
| reader.onload = function(event) { |
| const mediaData = { |
| id: Date.now() + i, |
| src: event.target.result, |
| name: file.name, |
| originalSrc: event.target.result, |
| type: file.type.startsWith('image/') ? 'image' : 'video' |
| }; |
| uploadedImages.push(mediaData); |
| |
| |
| const thumbnail = document.createElement('div'); |
| thumbnail.className = `image-thumbnail relative ${uploadedImages.length === 1 ? 'active' : ''}`; |
| thumbnail.innerHTML = ` |
| ${mediaData.type === 'image' ? |
| `<img src="${mediaData.src}" class="w-full h-full object-cover rounded">` : |
| `<video src="${mediaData.src}" class="w-full h-full object-cover rounded"></video>`} |
| <div class="absolute inset-0 flex items-center justify-center bg-black bg-opacity-0 hover:bg-opacity-30 transition-all duration-200"> |
| <button onclick="setActiveImage(${mediaData.id})" class="text-white opacity-0 hover:opacity-100"> |
| <i class="fas fa-check-circle text-xl"></i> |
| </button> |
| </div> |
| `; |
| thumbnailContainer.appendChild(thumbnail); |
| |
| |
| const referenceItem = document.createElement('div'); |
| referenceItem.className = 'flex items-center p-2 bg-gray-700 rounded-md hover:bg-gray-600'; |
| referenceItem.innerHTML = ` |
| <div class="w-10 h-10 bg-gray-600 rounded-md mr-3 overflow-hidden"> |
| ${mediaData.type === 'image' ? |
| `<img src="${mediaData.src}" class="w-full h-full object-cover">` : |
| `<video src="${mediaData.src}" class="w-full h-full object-cover"></video>`} |
| </div> |
| <div class="flex-1 truncate"> |
| <p class="text-sm font-medium truncate">${file.name}</p> |
| <p class="text-xs text-gray-400">${(file.size / 1024).toFixed(1)} KB</p> |
| </div> |
| <button onclick="removeImage(${mediaData.id})" class="text-gray-400 hover:text-pink-500 ml-2"> |
| <i class="fas fa-times"></i> |
| </button> |
| `; |
| referenceContainer.appendChild(referenceItem); |
| |
| |
| updateSelectOptions(); |
| |
| |
| if (uploadedImages.length === 1) { |
| setActiveImage(mediaData.id); |
| nsfwBadge.classList.remove('hidden'); |
| |
| |
| setTimeout(() => { |
| autoEnhance(); |
| }, 500); |
| } |
| |
| |
| setTimeout(() => { |
| analyzeContent(); |
| }, 1000); |
| }; |
| reader.readAsDataURL(file); |
| } |
| } |
| |
| function setActiveImage(id) { |
| const imageData = uploadedImages.find(img => img.id === id); |
| if (!imageData) return; |
| |
| currentImageIndex = uploadedImages.findIndex(img => img.id === id); |
| |
| if (imageData.type === 'image') { |
| previewImage.src = imageData.src; |
| previewImage.classList.remove('hidden'); |
| previewVideo.classList.add('hidden'); |
| } else { |
| previewVideo.src = imageData.src; |
| previewVideo.classList.remove('hidden'); |
| previewImage.classList.add('hidden'); |
| } |
| |
| previewContainer.classList.remove('hidden'); |
| placeholder.classList.add('hidden'); |
| |
| |
| document.querySelectorAll('.image-thumbnail').forEach((thumb, index) => { |
| if (index === currentImageIndex) { |
| thumb.classList.add('active'); |
| } else { |
| thumb.classList.remove('active'); |
| } |
| }); |
| |
| |
| saveToHistory(); |
| |
| |
| analyzeContent(); |
| } |
| |
| function removeImage(id) { |
| const index = uploadedImages.findIndex(img => img.id === id); |
| if (index === -1) return; |
| |
| uploadedImages.splice(index, 1); |
| |
| |
| thumbnailContainer.children[index].remove(); |
| |
| |
| referenceContainer.children[index].remove(); |
| |
| |
| updateSelectOptions(); |
| |
| |
| if (currentImageIndex === index) { |
| if (uploadedImages.length > 0) { |
| |
| const newIndex = Math.min(index, uploadedImages.length - 1); |
| setActiveImage(uploadedImages[newIndex].id); |
| } else { |
| |
| previewImage.src = ''; |
| previewVideo.src = ''; |
| previewContainer.classList.add('hidden'); |
| placeholder.classList.remove('hidden'); |
| nsfwBadge.classList.add('hidden'); |
| } |
| } else if (currentImageIndex > index) { |
| currentImageIndex--; |
| } |
| |
| saveToHistory(); |
| } |
| |
| function updateSelectOptions() { |
| const modalSourceFace = document.getElementById('modal-source-face'); |
| const modalTargetFace = document.getElementById('modal-target-face'); |
| |
| |
| [modalSourceFace, modalTargetFace].forEach(select => { |
| while (select.options.length > 1) { |
| select.remove(1); |
| } |
| }); |
| |
| |
| uploadedImages.forEach((img, index) => { |
| const option = document.createElement('option'); |
| option.value = img.id; |
| option.textContent = `Image ${index + 1}`; |
| option.className = 'text-white'; |
| |
| const option2 = option.cloneNode(true); |
| |
| modalSourceFace.appendChild(option); |
| modalTargetFace.appendChild(option2); |
| }); |
| } |
| |
| |
| function saveToHistory() { |
| if (uploadedImages.length === 0) return; |
| |
| |
| if (currentHistoryIndex < editHistory.length - 1) { |
| editHistory = editHistory.slice(0, currentHistoryIndex + 1); |
| } |
| |
| |
| const historyItem = { |
| imageSrc: uploadedImages[currentImageIndex].src, |
| bodyParams: {...bodyParams} |
| }; |
| |
| editHistory.push(historyItem); |
| currentHistoryIndex = editHistory.length - 1; |
| |
| |
| document.getElementById('undo-btn').disabled = currentHistoryIndex <= 0; |
| document.getElementById('redo-btn').disabled = currentHistoryIndex >= editHistory.length - 1; |
| } |
| |
| function undo() { |
| if (currentHistoryIndex <= 0) return; |
| |
| currentHistoryIndex--; |
| applyHistoryState(); |
| } |
| |
| function redo() { |
| if (currentHistoryIndex >= editHistory.length - 1) return; |
| |
| currentHistoryIndex++; |
| applyHistoryState(); |
| } |
| |
| function applyHistoryState() { |
| const historyItem = editHistory[currentHistoryIndex]; |
| |
| |
| if (uploadedImages[currentImageIndex].type === 'image') { |
| previewImage.src = historyItem.imageSrc; |
| } else { |
| previewVideo.src = historyItem.imageSrc; |
| } |
| uploadedImages[currentImageIndex].src = historyItem.imageSrc; |
| |
| |
| bodyParams = {...historyItem.bodyParams}; |
| document.getElementById('breast-slider').value = bodyParams.breast; |
| document.getElementById('ass-slider').value = bodyParams.ass; |
| document.getElementById('waist-slider').value = bodyParams.waist; |
| document.getElementById('pussy-slider').value = bodyParams.pussy; |
| |
| |
| document.getElementById('breast-value').textContent = `${bodyParams.breast}%`; |
| document.getElementById('ass-value').textContent = `${bodyParams.ass}%`; |
| document.getElementById('waist-value').textContent = `${bodyParams.waist}%`; |
| document.getElementById('pussy-value').textContent = `${bodyParams.pussy}%`; |
| |
| |
| document.getElementById('undo-btn').disabled = currentHistoryIndex <= 0; |
| document.getElementById('redo-btn').disabled = currentHistoryIndex >= editHistory.length - 1; |
| } |
| |
| |
| function resetEditor() { |
| if (uploadedImages.length === 0) return; |
| |
| if (uploadedImages[currentImageIndex].type === 'image') { |
| previewImage.src = uploadedImages[currentImageIndex].originalSrc; |
| } else { |
| previewVideo.src = uploadedImages[currentImageIndex].originalSrc; |
| } |
| uploadedImages[currentImageIndex].src = uploadedImages[currentImageIndex].originalSrc; |
| |
| |
| document.getElementById('breast-slider').value = 0; |
| document.getElementById('ass-slider').value = 0; |
| document.getElementById('waist-slider').value = 0; |
| document.getElementById('pussy-slider').value = 0; |
| bodyParams = { breast: 0, ass: 0, waist: 0, pussy: 0 }; |
| |
| |
| document.getElementById('breast-value').textContent = "0%"; |
| document.getElementById('ass-value').textContent = "0%"; |
| document.getElementById('waist-value').textContent = "0%"; |
| document.getElementById('pussy-value').textContent = "0%"; |
| |
| |
| editHistory = []; |
| currentHistoryIndex = -1; |
| document.getElementById('undo-btn').disabled = true; |
| document.getElementById('redo-btn').disabled = true; |
| |
| saveToHistory(); |
| } |
| |
| |
| async function processImage() { |
| if (!previewImage.src && !previewVideo.src) { |
| alert('Please upload NSFW content first'); |
| return; |
| } |
| |
| const promptBox = document.getElementById('ai-prompt'); |
| const prompt = promptBox.value; |
| |
| if (!prompt && Object.values(bodyParams).every(val => val === 0)) { |
| alert('Please enter a prompt or adjust body parameters'); |
| return; |
| } |
| |
| |
| const overlay = document.getElementById('processing-overlay'); |
| const progressBar = document.getElementById('progress-bar'); |
| const processingText = document.getElementById('processing-text'); |
| const aiSuggestions = document.getElementById('ai-suggestions'); |
| |
| overlay.classList.remove('hidden'); |
| processingText.textContent = 'Enhancing your content...'; |
| aiSuggestions.classList.add('hidden'); |
| |
| |
| let progress = 0; |
| const interval = setInterval(() => { |
| progress += Math.random() * 10; |
| if (progress > 100) progress = 100; |
| progressBar.style.width = `${progress}%`; |
| |
| if (progress === 100) { |
| clearInterval(interval); |
| processingText.textContent = 'Finalizing enhancements...'; |
| |
| setTimeout(() => { |
| overlay.classList.add('hidden'); |
| progressBar.style.width = '0%'; |
| |
| |
| |
| if (uploadedImages[currentImageIndex].type === 'image') { |
| const canvas = document.createElement('canvas'); |
| const ctx = canvas.getContext('2d'); |
| const img = new Image(); |
| img.onload = function() { |
| canvas.width = img.width; |
| canvas.height = img.height; |
| ctx.drawImage(img, 0, 0); |
| |
| |
| if (bodyParams.breast !== 0) { |
| |
| ctx.fillStyle = 'rgba(255, 200, 200, 0.1)'; |
| ctx.beginPath(); |
| ctx.ellipse(canvas.width * 0.4, canvas.height * 0.4, |
| canvas.width * 0.1 * (1 + bodyParams.breast/100), |
| canvas.height * 0.15 * (1 + bodyParams.breast/100), |
| 0, 0, Math.PI * 2); |
| ctx.fill(); |
| |
| ctx.beginPath(); |
| ctx.ellipse(canvas.width * 0.6, canvas.height * 0.4, |
| canvas.width * 0.1 * (1 + bodyParams.breast/100), |
| canvas.height * 0.15 * (1 + bodyParams.breast/100), |
| 0, 0, Math.PI * 2); |
| ctx.fill(); |
| } |
| |
| if (bodyParams.ass !== 0) { |
| |
| ctx.fillStyle = 'rgba(200, 200, 255, 0.1)'; |
| ctx.beginPath(); |
| ctx.ellipse(canvas.width * 0.5, canvas.height * 0.6, |
| canvas.width * 0.15 * (1 + bodyParams.ass/100), |
| canvas.height * 0.1 * (1 + bodyParams.ass/100), |
| 0, 0, Math.PI * 2); |
| ctx.fill(); |
| } |
| |
| if (bodyParams.waist !== 0) { |
| |
| ctx.fillStyle = 'rgba(255, 255, 200, 0.1)'; |
| ctx.beginPath(); |
| ctx.ellipse(canvas.width * 0.5, canvas.height * 0.5, |
| canvas.width * 0.1 * (1 - bodyParams.waist/200), |
| canvas.height * 0.15 * (1 - bodyParams.waist/200), |
| 0, 0, Math.PI * 2); |
| ctx.fill(); |
| } |
| |
| if (bodyParams.pussy !== 0) { |
| |
| ctx.fillStyle = 'rgba(255, 150, 200, 0.1)'; |
| ctx.beginPath(); |
| ctx.ellipse(canvas.width * 0.5, canvas.height * 0.7, |
| canvas.width * 0.08 * (1 + bodyParams.pussy/100), |
| canvas.height * 0.05 * (1 + bodyParams.pussy/100), |
| 0, 0, Math.PI * 2); |
| ctx.fill(); |
| } |
| |
| |
| if (prompt.includes('smooth') || prompt.includes('skin')) { |
| |
| ctx.filter = 'blur(1px)'; |
| ctx.drawImage(canvas, 0, 0); |
| ctx.filter = 'none'; |
| } |
| |
| if (prompt.includes('toy') || prompt.includes('dildo') || prompt.includes('vibrator')) { |
| |
| ctx.fillStyle = '#ff69b4'; |
| ctx.beginPath(); |
| ctx.ellipse(canvas.width * 0.5, canvas.height * 0.7, |
| canvas.width * 0.05, canvas.height * 0.15, |
| Math.PI/4, 0, Math.PI * 2); |
| ctx.fill(); |
| } |
| |
| if (prompt.includes('plug') || prompt.includes('anal')) { |
| |
| ctx.fillStyle = '#9370db'; |
| ctx.beginPath(); |
| ctx.ellipse(canvas.width * 0.5, canvas.height * 0.3, |
| canvas.width * 0.03, canvas.height * 0.03, |
| 0, 0, Math.PI * 2); |
| ctx.fill(); |
| |
| |
| ctx.fillStyle = '#ffd700'; |
| ctx.beginPath(); |
| ctx.ellipse(canvas.width * 0.5, canvas.height * 0.28, |
| canvas.width * 0.01, canvas.height * 0.01, |
| 0, 0, Math.PI * 2); |
| ctx.fill(); |
| } |
| |
| |
| const newSrc = canvas.toDataURL('image/jpeg'); |
| previewImage.src = newSrc; |
| uploadedImages[currentImageIndex].src = newSrc; |
| |
| saveToHistory(); |
| |
| |
| setTimeout(() => { |
| overlay.classList.remove('hidden'); |
| processingText.textContent = 'Enhancement complete!'; |
| aiSuggestions.classList.remove('hidden'); |
| progressBar.style.width = '0%'; |
| |
| |
| setTimeout(() => { |
| overlay.classList.add('hidden'); |
| }, 5000); |
| }, 500); |
| }; |
| img.src = previewImage.src; |
| } |
| }, 500); |
| } |
| }, 100); |
| } |
| |
| |
| function autoEnhance() { |
| if (!previewImage.src && !previewVideo.src) { |
| alert('Please upload NSFW content first'); |
| return; |
| } |
| |
| |
| document.getElementById('breast-slider').value = 15; |
| document.getElementById('ass-slider').value = 25; |
| document.getElementById('waist-slider').value = 20; |
| document.getElementById('pussy-slider').value = 10; |
| |
| |
| document.getElementById('breast-value').textContent = "15%"; |
| document.getElementById('ass-value').textContent = "25%"; |
| document.getElementById('waist-value').textContent = "20%"; |
| document.getElementById('pussy-value').textContent = "10%"; |
| |
| |
| bodyParams.breast = 15; |
| bodyParams.ass = 25; |
| bodyParams.waist = 20; |
| bodyParams.pussy = 10; |
| |
| |
| document.getElementById('ai-prompt').value = "Enhance curves, smooth skin, perfect lighting, professional look"; |
| |
| |
| processImage(); |
| } |
| |
| |
| function saveImage() { |
| if (!previewImage.src && !previewVideo.src) { |
| alert('Please upload NSFW content first'); |
| return; |
| } |
| |
| |
| let format = 'jpg'; |
| if (document.getElementById('format-png').checked) format = 'png'; |
| if (document.getElementById('format-webp').checked) format = 'webp'; |
| |
| |
| const quality = document.getElementById('export-quality').value; |
| |
| |
| const link = document.createElement('a'); |
| if (previewImage.src) { |
| link.href = previewImage.src; |
| link.download = `onlyfans-content.${format}`; |
| } else { |
| link.href = previewVideo.src; |
| link.download = 'onlyfans-video.mp4'; |
| } |
| document.body.appendChild(link); |
| link.click(); |
| document.body.removeChild(link); |
| |
| |
| alert(`Content saved as ${format.toUpperCase()} at ${quality}% quality!`); |
| } |
| |
| |
| function updateBodyParam(param, value) { |
| bodyParams[param] = parseInt(value); |
| document.getElementById(`${param}-value`).textContent = `${value}%`; |
| saveToHistory(); |
| } |
| |
| |
| function applyPrompt(prompt) { |
| document.getElementById('ai-prompt').value = prompt; |
| document.getElementById('char-count').textContent = prompt.length; |
| processImage(); |
| } |
| |
| |
| async function showFaceSwapModal() { |
| if (uploadedImages.length < 2) { |
| alert('You need at least 2 images to perform face swap'); |
| return; |
| } |
| |
| document.getElementById('face-swap-modal').classList.remove('hidden'); |
| |
| |
| if (!faceDetectionModelsLoaded) { |
| await loadFaceDetectionModels(); |
| } |
| } |
| |
| function hideFaceSwapModal() { |
| document.getElementById('face-swap-modal').classList.add('hidden'); |
| } |
| |
| async function updateFacePreview(type) { |
| const select = type === 'source' ? |
| document.getElementById('modal-source-face') : |
| document.getElementById('modal-target-face'); |
| const preview = document.getElementById(`${type}-face-preview`); |
| |
| const selectedId = select.value; |
| if (!selectedId) { |
| preview.innerHTML = '<span class="text-gray-500">No image selected</span>'; |
| return; |
| } |
| |
| const imageData = uploadedImages.find(img => img.id == selectedId); |
| if (!imageData) return; |
| |
| |
| preview.innerHTML = ''; |
| |
| |
| const img = document.createElement('img'); |
| img.src = imageData.src; |
| img.className = 'w-full h-full object-contain'; |
| preview.appendChild(img); |
| |
| |
| if (faceDetectionModelsLoaded) { |
| const detections = await faceapi.detectAllFaces(img, new faceapi.TinyFaceDetectorOptions()) |
| .withFaceLandmarks() |
| .withFaceDescriptors(); |
| |
| if (detections.length > 0) { |
| |
| detections.forEach(detection => { |
| const box = detection.detection.box; |
| const faceBox = document.createElement('div'); |
| faceBox.className = 'face-detection-box'; |
| faceBox.style.width = `${box.width}px`; |
| faceBox.style.height = `${box.height}px`; |
| faceBox.style.left = `${box.x}px`; |
| faceBox.style.top = `${box.y}px`; |
| preview.appendChild(faceBox); |
| }); |
| |
| |
| detections.forEach(detection => { |
| const landmarks = detection.landmarks; |
| landmarks.positions.forEach(point => { |
| const dot = document.createElement('div'); |
| dot.className = 'face-landmarks'; |
| dot.style.left = `${point.x}px`; |
| dot.style.top = `${point.y}px`; |
| preview.appendChild(dot); |
| }); |
| }); |
| } |
| } |
| } |
| |
| async function applyModalFaceSwap() { |
| const sourceId = document.getElementById('modal-source-face').value; |
| const targetId = document.getElementById('modal-target-face').value; |
| |
| if (!sourceId || !targetId) { |
| alert('Please select both source and target faces'); |
| return; |
| } |
| |
| if (sourceId === targetId) { |
| alert('Source and target faces must be different'); |
| return; |
| } |
| |
| const strength = document.getElementById('face-align-strength').value; |
| const skinTone = document.getElementById('skin-tone-match').value; |
| const blendIntensity = document.getElementById('blend-intensity').value; |
| |
| |
| const overlay = document.getElementById('processing-overlay'); |
| const progressBar = document.getElementById('progress-bar'); |
| const processingText = document.getElementById('processing-text'); |
| |
| overlay.classList.remove('hidden'); |
| processingText.textContent = 'Swapping faces...'; |
| |
| |
| const sourceImg = uploadedImages.find(img => img.id == sourceId); |
| const targetImg = uploadedImages.find(img => img.id == targetId); |
| |
| |
| const sourceCanvas = document.createElement('canvas'); |
| const sourceCtx = sourceCanvas.getContext('2d'); |
| const targetCanvas = document.createElement('canvas'); |
| const targetCtx = targetCanvas.getContext('2d'); |
| |
| |
| const sourceImage = new Image(); |
| sourceImage.onload = async function() { |
| sourceCanvas.width = sourceImage.width; |
| sourceCanvas.height = sourceImage.height; |
| sourceCtx.drawImage(sourceImage, 0, 0); |
| |
| |
| const targetImage = new Image(); |
| targetImage.onload = async function() { |
| targetCanvas.width = targetImage.width; |
| targetCanvas.height = targetImage.height; |
| targetCtx.drawImage(targetImage, 0, 0); |
| |
| |
| |
| </html> |