Checkpoint WIP for easier comparison to dhgr branch:

- naive version of NTSC artifacting, it uses a sliding 4-bit window to
  assign a nominal (D)HGR colour to each dot position.  A more
  sophisticated/correct implementation would model the YIQ signal
  directly.

- Switch DHGRBitmap implementation to use a 34-bit representation of
  the 4-byte tuple, comprised of a 3-bit header and footer, plus
  4*7=28-bit body.  The headers/footers account for the influence on
  neighbouring tuples from the 4-bit NTSC window.

- With this model each screen byte influences 13 pixels, so we need to
  precompute 2^26 edit distances for all possible (source, target)
  13-bit sequences.

- Checkpointing not-yet-working HGR implementation.

- Add new unit tests but not yet all passing due to refactoring
This commit is contained in:
kris
2019-07-02 22:40:50 +01:00
parent e2a8bd9b4d
commit 666272a8fc
9 changed files with 1268 additions and 367 deletions

View File

@ -4,6 +4,7 @@ import unittest
import numpy as np
import colours
import screen
@ -184,5 +185,411 @@ class TestDHGRBitmap(unittest.TestCase):
)
def binary(a):
return np.vectorize("{:032b}".format)(a)
class TestHGRBitmap(unittest.TestCase):
def setUp(self) -> None:
self.main = screen.MemoryMap(screen_page=1)
def test_pixel_packing_p0_p0(self):
# PDCCBBAA
self.main.page_offset[0, 0] = 0b01000011
# PGGFFEED
self.main.page_offset[0, 1] = 0b01000011
hgr = screen.HGRBitmap(
main_memory=self.main)
want = 0b1100000000111111000000001111
got = hgr.packed[0, 0]
self.assertEqual(
want, got, "\n%s\n%s" % (binary(want), binary(got))
)
def test_pixel_packing_p0_p1(self):
# PDCCBBAA
self.main.page_offset[0, 0] = 0b01000011
# PGGFFEED
self.main.page_offset[0, 1] = 0b11000011
hgr = screen.HGRBitmap(
main_memory=self.main)
want = 0b1000000001111111000000001111
got = hgr.packed[0, 0]
self.assertEqual(
want, got, "\n%s\n%s" % (binary(want), binary(got))
)
def test_pixel_packing_p1_p0(self):
# PDCCBBAA
self.main.page_offset[0, 0] = 0b11000011
# PGGFFEED
self.main.page_offset[0, 1] = 0b01000011
hgr = screen.HGRBitmap(
main_memory=self.main)
want = 0b1100000000111110000000011110
got = hgr.packed[0, 0]
self.assertEqual(
want, got, "\n%s\n%s" % (binary(want), binary(got))
)
def test_pixel_packing_p1_p1(self):
# PDCCBBAA
self.main.page_offset[0, 0] = 0b11000011
# PGGFFEED
self.main.page_offset[0, 1] = 0b11000011
hgr = screen.HGRBitmap(
main_memory=self.main)
want = 0b1000000001111110000000011110
got = hgr.packed[0, 0]
self.assertEqual(
want, got, "\n%s\n%s" % (binary(want), binary(got))
)
def test_pixel_packing_p1_promote_p0(self):
# PDCCBBAA
self.main.page_offset[0, 0] = 0b00000000
# PGGFFEED
self.main.page_offset[0, 1] = 0b01000000
# PDCCBBAA
self.main.page_offset[0, 2] = 0b10000000
hgr = screen.HGRBitmap(
main_memory=self.main)
want = 0b0000000000000000000000000001
got = hgr.packed[0, 1]
self.assertEqual(
want, got, "\n%s\n%s" % (binary(want), binary(got))
)
def test_pixel_packing_p1_promote_p1(self):
# PDCCBBAA
self.main.page_offset[0, 0] = 0b00000000
# PGGFFEED
self.main.page_offset[0, 1] = 0b11000000
# PDCCBBAA
self.main.page_offset[0, 2] = 0b10000000
hgr = screen.HGRBitmap(
main_memory=self.main)
want = 0b0000000000000000000000000001
got = hgr.packed[0, 1]
self.assertEqual(
want, got, "\n%s\n%s" % (binary(want), binary(got))
)
def testNominalColours(self):
# PDCCBBAA
self.main.page_offset[0, 0] = 0b01010101
# PGGFFEED
self.main.page_offset[0, 1] = 0b00101010
# PDCCBBAA
self.main.page_offset[0, 2] = 0b01010101
hgr = screen.HGRBitmap(
main_memory=self.main)
want = 0b000110011001100110011001100110011
got = hgr.packed[0, 0]
self.assertEqual(
want, got, "\n%s\n%s" % (binary(want), binary(got))
)
self.assertEqual(
(
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
colours.HGRColours.VIOLET,
),
colours.int34_to_nominal_colour_pixels(hgr.packed[0, 0],
colours.HGRColours)
)
# See Figure 8.15 from Sather, "Understanding the Apple IIe"
def testNominalColoursSather1(self):
# Extend violet into light blue
# PDCCBBAA
self.main.page_offset[0, 0] = 0b01000000
# PGGFFEED
self.main.page_offset[0, 1] = 0b10000000
hgr = screen.HGRBitmap(
main_memory=self.main)
self.assertEqual(
(
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.LIGHT_BLUE,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
),
colours.int28_to_nominal_colour_pixels(hgr.packed[0, 0],
colours.HGRColours)
)
def testNominalColoursSather2(self):
# Cut off blue with black to produce dark blue
# PDCCBBAA
self.main.page_offset[0, 0] = 0b11000000
# PGGFFEED
self.main.page_offset[0, 1] = 0b00000000
hgr = screen.HGRBitmap(
main_memory=self.main)
self.assertEqual(
(
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.DARK_BLUE,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
),
colours.int28_to_nominal_colour_pixels(hgr.packed[0, 0],
colours.HGRColours)
)
def testNominalColoursSather3(self):
# Cut off blue with green to produce aqua
# PDCCBBAA
self.main.page_offset[0, 0] = 0b11000000
# PGGFFEED
self.main.page_offset[0, 1] = 0b00000001
hgr = screen.HGRBitmap(
main_memory=self.main)
self.assertEqual(
(
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.AQUA,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
),
colours.int28_to_nominal_colour_pixels(hgr.packed[0, 0],
colours.HGRColours)
)
def testNominalColoursSather4(self):
# Cut off white with black to produce pink
# PDCCBBAA
self.main.page_offset[0, 0] = 0b11100000
# PGGFFEED
self.main.page_offset[0, 1] = 0b00000000
hgr = screen.HGRBitmap(
main_memory=self.main)
want = 0b0000000000000011100000000000
got = hgr.packed[0, 0]
self.assertEqual(
want, got, "\n%s\n%s" % (binary(want), binary(got))
)
# TODO: BROWN(0001)/VIOLET(1100) should reframe to PINK (1011)
self.assertEqual(
(
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.BROWN,
colours.HGRColours.VIOLET,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
),
colours.int28_to_nominal_colour_pixels(hgr.packed[0, 0],
colours.HGRColours)
)
def testNominalColoursSather5(self):
# Extend green into light brown
# PDCCBBAA
self.main.page_offset[0, 0] = 0b01000000
# PGGFFEED
self.main.page_offset[0, 1] = 0b10000000
hgr = screen.HGRBitmap(
main_memory=self.main)
want = 0b0000000000000111000000000000
got = hgr.packed[0, 0]
self.assertEqual(
want, got, "\n%s\n%s" % (binary(want), binary(got))
)
# TODO: LIGHT_BLUE should reframe to PINK (1011)
self.assertEqual(
(
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.LIGHT_BLUE,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
),
colours.int28_to_nominal_colour_pixels(hgr.packed[0, 0],
colours.HGRColours)
)
def testNominalColoursSather6(self):
# Cut off orange with black to produce dark brown
# PDCCBBAA
self.main.page_offset[0, 0] = 0b11000000
# PGGFFEED
self.main.page_offset[0, 1] = 0b00000000
hgr = screen.HGRBitmap(
main_memory=self.main)
want = 0b00000000000000010000000000000
got = hgr.packed[0, 0]
self.assertEqual(
want, got, "\n%s\n%s" % (binary(want), binary(got))
)
# TODO: DARK_BLUE should reframe to DARK_BROWN
self.assertEqual(
(
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.DARK_BLUE,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
),
colours.int28_to_nominal_colour_pixels(hgr.packed[0, 0],
colours.HGRColours)
)
def testNominalColoursSather7(self):
# Cut off orange with violet to produce pink
# PDCCBBAA
self.main.page_offset[0, 0] = 0b11000000
# PGGFFEED
self.main.page_offset[0, 1] = 0b00000001
hgr = screen.HGRBitmap(
main_memory=self.main)
want = 0b00000000000001110000000000000
got = hgr.packed[0, 0]
self.assertEqual(
want, got, "\n%s\n%s" % (binary(want), binary(got))
)
# TODO: AQUA should reframe to PINK
self.assertEqual(
(
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.AQUA,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
),
colours.int28_to_nominal_colour_pixels(hgr.packed[0, 0],
colours.HGRColours)
)
def testNominalColoursSather8(self):
# Cut off white with black to produce aqua
# PDCCBBAA
self.main.page_offset[0, 0] = 0b11100000
# PGGFFEED
self.main.page_offset[0, 1] = 0b00000000
hgr = screen.HGRBitmap(
main_memory=self.main)
want = 0b00000000000000011100000000000
got = hgr.packed[0, 0]
self.assertEqual(
want, got, "\n%s\n%s" % (binary(want), binary(got))
)
# TODO: BROWN/VIOLET should reframe to AQUA
self.assertEqual(
(
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.BROWN,
colours.HGRColours.VIOLET,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
colours.HGRColours.BLACK,
),
colours.int28_to_nominal_colour_pixels(
hgr.packed[0, 0], colours.HGRColours)
)
if __name__ == '__main__':
unittest.main()