mergechannels 0.1.2__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mergechannels might be problematic. Click here for more details.

Files changed (175) hide show
  1. {mergechannels-0.1.2 → mergechannels-0.2.0}/Cargo.lock +8 -1
  2. {mergechannels-0.1.2 → mergechannels-0.2.0}/Cargo.toml +2 -1
  3. {mergechannels-0.1.2 → mergechannels-0.2.0}/PKG-INFO +52 -22
  4. {mergechannels-0.1.2 → mergechannels-0.2.0}/README.md +48 -21
  5. {mergechannels-0.1.2 → mergechannels-0.2.0}/pyproject.toml +7 -0
  6. {mergechannels-0.1.2 → mergechannels-0.2.0}/pytests/test_colorize.py +50 -10
  7. {mergechannels-0.1.2 → mergechannels-0.2.0}/python/mergechannels/__init__.py +5 -5
  8. mergechannels-0.2.0/python/mergechannels/__init__.pyi +30 -0
  9. {mergechannels-0.1.2 → mergechannels-0.2.0}/python/mergechannels/_internal.py +25 -7
  10. {mergechannels-0.1.2 → mergechannels-0.2.0}/src/blend.rs +43 -8
  11. mergechannels-0.2.0/src/colorize.rs +397 -0
  12. mergechannels-0.2.0/src/interface.rs +239 -0
  13. mergechannels-0.2.0/src/lib.rs +15 -0
  14. {mergechannels-0.1.2 → mergechannels-0.2.0}/uv.lock +217 -2
  15. mergechannels-0.1.2/python/mergechannels/__init__.pyi +0 -27
  16. mergechannels-0.1.2/src/colorize.rs +0 -64
  17. mergechannels-0.1.2/src/interface.rs +0 -36
  18. mergechannels-0.1.2/src/lib.rs +0 -15
  19. {mergechannels-0.1.2 → mergechannels-0.2.0}/.gitattributes +0 -0
  20. {mergechannels-0.1.2 → mergechannels-0.2.0}/.github/workflows/CI.yml +0 -0
  21. {mergechannels-0.1.2 → mergechannels-0.2.0}/.gitignore +0 -0
  22. {mergechannels-0.1.2 → mergechannels-0.2.0}/.pre-commit-config.yaml +0 -0
  23. {mergechannels-0.1.2 → mergechannels-0.2.0}/LICENSE +0 -0
  24. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/16_colors.lut +0 -0
  25. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/5_ramps.lut +0 -0
  26. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/6_shades.lut +0 -0
  27. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/Cyan Hot.lut +0 -0
  28. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/Green Fire Blue.lut +0 -0
  29. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/HiLo.lut +0 -0
  30. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/ICA.lut +0 -0
  31. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/ICA2.lut +0 -0
  32. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/ICA3.lut +0 -0
  33. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/Magenta Hot.lut +0 -0
  34. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/Orange Hot.lut +0 -0
  35. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/Rainbow RGB.lut +0 -0
  36. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/Red Hot.lut +0 -0
  37. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/Thermal.lut +0 -0
  38. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/Yellow Hot.lut +0 -0
  39. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/blue_orange_icb.lut +0 -0
  40. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/brgbcmyw.lut +0 -0
  41. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/cool.lut +0 -0
  42. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/edges.lut +0 -0
  43. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/gem.lut +0 -0
  44. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/glasbey.lut +0 -0
  45. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/glasbey_inverted.lut +0 -0
  46. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/glasbey_on_dark.lut +0 -0
  47. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/glow.lut +0 -0
  48. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/mpl-inferno.lut +0 -0
  49. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/mpl-magma.lut +0 -0
  50. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/mpl-plasma.lut +0 -0
  51. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/mpl-viridis.lut +0 -0
  52. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/phase.lut +0 -0
  53. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/physics.lut +0 -0
  54. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/royal.lut +0 -0
  55. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/sepia.lut +0 -0
  56. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/smart.lut +0 -0
  57. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/thal.lut +0 -0
  58. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/thallium.lut +0 -0
  59. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/builtin_luts/unionjack.lut +0 -0
  60. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/3color-BMR.lut +0 -0
  61. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/3color-CGY.lut +0 -0
  62. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/3color-RMB.lut +0 -0
  63. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/3color-YGC.lut +0 -0
  64. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/BOP blue.lut +0 -0
  65. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/BOP orange.lut +0 -0
  66. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/BOP purple.lut +0 -0
  67. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/I Blue.lut +0 -0
  68. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/I Bordeaux.lut +0 -0
  69. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/I Cyan.lut +0 -0
  70. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/I Forest.lut +0 -0
  71. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/I Green.lut +0 -0
  72. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/I Magenta.lut +0 -0
  73. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/I Purple.lut +0 -0
  74. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/I Red.lut +0 -0
  75. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/I Yellow.lut +0 -0
  76. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/NOTICE +0 -0
  77. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/OPF fresh.lut +0 -0
  78. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/OPF orange.lut +0 -0
  79. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/OPF purple.lut +0 -0
  80. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/christ_luts/Turbo.lut +0 -0
  81. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/16_colors.txt +0 -0
  82. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/3-3-2 RGB.txt +0 -0
  83. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/3color-BMR.txt +0 -0
  84. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/3color-CGY.txt +0 -0
  85. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/3color-RMB.txt +0 -0
  86. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/3color-YGC.txt +0 -0
  87. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/5_ramps.txt +0 -0
  88. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/6_shades.txt +0 -0
  89. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/BOP blue.txt +0 -0
  90. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/BOP orange.txt +0 -0
  91. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/BOP purple.txt +0 -0
  92. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Blue.txt +0 -0
  93. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Cyan Hot.txt +0 -0
  94. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Cyan.txt +0 -0
  95. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Fire.txt +0 -0
  96. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Grays.txt +0 -0
  97. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Green Fire Blue.txt +0 -0
  98. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Green.txt +0 -0
  99. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/HiLo.txt +0 -0
  100. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/I Blue.txt +0 -0
  101. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/I Bordeaux.txt +0 -0
  102. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/I Cyan.txt +0 -0
  103. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/I Forest.txt +0 -0
  104. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/I Green.txt +0 -0
  105. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/I Magenta.txt +0 -0
  106. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/I Purple.txt +0 -0
  107. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/I Red.txt +0 -0
  108. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/I Yellow.txt +0 -0
  109. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/ICA.txt +0 -0
  110. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/ICA2.txt +0 -0
  111. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/ICA3.txt +0 -0
  112. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Ice.txt +0 -0
  113. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Magenta Hot.txt +0 -0
  114. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Magenta.txt +0 -0
  115. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/OIMB1.txt +0 -0
  116. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/OIMB2.txt +0 -0
  117. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/OIMB3.txt +0 -0
  118. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/OPF fresh.txt +0 -0
  119. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/OPF orange.txt +0 -0
  120. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/OPF purple.txt +0 -0
  121. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Orange Hot.txt +0 -0
  122. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Rainbow RGB.txt +0 -0
  123. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Red Hot.txt +0 -0
  124. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Red%Green.txt +0 -0
  125. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Red.txt +0 -0
  126. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Spectrum.txt +0 -0
  127. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Thermal.txt +0 -0
  128. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Turbo.txt +0 -0
  129. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Yellow Hot.txt +0 -0
  130. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/Yellow.txt +0 -0
  131. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/betterBlue.txt +0 -0
  132. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/betterCyan.txt +0 -0
  133. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/betterGreen.txt +0 -0
  134. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/betterOrange.txt +0 -0
  135. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/betterRed.txt +0 -0
  136. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/betterYellow.txt +0 -0
  137. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/blue_orange_icb.txt +0 -0
  138. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/brgbcmyw.txt +0 -0
  139. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/cool.txt +0 -0
  140. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/edges.txt +0 -0
  141. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/gem.txt +0 -0
  142. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/glasbey.txt +0 -0
  143. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/glasbey_inverted.txt +0 -0
  144. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/glasbey_on_dark.txt +0 -0
  145. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/glow.txt +0 -0
  146. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/mpl-inferno.txt +0 -0
  147. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/mpl-magma.txt +0 -0
  148. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/mpl-plasma.txt +0 -0
  149. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/mpl-viridis.txt +0 -0
  150. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/phase.txt +0 -0
  151. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/physics.txt +0 -0
  152. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/royal.txt +0 -0
  153. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/sepia.txt +0 -0
  154. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/smart.txt +0 -0
  155. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/thal.txt +0 -0
  156. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/thallium.txt +0 -0
  157. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/converted/unionjack.txt +0 -0
  158. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/zac_luts/OIMB1.lut +0 -0
  159. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/zac_luts/OIMB2.lut +0 -0
  160. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/zac_luts/OIMB3.lut +0 -0
  161. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/zac_luts/betterBlue.lut +0 -0
  162. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/zac_luts/betterCyan.lut +0 -0
  163. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/zac_luts/betterGreen.lut +0 -0
  164. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/zac_luts/betterOrange.lut +0 -0
  165. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/zac_luts/betterRed.lut +0 -0
  166. {mergechannels-0.1.2 → mergechannels-0.2.0}/assets/zac_luts/betterYellow.lut +0 -0
  167. {mergechannels-0.1.2 → mergechannels-0.2.0}/python/mergechannels/_blending.py +0 -0
  168. {mergechannels-0.1.2 → mergechannels-0.2.0}/python/mergechannels/_luts.py +0 -0
  169. {mergechannels-0.1.2 → mergechannels-0.2.0}/python/mergechannels/py.typed +0 -0
  170. {mergechannels-0.1.2 → mergechannels-0.2.0}/ruff.toml +0 -0
  171. {mergechannels-0.1.2 → mergechannels-0.2.0}/scripts/convert_luts_to_txt.ijm +0 -0
  172. {mergechannels-0.1.2 → mergechannels-0.2.0}/scripts/populate_luts.py +0 -0
  173. {mergechannels-0.1.2 → mergechannels-0.2.0}/src/cmaps.rs +0 -0
  174. {mergechannels-0.1.2 → mergechannels-0.2.0}/src/normalize.rs +0 -0
  175. {mergechannels-0.1.2 → mergechannels-0.2.0}/tox.ini +0 -0
