Merge remote-tracking branch 'upstream/development' into development

This commit is contained in:
psychedelicious 2022-09-17 11:28:42 +10:00
commit 1799bf5e42
15 changed files with 447 additions and 662 deletions

View File

@ -1,64 +0,0 @@
name: Cache Model
on:
workflow_dispatch
jobs:
build:
strategy:
matrix:
os: [ macos-12 ]
name: Create Caches using ${{ matrix.os }}
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
uses: actions/checkout@v3
- name: Cache model
id: cache-sd-v1-4
uses: actions/cache@v3
env:
cache-name: cache-sd-v1-4
with:
path: models/ldm/stable-diffusion-v1/model.ckpt
key: ${{ env.cache-name }}
restore-keys: |
${{ env.cache-name }}
- name: Download Stable Diffusion v1.4 model
if: ${{ steps.cache-sd-v1-4.outputs.cache-hit != 'true' }}
continue-on-error: true
run: |
if [ ! -e models/ldm/stable-diffusion-v1 ]; then
mkdir -p models/ldm/stable-diffusion-v1
fi
if [ ! -e models/ldm/stable-diffusion-v1/model.ckpt ]; then
curl -o models/ldm/stable-diffusion-v1/model.ckpt ${{ secrets.SD_V1_4_URL }}
fi
# Uncomment this when we no longer make changes to environment-mac.yaml
# - name: Cache environment
# id: cache-conda-env-ldm
# uses: actions/cache@v3
# env:
# cache-name: cache-conda-env-ldm
# with:
# path: ~/.conda/envs/ldm
# key: ${{ env.cache-name }}
# restore-keys: |
# ${{ env.cache-name }}
- name: Install dependencies
# if: ${{ steps.cache-conda-env-ldm.outputs.cache-hit != 'true' }}
run: |
conda env create -f environment-mac.yaml
- name: Cache hugginface and torch models
id: cache-hugginface-torch
uses: actions/cache@v3
env:
cache-name: cache-hugginface-torch
with:
path: ~/.cache
key: ${{ env.cache-name }}
restore-keys: |
${{ env.cache-name }}
- name: Download Huggingface and Torch models
if: ${{ steps.cache-hugginface-torch.outputs.cache-hit != 'true' }}
continue-on-error: true
run: |
export PYTHON_BIN=/usr/local/miniconda/envs/ldm/bin/python
$PYTHON_BIN scripts/preload_models.py

70
.github/workflows/create-caches.yml vendored Normal file
View File

@ -0,0 +1,70 @@
name: Create Caches
on:
workflow_dispatch
jobs:
build:
strategy:
matrix:
os: [ ubuntu-latest, macos-12 ]
name: Create Caches on ${{ matrix.os }} conda
runs-on: ${{ matrix.os }}
steps:
- name: Set platform variables
id: vars
run: |
if [ "$RUNNER_OS" = "macOS" ]; then
echo "::set-output name=ENV_FILE::environment-mac.yaml"
echo "::set-output name=PYTHON_BIN::/usr/local/miniconda/envs/ldm/bin/python"
elif [ "$RUNNER_OS" = "Linux" ]; then
echo "::set-output name=ENV_FILE::environment.yaml"
echo "::set-output name=PYTHON_BIN::/usr/share/miniconda/envs/ldm/bin/python"
fi
- name: Checkout sources
uses: actions/checkout@v3
- name: Use Cached Stable Diffusion v1.4 Model
id: cache-sd-v1-4
uses: actions/cache@v3
env:
cache-name: cache-sd-v1-4
with:
path: models/ldm/stable-diffusion-v1/model.ckpt
key: ${{ env.cache-name }}
restore-keys: |
${{ env.cache-name }}
- name: Download Stable Diffusion v1.4 Model
if: ${{ steps.cache-sd-v1-4.outputs.cache-hit != 'true' }}
run: |
if [ ! -e models/ldm/stable-diffusion-v1 ]; then
mkdir -p models/ldm/stable-diffusion-v1
fi
if [ ! -e models/ldm/stable-diffusion-v1/model.ckpt ]; then
curl -o models/ldm/stable-diffusion-v1/model.ckpt ${{ secrets.SD_V1_4_URL }}
fi
- name: Use Cached Dependencies
id: cache-conda-env-ldm
uses: actions/cache@v3
env:
cache-name: cache-conda-env-ldm
with:
path: ~/.conda/envs/ldm
key: ${{ env.cache-name }}
restore-keys: |
${{ env.cache-name }}-${{ runner.os }}-${{ hashFiles(steps.vars.outputs.ENV_FILE) }}
- name: Install Dependencies
if: ${{ steps.cache-conda-env-ldm.outputs.cache-hit != 'true' }}
run: |
conda env create -f ${{ steps.vars.outputs.ENV_FILE }}
- name: Use Cached Huggingface and Torch models
id: cache-huggingface-torch
uses: actions/cache@v3
env:
cache-name: cache-huggingface-torch
with:
path: ~/.cache
key: ${{ env.cache-name }}
restore-keys: |
${{ env.cache-name }}-${{ hashFiles('scripts/preload_models.py') }}
- name: Download Huggingface and Torch models
if: ${{ steps.cache-huggingface-torch.outputs.cache-hit != 'true' }}
run: |
${{ steps.vars.outputs.PYTHON_BIN }} scripts/preload_models.py

View File

