import unittest
from pyplanetarium import SpotShape, SpotId, Transform, Canvas, ImageFormat, Window
class CanvasCase(unittest.TestCase):
def test_init(self) -> None:
width = 1024
height = 768
canvas = Canvas.new(width, height)
self.assertIsInstance(canvas, Canvas)
self.assertEqual(canvas.dimensions(), (width, height))
self.assertEqual(str(canvas), "Canvas(1024, 768)")
self.assertEqual(repr(canvas), "Canvas(1024, 768)")
canvas.set_background(1000)
canvas.clear()
def test_init_err(self) -> None:
with self.assertRaises(TypeError):
Canvas.new()
with self.assertRaises(TypeError):
Canvas.new(100)
with self.assertRaises(TypeError):
Canvas.new((100, 200))
def test_enum_repr(self) -> None:
self.assertEqual(str(ImageFormat.PngGamma8Bpp), "PngGamma8Bpp")
self.assertEqual(repr(ImageFormat.PngGamma8Bpp), "PngGamma8Bpp")
self.assertEqual(repr(ImageFormat.PngLinear16Bpp), "PngLinear16Bpp")
self.assertEqual(repr(ImageFormat.RawGamma8Bpp), "RawGamma8Bpp")
self.assertEqual(repr(ImageFormat.RawLinear10BppLE), "RawLinear10BppLE")
self.assertEqual(repr(ImageFormat.RawLinear12BppLE), "RawLinear12BppLE")
def test_enum_hash(self) -> None:
self.assertEqual(hash(ImageFormat.PngGamma8Bpp), 3)
formats = {}
formats[ImageFormat.PngGamma8Bpp] = "PNG8"
formats[ImageFormat.PngLinear16Bpp] = "PNG16"
self.assertEqual(formats[ImageFormat.PngGamma8Bpp], "PNG8")
self.assertEqual(formats[ImageFormat.PngLinear16Bpp], "PNG16")
def test_draw_spots(self) -> None:
shape1 = SpotShape().scale(3.5)
shape2 = SpotShape(5.5).stretch(1.5, 1.0).rotate(45)
width = 1024
height = 768
canvas = Canvas.new(width, height)
self.assertEqual(canvas.dimensions(), (width, height))
spot1 = canvas.add_spot((100.5, 200.7), shape1, 0.8)
self.assertIsInstance(spot1, SpotId)
self.assertEqual(str(spot1), "SpotId(0)")
spot2 = canvas.add_spot((400.5, 600.7), shape2, 0.6)
self.assertIsInstance(spot2, SpotId)
self.assertEqual(repr(spot2), "SpotId(1)")
self.assertNotEqual(spot1, spot2)
canvas.set_background(int(0.1 * Canvas.PIXEL_MAX))
canvas.draw()
def test_move_spots(self) -> None:
shape1 = SpotShape().scale(3.5)
shape2 = SpotShape(5.5).stretch(1.0, 1.5).rotate(30)
width = 1024
height = 768
canvas = Canvas.new(width, height)
spot1 = canvas.add_spot((100.5, 200.7), shape1, 0.8)
spot2 = canvas.add_spot((400.5, 600.7), shape2, 0.6)
pos1 = canvas.spot_position(spot1)
pos2 = canvas.spot_position(spot2)
assert pos1 is not None
assert pos2 is not None
self.assertAlmostEqual(pos1[0], 100.5, 4)
self.assertAlmostEqual(pos2[1], 600.7, 4)
int1 = canvas.spot_intensity(spot1)
int2 = canvas.spot_intensity(spot2)
assert int1 is not None
assert int2 is not None
self.assertAlmostEqual(int1, 0.8, 4)
self.assertAlmostEqual(int2, 0.6, 4)
canvas.set_spot_offset(spot2, (5.5, -7.0))
canvas.set_spot_illumination(spot2, 0.5)
canvas.set_background(int(0.2 * Canvas.PIXEL_MAX))
canvas.set_brightness(1.3)
pos2 = canvas.spot_position(spot2)
assert pos2 is not None
self.assertAlmostEqual(pos2[0], 400.5 + 5.5, 4)
self.assertAlmostEqual(pos2[1], 600.7 - 7.0, 4)
int1 = canvas.spot_intensity(spot1)
int2 = canvas.spot_intensity(spot2)
assert int1 is not None
assert int2 is not None
self.assertAlmostEqual(int1, 0.8 * 1.3, 4)
self.assertAlmostEqual(int2, 0.6 * 0.5 * 1.3, 4)
canvas.draw()
def test_view_transform(self) -> None:
shape1 = SpotShape([[1, -0.5], [0.5, 1.5]])
shape2 = SpotShape(5.5).stretch(1.0, 1.5).rotate(30)
width = 1024
height = 768
canvas = Canvas.new(width, height)
spot1 = canvas.add_spot((100.5, 200.25), shape1, 0.8)
spot2 = canvas.add_spot((400.5, 600.75), shape2, 0.6)
pos1 = canvas.spot_position(spot1)
pos2 = canvas.spot_position(spot2)
assert pos1 is not None
assert pos2 is not None
self.assertAlmostEqual(pos1[0], 100.5, 4)
self.assertAlmostEqual(pos1[1], 200.25, 4)
self.assertAlmostEqual(pos2[0], 400.5, 4)
self.assertAlmostEqual(pos2[1], 600.75, 4)
canvas.set_view_transform(Transform())
canvas.set_spot_offset(spot2, (5.5, -7.0))
pos2 = canvas.spot_position(spot2)
assert pos2 is not None
self.assertAlmostEqual(pos2[0], 400.5 + 5.5, 4)
self.assertAlmostEqual(pos2[1], 600.75 - 7.0, 4)
canvas.set_view_transform(Transform((-10, 25)))
pos1 = canvas.spot_position(spot1)
pos2 = canvas.spot_position(spot2)
assert pos1 is not None
assert pos2 is not None
self.assertAlmostEqual(pos1[0], 100.5 - 10, 4)
self.assertAlmostEqual(pos1[1], 200.25 + 25, 4)
self.assertAlmostEqual(pos2[0], 400.5 + 5.5 - 10, 4)
self.assertAlmostEqual(pos2[1], 600.75 - 7.0 + 25, 4)
xfrm = Transform((-100, 200)).rotate(45).compose(Transform([[-1, 0], [0, 1]]))
canvas.set_view_transform(xfrm)
pos1 = canvas.spot_position(spot1)
pos2 = canvas.spot_position(spot2)
assert pos1 is not None
assert pos2 is not None
self.assertAlmostEqual(pos1[0], 282.6659, 4)
self.assertAlmostEqual(pos1[1], 283.373, 4)
self.assertAlmostEqual(pos2[0], 344.8913, 4)
self.assertAlmostEqual(pos2[1], 777.6407, 4)
canvas.draw()
def test_spot_hash(self) -> None:
canvas = Canvas.new(10, 10)
spot1 = canvas.add_spot((1.0, 1.0), SpotShape(), 0.8)
spot2 = canvas.add_spot((2.0, 2.0), SpotShape(2.0), 0.6)
self.assertEqual(hash(spot1), 0)
self.assertEqual(hash(spot2), 1)
spots = {}
spots[spot1] = "Spot1"
spots[spot2] = "Spot2"
self.assertEqual(spots[spot1], "Spot1")
self.assertEqual(spots[spot2], "Spot2")
def test_export_images(self) -> None:
shape1 = SpotShape().scale(3.5)
shape2 = SpotShape().scale(5.5)
width = 256
height = 256
canvas = Canvas.new(width, height)
spot1 = canvas.add_spot((180.5, 150.7), shape1, 0.8)
spot2 = canvas.add_spot((100.5, 110.7), shape2, 0.6)
self.assertNotEqual(spot1, spot2)
canvas.set_background(5000)
canvas.draw()
raw8_bytes = canvas.export_image(ImageFormat.RawGamma8Bpp)
self.assertIsInstance(raw8_bytes, bytes)
self.assertEqual(len(raw8_bytes), 65536)
self.assertEqual(raw8_bytes[0], 78)
self.assertEqual(raw8_bytes[65535], 78)
raw10_bytes = canvas.export_image(ImageFormat.RawLinear10BppLE)
self.assertIsInstance(raw10_bytes, bytes)
self.assertEqual(len(raw10_bytes), 2 * 65536)
self.assertEqual(raw10_bytes[0], 78)
self.assertEqual(raw10_bytes[1], 0)
raw12_bytes = canvas.export_image(ImageFormat.RawLinear12BppLE)
self.assertIsInstance(raw12_bytes, bytes)
self.assertEqual(len(raw12_bytes), 2 * 65536)
self.assertEqual(raw12_bytes[0], 56)
self.assertEqual(raw12_bytes[1], 1)
png8_bytes = canvas.export_image(ImageFormat.PngGamma8Bpp)
self.assertIsInstance(png8_bytes, bytes)
self.assertEqual(len(png8_bytes), 1301)
png16_bytes = canvas.export_image(ImageFormat.PngLinear16Bpp)
self.assertIsInstance(png16_bytes, bytes)
self.assertEqual(len(png16_bytes), 2743)
def test_export_window_images(self) -> None:
shape1 = SpotShape().scale(3.5)
shape2 = SpotShape().scale(5.5)
width = 256
height = 256
canvas = Canvas.new(width, height)
spot1 = canvas.add_spot((180.5, 150.7), shape1, 0.8)
spot2 = canvas.add_spot((100.5, 110.7), shape2, 0.6)
self.assertNotEqual(spot1, spot2)
canvas.set_background(5000)
canvas.draw()
wnd1 = Window.new(32, 16).at(170, 140)
wnd2 = Window.new(32, 16).at(90, 100)
raw8_bytes = canvas.export_window_image(wnd1, ImageFormat.RawGamma8Bpp)
self.assertIsInstance(raw8_bytes, bytes)
self.assertEqual(len(raw8_bytes), 32 * 16)
raw10_bytes = canvas.export_window_image(wnd1, ImageFormat.RawLinear10BppLE)
self.assertIsInstance(raw10_bytes, bytes)
self.assertEqual(len(raw10_bytes), 2 * 32 * 16)
raw12_bytes = canvas.export_window_image(wnd2, ImageFormat.RawLinear12BppLE)
self.assertIsInstance(raw12_bytes, bytes)
self.assertEqual(len(raw12_bytes), 2 * 32 * 16)
png8_bytes = canvas.export_window_image(wnd1, ImageFormat.PngGamma8Bpp)
self.assertIsInstance(png8_bytes, bytes)
self.assertEqual(len(png8_bytes), 256)
png16_bytes = canvas.export_window_image(wnd2, ImageFormat.PngLinear16Bpp)
self.assertIsInstance(png16_bytes, bytes)
self.assertEqual(len(png16_bytes), 670)
def test_export_subsampled_images(self) -> None:
shape1 = SpotShape().scale(3.5)
shape2 = SpotShape().scale(5.5)
width = 256
height = 256
canvas = Canvas.new(width, height)
spot1 = canvas.add_spot((180.5, 150.7), shape1, 0.8)
spot2 = canvas.add_spot((100.5, 110.7), shape2, 0.6)
self.assertNotEqual(spot1, spot2)
canvas.set_background(5000)
canvas.draw()
raw8_bytes = canvas.export_subsampled_image((2, 2), ImageFormat.RawGamma8Bpp)
self.assertIsInstance(raw8_bytes, bytes)
self.assertEqual(len(raw8_bytes), 128 * 128)
raw10_bytes = canvas.export_subsampled_image(
(2, 2), ImageFormat.RawLinear10BppLE
)
self.assertIsInstance(raw10_bytes, bytes)
self.assertEqual(len(raw10_bytes), 2 * 128 * 128)
raw12_bytes = canvas.export_subsampled_image(
(4, 4), ImageFormat.RawLinear12BppLE
)
self.assertIsInstance(raw12_bytes, bytes)
self.assertEqual(len(raw12_bytes), 2 * 64 * 64)
png8_bytes = canvas.export_subsampled_image((2, 2), ImageFormat.PngGamma8Bpp)
self.assertIsInstance(png8_bytes, bytes)
self.assertEqual(len(png8_bytes), 430)
png16_bytes = canvas.export_subsampled_image((4, 4), ImageFormat.PngLinear16Bpp)
self.assertIsInstance(png16_bytes, bytes)
self.assertEqual(len(png16_bytes), 309)
def test_export_window_error(self) -> None:
canvas = Canvas.new(256, 256)
bad_wnd = Window.new(100, 100).at(170, 140)
with self.assertRaises(ValueError):
canvas.export_window_image(bad_wnd, ImageFormat.RawGamma8Bpp)
def test_export_subsampled_error(self) -> None:
canvas = Canvas.new(256, 256)
bad_factors = 0, 30
with self.assertRaises(ValueError):
canvas.export_subsampled_image(bad_factors, ImageFormat.RawGamma8Bpp)
if __name__ == "__main__":
unittest.main()