Render Tests: Separate difference of Color and Alpha

This change fixes confusion situation when the render output
is an RGBA image: the difference in color was not visible in
the report because alpha channel was all zeros. This is due
to idiff performing per-channel difference.

The solution to this problem is to have separate images for
color and alpha difference, which makes it clear where the
difference actually is coming from.
This commit is contained in:
Sergey Sharybin 2024-01-25 10:04:16 +01:00 committed by Sergey Sharybin
parent 81c1490877
commit f11292104d
17 changed files with 108 additions and 101 deletions

View File

@ -12,7 +12,7 @@
# This can also be an environment variable.
# OPENIMAGEIO_FOUND, If false, do not try to use OpenImageIO.
# OPENIMAGEIO_PUGIXML_FOUND, Indicates whether OIIO has biltin PuguXML parser.
# OPENIMAGEIO_IDIFF, full path to idiff application if found.
# OPENIMAGEIO_TOOL, full path to oiiotool application if found.
#
# also defined, but not for general use are
# OPENIMAGEIO_LIBRARY, where to find the OpenImageIO library.
@ -51,9 +51,9 @@ find_library(OPENIMAGEIO_LIBRARY
set(_openimageio_LIBRARIES ${OPENIMAGEIO_LIBRARY})
find_file(OPENIMAGEIO_IDIFF
find_file(OPENIMAGEIO_TOOL
NAMES
idiff
oiiotool
HINTS
${_openimageio_SEARCH_DIRS}
PATH_SUFFIXES
@ -115,7 +115,7 @@ mark_as_advanced(
OPENIMAGEIO_INCLUDE_DIR
OPENIMAGEIO_LIBRARY
OPENIMAGEIO_UTIL_LIBRARY
OPENIMAGEIO_IDIFF
OPENIMAGEIO_TOOL
)
unset(_openimageio_SEARCH_DIRS)

View File

@ -684,7 +684,7 @@ if(NOT OpenImageIO_FOUND)
set(OIIO_OPTIMIZED optimized ${OPENIMAGEIO_LIBPATH}/OpenImageIO.lib optimized ${OPENIMAGEIO_LIBPATH}/OpenImageIO_Util.lib)
set(OIIO_DEBUG debug ${OPENIMAGEIO_LIBPATH}/OpenImageIO_d.lib debug ${OPENIMAGEIO_LIBPATH}/OpenImageIO_Util_d.lib)
set(OPENIMAGEIO_LIBRARIES ${OIIO_OPTIMIZED} ${OIIO_DEBUG})
set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe")
set(OPENIMAGEIO_TOOL "${OPENIMAGEIO}/bin/oiiotool.exe")
endif()
if(WITH_LLVM)

View File

@ -109,7 +109,7 @@ endfunction()
# Run Python render test.
function(add_render_test testname testscript)
set(_args ${ARGN} -blender "${TEST_BLENDER_EXE}" -idiff "${OPENIMAGEIO_IDIFF}")
set(_args ${ARGN} -blender "${TEST_BLENDER_EXE}" -oiiotool "${OPENIMAGEIO_TOOL}")
if(WITH_TESTS_BATCHED)
list(APPEND _args --batch)
endif()
@ -584,8 +584,8 @@ endif()
# SVG Import
if(TRUE)
if(NOT OPENIMAGEIO_IDIFF)
message(WARNING "Disabling SVG tests because OIIO idiff does not exist")
if(NOT OPENIMAGEIO_TOOL)
message(WARNING "Disabling SVG tests because OIIO oiiotool does not exist")
else()
set(_svg_render_tests complex path)
@ -603,8 +603,8 @@ if(TRUE)
endif()
if(WITH_CYCLES OR WITH_GPU_RENDER_TESTS)
if(NOT OPENIMAGEIO_IDIFF)
message(WARNING "Disabling render tests because OIIO idiff does not exist")
if(NOT OPENIMAGEIO_TOOL)
message(WARNING "Disabling render tests because OIIO oiiotool does not exist")
elseif(NOT EXISTS "${TEST_SRC_DIR}/render/shader")
message(WARNING "Disabling render tests because tests folder does not exist at ${TEST_SRC_DIR}")
elseif(NOT WITH_COMPOSITOR_CPU)
@ -751,8 +751,8 @@ if(WITH_CYCLES OR WITH_GPU_RENDER_TESTS)
endif()
if(WITH_COMPOSITOR_CPU)
if(NOT OPENIMAGEIO_IDIFF)
message(WARNING "Disabling Compositor CPU tests because OIIO idiff does not exist")
if(NOT OPENIMAGEIO_TOOL)
message(WARNING "Disabling Compositor CPU tests because OIIO oiiotool does not exist")
else()
set(compositor_tests
color
@ -783,8 +783,8 @@ endif()
# NOTE: WITH_COMPOSITOR_CPU is needed for rendering.
if(WITH_COMPOSITOR_REALTIME_TESTS AND WITH_COMPOSITOR_CPU)
if(NOT OPENIMAGEIO_IDIFF)
message(WARNING "Disabling realtime compositor tests because OIIO idiff does not exist")
if(NOT OPENIMAGEIO_TOOL)
message(WARNING "Disabling realtime compositor tests because OIIO oiiotool does not exist")
else()
set(compositor_tests
color
@ -876,8 +876,8 @@ endif()
if(WITH_GPU_DRAW_TESTS)
if(NOT OPENIMAGEIO_IDIFF)
message(STATUS "Disabling OpenGL draw tests because OIIO idiff does not exist")
if(NOT OPENIMAGEIO_TOOL)
message(STATUS "Disabling OpenGL draw tests because OIIO oiiotool does not exist")
elseif(NOT EXISTS "${TEST_SRC_DIR}/opengl")
message(STATUS "Disabling OpenGL draw tests because tests folder does not exist at ${TEST_SRC_DIR}")
else()
@ -950,8 +950,8 @@ if(WITH_CODEC_FFMPEG)
)
endif()
if(NOT OPENIMAGEIO_IDIFF)
message(STATUS "Disabling ImBuf image format tests because OIIO idiff does not exist")
if(NOT OPENIMAGEIO_TOOL)
message(STATUS "Disabling ImBuf image format tests because OIIO oiiotool does not exist")
else()
set(OPTIONAL_FORMATS "")
if(WITH_IMAGE_CINEON)
@ -973,7 +973,7 @@ else()
--
-test_dir "${TEST_SRC_DIR}/imbuf_io"
-output_dir "${TEST_OUT_DIR}/imbuf_io/save"
-idiff "${OPENIMAGEIO_IDIFF}"
-oiiotool "${OPENIMAGEIO_TOOL}"
-optional_formats "${OPTIONAL_FORMATS}"
)
@ -983,7 +983,7 @@ else()
--
-test_dir "${TEST_SRC_DIR}/imbuf_io"
-output_dir "${TEST_OUT_DIR}/imbuf_io/load"
-idiff "${OPENIMAGEIO_IDIFF}"
-oiiotool "${OPENIMAGEIO_TOOL}"
-optional_formats "${OPTIONAL_FORMATS}"
)
endif()
@ -991,8 +991,8 @@ endif()
# ------------------------------------------------------------------------------
# SEQUENCER RENDER TESTS
if(NOT OPENIMAGEIO_IDIFF)
message(STATUS "Disabling sequencer render tests because OIIO idiff does not exist")
if(NOT OPENIMAGEIO_TOOL)
message(STATUS "Disabling sequencer render tests because OIIO oiiotool does not exist")
else()
set(render_tests
transform

View File

@ -196,7 +196,7 @@ def main():
parser = argparse.ArgumentParser()
parser.add_argument('-test_dir', required=True, type=pathlib.Path)
parser.add_argument('-output_dir', required=True, type=pathlib.Path)
parser.add_argument('-idiff', required=True, type=pathlib.Path)
parser.add_argument('-oiiotool', required=True, type=pathlib.Path)
parser.add_argument('-optional_formats', required=True)
args, remaining = parser.parse_known_args(argv)

View File

@ -263,7 +263,7 @@ def main():
parser = argparse.ArgumentParser()
parser.add_argument('-test_dir', required=True, type=pathlib.Path)
parser.add_argument('-output_dir', required=True, type=pathlib.Path)
parser.add_argument('-idiff', required=True, type=pathlib.Path)
parser.add_argument('-oiiotool', required=True, type=pathlib.Path)
parser.add_argument('-optional_formats', required=True)
args, remaining = parser.parse_known_args(argv)

View File

@ -36,7 +36,7 @@ def create_argparse():
parser.add_argument("-blender", nargs="+")
parser.add_argument("-testdir", nargs=1)
parser.add_argument("-outdir", nargs=1)
parser.add_argument("-idiff", nargs=1)
parser.add_argument("-oiiotool", nargs=1)
parser.add_argument('--batch', default=False, action='store_true')
return parser
@ -47,11 +47,11 @@ def main():
blender = args.blender[0]
test_dir = args.testdir[0]
idiff = args.idiff[0]
oiiotool = args.oiiotool[0]
output_dir = args.outdir[0]
from modules import render_report
report = render_report.Report('IO Curve SVG', output_dir, idiff)
report = render_report.Report('IO Curve SVG', output_dir, oiiotool)
report.set_pixelated(True)
test_dir_name = Path(test_dir).name

View File

@ -37,7 +37,7 @@ def create_argparse():
parser.add_argument("-blender", nargs="+")
parser.add_argument("-testdir", nargs=1)
parser.add_argument("-outdir", nargs=1)
parser.add_argument("-idiff", nargs=1)
parser.add_argument("-oiiotool", nargs=1)
parser.add_argument('--batch', default=False, action='store_true')
return parser
@ -48,11 +48,11 @@ def main():
blender = args.blender[0]
test_dir = args.testdir[0]
idiff = args.idiff[0]
oiiotool = args.oiiotool[0]
output_dir = args.outdir[0]
from modules import render_report
report = render_report.Report("Compositor CPU", output_dir, idiff)
report = render_report.Report("Compositor CPU", output_dir, oiiotool)
report.set_pixelated(True)
report.set_reference_dir("compositor_cpu_renders")

View File

@ -42,7 +42,7 @@ def create_argparse():
parser.add_argument("-blender", nargs="+")
parser.add_argument("-testdir", nargs=1)
parser.add_argument("-outdir", nargs=1)
parser.add_argument("-idiff", nargs=1)
parser.add_argument("-oiiotool", nargs=1)
parser.add_argument('--batch', default=False, action='store_true')
return parser
@ -53,11 +53,11 @@ def main():
blender = args.blender[0]
test_dir = args.testdir[0]
idiff = args.idiff[0]
oiiotool = args.oiiotool[0]
output_dir = args.outdir[0]
from modules import render_report
report = render_report.Report("Compositor Realtime", output_dir, idiff)
report = render_report.Report("Compositor Realtime", output_dir, oiiotool)
report.set_reference_dir("compositor_realtime_renders")
ok = report.run(test_dir, blender, get_arguments, batch=args.batch)

View File

@ -104,7 +104,7 @@ def create_argparse():
parser.add_argument("-blender", nargs="+")
parser.add_argument("-testdir", nargs=1)
parser.add_argument("-outdir", nargs=1)
parser.add_argument("-idiff", nargs=1)
parser.add_argument("-oiiotool", nargs=1)
parser.add_argument("-device", nargs=1)
parser.add_argument("-blacklist", nargs="*")
parser.add_argument('--batch', default=False, action='store_true')
@ -117,7 +117,7 @@ def main():
blender = args.blender[0]
test_dir = args.testdir[0]
idiff = args.idiff[0]
oiiotool = args.oiiotool[0]
output_dir = args.outdir[0]
device = args.device[0]
@ -132,7 +132,7 @@ def main():
blacklist += BLACKLIST_METAL
from modules import render_report
report = render_report.Report('Cycles', output_dir, idiff, device, blacklist)
report = render_report.Report('Cycles', output_dir, oiiotool, device, blacklist)
report.set_pixelated(True)
report.set_reference_dir("cycles_renders")
if device == 'CPU':

View File

@ -114,7 +114,7 @@ def create_argparse():
parser.add_argument("-blender", nargs="+")
parser.add_argument("-testdir", nargs=1)
parser.add_argument("-outdir", nargs=1)
parser.add_argument("-idiff", nargs=1)
parser.add_argument("-oiiotool", nargs=1)
parser.add_argument('--batch', default=False, action='store_true')
return parser
@ -125,7 +125,7 @@ def main():
blender = args.blender[0]
test_dir = args.testdir[0]
idiff = args.idiff[0]
oiiotool = args.oiiotool[0]
output_dir = args.outdir[0]
gpu_device_type = get_gpu_device_type(blender)
@ -134,7 +134,7 @@ def main():
reference_override_dir = "eevee_next_renders/amd"
from modules import render_report
report = render_report.Report("Eevee Next", output_dir, idiff)
report = render_report.Report("Eevee Next", output_dir, oiiotool)
report.set_pixelated(True)
report.set_reference_dir("eevee_next_renders")
report.set_reference_override_dir(reference_override_dir)

View File

@ -142,7 +142,7 @@ def create_argparse():
parser.add_argument("-blender", nargs="+")
parser.add_argument("-testdir", nargs=1)
parser.add_argument("-outdir", nargs=1)
parser.add_argument("-idiff", nargs=1)
parser.add_argument("-oiiotool", nargs=1)
parser.add_argument('--batch', default=False, action='store_true')
return parser
@ -153,7 +153,7 @@ def main():
blender = args.blender[0]
test_dir = args.testdir[0]
idiff = args.idiff[0]
oiiotool = args.oiiotool[0]
output_dir = args.outdir[0]
gpu_device_type = get_gpu_device_type(blender)
@ -162,7 +162,7 @@ def main():
reference_override_dir = "eevee_renders/amd"
from modules import render_report
report = render_report.Report("Eevee", output_dir, idiff)
report = render_report.Report("Eevee", output_dir, oiiotool)
report.set_pixelated(True)
report.set_reference_dir("eevee_renders")
report.set_reference_override_dir(reference_override_dir)

View File

@ -19,7 +19,7 @@ class AbstractImBufTest(unittest.TestCase):
cls.reference_load_dir = pathlib.Path(args.test_dir).joinpath("reference_load")
cls.output_dir = pathlib.Path(args.output_dir)
cls.diff_dir = pathlib.Path(args.output_dir).joinpath("diff")
cls.idiff = pathlib.Path(args.idiff)
cls.oiiotool = pathlib.Path(args.oiiotool)
cls.optional_formats = args.optional_formats
os.makedirs(cls.diff_dir, exist_ok=True)
@ -51,11 +51,12 @@ class AbstractImBufTest(unittest.TestCase):
if os.path.exists(ref_filepath):
# Diff images test with threshold.
command = (
str(self.idiff),
"-fail", str(self.fail_threshold),
"-failpercent", str(self.fail_percent),
str(self.oiiotool),
ref_filepath,
out_filepath,
"--fail", str(self.fail_threshold),
"--failpercent", str(self.fail_percent),
"--diff",
)
try:
subprocess.check_output(command)
@ -63,7 +64,7 @@ class AbstractImBufTest(unittest.TestCase):
except subprocess.CalledProcessError as e:
if self.verbose:
print_message(e.output.decode("utf-8", 'ignore'))
failed = e.returncode != 1
failed = e.returncode != 0
else:
if not self.update:
return False
@ -78,13 +79,13 @@ class AbstractImBufTest(unittest.TestCase):
# Generate diff image (set fail thresholds high to reduce output spam).
diff_img = str(self.diff_dir.joinpath(out_name + ".diff.png"))
command = (
str(self.idiff),
"-fail", "1",
"-failpercent", "100",
"-abs", "-scale", "16",
"-o", diff_img,
str(self.oiiotool),
ref_filepath,
out_filepath
out_filepath,
"--sub",
"--abs",
"--mulc", "16",
"-o", diff_img,
)
try:

View File

@ -67,9 +67,10 @@ def test_get_images(output_dir, filepath, reference_dir, reference_override_dir)
diff_dirpath = os.path.join(output_dir, os.path.basename(dirpath), "diff")
os.makedirs(diff_dirpath, exist_ok=True)
diff_img = os.path.join(diff_dirpath, testname + ".diff.png")
diff_color_img = os.path.join(diff_dirpath, testname + ".diff_color.png")
diff_alpha_img = os.path.join(diff_dirpath, testname + ".diff_alpha.png")
return old_img, ref_img, new_img, diff_img
return old_img, ref_img, new_img, diff_color_img, diff_alpha_img
class Report:
@ -79,7 +80,7 @@ class Report:
'global_dir',
'reference_dir',
'reference_override_dir',
'idiff',
'oiiotool',
'pixelated',
'fail_threshold',
'fail_percent',
@ -93,13 +94,13 @@ class Report:
'blacklist',
)
def __init__(self, title, output_dir, idiff, device=None, blacklist=[]):
def __init__(self, title, output_dir, oiiotool, device=None, blacklist=[]):
self.title = title
self.output_dir = output_dir
self.global_dir = os.path.dirname(output_dir)
self.reference_dir = 'reference_renders'
self.reference_override_dir = None
self.idiff = idiff
self.oiiotool = oiiotool
self.compare_engine = None
self.fail_threshold = 0.016
self.fail_percent = 1
@ -246,13 +247,22 @@ class Report:
columns_html = "<tr><th>Name</th><th>%s</th><th>%s</th>" % (engine_self, engine_other)
else:
title = self.title + " Test Report"
columns_html = "<tr><th>Name</th><th>New</th><th>Reference</th><th>Diff</th>"
columns_html = "<tr><th>Name</th><th>New</th><th>Reference</th><th>Diff Color</th><th>Diff Alpha</th>"
html = """
html = f"""
<html>
<head>
<title>{title}</title>
<style>
div.page_container {{
text-align: center;
}}
div.page_container div {{
text-align: left;
}}
div.page_content {{
display: inline-block;
}}
img {{ image-rendering: {image_rendering}; width: 256px; background-color: #000; }}
img.render {{
background-color: #fff;
@ -279,7 +289,7 @@ class Report:
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="page_container"><div class="page_content">
<br/>
<h1>{title}</h1>
{menu}
@ -291,15 +301,10 @@ class Report:
{tests_html}
</table>
<br/>
</div>
</div></div>
</body>
</html>
""" . format(title=title,
menu=menu,
message=message,
image_rendering=image_rendering,
tests_html=tests_html,
columns_html=columns_html)
"""
filename = "report.html" if not comparison else "compare.html"
filepath = os.path.join(self.output_dir, filename)
@ -320,7 +325,7 @@ class Report:
name = test_get_name(filepath)
name = name.replace('_', ' ')
old_img, ref_img, new_img, diff_img = test_get_images(
old_img, ref_img, new_img, diff_color_img, diff_alpha_img = test_get_images(
self.output_dir, filepath, self.reference_dir, self.reference_override_dir)
status = error if error else ""
@ -328,21 +333,17 @@ class Report:
new_url = self._relative_url(new_img)
ref_url = self._relative_url(ref_img)
diff_url = self._relative_url(diff_img)
diff_color_url = self._relative_url(diff_color_img)
diff_alpha_url = self._relative_url(diff_alpha_img)
test_html = """
test_html = f"""
<tr{tr_style}>
<td><b>{name}</b><br/>{testname}<br/>{status}</td>
<td><img src="{new_url}" onmouseover="this.src='{ref_url}';" onmouseout="this.src='{new_url}';" class="render"></td>
<td><img src="{ref_url}" onmouseover="this.src='{new_url}';" onmouseout="this.src='{ref_url}';" class="render"></td>
<td><img src="{diff_url}"></td>
</tr>""" . format(tr_style=tr_style,
name=name,
testname=testname,
status=status,
new_url=new_url,
ref_url=ref_url,
diff_url=diff_url)
<td><img src="{diff_color_url}"></td>
<td><img src="{diff_alpha_url}"></td>
</tr>"""
if error:
self.failed_tests += test_html
@ -368,7 +369,7 @@ class Report:
self.compare_tests += test_html
def _diff_output(self, filepath, tmp_filepath):
old_img, ref_img, new_img, diff_img = test_get_images(
old_img, ref_img, new_img, diff_color_img, diff_alpha_img = test_get_images(
self.output_dir, filepath, self.reference_dir, self.reference_override_dir)
# Create reference render directory.
@ -384,11 +385,12 @@ class Report:
if os.path.exists(ref_img):
# Diff images test with threshold.
command = (
self.idiff,
"-fail", str(self.fail_threshold),
"-failpercent", str(self.fail_percent),
self.oiiotool,
ref_img,
tmp_filepath,
"--fail", str(self.fail_threshold),
"--failpercent", str(self.fail_percent),
"--diff",
)
try:
subprocess.check_output(command)
@ -396,7 +398,7 @@ class Report:
except subprocess.CalledProcessError as e:
if self.verbose:
print_message(e.output.decode("utf-8", 'ignore'))
failed = e.returncode != 1
failed = e.returncode != 0
else:
if not self.update:
return False
@ -411,11 +413,15 @@ class Report:
# Generate diff image.
command = (
self.idiff,
"-o", diff_img,
"-abs", "-scale", "16",
self.oiiotool,
ref_img,
tmp_filepath
"--ch", "R,G,B",
tmp_filepath,
"--ch", "R,G,B",
"--sub",
"--abs",
"--mulc", "16",
"-o", diff_color_img,
)
try:

View File

@ -54,7 +54,7 @@ def create_argparse():
parser.add_argument("-blender", nargs="+")
parser.add_argument("-testdir", nargs=1)
parser.add_argument("-outdir", nargs=1)
parser.add_argument("-idiff", nargs=1)
parser.add_argument("-oiiotool", nargs=1)
return parser
@ -64,11 +64,11 @@ def main():
blender = args.blender[0]
test_dir = args.testdir[0]
idiff = args.idiff[0]
oiiotool = args.oiiotool[0]
output_dir = args.outdir[0]
from modules import render_report
report = render_report.Report("OpenGL Draw", output_dir, idiff)
report = render_report.Report("OpenGL Draw", output_dir, oiiotool)
ok = report.run(test_dir, blender, get_arguments)
sys.exit(not ok)

View File

@ -33,7 +33,7 @@ def create_argparse():
parser.add_argument("-blender", nargs="+")
parser.add_argument("-testdir", nargs=1)
parser.add_argument("-outdir", nargs=1)
parser.add_argument("-idiff", nargs=1)
parser.add_argument("-oiiotool", nargs=1)
parser.add_argument('--batch', default=False, action='store_true')
return parser
@ -44,11 +44,11 @@ def main():
blender = args.blender[0]
test_dir = args.testdir[0]
idiff = args.idiff[0]
oiiotool = args.oiiotool[0]
output_dir = args.outdir[0]
from modules import render_report
report = render_report.Report("Sequencer", output_dir, idiff)
report = render_report.Report("Sequencer", output_dir, oiiotool)
report.set_pixelated(True)
report.set_reference_dir("reference")

View File

@ -56,7 +56,7 @@ def create_argparse():
parser.add_argument("-blender", nargs="+")
parser.add_argument("-testdir", nargs=1)
parser.add_argument("-outdir", nargs=1)
parser.add_argument("-idiff", nargs=1)
parser.add_argument("-oiiotool", nargs=1)
parser.add_argument("-export_method", nargs=1)
parser.add_argument('--batch', default=False, action='store_true')
return parser
@ -68,18 +68,18 @@ def main():
blender = args.blender[0]
test_dir = args.testdir[0]
idiff = args.idiff[0]
oiiotool = args.oiiotool[0]
output_dir = args.outdir[0]
export_method = args.export_method[0]
from modules import render_report
if export_method == 'HYDRA':
report = render_report.Report("Storm Hydra", output_dir, idiff)
report = render_report.Report("Storm Hydra", output_dir, oiiotool)
report.set_reference_dir("storm_hydra_renders")
report.set_compare_engine('cycles', 'CPU')
else:
report = render_report.Report("Storm USD", output_dir, idiff)
report = render_report.Report("Storm USD", output_dir, oiiotool)
report.set_reference_dir("storm_usd_renders")
report.set_compare_engine('storm_hydra')

View File

@ -56,7 +56,7 @@ def create_argparse():
parser.add_argument("-blender", nargs="+")
parser.add_argument("-testdir", nargs=1)
parser.add_argument("-outdir", nargs=1)
parser.add_argument("-idiff", nargs=1)
parser.add_argument("-oiiotool", nargs=1)
parser.add_argument('--batch', default=False, action='store_true')
return parser
@ -67,11 +67,11 @@ def main():
blender = args.blender[0]
test_dir = args.testdir[0]
idiff = args.idiff[0]
oiiotool = args.oiiotool[0]
output_dir = args.outdir[0]
from modules import render_report
report = render_report.Report("Workbench", output_dir, idiff)
report = render_report.Report("Workbench", output_dir, oiiotool)
report.set_pixelated(True)
report.set_reference_dir("workbench_renders")
report.set_compare_engine('eevee')