Enhance image editing tests and functionality
- Added parameterized tests for image edit replacement to ensure alpha mode preservation. - Refactored existing tests to utilize new image editing methods and improve clarity. - Introduced new tests for image target functionality, ensuring proper handling of shared textures and context. - Updated various tests to validate alpha mode handling across different scenarios. - Improved undo/redo functionality in image operators to maintain state consistency. - Added support for texture node actions, enhancing integration with Blender's node system. - Ensured that image properties are preserved during operations and that invalid contexts are handled gracefully.
This commit is contained in:
@@ -8,6 +8,14 @@ from pathlib import Path
|
||||
|
||||
import bpy
|
||||
|
||||
VIEW_TRANSFORM_COLOR_SPACES = (
|
||||
("ACES 1.3", "ACES 1.3 sRGB"),
|
||||
("ACES 2.0", "ACES 2.0 sRGB"),
|
||||
("AgX", "AgX Base sRGB"),
|
||||
("Filmic", "Filmic sRGB"),
|
||||
("Khronos PBR Neutral", "Khronos PBR Neutral sRGB"),
|
||||
)
|
||||
|
||||
IMAGE_NAME_SUFFIXES = (
|
||||
".jpeg",
|
||||
".jpg",
|
||||
@@ -296,7 +304,7 @@ def video_total_frames(image):
|
||||
|
||||
|
||||
def image_user_settings(source_object):
|
||||
"""Return the Empty's image user settings as a four-item tuple."""
|
||||
"""Return an image owner's playback settings as a four-item tuple."""
|
||||
image_user = getattr(source_object, "image_user", None)
|
||||
if image_user is None:
|
||||
return 1, 0, 0, False
|
||||
@@ -308,14 +316,13 @@ def image_user_settings(source_object):
|
||||
)
|
||||
|
||||
|
||||
def extract_frame_range(source_object):
|
||||
def extract_frame_range(image, image_user):
|
||||
"""Return the clamped (start_frame, frame_count) range extracted from the source."""
|
||||
total_frames = video_total_frames(getattr(source_object, "data", None))
|
||||
total_frames = video_total_frames(image)
|
||||
if total_frames <= 1:
|
||||
return 1, total_frames
|
||||
_frame_start, frame_offset, image_frames, _use_cyclic = (
|
||||
image_user_settings(source_object)
|
||||
)
|
||||
frame_offset = int(getattr(image_user, "frame_offset", 0) or 0)
|
||||
image_frames = int(getattr(image_user, "frame_duration", 0) or 0)
|
||||
frame_count = (
|
||||
min(image_frames, total_frames)
|
||||
if image_frames >= 1
|
||||
@@ -326,14 +333,9 @@ def extract_frame_range(source_object):
|
||||
return start_frame, frame_count
|
||||
|
||||
|
||||
def default_extract_frames(source_object):
|
||||
"""Return the Empty's Image Frames value, or the full frame count when unset."""
|
||||
return extract_frame_range(source_object)[1]
|
||||
|
||||
|
||||
def source_start_frame(source_object_name):
|
||||
source_object = bpy.data.objects.get(source_object_name)
|
||||
return extract_frame_range(source_object)[0] if source_object else 1
|
||||
return extract_frame_range(source_object.data, source_object.image_user)[0] if source_object else 1
|
||||
|
||||
|
||||
def image_path(image):
|
||||
@@ -615,16 +617,22 @@ def load_normal_result_image(path, source_object):
|
||||
return image
|
||||
|
||||
|
||||
def color_alpha_mode(color_space):
|
||||
"""Pair inverse view color spaces with straight alpha."""
|
||||
return "STRAIGHT" if color_space in dict(VIEW_TRANSFORM_COLOR_SPACES).values() else "PREMUL"
|
||||
|
||||
|
||||
def configure_color_alpha(image):
|
||||
"""Apply the presentation mode to an owned Color image."""
|
||||
if image.alpha_mode != "PREMUL":
|
||||
alpha_mode = color_alpha_mode(image.colorspace_settings.name)
|
||||
if image.alpha_mode != alpha_mode:
|
||||
pixels = (
|
||||
image_pixels(image)
|
||||
if getattr(image, "source", None) == "GENERATED"
|
||||
or getattr(image, "is_dirty", False)
|
||||
else None
|
||||
)
|
||||
image.alpha_mode = "PREMUL"
|
||||
image.alpha_mode = alpha_mode
|
||||
if pixels is not None:
|
||||
image.pixels.foreach_set(pixels)
|
||||
image.update()
|
||||
@@ -645,7 +653,7 @@ def create_image_edit_result(source_image, pixels, output_size):
|
||||
)
|
||||
try:
|
||||
image.colorspace_settings.name = source_image.colorspace_settings.name
|
||||
configure_color_alpha(image)
|
||||
image.alpha_mode = source_image.alpha_mode
|
||||
image.pixels.foreach_set(pixels)
|
||||
image.pack()
|
||||
image.update()
|
||||
@@ -801,11 +809,12 @@ def replace_empty_image(source_object, result_image, *, placement_bounds=None,
|
||||
|
||||
|
||||
def _load_packed_result_image(
|
||||
source_object,
|
||||
source_image,
|
||||
output_directory,
|
||||
*,
|
||||
frame_prefix,
|
||||
result_name,
|
||||
alpha_mode,
|
||||
):
|
||||
output_directory = Path(output_directory)
|
||||
color_paths = sorted_frame_paths(output_directory, frame_prefix)
|
||||
@@ -813,7 +822,6 @@ def _load_packed_result_image(
|
||||
raise RuntimeError(
|
||||
f"Color result has no images: {output_directory}"
|
||||
)
|
||||
source_image = source_object.data
|
||||
source_color_space = source_image.colorspace_settings.name
|
||||
animated = is_animated_image(source_image)
|
||||
try:
|
||||
@@ -822,7 +830,7 @@ def _load_packed_result_image(
|
||||
check_existing=False,
|
||||
)
|
||||
result_image.colorspace_settings.name = source_color_space
|
||||
configure_color_alpha(result_image)
|
||||
result_image.alpha_mode = alpha_mode
|
||||
if animated:
|
||||
force_sequence_source(result_image)
|
||||
except (OSError, RuntimeError, TypeError, ValueError) as error:
|
||||
@@ -843,17 +851,18 @@ def _load_packed_result_image(
|
||||
|
||||
|
||||
def load_image_edit_result(
|
||||
source_object,
|
||||
source_image,
|
||||
output_directory,
|
||||
*,
|
||||
frame_prefix="image.",
|
||||
):
|
||||
"""Load one packed Job result that directly edits the source Image."""
|
||||
return _load_packed_result_image(
|
||||
source_object,
|
||||
source_image,
|
||||
output_directory,
|
||||
frame_prefix=frame_prefix,
|
||||
result_name=source_object.data.name,
|
||||
result_name=source_image.name,
|
||||
alpha_mode=source_image.alpha_mode,
|
||||
)
|
||||
|
||||
|
||||
@@ -865,10 +874,11 @@ def load_color_result_image(
|
||||
):
|
||||
"""Load one packed Color texture result for a generated material."""
|
||||
return _load_packed_result_image(
|
||||
source_object,
|
||||
source_object.data,
|
||||
output_directory,
|
||||
frame_prefix=frame_prefix,
|
||||
result_name=color_data_name(source_object),
|
||||
alpha_mode=color_alpha_mode(source_object.data.colorspace_settings.name),
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user