Coverage for pyguymer3/image/save_array_as_PNG.py: 59%

22 statements  

« prev     ^ index     » next       coverage.py v7.10.3, created at 2025-08-16 08:31 +0000

1#!/usr/bin/env python3 

2 

3# Define function ... 

4def save_array_as_PNG( 

5 arrUint8, 

6 fname, 

7 /, 

8 *, 

9 calcAdaptive: bool = True, 

10 calcAverage: bool = True, 

11 calcNone: bool = True, 

12 calcPaeth: bool = True, 

13 calcSub: bool = True, 

14 calcUp: bool = True, 

15 debug: bool = __debug__, 

16 dpi: None | int = None, 

17 modTime = None, 

18 palUint8 = None, 

19): 

20 """Save an array as a PNG image. 

21 

22 Parameters 

23 ---------- 

24 arrUint8 : numpy.ndarray 

25 A "height * width * colour" unsigned 8-bit integer NumPy array. 

26 fname : str 

27 output file name 

28 calcAdaptive : bool, optional 

29 See :py:func:`pyguymer3.image.makePng` for the documentation. 

30 calcAverage : bool, optional 

31 See :py:func:`pyguymer3.image.makePng` for the documentation. 

32 calcNone : bool, optional 

33 See :py:func:`pyguymer3.image.makePng` for the documentation. 

34 calcPaeth : bool, optional 

35 See :py:func:`pyguymer3.image.makePng` for the documentation. 

36 calcSub : bool, optional 

37 See :py:func:`pyguymer3.image.makePng` for the documentation. 

38 calcUp : bool, optional 

39 See :py:func:`pyguymer3.image.makePng` for the documentation. 

40 debug : bool, optional 

41 Print debug messages. 

42 dpi : None or float or int, optional 

43 See :py:func:`pyguymer3.image.makePng` for the documentation. 

44 modTime : None or datetime.datetime, optional 

45 See :py:func:`pyguymer3.image.makePng` for the documentation. 

46 palUint8 : None or numpy.ndarray, optional 

47 See :py:func:`pyguymer3.image.makePng` for the documentation. 

48 

49 Notes 

50 ----- 

51 Copyright 2017 Thomas Guymer [1]_ 

52 

53 References 

54 ---------- 

55 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3 

56 """ 

57 

58 # Import standard modules ... 

59 import sys 

60 

61 # Import sub-functions ... 

62 from .makePng import makePng 

63 

64 # ************************************************************************** 

65 

66 # Check system ... 

67 assert sys.byteorder == "little", "the system is not little-endian" 

68 

69 # Check input ... 

70 assert arrUint8.dtype == "uint8", f"the NumPy array is not 8-bit (\"{arrUint8.dtype}\")" 

71 assert arrUint8.ndim == 3, f"the NumPy array is not 3D (\"{arrUint8.ndim:d}\")" 

72 match arrUint8.shape[2]: 

73 case 1: 

74 if palUint8 is None: 

75 pass 

76 else: 

77 assert palUint8.dtype == "uint8", f"the NumPy palette is not 8-bit (\"{palUint8.dtype}\")" 

78 assert palUint8.ndim == 2, f"the NumPy palette is not 2D (\"{palUint8.ndim:d}\")" 

79 assert palUint8.shape[0] <= 256, f"the NumPy palette has more than 256 colours (\"{palUint8.shape[0]:,d}\")" 

80 assert palUint8.shape[1] == 3, "the NumPy palette does not have 3 colour channels" 

81 assert arrUint8.max() < palUint8.shape[0], f"the NumPy array references more colours than are in the NumPy palette (\"{arrUint8.max():d}\" -vs- \"{palUint8.shape[0]:d}\")" 

82 case 3: 

83 pass 

84 case _: 

85 raise ValueError(f"the NumPy array does not have either 1 or 3 colour channels (\"{arrUint8.shape[2]:d}\")") from None 

86 

87 # ************************************************************************** 

88 

89 # Make PNG source ... 

90 src = makePng( 

91 arrUint8, 

92 calcAdaptive = calcAdaptive, 

93 calcAverage = calcAverage, 

94 calcNone = calcNone, 

95 calcPaeth = calcPaeth, 

96 calcSub = calcSub, 

97 calcUp = calcUp, 

98 choices = "all", 

99 debug = debug, 

100 dpi = dpi, 

101 levels = [9,], 

102 memLevels = [9,], 

103 modTime = modTime, 

104 palUint8 = palUint8, 

105 strategies = None, 

106 wbitss = [15,], 

107 ) 

108 

109 # Write PNG ... 

110 with open(fname, "wb") as fObj: 

111 fObj.write(src)