Tests: Add tests for image format saving and loading #104442
@ -933,6 +933,49 @@ if(WITH_CODEC_FFMPEG)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT OPENIMAGEIO_IDIFF)
|
||||
message(STATUS "Disabling ImBuf image format tests because OIIO idiff does not exist")
|
||||
else()
|
||||
SET(OPTIONAL_FORMATS "")
|
||||
if(WITH_IMAGE_CINEON)
|
||||
set(OPTIONAL_FORMATS "${OPTIONAL_FORMATS} CINEON")
|
||||
endif()
|
||||
if(WITH_IMAGE_HDR)
|
||||
set(OPTIONAL_FORMATS "${OPTIONAL_FORMATS} HDR")
|
||||
endif()
|
||||
if(WITH_IMAGE_OPENEXR)
|
||||
set(OPTIONAL_FORMATS "${OPTIONAL_FORMATS} OPENEXR")
|
||||
endif()
|
||||
if(WITH_IMAGE_OPENJPEG)
|
||||
set(OPTIONAL_FORMATS "${OPTIONAL_FORMATS} OPENJPEG")
|
||||
endif()
|
||||
if(WITH_IMAGE_TIFF)
|
||||
set(OPTIONAL_FORMATS "${OPTIONAL_FORMATS} TIFF")
|
||||
endif()
|
||||
if(WITH_IMAGE_WEBP)
|
||||
set(OPTIONAL_FORMATS "${OPTIONAL_FORMATS} WEBP")
|
||||
endif()
|
||||
|
||||
add_blender_test(
|
||||
bf_imbuf_save
|
||||
--python ${CMAKE_CURRENT_LIST_DIR}/bl_imbuf_save.py
|
||||
--
|
||||
-test_dir "${TEST_SRC_DIR}/imbuf_io"
|
||||
-output_dir "${TEST_OUT_DIR}/imbuf_io/save"
|
||||
-idiff "${OPENIMAGEIO_IDIFF}"
|
||||
-optional_formats "${OPTIONAL_FORMATS}"
|
||||
)
|
||||
|
||||
add_blender_test(
|
||||
bf_imbuf_load
|
||||
--python ${CMAKE_CURRENT_LIST_DIR}/bl_imbuf_load.py
|
||||
--
|
||||
-test_dir "${TEST_SRC_DIR}/imbuf_io"
|
||||
-output_dir "${TEST_OUT_DIR}/imbuf_io/load"
|
||||
-idiff "${OPENIMAGEIO_IDIFF}"
|
||||
-optional_formats "${OPTIONAL_FORMATS}"
|
||||
)
|
||||
endif()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# SEQUENCER RENDER TESTS
|
||||
|
179
tests/python/bl_imbuf_load.py
Normal file
179
tests/python/bl_imbuf_load.py
Normal file
@ -0,0 +1,179 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import bpy
|
||||
|
||||
sys.path.append(str(pathlib.Path(__file__).parent.absolute()))
|
||||
deadpin marked this conversation as resolved
|
||||
from modules.colored_print import print_message
|
||||
from modules.imbuf_test import AbstractImBufTest
|
||||
|
||||
|
||||
args = None
|
||||
|
||||
|
||||
class ImBufTest(AbstractImBufTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
AbstractImBufTest.init(args)
|
||||
|
||||
if cls.update:
|
||||
os.makedirs(cls.reference_load_dir, exist_ok=True)
|
||||
|
||||
def _get_image_files(self, file_pattern):
|
||||
return [f for f in pathlib.Path(self.reference_dir).glob(file_pattern)]
|
||||
|
||||
def _validate_metadata(self, img, ref_metadata_path, out_metadata_path):
|
||||
channels = img.channels
|
||||
is_float = img.is_float
|
||||
colorspace = img.colorspace_settings.name
|
||||
alpha_mode = img.alpha_mode
|
||||
actual_metadata = f"{channels=} {is_float=} {colorspace=} {alpha_mode=}"
|
||||
|
||||
# Save actual metadata
|
||||
out_metadata_path.write_text(actual_metadata, encoding="utf-8")
|
||||
deadpin marked this conversation as resolved
Brecht Van Lommel
commented
Can just be Or better Can just be `"w"`?
Or better `out_metadata_path.write_text(out_metadata_path)` when using `pathlib`.
|
||||
|
||||
if ref_metadata_path.exists():
|
||||
# Compare with expected
|
||||
try:
|
||||
expected_metadata = ref_metadata_path.read_text(encoding="utf-8")
|
||||
|
||||
failed = not (actual_metadata == expected_metadata)
|
||||
except BaseException as e:
|
||||
if self.verbose:
|
||||
print_message(e.output.decode("utf-8", 'ignore'))
|
||||
failed = True
|
||||
else:
|
||||
if not self.update:
|
||||
return False
|
||||
|
||||
failed = True
|
||||
|
||||
if failed and self.update:
|
||||
# Update reference if requested.
|
||||
ref_metadata_path.write_text(actual_metadata, encoding="utf-8")
|
||||
failed = False
|
||||
|
||||
return not failed
|
||||
deadpin marked this conversation as resolved
Brecht Van Lommel
commented
Same comment. Same comment.
|
||||
|
||||
def _save_exr(self, img, out_exr_path):
|
||||
scene = bpy.data.scenes[0]
|
||||
image_settings = scene.render.image_settings
|
||||
image_settings.file_format = "OPEN_EXR"
|
||||
image_settings.color_mode = "RGBA"
|
||||
image_settings.color_depth = "32"
|
||||
image_settings.exr_codec = "ZIP"
|
||||
|
||||
img.save_render(str(out_exr_path), scene=scene)
|
||||
|
||||
def _validate_pixels(self, img, ref_exr_path, out_exr_path):
|
||||
self._save_exr(img, out_exr_path)
|
||||
|
||||
return self.call_idiff(ref_exr_path, out_exr_path)
|
||||
|
||||
def check(self, file_pattern):
|
||||
image_files = self._get_image_files(file_pattern)
|
||||
if len(image_files) == 0:
|
||||
self.fail(f"No images found for pattern {file_pattern}")
|
||||
|
||||
for image_path in image_files:
|
||||
print_message(image_path.name, 'SUCCESS', 'RUN')
|
||||
|
||||
# Load the image under test
|
||||
bpy.ops.image.open(filepath=str(image_path))
|
||||
img = bpy.data.images[image_path.name]
|
||||
|
||||
# Compare the image with our exr/metadata references
|
||||
exr_filename = image_path.with_suffix(".exr").name
|
||||
metadata_filename = image_path.with_suffix(".txt").name
|
||||
|
||||
ref_exr_path = self.reference_load_dir.joinpath(exr_filename)
|
||||
ref_metadata_path = self.reference_load_dir.joinpath(metadata_filename)
|
||||
out_exr_path = self.output_dir.joinpath(exr_filename)
|
||||
out_metadata_path = self.output_dir.joinpath(metadata_filename)
|
||||
|
||||
res1 = self._validate_metadata(img, ref_metadata_path, out_metadata_path)
|
||||
res2 = self._validate_pixels(img, ref_exr_path, out_exr_path)
|
||||
|
||||
if not res1 or not res2:
|
||||
self.errors += 1
|
||||
print_message("Results are different from reference data")
|
||||
print_message(image_path.name, 'FAILURE', 'FAILED')
|
||||
else:
|
||||
print_message(image_path.name, 'SUCCESS', 'OK')
|
||||
|
||||
|
||||
class ImBufLoadTest(ImBufTest):
|
||||
def test_load_bmp(self):
|
||||
self.check("*.bmp")
|
||||
|
||||
def test_load_png(self):
|
||||
self.check("*.png")
|
||||
|
||||
def test_load_exr(self):
|
||||
self.skip_if_format_missing("OPENEXR")
|
||||
|
||||
self.check("*.exr")
|
||||
|
||||
def test_load_hdr(self):
|
||||
self.skip_if_format_missing("HDR")
|
||||
|
||||
self.check("*.hdr")
|
||||
|
||||
def test_load_targa(self):
|
||||
self.check("*.tga")
|
||||
|
||||
def test_load_tiff(self):
|
||||
self.skip_if_format_missing("TIFF")
|
||||
|
||||
self.check("*.tif")
|
||||
|
||||
def test_load_jpeg(self):
|
||||
self.check("*.jpg")
|
||||
|
||||
def test_load_jpeg2000(self):
|
||||
self.skip_if_format_missing("OPENJPEG")
|
||||
|
||||
self.check("*.jp2")
|
||||
self.check("*.j2c")
|
||||
|
||||
def test_load_dpx(self):
|
||||
self.skip_if_format_missing("CINEON")
|
||||
|
||||
self.check("*.dpx")
|
||||
|
||||
def test_load_cineon(self):
|
||||
self.skip_if_format_missing("CINEON")
|
||||
|
||||
self.check("*.cin")
|
||||
|
||||
def test_load_webp(self):
|
||||
self.skip_if_format_missing("WEBP")
|
||||
|
||||
self.check("*.webp")
|
||||
|
||||
|
||||
def main():
|
||||
global args
|
||||
import argparse
|
||||
|
||||
if '--' in sys.argv:
|
||||
argv = [sys.argv[0]] + sys.argv[sys.argv.index('--') + 1:]
|
||||
else:
|
||||
argv = sys.argv
|
||||
|
||||
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('-optional_formats', required=True)
|
||||
args, remaining = parser.parse_known_args(argv)
|
||||
|
||||
unittest.main(argv=remaining)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
272
tests/python/bl_imbuf_save.py
Normal file
272
tests/python/bl_imbuf_save.py
Normal file
@ -0,0 +1,272 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import bpy
|
||||
|
||||
sys.path.append(str(pathlib.Path(__file__).parent.absolute()))
|
||||
from modules.colored_print import print_message
|
||||
from modules.imbuf_test import AbstractImBufTest
|
||||
|
||||
|
||||
args = None
|
||||
|
||||
TEMPLATE_RGBA08 = "template-rgba08.png"
|
||||
TEMPLATE_RGBA32 = "template-rgba32.exr"
|
||||
|
||||
|
||||
class ImBufTest(AbstractImBufTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
AbstractImBufTest.init(args)
|
||||
|
||||
if cls.update:
|
||||
os.makedirs(cls.reference_dir, exist_ok=True)
|
||||
|
||||
def _load_template_image(self, name, template_name):
|
||||
image_path = str(self.test_dir.joinpath(template_name))
|
||||
bpy.ops.image.open(filepath=image_path)
|
||||
img = bpy.data.images[template_name]
|
||||
img.name = name
|
||||
return img
|
||||
|
||||
def _setup_image(self, src, ext, settings):
|
||||
scene = bpy.data.scenes[0]
|
||||
image_settings = scene.render.image_settings
|
||||
|
||||
# Make an appropriate filename which embeds all relevant settings and
|
||||
# set the file output parameters for the exact configuration we want
|
||||
name = ""
|
||||
for s in settings:
|
||||
if s == "color_depth":
|
||||
name += str(settings[s]).rjust(2, '0') + "-"
|
||||
else:
|
||||
name += str(settings[s]) + "-"
|
||||
|
||||
setattr(image_settings, s, settings[s])
|
||||
|
||||
image_name = name[:-1].lower() + "__from__" + src + "." + ext
|
||||
|
||||
return image_name
|
||||
|
||||
def _save_image(self, src, image_name):
|
||||
loaders = {
|
||||
"rgba08": lambda name: self._load_template_image(name, TEMPLATE_RGBA08),
|
||||
"rgba32": lambda name: self._load_template_image(name, TEMPLATE_RGBA32),
|
||||
}
|
||||
|
||||
# Load the template image and assign it the image name
|
||||
img = loaders[src](image_name)
|
||||
|
||||
# Save the image in the desired format with the desired settings
|
||||
scene = bpy.data.scenes[0]
|
||||
ref_image_path = self.reference_dir.joinpath(img.name)
|
||||
out_image_path = self.output_dir.joinpath(img.name)
|
||||
img.save_render(str(out_image_path), scene=scene)
|
||||
|
||||
# Completely remove image in case it was modified during save
|
||||
img.user_clear()
|
||||
bpy.data.images.remove(img)
|
||||
return ref_image_path, out_image_path
|
||||
|
||||
def _validate(self, ref_image_path, out_image_path):
|
||||
return self.call_idiff(ref_image_path, out_image_path)
|
||||
|
||||
def check(self, src, ext, settings):
|
||||
image_name = self._setup_image(src, ext, settings)
|
||||
print_message(image_name, 'SUCCESS', 'RUN')
|
||||
|
||||
ref_image_path, out_image_path = self._save_image(src, image_name)
|
||||
|
||||
if not self._validate(ref_image_path, out_image_path):
|
||||
self.errors += 1
|
||||
print_message("Save result is different from reference image")
|
||||
print_message(ref_image_path.name, 'FAILURE', 'FAILED')
|
||||
else:
|
||||
print_message(ref_image_path.name, 'SUCCESS', 'OK')
|
||||
|
||||
|
||||
# autopep8: off
|
||||
class ImBufSaveTest(ImBufTest):
|
||||
def test_save_bmp(self):
|
||||
self.check(src="rgba08", ext="bmp", settings={"file_format": "BMP", "color_mode": "BW"})
|
||||
self.check(src="rgba08", ext="bmp", settings={"file_format": "BMP", "color_mode": "RGB"})
|
||||
|
||||
self.check(src="rgba32", ext="bmp", settings={"file_format": "BMP", "color_mode": "BW"})
|
||||
self.check(src="rgba32", ext="bmp", settings={"file_format": "BMP", "color_mode": "RGB"})
|
||||
|
||||
def test_save_png(self):
|
||||
self.check(src="rgba08", ext="png", settings={"file_format": "PNG", "color_mode": "BW", "color_depth": "8", "compression": 15})
|
||||
self.check(src="rgba08", ext="png", settings={"file_format": "PNG", "color_mode": "RGB", "color_depth": "8", "compression": 15})
|
||||
self.check(src="rgba08", ext="png", settings={"file_format": "PNG", "color_mode": "RGBA", "color_depth": "8", "compression": 15})
|
||||
self.check(src="rgba08", ext="png", settings={"file_format": "PNG", "color_mode": "BW", "color_depth": "16", "compression": 25})
|
||||
self.check(src="rgba08", ext="png", settings={"file_format": "PNG", "color_mode": "RGB", "color_depth": "16", "compression": 25})
|
||||
self.check(src="rgba08", ext="png", settings={"file_format": "PNG", "color_mode": "RGBA", "color_depth": "16", "compression": 25})
|
||||
|
||||
self.check(src="rgba32", ext="png", settings={"file_format": "PNG", "color_mode": "BW", "color_depth": "8", "compression": 15})
|
||||
self.check(src="rgba32", ext="png", settings={"file_format": "PNG", "color_mode": "RGB", "color_depth": "8", "compression": 15})
|
||||
self.check(src="rgba32", ext="png", settings={"file_format": "PNG", "color_mode": "RGBA", "color_depth": "8", "compression": 15})
|
||||
self.check(src="rgba32", ext="png", settings={"file_format": "PNG", "color_mode": "BW", "color_depth": "16", "compression": 25})
|
||||
self.check(src="rgba32", ext="png", settings={"file_format": "PNG", "color_mode": "RGB", "color_depth": "16", "compression": 25})
|
||||
self.check(src="rgba32", ext="png", settings={"file_format": "PNG", "color_mode": "RGBA", "color_depth": "16", "compression": 25})
|
||||
|
||||
def test_save_exr(self):
|
||||
self.skip_if_format_missing("OPENEXR")
|
||||
|
||||
self.check(src="rgba08", ext="exr", settings={"file_format": "OPEN_EXR", "color_mode": "BW", "color_depth": "16", "exr_codec": "ZIP"})
|
||||
self.check(src="rgba08", ext="exr", settings={"file_format": "OPEN_EXR", "color_mode": "RGB", "color_depth": "16", "exr_codec": "DWAA"})
|
||||
self.check(src="rgba08", ext="exr", settings={"file_format": "OPEN_EXR", "color_mode": "RGBA", "color_depth": "16", "exr_codec": "DWAB"})
|
||||
self.check(src="rgba08", ext="exr", settings={"file_format": "OPEN_EXR", "color_mode": "BW", "color_depth": "32", "exr_codec": "DWAB"})
|
||||
self.check(src="rgba08", ext="exr", settings={"file_format": "OPEN_EXR", "color_mode": "RGB", "color_depth": "32", "exr_codec": "DWAA"})
|
||||
self.check(src="rgba08", ext="exr", settings={"file_format": "OPEN_EXR", "color_mode": "RGBA", "color_depth": "32", "exr_codec": "ZIP"})
|
||||
|
||||
self.check(src="rgba32", ext="exr", settings={"file_format": "OPEN_EXR", "color_mode": "BW", "color_depth": "16", "exr_codec": "ZIP"})
|
||||
self.check(src="rgba32", ext="exr", settings={"file_format": "OPEN_EXR", "color_mode": "RGB", "color_depth": "16", "exr_codec": "DWAA"})
|
||||
self.check(src="rgba32", ext="exr", settings={"file_format": "OPEN_EXR", "color_mode": "RGBA", "color_depth": "16", "exr_codec": "DWAB"})
|
||||
self.check(src="rgba32", ext="exr", settings={"file_format": "OPEN_EXR", "color_mode": "BW", "color_depth": "32", "exr_codec": "DWAB"})
|
||||
self.check(src="rgba32", ext="exr", settings={"file_format": "OPEN_EXR", "color_mode": "RGB", "color_depth": "32", "exr_codec": "DWAA"})
|
||||
self.check(src="rgba32", ext="exr", settings={"file_format": "OPEN_EXR", "color_mode": "RGBA", "color_depth": "32", "exr_codec": "ZIP"})
|
||||
|
||||
def test_save_hdr(self):
|
||||
self.skip_if_format_missing("HDR")
|
||||
|
||||
self.check(src="rgba08", ext="hdr", settings={"file_format": "HDR", "color_mode": "BW"})
|
||||
self.check(src="rgba08", ext="hdr", settings={"file_format": "HDR", "color_mode": "RGB"})
|
||||
|
||||
self.check(src="rgba32", ext="hdr", settings={"file_format": "HDR", "color_mode": "BW"})
|
||||
self.check(src="rgba32", ext="hdr", settings={"file_format": "HDR", "color_mode": "RGB"})
|
||||
|
||||
def test_save_targa(self):
|
||||
self.check(src="rgba08", ext="tga", settings={"file_format": "TARGA", "color_mode": "BW"})
|
||||
self.check(src="rgba08", ext="tga", settings={"file_format": "TARGA", "color_mode": "RGB"})
|
||||
self.check(src="rgba08", ext="tga", settings={"file_format": "TARGA", "color_mode": "RGBA"})
|
||||
|
||||
self.check(src="rgba32", ext="tga", settings={"file_format": "TARGA", "color_mode": "BW"})
|
||||
self.check(src="rgba32", ext="tga", settings={"file_format": "TARGA", "color_mode": "RGB"})
|
||||
self.check(src="rgba32", ext="tga", settings={"file_format": "TARGA", "color_mode": "RGBA"})
|
||||
|
||||
def test_save_targa_raw(self):
|
||||
self.check(src="rgba08", ext="tga", settings={"file_format": "TARGA_RAW", "color_mode": "BW"})
|
||||
self.check(src="rgba08", ext="tga", settings={"file_format": "TARGA_RAW", "color_mode": "RGB"})
|
||||
self.check(src="rgba08", ext="tga", settings={"file_format": "TARGA_RAW", "color_mode": "RGBA"})
|
||||
|
||||
self.check(src="rgba32", ext="tga", settings={"file_format": "TARGA_RAW", "color_mode": "BW"})
|
||||
self.check(src="rgba32", ext="tga", settings={"file_format": "TARGA_RAW", "color_mode": "RGB"})
|
||||
self.check(src="rgba32", ext="tga", settings={"file_format": "TARGA_RAW", "color_mode": "RGBA"})
|
||||
|
||||
def test_save_tiff(self):
|
||||
self.skip_if_format_missing("TIFF")
|
||||
|
||||
self.check(src="rgba08", ext="tif", settings={"file_format": "TIFF", "color_mode": "BW", "color_depth": "8", "tiff_codec": "DEFLATE"})
|
||||
self.check(src="rgba08", ext="tif", settings={"file_format": "TIFF", "color_mode": "RGB", "color_depth": "8", "tiff_codec": "LZW"})
|
||||
self.check(src="rgba08", ext="tif", settings={"file_format": "TIFF", "color_mode": "RGBA", "color_depth": "8", "tiff_codec": "PACKBITS"})
|
||||
self.check(src="rgba08", ext="tif", settings={"file_format": "TIFF", "color_mode": "BW", "color_depth": "16", "tiff_codec": "PACKBITS"})
|
||||
self.check(src="rgba08", ext="tif", settings={"file_format": "TIFF", "color_mode": "RGB", "color_depth": "16", "tiff_codec": "LZW"})
|
||||
self.check(src="rgba08", ext="tif", settings={"file_format": "TIFF", "color_mode": "RGBA", "color_depth": "16", "tiff_codec": "DEFLATE"})
|
||||
|
||||
self.check(src="rgba32", ext="tif", settings={"file_format": "TIFF", "color_mode": "BW", "color_depth": "8", "tiff_codec": "DEFLATE"})
|
||||
self.check(src="rgba32", ext="tif", settings={"file_format": "TIFF", "color_mode": "RGB", "color_depth": "8", "tiff_codec": "LZW"})
|
||||
self.check(src="rgba32", ext="tif", settings={"file_format": "TIFF", "color_mode": "RGBA", "color_depth": "8", "tiff_codec": "PACKBITS"})
|
||||
self.check(src="rgba32", ext="tif", settings={"file_format": "TIFF", "color_mode": "BW", "color_depth": "16", "tiff_codec": "PACKBITS"})
|
||||
self.check(src="rgba32", ext="tif", settings={"file_format": "TIFF", "color_mode": "RGB", "color_depth": "16", "tiff_codec": "LZW"})
|
||||
self.check(src="rgba32", ext="tif", settings={"file_format": "TIFF", "color_mode": "RGBA", "color_depth": "16", "tiff_codec": "DEFLATE"})
|
||||
|
||||
def test_save_jpeg(self):
|
||||
self.check(src="rgba08", ext="jpg", settings={"file_format": "JPEG", "color_mode": "BW", "quality": 90})
|
||||
self.check(src="rgba08", ext="jpg", settings={"file_format": "JPEG", "color_mode": "RGB", "quality": 90})
|
||||
|
||||
self.check(src="rgba32", ext="jpg", settings={"file_format": "JPEG", "color_mode": "BW", "quality": 70})
|
||||
self.check(src="rgba32", ext="jpg", settings={"file_format": "JPEG", "color_mode": "RGB", "quality": 70})
|
||||
|
||||
def test_save_jpeg2000(self):
|
||||
self.skip_if_format_missing("OPENJPEG")
|
||||
|
||||
# Is there a better combination of settings we can use so there's not so many?
|
||||
# Is this a good mix?
|
||||
self.check(src="rgba08", ext="jp2", settings={"file_format": "JPEG2000", "color_mode": "BW", "color_depth": "8", "jpeg2k_codec": "JP2", "quality": 90})
|
||||
self.check(src="rgba08", ext="jp2", settings={"file_format": "JPEG2000", "color_mode": "BW", "color_depth": "12", "jpeg2k_codec": "JP2", "quality": 90})
|
||||
self.check(src="rgba08", ext="j2c", settings={"file_format": "JPEG2000", "color_mode": "BW", "color_depth": "16", "jpeg2k_codec": "J2K", "quality": 90})
|
||||
self.check(src="rgba08", ext="jp2", settings={"file_format": "JPEG2000", "color_mode": "RGB", "color_depth": "8", "jpeg2k_codec": "JP2", "quality": 90})
|
||||
self.check(src="rgba08", ext="jp2", settings={"file_format": "JPEG2000", "color_mode": "RGB", "color_depth": "12", "jpeg2k_codec": "JP2", "quality": 90})
|
||||
self.check(src="rgba08", ext="j2c", settings={"file_format": "JPEG2000", "color_mode": "RGB", "color_depth": "16", "jpeg2k_codec": "J2K", "quality": 90})
|
||||
self.check(src="rgba08", ext="jp2", settings={"file_format": "JPEG2000", "color_mode": "RGBA", "color_depth": "8", "jpeg2k_codec": "JP2", "quality": 90})
|
||||
self.check(src="rgba08", ext="jp2", settings={"file_format": "JPEG2000", "color_mode": "RGBA", "color_depth": "12", "jpeg2k_codec": "JP2", "quality": 90})
|
||||
self.check(src="rgba08", ext="j2c", settings={"file_format": "JPEG2000", "color_mode": "RGBA", "color_depth": "16", "jpeg2k_codec": "J2K", "quality": 90})
|
||||
|
||||
self.check(src="rgba32", ext="jp2", settings={"file_format": "JPEG2000", "color_mode": "BW", "color_depth": "8", "jpeg2k_codec": "JP2", "quality": 70})
|
||||
self.check(src="rgba32", ext="jp2", settings={"file_format": "JPEG2000", "color_mode": "BW", "color_depth": "12", "jpeg2k_codec": "JP2", "quality": 70})
|
||||
self.check(src="rgba32", ext="j2c", settings={"file_format": "JPEG2000", "color_mode": "BW", "color_depth": "16", "jpeg2k_codec": "J2K", "quality": 70})
|
||||
self.check(src="rgba32", ext="jp2", settings={"file_format": "JPEG2000", "color_mode": "RGB", "color_depth": "8", "jpeg2k_codec": "JP2", "quality": 70})
|
||||
self.check(src="rgba32", ext="jp2", settings={"file_format": "JPEG2000", "color_mode": "RGB", "color_depth": "12", "jpeg2k_codec": "JP2", "quality": 70})
|
||||
self.check(src="rgba32", ext="j2c", settings={"file_format": "JPEG2000", "color_mode": "RGB", "color_depth": "16", "jpeg2k_codec": "J2K", "quality": 70})
|
||||
self.check(src="rgba32", ext="jp2", settings={"file_format": "JPEG2000", "color_mode": "RGBA", "color_depth": "8", "jpeg2k_codec": "JP2", "quality": 70})
|
||||
self.check(src="rgba32", ext="jp2", settings={"file_format": "JPEG2000", "color_mode": "RGBA", "color_depth": "12", "jpeg2k_codec": "JP2", "quality": 70})
|
||||
self.check(src="rgba32", ext="j2c", settings={"file_format": "JPEG2000", "color_mode": "RGBA", "color_depth": "16", "jpeg2k_codec": "J2K", "quality": 70})
|
||||
|
||||
# Note: The 'use_jpeg2k_cinema_preset' option mandates very large images
|
||||
# self.check(src="rgba08", ext="jpg", settings={"file_format":"JPEG2000", "color_mode":"RGBA", "color_depth":"8", "jpeg2k_codec":"JP2", "use_jpeg2k_cinema_preset":True, "use_jpeg2k_cinema_48":False, "use_jpeg2k_ycc":False, "quality":70})
|
||||
# self.check(src="rgba32", ext="jpg", settings={"file_format":"JPEG2000", "color_mode":"RGBA", "color_depth":"8", "jpeg2k_codec":"JP2", "use_jpeg2k_cinema_preset":True, "use_jpeg2k_cinema_48":False, "use_jpeg2k_ycc":False, "quality":70})
|
||||
|
||||
self.check(src="rgba08", ext="jp2", settings={"file_format": "JPEG2000", "color_mode": "RGBA", "color_depth": "12", "jpeg2k_codec": "JP2", "use_jpeg2k_cinema_preset": False, "use_jpeg2k_cinema_48": True, "use_jpeg2k_ycc": False, "quality": 70})
|
||||
self.check(src="rgba32", ext="jp2", settings={"file_format": "JPEG2000", "color_mode": "RGBA", "color_depth": "12", "jpeg2k_codec": "JP2", "use_jpeg2k_cinema_preset": False, "use_jpeg2k_cinema_48": True, "use_jpeg2k_ycc": False, "quality": 70})
|
||||
|
||||
self.check(src="rgba08", ext="jp2", settings={"file_format": "JPEG2000", "color_mode": "RGBA", "color_depth": "16", "jpeg2k_codec": "JP2", "use_jpeg2k_cinema_preset": False, "use_jpeg2k_cinema_48": False, "use_jpeg2k_ycc": True, "quality": 70})
|
||||
self.check(src="rgba32", ext="jp2", settings={"file_format": "JPEG2000", "color_mode": "RGBA", "color_depth": "16", "jpeg2k_codec": "JP2", "use_jpeg2k_cinema_preset": False, "use_jpeg2k_cinema_48": False, "use_jpeg2k_ycc": True, "quality": 70})
|
||||
|
||||
def test_save_dpx(self):
|
||||
self.skip_if_format_missing("CINEON")
|
||||
|
||||
self.check(src="rgba08", ext="dpx", settings={"file_format": "DPX", "color_mode": "RGB", "color_depth": "8", "use_cineon_log": False})
|
||||
self.check(src="rgba08", ext="dpx", settings={"file_format": "DPX", "color_mode": "RGB", "color_depth": "12", "use_cineon_log": False})
|
||||
self.check(src="rgba08", ext="dpx", settings={"file_format": "DPX", "color_mode": "RGB", "color_depth": "16", "use_cineon_log": False})
|
||||
self.check(src="rgba08", ext="dpx", settings={"file_format": "DPX", "color_mode": "RGBA", "color_depth": "10", "use_cineon_log": True})
|
||||
self.check(src="rgba08", ext="dpx", settings={"file_format": "DPX", "color_mode": "RGBA", "color_depth": "12", "use_cineon_log": True})
|
||||
self.check(src="rgba08", ext="dpx", settings={"file_format": "DPX", "color_mode": "RGBA", "color_depth": "16", "use_cineon_log": True})
|
||||
|
||||
self.check(src="rgba32", ext="dpx", settings={"file_format": "DPX", "color_mode": "RGB", "color_depth": "8", "use_cineon_log": False})
|
||||
self.check(src="rgba32", ext="dpx", settings={"file_format": "DPX", "color_mode": "RGB", "color_depth": "12", "use_cineon_log": False})
|
||||
self.check(src="rgba32", ext="dpx", settings={"file_format": "DPX", "color_mode": "RGB", "color_depth": "16", "use_cineon_log": False})
|
||||
self.check(src="rgba32", ext="dpx", settings={"file_format": "DPX", "color_mode": "RGBA", "color_depth": "10", "use_cineon_log": True})
|
||||
self.check(src="rgba32", ext="dpx", settings={"file_format": "DPX", "color_mode": "RGBA", "color_depth": "12", "use_cineon_log": True})
|
||||
self.check(src="rgba32", ext="dpx", settings={"file_format": "DPX", "color_mode": "RGBA", "color_depth": "16", "use_cineon_log": True})
|
||||
|
||||
def test_save_cineon(self):
|
||||
self.skip_if_format_missing("CINEON")
|
||||
|
||||
self.check(src="rgba08", ext="cin", settings={"file_format": "CINEON", "color_mode": "RGB"})
|
||||
self.check(src="rgba32", ext="cin", settings={"file_format": "CINEON", "color_mode": "RGB"})
|
||||
|
||||
def test_save_webp(self):
|
||||
self.skip_if_format_missing("WEBP")
|
||||
|
||||
self.check(src="rgba08", ext="webp", settings={"file_format": "WEBP", "color_mode": "RGB", "quality": 90})
|
||||
self.check(src="rgba08", ext="webp", settings={"file_format": "WEBP", "color_mode": "RGBA", "quality": 90})
|
||||
|
||||
self.check(src="rgba32", ext="webp", settings={"file_format": "WEBP", "color_mode": "RGB", "quality": 70})
|
||||
self.check(src="rgba32", ext="webp", settings={"file_format": "WEBP", "color_mode": "RGBA", "quality": 70})
|
||||
# autopep8: on
|
||||
|
||||
|
||||
def main():
|
||||
global args
|
||||
import argparse
|
||||
|
||||
if '--' in sys.argv:
|
||||
argv = [sys.argv[0]] + sys.argv[sys.argv.index('--') + 1:]
|
||||
else:
|
||||
argv = sys.argv
|
||||
|
||||
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('-optional_formats', required=True)
|
||||
args, remaining = parser.parse_known_args(argv)
|
||||
|
||||
unittest.main(argv=remaining)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
46
tests/python/modules/colored_print.py
Normal file
46
tests/python/modules/colored_print.py
Normal file
@ -0,0 +1,46 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
class COLORS_ANSI:
|
||||
RED = '\033[00;31m'
|
||||
GREEN = '\033[00;32m'
|
||||
ENDC = '\033[0m'
|
||||
|
||||
|
||||
class COLORS_NONE:
|
||||
RED = ''
|
||||
GREEN = ''
|
||||
ENDC = ''
|
||||
|
||||
|
||||
COLORS = COLORS_NONE
|
||||
|
||||
|
||||
def use_message_colors():
|
||||
global COLORS, COLORS_ANSI
|
||||
COLORS = COLORS_ANSI
|
||||
|
||||
|
||||
def print_message(message, type=None, status=''):
|
||||
if type == 'SUCCESS':
|
||||
print(COLORS.GREEN, end="")
|
||||
elif type == 'FAILURE':
|
||||
print(COLORS.RED, end="")
|
||||
status_text = ...
|
||||
if status == 'RUN':
|
||||
status_text = " RUN "
|
||||
elif status == 'OK':
|
||||
status_text = " OK "
|
||||
elif status == 'PASSED':
|
||||
status_text = " PASSED "
|
||||
elif status == 'FAILED':
|
||||
status_text = " FAILED "
|
||||
else:
|
||||
status_text = status
|
||||
if status_text:
|
||||
print("[{}]" . format(status_text), end="")
|
||||
print(COLORS.ENDC, end="")
|
||||
print(" {}" . format(message))
|
||||
sys.stdout.flush()
|
92
tests/python/modules/imbuf_test.py
Normal file
92
tests/python/modules/imbuf_test.py
Normal file
@ -0,0 +1,92 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
import shutil
|
||||
import subprocess
|
||||
import unittest
|
||||
|
||||
from .colored_print import (print_message, use_message_colors)
|
||||
|
||||
|
||||
class AbstractImBufTest(unittest.TestCase):
|
||||
deadpin marked this conversation as resolved
Brecht Van Lommel
commented
Can we deduplicate this colored printing code with other test modules? Can we deduplicate this colored printing code with other test modules?
|
||||
@classmethod
|
||||
def init(cls, args):
|
||||
cls.test_dir = pathlib.Path(args.test_dir)
|
||||
cls.reference_dir = pathlib.Path(args.test_dir).joinpath("reference")
|
||||
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.optional_formats = args.optional_formats
|
||||
|
||||
os.makedirs(cls.diff_dir, exist_ok=True)
|
||||
|
||||
cls.errors = 0
|
||||
cls.fail_threshold = 0.001
|
||||
cls.fail_percent = 1
|
||||
cls.verbose = os.environ.get("BLENDER_VERBOSE") is not None
|
||||
cls.update = os.getenv('BLENDER_TEST_UPDATE') is not None
|
||||
if os.environ.get("BLENDER_TEST_COLOR") is not None:
|
||||
use_message_colors()
|
||||
|
||||
def setUp(self):
|
||||
self.errors = 0
|
||||
print_message("")
|
||||
|
||||
def tearDown(self):
|
||||
if self.errors > 0:
|
||||
self.fail("{} errors encountered" . format(self.errors))
|
||||
|
||||
def skip_if_format_missing(self, format):
|
||||
if self.optional_formats.find(format) < 0:
|
||||
self.skipTest("format not available")
|
||||
|
||||
def call_idiff(self, ref_path, out_path):
|
||||
ref_filepath = str(ref_path)
|
||||
out_filepath = str(out_path)
|
||||
out_name = out_path.name
|
||||
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),
|
||||
ref_filepath,
|
||||
out_filepath,
|
||||
)
|
||||
try:
|
||||
subprocess.check_output(command)
|
||||
failed = False
|
||||
except subprocess.CalledProcessError as e:
|
||||
if self.verbose:
|
||||
print_message(e.output.decode("utf-8", 'ignore'))
|
||||
failed = e.returncode != 1
|
||||
else:
|
||||
if not self.update:
|
||||
return False
|
||||
|
||||
failed = True
|
||||
|
||||
if failed and self.update:
|
||||
# Update reference image if requested.
|
||||
shutil.copy(out_filepath, ref_filepath)
|
||||
failed = False
|
||||
|
||||
# Generate diff image.
|
||||
diff_img = str(self.diff_dir.joinpath(out_name + ".diff.png"))
|
||||
command = (
|
||||
str(self.idiff),
|
||||
"-o", diff_img,
|
||||
"-abs", "-scale", "16",
|
||||
ref_filepath,
|
||||
out_filepath
|
||||
)
|
||||
|
||||
try:
|
||||
subprocess.check_output(command)
|
||||
except subprocess.CalledProcessError as e:
|
||||
if self.verbose:
|
||||
print_message(e.output.decode("utf-8", 'ignore'))
|
||||
|
||||
return not failed
|
@ -14,44 +14,7 @@ import sys
|
||||
import time
|
||||
|
||||
from . import global_report
|
||||
|
||||
|
||||
class COLORS_ANSI:
|
||||
RED = '\033[00;31m'
|
||||
GREEN = '\033[00;32m'
|
||||
ENDC = '\033[0m'
|
||||
|
||||
|
||||
class COLORS_DUMMY:
|
||||
RED = ''
|
||||
GREEN = ''
|
||||
ENDC = ''
|
||||
|
||||
|
||||
COLORS = COLORS_DUMMY
|
||||
|
||||
|
||||
def print_message(message, type=None, status=''):
|
||||
if type == 'SUCCESS':
|
||||
print(COLORS.GREEN, end="")
|
||||
elif type == 'FAILURE':
|
||||
print(COLORS.RED, end="")
|
||||
status_text = ...
|
||||
if status == 'RUN':
|
||||
status_text = " RUN "
|
||||
elif status == 'OK':
|
||||
status_text = " OK "
|
||||
elif status == 'PASSED':
|
||||
status_text = " PASSED "
|
||||
elif status == 'FAILED':
|
||||
status_text = " FAILED "
|
||||
else:
|
||||
status_text = status
|
||||
if status_text:
|
||||
print("[{}]" . format(status_text), end="")
|
||||
print(COLORS.ENDC, end="")
|
||||
print(" {}" . format(message))
|
||||
sys.stdout.flush()
|
||||
from .colored_print import (print_message, use_message_colors)
|
||||
|
||||
|
||||
def blend_list(dirpath, device, blacklist):
|
||||
@ -151,8 +114,7 @@ class Report:
|
||||
self.update = os.getenv('BLENDER_TEST_UPDATE') is not None
|
||||
|
||||
if os.environ.get("BLENDER_TEST_COLOR") is not None:
|
||||
global COLORS, COLORS_ANSI
|
||||
COLORS = COLORS_ANSI
|
||||
use_message_colors()
|
||||
|
||||
self.failed_tests = ""
|
||||
self.passed_tests = ""
|
||||
|
Loading…
Reference in New Issue
Block a user
We're trying to move away from os.path towards pathlib. I think removing the few usages in the new code in this patch is relatively straightforward.