@ -1,80 +0,0 @@
name: Build
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
strategy:
matrix:
os: [ macos-12 ]
name: Build on ${{ matrix.os }} miniconda
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
uses: actions/checkout@v3
- name: Cache model
id: cache-sd-v1-4
uses: actions/cache@v3
env:
cache-name: cache-sd-v1-4
with:
path: models/ldm/stable-diffusion-v1/model.ckpt
key: ${{ env.cache-name }}
restore-keys: |
${{ env.cache-name }}
- name: Download Stable Diffusion v1.4 model
if: ${{ steps.cache-sd-v1-4.outputs.cache-hit != 'true' }}
continue-on-error: true
run: |
if [ ! -e models/ldm/stable-diffusion-v1 ]; then
mkdir -p models/ldm/stable-diffusion-v1
fi
if [ ! -e models/ldm/stable-diffusion-v1/model.ckpt ]; then
curl -o models/ldm/stable-diffusion-v1/model.ckpt ${{ secrets.SD_V1_4_URL }}
fi
# Uncomment this when we no longer make changes to environment-mac.yaml
# - name: Cache environment
# id: cache-conda-env-ldm
# uses: actions/cache@v3
# env:
# cache-name: cache-conda-env-ldm
# with:
# path: ~/.conda/envs/ldm
# key: ${{ env.cache-name }}
# restore-keys: |
# ${{ env.cache-name }}
- name: Install dependencies
# if: ${{ steps.cache-conda-env-ldm.outputs.cache-hit != 'true' }}
run: |
conda env create -f environment-mac.yaml
- name: Cache hugginface and torch models
id: cache-hugginface-torch
uses: actions/cache@v3
env:
cache-name: cache-hugginface-torch
with:
path: ~/.cache
key: ${{ env.cache-name }}
restore-keys: |
${{ env.cache-name }}
- name: Download Huggingface and Torch models
if: ${{ steps.cache-hugginface-torch.outputs.cache-hit != 'true' }}
continue-on-error: true
run: |
export PYTHON_BIN=/usr/local/miniconda/envs/ldm/bin/python
$PYTHON_BIN scripts/preload_models.py
- name: Run the tests
run: |
# Note, can't "activate" via automation, and activation is just env vars and path
export PYTHON_BIN=/usr/local/miniconda/envs/ldm/bin/python
export PYTORCH_ENABLE_MPS_FALLBACK=1
$PYTHON_BIN scripts/preload_models.py
mkdir -p outputs/img-samples
time $PYTHON_BIN scripts/dream.py --from_file tests/prompts.txt </dev/null 2> outputs/img-samples/err.log > outputs/img-samples/out.log
- name: Archive results
uses: actions/upload-artifact@v3
with:
name: results
path: outputs/img-samples

97
.github/workflows/test-dream-conda.yml vendored Normal file
View File

@ -0,0 +1,97 @@
name: Test Dream with Conda
on:
push:
branches:
- 'main'
- 'development'
jobs:
os_matrix:
strategy:
matrix:
os: [ ubuntu-latest, macos-12 ]
name: Test dream.py on ${{ matrix.os }} with conda
runs-on: ${{ matrix.os }}
steps:
- run: |
echo The PR was merged
- name: Set platform variables
id: vars
run: |
# Note, can't "activate" via github action; specifying the env's python has the same effect
if [ "$RUNNER_OS" = "macOS" ]; then
echo "::set-output name=ENV_FILE::environment-mac.yaml"
echo "::set-output name=PYTHON_BIN::/usr/local/miniconda/envs/ldm/bin/python"
elif [ "$RUNNER_OS" = "Linux" ]; then
echo "::set-output name=ENV_FILE::environment.yaml"
echo "::set-output name=PYTHON_BIN::/usr/share/miniconda/envs/ldm/bin/python"
fi
- name: Checkout sources
uses: actions/checkout@v3
- name: Use Cached Stable Diffusion v1.4 Model
id: cache-sd-v1-4
uses: actions/cache@v3
env:
cache-name: cache-sd-v1-4
with:
path: models/ldm/stable-diffusion-v1/model.ckpt
key: ${{ env.cache-name }}
restore-keys: |
${{ env.cache-name }}
- name: Download Stable Diffusion v1.4 Model
if: ${{ steps.cache-sd-v1-4.outputs.cache-hit != 'true' }}
run: |
if [ ! -e models/ldm/stable-diffusion-v1 ]; then
mkdir -p models/ldm/stable-diffusion-v1
fi
if [ ! -e models/ldm/stable-diffusion-v1/model.ckpt ]; then
curl -o models/ldm/stable-diffusion-v1/model.ckpt ${{ secrets.SD_V1_4_URL }}
fi
- name: Use Cached Dependencies
id: cache-conda-env-ldm
uses: actions/cache@v3
env:
cache-name: cache-conda-env-ldm
with:
path: ~/.conda/envs/ldm
key: ${{ env.cache-name }}
restore-keys: |
${{ env.cache-name }}-${{ runner.os }}-${{ hashFiles(steps.vars.outputs.ENV_FILE) }}
- name: Install Dependencies
if: ${{ steps.cache-conda-env-ldm.outputs.cache-hit != 'true' }}
run: |
conda env create -f ${{ steps.vars.outputs.ENV_FILE }}
- name: Use Cached Huggingface and Torch models
id: cache-hugginface-torch
uses: actions/cache@v3
env:
cache-name: cache-hugginface-torch
with:
path: ~/.cache
key: ${{ env.cache-name }}
restore-keys: |
${{ env.cache-name }}-${{ hashFiles('scripts/preload_models.py') }}
- name: Download Huggingface and Torch models
if: ${{ steps.cache-hugginface-torch.outputs.cache-hit != 'true' }}
run: |
${{ steps.vars.outputs.PYTHON_BIN }} scripts/preload_models.py
# - name: Run tmate
# uses: mxschmitt/action-tmate@v3
# timeout-minutes: 30
- name: Run the tests
run: |
# Note, can't "activate" via github action; specifying the env's python has the same effect
if [ $(uname) = "Darwin" ]; then
export PYTORCH_ENABLE_MPS_FALLBACK=1
fi
# Utterly hacky, but I don't know how else to do this
if [[ ${{ github.ref }} == 'refs/heads/master' ]]; then
time ${{ steps.vars.outputs.PYTHON_BIN }} scripts/dream.py --from_file tests/preflight_prompts.txt --full_precision
elif [[ ${{ github.ref }} == 'refs/heads/development' ]]; then
time ${{ steps.vars.outputs.PYTHON_BIN }} scripts/dream.py --from_file tests/dev_prompts.txt --full_precision
fi
mkdir -p outputs/img-samples
- name: Archive results
uses: actions/upload-artifact@v3
with:
name: results
path: outputs/img-samples

View File

