import os
import subprocess
import io
from PIL import Image
default_multiplier = {
'dib': 0.025,
'jpeg': 0.001,
'jpeg2000': 0.0001,
'png': 0.001,
'sgi': 0.01,
'tga': 0.03,
'webp': 0.000001,
}
fpath = 'input/ecfuzz.png'
outdir = 'output/'
input_format = 'jpeg'
output_format = 'png'
multiplier = default_multiplier[input_format]
frame_count = 128
max_iterations = 100000
frames_dir = os.path.join(outdir, 'frames')
assert os.path.isfile(fpath), 'input file does not exist'
if not os.path.isdir(frames_dir):
print(f'creating output directory: {frames_dir}')
os.makedirs(frames_dir)
with open(fpath, 'rb') as f:
img = f.read()
outfile = io.BytesIO()
assert outfile.tell() == 0
convert = Image.open(io.BytesIO(img))
if convert.size[0] > 512 or convert.size[1] > 512:
convert.thumbnail((512, 512))
convertcopy = convert.copy()
try:
convertcopy.save(fp=outfile,
format=input_format,
lossless=True,
quality=95,
method=6,
exact=True)
except OSError as e:
assert "cannot write mode RGBA" in str(e)
convertcopy = convertcopy.convert('RGB')
convertcopy.save(fp=outfile, format=input_format, quality=95, method=6)
outfile.seek(0)
img = outfile.read()
seed = 0
while len(os.listdir(frames_dir)) < frame_count:
seed += 1
args = ('ecfuzz', '--mutate-stdin', '--multiplier', str(multiplier),
'--seed', str(seed))
proc = subprocess.Popen(args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
out, _err = proc.communicate(img)
_ = proc.wait()
if _err is not None:
raise Exception("Mutation error")
if out == img:
print(f'warning: duplicate {seed=}')
continue
try:
outimg = Image.open(io.BytesIO(out), mode='r')
if outimg.mode != convertcopy.mode:
outimg = outimg.convert(convertcopy.mode)
outimg.save(
fp=f'{os.path.join(frames_dir, str(seed))}.{output_format}',
format=output_format)
except Exception:
pass
if seed > max_iterations:
print(f'warning: hit mutation limit after {max_iterations} attempts')
break
frames = [
Image.open(i) for i in sorted(
[os.path.join(frames_dir, f) for f in os.listdir(frames_dir)])
]
filename_stem = fpath.rsplit(os.path.sep, 1)[1].split('.')[0]
outname = os.path.join(os.path.dirname(frames_dir), filename_stem + '.gif')
outfile = Image.open(io.BytesIO(img))
outfile.save(outname,
format="gif",
append_images=frames,
save_all=True,
duration=128,
loop=0)
for file in os.listdir(frames_dir):
os.remove(frames_dir + os.path.sep + file)
assert len(os.listdir(frames_dir)) == 0