creator / index.html
peterpechal's picture
Update index.html
187c6eb verified
<!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 -->
<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 Content -->
<main class="container mx-auto px-4 py-8">
<div class="flex flex-col lg:flex-row gap-8">
<!-- Tools Panel -->
<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">
<!-- Multi Image Upload -->
<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>
<!-- AI Prompts -->
<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>
<!-- Content Categories -->
<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>
<!-- Body Tools -->
<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>
<!-- Toy & Prop Tools -->
<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>
<!-- Pose Maker -->
<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>
<!-- Background Tools -->
<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">
<!-- Video tools content -->
<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>
<!-- Editor Area -->
<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>
<!-- Predictive AI Suggestions -->
<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>
<!-- Layers Panel -->
<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">
<!-- Reference images will appear here -->
</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>
<!-- Face Swap Modal -->
<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>
<!-- Custom Pose Modal -->
<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>
<!-- Social Preview Modal -->
<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>
// Global variables
let uploadedImages = [];
let currentImageIndex = 0;
let editHistory = [];
let currentHistoryIndex = -1;
let bodyParams = {
breast: 0,
ass: 0,
waist: 0,
pussy: 0
};
let faceDetectionModelsLoaded = false;
// Initialize the editor
document.addEventListener('DOMContentLoaded', async function() {
// Set up character counter for prompt box
const promptBox = document.getElementById('ai-prompt');
const charCount = document.getElementById('char-count');
promptBox.addEventListener('input', function() {
charCount.textContent = this.value.length;
// Show predictive suggestions if typing
if(this.value.length > 10 && !this.value.includes('ass') && !this.value.includes('toy') && !this.value.includes('plug')) {
showPredictiveSuggestions();
}
});
// Initialize sliders with value displays
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}%`;
});
});
// Set up undo/redo buttons
document.getElementById('undo-btn').addEventListener('click', undo);
document.getElementById('redo-btn').addEventListener('click', redo);
// Load face detection models
await loadFaceDetectionModels();
// Auto-enhance after first upload
let firstUpload = true;
});
// Load face detection models
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);
}
}
// File upload functionality
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');
// Handle drag and drop
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);
// Add to thumbnail container
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);
// Add to reference container
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);
// Update select options
updateSelectOptions();
// Set first image as active
if (uploadedImages.length === 1) {
setActiveImage(mediaData.id);
nsfwBadge.classList.remove('hidden');
// Auto-enhance on first upload
setTimeout(() => {
autoEnhance();
}, 500);
}
// Analyze content for suggestions
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');
// Update active thumbnail
document.querySelectorAll('.image-thumbnail').forEach((thumb, index) => {
if (index === currentImageIndex) {
thumb.classList.add('active');
} else {
thumb.classList.remove('active');
}
});
// Save to history
saveToHistory();
// Analyze content for suggestions
analyzeContent();
}
function removeImage(id) {
const index = uploadedImages.findIndex(img => img.id === id);
if (index === -1) return;
uploadedImages.splice(index, 1);
// Remove from thumbnail container
thumbnailContainer.children[index].remove();
// Remove from reference container
referenceContainer.children[index].remove();
// Update select options
updateSelectOptions();
// If we removed the active image
if (currentImageIndex === index) {
if (uploadedImages.length > 0) {
// Set next available image as active
const newIndex = Math.min(index, uploadedImages.length - 1);
setActiveImage(uploadedImages[newIndex].id);
} else {
// No images left
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');
// Clear existing options except first
[modalSourceFace, modalTargetFace].forEach(select => {
while (select.options.length > 1) {
select.remove(1);
}
});
// Add new options
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);
});
}
// History management
function saveToHistory() {
if (uploadedImages.length === 0) return;
// Truncate history if we're not at the end
if (currentHistoryIndex < editHistory.length - 1) {
editHistory = editHistory.slice(0, currentHistoryIndex + 1);
}
// Save current state
const historyItem = {
imageSrc: uploadedImages[currentImageIndex].src,
bodyParams: {...bodyParams}
};
editHistory.push(historyItem);
currentHistoryIndex = editHistory.length - 1;
// Update undo/redo buttons
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];
// Update image
if (uploadedImages[currentImageIndex].type === 'image') {
previewImage.src = historyItem.imageSrc;
} else {
previewVideo.src = historyItem.imageSrc;
}
uploadedImages[currentImageIndex].src = historyItem.imageSrc;
// Update body params
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;
// Update slider values
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}%`;
// Update buttons
document.getElementById('undo-btn').disabled = currentHistoryIndex <= 0;
document.getElementById('redo-btn').disabled = currentHistoryIndex >= editHistory.length - 1;
}
// Reset button functionality
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;
// Reset sliders
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 };
// Update slider values
document.getElementById('breast-value').textContent = "0%";
document.getElementById('ass-value').textContent = "0%";
document.getElementById('waist-value').textContent = "0%";
document.getElementById('pussy-value').textContent = "0%";
// Clear history
editHistory = [];
currentHistoryIndex = -1;
document.getElementById('undo-btn').disabled = true;
document.getElementById('redo-btn').disabled = true;
saveToHistory();
}
// Process button functionality
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;
}
// Show processing overlay
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');
// Simulate processing with progress
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%';
// In a real app, this would call your AI processing API
// For demo, we'll just modify the image slightly
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);
// Apply body enhancements based on sliders
if (bodyParams.breast !== 0) {
// Simulate breast enhancement
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) {
// Simulate ass enhancement
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) {
// Simulate waist enhancement
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) {
// Simulate pussy enhancement
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();
}
// Apply effects based on prompt
if (prompt.includes('smooth') || prompt.includes('skin')) {
// Simulate skin smoothing
ctx.filter = 'blur(1px)';
ctx.drawImage(canvas, 0, 0);
ctx.filter = 'none';
}
if (prompt.includes('toy') || prompt.includes('dildo') || prompt.includes('vibrator')) {
// Simulate adding a toy
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')) {
// Simulate adding a butt plug
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();
// Add jewel to plug
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();
}
// Update the image
const newSrc = canvas.toDataURL('image/jpeg');
previewImage.src = newSrc;
uploadedImages[currentImageIndex].src = newSrc;
saveToHistory();
// Show AI suggestions
setTimeout(() => {
overlay.classList.remove('hidden');
processingText.textContent = 'Enhancement complete!';
aiSuggestions.classList.remove('hidden');
progressBar.style.width = '0%';
// Hide after 5 seconds
setTimeout(() => {
overlay.classList.add('hidden');
}, 5000);
}, 500);
};
img.src = previewImage.src;
}
}, 500);
}
}, 100);
}
// Auto-enhance function
function autoEnhance() {
if (!previewImage.src && !previewVideo.src) {
alert('Please upload NSFW content first');
return;
}
// Set some default enhancements
document.getElementById('breast-slider').value = 15;
document.getElementById('ass-slider').value = 25;
document.getElementById('waist-slider').value = 20;
document.getElementById('pussy-slider').value = 10;
// Update displayed values
document.getElementById('breast-value').textContent = "15%";
document.getElementById('ass-value').textContent = "25%";
document.getElementById('waist-value').textContent = "20%";
document.getElementById('pussy-value').textContent = "10%";
// Update body params
bodyParams.breast = 15;
bodyParams.ass = 25;
bodyParams.waist = 20;
bodyParams.pussy = 10;
// Set a smart prompt
document.getElementById('ai-prompt').value = "Enhance curves, smooth skin, perfect lighting, professional look";
// Process the image
processImage();
}
// Save button functionality
function saveImage() {
if (!previewImage.src && !previewVideo.src) {
alert('Please upload NSFW content first');
return;
}
// Get selected format
let format = 'jpg';
if (document.getElementById('format-png').checked) format = 'png';
if (document.getElementById('format-webp').checked) format = 'webp';
// Get quality
const quality = document.getElementById('export-quality').value;
// Simulate download
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);
// Show confirmation
alert(`Content saved as ${format.toUpperCase()} at ${quality}% quality!`);
}
// Body parameter updates
function updateBodyParam(param, value) {
bodyParams[param] = parseInt(value);
document.getElementById(`${param}-value`).textContent = `${value}%`;
saveToHistory();
}
// AI Prompt functions
function applyPrompt(prompt) {
document.getElementById('ai-prompt').value = prompt;
document.getElementById('char-count').textContent = prompt.length;
processImage();
}
// Face Swap Functions
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');
// Load face detection models if not already loaded
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;
// Clear previous preview
preview.innerHTML = '';
// Add image to preview
const img = document.createElement('img');
img.src = imageData.src;
img.className = 'w-full h-full object-contain';
preview.appendChild(img);
// Detect faces and draw landmarks
if (faceDetectionModelsLoaded) {
const detections = await faceapi.detectAllFaces(img, new faceapi.TinyFaceDetectorOptions())
.withFaceLandmarks()
.withFaceDescriptors();
if (detections.length > 0) {
// Draw face detection boxes
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);
});
// Draw face landmarks
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;
// Show processing
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...';
// Get the source and target images
const sourceImg = uploadedImages.find(img => img.id == sourceId);
const targetImg = uploadedImages.find(img => img.id == targetId);
// Create canvas elements for face swapping
const sourceCanvas = document.createElement('canvas');
const sourceCtx = sourceCanvas.getContext('2d');
const targetCanvas = document.createElement('canvas');
const targetCtx = targetCanvas.getContext('2d');
// Load source image
const sourceImage = new Image();
sourceImage.onload = async function() {
sourceCanvas.width = sourceImage.width;
sourceCanvas.height = sourceImage.height;
sourceCtx.drawImage(sourceImage, 0, 0);
// Load target image
const targetImage = new Image();
targetImage.onload = async function() {
targetCanvas.width = targetImage.width;
targetCanvas.height = targetImage.height;
targetCtx.drawImage(targetImage, 0, 0);
// Detect faces in both images
</html>