pixelarray_test.py 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420
  1. import sys
  2. import platform
  3. try:
  4. reduce
  5. except NameError:
  6. from functools import reduce
  7. import operator
  8. import weakref
  9. import gc
  10. import unittest
  11. from pygame.tests.test_utils import SurfaceSubclass
  12. try:
  13. from pygame.tests.test_utils import arrinter
  14. except NameError:
  15. pass
  16. import pygame
  17. from pygame.compat import xrange_
  18. PY3 = sys.version_info >= (3, 0, 0)
  19. IS_PYPY = 'PyPy' == platform.python_implementation()
  20. class TestMixin (object):
  21. def assert_surfaces_equal (self, s1, s2):
  22. # Assumes the surfaces are the same size.
  23. w, h = s1.get_size ()
  24. for x in range (w):
  25. for y in range (h):
  26. self.assertEqual (s1.get_at ((x, y)), s2.get_at ((x, y)),
  27. "size: (%i, %i), position: (%i, %i)" %
  28. (w, h, x, y))
  29. class PixelArrayTypeTest (unittest.TestCase, TestMixin):
  30. def test_compare(self):
  31. # __doc__ (as of 2008-06-25) for pygame.pixelarray.PixelArray.compare:
  32. # PixelArray.compare (array, distance=0, weights=(0.299, 0.587, 0.114)): Return PixelArray
  33. # Compares the PixelArray with another one.
  34. w = 10
  35. h = 20
  36. size = w, h
  37. sf = pygame.Surface (size, 0, 32)
  38. ar = pygame.PixelArray (sf)
  39. sf2 = pygame.Surface (size, 0, 32)
  40. self.assertRaises (TypeError, ar.compare, sf2)
  41. ar2 = pygame.PixelArray (sf2)
  42. ar3 = ar.compare (ar2)
  43. self.assertTrue(isinstance (ar3, pygame.PixelArray))
  44. self.assertEqual (ar3.shape, size)
  45. sf2.fill (pygame.Color ('white'))
  46. self.assert_surfaces_equal (sf2, ar3.surface)
  47. del ar3
  48. r = pygame.Rect (2, 5, 6, 13)
  49. sf.fill (pygame.Color ('blue'), r)
  50. sf2.fill (pygame.Color ('red'))
  51. sf2.fill (pygame.Color ('blue'), r)
  52. ar3 = ar.compare (ar2)
  53. sf.fill (pygame.Color ('white'), r)
  54. self.assert_surfaces_equal (sf, ar3.surface)
  55. # FINISH ME!
  56. # Test other bit depths, slices, and distance != 0.
  57. def test_close(self):
  58. """ does not crash when it is deleted.
  59. """
  60. s = pygame.Surface((10,10))
  61. a = pygame.PixelArray(s)
  62. a.close()
  63. del a
  64. def test_close_raises(self):
  65. """ when you try to do an operation after it is closed.
  66. """
  67. s = pygame.Surface((10,10))
  68. a = pygame.PixelArray(s)
  69. a.close()
  70. def do_operation():
  71. a[:]
  72. self.assertRaises (ValueError, do_operation)
  73. def do_operation2():
  74. a[:] = 1
  75. self.assertRaises (ValueError, do_operation2)
  76. def do_operation3():
  77. a.make_surface()
  78. self.assertRaises (ValueError, do_operation3)
  79. def do_operation4():
  80. for x in a:
  81. pass
  82. self.assertRaises (ValueError, do_operation4)
  83. def test_context_manager(self):
  84. """ closes properly.
  85. """
  86. s = pygame.Surface((10,10))
  87. with pygame.PixelArray(s) as a:
  88. a[:]
  89. def test_pixel_array (self):
  90. for bpp in (8, 16, 24, 32):
  91. sf = pygame.Surface ((10, 20), 0, bpp)
  92. sf.fill ((0, 0, 0))
  93. ar = pygame.PixelArray (sf)
  94. self.assertEqual (ar._pixels_address, sf._pixels_address)
  95. if sf.mustlock ():
  96. self.assertTrue (sf.get_locked ())
  97. self.assertEqual (len (ar), 10)
  98. del ar
  99. if sf.mustlock ():
  100. self.assertFalse (sf.get_locked ())
  101. def test_as_class (self):
  102. # Check general new-style class freatures.
  103. sf = pygame.Surface ((2, 3), 0, 32)
  104. ar = pygame.PixelArray (sf)
  105. self.assertRaises (AttributeError, getattr, ar, 'nonnative')
  106. ar.nonnative = 'value'
  107. self.assertEqual (ar.nonnative, 'value')
  108. r = weakref.ref (ar)
  109. self.assertTrue (r() is ar)
  110. del ar
  111. gc.collect ()
  112. self.assertTrue (r() is None)
  113. class C (pygame.PixelArray):
  114. def __str__ (self):
  115. return "string (%i, %i)" % self.shape
  116. ar = C (sf)
  117. self.assertEqual (str (ar), "string (2, 3)")
  118. r = weakref.ref (ar)
  119. self.assertTrue (r() is ar)
  120. del ar
  121. gc.collect ()
  122. self.assertTrue (r() is None)
  123. def test_pixelarray__subclassed_surface(self):
  124. """Ensure the PixelArray constructor accepts subclassed surfaces."""
  125. surface = SurfaceSubclass((3, 5), 0, 32)
  126. pixelarray = pygame.PixelArray(surface)
  127. self.assertIsInstance(pixelarray, pygame.PixelArray)
  128. # Sequence interfaces
  129. def test_get_column (self):
  130. for bpp in (8, 16, 24, 32):
  131. sf = pygame.Surface ((6, 8), 0, bpp)
  132. sf.fill ((0, 0, 255))
  133. val = sf.map_rgb ((0, 0, 255))
  134. ar = pygame.PixelArray (sf)
  135. ar2 = ar.__getitem__ (1)
  136. self.assertEqual (len(ar2), 8)
  137. self.assertEqual (ar2.__getitem__ (0), val)
  138. self.assertEqual (ar2.__getitem__ (1), val)
  139. self.assertEqual (ar2.__getitem__ (2), val)
  140. ar2 = ar.__getitem__ (-1)
  141. self.assertEqual (len(ar2), 8)
  142. self.assertEqual (ar2.__getitem__ (0), val)
  143. self.assertEqual (ar2.__getitem__ (1), val)
  144. self.assertEqual (ar2.__getitem__ (2), val)
  145. def test_get_pixel (self):
  146. w = 10
  147. h = 20
  148. size = w, h
  149. bg_color = (0, 0, 255)
  150. fg_color_y = (0, 0, 128)
  151. fg_color_x = (0, 0, 11)
  152. for bpp in (8, 16, 24, 32):
  153. sf = pygame.Surface (size, 0, bpp)
  154. mapped_bg_color = sf.map_rgb (bg_color)
  155. mapped_fg_color_y = sf.map_rgb (fg_color_y)
  156. mapped_fg_color_x = sf.map_rgb (fg_color_x)
  157. self.assertNotEqual (mapped_fg_color_y, mapped_bg_color,
  158. "Unusable test colors for bpp %i" % (bpp,))
  159. self.assertNotEqual (mapped_fg_color_x, mapped_bg_color,
  160. "Unusable test colors for bpp %i" % (bpp,))
  161. self.assertNotEqual (mapped_fg_color_y, mapped_fg_color_x,
  162. "Unusable test colors for bpp %i" % (bpp,))
  163. sf.fill (bg_color)
  164. ar = pygame.PixelArray (sf)
  165. ar_y = ar.__getitem__ (1)
  166. for y in xrange_ (h):
  167. ar2 = ar_y.__getitem__ (y)
  168. self.assertEqual (ar2, mapped_bg_color,
  169. "ar[1][%i] == %i, mapped_bg_color == %i" %
  170. (y, ar2, mapped_bg_color))
  171. sf.set_at ((1, y), fg_color_y)
  172. ar2 = ar_y.__getitem__ (y)
  173. self.assertEqual (ar2, mapped_fg_color_y,
  174. "ar[1][%i] == %i, mapped_fg_color_y == %i" %
  175. (y, ar2, mapped_fg_color_y))
  176. sf.set_at ((1, 1), bg_color)
  177. for x in xrange_ (w):
  178. ar2 = ar.__getitem__ (x).__getitem__ (1)
  179. self.assertEqual (ar2, mapped_bg_color,
  180. "ar[%i][1] = %i, mapped_bg_color = %i" %
  181. (x, ar2, mapped_bg_color))
  182. sf.set_at ((x, 1), fg_color_x)
  183. ar2 = ar.__getitem__ (x).__getitem__ (1)
  184. self.assertEqual (ar2, mapped_fg_color_x,
  185. "ar[%i][1] = %i, mapped_fg_color_x = %i" %
  186. (x, ar2, mapped_fg_color_x))
  187. ar2 = ar.__getitem__ (0).__getitem__ (0)
  188. self.assertEqual (ar2, mapped_bg_color, "bpp = %i" % (bpp,))
  189. ar2 = ar.__getitem__ (1).__getitem__ (0)
  190. self.assertEqual (ar2, mapped_fg_color_y, "bpp = %i" % (bpp,))
  191. ar2 = ar.__getitem__ (-4).__getitem__ (1)
  192. self.assertEqual (ar2, mapped_fg_color_x, "bpp = %i" % (bpp,))
  193. ar2 = ar.__getitem__ (-4).__getitem__ (5)
  194. self.assertEqual (ar2, mapped_bg_color, "bpp = %i" % (bpp,))
  195. ar2 = ar.__getitem__ (-4).__getitem__ (0)
  196. self.assertEqual (ar2, mapped_bg_color, "bpp = %i" % (bpp,))
  197. ar2 = ar.__getitem__ (-w + 1).__getitem__ (0)
  198. self.assertEqual (ar2, mapped_fg_color_y, "bpp = %i" % (bpp,))
  199. ar2 = ar.__getitem__ (-w).__getitem__ (0)
  200. self.assertEqual (ar2, mapped_bg_color, "bpp = %i" % (bpp,))
  201. ar2 = ar.__getitem__ (5).__getitem__ (-4)
  202. self.assertEqual (ar2, mapped_bg_color, "bpp = %i" % (bpp,))
  203. ar2 = ar.__getitem__ (5).__getitem__ (-h + 1)
  204. self.assertEqual (ar2, mapped_fg_color_x, "bpp = %i" % (bpp,))
  205. ar2 = ar.__getitem__ (5).__getitem__ (-h)
  206. self.assertEqual (ar2, mapped_bg_color, "bpp = %i" % (bpp,))
  207. ar2 = ar.__getitem__ (0).__getitem__ (-h + 1)
  208. self.assertEqual (ar2, mapped_fg_color_x, "bpp = %i" % (bpp,))
  209. ar2 = ar.__getitem__ (0).__getitem__ (-h)
  210. self.assertEqual (ar2, mapped_bg_color, "bpp = %i" % (bpp,))
  211. def test_set_pixel (self):
  212. for bpp in (8, 16, 24, 32):
  213. sf = pygame.Surface ((10, 20), 0, bpp)
  214. sf.fill ((0, 0, 0))
  215. ar = pygame.PixelArray (sf)
  216. ar.__getitem__ (0).__setitem__ (0, (0, 255, 0))
  217. self.assertEqual (ar[0][0], sf.map_rgb ((0, 255, 0)))
  218. ar.__getitem__ (1).__setitem__ (1, (128, 128, 128))
  219. self.assertEqual (ar[1][1], sf.map_rgb ((128, 128, 128)))
  220. ar.__getitem__(-1).__setitem__ (-1, (128, 128, 128))
  221. self.assertEqual (ar[9][19], sf.map_rgb ((128, 128, 128)))
  222. ar.__getitem__ (-2).__setitem__ (-2, (128, 128, 128))
  223. self.assertEqual (ar[8][-2], sf.map_rgb ((128, 128, 128)))
  224. def test_set_column (self):
  225. for bpp in (8, 16, 24, 32):
  226. sf = pygame.Surface ((6, 8), 0, bpp)
  227. sf.fill ((0, 0, 0))
  228. ar = pygame.PixelArray (sf)
  229. sf2 = pygame.Surface ((6, 8), 0, bpp)
  230. sf2.fill ((0, 255, 255))
  231. ar2 = pygame.PixelArray (sf2)
  232. # Test single value assignment
  233. ar.__setitem__ (2, (128, 128, 128))
  234. self.assertEqual (ar[2][0], sf.map_rgb ((128, 128, 128)))
  235. self.assertEqual (ar[2][1], sf.map_rgb ((128, 128, 128)))
  236. ar.__setitem__ (-1, (0, 255, 255))
  237. self.assertEqual (ar[5][0], sf.map_rgb ((0, 255, 255)))
  238. self.assertEqual (ar[-1][1], sf.map_rgb ((0, 255, 255)))
  239. ar.__setitem__ (-2, (255, 255, 0))
  240. self.assertEqual (ar[4][0], sf.map_rgb ((255, 255, 0)))
  241. self.assertEqual (ar[-2][1], sf.map_rgb ((255, 255, 0)))
  242. # Test list assignment.
  243. ar.__setitem__ (0, [(255, 255, 255)] * 8)
  244. self.assertEqual (ar[0][0], sf.map_rgb ((255, 255, 255)))
  245. self.assertEqual (ar[0][1], sf.map_rgb ((255, 255, 255)))
  246. # Test tuple assignment.
  247. # Changed in Pygame 1.9.2 - Raises an exception.
  248. self.assertRaises (ValueError, ar.__setitem__, 1,
  249. ((204, 0, 204), (17, 17, 17), (204, 0, 204),
  250. (17, 17, 17), (204, 0, 204), (17, 17, 17),
  251. (204, 0, 204), (17, 17, 17)))
  252. # Test pixel array assignment.
  253. ar.__setitem__ (1, ar2.__getitem__ (3))
  254. self.assertEqual (ar[1][0], sf.map_rgb ((0, 255, 255)))
  255. self.assertEqual (ar[1][1], sf.map_rgb ((0, 255, 255)))
  256. def test_get_slice (self):
  257. for bpp in (8, 16, 24, 32):
  258. sf = pygame.Surface ((10, 20), 0, bpp)
  259. sf.fill ((0, 0, 0))
  260. ar = pygame.PixelArray (sf)
  261. self.assertEqual (len (ar[0:2]), 2)
  262. self.assertEqual (len (ar[3:7][3]), 20)
  263. self.assertEqual (ar[0:0], None)
  264. self.assertEqual (ar[5:5], None)
  265. self.assertEqual (ar[9:9], None)
  266. # Has to resolve to ar[7:8]
  267. self.assertEqual (len (ar[-3:-2]), 1) # 2D
  268. self.assertEqual (len (ar[-3:-2][0]), 20) # 1D
  269. # Try assignments.
  270. # 2D assignment.
  271. ar[2:5] = (255, 255, 255)
  272. # 1D assignment
  273. ar[3][3:7] = (10, 10, 10)
  274. self.assertEqual (ar[3][5], sf.map_rgb ((10, 10, 10)))
  275. self.assertEqual (ar[3][6], sf.map_rgb ((10, 10, 10)))
  276. @unittest.skipIf(IS_PYPY, 'skipping for PyPy (segfaults on mac pypy3 6.0.0)')
  277. def test_contains (self):
  278. for bpp in (8, 16, 24, 32):
  279. sf = pygame.Surface ((10, 20), 0, bpp)
  280. sf.fill ((0, 0, 0))
  281. sf.set_at ((8, 8), (255, 255, 255))
  282. ar = pygame.PixelArray (sf)
  283. self.assertTrue ((0, 0, 0) in ar)
  284. self.assertTrue ((255, 255, 255) in ar)
  285. self.assertFalse ((255, 255, 0) in ar)
  286. self.assertFalse (0x0000ff in ar)
  287. # Test sliced array
  288. self.assertTrue ((0, 0, 0) in ar[8])
  289. self.assertTrue ((255, 255, 255) in ar[8])
  290. self.assertFalse ((255, 255, 0) in ar[8])
  291. self.assertFalse (0x0000ff in ar[8])
  292. def test_get_surface (self):
  293. for bpp in (8, 16, 24, 32):
  294. sf = pygame.Surface((10, 20), 0, bpp)
  295. sf.fill((0, 0, 0))
  296. ar = pygame.PixelArray(sf)
  297. self.assertTrue(ar.surface is sf)
  298. def test_get_surface__subclassed_surface(self):
  299. """Ensure the surface attribute can handle subclassed surfaces."""
  300. expected_surface = SurfaceSubclass((5, 3), 0, 32)
  301. pixelarray = pygame.PixelArray(expected_surface)
  302. surface = pixelarray.surface
  303. self.assertIs(surface, expected_surface)
  304. self.assertIsInstance(surface, pygame.Surface)
  305. self.assertIsInstance(surface, SurfaceSubclass)
  306. def test_set_slice (self):
  307. for bpp in (8, 16, 24, 32):
  308. sf = pygame.Surface ((6, 8), 0, bpp)
  309. sf.fill ((0, 0, 0))
  310. ar = pygame.PixelArray (sf)
  311. # Test single value assignment
  312. val = sf.map_rgb ((128, 128, 128))
  313. ar[0:2] = val
  314. self.assertEqual (ar[0][0], val)
  315. self.assertEqual (ar[0][1], val)
  316. self.assertEqual (ar[1][0], val)
  317. self.assertEqual (ar[1][1], val)
  318. val = sf.map_rgb ((0, 255, 255))
  319. ar[-3:-1] = val
  320. self.assertEqual (ar[3][0], val)
  321. self.assertEqual (ar[-2][1], val)
  322. val = sf.map_rgb ((255, 255, 255))
  323. ar[-3:] = (255, 255, 255)
  324. self.assertEqual (ar[4][0], val)
  325. self.assertEqual (ar[-1][1], val)
  326. # Test array size mismatch.
  327. # Changed in ver. 1.9.2
  328. # (was "Test list assignment, this is a vertical assignment.")
  329. val = sf.map_rgb ((0, 255, 0))
  330. self.assertRaises (ValueError, ar.__setitem__, slice (2, 4),
  331. [val] * 8)
  332. # And the horizontal assignment.
  333. val = sf.map_rgb ((255, 0, 0))
  334. val2 = sf.map_rgb ((128, 0, 255))
  335. ar[0:2] = [val, val2]
  336. self.assertEqual (ar[0][0], val)
  337. self.assertEqual (ar[1][0], val2)
  338. self.assertEqual (ar[0][1], val)
  339. self.assertEqual (ar[1][1], val2)
  340. self.assertEqual (ar[0][4], val)
  341. self.assertEqual (ar[1][4], val2)
  342. self.assertEqual (ar[0][5], val)
  343. self.assertEqual (ar[1][5], val2)
  344. # Test pixelarray assignment.
  345. ar[:] = (0, 0, 0)
  346. sf2 = pygame.Surface ((6, 8), 0, bpp)
  347. sf2.fill ((255, 0, 255))
  348. val = sf.map_rgb ((255, 0, 255))
  349. ar2 = pygame.PixelArray (sf2)
  350. ar[:] = ar2[:]
  351. self.assertEqual (ar[0][0], val)
  352. self.assertEqual (ar[5][7], val)
  353. # Ensure p1 ... pn are freed for array[...] = [p1, ..., pn]
  354. # Bug fix: reference counting.
  355. if hasattr(sys, 'getrefcount'):
  356. class Int(int):
  357. """Unique int instances"""
  358. pass
  359. sf = pygame.Surface ((5, 2), 0, 32)
  360. ar = pygame.PixelArray (sf)
  361. pixel_list = [Int(i) for i in range(ar.shape[0])]
  362. refcnts_before = [sys.getrefcount (i) for i in pixel_list]
  363. ar[...] = pixel_list
  364. refcnts_after = [sys.getrefcount (i) for i in pixel_list]
  365. gc.collect ()
  366. self.assertEqual (refcnts_after, refcnts_before)
  367. def test_subscript (self):
  368. # By default we do not need to work with any special __***__
  369. # methods as map subscripts are the first looked up by the
  370. # object system.
  371. for bpp in (8, 16, 24, 32):
  372. sf = pygame.Surface ((6, 8), 0, bpp)
  373. sf.set_at ((1, 3), (0, 255, 0))
  374. sf.set_at ((0, 0), (0, 255, 0))
  375. sf.set_at ((4, 4), (0, 255, 0))
  376. val = sf.map_rgb ((0, 255, 0))
  377. ar = pygame.PixelArray (sf)
  378. # Test single value requests.
  379. self.assertEqual (ar[1,3], val)
  380. self.assertEqual (ar[0,0], val)
  381. self.assertEqual (ar[4,4], val)
  382. self.assertEqual (ar[1][3], val)
  383. self.assertEqual (ar[0][0], val)
  384. self.assertEqual (ar[4][4], val)
  385. # Test ellipse working.
  386. self.assertEqual (len (ar[...,...]), 6)
  387. self.assertEqual (len (ar[1,...]), 8)
  388. self.assertEqual (len (ar[...,3]), 6)
  389. # Test simple slicing
  390. self.assertEqual (len (ar[:,:]), 6)
  391. self.assertEqual (len (ar[:,]), 6)
  392. self.assertEqual (len (ar[1,:]), 8)
  393. self.assertEqual (len (ar[:,2]), 6)
  394. # Empty slices
  395. self.assertEqual (ar[4:4,], None)
  396. self.assertEqual (ar[4:4,...], None)
  397. self.assertEqual (ar[4:4,2:2], None)
  398. self.assertEqual (ar[4:4,1:4], None)
  399. self.assertEqual (ar[4:4:2,], None)
  400. self.assertEqual (ar[4:4:-2,], None)
  401. self.assertEqual (ar[4:4:1,...], None)
  402. self.assertEqual (ar[4:4:-1,...], None)
  403. self.assertEqual (ar[4:4:1,2:2], None)
  404. self.assertEqual (ar[4:4:-1,1:4], None)
  405. self.assertEqual (ar[...,4:4], None)
  406. self.assertEqual (ar[1:4,4:4], None)
  407. self.assertEqual (ar[...,4:4:1], None)
  408. self.assertEqual (ar[...,4:4:-1], None)
  409. self.assertEqual (ar[2:2,4:4:1], None)
  410. self.assertEqual (ar[1:4,4:4:-1], None)
  411. # Test advanced slicing
  412. ar[0] = 0
  413. ar[1] = 1
  414. ar[2] = 2
  415. ar[3] = 3
  416. ar[4] = 4
  417. ar[5] = 5
  418. # We should receive something like [0,2,4]
  419. self.assertEqual (ar[::2,1][0], 0)
  420. self.assertEqual (ar[::2,1][1], 2)
  421. self.assertEqual (ar[::2,1][2], 4)
  422. # We should receive something like [2,2,2]
  423. self.assertEqual (ar[2,::2][0], 2)
  424. self.assertEqual (ar[2,::2][1], 2)
  425. self.assertEqual (ar[2,::2][2], 2)
  426. # Should create a 3x3 array of [0,2,4]
  427. ar2 = ar[::2,::2]
  428. self.assertEqual (len (ar2), 3)
  429. self.assertEqual (ar2[0][0], 0)
  430. self.assertEqual (ar2[0][1], 0)
  431. self.assertEqual (ar2[0][2], 0)
  432. self.assertEqual (ar2[2][0], 4)
  433. self.assertEqual (ar2[2][1], 4)
  434. self.assertEqual (ar2[2][2], 4)
  435. self.assertEqual (ar2[1][0], 2)
  436. self.assertEqual (ar2[2][0], 4)
  437. self.assertEqual (ar2[1][1], 2)
  438. # Should create a reversed 3x8 array over X of [1,2,3] -> [3,2,1]
  439. ar2 = ar[3:0:-1]
  440. self.assertEqual (len (ar2), 3)
  441. self.assertEqual (ar2[0][0], 3)
  442. self.assertEqual (ar2[0][1], 3)
  443. self.assertEqual (ar2[0][2], 3)
  444. self.assertEqual (ar2[0][7], 3)
  445. self.assertEqual (ar2[2][0], 1)
  446. self.assertEqual (ar2[2][1], 1)
  447. self.assertEqual (ar2[2][2], 1)
  448. self.assertEqual (ar2[2][7], 1)
  449. self.assertEqual (ar2[1][0], 2)
  450. self.assertEqual (ar2[1][1], 2)
  451. # Should completely reverse the array over X -> [5,4,3,2,1,0]
  452. ar2 = ar[::-1]
  453. self.assertEqual (len (ar2), 6)
  454. self.assertEqual (ar2[0][0], 5)
  455. self.assertEqual (ar2[0][1], 5)
  456. self.assertEqual (ar2[0][3], 5)
  457. self.assertEqual (ar2[0][-1], 5)
  458. self.assertEqual (ar2[1][0], 4)
  459. self.assertEqual (ar2[1][1], 4)
  460. self.assertEqual (ar2[1][3], 4)
  461. self.assertEqual (ar2[1][-1], 4)
  462. self.assertEqual (ar2[-1][-1], 0)
  463. self.assertEqual (ar2[-2][-2], 1)
  464. self.assertEqual (ar2[-3][-1], 2)
  465. # Test advanced slicing
  466. ar[:] = 0
  467. ar2 = ar[:,1]
  468. ar2[:] = [99] * len(ar2)
  469. self.assertEqual (ar2[0], 99)
  470. self.assertEqual (ar2[-1], 99)
  471. self.assertEqual (ar2[-2], 99)
  472. self.assertEqual (ar2[2], 99)
  473. self.assertEqual (ar[0,1], 99)
  474. self.assertEqual (ar[1,1], 99)
  475. self.assertEqual (ar[2,1], 99)
  476. self.assertEqual (ar[-1,1], 99)
  477. self.assertEqual (ar[-2,1], 99)
  478. # Cases where a 2d array should have a dimension of length 1.
  479. ar2 = ar[1:2,:]
  480. self.assertEqual (ar2.shape, (1, ar.shape[1]))
  481. ar2 = ar[:,1:2]
  482. self.assertEqual (ar2.shape, (ar.shape[0], 1))
  483. sf2 = pygame.Surface ((1, 5), 0, 32)
  484. ar2 = pygame.PixelArray (sf2)
  485. self.assertEqual (ar2.shape, sf2.get_size ())
  486. sf2 = pygame.Surface ((7, 1), 0, 32)
  487. ar2 = pygame.PixelArray (sf2)
  488. self.assertEqual (ar2.shape, sf2.get_size ())
  489. # Array has a single ellipsis subscript: the identity operator
  490. ar2 = ar[...]
  491. self.assertTrue(ar2 is ar)
  492. # Ensure x and y are freed for p = array[x, y]
  493. # Bug fix: reference counting
  494. if hasattr(sys, 'getrefcount'):
  495. class Int(int):
  496. """Unique int instances"""
  497. pass
  498. sf = pygame.Surface ((2, 2), 0, 32)
  499. ar = pygame.PixelArray (sf)
  500. x, y = Int(0), Int(1)
  501. rx_before, ry_before = sys.getrefcount (x), sys.getrefcount (y)
  502. p = ar[x, y]
  503. rx_after, ry_after = sys.getrefcount (x), sys.getrefcount (y)
  504. self.assertEqual (rx_after, rx_before)
  505. self.assertEqual (ry_after, ry_before)
  506. def test_ass_subscript (self):
  507. for bpp in (8, 16, 24, 32):
  508. sf = pygame.Surface ((6, 8), 0, bpp)
  509. sf.fill ((255, 255, 255))
  510. ar = pygame.PixelArray (sf)
  511. # Test ellipse working
  512. ar[...,...] = (0, 0, 0)
  513. self.assertEqual (ar[0,0], 0)
  514. self.assertEqual (ar[1,0], 0)
  515. self.assertEqual (ar[-1,-1], 0)
  516. ar[...,] = (0, 0, 255)
  517. self.assertEqual (ar[0,0], sf.map_rgb ((0, 0, 255)))
  518. self.assertEqual (ar[1,0], sf.map_rgb ((0, 0, 255)))
  519. self.assertEqual (ar[-1,-1], sf.map_rgb ((0, 0, 255)))
  520. ar[:,...] = (255, 0, 0)
  521. self.assertEqual (ar[0,0], sf.map_rgb ((255, 0, 0)))
  522. self.assertEqual (ar[1,0], sf.map_rgb ((255, 0, 0)))
  523. self.assertEqual (ar[-1,-1], sf.map_rgb ((255, 0, 0)))
  524. ar[...] = (0, 255, 0)
  525. self.assertEqual (ar[0,0], sf.map_rgb ((0, 255, 0)))
  526. self.assertEqual (ar[1,0], sf.map_rgb ((0, 255, 0)))
  527. self.assertEqual (ar[-1,-1], sf.map_rgb ((0, 255, 0)))
  528. # Ensure x and y are freed for array[x, y] = p
  529. # Bug fix: reference counting
  530. if hasattr(sys, 'getrefcount'):
  531. class Int(int):
  532. """Unique int instances"""
  533. pass
  534. sf = pygame.Surface ((2, 2), 0, 32)
  535. ar = pygame.PixelArray (sf)
  536. x, y = Int(0), Int(1)
  537. rx_before, ry_before = sys.getrefcount (x), sys.getrefcount (y)
  538. ar[x, y] = 0
  539. rx_after, ry_after = sys.getrefcount (x), sys.getrefcount (y)
  540. self.assertEqual (rx_after, rx_before)
  541. self.assertEqual (ry_after, ry_before)
  542. def test_pixels_field(self):
  543. for bpp in [1, 2, 3, 4]:
  544. sf = pygame.Surface ((11, 7), 0, bpp * 8)
  545. ar = pygame.PixelArray (sf)
  546. ar2 = ar[1:,:]
  547. self.assertEqual (ar2._pixels_address - ar._pixels_address,
  548. ar.itemsize)
  549. ar2 = ar[:,1:]
  550. self.assertEqual (ar2._pixels_address - ar._pixels_address,
  551. ar.strides[1])
  552. ar2 = ar[::-1,:]
  553. self.assertEqual (ar2._pixels_address - ar._pixels_address,
  554. (ar.shape[0] - 1) * ar.itemsize)
  555. ar2 = ar[::-2,:]
  556. self.assertEqual (ar2._pixels_address - ar._pixels_address,
  557. (ar.shape[0] - 1) * ar.itemsize)
  558. ar2 = ar[:,::-1]
  559. self.assertEqual (ar2._pixels_address - ar._pixels_address,
  560. (ar.shape[1] - 1) * ar.strides[1])
  561. ar3 = ar2[::-1,:]
  562. self.assertEqual (ar3._pixels_address - ar._pixels_address,
  563. (ar.shape[0] - 1) * ar.strides[0] +
  564. (ar.shape[1] - 1) * ar.strides[1])
  565. ar2 = ar[:,::-2]
  566. self.assertEqual (ar2._pixels_address - ar._pixels_address,
  567. (ar.shape[1] - 1) * ar.strides[1])
  568. ar2 = ar[2::,3::]
  569. self.assertEqual (ar2._pixels_address - ar._pixels_address,
  570. ar.strides[0] * 2 + ar.strides[1] * 3)
  571. ar2 = ar[2::2,3::4]
  572. self.assertEqual (ar2._pixels_address - ar._pixels_address,
  573. ar.strides[0] * 2 + ar.strides[1] * 3)
  574. ar2 = ar[9:2:-1,:]
  575. self.assertEqual (ar2._pixels_address - ar._pixels_address,
  576. ar.strides[0] * 9)
  577. ar2 = ar[:,5:2:-1]
  578. self.assertEqual (ar2._pixels_address - ar._pixels_address,
  579. ar.strides[1] * 5)
  580. ##? ar2 = ar[:,9:2:-1]
  581. def test_make_surface (self):
  582. bg_color = pygame.Color (255, 255, 255)
  583. fg_color = pygame.Color (128, 100, 0)
  584. for bpp in (8, 16, 24, 32):
  585. sf = pygame.Surface ((10, 20), 0, bpp)
  586. bg_color_adj = sf.unmap_rgb (sf.map_rgb (bg_color))
  587. fg_color_adj = sf.unmap_rgb (sf.map_rgb (fg_color))
  588. sf.fill (bg_color_adj)
  589. sf.fill (fg_color_adj, (2, 5, 4, 11))
  590. ar = pygame.PixelArray (sf)
  591. newsf = ar[::2,::2].make_surface ()
  592. rect = newsf.get_rect ()
  593. self.assertEqual (rect.width, 5)
  594. self.assertEqual (rect.height, 10)
  595. for p in [(0, 2), (0, 3), (1, 2),
  596. (2, 2), (3, 2), (3, 3),
  597. (0, 7), (0, 8), (1, 8),
  598. (2, 8), (3, 8), (3, 7)]:
  599. self.assertEqual (newsf.get_at (p), bg_color_adj)
  600. for p in [(1, 3), (2, 3), (1, 5), (2, 5), (1, 7), (2, 7)]:
  601. self.assertEqual (newsf.get_at (p), fg_color_adj)
  602. # Bug when array width is not a multiple of the slice step.
  603. w = 17
  604. lst = list(range(w))
  605. w_slice = len(lst[::2])
  606. h = 3
  607. sf = pygame.Surface ((w, h), 0, 32)
  608. ar = pygame.PixelArray (sf)
  609. ar2 = ar[::2,:]
  610. sf2 = ar2.make_surface ()
  611. w2, h2 = sf2.get_size ()
  612. self.assertEqual (w2, w_slice)
  613. self.assertEqual (h2, h)
  614. # Bug when array height is not a multiple of the slice step.
  615. # This can hang the Python interpreter.
  616. h = 17
  617. lst = list(range(h))
  618. h_slice = len(lst[::2])
  619. w = 3
  620. sf = pygame.Surface ((w, h), 0, 32)
  621. ar = pygame.PixelArray (sf)
  622. ar2 = ar[:,::2]
  623. sf2 = ar2.make_surface () # Hangs here.
  624. w2, h2 = sf2.get_size ()
  625. self.assertEqual (w2, w)
  626. self.assertEqual (h2, h_slice)
  627. def test_make_surface__subclassed_surface(self):
  628. """Ensure make_surface can handle subclassed surfaces."""
  629. expected_size = (3, 5)
  630. expected_flags = 0
  631. expected_depth = 32
  632. original_surface = SurfaceSubclass(expected_size, expected_flags,
  633. expected_depth)
  634. pixelarray = pygame.PixelArray(original_surface)
  635. surface = pixelarray.make_surface()
  636. self.assertIsNot(surface, original_surface)
  637. self.assertIsInstance(surface, pygame.Surface)
  638. self.assertNotIsInstance(surface, SurfaceSubclass)
  639. self.assertEqual(surface.get_size(), expected_size)
  640. self.assertEqual(surface.get_flags(), expected_flags)
  641. self.assertEqual(surface.get_bitsize(), expected_depth)
  642. def test_iter (self):
  643. for bpp in (8, 16, 24, 32):
  644. sf = pygame.Surface ((5, 10), 0, bpp)
  645. ar = pygame.PixelArray (sf)
  646. iterations = 0
  647. for col in ar:
  648. self.assertEqual (len (col), 10)
  649. iterations += 1
  650. self.assertEqual (iterations, 5)
  651. def test_replace (self):
  652. #print "replace start"
  653. for bpp in (8, 16, 24, 32):
  654. sf = pygame.Surface ((10, 10), 0, bpp)
  655. sf.fill ((255, 0, 0))
  656. rval = sf.map_rgb ((0, 0, 255))
  657. oval = sf.map_rgb ((255, 0, 0))
  658. ar = pygame.PixelArray (sf)
  659. ar[::2].replace ((255, 0, 0), (0, 0, 255))
  660. self.assertEqual (ar[0][0], rval)
  661. self.assertEqual (ar[1][0], oval)
  662. self.assertEqual (ar[2][3], rval)
  663. self.assertEqual (ar[3][6], oval)
  664. self.assertEqual (ar[8][9], rval)
  665. self.assertEqual (ar[9][9], oval)
  666. ar[::2].replace ((0, 0, 255), (255, 0, 0), weights=(10, 20, 50))
  667. self.assertEqual (ar[0][0], oval)
  668. self.assertEqual (ar[2][3], oval)
  669. self.assertEqual (ar[3][6], oval)
  670. self.assertEqual (ar[8][9], oval)
  671. self.assertEqual (ar[9][9], oval)
  672. #print "replace end"
  673. def test_extract (self):
  674. #print "extract start"
  675. for bpp in (8, 16, 24, 32):
  676. sf = pygame.Surface ((10, 10), 0, bpp)
  677. sf.fill ((0, 0, 255))
  678. sf.fill ((255, 0, 0), (2, 2, 6, 6))
  679. white = sf.map_rgb ((255, 255, 255))
  680. black = sf.map_rgb ((0, 0, 0))
  681. ar = pygame.PixelArray (sf)
  682. newar = ar.extract ((255, 0, 0))
  683. self.assertEqual (newar[0][0], black)
  684. self.assertEqual (newar[1][0], black)
  685. self.assertEqual (newar[2][3], white)
  686. self.assertEqual (newar[3][6], white)
  687. self.assertEqual (newar[8][9], black)
  688. self.assertEqual (newar[9][9], black)
  689. newar = ar.extract ((255, 0, 0), weights=(10, 0.1, 50))
  690. self.assertEqual (newar[0][0], black)
  691. self.assertEqual (newar[1][0], black)
  692. self.assertEqual (newar[2][3], white)
  693. self.assertEqual (newar[3][6], white)
  694. self.assertEqual (newar[8][9], black)
  695. self.assertEqual (newar[9][9], black)
  696. #print "extract end"
  697. def test_2dslice_assignment (self):
  698. w = 2 * 5 * 8
  699. h = 3 * 5 * 9
  700. sf = pygame.Surface ((w, h), 0, 32)
  701. ar = pygame.PixelArray (sf)
  702. size = (w, h)
  703. strides = (1, w)
  704. offset = 0
  705. self._test_assignment (sf, ar, size, strides, offset)
  706. xslice = slice (None, None, 2)
  707. yslice = slice (None, None, 3)
  708. ar, size, strides, offset = self._array_slice (
  709. ar, size, (xslice, yslice), strides, offset)
  710. self._test_assignment (sf, ar, size, strides, offset)
  711. xslice = slice (5, None, 5)
  712. yslice = slice (5, None, 5)
  713. ar, size, strides, offset = self._array_slice (
  714. ar, size, (xslice, yslice), strides, offset)
  715. self._test_assignment (sf, ar, size, strides, offset)
  716. def _test_assignment (self, sf, ar, ar_size, ar_strides, ar_offset):
  717. self.assertEqual (ar.shape, ar_size)
  718. ar_w, ar_h = ar_size
  719. ar_xstride, ar_ystride = ar_strides
  720. sf_w, sf_h = sf.get_size ()
  721. black = pygame.Color ('black')
  722. color = pygame.Color (0, 0, 12)
  723. pxcolor = sf.map_rgb (color)
  724. sf.fill (black)
  725. for ar_x, ar_y in [(0, 0),
  726. (0, ar_h - 4),
  727. (ar_w - 3, 0),
  728. (0, ar_h - 1),
  729. (ar_w - 1, 0),
  730. (ar_w - 1, ar_h - 1)]:
  731. sf_offset = ar_offset + ar_x * ar_xstride + ar_y * ar_ystride
  732. sf_y = sf_offset // sf_w
  733. sf_x = sf_offset - sf_y * sf_w
  734. sf_posn = (sf_x, sf_y)
  735. sf_pix = sf.get_at (sf_posn)
  736. self.assertEqual (sf_pix, black,
  737. "at pixarr posn (%i, %i) (surf posn (%i, %i)): "
  738. "%s != %s" %
  739. (ar_x, ar_y, sf_x, sf_y, sf_pix, black))
  740. ar[ar_x, ar_y] = pxcolor
  741. sf_pix = sf.get_at (sf_posn)
  742. self.assertEqual (sf_pix, color,
  743. "at pixarr posn (%i, %i) (surf posn (%i, %i)): "
  744. "%s != %s" %
  745. (ar_x, ar_y, sf_x, sf_y, sf_pix, color))
  746. def _array_slice (self, ar, size, slices, strides, offset):
  747. ar = ar[slices]
  748. xslice, yslice = slices
  749. w, h = size
  750. xstart, xstop, xstep = xslice.indices(w)
  751. ystart, ystop, ystep = yslice.indices(h)
  752. w = (xstop - xstart + xstep - 1) // xstep
  753. h = (ystop - ystart + ystep - 1) // ystep
  754. xstride, ystride = strides
  755. offset += xstart * xstride + ystart * ystride
  756. xstride *= xstep
  757. ystride *= ystep
  758. return ar, (w, h), (xstride, ystride), offset
  759. def test_array_properties(self):
  760. # itemsize, ndim, shape, and strides.
  761. for bpp in [1, 2, 3, 4]:
  762. sf = pygame.Surface ((2, 2), 0, bpp * 8)
  763. ar = pygame.PixelArray (sf)
  764. self.assertEqual (ar.itemsize, bpp)
  765. for shape in [(4, 16), (5, 13)]:
  766. w, h = shape
  767. sf = pygame.Surface (shape, 0, 32)
  768. bpp = sf.get_bytesize ()
  769. pitch = sf.get_pitch ()
  770. ar = pygame.PixelArray (sf)
  771. self.assertEqual (ar.ndim, 2)
  772. self.assertEqual (ar.shape, shape)
  773. self.assertEqual (ar.strides, (bpp, pitch))
  774. ar2 = ar[::2,:]
  775. w2 = len(([0] * w)[::2])
  776. self.assertEqual (ar2.ndim, 2)
  777. self.assertEqual (ar2.shape, (w2, h))
  778. self.assertEqual (ar2.strides, (2 * bpp, pitch))
  779. ar2 = ar[:,::2]
  780. h2 = len(([0] * h)[::2])
  781. self.assertEqual (ar2.ndim, 2)
  782. self.assertEqual (ar2.shape, (w, h2))
  783. self.assertEqual (ar2.strides, (bpp, 2 * pitch))
  784. ar2 = ar[1]
  785. self.assertEqual (ar2.ndim, 1)
  786. self.assertEqual (ar2.shape, (h,))
  787. self.assertEqual (ar2.strides, (pitch,))
  788. ar2 = ar[:,1]
  789. self.assertEqual (ar2.ndim, 1)
  790. self.assertEqual (ar2.shape, (w,))
  791. self.assertEqual (ar2.strides, (bpp,))
  792. def test_self_assign(self):
  793. # This differs from NumPy arrays.
  794. w = 10
  795. max_x = w - 1
  796. h = 20
  797. max_y = h - 1
  798. for bpp in [1, 2, 3, 4]:
  799. sf = pygame.Surface ((w, h), 0, bpp * 8)
  800. ar = pygame.PixelArray (sf)
  801. for i in range (w * h):
  802. ar[i % w, i // w] = i
  803. ar[:,:] = ar[::-1,:]
  804. for i in range (w * h):
  805. self.assertEqual (ar[max_x - i % w, i // w], i)
  806. ar = pygame.PixelArray (sf)
  807. for i in range (w * h):
  808. ar[i % w, i // w] = i
  809. ar[:,:] = ar[:,::-1]
  810. for i in range (w * h):
  811. self.assertEqual (ar[i % w, max_y - i // w ], i)
  812. ar = pygame.PixelArray (sf)
  813. for i in range(w * h):
  814. ar[i % w, i // w] = i
  815. ar[:,:] = ar[::-1,::-1]
  816. for i in range (w * h):
  817. self.assertEqual (ar[max_x - i % w, max_y - i // w], i)
  818. def test_color_value (self):
  819. # Confirm that a PixelArray slice assignment distinguishes between
  820. # pygame.Color and tuple objects as single (r, g, b[, a]) colors
  821. # and other sequences as sequences of colors to be treated as
  822. # slices.
  823. sf = pygame.Surface ((5, 5), 0, 32)
  824. ar = pygame.PixelArray (sf)
  825. index = slice(None, None, 1)
  826. ar.__setitem__ (index, (1, 2, 3))
  827. self.assertEqual (ar[0, 0], sf.map_rgb ((1, 2, 3)))
  828. ar.__setitem__ (index, pygame.Color (10, 11, 12))
  829. self.assertEqual (ar[0, 0], sf.map_rgb ((10, 11, 12)))
  830. self.assertRaises (ValueError, ar.__setitem__, index, (1, 2, 3, 4, 5))
  831. self.assertRaises (ValueError, ar.__setitem__, (index, index),
  832. (1, 2, 3, 4, 5))
  833. self.assertRaises (ValueError, ar.__setitem__, index, [1, 2, 3])
  834. self.assertRaises (ValueError, ar.__setitem__, (index, index),
  835. [1, 2, 3])
  836. sf = pygame.Surface ((3, 3), 0, 32)
  837. ar = pygame.PixelArray (sf)
  838. ar[:] = (20, 30, 40)
  839. self.assertEqual (ar[0, 0], sf.map_rgb ((20, 30, 40)))
  840. ar[:] = [20, 30, 40]
  841. self.assertEqual (ar[0, 0], 20)
  842. self.assertEqual (ar[1, 0], 30)
  843. self.assertEqual (ar[2, 0], 40)
  844. def test_transpose (self):
  845. # PixelArray.transpose(): swap axis on a 2D array, add a length
  846. # 1 x axis to a 1D array.
  847. sf = pygame.Surface ((3, 7), 0, 32)
  848. ar = pygame.PixelArray (sf)
  849. w, h = ar.shape
  850. dx, dy = ar.strides
  851. for i in range (w * h):
  852. x = i % w
  853. y = i // w
  854. ar[x, y] = i
  855. ar_t = ar.transpose()
  856. self.assertEqual (ar_t.shape, (h, w))
  857. self.assertEqual (ar_t.strides, (dy, dx))
  858. for i in range (w * h):
  859. x = i % w
  860. y = i // w
  861. self.assertEqual (ar_t[y, x], ar[x, y])
  862. ar1D = ar[0]
  863. ar2D = ar1D.transpose()
  864. self.assertEqual (ar2D.shape, (1, h))
  865. for y in range (h):
  866. self.assertEqual (ar1D[y], ar2D[0, y])
  867. ar1D = ar[:,0]
  868. ar2D = ar1D.transpose()
  869. self.assertEqual (ar2D.shape, (1, w))
  870. for x in range (2):
  871. self.assertEqual (ar1D[x], ar2D[0, x])
  872. def test_length_1_dimension_broadcast (self):
  873. w = 5
  874. sf = pygame.Surface ((w, w), 0, 32)
  875. ar = pygame.PixelArray (sf)
  876. # y-axis broadcast.
  877. sf_x = pygame.Surface ((w, 1), 0, 32)
  878. ar_x = pygame.PixelArray (sf_x)
  879. for i in range (w):
  880. ar_x[i, 0] = (w + 1) * 10
  881. ar[...] = ar_x
  882. for y in range (w):
  883. for x in range (w):
  884. self.assertEqual (ar[x, y], ar_x[x, 0])
  885. # x-axis broadcast.
  886. ar[...] = 0
  887. sf_y = pygame.Surface ((1, w), 0, 32)
  888. ar_y = pygame.PixelArray (sf_y)
  889. for i in range (w):
  890. ar_y[0, i] = (w + 1) * 10
  891. ar[...] = ar_y
  892. for x in range (w):
  893. for y in range (w):
  894. self.assertEqual (ar[x, y], ar_y[0, y])
  895. # (1, 1) array broadcast.
  896. ar[...] = 0
  897. sf_1px = pygame.Surface ((1, 1), 0, 32)
  898. ar_1px = pygame.PixelArray (sf_1px)
  899. ar_1px[0, 0] = 42 # Well it had to show up somewhere.
  900. ar[...] = ar_1px
  901. for y in range (w):
  902. for x in range (w):
  903. self.assertEqual (ar[x, y], 42)
  904. def test_assign_size_mismatch (self):
  905. sf = pygame.Surface ((7, 11), 0, 32)
  906. ar = pygame.PixelArray (sf)
  907. self.assertRaises (ValueError, ar.__setitem__, Ellipsis, ar[:, 0:2])
  908. self.assertRaises (ValueError, ar.__setitem__, Ellipsis, ar[0:2, :])
  909. def test_repr (self):
  910. # Python 3.x bug: the tp_repr slot function returned NULL instead
  911. # of a Unicode string, triggering an exception.
  912. sf = pygame.Surface ((3, 1), pygame.SRCALPHA, 16)
  913. ar = pygame.PixelArray(sf)
  914. ar[...] = 42
  915. pixel = sf.get_at_mapped ((0, 0))
  916. self.assertEqual(repr (ar),
  917. type (ar).__name__ + "([\n [42, 42, 42]]\n)")
  918. class PixelArrayArrayInterfaceTest(unittest.TestCase, TestMixin):
  919. @unittest.skipIf(IS_PYPY, 'skipping for PyPy (why?)')
  920. def test_basic (self):
  921. # Check unchanging fields.
  922. sf = pygame.Surface ((2, 2), 0, 32)
  923. ar = pygame.PixelArray (sf)
  924. ai = arrinter.ArrayInterface (ar)
  925. self.assertEqual (ai.two, 2)
  926. self.assertEqual (ai.typekind, 'u')
  927. self.assertEqual (ai.nd, 2)
  928. self.assertEqual (ai.data, ar._pixels_address)
  929. @unittest.skipIf(IS_PYPY, 'skipping for PyPy (why?)')
  930. def test_shape(self):
  931. for shape in [[4, 16], [5, 13]]:
  932. w, h = shape
  933. sf = pygame.Surface (shape, 0, 32)
  934. ar = pygame.PixelArray (sf)
  935. ai = arrinter.ArrayInterface (ar)
  936. ai_shape = [ai.shape[i] for i in range(ai.nd)]
  937. self.assertEqual (ai_shape, shape)
  938. ar2 = ar[::2,:]
  939. ai2 = arrinter.ArrayInterface (ar2)
  940. w2 = len(([0] * w)[::2])
  941. ai_shape = [ai2.shape[i] for i in range(ai2.nd)]
  942. self.assertEqual (ai_shape, [w2, h])
  943. ar2 = ar[:,::2]
  944. ai2 = arrinter.ArrayInterface (ar2)
  945. h2 = len(([0] * h)[::2])
  946. ai_shape = [ai2.shape[i] for i in range(ai2.nd)]
  947. self.assertEqual (ai_shape, [w, h2])
  948. @unittest.skipIf(IS_PYPY, 'skipping for PyPy (why?)')
  949. def test_itemsize (self):
  950. for bytes_per_pixel in range(1, 5):
  951. bits_per_pixel = 8 * bytes_per_pixel
  952. sf = pygame.Surface ((2, 2), 0, bits_per_pixel)
  953. ar = pygame.PixelArray (sf)
  954. ai = arrinter.ArrayInterface (ar)
  955. self.assertEqual (ai.itemsize, bytes_per_pixel)
  956. @unittest.skipIf(IS_PYPY, 'skipping for PyPy (why?)')
  957. def test_flags (self):
  958. aim = arrinter
  959. common_flags = (aim.PAI_NOTSWAPPED | aim.PAI_WRITEABLE |
  960. aim.PAI_ALIGNED)
  961. s = pygame.Surface ((10, 2), 0, 32)
  962. ar = pygame.PixelArray (s)
  963. ai = aim.ArrayInterface (ar)
  964. self.assertEqual (ai.flags, common_flags | aim.PAI_FORTRAN)
  965. ar2 = ar[::2,:]
  966. ai = aim.ArrayInterface (ar2)
  967. self.assertEqual (ai.flags, common_flags)
  968. s = pygame.Surface ((8, 2), 0, 24)
  969. ar = pygame.PixelArray (s)
  970. ai = aim.ArrayInterface (ar)
  971. self.assertEqual (ai.flags, common_flags | aim.PAI_FORTRAN)
  972. s = pygame.Surface ((7, 2), 0, 24)
  973. ar = pygame.PixelArray (s)
  974. ai = aim.ArrayInterface (ar)
  975. self.assertEqual (ai.flags, common_flags)
  976. def test_slicing (self):
  977. # This will implicitly test data and strides fields.
  978. #
  979. # Need an 8 bit test surfaces because pixelcopy.make_surface
  980. # returns an 8 bit surface for a 2d array.
  981. factors = [7, 3, 11]
  982. w = reduce (operator.mul, factors, 1)
  983. h = 13
  984. sf = pygame.Surface ((w, h), 0, 8)
  985. color = sf.map_rgb ((1, 17, 128))
  986. ar = pygame.PixelArray (sf)
  987. for f in factors[:-1]:
  988. w = w // f
  989. sf.fill ((0, 0, 0))
  990. ar = ar[f:f + w,:]
  991. ar[0][0] = color
  992. ar[-1][-2] = color
  993. ar[0][-3] = color
  994. sf2 = ar.make_surface ()
  995. sf3 = pygame.pixelcopy.make_surface (ar)
  996. self.assert_surfaces_equal (sf3, sf2)
  997. h = reduce (operator.mul, factors, 1)
  998. w = 13
  999. sf = pygame.Surface ((w, h), 0, 8)
  1000. color = sf.map_rgb ((1, 17, 128))
  1001. ar = pygame.PixelArray (sf)
  1002. for f in factors[:-1]:
  1003. h = h // f
  1004. sf.fill ((0, 0, 0))
  1005. ar = ar[:,f:f + h]
  1006. ar[0][0] = color
  1007. ar[-1][-2] = color
  1008. ar[0][-3] = color
  1009. sf2 = ar.make_surface ()
  1010. sf3 = pygame.pixelcopy.make_surface (ar)
  1011. self.assert_surfaces_equal (sf3, sf2)
  1012. w = 20
  1013. h = 10
  1014. sf = pygame.Surface ((w, h), 0, 8)
  1015. color = sf.map_rgb ((1, 17, 128))
  1016. ar = pygame.PixelArray (sf)
  1017. for slices in [(slice (w), slice (h)),
  1018. (slice (0, w, 2), slice (h)),
  1019. (slice (0, w, 3), slice (h)),
  1020. (slice (w), slice (0, h, 2)),
  1021. (slice (w), slice (0, h, 3)),
  1022. (slice (0, w, 2), slice (0, h, 2)),
  1023. (slice (0, w, 3), slice (0, h, 3)),
  1024. ]:
  1025. sf.fill ((0, 0, 0))
  1026. ar2 = ar[slices]
  1027. ar2[0][0] = color
  1028. ar2[-1][-2] = color
  1029. ar2[0][-3] = color
  1030. sf2 = ar2.make_surface ()
  1031. sf3 = pygame.pixelcopy.make_surface (ar2)
  1032. self.assert_surfaces_equal (sf3, sf2)
  1033. @unittest.skipIf(not pygame.HAVE_NEWBUF, 'newbuf not implemented')
  1034. class PixelArrayNewBufferTest(unittest.TestCase, TestMixin):
  1035. if pygame.HAVE_NEWBUF:
  1036. from pygame.tests.test_utils import buftools
  1037. bitsize_to_format = {8: 'B', 16: '=H', 24: '3x', 32: '=I'}
  1038. def test_newbuf_2D (self):
  1039. buftools = self.buftools
  1040. Importer = buftools.Importer
  1041. for bit_size in [8, 16, 24, 32]:
  1042. s = pygame.Surface ((10, 2), 0, bit_size)
  1043. ar = pygame.PixelArray (s)
  1044. format = self.bitsize_to_format[bit_size]
  1045. itemsize = ar.itemsize
  1046. shape = ar.shape
  1047. w, h = shape
  1048. strides = ar.strides
  1049. length = w * h * itemsize
  1050. imp = Importer (ar, buftools.PyBUF_FULL)
  1051. self.assertTrue (imp.obj, ar)
  1052. self.assertEqual (imp.len, length)
  1053. self.assertEqual (imp.ndim, 2)
  1054. self.assertEqual (imp.itemsize, itemsize)
  1055. self.assertEqual (imp.format, format)
  1056. self.assertFalse (imp.readonly)
  1057. self.assertEqual (imp.shape, shape)
  1058. self.assertEqual (imp.strides, strides)
  1059. self.assertTrue (imp.suboffsets is None)
  1060. self.assertEqual (imp.buf, s._pixels_address)
  1061. s = pygame.Surface ((8, 16), 0, 32)
  1062. ar = pygame.PixelArray (s)
  1063. format = self.bitsize_to_format[s.get_bitsize ()]
  1064. itemsize = ar.itemsize
  1065. shape = ar.shape
  1066. w, h = shape
  1067. strides = ar.strides
  1068. length = w * h * itemsize
  1069. imp = Importer (ar, buftools.PyBUF_SIMPLE)
  1070. self.assertTrue (imp.obj, ar)
  1071. self.assertEqual (imp.len, length)
  1072. self.assertEqual (imp.ndim, 0)
  1073. self.assertEqual (imp.itemsize, itemsize)
  1074. self.assertTrue (imp.format is None)
  1075. self.assertFalse (imp.readonly)
  1076. self.assertTrue (imp.shape is None)
  1077. self.assertTrue (imp.strides is None)
  1078. self.assertTrue (imp.suboffsets is None)
  1079. self.assertEqual (imp.buf, s._pixels_address)
  1080. imp = Importer (ar, buftools.PyBUF_FORMAT)
  1081. self.assertEqual (imp.ndim, 0)
  1082. self.assertEqual (imp.format, format)
  1083. imp = Importer (ar, buftools.PyBUF_WRITABLE)
  1084. self.assertEqual (imp.ndim, 0)
  1085. self.assertTrue (imp.format is None)
  1086. imp = Importer (ar, buftools.PyBUF_F_CONTIGUOUS)
  1087. self.assertEqual (imp.ndim, 2)
  1088. self.assertTrue (imp.format is None)
  1089. self.assertEqual (imp.shape, shape)
  1090. self.assertEqual (imp.strides, strides)
  1091. imp = Importer (ar, buftools.PyBUF_ANY_CONTIGUOUS)
  1092. self.assertEqual (imp.ndim, 2)
  1093. self.assertTrue (imp.format is None)
  1094. self.assertEqual (imp.shape, shape)
  1095. self.assertEqual (imp.strides, strides)
  1096. self.assertRaises (BufferError, Importer, ar,
  1097. buftools.PyBUF_C_CONTIGUOUS)
  1098. self.assertRaises (BufferError, Importer, ar, buftools.PyBUF_ND)
  1099. ar_sliced = ar[:,::2]
  1100. format = self.bitsize_to_format[s.get_bitsize ()]
  1101. itemsize = ar_sliced.itemsize
  1102. shape = ar_sliced.shape
  1103. w, h = shape
  1104. strides = ar_sliced.strides
  1105. length = w * h * itemsize
  1106. imp = Importer (ar_sliced, buftools.PyBUF_STRIDED)
  1107. self.assertEqual (imp.len, length)
  1108. self.assertEqual (imp.ndim, 2)
  1109. self.assertEqual (imp.itemsize, itemsize)
  1110. self.assertTrue (imp.format is None)
  1111. self.assertFalse (imp.readonly)
  1112. self.assertEqual (imp.shape, shape)
  1113. self.assertEqual (imp.strides, strides)
  1114. self.assertEqual (imp.buf, s._pixels_address)
  1115. self.assertRaises (BufferError, Importer, ar_sliced,
  1116. buftools.PyBUF_SIMPLE)
  1117. self.assertRaises (BufferError, Importer, ar_sliced,
  1118. buftools.PyBUF_ND)
  1119. self.assertRaises (BufferError, Importer, ar_sliced,
  1120. buftools.PyBUF_C_CONTIGUOUS)
  1121. self.assertRaises (BufferError, Importer, ar_sliced,
  1122. buftools.PyBUF_F_CONTIGUOUS)
  1123. self.assertRaises (BufferError, Importer, ar_sliced,
  1124. buftools.PyBUF_ANY_CONTIGUOUS)
  1125. ar_sliced = ar[::2,:]
  1126. format = self.bitsize_to_format[s.get_bitsize ()]
  1127. itemsize = ar_sliced.itemsize
  1128. shape = ar_sliced.shape
  1129. w, h = shape
  1130. strides = ar_sliced.strides
  1131. length = w * h * itemsize
  1132. imp = Importer (ar_sliced, buftools.PyBUF_STRIDED)
  1133. self.assertEqual (imp.len, length)
  1134. self.assertEqual (imp.ndim, 2)
  1135. self.assertEqual (imp.itemsize, itemsize)
  1136. self.assertTrue (imp.format is None)
  1137. self.assertFalse (imp.readonly)
  1138. self.assertEqual (imp.shape, shape)
  1139. self.assertEqual (imp.strides, strides)
  1140. self.assertEqual (imp.buf, s._pixels_address)
  1141. self.assertRaises (BufferError, Importer, ar_sliced,
  1142. buftools.PyBUF_SIMPLE)
  1143. self.assertRaises (BufferError, Importer, ar_sliced,
  1144. buftools.PyBUF_ND)
  1145. self.assertRaises (BufferError, Importer, ar_sliced,
  1146. buftools.PyBUF_C_CONTIGUOUS)
  1147. self.assertRaises (BufferError, Importer, ar_sliced,
  1148. buftools.PyBUF_F_CONTIGUOUS)
  1149. self.assertRaises (BufferError, Importer, ar_sliced,
  1150. buftools.PyBUF_ANY_CONTIGUOUS)
  1151. s2 = s.subsurface ((2, 3, 5, 7))
  1152. ar = pygame.PixelArray (s2)
  1153. format = self.bitsize_to_format[s.get_bitsize ()]
  1154. itemsize = ar.itemsize
  1155. shape = ar.shape
  1156. w, h = shape
  1157. strides = ar.strides
  1158. length = w * h * itemsize
  1159. imp = Importer (ar, buftools.PyBUF_STRIDES)
  1160. self.assertTrue (imp.obj, ar)
  1161. self.assertEqual (imp.len, length)
  1162. self.assertEqual (imp.ndim, 2)
  1163. self.assertEqual (imp.itemsize, itemsize)
  1164. self.assertTrue (imp.format is None)
  1165. self.assertFalse (imp.readonly)
  1166. self.assertEqual (imp.shape, shape)
  1167. self.assertEqual (imp.strides, strides)
  1168. self.assertTrue (imp.suboffsets is None)
  1169. self.assertEqual (imp.buf, s2._pixels_address)
  1170. self.assertRaises (BufferError, Importer, ar, buftools.PyBUF_SIMPLE)
  1171. self.assertRaises (BufferError, Importer, ar, buftools.PyBUF_FORMAT)
  1172. self.assertRaises (BufferError, Importer, ar, buftools.PyBUF_WRITABLE)
  1173. self.assertRaises (BufferError, Importer, ar, buftools.PyBUF_ND)
  1174. self.assertRaises (BufferError, Importer, ar,
  1175. buftools.PyBUF_C_CONTIGUOUS)
  1176. self.assertRaises (BufferError, Importer, ar,
  1177. buftools.PyBUF_F_CONTIGUOUS)
  1178. self.assertRaises (BufferError, Importer, ar,
  1179. buftools.PyBUF_ANY_CONTIGUOUS)
  1180. def test_newbuf_1D(self):
  1181. buftools = self.buftools
  1182. Importer = buftools.Importer
  1183. s = pygame.Surface ((2, 16), 0, 32)
  1184. ar_2D = pygame.PixelArray (s)
  1185. x = 0
  1186. ar = ar_2D[x]
  1187. format = self.bitsize_to_format[s.get_bitsize ()]
  1188. itemsize = ar.itemsize
  1189. shape = ar.shape
  1190. h = shape[0]
  1191. strides = ar.strides
  1192. length = h * itemsize
  1193. buf = s._pixels_address + x * itemsize
  1194. imp = Importer (ar, buftools.PyBUF_STRIDES)
  1195. self.assertTrue (imp.obj, ar)
  1196. self.assertEqual (imp.len, length)
  1197. self.assertEqual (imp.ndim, 1)
  1198. self.assertEqual (imp.itemsize, itemsize)
  1199. self.assertTrue (imp.format is None)
  1200. self.assertFalse (imp.readonly)
  1201. self.assertEqual (imp.shape, shape)
  1202. self.assertEqual (imp.strides, strides)
  1203. self.assertTrue (imp.suboffsets is None)
  1204. self.assertEqual (imp.buf, buf)
  1205. imp = Importer (ar, buftools.PyBUF_FULL)
  1206. self.assertEqual (imp.ndim, 1)
  1207. self.assertEqual (imp.format, format)
  1208. self.assertRaises (BufferError, Importer, ar,
  1209. buftools.PyBUF_SIMPLE)
  1210. self.assertRaises (BufferError, Importer, ar,
  1211. buftools.PyBUF_FORMAT)
  1212. self.assertRaises (BufferError, Importer, ar,
  1213. buftools.PyBUF_WRITABLE)
  1214. self.assertRaises (BufferError, Importer, ar,
  1215. buftools.PyBUF_ND)
  1216. self.assertRaises (BufferError, Importer, ar,
  1217. buftools.PyBUF_C_CONTIGUOUS)
  1218. self.assertRaises (BufferError, Importer, ar,
  1219. buftools.PyBUF_F_CONTIGUOUS)
  1220. self.assertRaises (BufferError, Importer, ar,
  1221. buftools.PyBUF_ANY_CONTIGUOUS)
  1222. y = 10
  1223. ar = ar_2D[:,y]
  1224. shape = ar.shape
  1225. w = shape[0]
  1226. strides = ar.strides
  1227. length = w * itemsize
  1228. buf = s._pixels_address + y * s.get_pitch()
  1229. imp = Importer (ar, buftools.PyBUF_FULL)
  1230. self.assertEqual (imp.len, length)
  1231. self.assertEqual (imp.ndim, 1)
  1232. self.assertEqual (imp.itemsize, itemsize)
  1233. self.assertEqual (imp.format, format)
  1234. self.assertFalse (imp.readonly)
  1235. self.assertEqual (imp.shape, shape)
  1236. self.assertEqual (imp.strides, strides)
  1237. self.assertEqual (imp.buf, buf)
  1238. self.assertTrue (imp.suboffsets is None)
  1239. imp = Importer (ar, buftools.PyBUF_SIMPLE)
  1240. self.assertEqual (imp.len, length)
  1241. self.assertEqual (imp.ndim, 0)
  1242. self.assertEqual (imp.itemsize, itemsize)
  1243. self.assertTrue (imp.format is None)
  1244. self.assertFalse (imp.readonly)
  1245. self.assertTrue (imp.shape is None)
  1246. self.assertTrue (imp.strides is None)
  1247. imp = Importer (ar, buftools.PyBUF_ND)
  1248. self.assertEqual (imp.len, length)
  1249. self.assertEqual (imp.ndim, 1)
  1250. self.assertEqual (imp.itemsize, itemsize)
  1251. self.assertTrue (imp.format is None)
  1252. self.assertFalse (imp.readonly)
  1253. self.assertEqual (imp.shape, shape)
  1254. self.assertTrue (imp.strides is None)
  1255. imp = Importer (ar, buftools.PyBUF_C_CONTIGUOUS)
  1256. self.assertEqual (imp.ndim, 1)
  1257. imp = Importer (ar, buftools.PyBUF_F_CONTIGUOUS)
  1258. self.assertEqual (imp.ndim, 1)
  1259. imp = Importer (ar, buftools.PyBUF_ANY_CONTIGUOUS)
  1260. self.assertEqual (imp.ndim, 1)
  1261. if __name__ == '__main__':
  1262. unittest.main()