Coverage for paintmaskanimator/shadow_export.py: 100%

38 statements  

« prev     ^ index     » next       coverage.py v7.17.0, created at 2026-11-02 04:50 +0000

1"""使用色フォルダーを使った影素材の書き出し(Issue #21)。 

2 

3影色を使用色フォルダーにまとめておけば、撮影へ渡す素材を自動で作れる。 

41枚のセルから3種類を取り出す。 

5 

6* ノーマル単色塗り … 絵のある画素をすべて1色で塗ったもの(通常のベタ) 

7* 影単色 … フォルダーの色の画素だけを1色で塗ったもの 

8* 影のマスク … フォルダーの色を白、それ以外を黒にした不透明な画像 

9 

10Qt には依存しない素の numpy 配列として扱う。 

11""" 

12import numpy as np 

13 

14#: 書き出す素材の種類(フォルダー名にも使う)。 

15NORMAL = "normal" 

16SHADOW = "shadow" 

17SHADOW_MASK = "shadow_mask" 

18KINDS = (NORMAL, SHADOW, SHADOW_MASK) 

19 

20#: 既定の塗り色。撮影で扱いやすい原色にしておく。 

21DEFAULT_NORMAL_COLOR = (255, 255, 255) 

22DEFAULT_SHADOW_COLOR = (0, 0, 255) 

23 

24 

25def shadow_mask_of(rgba, shadow_rgbs): 

26 """フォルダーの色が置かれている画素を真にしたマスク。""" 

27 rgba = np.asarray(rgba, dtype=np.uint8) 

28 mask = np.zeros(rgba.shape[:2], dtype=bool) 

29 opaque = rgba[:, :, 3] > 0 

30 for rgb in shadow_rgbs or (): 

31 target = np.asarray( 

32 [int(channel) for channel in rgb[:3]], dtype=np.uint8 

33 ) 

34 mask |= opaque & np.all(rgba[:, :, :3] == target, axis=2) 

35 return mask 

36 

37 

38def flat_normal(rgba, color=DEFAULT_NORMAL_COLOR): 

39 """絵のある画素をすべて ``color`` で塗った、透明背景の画像。""" 

40 rgba = np.asarray(rgba, dtype=np.uint8) 

41 result = np.zeros_like(rgba) 

42 opaque = rgba[:, :, 3] > 0 

43 result[:, :, :3][opaque] = np.asarray(color[:3], dtype=np.uint8) 

44 result[:, :, 3][opaque] = 255 

45 return result 

46 

47 

48def flat_shadow(rgba, shadow_rgbs, color=DEFAULT_SHADOW_COLOR): 

49 """フォルダーの色の画素だけを ``color`` で塗った、透明背景の画像。""" 

50 rgba = np.asarray(rgba, dtype=np.uint8) 

51 result = np.zeros_like(rgba) 

52 mask = shadow_mask_of(rgba, shadow_rgbs) 

53 result[:, :, :3][mask] = np.asarray(color[:3], dtype=np.uint8) 

54 result[:, :, 3][mask] = 255 

55 return result 

56 

57 

58def shadow_matte(rgba, shadow_rgbs): 

59 """影を白、それ以外を黒にした不透明な画像(マスク)。""" 

60 rgba = np.asarray(rgba, dtype=np.uint8) 

61 mask = shadow_mask_of(rgba, shadow_rgbs) 

62 result = np.zeros_like(rgba) 

63 result[:, :, 3] = 255 

64 result[:, :, :3][mask] = 255 

65 return result 

66 

67 

68def materials(rgba, shadow_rgbs, *, normal_color=DEFAULT_NORMAL_COLOR, 

69 shadow_color=DEFAULT_SHADOW_COLOR): 

70 """3種類をまとめて作る。``{種類: RGBA 配列}``。""" 

71 return { 

72 NORMAL: flat_normal(rgba, normal_color), 

73 SHADOW: flat_shadow(rgba, shadow_rgbs, shadow_color), 

74 SHADOW_MASK: shadow_matte(rgba, shadow_rgbs), 

75 }