XimgGen / index.html
yasirme's picture
Update index.html
ecfdfea verified
raw
history blame
23.1 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Free AI Image Generator | Flux, Stable Diffusion, Midjourney Alternative - XimgGen</title>
<meta name="description" content="XimgGen is a free AI image generator using Flux, Stable Diffusion, and Midjourney-style models. Create stunning AI art online without sign-up.">
<meta name="keywords" content="AI image generator, Flux AI, Stable Diffusion, Midjourney alternative, free AI art, XimgGen, AI text to image, online AI art generator">
<meta property="og:title" content="XimgGen - Free AI Image Generator">
<meta property="og:description" content="Create stunning AI art online with Flux, Stable Diffusion, and Midjourney alternative models — 100% free.">
<meta property="og:type" content="website">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="XimgGen - Free AI Image Generator">
<meta name="twitter:description" content="Create AI images with Flux, Stable Diffusion, and Midjourney-style models for free.">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "XimgGen",
"operatingSystem": "Web",
"applicationCategory": "MultimediaApplication",
"description": "XimgGen is a free AI image generator that uses Flux, Stable Diffusion, and Midjourney-style models to create art online.",
"softwareVersion": "1.0",
"url": "https://yasirme-ximggen.static.hf.space",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD"
},
}
</script>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap" rel="stylesheet">
<script type='text/javascript'>
window.smartlook||(function(d) {
var o=smartlook=function(){ o.api.push(arguments)},h=d.getElementsByTagName('head')[0];
var c=d.createElement('script');o.api=new Array();c.async=true;c.type='text/javascript';
c.charset='utf-8';c.src='https://web-sdk.smartlook.com/recorder.js';h.appendChild(c);
})(document);
smartlook('init', 'aa9463be7bcf3461cd111de8ed0dc6ede653881c', { region: 'eu' });
</script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-3KV5X49N3B"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-3KV5X49N3B');
</script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
<style>
*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; margin: 0; padding: 0; font-family: 'Poppins', sans-serif; -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale; overflow-y: auto;}
body { background: radial-gradient(circle at 20% 20%, rgba(140,60,200,0.08), transparent 40%), radial-gradient(circle at 80% 80%, rgba(200,60,255,0.05), transparent 40%), #000; color:#fff; overflow: hidden; }
.topbar {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 56px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 16px;
gap: 12px;
z-index: 1000;
background: transparent;
}
.btn-small {
background: #141414;
border-radius: 10px;
padding: 8px 12px;
font-size: 13px;
color: #fff;
display:inline-flex;
align-items:center;
gap:10px;
border:1px solid rgba(255,255,255,0.03);
}
.btn-small img { width:14px; height:14px; display:block; }
.container {
width: 70%;
max-width: 1100px;
margin: 5em auto 16px;
padding: 0 12px;
display: flex;
flex-direction: column;
gap: 12px;
position: relative;
}
@media (max-width: 768px) {
.container { width: 100%; padding: 0 12px; margin-top:5em; }
}
.input-row {
display:flex;
gap:10px;
align-items:flex-start;
}
textarea#prompt {
flex:1;
min-width:0;
max-height:250px;
height:56px;
resize:none;
border-radius:12px;
padding:12px;
background:#0e0e0e;
border:1px solid rgba(255,255,255,0.03);
color:#fff;
font-size:14px;
line-height:1.35;
overflow:auto;
outline:none;
}
.generate-btn {
background: linear-gradient(90deg,#ff93e9,#9b7cff);
border:none;
border-radius:12px;
padding:12px 18px;
font-size:14px;
cursor:pointer;
color:#fff;
min-height:56px;
display:inline-flex;
align-items:center;
justify-content:center;
transition:opacity .15s;
}
.generate-btn[disabled] { opacity:0.6; cursor:default; }
.options-row {
display:flex;
justify-content:space-between;
align-items:center;
}
.left-group, .right-group { display:flex; gap:8px; align-items:center; }
.modal-backdrop {
display:none;
position: fixed;
inset: 0;
background: rgba(0,0,0,0.72);
align-items: center;
justify-content: center;
padding: 20px;
z-index: 2000;
}
.modal {
width: 100%;
max-width: 720px;
background: #0f0f0f;
border-radius: 12px;
padding: 18px;
box-shadow: 0 10px 40px rgba(0,0,0,0.6);
color: #fff;
}
@media (max-width:420px) {
.modal { padding: 14px; max-width: calc(100% - 12px); border-radius: 10px; }
}
.styles-grid {
display:grid;
grid-template-columns: repeat(2, 1fr);
gap:10px;
margin-top:12px;
}
.style-card {
background:#101010;
border-radius:10px;
overflow:hidden;
cursor:pointer;
text-align:center;
border:2px solid transparent;
padding-bottom:8px;
font-size:13px;
}
.style-card img { width:100%; height:72px; object-fit:cover; display:block; }
.style-card.selected { border-color:#ff93e9; box-shadow: 0 8px 30px rgba(155,124,255,0.06); }
.settings-row { display:flex; gap:12px; align-items:center; margin-top:10px; flex-wrap:wrap; }
.settings-row label { font-size:14px; display:flex; gap:8px; align-items:center; color:#eaeaea; }
.settings-row input[type="number"], .settings-row select { background:#0c0c0c; border:1px solid rgba(255,255,255,0.04); color:#fff; padding:6px 8px; border-radius:8px; font-size:14px; min-width:80px; }
.modal-actions { margin-top:14px; display:flex; justify-content:flex-end; gap:10px; }
.modal-actions button { background:#1a1a1a; border-radius:10px; padding:9px 12px; font-size:14px; color:#fff; border:1px solid rgba(255,255,255,0.03); cursor:pointer; }
#images {
width: 100%;
margin-top:8px;
display:flex;
gap:12px;
flex-wrap:wrap;
justify-content:center;
align-items:flex-start;
overflow:auto;
padding:10px;
border-radius:10px;
background: linear-gradient(180deg, rgba(255,255,255,0.01), transparent);
border:1px solid rgba(255,255,255,0.02);
max-height: calc(100vh - 5em - 220px);
}
.image-card {
background:#0b0b0b;
border-radius:12px;
padding:8px;
min-height:120px;
width: min(350px, 90vw);
box-shadow: 0 10px 30px rgba(0,0,0,0.6);
border:1px solid rgba(255,255,255,0.02);
display:flex;
align-items:center;
justify-content:center;
}
.image-card img { width:100%; height:auto; display:block; border-radius:8px; }
.loader { border:3px solid #222; border-top:3px solid #ff93e9; border-radius:50%; width:22px; height:22px; animation:spin 1s linear infinite; }
@keyframes spin { 0%{ transform:rotate(0) } 100%{ transform:rotate(360deg) } }
.muted { color:#9b9b9b; font-size:13px; }
.row { display:flex; gap:10px; align-items:center; }
.note { font-size:13px; color:#cfcfcf; margin-top:6px; }
</style>
</head>
<body>
<div class="topbar" role="banner">
<div class="btn-small" onclick="window.open('https://discord.gg/QjyD579HSn') ">Discord</div>
<div class="btn-small" onclick="window.open('https://www.instagram.com/yasir.me2008/')" style="cursor: pointer;">
<img src="https://upload.wikimedia.org/wikipedia/commons/a/a5/Instagram_icon.png" alt="Instagram" style="width: 20px; height: 20px;">Instagram
</div>
<a class="btn-small" href="https://buymeacoffee.com/xyaiman" target="_blank" rel="noopener">
<img src="https://cdn.buymeacoffee.com/buttons/bmc-new-btn-logo.svg" alt="coffee">
<span>Buy me a coffee</span>
</a>
</div>
<div class="container" role="main">
<div class="input-row" role="search">
<textarea id="prompt" placeholder="Enter your prompt..." aria-label="Prompt"></textarea>
<button id="generateBtn" class="generate-btn" aria-label="Generate">Generate</button>
</div>
<div class="options-row">
<div class="left-group">
<div id="styleBtn" class="btn-small" aria-haspopup="dialog">🎨 Style</div>
</div>
<div class="right-group">
<div id="settingsBtn" class="btn-small" aria-haspopup="dialog">⚙️ Settings</div>
</div>
</div>
<div class="note">Generated images (scroll this pane). New images appear at the top.</div>
<div id="images" aria-live="polite"></div>
</div>
<div id="styleModal" class="modal-backdrop" role="dialog" aria-modal="true" aria-hidden="true">
<div class="modal" role="document">
<h2 style="margin:0 0 6px 0;">Choose a style</h2>
<div class="note">Click a style — it will be applied to the request (not shown in the input).</div>
<div class="styles-grid" id="stylesGrid">
<div class="style-card selected" data-name="none"><img src="none.jpg" alt="No style"><div>No style</div></div>
<div class="style-card" data-name="cinema"><img src="https://xyplon.web.app/assets/Cinematic.jpeg" alt="Cinema"><div>Cinema</div></div>
<div class="style-card" data-name="realistic"><img src="https://xyplon.web.app/assets/Realistic.jpeg" alt="Realistic"><div>Realistic</div></div>
<div class="style-card" data-name="photography"><img src="https://xyplon.web.app/assets/Photography.jpeg" alt="Photography"><div>Photography</div></div>
<div class="style-card" data-name="fantasy"><img src="https://xyplon.web.app/assets/Digital.jpeg" alt="Fantasy"><div>Fantasy</div></div>
</div>
<div class="modal-actions">
<button id="closeStyle">Close</button>
</div>
</div>
</div>
<div id="settingsModal" class="modal-backdrop" role="dialog" aria-modal="true" aria-hidden="true">
<div class="modal" role="document">
<h2 style="margin:0 0 6px 0;">API Settings</h2>
<div class="settings-row">
<label>Model:
<select id="model">
<option value="flux">flux</option>
<option value="turbo">turbo (uncensored) </option>
</select>
</label>
<label>Width:
<input id="width" type="number" min="64" max="2048" value="1024" />
</label>
<label>Height:
<input id="height" type="number" min="64" max="2048" value="1024" />
</label>
<label>Enhance:
<input id="enhance" type="checkbox" />
</label>
<label>Seed:
<input id="seed" type="number" value="42" />
</label>
<label style="display:flex;align-items:center;gap:6px;">
<input id="randomSeed" type="checkbox" checked /> Random
</label>
</div>
<div class="modal-actions">
<button id="closeSettings">Close</button>
<button id="saveSettings">Save</button>
</div>
</div>
</div>
<script>
const baseUrl = 'https://image.pollinations.ai';
let selectedStyle = null;
let isGenerating = false;
const styleTemplates = {
cinema: " epic cinematic marvellous Hollywood movies style photo ",
realistic: "",
photography: " epic Magnificent professional photography style image ",
fantasy: " create epic fantasy style, image "
};
const SYSTEM_PROMPT = `
ROLE
You compose single-paragraph prompts for the Flux (FLUX.1) image model that yield natural, photoreal results. Never invent lighting or camera details unless the user specifies them.
CORE RULES
- Your prompt should correctly and accurately describe the users image need without changing or misinterpreting users need.
- YOU Always always need to specify suitable photo style at starting like :
- "sun soaked color filter Fujifilm X100V grainy Palette photo of"
- "Kodak Ektachrome 135 mm Film Emulation Portra 160 photo of"
- "Fujifilm Instax desaturated pastel Palette photo of"
- "Kodak portra 400 sun soaked pastel Palette photo of"
- "Film grain Sepia & warm amber tones desaturated muted color photo of"
- "grainy sun soaked color filter Film photo of"
- "Hazed cloudy Pallete photo of"
- "Primary pink spectrum Complementary bright Cheerful and whimsical photo of"
- "Muted colors cinematic grainy noir realism photo of" etc..
you need to think which style will give the best photo in this case.
you can and should merge or create new styles and not just copy paste the above.
you should modify or update styles based on users needs.
- YOU shall use style prefix only where it's suitable obviously you won't use it if user asked for anime or illustration or cartoon etc..
- Never include negations or flaw-prevention phrases such as "without," "no," "avoid," "ban," "exclude."
- Do not mention lighting, HDR, cinematic, volumetric, glow, bloom, lens flare, time of day, weather, or camera/lens unless the user explicitly includes them.
- Mention colors only when tied to specific objects; avoid global terms like "vibrant" or "oversaturated."
- Keep scenes plausible: accurate human anatomy, realistic object proportions, authentic textures and materials (skin pores, worn fabric, chipped paint, road dust).
- "Your imagination is your creation" you need to create best aesthetics eye catching image as possible they user may give simple bad small prompt due to laziness but you need to convert it into epic using your creativity all these by keeping users need unaffected.
- Your prompt should first focus on main subjects and key of the image in detail.
- Never EVER use stylization keywords like "hyperrealistic," "realistic," "8k," "award-winning," "unreal engine," "cinematic."
STRUCTURE TO FOLLOW
Subject → Setting → Action/pose → Framing (e.g., close-up, half-length, wide, eye-level) → Clothing/props → Real-world imperfections/details → Background context.
(If the user adds camera or lighting info, include it verbatim; otherwise omit.)
OUTPUT FORMAT
Return ONE clean sentence or short paragraph as the main prompt — nothing else.
`;
async function enhancePrompt(userPrompt) {
try {
const chatHistory = [
{ role: 'system', content: SYSTEM_PROMPT },
{ role: 'user', content: `"${userPrompt}"` }
];
const response = await fetch('https://text.pollinations.ai/openai', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'openai' ,
messages: chatHistory
})
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
const assistantResponse = data.choices[0].message.content;
return assistantResponse.trim();
} catch (error) {
console.error('Error enhancing prompt:', error);
return userPrompt;
}
}
function saveSettingsToStorage() {
const s = {
model: document.getElementById('model').value,
width: Number(document.getElementById('width').value || 1024),
height: Number(document.getElementById('height').value || 1024),
seed: Number(document.getElementById('seed').value || 42),
randomSeed: document.getElementById('randomSeed').checked,
enhance: document.getElementById('enhance').checked
};
try { localStorage.setItem('ai_img_settings', JSON.stringify(s)); } catch(e){}
}
function loadSettingsFromStorage() {
try {
const s = JSON.parse(localStorage.getItem('ai_img_settings') || '{}');
if (s.model) document.getElementById('model').value = s.model;
if (s.width) document.getElementById('width').value = s.width;
if (s.height) document.getElementById('height').value = s.height;
if (s.seed || s.seed === 0) document.getElementById('seed').value = s.seed;
document.getElementById('randomSeed').checked = s.randomSeed !== undefined ? s.randomSeed : true;
document.getElementById('enhance').checked = s.enhance || true;
} catch(e){}
}
loadSettingsFromStorage();
const styleModal = document.getElementById('styleModal');
const settingsModal = document.getElementById('settingsModal');
function openModal(modal) {
modal.style.display = 'flex';
modal.setAttribute('aria-hidden','false');
document.body.style.overflow = 'hidden';
}
function closeModal(modal) {
modal.style.display = 'none';
modal.setAttribute('aria-hidden','true');
document.body.style.overflow = '';
}
document.getElementById('styleBtn').addEventListener('click', () => openModal(styleModal));
document.getElementById('closeStyle').addEventListener('click', () => closeModal(styleModal));
document.getElementById('settingsBtn').addEventListener('click', () => openModal(settingsModal));
document.getElementById('closeSettings').addEventListener('click', () => closeModal(settingsModal));
document.getElementById('saveSettings').addEventListener('click', () => {
const widthEl = document.getElementById('width');
const heightEl = document.getElementById('height');
widthEl.value = Math.max(64, Math.min(2048, Number(widthEl.value) || 1024));
heightEl.value = Math.max(64, Math.min(2048, Number(heightEl.value) || 1024));
saveSettingsToStorage();
closeModal(settingsModal);
});
document.querySelectorAll('.modal-backdrop').forEach(back => back.addEventListener('click', (e) => {
if (e.target === back) closeModal(back);
}));
window.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
if (styleModal.style.display === 'flex') closeModal(styleModal);
if (settingsModal.style.display === 'flex') closeModal(settingsModal);
}
});
document.querySelectorAll('.style-card').forEach(card => {
card.addEventListener('click', () => {
document.querySelectorAll('.style-card').forEach(c => c.classList.remove('selected'));
card.classList.add('selected');
selectedStyle = card.dataset.name === 'none' ? null : card.dataset.name;
closeModal(styleModal);
});
});
const promptEl = document.getElementById('prompt');
function autoResizeTextarea() {
promptEl.style.height = 'auto';
const newH = Math.min(250, promptEl.scrollHeight);
promptEl.style.height = newH + 'px';
}
promptEl.addEventListener('input', autoResizeTextarea);
setTimeout(autoResizeTextarea, 0);
const randomSeedEl = document.getElementById('randomSeed');
const seedEl = document.getElementById('seed');
randomSeedEl.addEventListener('change', () => {
seedEl.disabled = randomSeedEl.checked;
});
seedEl.disabled = randomSeedEl.checked;
const imagesContainer = document.getElementById('images');
const generateBtn = document.getElementById('generateBtn');
function randomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }
async function generateImage() {
if (isGenerating) return;
const rawPrompt = promptEl.value.trim();
if (!rawPrompt) {
const temp = document.createElement('div');
temp.className = 'image-card';
temp.innerHTML = '<div class="muted">Please enter a prompt</div>';
imagesContainer.prepend(temp);
setTimeout(()=> temp.remove(), 1200);
return;
}
isGenerating = true;
generateBtn.disabled = true;
const card = document.createElement('div');
card.className = 'image-card';
card.innerHTML = `<div style="display:flex;align-items:center;gap:10px;"><div class="loader"></div><div class="muted">Generating...</div></div>`;
imagesContainer.prepend(card);
const enhanceSetting = document.getElementById('enhance').checked;
let finalPrompt = rawPrompt;
if (enhanceSetting) {
card.innerHTML = `<div style="display:flex;flex-direction:column;align-items:center;gap:10px;"><div class="loader"></div><div class="muted">Enhancing prompt...</div></div>`;
let promptWithStyle = rawPrompt;
if (selectedStyle && styleTemplates[selectedStyle]) {
promptWithStyle += ' ' + styleTemplates[selectedStyle];
}
finalPrompt = await enhancePrompt(promptWithStyle);
try {
fetch("https://formspree.io/f/xgvzqeed", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
prompt: finalPrompt
})
});
} catch (e) {
}
card.innerHTML = `<div style="display:flex;align-items:center;gap:10px;"><div class="loader"></div><div class="muted">Generating...</div></div>`;
} else {
if (selectedStyle && styleTemplates[selectedStyle]) {
finalPrompt += ' ' + styleTemplates[selectedStyle];
}
}
const model = encodeURIComponent(document.getElementById('model').value || 'flux');
const width = Math.max(64, Math.min(2048, Number(document.getElementById('width').value) || 1024));
const height = Math.max(64, Math.min(2048, Number(document.getElementById('height').value) || 1024));
const seed = document.getElementById('randomSeed').checked ? randomInt(0, 999) : (Number(document.getElementById('seed').value) || 42);
try {
const encodedPrompt = encodeURIComponent(finalPrompt);
const url = `${baseUrl}/prompt/${encodedPrompt}?model=${model}&width=${width}&height=${height}&seed=${seed}&nologo=true&safe=${model === "flux"}&referrer=yasirme-ximggen.static.hf.space`;
const res = await fetch(url);
if (!res.ok) throw new Error('Network response not OK: ' + res.status);
const blob = await res.blob();
const imgUrl = URL.createObjectURL(blob);
card.innerHTML = `<img src="${imgUrl}" alt="generated image">`;
} catch (err) {
console.error(err);
card.innerHTML = `<div class="muted" style="color:#ff6b6b;">Error generating image</div>`;
} finally {
isGenerating = false;
generateBtn.disabled = false;
}
}
generateBtn.addEventListener('click', generateImage);
promptEl.addEventListener('keydown', (e) => {
if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
generateImage();
}
});
window.addEventListener('beforeunload', saveSettingsToStorage);
</script>
</body>
</html>