@@ -59,12 +59,13 @@ dependencies = [
59
59
 
60
60
  [[package]]
61
61
  name = "mergechannels"
62
- version = "0.1.2"
62
+ version = "0.2.0"
63
63
  dependencies = [
64
64
  "lazy_static",
65
65
  "ndarray",
66
66
  "numpy",
67
67
  "pyo3",
68
+ "smallvec",
68
69
  ]
69
70
 
70
71
  [[package]]
@@ -239,6 +240,12 @@ version = "2.1.1"
239
240
  source = "registry+https://github.com/rust-lang/crates.io-index"
240
241
  checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
241
242
 
243
+ [[package]]
244
+ name = "smallvec"
245
+ version = "1.15.0"
246
+ source = "registry+https://github.com/rust-lang/crates.io-index"
247
+ checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
248
+
242
249
  [[package]]
243
250
  name = "syn"
244
251
  version = "2.0.98"
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "mergechannels"
3
- version = "0.1.2"
3
+ version = "0.2.0"
4
4
  edition = "2021"
5
5
 
6
6
  # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -13,3 +13,4 @@ lazy_static = "1.5.0"
13
13
  ndarray = "0.16.1"
14
14
  numpy = "0.24.0"
15
15
  pyo3 = "0.24.1"
16
+ smallvec = "1.15.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mergechannels
3
- Version: 0.1.2
3
+ Version: 0.2.0
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -12,7 +12,10 @@ Classifier: Programming Language :: Python :: 3.11
12
12
  Classifier: Programming Language :: Python :: 3.12
13
13
  Classifier: Programming Language :: Python :: 3.13
14
14
  Requires-Dist: numpy>1.25.0
15
+ Provides-Extra: nvim
15
16
  License-File: LICENSE
17
+ Summary: Apply and merge colormaps
18
+ Author-email: Zac Swider <zac.swider@gmail.com>
16
19
  License: MIT
17
20
  Requires-Python: >=3.9, <=3.13
18
21
  Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
@@ -60,8 +63,7 @@ plt.show()
60
63
  print(colorized.shape, colorized.dtype)
61
64
  >> (512, 512, 3) uint8
62
65
  ```
63
- ![colorize a single image](https://raw.githubusercontent.com/zacswider/README_Images/main/camera_red-green.png
64
- )
66
+ ![colorize a single image](https://raw.githubusercontent.com/zacswider/README_Images/main/camera_red-green.png)
65
67
 
66
68
 
67
69
  ### apply a different colormap to each channel
@@ -71,38 +73,66 @@ import matplotlib.pyplot as plt
71
73
  import mergechannels as mc
72
74
 
73
75
  cells, nuclei = data.cells3d().max(axis=0)
74
- cells = to_uint8(cells) # normalize your own arrays, mergechannels doesn't currently handle this
75
- nuclei = to_uint8(nuclei) # normalize your own arrays, mergechannels doesn't currently handle this
76
+ assert cells.dtype == 'uint16' and nuclei.dtype == 'uint16'
77
+ fig, axes = plt.subplots(1, 2, figsize=(3, 6), dpi=300)
78
+ for ax in axes.ravel(): ax.axis('off')
79
+ (a, b) = axes.ravel()
80
+ a.imshow(mc.merge([cells, nuclei],['Orange Hot', 'Cyan Hot']))
81
+ b.imshow(mc.merge([cells, nuclei],['I Blue', 'I Forest'], blending='min'))
82
+ fig.tight_layout()
83
+ plt.show()
84
+ ```
85
+ ![max and min multicolor blending](https://raw.githubusercontent.com/zacswider/README_Images/main/overlay_normal_and_inverted.png)
76
86
 
77
- fig, axes = plt.subplots(2, 2, figsize=(6, 6), dpi=150)
87
+ ### apply a colormap to a whole stack
88
+ ```python
89
+ from skimage import data
90
+ from matplotlib import pyplot as plt
91
+ import mergechannels as mc
92
+
93
+ volume = data.cells3d()
94
+ cells = volume[:, 0]
95
+ nuclei = volume[:, 1]
96
+ merged = mc.merge([cells, nuclei],['Orange Hot', 'Cyan Hot'])
97
+ plt.imshow(merged[24]); plt.show()
98
+ ```
99
+ ![colorize a whole stack of images](https://raw.githubusercontent.com/zacswider/README_Images/main/merged_stacks.png)
100
+
101
+ ### adjust the saturation limits when applying colormaps
102
+ ``` python
103
+ from skimage import data
104
+ import matplotlib.pyplot as plt
105
+ import mergechannels as mc
106
+
107
+ cells, nuclei = data.cells3d().max(axis=0)
108
+ channels = [cells, nuclei]
109
+ colormaps = ['I Blue', 'I Forest']
110
+ fig, axes = plt.subplots(1, 2, figsize=(3, 6), dpi=300)
78
111
  for ax in axes.ravel(): ax.axis('off')
79
- (a, b, c, d) = axes.ravel()
80
- a.imshow(cells, cmap='gray')
81
- b.imshow(nuclei, cmap='gray')
82
- c.imshow(
83
- mc.merge(
84
- [cells, nuclei],
85
- ['Orange Hot', 'Cyan Hot'], # maximum blending is the default
86
- ),
87
- )
88
- d.imshow(
112
+ (a, b) = axes.ravel()
113
+ a.imshow(mc.merge(channels, colormaps, blending='min'))
114
+ b.imshow(
89
115
  mc.merge(
90
- [cells, nuclei],
91
- ['I Blue', 'I Forest'],
92
- blending='min', # use minimum blending with inverted colormaps
116
+ channels,
117
+ colormaps,
118
+ blending='min',
119
+ saturation_limits=(
120
+ 0.01, # bottom 1% of pixels set to black point
121
+ 0.97, # top 3% of pixels set to white point
122
+ ),
93
123
  ),
94
124
  )
95
125
  fig.tight_layout()
96
126
  plt.show()
97
127
  ```
98
- ![max and min multicolor blending](https://raw.githubusercontent.com/zacswider/README_Images/main/cells_multicolor.png)
128
+ ![adjust saturation limits](https://raw.githubusercontent.com/zacswider/README_Images/main/adjust_sat_lims.png)
99
129
 
100
130
 
101
131
  ## Roadmap
102
- mergechannels is currently incredibly simple. It can apply one or more colormaps to one or more 2D 8-bit images and that's it.
132
+ mergechannels is currently incredibly simple. It can apply one or more colormaps to one or more 2D and 3D 8-bit or 16-bit images and that's it.
103
133
  - Add support for any numerical dtype
104
- - Add support for 3D images
105
134
  - Add option to return any colormap as a matplotlib colormap
135
+ - Add option to pass external colormaps to mergechannels
106
136
  - Add support for directly passing matplotlib colormaps instead of colormap names
107
137
  - Parallelize colormap application on large images (if it's helpful)
108
138
  - Add option to overlay binary or instance masks onto colorized images
@@ -41,8 +41,7 @@ plt.show()
41
41
  print(colorized.shape, colorized.dtype)
42
42
  >> (512, 512, 3) uint8
43
43
  ```
44
- ![colorize a single image](https://raw.githubusercontent.com/zacswider/README_Images/main/camera_red-green.png
45
- )
44
+ ![colorize a single image](https://raw.githubusercontent.com/zacswider/README_Images/main/camera_red-green.png)
46
45
 
47
46
 
48
47
  ### apply a different colormap to each channel
@@ -52,38 +51,66 @@ import matplotlib.pyplot as plt
52
51
  import mergechannels as mc
53
52
 
54
53
  cells, nuclei = data.cells3d().max(axis=0)
55
- cells = to_uint8(cells) # normalize your own arrays, mergechannels doesn't currently handle this
56
- nuclei = to_uint8(nuclei) # normalize your own arrays, mergechannels doesn't currently handle this
54
+ assert cells.dtype == 'uint16' and nuclei.dtype == 'uint16'
55
+ fig, axes = plt.subplots(1, 2, figsize=(3, 6), dpi=300)
56
+ for ax in axes.ravel(): ax.axis('off')
57
+ (a, b) = axes.ravel()
58
+ a.imshow(mc.merge([cells, nuclei],['Orange Hot', 'Cyan Hot']))
59
+ b.imshow(mc.merge([cells, nuclei],['I Blue', 'I Forest'], blending='min'))
60
+ fig.tight_layout()
61
+ plt.show()
62
+ ```
63
+ ![max and min multicolor blending](https://raw.githubusercontent.com/zacswider/README_Images/main/overlay_normal_and_inverted.png)
57
64
 
58
- fig, axes = plt.subplots(2, 2, figsize=(6, 6), dpi=150)
65
+ ### apply a colormap to a whole stack
66
+ ```python
67
+ from skimage import data
68
+ from matplotlib import pyplot as plt
69
+ import mergechannels as mc
70
+
71
+ volume = data.cells3d()
72
+ cells = volume[:, 0]
73
+ nuclei = volume[:, 1]
74
+ merged = mc.merge([cells, nuclei],['Orange Hot', 'Cyan Hot'])
75
+ plt.imshow(merged[24]); plt.show()
76
+ ```
77
+ ![colorize a whole stack of images](https://raw.githubusercontent.com/zacswider/README_Images/main/merged_stacks.png)
78
+
79
+ ### adjust the saturation limits when applying colormaps
80
+ ``` python
81
+ from skimage import data
82
+ import matplotlib.pyplot as plt
83
+ import mergechannels as mc
84
+
85
+ cells, nuclei = data.cells3d().max(axis=0)
86
+ channels = [cells, nuclei]
87
+ colormaps = ['I Blue', 'I Forest']
88
+ fig, axes = plt.subplots(1, 2, figsize=(3, 6), dpi=300)
59
89
  for ax in axes.ravel(): ax.axis('off')
60
- (a, b, c, d) = axes.ravel()
61
- a.imshow(cells, cmap='gray')
62
- b.imshow(nuclei, cmap='gray')
63
- c.imshow(
64
- mc.merge(
65
- [cells, nuclei],
66
- ['Orange Hot', 'Cyan Hot'], # maximum blending is the default
67
- ),
68
- )
69
- d.imshow(
90
+ (a, b) = axes.ravel()
91
+ a.imshow(mc.merge(channels, colormaps, blending='min'))
92
+ b.imshow(
70
93
  mc.merge(
71
- [cells, nuclei],
72
- ['I Blue', 'I Forest'],
73
- blending='min', # use minimum blending with inverted colormaps
94
+ channels,
95
+ colormaps,
96
+ blending='min',
97
+ saturation_limits=(
98
+ 0.01, # bottom 1% of pixels set to black point
99
+ 0.97, # top 3% of pixels set to white point
100
+ ),
74
101
  ),
75
102
  )
76
103
  fig.tight_layout()
77
104
  plt.show()
78
105
  ```
79
- ![max and min multicolor blending](https://raw.githubusercontent.com/zacswider/README_Images/main/cells_multicolor.png)
106
+ ![adjust saturation limits](https://raw.githubusercontent.com/zacswider/README_Images/main/adjust_sat_lims.png)
80
107
 
81
108
 
82
109
  ## Roadmap
83
- mergechannels is currently incredibly simple. It can apply one or more colormaps to one or more 2D 8-bit images and that's it.
110
+ mergechannels is currently incredibly simple. It can apply one or more colormaps to one or more 2D and 3D 8-bit or 16-bit images and that's it.
84
111
  - Add support for any numerical dtype
85
- - Add support for 3D images
86
112
  - Add option to return any colormap as a matplotlib colormap
113
+ - Add option to pass external colormaps to mergechannels
87
114
  - Add support for directly passing matplotlib colormaps instead of colormap names
88
115
  - Parallelize colormap application on large images (if it's helpful)
89
116
  - Add option to overlay binary or instance masks onto colorized images
@@ -4,6 +4,9 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "mergechannels"
7
+ description = "Apply and merge colormaps"
8
+ readme = "README.md"
9
+ authors = [{ name = "Zac Swider", email = "zac.swider@gmail.com" }]
7
10
  license = { text = "MIT" }
8
11
  requires-python = ">=3.9, <=3.13"
9
12
  classifiers = [
@@ -20,6 +23,9 @@ classifiers = [
20
23
  ]
21
24
  dynamic = ["version"]
22
25
  dependencies = ["numpy>1.25.0"]
26
+
27
+ [project.optional-dependencies]
28
+ nvim = []
23
29
  [tool.maturin]
24
30
  features = ["pyo3/extension-module"]
25
31
  python-source = "python"
@@ -28,6 +34,7 @@ python-source = "python"
28
34
  dev = [
29
35
  "matplotlib>=3.7.5",
30
36
  "pre-commit>=3.5.0",
37
+ "pynvim>=0.5.2",
31
38
  "pytest-benchmark>=4.0.0",
32
39
  "pytest>=8.3.5",
33
40
  ]
@@ -7,7 +7,7 @@ def test_apply_color_map():
7
7
  Test that the color map is applied correctly
8
8
  '''
9
9
  x = np.ones((1, 1), dtype=np.uint8)
10
- rgb = mc.apply_color_map(x, 'betterBlue')
10
+ rgb = mc.dispatch_single_channel(x, 'betterBlue', (0, 255))
11
11
  assert rgb.shape == (1,1,3)
12
12
  assert rgb.dtype == np.uint8
13
13
  assert np.allclose(
@@ -17,7 +17,7 @@ def test_apply_color_map():
17
17
  )
18
18
  )
19
19
  x = np.ones((1, 1), dtype=np.uint8) * 255
20
- rgb = mc.apply_color_map(x, 'betterBlue')
20
+ rgb = mc.dispatch_single_channel(x, 'betterBlue', (0, 255))
21
21
  assert np.allclose(
22
22
  rgb,
23
23
  np.array(
@@ -31,7 +31,12 @@ def test_apply_colors_and_merge_low_sum():
31
31
  '''
32
32
  x = np.ones((1, 1), dtype=np.uint8)
33
33
  y = np.ones((1, 1), dtype=np.uint8)
34
- rgb_sum = mc.apply_colors_and_merge_nc([x, y], ['betterBlue', 'betterOrange'], 'sum')
34
+ rgb_sum = mc.dispatch_multi_channel(
35
+ [x, y],
36
+ ['betterBlue', 'betterOrange'],
37
+ 'sum',
38
+ [(0, 255), (0, 255)],
39
+ )
35
40
  # blue = [0, 1, 2,]
36
41
  # orange = [1, 1, 0]
37
42
  assert np.allclose(
@@ -47,7 +52,12 @@ def test_apply_colors_and_merge_high_sum():
47
52
  '''
48
53
  x = np.ones((1, 1), dtype=np.uint8) * 255
49
54
  y = np.ones((1, 1), dtype=np.uint8) * 255
50
- rgb_sum = mc.apply_colors_and_merge_nc([x, y], ['betterBlue', 'betterOrange'], 'sum')
55
+ rgb_sum = mc.dispatch_multi_channel(
56
+ [x, y],
57
+ ['betterBlue', 'betterOrange'],
58
+ 'sum',
59
+ [(0, 255), (0, 255)],
60
+ )
51
61
  # blue = [0, 188, 254]
52
62
  # orange = [255, 149, 0]
53
63
  assert np.allclose(
@@ -63,7 +73,12 @@ def test_apply_colors_and_merge_low_max():
63
73
  '''
64
74
  x = np.ones((1, 1), dtype=np.uint8)
65
75
  y = np.ones((1, 1), dtype=np.uint8)
66
- rgb_max = mc.apply_colors_and_merge_nc([x, y], ['betterBlue', 'betterOrange'], 'max')
76
+ rgb_max = mc.dispatch_multi_channel(
77
+ [x, y],
78
+ ['betterBlue', 'betterOrange'],
79
+ 'max',
80
+ [(0, 255), (0, 255)],
81
+ )
67
82
  # blue = [0, 1, 2,]
68
83
  # orange = [1, 1, 0]
69
84
  assert np.allclose(
@@ -79,7 +94,12 @@ def test_apply_colors_and_merge_high_max():
79
94
  '''
80
95
  x = np.ones((1, 1), dtype=np.uint8) * 255
81
96
  y = np.ones((1, 1), dtype=np.uint8) * 255
82
- rgb_max = mc.apply_colors_and_merge_nc([x, y], ['betterBlue', 'betterOrange'], 'max')
97
+ rgb_max = mc.dispatch_multi_channel(
98
+ [x, y],
99
+ ['betterBlue', 'betterOrange'],
100
+ 'max',
101
+ [(0, 255), (0, 255)],
102
+ )
83
103
  # blue = [0, 188, 254]
84
104
  # orange = [255, 149, 0]
85
105
  assert np.allclose(
@@ -95,7 +115,12 @@ def test_apply_colors_and_merge_low_min():
95
115
  '''
96
116
  x = np.ones((1, 1), dtype=np.uint8)
97
117
  y = np.ones((1, 1), dtype=np.uint8)
98
- rgb_min = mc.apply_colors_and_merge_nc([x, y], ['betterBlue', 'betterOrange'], 'min')
118
+ rgb_min = mc.dispatch_multi_channel(
119
+ [x, y],
120
+ ['betterBlue', 'betterOrange'],
121
+ 'min',
122
+ [(0, 255), (0, 255)],
123
+ )
99
124
  # blue = [0, 1, 2,]
100
125
  # orange = [1, 1, 0]
101
126
  assert np.allclose(
@@ -111,7 +136,12 @@ def test_apply_colors_and_merge_high_min():
111
136
  '''
112
137
  x = np.ones((1, 1), dtype=np.uint8) * 255
113
138
  y = np.ones((1, 1), dtype=np.uint8) * 255
114
- rgb_min = mc.apply_colors_and_merge_nc([x, y], ['betterBlue', 'betterOrange'], 'min')
139
+ rgb_min = mc.dispatch_multi_channel(
140
+ [x, y],
141
+ ['betterBlue', 'betterOrange'],
142
+ 'min',
143
+ [(0, 255), (0, 255)],
144
+ )
115
145
  # blue = [0, 188, 254]
116
146
  # orange = [255, 149, 0]
117
147
  assert np.allclose(
@@ -127,7 +157,12 @@ def test_apply_colors_and_merge_low_mean():
127
157
  '''
128
158
  x = np.ones((1, 1), dtype=np.uint8)
129
159
  y = np.ones((1, 1), dtype=np.uint8)
130
- rgb_mean = mc.apply_colors_and_merge_nc([x, y], ['betterBlue', 'betterOrange'], 'mean')
160
+ rgb_mean = mc.dispatch_multi_channel(
161
+ [x, y],
162
+ ['betterBlue', 'betterOrange'],
163
+ 'mean',
164
+ [(0, 255), (0, 255)],
165
+ )
131
166
  # blue = [0, 1, 2,]
132
167
  # orange = [1, 1, 0]
133
168
  assert np.allclose(
@@ -145,7 +180,12 @@ def test_apply_colors_and_merge_high_mean():
145
180
  '''
146
181
  x = np.ones((1, 1), dtype=np.uint8) * 255
147
182
  y = np.ones((1, 1), dtype=np.uint8) * 255
148
- rgb_mean = mc.apply_colors_and_merge_nc([x, y], ['betterBlue', 'betterOrange'], 'mean')
183
+ rgb_mean = mc.dispatch_multi_channel(
184
+ [x, y],
185
+ ['betterBlue', 'betterOrange'],
186
+ 'mean',
187
+ [(0, 255), (0, 255)]
188
+ )
149
189
  # blue = [0, 188, 254]
150
190
  # orange = [255, 149, 0]
151
191
  assert np.allclose(
@@ -1,13 +1,13 @@
1
1
  # Import Rust functions
2
2
  from .mergechannels import ( # type: ignore
3
- apply_color_map,
4
- apply_colors_and_merge_nc,
3
+ dispatch_single_channel,
4
+ dispatch_multi_channel,
5
5
  )
6
-
7
6
  from ._internal import merge
8
7
 
8
+
9
9
  __all__ = [
10
- 'apply_color_map',
11
- 'apply_colors_and_merge_nc',
10
+ 'dispatch_single_channel',
11
+ 'dispatch_multi_channel',
12
12
  'merge',
13
13
  ]
@@ -0,0 +1,30 @@
1
+
2
+ from typing import Literal, Sequence
3
+ import numpy as np
4
+
5
+ from python.mergechannels._blending import BLENDING_OPTIONS
6
+ from python.mergechannels._luts import COLORMAPS
7
+
8
+
9
+ def merge(
10
+ arrs: np.ndarray | Sequence[np.ndarray],
11
+ colors: Sequence[COLORMAPS] = (),
12
+ blending: Literal[BLENDING_OPTIONS] = 'max',
13
+ saturation_limits: tuple[float, float] = (0.2, 99.8),
14
+ ) -> np.ndarray:
15
+ ...
16
+
17
+ def dispatch_single_channel(
18
+ array_reference: np.ndarray,
19
+ cmap_name: str,
20
+ limits: tuple[float, float],
21
+ ) -> np.ndarray:
22
+ ...
23
+
24
+ def dispatch_multi_channel(
25
+ array_references: Sequence[np.ndarray],
26
+ cmap_names: Sequence[str],
27
+ blending: Literal[BLENDING_OPTIONS],
28
+ limits: Sequence[tuple[float, float]],
29
+ ) -> np.ndarray:
30
+ ...
@@ -3,8 +3,8 @@ from typing import Sequence
3
3
  import numpy as np
4
4
 
5
5
  from mergechannels import (
6
- apply_color_map,
7
- apply_colors_and_merge_nc,
6
+ dispatch_single_channel,
7
+ dispatch_multi_channel,
8
8
  )
9
9
  from ._luts import COLORMAPS
10
10
  from ._blending import BLENDING_OPTIONS
@@ -13,6 +13,7 @@ def merge(
13
13
  arrs: Sequence[np.ndarray],
14
14
  colors: Sequence[COLORMAPS],
15
15
  blending: BLENDING_OPTIONS = 'max',
16
+ saturation_limits: tuple[float, float] = (0.011, 0.999),
16
17
  ) -> np.ndarray:
17
18
  '''
18
19
  apply cmaps to arrays and blend the colors
@@ -30,9 +31,9 @@ def merge(
30
31
  raise ValueError(
31
32
  f'Expected every array to have the same shape, got {arr_shapes}'
32
33
  )
33
- if not len(arr_shapes[0]) == 2:
34
+ if len(arr_shapes[0]) not in (2, 3):
34
35
  raise ValueError(
35
- f'Expected every array to be 2D, got {arr_shapes[0]}'
36
+ f'Expected every array to be 2D or 3D, got {arr_shapes[0]}'
36
37
  )
37
38
  arr_dtypes = [arr.dtype for arr in arrs]
38
39
  if not len(set(arr_dtypes)) == 1:
@@ -40,8 +41,25 @@ def merge(
40
41
  f'Expected every array to have the same dtype, got {arr_dtypes}'
41
42
  )
42
43
  # endregion
43
-
44
44
  if n_arrs == 1:
45
- return apply_color_map(arr=arrs[0], cmap_name=colors[0])
45
+ if arrs[0].dtype == 'uint8':
46
+ limits = (0, 255)
47
+ else:
48
+ low, high = np.percentile(arrs[0], np.array(saturation_limits) * 100)
49
+ limits = (low, high)
50
+ return dispatch_single_channel(
51
+ array_reference=arrs[0],
52
+ cmap_name=colors[0],
53
+ limits=limits,
54
+ )
46
55
  else:
47
- return apply_colors_and_merge_nc(arrs, colors, blending)
56
+ if all(arr.dtype == 'uint8' for arr in arrs):
57
+ limits = (0, 255)
58
+ else:
59
+ limits = tuple(np.percentile(arr, np.array(saturation_limits) * 100) for arr in arrs)
60
+ return dispatch_multi_channel(
61
+ array_references=arrs,
62
+ cmap_names=colors,
63
+ blending=blending,
64
+ limits=limits, # type: ignore
65
+ )
@@ -1,4 +1,33 @@
1
- pub fn max_blending(px_vals: &Vec<[u8; 3]>) -> [u8; 3] {
1
+ use smallvec::SmallVec;
2
+ use std::error::Error;
3
+ use std::fmt;
4
+
5
+ pub const MAX_N_CH: usize = 5;
6
+
7
+ pub type BlendFn = fn(&SmallVec<[[u8; 3]; 5]>) -> [u8; 3];
8
+
9
+ #[derive(Debug)]
10
+ pub enum MergeError {
11
+ InvalidBlendingMode(String),
12
+ }
13
+
14
+ impl fmt::Display for MergeError {
15
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16
+ match self {
17
+ MergeError::InvalidBlendingMode(mode) => {
18
+ write!(
19
+ f,
20
+ "Invalid blending mode: `{}`. Valid modes are 'max', 'sum', 'min', and 'mean'.",
21
+ mode
22
+ )
23
+ }
24
+ }
25
+ }
26
+ }
27
+
28
+ impl Error for MergeError {}
29
+
30
+ pub fn max_blending(px_vals: &SmallVec<[[u8; 3]; 5]>) -> [u8; 3] {
2
31
  let mut r: u8 = 0;
3
32
  let mut g: u8 = 0;
4
33
  let mut b: u8 = 0;
@@ -16,7 +45,7 @@ pub fn max_blending(px_vals: &Vec<[u8; 3]>) -> [u8; 3] {
16
45
  [r, g, b]
17
46
  }
18
47
 
19
- pub fn sum_blending(px_vals: &Vec<[u8; 3]>) -> [u8; 3] {
48
+ pub fn sum_blending(px_vals: &SmallVec<[[u8; 3]; 5]>) -> [u8; 3] {
20
49
  let mut r: u8 = 0;
21
50
  let mut g: u8 = 0;
22
51
  let mut b: u8 = 0;
@@ -28,7 +57,7 @@ pub fn sum_blending(px_vals: &Vec<[u8; 3]>) -> [u8; 3] {
28
57
  [r, g, b]
29
58
  }
30
59
 
31
- pub fn min_blending(px_vals: &Vec<[u8; 3]>) -> [u8; 3] {
60
+ pub fn min_blending(px_vals: &SmallVec<[[u8; 3]; 5]>) -> [u8; 3] {
32
61
  let mut r: u8 = 255;
33
62
  let mut g: u8 = 255;
34
63
  let mut b: u8 = 255;
@@ -46,7 +75,7 @@ pub fn min_blending(px_vals: &Vec<[u8; 3]>) -> [u8; 3] {
46
75
  [r, g, b]
47
76
  }
48
77
 
49
- pub fn mean_blending(px_vals: &Vec<[u8; 3]>) -> [u8; 3] {
78
+ pub fn mean_blending(px_vals: &SmallVec<[[u8; 3]; 5]>) -> [u8; 3] {
50
79
  let mut r: u16 = 0;
51
80
  let mut g: u16 = 0;
52
81
  let mut b: u16 = 0;
@@ -65,31 +94,37 @@ pub fn mean_blending(px_vals: &Vec<[u8; 3]>) -> [u8; 3] {
65
94
  #[cfg(test)]
66
95
  mod tests {
67
96
  use super::*;
97
+ fn create_test_data() -> SmallVec<[[u8; 3]; MAX_N_CH]> {
98
+ let mut px_vals: SmallVec<[[u8; 3]; MAX_N_CH]> = SmallVec::new();
99
+ px_vals.push([100, 100, 100]);
100
+ px_vals.push([200, 200, 200]);
101
+ px_vals
102
+ }
68
103
 
69
104
  #[test]
70
105
  fn test_max_blending() {
71
- let px_vals = vec![[100, 100, 100], [200, 200, 200]];
106
+ let px_vals = create_test_data();
72
107
  let result = max_blending(&px_vals);
73
108
  assert_eq!(result, [200, 200, 200]);
74
109
  }
75
110
 
76
111
  #[test]
77
112
  fn test_sum_blending() {
78
- let px_vals = vec![[100, 100, 100], [200, 200, 200]];
113
+ let px_vals = create_test_data();
79
114
  let result = sum_blending(&px_vals);
80
115
  assert_eq!(result, [255, 255, 255]);
81
116
  }
82
117
 
83
118
  #[test]
84
119
  fn test_min_blending() {
85
- let px_vals = vec![[100, 100, 100], [200, 200, 200]];
120
+ let px_vals = create_test_data();
86
121
  let result = min_blending(&px_vals);
87
122
  assert_eq!(result, [100, 100, 100]);
88
123
  }
89
124
 
90
125
  #[test]
91
126
  fn test_mean_blending() {
92
- let px_vals = vec![[100, 100, 100], [200, 200, 200]];
127
+ let px_vals = create_test_data();
93
128
  let result = mean_blending(&px_vals);
94
129
  assert_eq!(result, [150, 150, 150]);
95
130
  }