🏖️ Summer Update: Retro cleanup, QOL, optimized JPEG output

This commit is contained in:
mrkmntal 2025-06-22 18:35:05 -04:00
commit cb3ccd80c0
6 changed files with 421 additions and 392 deletions

207
README.md
View file

@ -1,92 +1,179 @@
# Legacy Stable Diffusion WebUI
# Legacy Stable Diffusion WebUI — Summer Update ☀️
![phpsd-logo-256](https://github.com/user-attachments/assets/9ca5934f-97e2-4885-bf06-a93dcfc393a6)
A minimalistic, **JavaScript-free** web interface for Stable Diffusion, designed for compatibility with **legacy web browsers** like Internet Explorer 4, Netscape 4.x, and even Classilla on Mac OS 9.
Built for long-term access to AI image generation using the AUTOMATIC1111 API — from modern GPUs to vintage clients.
A minimalistic, JavaScript-free web interface, front-end and processing server for Stable Diffusion, designed specifically for being accessed by legacy systems and browsers as clients. This interface relies on the API from AUTOMATIC1111's Stable Diffusion WebUI.
---
## Features
- No JavaScript dependencies
- Lightweight and fast loading
- Support for LORA models using square bracket syntax
- Image optimization with automatic PNG to JPG conversion
- Prompt saving and loading functionality
- Full configurability of key generation parameters:
- Image dimensions
- Sampling steps
- CFG Scale
- Choice of sampling methods
- Negative prompt support (1-19-2025 Update)
- Optimized default parameters for better quality images by default (1-19-2025 Update)
## 🆕 Summer 2025 Update Highlights
## Browser Compatibility
- 🗂 **File structure cleanup** Generation, prompt saving, and UI now fully separated for better maintainability.
- ⏳ **True loading screen** `loading.php` now displays a loading message before generation starts.
- 💾 **"Save Prompt" moved to result page** Save your prompt right after generation from `result.php`.
- 📉 **Improved compression** Lowered ImageMagick quality to 75 (from 85) for **9093% file size reduction**.
- ✅ **Default sampler set to `Euler a`**, which works especially well with **Illustrious XL** (the recommended model).
- 🧼 Overall code quality and parameter consistency improved.
- `index.php`: Tested working on IE4+, Netscape 4.x and above browsers (HTML 4 compliant)
---
## Requirements
## 🔧 Features
- Linux server with a suitable GPU; running a model in AUTOMATIC1111's Stable Diffusion WebUI https://github.com/AUTOMATIC1111/stable-diffusion-webui with API access (image generation back-end)
- Externally accessible Linux server running PHP 8+ to run the PHP front-end (Tested on frankenphp running on Debian 12, should also run with traditional PHP setups with apache/nginx, can run on the same server as the back-end)
- Web server (Apache, nginx, etc.)
- ImageMagick for image optimization
- Curl
- Client machine to access the front-end via web browser
- No JavaScript — 100% HTML 4.01 and PHP
- Ultra-lightweight for slow or vintage clients
- LORA model support via `[name:weight]` syntax
- Prompt saving and loading via `saved-prompts.json`
- Server-side PNG ➜ JPG conversion with ImageMagick
- Compatible with AUTOMATIC1111 Stable Diffusion WebUI
- Configurable generation settings:
- Image size
- CFG scale
- Steps
- Sampler method
- Negative prompt support
---
## Installation
## 🌐 Browser Compatibility
1. Ensure you have AUTOMATIC1111's Stable Diffusion WebUI running with the `--api` flag
2. Install PHP and ImageMagick on your system
3. Copy both `index.php` to your web server directory
4. Ensure the directory is writable by the web server for saved prompts and generated images
5. Access through your web browser:
- Use `index.php` for HTML 4.01+ compatible browsers
Tested on:
## Usage
- ✅ Internet Explorer 46 (Windows 952000)
- ✅ Netscape 4.x
- ✅ Classilla (Mac OS 9)
- ✅ Firefox ESR 102+ (modern systems)
1. Enter your prompt and negative prompt if applicable in the text area
2. Configure generation parameters as needed
3. Click "Generate Image" to create your image
4. Save frequently used prompts server-side using the "Save Prompt" feature
5. Load saved prompts from the dropdown menu
---
## LORA Usage
## 📦 Requirements
To use LORA models, include them in your prompt using square brackets:
```[lora-name:weight]```
- **Back-end:**
AUTOMATIC1111 Stable Diffusion WebUI running with `--api`
https://github.com/AUTOMATIC1111/stable-diffusion-webui
- **Front-end Server:**
Linux server with:
- PHP 8+
- ImageMagick
- cURL
- Any web server (Apache, nginx, or FrankenPHP)
- **Client:**
Any browser capable of submitting forms and rendering HTML 4.01
(Yes, it really works on Windows NT 4.0)
---
## 🧪 Installation
1. Start AUTOMATIC1111's WebUI with `--api`
2. Install PHP and ImageMagick on your web server
3. Place `index.php`, `loading.php`, `generate.php`, and `result.php` in your web directory
4. Ensure write permissions for:
- `saved-prompts.json`
- Your web server's root directory containing the phpsd files, this is where images will be stored
5. Access `index.php` from a browser and start generating!
---
## 🧭 Usage Guide
1. Open `index.php`
2. Type your prompt and negative prompt (optional)
3. Adjust generation parameters
4. Submit ➜ loading screen ➜ image result
5. Save your favorite prompts directly from `result.php`
---
## 🧠 LORA Support
Use the syntax:
```text
[lora-name:weight]
````
Example:
```a beautiful landscape by [my-artist-lora:0.8]```
## Notes
```text
a high-detail wizard portrait [wizard-style:0.8]
```
- Images are automatically optimized and converted from PNG to JPG for faster loading
- The interface works without any client-side scripting
- All processing is done server-side
- Compatible with browsers from the late 1990s to now
Weight values typically range from `0.1` to `1.0`
## Screenshots
---
### Running on Windows NT 4.0 With IE 4
![Screenshot 2024-12-14 142743](https://github.com/user-attachments/assets/838095cb-0af7-4c6e-a140-78e8f7c65691)
## 📸 Image Processing Notes
### Running on Debian 12 With Firefox ESR 115
![Screenshot 2024-12-14 143036](https://github.com/user-attachments/assets/9745d00f-57cc-4788-a17d-43782d7e6fa3)
* Generated PNGs are automatically converted to optimized JPGs
* ImageMagick runs with:
```
-quality 75 -strip -interlace Plane -gaussian-blur 0.05 -sampling-factor 4:2:0
```
* Resulting file sizes reduced by \~9093%, ideal for slow connections and legacy hardware
---
## 🧭 System Architecture
Below is a flowchart diagram representing the separation of concerns between the legacy client and the backend server during prompt submission and image generation.
![Screenshot 2025-06-22 182155](https://github.com/user-attachments/assets/28e9aa66-42d8-4820-bfd9-6b4b23571188)
---
## 🖥️ Screenshots
### Running on Windows 2000 SP2 with IE 5 — Illustrious XL Output (June 22, 2025 Summer Update)
![Gura sample](https://github.com/user-attachments/assets/afa2366b-1760-47da-a7d6-12465b1ba076)
This image was generated using `Euler a` sampler and the Illustrious XL model, processed entirely through the `phpsd` legacy frontend. Displayed here in Internet Explorer 5 on Windows 2000 SP2.
### Running on Mac OS 9 + Classilla
### Running on Mac OS 9 With Classilla
![screenshot2](https://github.com/user-attachments/assets/5284613c-9060-49d4-aed6-5d7fa1d041d3)
### Firefox ESR 115 on Debian 12
## Contributing
![Screenshot 2024-12-14 143036](https://github.com/user-attachments/assets/9745d00f-57cc-4788-a17d-43782d7e6fa3)
Contributions are welcome! Please feel free to submit a Pull Request or fork.
---
## License
## 🖼️ Legacy Wallpaper Output
This project is MIT licensed.
Dont just generate — **decorate**.
All generated images are:
- Optimized for ultra-low size (JPG @ quality 75)
- CRT-safe resolution options
- Perfect for Retro PC wallpapers
Whether youre browsing from Classilla or setting your ThinkPad T21s background, `phpsd` delivers.
## 🤝 Contributing
Pull requests, forks, and retro tweaks welcome!
Feel free to adapt the UI for even older setups or customize layouts per browser profile.
---
## 📜 License
MIT License
---
## 🧠 Credits
* Front-end & optimization by markmental
* Powered by [AUTOMATIC1111s Stable Diffusion WebUI](https://github.com/AUTOMATIC1111/stable-diffusion-webui)
---
## Credits
Built to work with AUTOMATIC1111's Stable Diffusion WebUI API:
https://github.com/AUTOMATIC1111/stable-diffusion-webui

101
generate.php Normal file
View file

@ -0,0 +1,101 @@
<?php
// generate.php
session_start();
ini_set('max_execution_time', '300');
header('Content-Type: text/html; charset=iso-8859-1');
// Input values
$prompt = $_POST['prompt'] ?? '';
$negative_prompt = $_POST['negative_prompt'] ?? '';
$width = isset($_POST['width']) ? (int)$_POST['width'] : 512;
$height = isset($_POST['height']) ? (int)$_POST['height'] : 512;
$steps = isset($_POST['steps']) ? (int)$_POST['steps'] : 20;
$cfg_scale = isset($_POST['cfg_scale']) ? (float)$_POST['cfg_scale'] : 7.5;
$sampler = $_POST['sampler'] ?? 'Euler';
// Input validation
if (strpos($prompt, '<') !== false || strpos($prompt, '>') !== false) {
die("Error: Angle brackets are not allowed in prompts.");
}
// Convert LORA-style square bracket syntax
$processed_prompt = preg_replace('/\[([\w\s\-]+?):([\d\.]+)\]/', '<lora:$1:$2>', $prompt);
// Build request
$data = array(
'prompt' => $processed_prompt,
'negative_prompt' => $negative_prompt,
'steps' => $steps,
'width' => $width,
'height' => $height,
'cfg_scale' => $cfg_scale,
'sampler_name' => $sampler,
'override_settings' => new stdClass(),
'override_settings_restore_afterwards' => true
);
// Call Stable Diffusion API
$ch = curl_init('http://127.0.0.1:7860/sdapi/v1/txt2img');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
$result = curl_exec($ch);
curl_close($ch);
if (!$result) {
die("Error: Failed to communicate with the image generation API.");
}
$decoded = json_decode($result, true);
if (!isset($decoded['images'][0])) {
die("Error: No image returned.");
}
// Decode base64 PNG
$image_data = base64_decode($decoded['images'][0]);
// Save original PNG temporarily
$temp_png = 'temp_' . time() . '_' . bin2hex(random_bytes(8)) . '.png';
file_put_contents($temp_png, $image_data);
// Convert PNG to JPG with ImageMagick
$generated_image = 'generated_' . time() . '_' . bin2hex(random_bytes(8)) . '.jpg';
$quality = 75;
$cmd = "convert \"$temp_png\" -strip -interlace Plane -gaussian-blur 0.05 -quality $quality -sampling-factor 4:2:0 \"$generated_image\" 2>&1";
exec($cmd, $output, $returnVar);
// Get image size info
if ($returnVar !== 0 || !file_exists($generated_image)) {
$generated_image = $temp_png;
$size_info = null;
} else {
$originalSize = filesize($temp_png);
$convertedSize = filesize($generated_image);
unlink($temp_png);
$size_info = array(
'original' => round($originalSize / 1024, 2),
'converted' => round($convertedSize / 1024, 2),
'reduction' => round((($originalSize - $convertedSize) / $originalSize) * 100, 2)
);
}
// Save result to session
$_SESSION['result'] = array(
'generated_image' => $generated_image,
'prompt' => $prompt,
'negative_prompt' => $negative_prompt,
'processed_prompt' => $processed_prompt,
'width' => $width,
'height' => $height,
'steps' => $steps,
'cfg_scale' => $cfg_scale,
'sampler' => $sampler,
'size_info' => $size_info
);
// Redirect to result page
header("Location: result.php");
exit;

386
index.php
View file

@ -2,22 +2,8 @@
ini_set('max_execution_time', '300');
header('Content-Type: text/html; charset=iso-8859-1');
$response = "";
$generated_image = "";
$prompt = "";
$negative_prompt = "";
$width = 768;
$height = 768;
$steps = 35;
$cfg_scale = 3;
$sampler = "DPM++ 3M SDE";
$error_message = "";
$success_message = "";
// File to store saved prompts
$saved_prompts_file = 'saved-prompts.json';
// Load saved prompts
function loadSavedPrompts() {
global $saved_prompts_file;
if (file_exists($saved_prompts_file)) {
@ -27,366 +13,102 @@ function loadSavedPrompts() {
return array();
}
// Save a new prompt
function savePrompt($prompt_text, $negative_prompt_text, $prompt_name) {
global $saved_prompts_file;
$prompts = loadSavedPrompts();
$prompts[$prompt_name] = array(
'prompt' => $prompt_text,
'negative_prompt' => $negative_prompt_text
);
file_put_contents($saved_prompts_file, json_encode($prompts, JSON_PRETTY_PRINT));
}
$saved_prompts = loadSavedPrompts();
// List of available samplers
$samplers = array(
"Euler",
"Euler a",
"Heun",
"DPM2",
"DPM2 a",
"DPM++ 2S a",
"DPM++ 2M",
"DPM++ SDE",
"DPM++ 2M SDE",
"DPM++ 3M SDE",
"DPM fast",
"DPM adaptive",
"LMS",
"DPM++ SDE Karras",
"DPM++ 2M SDE Karras",
"DPM++ 3M SDE Karras",
"DDIM",
"PLMS"
);
$prompt = '';
$negative_prompt = '';
$width = 768;
$height = 768;
$steps = 35;
$cfg_scale = 3;
$sampler = "Euler a";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// All requests to the server to save or execute prompts will be POST requests to itself
// Handle prompt saving
if (isset($_POST['save_prompt']) && isset($_POST['prompt_name'])) {
$prompt_to_save = trim($_POST['prompt']);
$negative_prompt_to_save = trim($_POST['negative_prompt']);
$prompt_name = trim($_POST['prompt_name']);
if (!empty($prompt_to_save) && !empty($prompt_name)) {
savePrompt($prompt_to_save, $negative_prompt_to_save, $prompt_name);
$success_message = "Prompt saved successfully!";
$saved_prompts = loadSavedPrompts(); // Reload prompts
} else {
$error_message = "Both prompt and prompt name are required to save.";
}
}
// Handle image generation
else {
$prompt = isset($_POST['prompt']) ? $_POST['prompt'] : '';
$negative_prompt = isset($_POST['negative_prompt']) ? $_POST['negative_prompt'] : '';
$width = isset($_POST['width']) ? (int)$_POST['width'] : 512;
$height = isset($_POST['height']) ? (int)$_POST['height'] : 512;
$steps = isset($_POST['steps']) ? (int)$_POST['steps'] : 20;
$cfg_scale = isset($_POST['cfg_scale']) ? (float)$_POST['cfg_scale'] : 7.5;
$sampler = isset($_POST['sampler']) ? $_POST['sampler'] : 'Euler';
// Check for angle brackets in the prompt
if (strpos($prompt, '<') !== false || strpos($prompt, '>') !== false) {
$error_message = "Error: Angle brackets are not allowed in the prompt. Please use square brackets [lora-name:weight] for LORAs.";
}
// Only proceed if there's no error
elseif (!empty($prompt)) {
// Process the prompt to handle LORA syntax
$processed_prompt = preg_replace('/\[([\w\s\-]+?):([\d\.]+)\]/', '<lora:$1:$2>', $prompt);
$data = array(
'prompt' => $processed_prompt,
'negative_prompt' => $negative_prompt,
'steps' => $steps,
'width' => $width,
'height' => $height,
'cfg_scale' => $cfg_scale,
'sampler_name' => $sampler,
'override_settings' => new stdClass(),
'override_settings_restore_afterwards' => true
);
// Replace 127.0.0.1 with your Stable diffusion server's IP if running externally
$ch = curl_init('http://127.0.0.1:7860/sdapi/v1/txt2img');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
$result = curl_exec($ch);
if (curl_errno($ch)) {
$response = 'Error: ' . curl_error($ch);
} else {
$decoded = json_decode($result, true);
if (isset($decoded['images'][0])) {
$image_data = base64_decode($decoded['images'][0]);
// Save original PNG temporarily
$temp_png = 'temp_' . time() . '_' . bin2hex(random_bytes(8)) . '.png';
file_put_contents($temp_png, $image_data);
// Create output JPG filename
$generated_image = 'generated_' . time() . '_' . bin2hex(random_bytes(8)) . '.jpg';
// Build ImageMagick convert command with optimization
$quality = 85; // Balanced quality setting
$cmd = "convert \"$temp_png\" -strip -interlace Plane -gaussian-blur 0.05 -quality $quality ";
$cmd .= "-sampling-factor 4:2:0 \"$generated_image\" 2>&1";
// Execute conversion
$output = [];
$returnVar = 0;
exec($cmd, $output, $returnVar);
if ($returnVar === 0 && file_exists($generated_image)) {
// Get file sizes for comparison
$originalSize = filesize($temp_png);
$convertedSize = filesize($generated_image);
// Clean up temporary PNG file
if (file_exists($temp_png)) {
unlink($temp_png);
}
// Clean up old generated files
foreach (glob("generated_*.png") as $file) {
if ($file != $generated_image && (time() - filemtime($file)) > 3600) {
unlink($file);
}
}
// Store size information for display
$size_info = array(
'original' => round($originalSize / 1024, 2),
'converted' => round($convertedSize / 1024, 2),
'reduction' => round((($originalSize - $convertedSize) / $originalSize) * 100, 2)
);
} else {
// If conversion fails, keep the original PNG
if (file_exists($temp_png)) {
$generated_image = $temp_png;
}
$error_message = "Image conversion failed. Using original PNG format.";
}
}
}
curl_close($ch);
}
}
} else if ($_SERVER["REQUEST_METHOD"] == "GET" && isset($_GET['load_prompt'])) {
// For loading prompts we use GET method to send the client's choice of prompt to load
// Load saved prompt into textarea
$saved_prompts = loadSavedPrompts();
if ($_SERVER["REQUEST_METHOD"] == "GET" && isset($_GET['load_prompt'])) {
if (isset($saved_prompts[$_GET['load_prompt']])) {
// Check if the saved prompt is in the new format (array) or old format (string)
if (is_array($saved_prompts[$_GET['load_prompt']])) {
$prompt = $saved_prompts[$_GET['load_prompt']]['prompt'];
$negative_prompt = $saved_prompts[$_GET['load_prompt']]['negative_prompt'];
} else {
// Handle old format
$prompt = $saved_prompts[$_GET['load_prompt']];
$negative_prompt = '';
}
}
}
$samplers = array(
"Euler", "Euler a", "Heun", "DPM2", "DPM2 a", "DPM++ 2S a", "DPM++ 2M",
"DPM++ SDE", "DPM++ 2M SDE", "DPM++ 3M SDE", "DPM fast", "DPM adaptive",
"LMS", "DPM++ SDE Karras", "DPM++ 2M SDE Karras", "DPM++ 3M SDE Karras",
"DDIM", "PLMS"
);
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!DOCTYPE HTML>
<html>
<head>
<title>Stable Diffusion Image Generator</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css">
.lora-help {
background-color: #f8f8f8;
padding: 10px;
margin: 10px 0;
border: 1px solid #ddd;
}
.form-group {
margin-bottom: 15px;
}
textarea#prompt {
width: 100%;
height: 100px;
padding: 8px;
font-family: Arial, sans-serif;
font-size: 14px;
border: 1px solid #ddd;
}
textarea#negative_prompt {
width: 100%;
height: 100px;
padding: 8px;
font-family: Arial, sans-serif;
font-size: 14px;
border: 1px solid #ddd;
background-color: #fff3f3;
}
.error-message {
color: #dc3545;
background-color: #f8d7da;
border: 1px solid #f5c6cb;
padding: 10px;
margin: 10px 0;
}
.success-message {
color: #28a745;
background-color: #d4edda;
border: 1px solid #c3e6cb;
padding: 10px;
margin: 10px 0;
}
.saved-prompts {
margin: 20px 0;
padding: 15px;
background-color: #f8f8f8;
border: 1px solid #ddd;
}
.save-prompt-form {
margin: 20px 0;
padding: 15px;
background-color: #f8f8f8;
border: 1px solid #ddd;
}
</style>
</head>
<body>
<?php if (isset($_GET['save_success'])): ?>
<div style="color:green;">Prompt saved successfully.</div>
<?php elseif (isset($_GET['save_error'])): ?>
<div style="color:red;">Error: Prompt and name are required.</div>
<?php endif; ?>
<h1>Stable Diffusion Image Generator</h1>
<div class="lora-help">
<h3>How to use LORAs:</h3>
<p>Include LORAs in your prompt using this syntax: <code>[lora-name:weight]</code></p>
<p>Example: <code>a beautiful landscape by [my-artist-lora:0.8]</code></p>
<p>Weight values typically range from 0.1 to 1.0</p>
<p><strong>Note:</strong> Angle brackets (< >) are not allowed in prompts. Use square brackets instead.</p>
<div style="border:1px solid #ccc;padding:10px;margin-bottom:10px;">
<strong>How to use LORAs:</strong>
<p>Use square bracket format: <code>[lora-name:weight]</code></p>
<p>Example: <code>a detailed castle, [my-style-lora:0.7]</code></p>
<p><b>Note:</b> Angle brackets are not allowed.</p>
</div>
<?php if (!empty($error_message)): ?>
<div class="error-message">
<?php echo htmlspecialchars($error_message); ?>
</div>
<?php endif; ?>
<?php if (!empty($success_message)): ?>
<div class="success-message">
<?php echo htmlspecialchars($success_message); ?>
</div>
<?php endif; ?>
<div class="saved-prompts">
<h3>Saved Prompts</h3>
<form method="get" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
<select name="load_prompt">
<option value="">Select a saved prompt</option>
<?php foreach ($saved_prompts as $name => $saved_prompt): ?>
<option value="<?php echo htmlspecialchars($name); ?>"
title="Prompt: <?php echo htmlspecialchars(is_array($saved_prompt) ? $saved_prompt['prompt'] : $saved_prompt); ?>&#13;Negative: <?php echo htmlspecialchars(is_array($saved_prompt) ? $saved_prompt['negative_prompt'] : ''); ?>">
<div>
<form method="get" action="index.php">
<label for="load_prompt">Load Saved Prompt:</label>
<select name="load_prompt" id="load_prompt">
<option value="">-- Choose --</option>
<?php foreach ($saved_prompts as $name => $data): ?>
<option value="<?php echo htmlspecialchars($name); ?>">
<?php echo htmlspecialchars($name); ?>
</option>
<?php endforeach; ?>
</select>
<input type="submit" value="Load Prompt">
<input type="submit" value="Load">
</form>
</div>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
<div class="form-group">
<label for="prompt">Enter your prompt (including LORA syntax if needed):</label><br>
<textarea name="prompt" id="prompt"><?php echo htmlspecialchars($prompt); ?></textarea>
</div>
<form method="post" action="loading.php">
<p><label for="prompt">Prompt:</label><br>
<textarea name="prompt" id="prompt" rows="5" cols="60"><?php echo htmlspecialchars($prompt); ?></textarea></p>
<div class="form-group">
<label for="negative_prompt">Enter your negative prompt (things to avoid in the image):</label><br>
<textarea name="negative_prompt" id="negative_prompt"><?php echo htmlspecialchars($negative_prompt); ?></textarea>
</div>
<p><label for="negative_prompt">Negative Prompt:</label><br>
<textarea name="negative_prompt" id="negative_prompt" rows="5" cols="60"><?php echo htmlspecialchars($negative_prompt); ?></textarea></p>
<div class="form-group">
<label for="width">Width:</label>
<input type="number" name="width" id="width" value="<?php echo $width; ?>" min="64" max="2048" step="64">
</div>
<p>
Width: <input type="number" name="width" value="<?php echo $width; ?>" min="64" max="2048" step="64">
Height: <input type="number" name="height" value="<?php echo $height; ?>" min="64" max="2048" step="64">
</p>
<div class="form-group">
<label for="height">Height:</label>
<input type="number" name="height" id="height" value="<?php echo $height; ?>" min="64" max="2048" step="64">
</div>
<p>
Steps: <input type="number" name="steps" value="<?php echo $steps; ?>" min="1" max="150">
CFG Scale: <input type="number" name="cfg_scale" value="<?php echo $cfg_scale; ?>" min="1" max="30" step="0.5">
</p>
<div class="form-group">
<label for="steps">Steps:</label>
<input type="number" name="steps" id="steps" value="<?php echo $steps; ?>" min="1" max="150">
</div>
<div class="form-group">
<label for="cfg_scale">CFG Scale:</label>
<input type="number" name="cfg_scale" id="cfg_scale" value="<?php echo $cfg_scale; ?>" min="1" max="30" step="0.5">
</div>
<div class="form-group">
<label for="sampler">Sampler:</label>
<select name="sampler" id="sampler">
<p>
Sampler:
<select name="sampler">
<?php foreach ($samplers as $s): ?>
<option value="<?php echo htmlspecialchars($s); ?>" <?php echo $s === $sampler ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($s); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div>
<input type="submit" value="Generate Image">
</div>
</form>
<div class="save-prompt-form">
<h3>Save Current Prompt</h3>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
<div class="form-group">
<label for="prompt_name">Prompt Name:</label>
<input type="text" name="prompt_name" id="prompt_name" required>
</div>
<input type="hidden" name="prompt" value="<?php echo htmlspecialchars($prompt); ?>">
<input type="hidden" name="negative_prompt" value="<?php echo htmlspecialchars($negative_prompt); ?>">
<input type="submit" name="save_prompt" value="Save Prompt">
</form>
</div>
<?php if (!empty($generated_image)): ?>
<div class="result">
<h2>Generated Image:</h2>
<img width="250px" src="<?php echo htmlspecialchars($generated_image); ?>" alt="Generated image"/>
<br/>
<a download href="<?php echo htmlspecialchars($generated_image); ?>">Download Generated Image</a>
<?php if (isset($size_info)): ?>
<div class="size-info">
<p>
Original size: <?php echo $size_info['original']; ?> KB<br>
Converted size: <?php echo $size_info['converted']; ?> KB<br>
Size reduction: <?php echo $size_info['reduction']; ?>%
</p>
</div>
<?php endif; ?>
<div class="parameters">
<strong>Parameters used:</strong><br>
Prompt: <?php echo htmlspecialchars($prompt); ?><br>
Negative Prompt: <?php echo htmlspecialchars($negative_prompt); ?><br>
Processed Prompt: <?php echo htmlspecialchars($processed_prompt); ?><br>
Size: <?php echo $width; ?>x<?php echo $height; ?><br>
Steps: <?php echo $steps; ?><br>
CFG Scale: <?php echo $cfg_scale; ?><br>
Sampler: <?php echo htmlspecialchars($sampler); ?>
</div>
</div>
<?php endif; ?>
<?php if (!empty($response)): ?>
<div class="result">
<h2>Error:</h2>
<p><?php echo htmlspecialchars($response); ?></p>
</div>
<?php endif; ?>
<p><input type="submit" value="Generate Image"></p>
</form>
</body>
</html>

28
loading.php Normal file
View file

@ -0,0 +1,28 @@
<?php
// loading.php
?>
<!DOCTYPE HTML>
<html>
<head>
<title>Generating Image...</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body onload="document.forms[0].submit();">
<h1>Generating Your Image...</h1>
<p>Please wait. This may take up to 30 seconds depending on prompt complexity.</p>
<form method="post" action="generate.php">
<?php
foreach ($_POST as $key => $value):
$safeKey = htmlspecialchars($key, ENT_QUOTES);
$safeValue = htmlspecialchars($value, ENT_QUOTES);
?>
<input type="hidden" name="<?php echo $safeKey; ?>" value="<?php echo $safeValue; ?>">
<?php endforeach; ?>
<noscript>
<p><input type="submit" value="Click here if not redirected."></p>
</noscript>
</form>
</body>
</html>

50
result.php Normal file
View file

@ -0,0 +1,50 @@
<?php
// result.php
session_start();
if (!isset($_SESSION['result'])) {
die("No image generated yet.");
}
$data = $_SESSION['result'];
unset($_SESSION['result']); // clear for next use
?>
<!DOCTYPE HTML>
<html>
<head>
<title>Stable Diffusion Result</title>
</head>
<body>
<h1>Generated Image</h1>
<img width="250px" src="<?php echo htmlspecialchars($data['generated_image']); ?>" alt="Generated image"/><br>
<a download href="<?php echo htmlspecialchars($data['generated_image']); ?>">Download Generated Image</a>
<div class="parameters">
<strong>Parameters used:</strong><br>
Prompt: <?php echo htmlspecialchars($data['prompt']); ?><br>
Negative Prompt: <?php echo htmlspecialchars($data['negative_prompt']); ?><br>
Processed Prompt: <?php echo htmlspecialchars($data['processed_prompt']); ?><br><br>
Size: <?php echo $data['width']; ?>x<?php echo $data['height']; ?><br>
Steps: <?php echo $data['steps']; ?><br>
CFG Scale: <?php echo $data['cfg_scale']; ?><br>
Sampler: <?php echo htmlspecialchars($data['sampler']); ?><br>
<?php if (!empty($data['size_info'])): ?>
<p>
Original size: <?php echo $data['size_info']['original']; ?> KB<br>
Converted size: <?php echo $data['size_info']['converted']; ?> KB<br>
Size reduction: <?php echo $data['size_info']['reduction']; ?>%
</p>
<?php endif; ?>
</div>
<div class="save-prompt-form" style="margin-top:20px;padding:10px;border:1px solid #ccc;">
<h3>Save This Prompt</h3>
<form method="post" action="save-prompt.php">
<label for="prompt_name">Prompt Name:</label><br>
<input type="text" name="prompt_name" id="prompt_name" required>
<input type="hidden" name="prompt" value="<?php echo htmlspecialchars($data['prompt']); ?>">
<input type="hidden" name="negative_prompt" value="<?php echo htmlspecialchars($data['negative_prompt']); ?>">
<input type="submit" value="Save Prompt">
</form>
</div>
<a href="/" >Return to Home</a>
</body>
</html>

41
save-prompt.php Normal file
View file

@ -0,0 +1,41 @@
<?php
// save-prompt.php
header('Content-Type: text/html; charset=iso-8859-1');
$saved_prompts_file = 'saved-prompts.json';
function loadSavedPrompts() {
global $saved_prompts_file;
if (file_exists($saved_prompts_file)) {
$json = file_get_contents($saved_prompts_file);
return json_decode($json, true) ?: array();
}
return array();
}
function savePrompt($prompt_text, $negative_prompt_text, $prompt_name) {
global $saved_prompts_file;
$prompts = loadSavedPrompts();
$prompts[$prompt_name] = array(
'prompt' => $prompt_text,
'negative_prompt' => $negative_prompt_text
);
file_put_contents($saved_prompts_file, json_encode($prompts, JSON_PRETTY_PRINT));
}
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$prompt = trim($_POST['prompt'] ?? '');
$negative_prompt = trim($_POST['negative_prompt'] ?? '');
$prompt_name = trim($_POST['prompt_name'] ?? '');
if (!empty($prompt) && !empty($prompt_name)) {
savePrompt($prompt, $negative_prompt, $prompt_name);
header("Location: index.php?save_success=1");
} else {
header("Location: index.php?save_error=1");
}
exit;
} else {
echo "Invalid request method.";
}