process images in threads

This commit is contained in:
Vladimir Mandic
2023-05-12 14:21:26 -04:00
parent 0a46f8ada7
commit 62dda471a3
9 changed files with 592 additions and 181 deletions
+451
View File
@@ -0,0 +1,451 @@
[
{
"filename": "outputs/text/00189-3905757009-beautiful woman wearing a bikini in a city during night",
"time": "2023-05-12T12:51:23.125657",
"info": "beautiful woman wearing a bikini in a city during night\nNegative prompt: easynegative, badprompts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck\nSteps: 20, Sampler: UniPC, CFG scale: 6, Seed: 3905757009, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00009-3905757009-beautiful woman wearing a bikini in a city during night",
"time": "2023-05-12T13:02:56.680825",
"info": "beautiful woman wearing a bikini in a city during night\nNegative prompt: easynegative, badprompts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck\nSteps: 20, Sampler: UniPC, CFG scale: 6, Seed: 3905757009, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00010-3905757009-beautiful woman wearing a bikini in a city during night",
"time": "2023-05-12T13:03:10.309811",
"info": "beautiful woman wearing a bikini in a city during night\nNegative prompt: easynegative, badprompts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck\nSteps: 20, Sampler: UniPC, CFG scale: 6, Seed: 3905757009, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00011-3905757009-beautiful woman wearing a bikini in a city during night",
"time": "2023-05-12T13:04:47.198064",
"info": "beautiful woman wearing a bikini in a city during night\nNegative prompt: easynegative, badprompts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck\nSteps: 20, Sampler: UniPC, CFG scale: 6, Seed: 3905757009, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00012-3905757009-beautiful woman wearing a bikini in a city during night",
"time": "2023-05-12T13:16:21.231228",
"info": "beautiful woman wearing a bikini in a city during night\nNegative prompt: easynegative, badprompts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck\nSteps: 20, Sampler: UniPC, CFG scale: 6, Seed: 3905757009, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00013-3905757009-beautiful woman wearing a bikini in a city during night",
"time": "2023-05-12T13:19:10.190976",
"info": "beautiful woman wearing a bikini in a city during night\nNegative prompt: easynegative, badprompts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck\nSteps: 20, Sampler: UniPC, CFG scale: 6, Seed: 3905757009, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00013-3905757009-beautiful woman wearing a bikini in a city during night",
"time": "2023-05-12T13:19:12.646301",
"info": "beautiful woman wearing a bikini in a city during night\nNegative prompt: easynegative, badprompts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck\nSteps: 20, Sampler: UniPC, CFG scale: 6, Seed: 3905757009, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00013-3905757009-beautiful woman wearing a bikini in a city during night",
"time": "2023-05-12T13:19:14.541258",
"info": "beautiful woman wearing a bikini in a city during night\nNegative prompt: easynegative, badprompts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck\nSteps: 20, Sampler: UniPC, CFG scale: 6, Seed: 3905757009, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00013-3905757009-beautiful woman wearing a bikini in a city during night",
"time": "2023-05-12T13:19:45.747797",
"info": "beautiful woman wearing a bikini in a city during night\nNegative prompt: easynegative, badprompts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck\nSteps: 20, Sampler: UniPC, CFG scale: 6, Seed: 3905757009, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00013-3905757009-beautiful woman wearing a bikini in a city during night",
"time": "2023-05-12T13:19:47.702913",
"info": "beautiful woman wearing a bikini in a city during night\nNegative prompt: easynegative, badprompts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck\nSteps: 20, Sampler: UniPC, CFG scale: 6, Seed: 3905757009, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00013-3905757009-beautiful woman wearing a bikini in a city during night",
"time": "2023-05-12T13:19:49.710276",
"info": "beautiful woman wearing a bikini in a city during night\nNegative prompt: easynegative, badprompts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck\nSteps: 20, Sampler: UniPC, CFG scale: 6, Seed: 3905757009, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00190-1800237580-beautiful woman wearing a bikini in a city during night",
"time": "2023-05-12T13:25:36.025059",
"info": "beautiful woman wearing a bikini in a city during night\nNegative prompt: easynegative, badprompts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck\nSteps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1800237580, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00014-1800237580-beautiful woman wearing a bikini in a city during night",
"time": "2023-05-12T13:25:38.529309",
"info": "beautiful woman wearing a bikini in a city during night\nNegative prompt: easynegative, badprompts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck\nSteps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1800237580, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00015-1800237580-beautiful woman wearing a bikini in a city during night",
"time": "2023-05-12T13:25:41.355289",
"info": "beautiful woman wearing a bikini in a city during night\nNegative prompt: easynegative, badprompts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck\nSteps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1800237580, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00016-1800237580-beautiful woman wearing a bikini in a city during night",
"time": "2023-05-12T13:25:42.365440",
"info": "beautiful woman wearing a bikini in a city during night\nNegative prompt: easynegative, badprompts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck\nSteps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1800237580, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00017-1800237580-beautiful woman wearing a bikini in a city during night",
"time": "2023-05-12T13:25:43.280769",
"info": "beautiful woman wearing a bikini in a city during night\nNegative prompt: easynegative, badprompts, ugly, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck\nSteps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1800237580, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00191-2754842760-",
"time": "2023-05-12T13:45:50.125245",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00018-2754842760-",
"time": "2023-05-12T13:45:52.586131",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00019-2754842760-",
"time": "2023-05-12T13:48:17.093520",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00020-2754842760-",
"time": "2023-05-12T13:48:18.196932",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00021-2754842760-",
"time": "2023-05-12T13:48:19.164835",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00022-2754842760-",
"time": "2023-05-12T13:48:20.047468",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00023-2754842760-",
"time": "2023-05-12T13:48:20.889756",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00024-2754842760-",
"time": "2023-05-12T13:48:21.679708",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00025-2754842760-",
"time": "2023-05-12T13:48:22.487093",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00026-2754842760-",
"time": "2023-05-12T13:48:23.288043",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00027-2754842760-",
"time": "2023-05-12T13:48:24.012309",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00028-2754842760-",
"time": "2023-05-12T13:48:24.910025",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00029-2754842760-",
"time": "2023-05-12T13:48:25.676995",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00030-2754842760-",
"time": "2023-05-12T13:48:26.504592",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00031-2754842760-",
"time": "2023-05-12T13:48:27.437550",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00032-2754842760-",
"time": "2023-05-12T13:48:28.239230",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00033-2754842760-",
"time": "2023-05-12T13:48:29.001641",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00034-2754842760-",
"time": "2023-05-12T13:48:29.744071",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00035-2754842760-",
"time": "2023-05-12T13:48:30.643950",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00036-2754842760-",
"time": "2023-05-12T13:48:31.487216",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00037-2754842760-",
"time": "2023-05-12T13:48:32.332520",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00038-2754842760-",
"time": "2023-05-12T13:48:33.101266",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00039-2754842760-",
"time": "2023-05-12T13:48:33.926420",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00040-2754842760-",
"time": "2023-05-12T13:48:34.710441",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00041-2754842760-",
"time": "2023-05-12T13:48:35.478143",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00042-2754842760-",
"time": "2023-05-12T13:48:36.316470",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00043-2754842760-",
"time": "2023-05-12T13:48:37.138220",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00044-2754842760-",
"time": "2023-05-12T13:48:37.813014",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00045-2754842760-",
"time": "2023-05-12T13:48:38.499095",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00046-2754842760-",
"time": "2023-05-12T13:48:39.095014",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00047-2754842760-",
"time": "2023-05-12T13:48:39.822240",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00048-2754842760-",
"time": "2023-05-12T13:48:40.373347",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00049-2754842760-",
"time": "2023-05-12T13:48:41.024193",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00050-2754842760-",
"time": "2023-05-12T13:48:41.608742",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00051-2754842760-",
"time": "2023-05-12T13:48:42.278164",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00052-2754842760-",
"time": "2023-05-12T13:48:42.892458",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00053-2754842760-",
"time": "2023-05-12T13:48:44.806619",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00054-2754842760-",
"time": "2023-05-12T13:48:45.716492",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00055-2754842760-",
"time": "2023-05-12T13:48:46.466023",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00056-2754842760-",
"time": "2023-05-12T13:48:47.509243",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/save/00057-2754842760-",
"time": "2023-05-12T13:50:16.947892",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2754842760, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00192-2011235778-",
"time": "2023-05-12T13:52:22.241607",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 2011235778, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00193-4221894582-",
"time": "2023-05-12T13:57:20.270873",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 4221894582, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00194-1506239356-",
"time": "2023-05-12T13:57:29.718097",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1506239356, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00195-1506239357-",
"time": "2023-05-12T13:57:35.325309",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1506239357, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00196-1506239358-",
"time": "2023-05-12T13:57:40.926351",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1506239358, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00197-1506239359-",
"time": "2023-05-12T13:57:46.527684",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1506239359, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00198-1506239360-",
"time": "2023-05-12T13:57:52.123180",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1506239360, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00199-1506239361-",
"time": "2023-05-12T13:57:57.744069",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1506239361, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00200-1506239362-",
"time": "2023-05-12T13:58:03.368185",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1506239362, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00201-1506239363-",
"time": "2023-05-12T13:58:09.009217",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1506239363, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00202-1506239364-",
"time": "2023-05-12T13:58:14.702054",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1506239364, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00203-1506239365-",
"time": "2023-05-12T13:58:20.400389",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1506239365, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00204-1506239366-",
"time": "2023-05-12T13:58:26.207687",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1506239366, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00205-1506239367-",
"time": "2023-05-12T13:58:31.935958",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1506239367, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00206-1506239368-",
"time": "2023-05-12T13:58:32.533708",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1506239368, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/grids/grid-0007-1506239356-",
"time": "2023-05-12T13:58:32.643158",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1506239356, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
][
{
"filename": "outputs/text/00207-1135673010-",
"time": "2023-05-12T14:01:56.795209",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 1135673010, Size: 512x512, Model hash: 362adb1351, Model: 3moon-realdoll, Clip skip: 1"
}
][
{
"filename": "outputs/text/00208-60785991-",
"time": "2023-05-12T14:09:26.861751",
"info": "Steps: 20, Sampler: UniPC, CFG scale: 6, Seed: 60785991, Size: 512x512, Model hash: 6ce0161689, Model: v1-5-pruned-emaonly, Clip skip: 1"
}
]
-1
View File
@@ -102,5 +102,4 @@ def compatibility_args(opts, args):
opts.dimensions_and_batch_together = True
args = parser.parse_args()
return args
+4
View File
@@ -64,6 +64,8 @@ def get_device_for(task):
def torch_gc():
if shared.opts.disable_gc:
return
gc.collect()
if shared.cmd_opts.use_ipex:
try:
@@ -86,6 +88,7 @@ def test_fp16():
x = torch.tensor([[1.5,.0,.0,.0]]).to(device).half()
layerNorm = torch.nn.LayerNorm(4, eps=0.00001, elementwise_affine=True, dtype=torch.float16, device=device)
_y = layerNorm(x)
shared.log.debug('Torch FP16 test passed')
return True
except:
shared.log.warning('Torch FP16 test failed: Forcing FP32 operations')
@@ -131,6 +134,7 @@ def set_cuda_params():
if shared.opts.no_half_vae: # set dtype again as no-half-vae options take priority
dtype_vae = torch.float32
unet_needs_upcast = shared.opts.upcast_sampling
shared.log.debug(f'Desired CUDA parameters: dtype={shared.opts.cuda_dtype} no-half={shared.opts.no_half} no-half-vae={shared.opts.no_half_vae} upscast={shared.opts.upcast_sampling}')
shared.log.debug(f'Setting CUDA parameters: dtype={dtype} vae={dtype_vae} unet={dtype_unet}')
+9 -8
View File
@@ -36,7 +36,6 @@ def reset():
def quote(text):
if ',' not in str(text):
return text
text = str(text)
text = text.replace('\\', '\\\\')
text = text.replace('"', '\\"')
@@ -46,27 +45,29 @@ def quote(text):
def image_from_url_text(filedata):
if filedata is None:
return None
if type(filedata) == list and len(filedata) > 0 and type(filedata[0]) == dict and filedata[0].get("is_file", False):
filedata = filedata[0]
if type(filedata) == dict and filedata.get("is_file", False):
filename = filedata["name"]
is_in_right_dir = ui_tempdir.check_tmp_file(shared.demo, filename)
if is_in_right_dir:
return Image.open(filename)
else:
shared.log.warning(f'Attempted to open file outside of allowed directories: {filename}')
shared.log.warning(f'File access denied: {filename}')
return None
if type(filedata) == list:
if len(filedata) == 0:
return None
filedata = filedata[0]
if type(filedata) == dict:
shared.log.warning('Incorrect filedata received')
return None
if filedata.startswith("data:image/png;base64,"):
filedata = filedata[len("data:image/png;base64,"):]
if filedata.startswith("data:image/webp;base64,"):
filedata = filedata[len("data:image/webp;base64,"):]
if filedata.startswith("data:image/jpeg;base64,"):
filedata = filedata[len("data:image/jpeg;base64,"):]
filedata = base64.decodebytes(filedata.encode('utf-8'))
image = Image.open(io.BytesIO(filedata))
return image
+84 -125
View File
@@ -6,26 +6,26 @@ import math
import json
import string
import hashlib
import queue
import threading
from collections import namedtuple
import pytz
import numpy as np
import piexif
import piexif.helper
from PIL import Image, ImageFont, ImageDraw, PngImagePlugin, ExifTags
from modules import sd_samplers, shared, script_callbacks, errors
from modules.shared import opts, log
LANCZOS = (Image.Resampling.LANCZOS if hasattr(Image, 'Resampling') else Image.LANCZOS)
def image_grid(imgs, batch_size=1, rows=None):
if rows is None:
if opts.n_rows > 0:
rows = opts.n_rows
elif opts.n_rows == 0:
if shared.opts.n_rows > 0:
rows = shared.opts.n_rows
elif shared.opts.n_rows == 0:
rows = batch_size
elif opts.grid_prevent_empty_spots:
elif shared.opts.grid_prevent_empty_spots:
rows = math.floor(math.sqrt(len(imgs)))
while len(imgs) % rows != 0:
rows -= 1
@@ -34,18 +34,13 @@ def image_grid(imgs, batch_size=1, rows=None):
rows = round(rows)
if rows > len(imgs):
rows = len(imgs)
cols = math.ceil(len(imgs) / rows)
params = script_callbacks.ImageGridLoopParams(imgs, cols, rows)
script_callbacks.image_grid_callback(params)
w, h = imgs[0].size
grid = Image.new('RGB', size=(params.cols * w, params.rows * h), color='black')
for i, img in enumerate(params.imgs):
grid.paste(img, box=(i % params.cols * w, i // params.cols * h))
return grid
@@ -139,7 +134,7 @@ def draw_grid_annotations(im, width, height, hor_texts, ver_texts, margin=0):
def get_font(fontsize):
try:
return ImageFont.truetype(opts.font or 'javascript/roboto.ttf', fontsize)
return ImageFont.truetype(shared.opts.font or 'javascript/roboto.ttf', fontsize)
except Exception:
return ImageFont.truetype('javascript/roboto.ttf', fontsize)
@@ -151,90 +146,65 @@ def draw_grid_annotations(im, width, height, hor_texts, ver_texts, margin=0):
fontsize -= 1
fnt = get_font(fontsize)
drawing.multiline_text((draw_x, draw_y + line.size[1] / 2), line.text, font=fnt, fill=color_active if line.is_active else color_inactive, anchor="mm", align="center")
if not line.is_active:
drawing.line((draw_x - line.size[0] // 2, draw_y + line.size[1] // 2, draw_x + line.size[0] // 2, draw_y + line.size[1] // 2), fill=color_inactive, width=4)
draw_y += line.size[1] + line_spacing
fontsize = (width + height) // 25
line_spacing = fontsize // 2
fnt = get_font(fontsize)
color_active = (0, 0, 0)
color_inactive = (153, 153, 153)
pad_left = 0 if sum([sum([len(line.text) for line in lines]) for lines in ver_texts]) == 0 else width * 3 // 4
cols = im.width // width
rows = im.height // height
assert cols == len(hor_texts), f'bad number of horizontal texts: {len(hor_texts)}; must be {cols}'
assert rows == len(ver_texts), f'bad number of vertical texts: {len(ver_texts)}; must be {rows}'
calc_img = Image.new("RGB", (1, 1), "white")
calc_d = ImageDraw.Draw(calc_img)
for texts, allowed_width in zip(hor_texts + ver_texts, [width] * len(hor_texts) + [pad_left] * len(ver_texts)):
items = [] + texts
texts.clear()
for line in items:
wrapped = wrap(calc_d, line.text, fnt, allowed_width)
texts += [GridAnnotation(x, line.is_active) for x in wrapped]
for line in texts:
bbox = calc_d.multiline_textbbox((0, 0), line.text, font=fnt)
line.size = (bbox[2] - bbox[0], bbox[3] - bbox[1])
line.allowed_width = allowed_width
hor_text_heights = [sum([line.size[1] + line_spacing for line in lines]) - line_spacing for lines in hor_texts]
ver_text_heights = [sum([line.size[1] + line_spacing for line in lines]) - line_spacing * len(lines) for lines in ver_texts]
pad_top = 0 if sum(hor_text_heights) == 0 else max(hor_text_heights) + line_spacing * 2
result = Image.new("RGB", (im.width + pad_left + margin * (cols-1), im.height + pad_top + margin * (rows-1)), "white")
for row in range(rows):
for col in range(cols):
cell = im.crop((width * col, height * row, width * (col+1), height * (row+1)))
result.paste(cell, (pad_left + (width + margin) * col, pad_top + (height + margin) * row))
d = ImageDraw.Draw(result)
for col in range(cols):
x = pad_left + (width + margin) * col + width / 2
y = pad_top / 2 - hor_text_heights[col] / 2
draw_texts(d, x, y, hor_texts[col], fnt, fontsize)
for row in range(rows):
x = pad_left / 2
y = pad_top + (height + margin) * row + height / 2 - ver_text_heights[row] / 2
draw_texts(d, x, y, ver_texts[row], fnt, fontsize)
return result
def draw_prompt_matrix(im, width, height, all_prompts, margin=0):
prompts = all_prompts[1:]
boundary = math.ceil(len(prompts) / 2)
prompts_horiz = prompts[:boundary]
prompts_vert = prompts[boundary:]
hor_texts = [[GridAnnotation(x, is_active=pos & (1 << i) != 0) for i, x in enumerate(prompts_horiz)] for pos in range(1 << len(prompts_horiz))]
ver_texts = [[GridAnnotation(x, is_active=pos & (1 << i) != 0) for i, x in enumerate(prompts_vert)] for pos in range(1 << len(prompts_vert))]
return draw_grid_annotations(im, width, height, hor_texts, ver_texts, margin)
def resize_image(resize_mode, im, width, height, upscaler_name=None):
"""
Resizes an image with the specified resize_mode, width, and height.
Args:
resize_mode: The mode to use when resizing the image.
0: Resize the image to the specified width and height.
@@ -245,55 +215,42 @@ def resize_image(resize_mode, im, width, height, upscaler_name=None):
height: The height to resize the image to.
upscaler_name: The name of the upscaler to use. If not provided, defaults to opts.upscaler_for_img2img.
"""
upscaler_name = upscaler_name or opts.upscaler_for_img2img
upscaler_name = upscaler_name or shared.opts.upscaler_for_img2img
def resize(im, w, h):
if upscaler_name is None or upscaler_name == "None" or im.mode == 'L':
return im.resize((w, h), resample=LANCZOS)
scale = max(w / im.width, h / im.height)
if scale > 1.0:
upscalers = [x for x in shared.sd_upscalers if x.name == upscaler_name]
if len(upscalers) == 0:
upscaler = shared.sd_upscalers[0]
log.warning(f"could not find upscaler named {upscaler_name or '<empty string>'}, using {upscaler.name} as a fallback")
shared.log.warning(f"could not find upscaler named {upscaler_name or '<empty string>'}, using {upscaler.name} as a fallback")
else:
upscaler = upscalers[0]
im = upscaler.scaler.upscale(im, scale, upscaler.data_path)
if im.width != w or im.height != h:
im = im.resize((w, h), resample=LANCZOS)
return im
if resize_mode == 0:
res = resize(im, width, height)
elif resize_mode == 1:
ratio = width / height
src_ratio = im.width / im.height
src_w = width if ratio > src_ratio else im.width * height // im.height
src_h = height if ratio <= src_ratio else im.height * width // im.width
resized = resize(im, src_w, src_h)
res = Image.new("RGB", (width, height))
res.paste(resized, box=(width // 2 - src_w // 2, height // 2 - src_h // 2))
else:
ratio = width / height
src_ratio = im.width / im.height
src_w = width if ratio < src_ratio else im.width * height // im.height
src_h = height if ratio >= src_ratio else im.height * width // im.width
resized = resize(im, src_w, src_h)
res = Image.new("RGB", (width, height))
res.paste(resized, box=(width // 2 - src_w // 2, height // 2 - src_h // 2))
if ratio < src_ratio:
fill_height = height // 2 - src_h // 2
res.paste(resized.resize((width, fill_height), box=(0, 0, width, 0)), box=(0, 0))
@@ -302,7 +259,6 @@ def resize_image(resize_mode, im, width, height, upscaler_name=None):
fill_width = width // 2 - src_w // 2
res.paste(resized.resize((fill_width, height), box=(0, 0, 0, height)), box=(0, 0))
res.paste(resized.resize((fill_width, height), box=(resized.width, 0, resized.width, height)), box=(fill_width + src_w, 0))
return res
@@ -351,7 +307,7 @@ class FilenameGenerator:
'batch_number': lambda self: NOTHING_AND_SKIP_PREVIOUS_TEXT if self.p.batch_size == 1 else self.p.batch_index + 1,
'generation_number': lambda self: NOTHING_AND_SKIP_PREVIOUS_TEXT if self.p.n_iter == 1 and self.p.batch_size == 1 else self.p.iteration * self.p.batch_size + self.p.batch_index + 1,
'hasprompt': lambda self, *args: self.hasprompt(*args), # accepts formats:[hasprompt<prompt1|default><prompt2>..]
'clip_skip': lambda self: opts.data["CLIP_stop_at_last_layers"],
'clip_skip': lambda self: shared.opts.data["CLIP_stop_at_last_layers"],
}
default_time_format = '%Y%m%d%H%M%S'
@@ -380,7 +336,6 @@ class FilenameGenerator:
def prompt_no_style(self):
if self.p is None or self.prompt is None:
return None
prompt_no_style = self.prompt
for style in shared.prompt_styles.get_style_prompts(self.p.styles):
if len(style) > 0:
@@ -388,50 +343,42 @@ class FilenameGenerator:
prompt_no_style = prompt_no_style.replace(part, "").replace(", ,", ",").strip().strip(',')
prompt_no_style = prompt_no_style.replace(style, "").strip().strip(',').strip()
return sanitize_filename_part(prompt_no_style, replace_spaces=False)
def prompt_words(self):
words = [x for x in re_nonletters.split(self.prompt or "") if len(x) > 0]
if len(words) == 0:
words = ["empty"]
return sanitize_filename_part(" ".join(words[0:opts.directories_max_prompt_words]), replace_spaces=False)
return sanitize_filename_part(" ".join(words[0:shared.opts.directories_max_prompt_words]), replace_spaces=False)
def datetime(self, *args):
time_datetime = datetime.datetime.now()
time_format = args[0] if len(args) > 0 and args[0] != "" else self.default_time_format
try:
time_zone = pytz.timezone(args[1]) if len(args) > 1 else None
except pytz.exceptions.UnknownTimeZoneError as _:
time_zone = None
time_zone_time = time_datetime.astimezone(time_zone)
try:
formatted_time = time_zone_time.strftime(time_format)
except (ValueError, TypeError) as _:
formatted_time = time_zone_time.strftime(self.default_time_format)
return sanitize_filename_part(formatted_time, replace_spaces=False)
def apply(self, x):
res = ''
for m in re_pattern.finditer(x):
text, pattern = m.groups()
if pattern is None:
res += text
continue
pattern_args = []
while True:
m = re_pattern_arg.match(pattern)
if m is None:
break
pattern, arg = m.groups()
pattern_args.insert(0, arg)
fun = self.replacements.get(pattern.lower())
if fun is not None:
try:
@@ -439,28 +386,22 @@ class FilenameGenerator:
except Exception as e:
replacement = None
errors.display(e, 'filename pattern')
if replacement == NOTHING_AND_SKIP_PREVIOUS_TEXT:
continue
elif replacement is not None:
res += text + str(replacement)
continue
res += f'{text}[{pattern}]'
return res
def get_next_sequence_number(path, basename):
"""
Determines and returns the next sequence number to use when saving an image in the specified directory.
The sequence starts at 0.
"""
result = -1
if basename != '':
basename = basename + "-"
prefix_length = len(basename)
for p in os.listdir(path):
if p.startswith(basename):
@@ -469,13 +410,68 @@ def get_next_sequence_number(path, basename):
result = max(int(l[0]), result)
except ValueError:
pass
return result + 1
def atomically_save_image():
Image.MAX_IMAGE_PIXELS = None # disable check in Pillow and rely on check below to allow large custom image sizes
while True:
image, filename, extension, params, exifinfo_data, txt_fullfn = save_queue.get()
mp = round(image.width * image.height / 1000000)
if mp > shared.opts.img_max_size_mp:
shared.log.warning(f'Image size: {image.size} excedes {shared.opts.img_max_size_mp} MPixels')
fn = filename + extension
image_format = Image.registered_extensions()[extension]
shared.log.debug(f'Saving image: {image_format} {fn} {image.size}')
# actual save
if image_format == 'PNG':
pnginfo_data = PngImagePlugin.PngInfo()
for k, v in params.pnginfo.items():
pnginfo_data.add_text(k, str(v))
image.save(fn, format=image_format, quality=shared.opts.jpeg_quality, pnginfo=pnginfo_data)
elif image_format == 'JPEG':
if image.mode == 'RGBA':
shared.log.warning('Saving RGBA image as JPEG: Alpha channel will be lost')
image = image.convert("RGB")
elif image.mode == 'I;16':
image = image.point(lambda p: p * 0.0038910505836576).convert("L")
exif_bytes = piexif.dump({ "Exif": { piexif.ExifIFD.UserComment: piexif.helper.UserComment.dump(exifinfo_data or "", encoding="unicode") } })
image.save(fn, format=image_format, quality=shared.opts.jpeg_quality, exif=exif_bytes)
elif image_format == 'WEBP':
if image.mode == 'I;16':
image = image.point(lambda p: p * 0.0038910505836576).convert("RGB")
exif_bytes = piexif.dump({ "Exif": { piexif.ExifIFD.UserComment: piexif.helper.UserComment.dump(exifinfo_data or "", encoding="unicode") } })
image.save(fn, format=image_format, quality=shared.opts.jpeg_quality, lossless=shared.opts.webp_lossless, exif=exif_bytes)
else:
shared.log.warning(f'Unrecognized image format: {extension} attempting save as {image_format}')
image.save(fn, format=image_format, quality=shared.opts.jpeg_quality)
# additional metadata saved in files
if shared.opts.save_txt and len(exifinfo_data) > 0:
with open(txt_fullfn, "w", encoding="utf8") as file:
file.write(exifinfo_data + "\n")
if shared.opts.save_log_fn != '' and len(exifinfo_data) > 0:
try:
with open(shared.opts.save_log_fn, mode='a+', encoding='utf-8') as f:
try:
entries = json.load(f)
except:
entries = []
f.seek(0)
entries.append({ 'filename': filename, 'time': datetime.datetime.now().isoformat(), 'info': exifinfo_data })
json.dump(entries, f, indent=4)
del entries
except Exception as e:
shared.log.warning(f'Failed to save log file: {shared.opts.save_log_fn} {e}')
save_queue.task_done()
save_queue = queue.Queue()
save_thread = threading.Thread(target=atomically_save_image, daemon=True)
save_thread.start()
def save_image(image, path, basename, seed=None, prompt=None, extension='jpg', info=None, short_filename=False, no_prompt=False, grid=False, pnginfo_section_name='parameters', p=None, existing_info=None, forced_filename=None, suffix="", save_to_dirs=None):
"""Save an image.
Args:
image (`PIL.Image`):
The image to be saved.
@@ -499,7 +495,6 @@ def save_image(image, path, basename, seed=None, prompt=None, extension='jpg', i
If specified, `basename` and filename pattern will be ignored.
save_to_dirs (bool):
If true, the image will be saved into a subdirectory of `path`.
Returns: (fullfn, txt_fullfn)
fullfn (`str`):
The full path of the saved imaged.
@@ -507,23 +502,25 @@ def save_image(image, path, basename, seed=None, prompt=None, extension='jpg', i
If a text file is saved for this image, this will be its full path. Otherwise None.
"""
namegen = FilenameGenerator(p, seed, prompt, image)
if image is None:
shared.log.warning('Image is none')
return None, None
if path is None: # set default path to avoid errors when functions are triggered manually or via api and param is not set
path = opts.outdir_save
path = shared.opts.outdir_save
if save_to_dirs is None:
save_to_dirs = (grid and opts.grid_save_to_dirs) or (not grid and opts.save_to_dirs and not no_prompt)
save_to_dirs = (grid and shared.opts.grid_save_to_dirs) or (not grid and shared.opts.save_to_dirs and not no_prompt)
if save_to_dirs:
dirname = namegen.apply(opts.directories_filename_pattern or "[prompt_words]").lstrip(' ').rstrip('\\ /')
dirname = namegen.apply(shared.opts.directories_filename_pattern or "[prompt_words]").lstrip(' ').rstrip('\\ /')
path = os.path.join(path, dirname)
os.makedirs(path, exist_ok=True)
if forced_filename is None:
if short_filename or seed is None:
file_decoration = ""
elif opts.save_to_dirs:
file_decoration = opts.samples_filename_pattern or "[seed]"
elif shared.opts.save_to_dirs:
file_decoration = shared.opts.samples_filename_pattern or "[seed]"
else:
file_decoration = opts.samples_filename_pattern or "[seed]-[prompt_spaces]"
add_number = opts.save_images_add_number or file_decoration == ''
file_decoration = shared.opts.samples_filename_pattern or "[seed]-[prompt_spaces]"
add_number = shared.opts.save_images_add_number or file_decoration == ''
if file_decoration != "" and add_number:
file_decoration = "-" + file_decoration
file_decoration = namegen.apply(file_decoration) + suffix
@@ -544,63 +541,25 @@ def save_image(image, path, basename, seed=None, prompt=None, extension='jpg', i
pnginfo[pnginfo_section_name] = info
params = script_callbacks.ImageSaveParams(image, p, fullfn, pnginfo)
script_callbacks.before_image_saved_callback(params)
image = params.image
fullfn = params.filename
exifinfo_data = params.pnginfo.get('UserComment', '')
if len(exifinfo_data) > 0:
exifinfo_data = exifinfo_data + ', ' + params.pnginfo.get(pnginfo_section_name, '')
else:
exifinfo_data = params.pnginfo.get(pnginfo_section_name, '')
def atomically_save_image(image: Image, basename: str, extension: str):
Image.MAX_IMAGE_PIXELS = None # disable check in Pillow and rely on check below to allow large custom image sizes
mp = round(image.width * image.height / 1000000)
if mp > shared.opts.img_max_size_mp:
shared.log.warning(f'Image size: {image.size} excedes {shared.opts.img_max_size_mp} MPixels')
fn = basename + extension
image_format = Image.registered_extensions()[extension]
log.debug(f'Saving image: {image_format} {fn} {image.size}')
if image_format == 'PNG':
pnginfo_data = PngImagePlugin.PngInfo()
for k, v in params.pnginfo.items():
pnginfo_data.add_text(k, str(v))
image.save(fn, format=image_format, quality=opts.jpeg_quality, pnginfo=pnginfo_data)
elif image_format == 'JPEG':
if image.mode == 'RGBA':
shared.log.warning('Saving RGBA image as JPEG: Alpha channel will be lost')
image = image.convert("RGB")
elif image.mode == 'I;16':
image = image.point(lambda p: p * 0.0038910505836576).convert("L")
exif_bytes = piexif.dump({ "Exif": { piexif.ExifIFD.UserComment: piexif.helper.UserComment.dump(exifinfo_data or "", encoding="unicode") } })
image.save(fn, format=image_format, quality=opts.jpeg_quality, exif=exif_bytes)
elif image_format == 'WEBP':
if image.mode == 'I;16':
image = image.point(lambda p: p * 0.0038910505836576).convert("RGB")
exif_bytes = piexif.dump({ "Exif": { piexif.ExifIFD.UserComment: piexif.helper.UserComment.dump(exifinfo_data or "", encoding="unicode") } })
image.save(fn, format=image_format, quality=opts.jpeg_quality, lossless=opts.webp_lossless, exif=exif_bytes)
else:
shared.log.warning(f'Unrecognized image format: {extension} attempting save as {image_format}')
image.save(fn, format=image_format, quality=opts.jpeg_quality)
filename, extension = os.path.splitext(params.filename)
if hasattr(os, 'statvfs'):
max_name_len = os.statvfs(path).f_namemax
filename = filename[:max_name_len - max(4, len(extension))]
params.filename = filename + extension
fullfn = params.filename
atomically_save_image(image, filename, extension)
txt_fullfn = f"{filename}.txt" if shared.opts.save_txt and len(exifinfo_data) > 0 else None
image.already_saved_as = fullfn
if opts.save_txt and len(exifinfo_data) > 0:
txt_fullfn = f"{filename}.txt"
with open(txt_fullfn, "w", encoding="utf8") as file:
file.write(exifinfo_data + "\n")
else:
txt_fullfn = None
save_queue.put((params.image, filename, extension, params, exifinfo_data, txt_fullfn))
save_queue.join()
# atomically_save_image(params.image, filename, extension, params, exifinfo_data, txt_fullfn)
params.image.already_saved_as = params.filename
script_callbacks.image_saved_callback(params)
return fullfn, txt_fullfn
return params.filename, txt_fullfn
def safe_decode_string(s: bytes):
-1
View File
@@ -538,7 +538,6 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
assert len(p.prompt) > 0
else:
assert p.prompt is not None
# devices.torch_gc() # TODO: gc
seed = get_fixed_seed(p.seed)
subseed = get_fixed_seed(p.subseed)
modules.sd_hijack.model_hijack.apply_circular(p.tiling)
+3 -1
View File
@@ -286,6 +286,7 @@ options_templates.update(options_section(('saving-images', "Image options"), {
"grid_prevent_empty_spots": OptionInfo(True, "Prevent empty spots in grid (when set to autodetect)"),
"n_rows": OptionInfo(-1, "Grid row count; use -1 for autodetect and 0 for it to be same as batch size", gr.Slider, {"minimum": -1, "maximum": 16, "step": 1}),
"save_txt": OptionInfo(False, "Create a text file next to every image with generation parameters"),
"save_log_fn": OptionInfo("", "Create a log file with image information for each saved image", component_args=hide_dirs),
"save_images_before_face_restoration": OptionInfo(False, "Save a copy of image before doing face restoration"),
"save_images_before_highres_fix": OptionInfo(False, "Save a copy of image before applying highres fix"),
"save_images_before_color_correction": OptionInfo(False, "Save a copy of image before applying color correction to img2img results"),
@@ -334,6 +335,7 @@ options_templates.update(options_section(('cuda', "Compute Settings"), {
"cuda_compile_mode": OptionInfo("none", "Model compile mode (experimental)", gr.Radio, lambda: {"choices": ['none', 'inductor', 'cudagraphs', 'aot_ts_nvfuser', 'hidet']}),
"cuda_compile_verbose": OptionInfo(True, "Model compile verbose mode"),
"cuda_compile_errors": OptionInfo(True, "Model compile suppress errors"),
"disable_gc": OptionInfo(False, "Disable Torch memory garbage collection (experimental)"),
}))
options_templates.update(options_section(('upscaling', "Upscaling"), {
@@ -594,10 +596,10 @@ class Options:
opts = Options()
cmd_opts = cmd_args.compatibility_args(opts, cmd_opts)
config_filename = cmd_opts.config
if os.path.exists(config_filename):
opts.load(config_filename)
cmd_opts = cmd_args.compatibility_args(opts, cmd_opts)
os.makedirs(opts.hypernetwork_dir, exist_ok=True)
prompt_styles = modules.styles.StyleDatabase(opts.styles_dir)
+24 -38
View File
@@ -2,10 +2,8 @@ import json
import html
import os
import platform
import subprocess as sp
import subprocess
import gradio as gr
from modules import call_queue, shared
from modules.generation_parameters_copypaste import image_from_url_text
import modules.images
@@ -31,7 +29,8 @@ def plaintext_to_html(text):
def save_files(js_data, images, do_make_zip, index):
import csv
if js_data is None or len(js_data) == 0:
return
filenames = []
fullfns = []
@@ -43,45 +42,32 @@ def save_files(js_data, images, do_make_zip, index):
setattr(self, key, value)
data = json.loads(js_data)
p = MyObject(data)
path = shared.opts.outdir_save
save_to_dirs = shared.opts.use_save_to_dirs_for_ui
extension: str = shared.opts.samples_format
start_index = 0
if index > -1 and shared.opts.save_selected_only and (index >= data["index_of_first_image"]): # ensures we are looking at a specific non-grid picture, and we have save_selected_only
images = [images[index]]
start_index = index
os.makedirs(shared.opts.outdir_save, exist_ok=True)
with open(os.path.join(shared.opts.outdir_save, "log.csv"), "a", encoding="utf8", newline='') as file:
at_start = file.tell() == 0
writer = csv.writer(file)
if at_start:
writer.writerow(["prompt", "seed", "width", "height", "sampler", "cfgs", "steps", "filename", "negative_prompt"])
for image_index, filedata in enumerate(images, start_index):
image = image_from_url_text(filedata)
is_grid = image_index < p.index_of_first_image # pylint: disable=no-member
i = 0 if is_grid else (image_index - p.index_of_first_image) # pylint: disable=no-member
if len(p.all_seeds) <= i: # pylint: disable=no-member
p.all_seeds.append(p.seed) # pylint: disable=no-member
if len(p.all_prompts) <= i: # pylint: disable=no-member
p.all_prompts.append(p.prompt) # pylint: disable=no-member
fullfn, txt_fullfn = modules.images.save_image(image, path, "", seed=p.all_seeds[i], prompt=p.all_prompts[i], extension=extension, info=p.infotexts[image_index], grid=is_grid, p=p, save_to_dirs=save_to_dirs) # pylint: disable=no-member
filename = os.path.relpath(fullfn, path)
filenames.append(filename)
fullfns.append(fullfn)
if txt_fullfn:
filenames.append(os.path.basename(txt_fullfn))
fullfns.append(txt_fullfn)
writer.writerow([data["prompt"], data["seed"], data["width"], data["height"], data["sampler_name"], data["cfg_scale"], data["steps"], filenames[0], data["negative_prompt"]])
# Make Zip
for image_index, filedata in enumerate(images, start_index):
image = image_from_url_text(filedata)
is_grid = image_index < p.index_of_first_image # pylint: disable=no-member
i = 0 if is_grid else (image_index - p.index_of_first_image) # pylint: disable=no-member
if len(p.all_seeds) <= i: # pylint: disable=no-member
p.all_seeds.append(p.seed) # pylint: disable=no-member
if len(p.all_prompts) <= i: # pylint: disable=no-member
p.all_prompts.append(p.prompt) # pylint: disable=no-member
fullfn, txt_fullfn = modules.images.save_image(image, path, "", seed=p.all_seeds[i], prompt=p.all_prompts[i], extension=extension, info=p.infotexts[image_index], grid=is_grid, p=p, save_to_dirs=save_to_dirs) # pylint: disable=no-member
if fullfn is None:
continue
filename = os.path.relpath(fullfn, path)
filenames.append(filename)
fullfns.append(fullfn)
if txt_fullfn:
filenames.append(os.path.basename(txt_fullfn))
fullfns.append(txt_fullfn)
if do_make_zip:
zip_filepath = os.path.join(path, "images.zip")
from zipfile import ZipFile
@@ -90,7 +76,7 @@ def save_files(js_data, images, do_make_zip, index):
with open(fullfns[i], mode="rb") as f:
zip_file.writestr(filenames[i], f.read())
fullfns.insert(0, zip_filepath)
return gr.File.update(value=fullfns, visible=True), plaintext_to_html(f"Saved: {filenames[0]}")
return gr.File.update(value=fullfns, visible=True), plaintext_to_html(f"Saved: {filenames[0] if len(filenames) > 0 else 'none'}")
def create_output_panel(tabname, outdir):
@@ -109,11 +95,11 @@ def create_output_panel(tabname, outdir):
if platform.system() == "Windows":
os.startfile(path) # pylint: disable=no-member
elif platform.system() == "Darwin":
sp.Popen(["open", path])
subprocess.Popen(["open", path])
elif "microsoft-standard-WSL2" in platform.uname().release:
sp.Popen(["wsl-open", path])
subprocess.Popen(["wsl-open", path])
else:
sp.Popen(["xdg-open", path])
subprocess.Popen(["xdg-open", path])
with gr.Column(variant='panel', elem_id=f"{tabname}_results"):
with gr.Group(elem_id=f"{tabname}_gallery_container"):
+17 -7
View File
@@ -11,18 +11,28 @@ Savedfile = namedtuple("Savedfile", ["name"])
def register_tmp_file(gradio, filename):
if hasattr(gradio, 'temp_file_sets'): # gradio 3.15
if hasattr(gradio, 'temp_file_sets'):
gradio.temp_file_sets[0] = gradio.temp_file_sets[0] | {os.path.abspath(filename)}
if hasattr(gradio, 'temp_dirs'): # gradio 3.9
gradio.temp_dirs = gradio.temp_dirs | {os.path.abspath(os.path.dirname(filename))}
def check_tmp_file(gradio, filename):
ok = False
if hasattr(gradio, 'temp_file_sets'):
return any([filename in fileset for fileset in gradio.temp_file_sets])
if hasattr(gradio, 'temp_dirs'):
return any(Path(temp_dir).resolve() in Path(filename).resolve().parents for temp_dir in gradio.temp_dirs)
return False
ok = ok or any([filename in fileset for fileset in gradio.temp_file_sets])
if shared.opts.outdir_samples != '':
ok = ok or Path(shared.opts.outdir_samples).resolve() in Path(filename).resolve().parents
else:
ok = ok or Path(shared.opts.outdir_txt2img_samples).resolve() in Path(filename).resolve().parents
ok = ok or Path(shared.opts.outdir_img2img_samples).resolve() in Path(filename).resolve().parents
ok = ok or Path(shared.opts.outdir_extras_samples).resolve() in Path(filename).resolve().parents
if shared.opts.outdir_grids != '':
ok = ok or Path(shared.opts.outdir_grids).resolve() in Path(filename).resolve().parents
else:
ok = ok or Path(shared.opts.outdir_txt2img_grids).resolve() in Path(filename).resolve().parents
ok = ok or Path(shared.opts.outdir_img2img_grids).resolve() in Path(filename).resolve().parents
ok = ok or Path(shared.opts.outdir_save).resolve() in Path(filename).resolve().parents
ok = ok or Path(shared.opts.outdir_init_images).resolve() in Path(filename).resolve().parents
return ok
def save_pil_to_file(pil_image, dir=None): # pylint: disable=redefined-builtin