From 0edb5dc2b121b4955655fe6a5178243b1408649f Mon Sep 17 00:00:00 2001 From: Jennifer Taylor Date: Sat, 22 May 2021 01:31:42 +0000 Subject: [PATCH] Rework additive color a bit for type clarity and add warnings where we don't support it. --- bemani/format/afp/blend.py | 16 ++++++++-------- bemani/format/afp/blendalt.pyi | 2 +- bemani/format/afp/blendalt.pyx | 12 +++--------- bemani/format/afp/blendaltimpl.cxx | 14 +++++++------- bemani/format/afp/render.py | 27 ++++++++++++++++++++++++--- 5 files changed, 43 insertions(+), 28 deletions(-) diff --git a/bemani/format/afp/blend.py b/bemani/format/afp/blend.py index 46e6384..b226acf 100644 --- a/bemani/format/afp/blend.py +++ b/bemani/format/afp/blend.py @@ -1,7 +1,7 @@ import multiprocessing import signal from PIL import Image # type: ignore -from typing import Any, List, Sequence, Tuple +from typing import Any, List, Sequence from .types.generic import Color, Matrix, Point @@ -111,7 +111,7 @@ except ImportError: def affine_composite( img: Image.Image, - add_color: Tuple[int, int, int, int], + add_color: Color, mult_color: Color, transform: Matrix, blendfunc: int, @@ -257,7 +257,7 @@ except ImportError: texwidth: int, texheight: int, inverse: Matrix, - add_color: Tuple[int, int, int, int], + add_color: Color, mult_color: Color, blendfunc: int, imgbytes: bytes, @@ -293,7 +293,7 @@ except ImportError: results.put((imgy, linebytes)) def blend_point( - add_color: Tuple[int, int, int, int], + add_color: Color, mult_color: Color, # This should be a sequence of exactly 4 values, either bytes or a tuple. src_color: Sequence[int], @@ -303,10 +303,10 @@ except ImportError: ) -> Sequence[int]: # Calculate multiplicative and additive colors against the source. src_color = ( - clamp((src_color[0] * mult_color.r) + add_color[0]), - clamp((src_color[1] * mult_color.g) + add_color[1]), - clamp((src_color[2] * mult_color.b) + add_color[2]), - clamp((src_color[3] * mult_color.a) + add_color[3]), + clamp((src_color[0] * mult_color.r) + (255 * add_color.r)), + clamp((src_color[1] * mult_color.g) + (255 * add_color.g)), + clamp((src_color[2] * mult_color.b) + (255 * add_color.b)), + clamp((src_color[3] * mult_color.a) + (255 * add_color.a)), ) if blendfunc == 3: diff --git a/bemani/format/afp/blendalt.pyi b/bemani/format/afp/blendalt.pyi index 3d2b2f7..c552ac4 100644 --- a/bemani/format/afp/blendalt.pyi +++ b/bemani/format/afp/blendalt.pyi @@ -5,7 +5,7 @@ from .types.generic import Color, Matrix, Point def affine_composite( img: Image.Image, - add_color: Tuple[int, int, int, int], + add_color: Color, mult_color: Color, transform: Matrix, blendfunc: int, diff --git a/bemani/format/afp/blendalt.pyx b/bemani/format/afp/blendalt.pyx index 5fd6867..29e1ccf 100644 --- a/bemani/format/afp/blendalt.pyx +++ b/bemani/format/afp/blendalt.pyx @@ -4,12 +4,6 @@ from typing import Tuple from .types.generic import Color, Matrix, Point -cdef extern struct intcolor_t: - unsigned char r; - unsigned char g; - unsigned char b; - unsigned char a; - cdef extern struct floatcolor_t: float r; float g; @@ -36,7 +30,7 @@ cdef extern int affine_composite_fast( unsigned int maxx, unsigned int miny, unsigned int maxy, - intcolor_t add_color, + floatcolor_t add_color, floatcolor_t mult_color, matrix_t inverse, int blendfunc, @@ -48,7 +42,7 @@ cdef extern int affine_composite_fast( def affine_composite( img: Image.Image, - add_color: Tuple[int, int, int, int], + add_color: Color, mult_color: Color, transform: Matrix, blendfunc: int, @@ -96,7 +90,7 @@ def affine_composite( texbytes = texture.tobytes('raw', 'RGBA') # Convert classes to C structs. - cdef intcolor_t c_addcolor = intcolor_t(r=add_color[0], g=add_color[1], b=add_color[2], a=add_color[3]) + cdef floatcolor_t c_addcolor = floatcolor_t(r=add_color.r, g=add_color.g, b=add_color.b, a=add_color.a) cdef floatcolor_t c_multcolor = floatcolor_t(r=mult_color.r, g=mult_color.g, b=mult_color.b, a=mult_color.a) cdef matrix_t c_inverse = matrix_t(a=inverse.a, b=inverse.b, c=inverse.c, d=inverse.d, tx=inverse.tx, ty=inverse.ty) cdef unsigned int threads = 1 if single_threaded else multiprocessing.cpu_count() diff --git a/bemani/format/afp/blendaltimpl.cxx b/bemani/format/afp/blendaltimpl.cxx index 9b764ad..784a9e7 100644 --- a/bemani/format/afp/blendaltimpl.cxx +++ b/bemani/format/afp/blendaltimpl.cxx @@ -60,7 +60,7 @@ extern "C" unsigned int texwidth; unsigned int texheight; matrix_t inverse; - intcolor_t add_color; + floatcolor_t add_color; floatcolor_t mult_color; int blendfunc; pthread_t *thread; @@ -167,7 +167,7 @@ extern "C" } intcolor_t blend_point( - intcolor_t add_color, + floatcolor_t add_color, floatcolor_t mult_color, intcolor_t src_color, intcolor_t dest_color, @@ -175,10 +175,10 @@ extern "C" ) { // Calculate multiplicative and additive colors against the source. src_color = (intcolor_t){ - clamp((src_color.r * mult_color.r) + add_color.r), - clamp((src_color.g * mult_color.g) + add_color.g), - clamp((src_color.b * mult_color.b) + add_color.b), - clamp((src_color.a * mult_color.a) + add_color.a), + clamp((src_color.r * mult_color.r) + (255 * add_color.r)), + clamp((src_color.g * mult_color.g) + (255 * add_color.g)), + clamp((src_color.b * mult_color.b) + (255 * add_color.b)), + clamp((src_color.a * mult_color.a) + (255 * add_color.a)), }; if (blendfunc == 3) { @@ -242,7 +242,7 @@ extern "C" unsigned int maxx, unsigned int miny, unsigned int maxy, - intcolor_t add_color, + floatcolor_t add_color, floatcolor_t mult_color, matrix_t inverse, int blendfunc, diff --git a/bemani/format/afp/render.py b/bemani/format/afp/render.py index a58cd1c..0b38a40 100644 --- a/bemani/format/afp/render.py +++ b/bemani/format/afp/render.py @@ -460,6 +460,24 @@ class AFPRenderer(VerboseOutput): else: new_only_depths = None + # We don't support mixing colors on sub-objects yet. + add_color = renderable.add_color or Color(0.0, 0.0, 0.0, 0.0) + mult_color = renderable.mult_color or Color(1.0, 1.0, 1.0, 1.0) + if not ( + add_color.r == 0.0 and + add_color.g == 0.0 and + add_color.b == 0.0 and + add_color.a == 0.0 + ): + print(f"WARNING: Unhandled sprite additive color {add_color}!") + if not ( + mult_color.r == 1.0 and + mult_color.g == 1.0 and + mult_color.b == 1.0 and + mult_color.a == 1.0 + ): + print(f"WARNING: Unhandled sprite multiplicative color {mult_color}!") + # This is a sprite placement reference. Make sure that we render lower depths # first, but preserved placed order as well. depths = set(obj.depth for obj in renderable.placed_objects) @@ -477,7 +495,7 @@ class AFPRenderer(VerboseOutput): shape = renderable.source # Calculate add color if it is present. - add_color = (renderable.add_color or Color(0.0, 0.0, 0.0, 0.0)).as_tuple() + add_color = renderable.add_color or Color(0.0, 0.0, 0.0, 0.0) mult_color = renderable.mult_color or Color(1.0, 1.0, 1.0, 1.0) blend = renderable.blend or 0 @@ -519,14 +537,17 @@ class AFPRenderer(VerboseOutput): if texture is not None: # See if we can cheat and use the faster blitting method. if ( - add_color == (0, 0, 0, 0) and + add_color.r == 0.0 and + add_color.g == 0.0 and + add_color.b == 0.0 and + add_color.a == 0.0 and mult_color.r == 1.0 and mult_color.g == 1.0 and mult_color.b == 1.0 and mult_color.a == 1.0 and + transform.a == 1.0 and transform.b == 0.0 and transform.c == 0.0 and - transform.a == 1.0 and transform.d == 1.0 and (blend == 0 or blend == 2) ):