@ -5,11 +5,16 @@
</p> </p>
<p align="center"> <p align="center">
<img src="https://img.shields.io/github/last-commit/lstein/stable-diffusion?logo=Python&logoColor=green&style=for-the-badge" alt="last-commit"/> <a href="https://github.com/lstein/stable-diffusion/releases"><img src="https://flat.badgen.net/github/release/lstein/stable-diffusion/development?icon=github" alt="release"/></a>
<img src="https://img.shields.io/github/stars/lstein/stable-diffusion?logo=GitHub&style=for-the-badge" alt="stars"/> <a href="https://github.com/lstein/stable-diffusion/stargazers"><img src="https://flat.badgen.net/github/stars/lstein/stable-diffusion?icon=github" alt="stars"/></a>
<br> <a href="https://useful-forks.github.io/?repo=lstein%2Fstable-diffusion"><img src="https://flat.badgen.net/github/forks/lstein/stable-diffusion?icon=github" alt="forks"/></a>
<img src="https://img.shields.io/github/issues/lstein/stable-diffusion?logo=GitHub&style=for-the-badge" alt="issues"/> <br />
<img src="https://img.shields.io/github/issues-pr/lstein/stable-diffusion?logo=GitHub&style=for-the-badge" alt="pull-requests"/> <a href="https://github.com/lstein/stable-diffusion/actions/workflows/test-dream-conda.yml"><img src="https://flat.badgen.net/github/checks/lstein/stable-diffusion/main?label=CI%20status%20on%20main&cache=900&icon=github" alt="CI status on main"/></a>
<a href="https://github.com/lstein/stable-diffusion/actions/workflows/test-dream-conda.yml"><img src="https://flat.badgen.net/github/checks/lstein/stable-diffusion/development?label=CI%20status%20on%20dev&cache=900&icon=github" alt="CI status on dev"/></a>
<a href="https://github.com/lstein/stable-diffusion/commits/development"><img src="https://flat.badgen.net/github/last-commit/lstein/stable-diffusion/development?icon=github&color=yellow&label=last%20dev%20commit&cache=900" alt="last-dev-commit"/></a>
<br />
<a href="https://github.com/lstein/stable-diffusion/issues?q=is%3Aissue+is%3Aopen"><img src="https://flat.badgen.net/github/open-issues/lstein/stable-diffusion?icon=github" alt="open-issues"/></a>
<a href="https://github.com/lstein/stable-diffusion/pulls?q=is%3Apr+is%3Aopen"><img src="https://flat.badgen.net/github/open-prs/lstein/stable-diffusion?icon=github" alt="open-prs"/></a>
</p> </p>
This is a fork of [CompVis/stable-diffusion](https://github.com/CompVis/stable-diffusion), the open This is a fork of [CompVis/stable-diffusion](https://github.com/CompVis/stable-diffusion), the open

View File

@ -7,10 +7,7 @@ title: macOS
- macOS 12.3 Monterey or later - macOS 12.3 Monterey or later
- Python - Python
- Patience - Patience
- Apple Silicon\* - Apple Silicon or Intel Mac
\*I haven't tested any of this on Intel Macs but I have read that one person got
it to work, so Apple Silicon might not be requried.
Things have moved really fast and so these instructions change often and are Things have moved really fast and so these instructions change often and are
often out-of-date. One of the problems is that there are so many different ways often out-of-date. One of the problems is that there are so many different ways
@ -59,9 +56,13 @@ First get the weights checkpoint download started - it's big:
# install python 3, git, cmake, protobuf: # install python 3, git, cmake, protobuf:
brew install cmake protobuf rust brew install cmake protobuf rust
# install miniconda (M1 arm64 version): # install miniconda for M1 arm64:
curl https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh -o Miniconda3-latest-MacOSX-arm64.sh curl https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh -o Miniconda3-latest-MacOSX-arm64.sh
/bin/bash Miniconda3-latest-MacOSX-arm64.sh /bin/bash Miniconda3-latest-MacOSX-arm64.sh
# OR install miniconda for Intel:
curl https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh -o Miniconda3-latest-MacOSX-x86_64.sh
/bin/bash Miniconda3-latest-MacOSX-x86_64.sh
# EITHER WAY, # EITHER WAY,
@ -82,15 +83,22 @@ brew install cmake protobuf rust
ln -s "$PATH_TO_CKPT/sd-v1-4.ckpt" models/ldm/stable-diffusion-v1/model.ckpt ln -s "$PATH_TO_CKPT/sd-v1-4.ckpt" models/ldm/stable-diffusion-v1/model.ckpt
# install packages # install packages for arm64
PIP_EXISTS_ACTION=w CONDA_SUBDIR=osx-arm64 conda env create -f environment-mac.yaml PIP_EXISTS_ACTION=w CONDA_SUBDIR=osx-arm64 conda env create -f environment-mac.yaml
conda activate ldm conda activate ldm
# OR install packages for x86_64
PIP_EXISTS_ACTION=w CONDA_SUBDIR=osx-x86_64 conda env create -f environment-mac.yaml
conda activate ldm
# only need to do this once # only need to do this once
python scripts/preload_models.py python scripts/preload_models.py
# run SD! # run SD!
python scripts/dream.py --full_precision # half-precision requires autocast and won't work python scripts/dream.py --full_precision # half-precision requires autocast and won't work
# or run the web interface!
python scripts/dream.py --web
``` ```
The original scripts should work as well. The original scripts should work as well.
@ -181,7 +189,12 @@ There are several causes of these errors.
- Third, if it says you're missing taming you need to rebuild your virtual - Third, if it says you're missing taming you need to rebuild your virtual
environment. environment.
`conda env remove -n ldm conda env create -f environment-mac.yaml` ````bash
conda deactivate
conda env remove -n ldm
PIP_EXISTS_ACTION=w CONDA_SUBDIR=osx-arm64 conda env create -f environment-mac.yaml
```
Fourth, If you have activated the ldm virtual environment and tried rebuilding Fourth, If you have activated the ldm virtual environment and tried rebuilding
it, maybe the problem could be that I have something installed that you don't it, maybe the problem could be that I have something installed that you don't

View File

@ -216,9 +216,7 @@ class Args(object):
# the arg value. For example, the --grid and --individual options are a little # the arg value. For example, the --grid and --individual options are a little
# funny because of their push/pull relationship. This is how to handle it. # funny because of their push/pull relationship. This is how to handle it.
if name=='grid': if name=='grid':
return value_arg or value_cmd # arg supersedes cmd return not cmd_switches.individual and value_arg # arg supersedes cmd
if name=='individual':
return value_cmd or value_arg # cmd supersedes arg
if value_cmd is not None: if value_cmd is not None:
return value_cmd return value_cmd
else: else:
@ -294,11 +292,6 @@ class Args(object):
action='store_true', action='store_true',
help='Place images in subdirectories named after the prompt.', help='Place images in subdirectories named after the prompt.',
) )
render_group.add_argument(
'--seamless',
action='store_true',
help='Change the model to seamless tiling (circular) mode',
)
render_group.add_argument( render_group.add_argument(
'--grid', '--grid',
'-g', '-g',
@ -416,8 +409,8 @@ class Args(object):
help='generate a grid' help='generate a grid'
) )
render_group.add_argument( render_group.add_argument(
'--individual',
'-i', '-i',
'--individual',
action='store_true', action='store_true',
help='override command-line --grid setting and generate individual images' help='override command-line --grid setting and generate individual images'
) )
@ -448,7 +441,6 @@ class Args(object):
'--outdir', '--outdir',
'-o', '-o',
type=str, type=str,
default='outputs/img-samples',
help='Directory to save generated images and a log of prompts and seeds', help='Directory to save generated images and a log of prompts and seeds',
) )
img2img_group.add_argument( img2img_group.add_argument(

View File

@ -228,7 +228,8 @@ class DreamServer(BaseHTTPRequestHandler):
nonlocal step_index nonlocal step_index
if opt.progress_images and step % 5 == 0 and step < opt.steps - 1: if opt.progress_images and step % 5 == 0 and step < opt.steps - 1:
image = self.model.sample_to_image(sample) image = self.model.sample_to_image(sample)
name = f'{prefix}.{opt.seed}.{step_index}.png' step_index_padded = str(step_index).rjust(len(str(opt.steps)), '0')
name = f'{prefix}.{opt.seed}.{step_index_padded}.png'
metadata = f'{opt.prompt} -S{opt.seed} [intermediate]' metadata = f'{opt.prompt} -S{opt.seed} [intermediate]'
path = step_writer.save_image_and_prompt_to_png(image, dream_prompt=metadata, name=name) path = step_writer.save_image_and_prompt_to_png(image, dream_prompt=metadata, name=name)
step_index += 1 step_index += 1

View File

@ -82,7 +82,9 @@ class EmbeddingManager(nn.Module):
get_embedding_for_clip_token, get_embedding_for_clip_token,
embedder.transformer.text_model.embeddings, embedder.transformer.text_model.embeddings,
) )
token_dim = 1280 # per bug report #572
#token_dim = 1280
token_dim = 768
else: # using LDM's BERT encoder else: # using LDM's BERT encoder
self.is_clip = False self.is_clip = False
get_token_for_string = partial( get_token_for_string = partial(

View File

@ -1,8 +1,3 @@
:root {
--fields-dark:#DCDCDC;
--fields-light:#F5F5F5;
}
* { * {
font-family: 'Arial'; font-family: 'Arial';
font-size: 100%; font-size: 100%;
@ -23,26 +18,15 @@ fieldset {
border: none; border: none;
line-height: 2.2em; line-height: 2.2em;
} }
fieldset > legend {
width: auto;
margin-left: 0;
margin-right: auto;
font-weight:bold;
}
select, input { select, input {
margin-right: 10px; margin-right: 10px;
padding: 2px; padding: 2px;
} }
input:disabled {
cursor:auto;
}
input[type=submit] { input[type=submit] {
cursor: pointer;
background-color: #666; background-color: #666;
color: white; color: white;
} }
input[type=checkbox] { input[type=checkbox] {
cursor: pointer;
margin-right: 0px; margin-right: 0px;
width: 20px; width: 20px;
height: 20px; height: 20px;
@ -103,11 +87,11 @@ header h1 {
} }
#results img { #results img {
border-radius: 5px; border-radius: 5px;
object-fit: contain; object-fit: cover;
background-color: var(--fields-dark);
} }
#fieldset-config { #fieldset-config {
line-height:2em; line-height:2em;
background-color: #F0F0F0;
} }
input[type="number"] { input[type="number"] {
width: 60px; width: 60px;
@ -134,46 +118,35 @@ label {
#progress-image { #progress-image {
width: 30vh; width: 30vh;
height: 30vh; height: 30vh;
object-fit: contain;
background-color: var(--fields-dark);
} }
#cancel-button { #cancel-button {
cursor: pointer; cursor: pointer;
color: red; color: red;
} }
#basic-parameters {
background-color: #EEEEEE;
}
#txt2img { #txt2img {
background-color: var(--fields-dark); background-color: #DCDCDC;
} }
#variations { #variations {
background-color: var(--fields-light); background-color: #EEEEEE;
}
#initimg {
background-color: var(--fields-dark);
} }
#img2img { #img2img {
background-color: var(--fields-light); background-color: #DCDCDC;
} }
#initimg > :not(legend) { #gfpgan {
background-color: var(--fields-light); background-color: #EEEEEE;
margin: .5em;
}
#postprocess, #initimg {
display:flex;
flex-wrap:wrap;
padding: 0;
margin-top: 1em;
background-color: var(--fields-dark);
}
#postprocess > fieldset, #initimg > * {
flex-grow: 1;
}
#postprocess > fieldset {
background-color: var(--fields-dark);
} }
#progress-section { #progress-section {
background-color: var(--fields-light); background-color: #F5F5F5;
}
.section-header {
text-align: left;
font-weight: bold;
padding: 0 0 0 0;
} }
#no-results-message:not(:only-child) { #no-results-message:not(:only-child) {
display: none; display: none;
} }

View File

@ -1,152 +1,102 @@
<html lang="en"> <html lang="en">
<head>
<head> <title>Stable Diffusion Dream Server</title>
<title>Stable Diffusion Dream Server</title> <meta charset="utf-8">
<meta charset="utf-8"> <link rel="icon" type="image/x-icon" href="static/dream_web/favicon.ico" />
<link rel="icon" type="image/x-icon" href="static/dream_web/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="static/dream_web/index.css">
<script src="config.js"></script>
<script src="config.js"></script> <script src="static/dream_web/index.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js" </head>
integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" <body>
crossorigin="anonymous"></script> <header>
<link rel="stylesheet" href="index.css"> <h1>Stable Diffusion Dream Server</h1>
<script src="index.js"></script> <div id="about">
</head> For news and support for this web service, visit our <a href="http://github.com/lstein/stable-diffusion">GitHub site</a>
<body>
<header>
<h1>Stable Diffusion Dream Server</h1>
<div id="about">
For news and support for this web service, visit our <a href="http://github.com/lstein/stable-diffusion">GitHub
site</a>
</div>
</header>
<main>
<!--
<div id="dropper" style="background-color:red;width:200px;height:200px;">
</div> </div>
--> </header>
<form id="generate-form" method="post" action="api/jobs">
<fieldset id="txt2img"> <main>
<legend> <form id="generate-form" method="post" action="#">
<input type="checkbox" name="enable_generate" id="enable_generate" checked> <fieldset id="txt2img">
<label for="enable_generate">Generate</label> <div id="search-box">
</legend> <textarea rows="3" id="prompt" name="prompt"></textarea>
<div id="search-box"> <input type="submit" id="submit" value="Generate">
<textarea rows="3" id="prompt" name="prompt"></textarea> </div>
</div> </fieldset>
<label for="iterations">Images to generate:</label> <fieldset id="fieldset-config">
<input value="1" type="number" id="iterations" name="iterations" size="4"> <div class="section-header">Basic options</div>
<label for="steps">Steps:</label> <label for="iterations">Images to generate:</label>
<input value="50" type="number" id="steps" name="steps"> <input value="1" type="number" id="iterations" name="iterations" size="4">
<label for="cfg_scale">Cfg Scale:</label> <label for="steps">Steps:</label>
<input value="7.5" type="number" id="cfg_scale" name="cfg_scale" step="any"> <input value="50" type="number" id="steps" name="steps">
<label for="sampler_name">Sampler:</label> <label for="cfg_scale">Cfg Scale:</label>
<select id="sampler_name" name="sampler_name" value="k_lms"> <input value="7.5" type="number" id="cfg_scale" name="cfg_scale" step="any">
<option value="ddim">DDIM</option> <label for="sampler_name">Sampler:</label>
<option value="plms">PLMS</option> <select id="sampler_name" name="sampler_name" value="k_lms">
<option value="k_lms" selected>KLMS</option> <option value="ddim">DDIM</option>
<option value="k_dpm_2">KDPM_2</option> <option value="plms">PLMS</option>
<option value="k_dpm_2_a">KDPM_2A</option> <option value="k_lms" selected>KLMS</option>
<option value="k_euler">KEULER</option> <option value="k_dpm_2">KDPM_2</option>
<option value="k_euler_a">KEULER_A</option> <option value="k_dpm_2_a">KDPM_2A</option>
<option value="k_heun">KHEUN</option> <option value="k_euler">KEULER</option>
</select> <option value="k_euler_a">KEULER_A</option>
<input type="checkbox" name="seamless" id="seamless"> <option value="k_heun">KHEUN</option>
<label for="seamless">Seamless circular tiling</label> </select>
<br> <input type="checkbox" name="seamless" id="seamless">
<label title="Set to multiple of 64" for="width">Width:</label> <label for="seamless">Seamless circular tiling</label>
<select id="width" name="width" value="512"> <br>
<option value="64">64</option> <label title="Set to multiple of 64" for="width">Width:</label>
<option value="128">128</option> <select id="width" name="width" value="512">
<option value="192">192</option> <option value="64">64</option> <option value="128">128</option>
<option value="256">256</option> <option value="192">192</option> <option value="256">256</option>
<option value="320">320</option> <option value="320">320</option> <option value="384">384</option>
<option value="384">384</option> <option value="448">448</option> <option value="512" selected>512</option>
<option value="448">448</option> <option value="576">576</option> <option value="640">640</option>
<option value="512" selected>512</option> <option value="704">704</option> <option value="768">768</option>
<option value="576">576</option> <option value="832">832</option> <option value="896">896</option>
<option value="640">640</option> <option value="960">960</option> <option value="1024">1024</option>
<option value="704">704</option> </select>
<option value="768">768</option> <label title="Set to multiple of 64" for="height">Height:</label>
<option value="832">832</option> <select id="height" name="height" value="512">
<option value="896">896</option> <option value="64">64</option> <option value="128">128</option>
<option value="960">960</option> <option value="192">192</option> <option value="256">256</option>
<option value="1024">1024</option> <option value="320">320</option> <option value="384">384</option>
</select> <option value="448">448</option> <option value="512" selected>512</option>
<label title="Set to multiple of 64" for="height">Height:</label> <option value="576">576</option> <option value="640">640</option>
<select id="height" name="height" value="512"> <option value="704">704</option> <option value="768">768</option>
<option value="64">64</option> <option value="832">832</option> <option value="896">896</option>
<option value="128">128</option> <option value="960">960</option> <option value="1024">1024</option>
<option value="192">192</option> </select>
<option value="256">256</option> <label title="Set to -1 for random seed" for="seed">Seed:</label>
<option value="320">320</option> <input value="-1" type="number" id="seed" name="seed">
<option value="384">384</option> <button type="button" id="reset-seed">&olarr;</button>
<option value="448">448</option> <input type="checkbox" name="progress_images" id="progress_images">
<option value="512" selected>512</option> <label for="progress_images">Display in-progress images (slower)</label>
<option value="576">576</option> <button type="button" id="reset-all">Reset to Defaults</button>
<option value="640">640</option> <span id="variations">
<option value="704">704</option> <label title="If > 0, generates variations on the initial seed instead of random seeds per iteration. Must be between 0 and 1. Higher values will be more different." for="variation_amount">Variation amount (0 to disable):</label>
<option value="768">768</option> <input value="0" type="number" id="variation_amount" name="variation_amount" step="0.01" min="0" max="1">
<option value="832">832</option> <label title="list of variations to apply, in the format `seed:weight,seed:weight,..." for="with_variations">With variations (seed:weight,seed:weight,...):</label>
<option value="896">896</option> <input value="" type="text" id="with_variations" name="with_variations">
<option value="960">960</option> </span>
<option value="1024">1024</option> </fieldset>
</select> <fieldset id="img2img">
<label title="Set to 0 for random seed" for="seed">Seed:</label> <div class="section-header">Image-to-image options</div>
<input value="0" type="number" id="seed" name="seed">
<button type="button" id="reset-seed">&olarr;</button>
<input type="checkbox" name="progress_images" id="progress_images">
<label for="progress_images">Display in-progress images (slower)</label>
<button type="button" id="reset-all">Reset to Defaults</button>
<div id="variations">
<label
title="If > 0, generates variations on the initial seed instead of random seeds per iteration. Must be between 0 and 1. Higher values will be more different."
for="variation_amount">Variation amount (0 to disable):</label>
<input value="0" type="number" id="variation_amount" name="variation_amount" step="0.01" min="0" max="1">
<label title="list of variations to apply, in the format `seed:weight,seed:weight,..."
for="with_variations">With variations (seed:weight,seed:weight,...):</label>
<input value="" type="text" id="with_variations" name="with_variations">
</div>
</fieldset>
<fieldset id="initimg">
<legend>
<input type="checkbox" name="enable_init_image" id="enable_init_image" checked>
<label for="enable_init_image">Enable init image</label>
</legend>
<div>
<label title="Upload an image to use img2img" for="initimg">Initial image:</label> <label title="Upload an image to use img2img" for="initimg">Initial image:</label>
<input type="file" id="initimg" name="initimg" accept=".jpg, .jpeg, .png"> <input type="file" id="initimg" name="initimg" accept=".jpg, .jpeg, .png">
<button type="button" id="remove-image">Remove Image</button> <button type="button" id="remove-image">Remove Image</button>
</div> <br>
<fieldset id="img2img"> <label for="strength">Img2Img Strength:</label>
<legend> <input value="0.75" type="number" id="strength" name="strength" step="0.01" min="0" max="1">
<input type="checkbox" name="enable_img2img" id="enable_img2img" checked> <input type="checkbox" id="fit" name="fit" checked>
<label for="enable_img2img">Enable Img2Img</label> <label title="Rescale image to fit within requested width and height" for="fit">Fit to width/height</label>
</legend> </fieldset>
<label for="strength">Img2Img Strength:</label>
<input value="0.75" type="number" id="strength" name="strength" step="0.01" min="0" max="1">
<input type="checkbox" id="fit" name="fit" checked>
<label title="Rescale image to fit within requested width and height" for="fit">Fit to width/height:</label>
</fieldset>
</fieldset>
<div id="postprocess">
<fieldset id="gfpgan"> <fieldset id="gfpgan">
<legend> <div class="section-header">Post-processing options</div>
<input type="checkbox" name="enable_gfpgan" id="enable_gfpgan"> <label title="Strength of the gfpgan (face fixing) algorithm." for="gfpgan_strength">GPFGAN Strength (0 to disable):</label>
<label for="enable_gfpgan">Enable gfpgan</label> <input value="0.0" min="0" max="1" type="number" id="gfpgan_strength" name="gfpgan_strength" step="0.1">
</legend> <label title="Upscaling to perform using ESRGAN." for="upscale_level">Upscaling Level</label>
<label title="Strength of the gfpgan (face fixing) algorithm." for="gfpgan_strength">GPFGAN Strength:</label>
<input value="0.8" min="0" max="1" type="number" id="gfpgan_strength" name="gfpgan_strength" step="0.05">
</fieldset>
<fieldset id="upscale">
<legend>
<input type="checkbox" name="enable_upscale" id="enable_upscale">
<label for="enable_upscale">Enable Upscaling</label>
</legend>
<label title="Upscaling to perform using ESRGAN." for="upscale_level">Upscaling Level:</label>
<select id="upscale_level" name="upscale_level" value=""> <select id="upscale_level" name="upscale_level" value="">
<option value="" selected>None</option> <option value="" selected>None</option>
<option value="2">2x</option> <option value="2">2x</option>
@ -155,25 +105,25 @@
<label title="Strength of the esrgan (upscaling) algorithm." for="upscale_strength">Upscale Strength:</label> <label title="Strength of the esrgan (upscaling) algorithm." for="upscale_strength">Upscale Strength:</label>
<input value="0.75" min="0" max="1" type="number" id="upscale_strength" name="upscale_strength" step="0.05"> <input value="0.75" min="0" max="1" type="number" id="upscale_strength" name="upscale_strength" step="0.05">
</fieldset> </fieldset>
</div> </form>
<input type="submit" id="submit" value="Generate"> <br>
</form> <section id="progress-section">
<br> <div id="progress-container">
<section id="progress-section"> <progress id="progress-bar" value="0" max="1"></progress>
<div id="progress-container"> <span id="cancel-button" title="Cancel">&#10006;</span>
<progress id="progress-bar" value="0" max="1"></progress> <br>
<span id="cancel-button" title="Cancel">&#10006;</span> <img id="progress-image" src='data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg"/>'>
<br> <div id="scaling-inprocess-message">
<img id="progress-image" src='data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg"/>'> <i><span>Postprocessing...</span><span id="processing_cnt">1/3</span></i>
<div id="scaling-inprocess-message"> </div>
<i><span>Postprocessing...</span><span id="processing_cnt">1</span>/<span id="processing_total">3</span></i> </span>
</section>
<div id="results">
<div id="no-results-message">
<i><p>No results...</p></i>
</div> </div>
</div> </div>
</section> </main>
</body>
<div id="results">
</div>
</main>
</body>
</html> </html>

View File

@ -1,109 +1,3 @@
const socket = io();
var priorResultsLoadState = {
page: 0,
pages: 1,
per_page: 10,
total: 20,
offset: 0, // number of items generated since last load
loading: false,
initialized: false
};
function loadPriorResults() {
// Fix next page by offset
let offsetPages = priorResultsLoadState.offset / priorResultsLoadState.per_page;
priorResultsLoadState.page += offsetPages;
priorResultsLoadState.pages += offsetPages;
priorResultsLoadState.total += priorResultsLoadState.offset;
priorResultsLoadState.offset = 0;
if (priorResultsLoadState.loading) {
return;
}
if (priorResultsLoadState.page >= priorResultsLoadState.pages) {
return; // Nothing more to load
}
// Load
priorResultsLoadState.loading = true
let url = new URL('/api/images', document.baseURI);
url.searchParams.append('page', priorResultsLoadState.initialized ? priorResultsLoadState.page + 1 : priorResultsLoadState.page);
url.searchParams.append('per_page', priorResultsLoadState.per_page);
fetch(url.href, {
method: 'GET',
headers: new Headers({'content-type': 'application/json'})
})
.then(response => response.json())
.then(data => {
priorResultsLoadState.page = data.page;
priorResultsLoadState.pages = data.pages;
priorResultsLoadState.per_page = data.per_page;
priorResultsLoadState.total = data.total;
data.items.forEach(function(dreamId, index) {
let src = 'api/images/' + dreamId;
fetch('/api/images/' + dreamId + '/metadata', {
method: 'GET',
headers: new Headers({'content-type': 'application/json'})
})
.then(response => response.json())
.then(metadata => {
let seed = metadata.seed || 0; // TODO: Parse old metadata
appendOutput(src, seed, metadata, true);
});
});
// Load until page is full
if (!priorResultsLoadState.initialized) {
if (document.body.scrollHeight <= window.innerHeight) {
loadPriorResults();
}
}
})
.finally(() => {
priorResultsLoadState.loading = false;
priorResultsLoadState.initialized = true;
});
}
function resetForm() {
var form = document.getElementById('generate-form');
form.querySelector('fieldset').removeAttribute('disabled');
}
function initProgress(totalSteps, showProgressImages) {
// TODO: Progress could theoretically come from multiple jobs at the same time (in the future)
let progressSectionEle = document.querySelector('#progress-section');
progressSectionEle.style.display = 'initial';
let progressEle = document.querySelector('#progress-bar');
progressEle.setAttribute('max', totalSteps);
let progressImageEle = document.querySelector('#progress-image');
progressImageEle.src = BLANK_IMAGE_URL;
progressImageEle.style.display = showProgressImages ? 'initial': 'none';
}
function setProgress(step, totalSteps, src) {
let progressEle = document.querySelector('#progress-bar');
progressEle.setAttribute('value', step);
if (src) {
let progressImageEle = document.querySelector('#progress-image');
progressImageEle.src = src;
}
}
function resetProgress(hide = true) {
if (hide) {
let progressSectionEle = document.querySelector('#progress-section');
progressSectionEle.style.display = 'none';
}
let progressEle = document.querySelector('#progress-bar');
progressEle.setAttribute('value', 0);
}
function toBase64(file) { function toBase64(file) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const r = new FileReader(); const r = new FileReader();
@ -113,41 +7,17 @@ function toBase64(file) {
}); });
} }
function ondragdream(event) { function appendOutput(src, seed, config) {
let dream = event.target.dataset.dream;
event.dataTransfer.setData("dream", dream);
}
function seedClick(event) {
// Get element
var image = event.target.closest('figure').querySelector('img');
var dream = JSON.parse(decodeURIComponent(image.dataset.dream));
let form = document.querySelector("#generate-form");
for (const [k, v] of new FormData(form)) {
if (k == 'initimg') { continue; }
let formElem = form.querySelector(`*[name=${k}]`);
formElem.value = dream[k] !== undefined ? dream[k] : formElem.defaultValue;
}
document.querySelector("#seed").value = dream.seed;
document.querySelector('#iterations').value = 1; // Reset to 1 iteration since we clicked a single image (not a full job)
// NOTE: leaving this manual for the user for now - it was very confusing with this behavior
// document.querySelector("#with_variations").value = variations || '';
// if (document.querySelector("#variation_amount").value <= 0) {
// document.querySelector("#variation_amount").value = 0.2;
// }
saveFields(document.querySelector("#generate-form"));
}
function appendOutput(src, seed, config, toEnd=false) {
let outputNode = document.createElement("figure"); let outputNode = document.createElement("figure");
let altText = seed.toString() + " | " + config.prompt;
let variations = config.with_variations;
if (config.variation_amount > 0) {
variations = (variations ? variations + ',' : '') + seed + ':' + config.variation_amount;
}
let baseseed = (config.with_variations || config.variation_amount > 0) ? config.seed : seed;
let altText = baseseed + ' | ' + (variations ? variations + ' | ' : '') + config.prompt;
// img needs width and height for lazy loading to work // img needs width and height for lazy loading to work
// TODO: store the full config in a data attribute on the image?
const figureContents = ` const figureContents = `
<a href="${src}" target="_blank"> <a href="${src}" target="_blank">
<img src="${src}" <img src="${src}"
@ -155,23 +25,32 @@ function appendOutput(src, seed, config, toEnd=false) {
title="${altText}" title="${altText}"
loading="lazy" loading="lazy"
width="256" width="256"
height="256" height="256">
draggable="true"
ondragstart="ondragdream(event, this)"
data-dream="${encodeURIComponent(JSON.stringify(config))}"
data-dreamId="${encodeURIComponent(config.dreamId)}">
</a> </a>
<figcaption onclick="seedClick(event, this)">${seed}</figcaption> <figcaption>${seed}</figcaption>
`; `;
outputNode.innerHTML = figureContents; outputNode.innerHTML = figureContents;
let figcaption = outputNode.querySelector('figcaption');
if (toEnd) { // Reload image config
document.querySelector("#results").append(outputNode); figcaption.addEventListener('click', () => {
} else { let form = document.querySelector("#generate-form");
document.querySelector("#results").prepend(outputNode); for (const [k, v] of new FormData(form)) {
} if (k == 'initimg') { continue; }
document.querySelector("#no-results-message")?.remove(); form.querySelector(`*[name=${k}]`).value = config[k];
}
document.querySelector("#seed").value = baseseed;
document.querySelector("#with_variations").value = variations || '';
if (document.querySelector("#variation_amount").value <= 0) {
document.querySelector("#variation_amount").value = 0.2;
}
saveFields(document.querySelector("#generate-form"));
});
document.querySelector("#results").prepend(outputNode);
} }
function saveFields(form) { function saveFields(form) {
@ -200,109 +79,93 @@ function clearFields(form) {
const BLANK_IMAGE_URL = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg"/>'; const BLANK_IMAGE_URL = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg"/>';
async function generateSubmit(form) { async function generateSubmit(form) {
const prompt = document.querySelector("#prompt").value;
// Convert file data to base64 // Convert file data to base64
// TODO: Should probably uplaod files with formdata or something, and store them in the backend?
let formData = Object.fromEntries(new FormData(form)); let formData = Object.fromEntries(new FormData(form));
if (!formData.enable_generate && !formData.enable_init_image) {
gen_label = document.querySelector("label[for=enable_generate]").innerHTML;
initimg_label = document.querySelector("label[for=enable_init_image]").innerHTML;
alert(`Error: one of "${gen_label}" or "${initimg_label}" must be set`);
}
formData.initimg_name = formData.initimg.name formData.initimg_name = formData.initimg.name
formData.initimg = formData.initimg.name !== '' ? await toBase64(formData.initimg) : null; formData.initimg = formData.initimg.name !== '' ? await toBase64(formData.initimg) : null;
// Evaluate all checkboxes
let checkboxes = form.querySelectorAll('input[type=checkbox]');
checkboxes.forEach(function (checkbox) {
if (checkbox.checked) {
formData[checkbox.name] = 'true';
}
});
let strength = formData.strength; let strength = formData.strength;
let totalSteps = formData.initimg ? Math.floor(strength * formData.steps) : formData.steps; let totalSteps = formData.initimg ? Math.floor(strength * formData.steps) : formData.steps;
let showProgressImages = formData.progress_images;
// Set enabling flags let progressSectionEle = document.querySelector('#progress-section');
progressSectionEle.style.display = 'initial';
let progressEle = document.querySelector('#progress-bar');
progressEle.setAttribute('max', totalSteps);
let progressImageEle = document.querySelector('#progress-image');
progressImageEle.src = BLANK_IMAGE_URL;
progressImageEle.style.display = {}.hasOwnProperty.call(formData, 'progress_images') ? 'initial': 'none';
// Initialize the progress bar // Post as JSON, using Fetch streaming to get results
initProgress(totalSteps, showProgressImages);
// POST, use response to listen for events
fetch(form.action, { fetch(form.action, {
method: form.method, method: form.method,
headers: new Headers({'content-type': 'application/json'}),
body: JSON.stringify(formData), body: JSON.stringify(formData),
}) }).then(async (response) => {
.then(response => response.json()) const reader = response.body.getReader();
.then(data => {
var jobId = data.jobId; let noOutputs = true;
socket.emit('join_room', { 'room': jobId }); while (true) {
let {value, done} = await reader.read();
value = new TextDecoder().decode(value);
if (done) {
progressSectionEle.style.display = 'none';
break;
}
for (let event of value.split('\n').filter(e => e !== '')) {
const data = JSON.parse(event);
if (data.event === 'result') {
noOutputs = false;
appendOutput(data.url, data.seed, data.config);
progressEle.setAttribute('value', 0);
progressEle.setAttribute('max', totalSteps);
} else if (data.event === 'upscaling-started') {
document.getElementById("processing_cnt").textContent=data.processed_file_cnt;
document.getElementById("scaling-inprocess-message").style.display = "block";
} else if (data.event === 'upscaling-done') {
document.getElementById("scaling-inprocess-message").style.display = "none";
} else if (data.event === 'step') {
progressEle.setAttribute('value', data.step);
if (data.url) {
progressImageEle.src = data.url;
}
} else if (data.event === 'canceled') {
// avoid alerting as if this were an error case
noOutputs = false;
}
}
}
// Re-enable form, remove no-results-message
form.querySelector('fieldset').removeAttribute('disabled');
document.querySelector("#prompt").value = prompt;
document.querySelector('progress').setAttribute('value', '0');
if (noOutputs) {
alert("Error occurred while generating.");
}
}); });
// Disable form while generating
form.querySelector('fieldset').setAttribute('disabled',''); form.querySelector('fieldset').setAttribute('disabled','');
document.querySelector("#prompt").value = `Generating: "${prompt}"`;
} }
function fieldSetEnableChecked(event) { async function fetchRunLog() {
cb = event.target; try {
fields = cb.closest('fieldset'); let response = await fetch('/run_log.json')
fields.disabled = !cb.checked; const data = await response.json();
for(let item of data.run_log) {
appendOutput(item.url, item.seed, item);
}
} catch (e) {
console.error(e);
}
} }
// Socket listeners
socket.on('job_started', (data) => {})
socket.on('dream_result', (data) => {
var jobId = data.jobId;
var dreamId = data.dreamId;
var dreamRequest = data.dreamRequest;
var src = 'api/images/' + dreamId;
priorResultsLoadState.offset += 1;
appendOutput(src, dreamRequest.seed, dreamRequest);
resetProgress(false);
})
socket.on('dream_progress', (data) => {
// TODO: it'd be nice if we could get a seed reported here, but the generator would need to be updated
var step = data.step;
var totalSteps = data.totalSteps;
var jobId = data.jobId;
var dreamId = data.dreamId;
var progressType = data.progressType
if (progressType === 'GENERATION') {
var src = data.hasProgressImage ?
'api/intermediates/' + dreamId + '/' + step
: null;
setProgress(step, totalSteps, src);
} else if (progressType === 'UPSCALING_STARTED') {
// step and totalSteps are used for upscale count on this message
document.getElementById("processing_cnt").textContent = step;
document.getElementById("processing_total").textContent = totalSteps;
document.getElementById("scaling-inprocess-message").style.display = "block";
} else if (progressType == 'UPSCALING_DONE') {
document.getElementById("scaling-inprocess-message").style.display = "none";
}
})
socket.on('job_canceled', (data) => {
resetForm();
resetProgress();
})
socket.on('job_done', (data) => {
jobId = data.jobId
socket.emit('leave_room', { 'room': jobId });
resetForm();
resetProgress();
})
window.onload = async () => { window.onload = async () => {
document.querySelector("#prompt").addEventListener("keydown", (e) => { document.querySelector("#prompt").addEventListener("keydown", (e) => {
if (e.key === "Enter" && !e.shiftKey) { if (e.key === "Enter" && !e.shiftKey) {
@ -320,7 +183,7 @@ window.onload = async () => {
saveFields(e.target.form); saveFields(e.target.form);
}); });
document.querySelector("#reset-seed").addEventListener('click', (e) => { document.querySelector("#reset-seed").addEventListener('click', (e) => {
document.querySelector("#seed").value = 0; document.querySelector("#seed").value = -1;
saveFields(e.target.form); saveFields(e.target.form);
}); });
document.querySelector("#reset-all").addEventListener('click', (e) => { document.querySelector("#reset-all").addEventListener('click', (e) => {
@ -332,13 +195,13 @@ window.onload = async () => {
loadFields(document.querySelector("#generate-form")); loadFields(document.querySelector("#generate-form"));
document.querySelector('#cancel-button').addEventListener('click', () => { document.querySelector('#cancel-button').addEventListener('click', () => {
fetch('/api/cancel').catch(e => { fetch('/cancel').catch(e => {
console.error(e); console.error(e);
}); });
}); });
document.documentElement.addEventListener('keydown', (e) => { document.documentElement.addEventListener('keydown', (e) => {
if (e.key === "Escape") if (e.key === "Escape")
fetch('/api/cancel').catch(err => { fetch('/cancel').catch(err => {
console.error(err); console.error(err);
}); });
}); });
@ -346,51 +209,5 @@ window.onload = async () => {
if (!config.gfpgan_model_exists) { if (!config.gfpgan_model_exists) {
document.querySelector("#gfpgan").style.display = 'none'; document.querySelector("#gfpgan").style.display = 'none';
} }
await fetchRunLog()
window.addEventListener("scroll", () => {
if ((window.innerHeight + window.pageYOffset) >= document.body.offsetHeight) {
loadPriorResults();
}
});
// Enable/disable forms by checkboxes
document.querySelectorAll("legend > input[type=checkbox]").forEach(function(cb) {
cb.addEventListener('change', fieldSetEnableChecked);
fieldSetEnableChecked({ target: cb})
});
// Load some of the previous results
loadPriorResults();
// Image drop/upload WIP
/*
let drop = document.getElementById('dropper');
function ondrop(event) {
let dreamData = event.dataTransfer.getData('dream');
if (dreamData) {
var dream = JSON.parse(decodeURIComponent(dreamData));
alert(dream.dreamId);
}
};
function ondragenter(event) {
event.preventDefault();
};
function ondragover(event) {
event.preventDefault();
};
function ondragleave(event) {
}
drop.addEventListener('drop', ondrop);
drop.addEventListener('dragenter', ondragenter);
drop.addEventListener('dragover', ondragover);
drop.addEventListener('dragleave', ondragleave);
*/
}; };

1
tests/dev_prompts.txt Normal file
View File

@ -0,0 +1 @@
banana sushi -Ak_lms -S42

View File

@ -0,0 +1,9 @@
banana sushi -Ak_lms -S42
banana sushi -Addim -S42
banana sushi -Ak_lms -W640 -H480 -S42
banana sushi -Ak_lms -S42 -G1 -U 2 0.5
banana sushi -Ak_lms -S42 -v0.2 -n3
banana sushi -Ak_lms -S42 -V1349749425:0.1,4145759947:0.1
snake -I outputs/preflight/000006.4145759947.png -S42
snake -I outputs/preflight/000006.4145759947.png -S42 -W640 -H640 --fit
strawberry sushi -I./image-and-mask.png -S42 -f0.9 -s100 -C15

View File

@ -1 +0,0 @@
test trending on artstation -s 1 -S 1