stable-diffusion-webui-forge/modules/stealth_infotext.py
2025-02-23 15:03:50 -05:00

164 lines
6.3 KiB
Python

import gzip
from modules.script_callbacks import ImageSaveParams
from modules import shared
def add_stealth_pnginfo(params: ImageSaveParams):
stealth_pnginfo_option = shared.opts.data.get('stealth_pnginfo_option', 'Alpha')
if not stealth_pnginfo_option or stealth_pnginfo_option == 'None':
return
if not params.filename.endswith('.png') or params.pnginfo is None:
return
if 'parameters' not in params.pnginfo:
return
add_data(params, str(stealth_pnginfo_option), True)
def prepare_data(params, mode='Alpha', compressed=True):
signature = f"stealth_{'png' if mode == 'Alpha' else 'rgb'}{'info' if not compressed else 'comp'}"
binary_signature = ''.join(format(byte, '08b') for byte in signature.encode('utf-8'))
param = params.encode('utf-8') if not compressed else gzip.compress(bytes(params, 'utf-8'))
binary_param = ''.join(format(byte, '08b') for byte in param)
binary_param_len = format(len(binary_param), '032b')
return binary_signature + binary_param_len + binary_param
def add_data(params, mode='Alpha', compressed=True):
binary_data = prepare_data(params.pnginfo['parameters'], mode, compressed)
if mode == 'Alpha':
params.image.putalpha(255)
width, height = params.image.size
pixels = params.image.load()
index = 0
end_write = False
for x in range(width):
for y in range(height):
if index >= len(binary_data):
end_write = True
break
values = pixels[x, y]
if mode == 'Alpha':
r, g, b, a = values
else:
r, g, b = values
if mode == 'Alpha':
a = (a & ~1) | int(binary_data[index])
index += 1
else:
r = (r & ~1) | int(binary_data[index])
if index + 1 < len(binary_data):
g = (g & ~1) | int(binary_data[index + 1])
if index + 2 < len(binary_data):
b = (b & ~1) | int(binary_data[index + 2])
index += 3
pixels[x, y] = (r, g, b, a) if mode == 'Alpha' else (r, g, b)
if end_write:
break
def read_info_from_image_stealth(image):
geninfo = None
width, height = image.size
pixels = image.load()
has_alpha = True if image.mode == 'RGBA' else False
mode = None
compressed = False
binary_data = ''
buffer_a = ''
buffer_rgb = ''
index_a = 0
index_rgb = 0
sig_confirmed = False
confirming_signature = True
reading_param_len = False
reading_param = False
read_end = False
for x in range(width):
for y in range(height):
if has_alpha:
r, g, b, a = pixels[x, y]
buffer_a += str(a & 1)
index_a += 1
else:
r, g, b = pixels[x, y]
buffer_rgb += str(r & 1)
buffer_rgb += str(g & 1)
buffer_rgb += str(b & 1)
index_rgb += 3
if confirming_signature:
if index_a == len('stealth_pnginfo') * 8:
decoded_sig = bytearray(int(buffer_a[i:i + 8], 2) for i in
range(0, len(buffer_a), 8)).decode('utf-8', errors='ignore')
if decoded_sig in {'stealth_pnginfo', 'stealth_pngcomp'}:
confirming_signature = False
sig_confirmed = True
reading_param_len = True
mode = 'alpha'
if decoded_sig == 'stealth_pngcomp':
compressed = True
buffer_a = ''
index_a = 0
else:
read_end = True
break
elif index_rgb == len('stealth_pnginfo') * 8:
decoded_sig = bytearray(int(buffer_rgb[i:i + 8], 2) for i in
range(0, len(buffer_rgb), 8)).decode('utf-8', errors='ignore')
if decoded_sig in {'stealth_rgbinfo', 'stealth_rgbcomp'}:
confirming_signature = False
sig_confirmed = True
reading_param_len = True
mode = 'rgb'
if decoded_sig == 'stealth_rgbcomp':
compressed = True
buffer_rgb = ''
index_rgb = 0
elif reading_param_len:
if mode == 'alpha':
if index_a == 32:
param_len = int(buffer_a, 2)
reading_param_len = False
reading_param = True
buffer_a = ''
index_a = 0
else:
if index_rgb == 33:
pop = buffer_rgb[-1]
buffer_rgb = buffer_rgb[:-1]
param_len = int(buffer_rgb, 2)
reading_param_len = False
reading_param = True
buffer_rgb = pop
index_rgb = 1
elif reading_param:
if mode == 'alpha':
if index_a == param_len:
binary_data = buffer_a
read_end = True
break
else:
if index_rgb >= param_len:
diff = param_len - index_rgb
if diff < 0:
buffer_rgb = buffer_rgb[:diff]
binary_data = buffer_rgb
read_end = True
break
else:
# impossible
read_end = True
break
if read_end:
break
if sig_confirmed and binary_data != '':
# Convert binary string to UTF-8 encoded text
byte_data = bytearray(int(binary_data[i:i + 8], 2) for i in range(0, len(binary_data), 8))
try:
if compressed:
decoded_data = gzip.decompress(bytes(byte_data)).decode('utf-8')
else:
decoded_data = byte_data.decode('utf-8', errors='ignore')
geninfo = decoded_data
except:
pass
return geninfo