mirror of
https://github.com/vladmandic/automatic
synced 2026-09-13 10:08:43 +02:00
add batch info to metadata
This commit is contained in:
+1
-1
@@ -356,7 +356,7 @@
|
||||
{"id":"","label":"Enable splitting of hires batch processing","localized":"","hint":"Reduces VRAM usage when using hires fix on batches of images"},
|
||||
{"id":"","label":"Load models using stream loading method","localized":"","hint":"When loading models attempt stream loading optimized for slow or network storage"},
|
||||
{"id":"","label":"When loading models attempt to reuse previous model dictionary","localized":"","hint":""},
|
||||
{"id":"","label":"Disable cross-attention layer optimization","localized":"","hint":"Disable the all cross-attention optimization. May result in higher VRAM usage and longer generation times"},
|
||||
{"id":"","label":"Disabled","localized":"","hint":""},
|
||||
{"id":"","label":"xFormers","localized":"","hint":"Memory optimization. Non-Deterministic (different results each time)"},
|
||||
{"id":"","label":"Scaled-Dot-Product","localized":"","hint":"Memory optimization. Non-Deterministic unless SDP memory attention is disabled."},
|
||||
{"id":"","label":"Doggettx's","localized":"","hint":""},
|
||||
|
||||
+20
-8
@@ -291,7 +291,8 @@ def sanitize_filename_part(text, replace_spaces=True):
|
||||
|
||||
class FilenameGenerator:
|
||||
replacements = {
|
||||
'batch_number': lambda self: NOTHING if self.index <= 1 else self.index,
|
||||
'batch_number': lambda self: self.batch_number,
|
||||
'iter_number': lambda self: self.iter_number,
|
||||
'cfg': lambda self: self.p and self.p.cfg_scale,
|
||||
'clip_skip': lambda self: self.p and self.p.clip_skip,
|
||||
'date': lambda self: datetime.datetime.now().strftime('%Y-%m-%d'),
|
||||
@@ -320,12 +321,17 @@ class FilenameGenerator:
|
||||
}
|
||||
default_time_format = '%Y%m%d%H%M%S'
|
||||
|
||||
def __init__(self, p, seed, prompt, image, index = 0):
|
||||
def __init__(self, p, seed, prompt, image, grid=False):
|
||||
self.p = p
|
||||
self.seed = seed
|
||||
self.prompt = prompt
|
||||
self.image = image
|
||||
self.index = index if self.p is None or self.p.batch_size == 1 else self.p.batch_index + 1
|
||||
if not grid:
|
||||
self.batch_number = NOTHING if self.p is None or getattr(self.p, 'batch_size', 1) == 1 else (self.p.batch_index + 1 if hasattr(self.p, 'batch_index') else NOTHING)
|
||||
self.iter_number = NOTHING if self.p is None or getattr(self.p, 'n_iter', 1) == 1 else (self.p.iteration + 1 if hasattr(self.p, 'iteration') else NOTHING)
|
||||
else:
|
||||
self.batch_number = NOTHING
|
||||
self.iter_number = NOTHING
|
||||
|
||||
def hasprompt(self, *args):
|
||||
lower = self.prompt.lower()
|
||||
@@ -449,7 +455,7 @@ def atomically_save_image():
|
||||
image_format = 'JPEG'
|
||||
if shared.opts.image_watermark_enabled:
|
||||
image = set_watermark(image, shared.opts.image_watermark)
|
||||
shared.log.debug(f'Saving: image={fn} type={image_format} size={image.width}x{image.height}')
|
||||
shared.log.debug(f'Saving: image="{fn}" type={image_format} size={image.width}x{image.height}')
|
||||
# actual save
|
||||
exifinfo = (exifinfo or "") if shared.opts.image_metadata else ""
|
||||
if image_format == 'PNG':
|
||||
@@ -489,8 +495,14 @@ def atomically_save_image():
|
||||
with open(os.path.join(paths.data_path, "params.txt"), "w", encoding="utf8") as file:
|
||||
file.write(exifinfo)
|
||||
if shared.opts.save_log_fn != '' and len(exifinfo) > 0:
|
||||
entry = { 'filename': filename, 'time': datetime.datetime.now().isoformat(), 'info': exifinfo }
|
||||
shared.writefile(entry, os.path.join(paths.data_path, shared.opts.save_log_fn), mode='a+')
|
||||
fn = os.path.join(paths.data_path, shared.opts.save_log_fn)
|
||||
entries = shared.readfile(fn)
|
||||
idx = len(list(entries))
|
||||
if idx == 0:
|
||||
entries = []
|
||||
entry = { 'id': idx, 'filename': filename, 'time': datetime.datetime.now().isoformat(), 'info': exifinfo }
|
||||
entries.append(entry)
|
||||
shared.writefile(entries, fn, mode='w')
|
||||
save_queue.task_done()
|
||||
|
||||
|
||||
@@ -499,7 +511,7 @@ 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, index=0):
|
||||
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`):
|
||||
@@ -537,7 +549,7 @@ def save_image(image, path, basename, seed=None, prompt=None, extension='jpg', i
|
||||
return None, None
|
||||
if path is None or len(path) == 0: # set default path to avoid errors when functions are triggered manually or via api and param is not set
|
||||
path = shared.opts.outdir_save
|
||||
namegen = FilenameGenerator(p, seed, prompt, image, index)
|
||||
namegen = FilenameGenerator(p, seed, prompt, image, grid=grid)
|
||||
if save_to_dirs is None:
|
||||
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:
|
||||
|
||||
+10
-9
@@ -472,6 +472,7 @@ def create_infotext(p: StableDiffusionProcessing, all_prompts, all_seeds, all_su
|
||||
"CFG scale": p.cfg_scale,
|
||||
"Size": f"{p.width}x{p.height}",
|
||||
"Batch": f'{p.n_iter}x{p.batch_size}' if p.n_iter > 1 or p.batch_size > 1 else None,
|
||||
"Index": f'{p.iteration + 1}x{index + 1}' if (p.n_iter > 1 or p.batch_size > 1) and index >= 0 else None,
|
||||
"Parser": shared.opts.prompt_attention,
|
||||
"Model": None if (not shared.opts.add_model_name_to_info) or (not shared.sd_model.sd_checkpoint_info.model_name) else shared.sd_model.sd_checkpoint_info.model_name.replace(',', '').replace(':', ''),
|
||||
"Model hash": getattr(p, 'sd_model_hash', None if (not shared.opts.add_model_hash_to_info) or (not shared.sd_model.sd_model_hash) else shared.sd_model.sd_model_hash),
|
||||
@@ -798,7 +799,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||
p.scripts.postprocess_batch_list(p, batch_params, batch_number=n)
|
||||
x_samples_ddim = batch_params.images
|
||||
|
||||
def infotext(index=0): # pylint: disable=function-redefined # noqa: F811
|
||||
def infotext(index): # pylint: disable=function-redefined # noqa: F811
|
||||
return create_infotext(p, p.prompts, p.seeds, p.subseeds, index=index, all_negative_prompts=p.negative_prompts)
|
||||
|
||||
for i, x_sample in enumerate(x_samples_ddim):
|
||||
@@ -816,7 +817,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||
p.restore_faces = False
|
||||
info = infotext(i)
|
||||
p.restore_faces = orig
|
||||
images.save_image(Image.fromarray(x_sample), path=p.outpath_samples, basename="", seed=p.seeds[i], prompt=p.prompts[i], extension=shared.opts.samples_format, info=info, p=p, suffix="-before-face-restoration")
|
||||
images.save_image(Image.fromarray(x_sample), path=p.outpath_samples, basename="", seed=p.seeds[i], prompt=p.prompts[i], extension=shared.opts.samples_format, info=info, p=p, suffix="-before-face-restore")
|
||||
p.ops.append('face')
|
||||
x_sample = modules.face_restoration.restore_faces(x_sample)
|
||||
image = Image.fromarray(x_sample)
|
||||
@@ -831,7 +832,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||
info = infotext(i)
|
||||
p.color_corrections = orig
|
||||
image_without_cc = apply_overlay(image, p.paste_to, i, p.overlay_images)
|
||||
images.save_image(image_without_cc, path=p.outpath_samples, basename="", seed=p.seeds[i], prompt=p.prompts[i], extension=shared.opts.samples_format, info=info, p=p, suffix="-before-color-correction")
|
||||
images.save_image(image_without_cc, path=p.outpath_samples, basename="", seed=p.seeds[i], prompt=p.prompts[i], extension=shared.opts.samples_format, info=info, p=p, suffix="-before-color-correct")
|
||||
p.ops.append('color')
|
||||
image = apply_color_correction(p.color_corrections[i], image)
|
||||
image = apply_overlay(image, p.paste_to, i, p.overlay_images)
|
||||
@@ -840,7 +841,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||
image.info["parameters"] = text
|
||||
output_images.append(image)
|
||||
if shared.opts.samples_save and not p.do_not_save_samples:
|
||||
images.save_image(image, p.outpath_samples, "", p.seeds[i], p.prompts[i], shared.opts.samples_format, info=text, p=p)
|
||||
images.save_image(image, p.outpath_samples, "", p.seeds[i], p.prompts[i], shared.opts.samples_format, info=text, p=p) # main save image
|
||||
if hasattr(p, 'mask_for_overlay') and p.mask_for_overlay and any([shared.opts.save_mask, shared.opts.save_mask_composite, shared.opts.return_mask, shared.opts.return_mask_composite]):
|
||||
image_mask = p.mask_for_overlay.convert('RGB')
|
||||
image_mask_composite = Image.composite(image.convert('RGBA').convert('RGBa'), Image.new('RGBa', image.size), images.resize_image(3, p.mask_for_overlay, image.width, image.height).convert('L')).convert('RGBA')
|
||||
@@ -865,13 +866,13 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||
if images.check_grid_size(output_images):
|
||||
grid = images.image_grid(output_images, p.batch_size)
|
||||
if shared.opts.return_grid:
|
||||
text = infotext()
|
||||
text = infotext(-1)
|
||||
infotexts.insert(0, text)
|
||||
grid.info["parameters"] = text
|
||||
output_images.insert(0, grid)
|
||||
index_of_first_image = 1
|
||||
if shared.opts.grid_save:
|
||||
images.save_image(grid, p.outpath_grids, "grid", p.all_seeds[0], p.all_prompts[0], shared.opts.grid_format, info=infotext(), short_filename=not shared.opts.grid_extended_filename, p=p, grid=True)
|
||||
images.save_image(grid, p.outpath_grids, "", p.all_seeds[0], p.all_prompts[0], shared.opts.grid_format, info=infotext(-1), short_filename=not shared.opts.grid_extended_filename, p=p, grid=True, suffix="-grid") # main save grid
|
||||
|
||||
if not p.disable_extra_networks and extra_network_data:
|
||||
modules.extra_networks.deactivate(p, extra_network_data)
|
||||
@@ -880,7 +881,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||
p,
|
||||
images_list=output_images,
|
||||
seed=p.all_seeds[0],
|
||||
info=infotext(),
|
||||
info=infotext(0),
|
||||
comments="\n".join(comments),
|
||||
subseed=p.all_subseeds[0],
|
||||
index_of_first_image=index_of_first_image,
|
||||
@@ -987,7 +988,7 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
|
||||
info = create_infotext(self, self.all_prompts, self.all_seeds, self.all_subseeds, [], iteration=self.iteration, position_in_batch=index)
|
||||
self.extra_generation_params = orig1
|
||||
self.restore_faces = orig2
|
||||
images.save_image(image, self.outpath_samples, "", seeds[index], prompts[index], shared.opts.samples_format, info=info, suffix="-before-hires", index=index+1)
|
||||
images.save_image(image, self.outpath_samples, "", seeds[index], prompts[index], shared.opts.samples_format, info=info, suffix="-before-hires")
|
||||
|
||||
if shared.backend == shared.Backend.DIFFUSERS:
|
||||
modules.sd_models.set_diffuser_pipe(self.sd_model, modules.sd_models.DiffusersTaskType.TEXT_2_IMAGE)
|
||||
@@ -1140,7 +1141,7 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing):
|
||||
self.init_img_width = img.width # pylint: disable=attribute-defined-outside-init
|
||||
self.init_img_height = img.height # pylint: disable=attribute-defined-outside-init
|
||||
if shared.opts.save_init_img:
|
||||
images.save_image(img, path=shared.opts.outdir_init_images, basename=None, forced_filename=self.init_img_hash, save_to_dirs=False)
|
||||
images.save_image(img, path=shared.opts.outdir_init_images, basename=None, forced_filename=self.init_img_hash, save_to_dirs=False, suffix="-init-image")
|
||||
image = images.flatten(img, shared.opts.img2img_background_color)
|
||||
if crop_region is None and self.resize_mode != 4:
|
||||
image = images.resize_image(self.resize_mode, image, self.width, self.height)
|
||||
|
||||
+4
-11
@@ -37,45 +37,38 @@ def apply_optimizations():
|
||||
can_use_sdp = hasattr(torch.nn.functional, "scaled_dot_product_attention") and callable(torch.nn.functional.scaled_dot_product_attention)
|
||||
if devices.device == torch.device("cpu"):
|
||||
if opts.cross_attention_optimization == "Scaled-Dot-Product":
|
||||
shared.log.warning("Scaled dot product cross attention is not available on CPU")
|
||||
shared.log.warning("Cross-attention: Scaled dot product is not available on CPU")
|
||||
can_use_sdp = False
|
||||
if opts.cross_attention_optimization == "xFormers":
|
||||
shared.log.warning("xFormers cross attention is not available on CPU")
|
||||
shared.log.warning("Cross-attention: xFormers is not available on CPU")
|
||||
shared.xformers_available = False
|
||||
|
||||
if opts.cross_attention_optimization == "Disable cross-attention layer optimization":
|
||||
shared.log.warning("Cross-attention optimization disabled")
|
||||
shared.log.info(f"Cross-attention: optimization={opts.cross_attention_optimization} options={opts.cross_attention_options}")
|
||||
if opts.cross_attention_optimization == "Disabled":
|
||||
optimization_method = 'none'
|
||||
if can_use_sdp and opts.cross_attention_optimization == "Scaled-Dot-Product" and 'SDP disable memory attention' in opts.cross_attention_options:
|
||||
shared.log.info("Applying scaled dot product cross attention optimization (without memory efficient attention)")
|
||||
ldm.modules.attention.CrossAttention.forward = sd_hijack_optimizations.scaled_dot_product_no_mem_attention_forward
|
||||
ldm.modules.diffusionmodules.model.AttnBlock.forward = sd_hijack_optimizations.sdp_no_mem_attnblock_forward
|
||||
optimization_method = 'sdp-no-mem'
|
||||
elif can_use_sdp and opts.cross_attention_optimization == "Scaled-Dot-Product":
|
||||
shared.log.info("Applying scaled dot product cross attention optimization")
|
||||
ldm.modules.attention.CrossAttention.forward = sd_hijack_optimizations.scaled_dot_product_attention_forward
|
||||
ldm.modules.diffusionmodules.model.AttnBlock.forward = sd_hijack_optimizations.sdp_attnblock_forward
|
||||
optimization_method = 'sdp'
|
||||
if shared.xformers_available and opts.cross_attention_optimization == "xFormers":
|
||||
shared.log.info("Applying xformers cross attention optimization")
|
||||
ldm.modules.attention.CrossAttention.forward = sd_hijack_optimizations.xformers_attention_forward
|
||||
ldm.modules.diffusionmodules.model.AttnBlock.forward = sd_hijack_optimizations.xformers_attnblock_forward
|
||||
optimization_method = 'xformers'
|
||||
if opts.cross_attention_optimization == "Sub-quadratic":
|
||||
shared.log.info("Applying sub-quadratic cross attention optimization")
|
||||
ldm.modules.attention.CrossAttention.forward = sd_hijack_optimizations.sub_quad_attention_forward
|
||||
ldm.modules.diffusionmodules.model.AttnBlock.forward = sd_hijack_optimizations.sub_quad_attnblock_forward
|
||||
optimization_method = 'sub-quadratic'
|
||||
if opts.cross_attention_optimization == "Split attention":
|
||||
shared.log.info("Applying split attention optimization")
|
||||
ldm.modules.attention.CrossAttention.forward = sd_hijack_optimizations.split_cross_attention_forward_v1
|
||||
optimization_method = 'v1'
|
||||
if opts.cross_attention_optimization == "InvokeAI's":
|
||||
shared.log.info("Applying InvokeAI cross attention optimization")
|
||||
ldm.modules.attention.CrossAttention.forward = sd_hijack_optimizations.split_cross_attention_forward_invokeAI
|
||||
optimization_method = 'invokeai'
|
||||
if opts.cross_attention_optimization == "Doggettx's":
|
||||
shared.log.info("Applying Doggettx cross attention optimization")
|
||||
ldm.modules.attention.CrossAttention.forward = sd_hijack_optimizations.split_cross_attention_forward
|
||||
ldm.modules.diffusionmodules.model.AttnBlock.forward = sd_hijack_optimizations.cross_attention_attnblock_forward
|
||||
optimization_method = 'doggettx'
|
||||
|
||||
@@ -261,7 +261,7 @@ def select_checkpoint(op='model'):
|
||||
return None
|
||||
checkpoint_info = get_closet_checkpoint_match(model_checkpoint)
|
||||
if checkpoint_info is not None:
|
||||
shared.log.debug(f'Select checkpoint: {op} {checkpoint_info.title if checkpoint_info is not None else None}')
|
||||
shared.log.debug(f'Select checkpoint: {op}="{checkpoint_info.title if checkpoint_info is not None else None}"')
|
||||
return checkpoint_info
|
||||
if len(checkpoints_list) == 0 and not shared.cmd_opts.no_download:
|
||||
shared.log.error("Cannot run without a checkpoint")
|
||||
@@ -275,7 +275,7 @@ def select_checkpoint(op='model'):
|
||||
shared.log.info("Selecting first available checkpoint")
|
||||
# shared.log.warning(f"Loading fallback checkpoint: {checkpoint_info.title}")
|
||||
shared.opts.data['sd_model_checkpoint'] = checkpoint_info.title
|
||||
shared.log.debug(f'Select checkpoint: {checkpoint_info.title if checkpoint_info is not None else None}')
|
||||
shared.log.debug(f'Select checkpoint: {op}="{checkpoint_info.title if checkpoint_info is not None else None}"')
|
||||
return checkpoint_info
|
||||
|
||||
|
||||
|
||||
+3
-2
@@ -340,7 +340,7 @@ def readfile(filename, silent=False):
|
||||
return data
|
||||
|
||||
|
||||
def writefile(data, filename, mode='w'):
|
||||
def writefile(data, filename, mode='w', silent=False):
|
||||
|
||||
def default(obj):
|
||||
log.error(f"Saving: {filename} not a valid object: {obj}")
|
||||
@@ -350,7 +350,8 @@ def writefile(data, filename, mode='w'):
|
||||
with fasteners.InterProcessLock(f"{filename}.lock"):
|
||||
# skipkeys=True, ensure_ascii=True, check_circular=True, allow_nan=True
|
||||
output = json.dumps(data, indent=2, default=default)
|
||||
log.debug(f'Saving: {filename} len={len(output)}')
|
||||
if not silent:
|
||||
log.debug(f'Saving: {filename} len={len(output)}')
|
||||
with open(filename, mode, encoding="utf8") as file:
|
||||
file.write(output)
|
||||
except Exception as e:
|
||||
|
||||
@@ -20,7 +20,7 @@ def refresh_vae_list():
|
||||
|
||||
def list_crossattention():
|
||||
return [
|
||||
"Disable cross-attention layer optimization",
|
||||
"Disabled",
|
||||
"xFormers",
|
||||
"Scaled-Dot-Product",
|
||||
"Doggettx's",
|
||||
|
||||
+13
-11
@@ -75,17 +75,21 @@ def save_files(js_data, images, html_info, index):
|
||||
class PObject: # pylint: disable=too-few-public-methods
|
||||
def __init__(self, d=None):
|
||||
if d is not None:
|
||||
for key, value in d.items():
|
||||
setattr(self, key, value)
|
||||
self.seed = getattr(self, 'seed', None) or getattr(self, 'Seed', None)
|
||||
for k, v in d.items():
|
||||
setattr(self, k, v)
|
||||
self.prompt = getattr(self, 'prompt', None) or getattr(self, 'Prompt', None)
|
||||
self.all_seeds = getattr(self, 'all_seeds', [self.seed])
|
||||
self.all_prompts = getattr(self, 'all_prompts', [self.prompt])
|
||||
self.negative_prompt = getattr(self, 'negative_prompt', None)
|
||||
self.all_negative_prompt = getattr(self, 'all_negative_prompts', [self.negative_prompt])
|
||||
self.seed = getattr(self, 'seed', None) or getattr(self, 'Seed', None)
|
||||
self.all_seeds = getattr(self, 'all_seeds', [self.seed])
|
||||
self.subseed = getattr(self, 'subseed', None)
|
||||
self.all_subseeds = getattr(self, 'all_subseeds', [self.subseed])
|
||||
self.width = getattr(self, 'width', None)
|
||||
self.height = getattr(self, 'height', None)
|
||||
self.index_of_first_image = getattr(self, 'index_of_first_image', 0)
|
||||
self.infotexts = getattr(self, 'infotexts', [html_info])
|
||||
self.infotext = self.infotexts[0] if len(self.infotexts) > 0 else html_info
|
||||
self.index_of_first_image = getattr(self, 'index_of_first_image', 0)
|
||||
self.batch_size = 1
|
||||
|
||||
try:
|
||||
data = json.loads(js_data)
|
||||
except Exception:
|
||||
@@ -95,8 +99,6 @@ def save_files(js_data, images, html_info, index):
|
||||
if index > -1 and shared.opts.save_selected_only and (index >= p.index_of_first_image): # ensures we are looking at a specific non-grid picture, and we have save_selected_only # pylint: disable=no-member
|
||||
images = [images[index]]
|
||||
start_index = index
|
||||
else:
|
||||
p.batch_size = len(images)
|
||||
filenames = []
|
||||
fullfns = []
|
||||
for image_index, filedata in enumerate(images, start_index):
|
||||
@@ -114,12 +116,12 @@ def save_files(js_data, images, html_info, index):
|
||||
fullfns.append(fullfn)
|
||||
destination = shared.opts.outdir_save
|
||||
if shared.opts.use_save_to_dirs_for_ui:
|
||||
namegen = modules.images.FilenameGenerator(p, seed=p.all_seeds[i], prompt=p.all_prompts[i], image=None, index=image_index) # pylint: disable=no-member
|
||||
namegen = modules.images.FilenameGenerator(p, seed=p.all_seeds[i], prompt=p.all_prompts[i], image=None) # pylint: disable=no-member
|
||||
dirname = namegen.apply(shared.opts.directories_filename_pattern or "[prompt_words]").lstrip(' ').rstrip('\\ /')
|
||||
destination = os.path.join(destination, dirname)
|
||||
os.makedirs(destination, exist_ok = True)
|
||||
shutil.copy(fullfn, destination)
|
||||
shared.log.info(f"Copying image: {fullfn} -> {destination}")
|
||||
shared.log.info(f'Copying image: file="{fullfn}" folder="{destination}"')
|
||||
tgt_filename = os.path.join(destination, os.path.basename(fullfn))
|
||||
modules.script_callbacks.image_save_btn_callback(tgt_filename)
|
||||
else:
|
||||
|
||||
@@ -61,7 +61,7 @@ def pil_to_temp_file(self, img, dir: str, format="png") -> str: # pylint: disabl
|
||||
file_obj = tempfile.NamedTemporaryFile(delete=False, suffix=".png", dir=dir)
|
||||
img.save(file_obj, pnginfo=(metadata if use_metadata else None))
|
||||
name = file_obj.name
|
||||
shared.log.debug(f'Saving temp image: {name}')
|
||||
shared.log.debug(f'Saving temp: image="{name}"')
|
||||
return name
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user