Как управлять генерацией и получать точные изображения - 7Post

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Генератор изображений по описанию</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    }

    body {
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      min-height: 100vh;
      padding: 20px;
      display: flex;
      justify-content: center;
      align-items: flex-start;
    }

    .container {
      background: #fff;
      border-radius: 20px;
      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
      padding: 30px;
      max-width: 820px;
      width: 100%;
    }

    h1 {
      color: #333;
      margin-bottom: 8px;
      text-align: center;
      font-size: 28px;
    }

    .subtitle {
      text-align: center;
      color: #777;
      margin-bottom: 25px;
      font-size: 14px;
    }

    .form-group {
      margin-bottom: 16px;
    }

    label {
      display: block;
      margin-bottom: 5px;
      color: #555;
      font-weight: 500;
      font-size: 14px;
    }

    textarea {
      width: 100%;
      min-height: 100px;
      padding: 12px;
      border: 2px solid #e0e0e0;
      border-radius: 10px;
      font-size: 15px;
      resize: vertical;
      transition: border-color 0.3s;
      font-family: inherit;
    }

    textarea:focus {
      outline: none;
      border-color: #667eea;
    }

    .options {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
      gap: 12px;
      margin-bottom: 16px;
    }

    .options select,
    .options input[type="number"],
    .options input[type="text"] {
      width: 100%;
      padding: 10px;
      border: 2px solid #e0e0e0;
      border-radius: 10px;
      font-size: 14px;
      background: #fff;
      cursor: pointer;
      transition: border-color 0.3s;
    }

    .options select:focus,
    .options input:focus {
      outline: none;
      border-color: #667eea;
    }

    .extra-options {
      display: flex;
      flex-wrap: wrap;
      gap: 16px 24px;
      margin-bottom: 18px;
      padding: 14px 16px;
      background: #f8f9fc;
      border-radius: 12px;
      border: 1px solid #e9ecf2;
    }

    .extra-options .checkbox-group {
      display: flex;
      align-items: center;
      gap: 6px;
      font-size: 14px;
      color: #444;
      cursor: pointer;
    }

    .extra-options .checkbox-group input[type="checkbox"] {
      width: 17px;
      height: 17px;
      accent-color: #667eea;
      cursor: pointer;
    }

    .btn {
      width: 100%;
      padding: 14px;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      color: #fff;
      border: none;
      border-radius: 10px;
      font-size: 16px;
      font-weight: 600;
      cursor: pointer;
      transition: transform 0.2s, box-shadow 0.2s;
    }

    .btn:hover:not(:disabled) {
      transform: translateY(-2px);
      box-shadow: 0 10px 20px rgba(102, 126, 234, 0.4);
    }

    .btn:disabled {
      opacity: 0.6;
      cursor: not-allowed;
    }

    .result {
      margin-top: 25px;
      text-align: center;
    }

    .loader {
      display: none;
      margin: 30px auto;
      width: 50px;
      height: 50px;
      border: 5px solid #f3f3f3;
      border-top: 5px solid #667eea;
      border-radius: 50%;
      animation: spin 1s linear infinite;
    }

    @keyframes spin {
      0% {
        transform: rotate(0deg);
      }
      100% {
        transform: rotate(360deg);
      }
    }

    .loader-text {
      display: none;
      color: #666;
      margin-top: 10px;
      font-size: 14px;
    }

    #resultImage {
      max-width: 100%;
      border-radius: 12px;
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
      display: none;
      margin: 0 auto;
    }

    .download-btn {
      display: none;
      margin-top: 15px;
      padding: 10px 25px;
      background: #28a745;
      color: #fff;
      border: none;
      border-radius: 8px;
      font-size: 14px;
      cursor: pointer;
      text-decoration: none;
      transition: background 0.2s;
    }

    .download-btn:hover {
      background: #218838;
    }

    .error {
      display: none;
      background: #fee;
      color: #c33;
      padding: 12px;
      border-radius: 8px;
      margin-top: 15px;
      border: 1px solid #fcc;
    }

    .examples {
      margin-top: 20px;
      padding: 15px;
      background: #f8f9fa;
      border-radius: 10px;
    }

    .examples h3 {
      font-size: 14px;
      color: #555;
      margin-bottom: 10px;
    }

    .example-chip {
      display: inline-block;
      padding: 6px 14px;
      margin: 4px 4px 4px 0;
      background: #fff;
      border: 1px solid #ddd;
      border-radius: 20px;
      font-size: 13px;
      cursor: pointer;
      transition: all 0.2s;
      user-select: none;
    }

    .example-chip:hover {
      background: #667eea;
      color: #fff;
      border-color: #667eea;
    }

    .hint {
      font-size: 13px;
      color: #888;
      margin-top: 6px;
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>🎨 Генератор изображений</h1>
    <p class="subtitle">Опишите картинку — нейросеть создаст её с учётом выбранных стилей</p>

    <div class="form-group">
      <label for="prompt">Описание изображения:</label>
      <textarea id="prompt" placeholder="Например: Космический кот-астронавт, летящий среди галактик"></textarea>
      <div class="hint">Чем детальнее описание, тем точнее результат</div>
    </div>

    <div class="options">
      <div>
        <label for="size">Размер:</label>
        <select id="size">
          <option value="1024x1024">1:1 (1024×1024)</option>
          <option value="1280x720">16:9 (1280×720)</option>
          <option value="720x1280">9:16 (720×1280)</option>
          <option value="1024x768">4:3 (1024×768)</option>
          <option value="768x1024">3:4 (768×1024)</option>
        </select>
      </div>
      <div>
        <label for="model">Модель:</label>
        <select id="model">
          <option value="flux">Flux (качество)</option>
          <option value="flux-realism">Flux Realism</option>
          <option value="flux-anime">Flux Anime</option>
          <option value="flux-3d">Flux 3D</option>
          <option value="turbo">Turbo (быстро)</option>
        </select>
      </div>
      <div>
        <label for="seed">Seed (необяз.):</label>
        <input type="number" id="seed" placeholder="Случайный" min="1" max="999999999" />
      </div>
    </div>

    <!-- Дополнительные настройки для уточнения -->
    <div class="extra-options">
      <div class="checkbox-group">
        <input type="checkbox" id="enableStyle" checked />
        <label for="enableStyle">Добавить стиль</label>
      </div>
      <div>
        <label for="styleSelect" style="display:inline-block; margin-right:6px; font-weight:500; font-size:14px;">Стиль:</label>
        <select id="styleSelect" style="padding:6px 10px; border-radius:8px; border:1px solid #ccc; font-size:14px;">
          <option value="realistic">Реалистичный</option>
          <option value="anime">Аниме</option>
          <option value="3d">3D-рендеринг</option>
          <option value="oil painting">Живопись маслом</option>
          <option value="watercolor">Акварель</option>
          <option value="cyberpunk">Киберпанк</option>
          <option value="fantasy">Фэнтези</option>
          <option value="scifi">Научная фантастика</option>
          <option value="cinematic">Кинематографичный</option>
        </select>
      </div>
      <div class="checkbox-group">
        <input type="checkbox" id="enhanceDetails" checked />
        <label for="enhanceDetails">Детализация</label>
      </div>
      <div class="checkbox-group">
        <input type="checkbox" id="photorealistic" checked />
        <label for="photorealistic">Фотореализм</label>
      </div>
    </div>

    <button class="btn" id="generateBtn" onclick="generateImage()">✨ Создать изображение</button>

    <div class="result">
      <div class="loader" id="loader"></div>
      <div class="loader-text" id="loaderText">Генерируем изображение... это может занять 10–30 секунд</div>
      <img id="resultImage" alt="Сгенерированное изображение" />
      <br />
      <a id="downloadBtn" class="download-btn" download="generated-image.png">⬇️ Скачать изображение</a>
      <div class="error" id="errorMsg"></div>
    </div>

    <div class="examples">
      <h3>💡 Примеры запросов (нажмите, чтобы вставить):</h3>
      <span class="example-chip" onclick="setPrompt(this)">Уютный домик в осеннем лесу, тёплый свет из окон, туман, закат</span>
      <span class="example-chip" onclick="setPrompt(this)">Футуристический киберпанк-город ночью, неоновые вывески, дождь</span>
      <span class="example-chip" onclick="setPrompt(this)">Милый котёнок в шляпе волшебника, окружённый магическими книгами</span>
      <span class="example-chip" onclick="setPrompt(this)">Подводный мир с кораллами и тропическими рыбками, солнечные лучи</span>
      <span class="example-chip" onclick="setPrompt(this)">Космическая станция на орбите Сатурна, вид на кольца планеты</span>
    </div>
  </div>

  <script>
    function setPrompt(el) {
      document.getElementById('prompt').value = el.textContent;
      document.getElementById('prompt').focus();
    }

    async function generateImage() {
      const promptInput = document.getElementById('prompt');
      const size = document.getElementById('size').value;
      const model = document.getElementById('model').value;
      const seed = document.getElementById('seed').value;
      const btn = document.getElementById('generateBtn');
      const loader = document.getElementById('loader');
      const loaderText = document.getElementById('loaderText');
      const resultImage = document.getElementById('resultImage');
      const downloadBtn = document.getElementById('downloadBtn');
      const errorMsg = document.getElementById('errorMsg');

      // Дополнительные настройки
      const enableStyle = document.getElementById('enableStyle').checked;
      const style = document.getElementById('styleSelect').value;
      const enhanceDetails = document.getElementById('enhanceDetails').checked;
      const photorealistic = document.getElementById('photorealistic').checked;

      let prompt = promptInput.value.trim();

      if (!prompt) {
        errorMsg.textContent = '❌ Пожалуйста, введите описание изображения';
        errorMsg.style.display = 'block';
        return;
      }

      // Сброс предыдущих результатов
      errorMsg.style.display = 'none';
      resultImage.style.display = 'none';
      downloadBtn.style.display = 'none';
      loader.style.display = 'block';
      loaderText.style.display = 'block';
      btn.disabled = true;
      btn.textContent = '⏳ Генерация...';

      // --- Улучшаем промпт дополнительными ключевыми словами ---
      let enhancedPrompt = prompt;

      // Добавляем стиль, если включено
      if (enableStyle && style && style !== 'realistic') {
        // Для реалистичного не добавляем отдельно, т.к. он базовый
        enhancedPrompt += `, ${style} style`;
      }

      // Добавляем слова для детализации
      if (enhanceDetails) {
        enhancedPrompt += ', highly detailed, intricate details, sharp focus, masterpiece';
      }

      // Добавляем фотореализм
      if (photorealistic) {
        enhancedPrompt += ', photorealistic, 8k, ultra realistic, high quality';
      }

      // Если выбрана модель flux-realism, дополнительно подчёркиваем реализм
      if (model === 'flux-realism') {
        enhancedPrompt += ', realistic, lifelike';
      }

      // Если аниме-модель — добавим аниме-стиль, если не добавлен
      if (model === 'flux-anime' && !enhancedPrompt.includes('anime')) {
        enhancedPrompt += ', anime style';
      }

      if (model === 'flux-3d' && !enhancedPrompt.includes('3d')) {
        enhancedPrompt += ', 3d render';
      }

      const [width, height] = size.split('x');

      // Формируем URL для Pollinations.ai
      let url =
        `https://image.pollinations.ai/prompt/${encodeURIComponent(enhancedPrompt)}?width=${width}&height=${height}&model=${model}&nologo=true&enhance=true`;
      if (seed) {
        url += `&seed=${seed}`;
      }

      try {
        const img = new Image();
        img.crossOrigin = 'anonymous';

        img.onload = function () {
          resultImage.src = url;
          resultImage.style.display = 'block';
          downloadBtn.href = url;
          downloadBtn.style.display = 'inline-block';
          loader.style.display = 'none';
          loaderText.style.display = 'none';
          btn.disabled = false;
          btn.textContent = '✨ Создать изображение';
        };

        img.onerror = function () {
          throw new Error('Не удалось загрузить изображение. Проверьте описание или попробуйте другой стиль.');
        };

        img.src = url;
      } catch (error) {
        loader.style.display = 'none';
        loaderText.style.display = 'none';
        errorMsg.textContent = '❌ Ошибка: ' + error.message;
        errorMsg.style.display = 'block';
        btn.disabled = false;
        btn.textContent = '✨ Создать изображение';
      }
    }

    // Генерация по Ctrl+Enter
    document.getElementById('prompt').addEventListener('keydown', function (e) {
      if (e.ctrlKey && e.key === 'Enter') {
        generateImage();
      }
    });
  </script>
</body>
</html>

Теперь вы можете влиять на результат через несколько дополнительных параметров:

Стиль — выберите из списка (реализм, аниме, 3D, живопись и др.), чтобы задать общее настроение и визуальный язык.

Детализация — при включении добавляет в промпт ключевые слова для проработки мелких элементов и резкости.

Фотореализм — усиливает эффект фотографической достоверности, добавляя запросы на высокое разрешение и реалистичность.

Модель — можно выбрать специализированную версию Flux (для аниме, 3D, реализма) или быстрый Turbo.

Дополнительно вы можете указать seed для воспроизводимости результата или использовать примеры запросов — они вставляются в поле описания по клику. Готовое изображение можно скачать кнопкой под ним.

Оптимизация: Для более точной генерации я рекомендую комбинировать стиль и фотореализм с детальным описанием. Например, «закат над горами» + «реалистичный» + «фотореализм» даст более насыщенный и правдоподобный результат.