Repository: briggySmalls/pyflipdot

Issue:
On larger signs 0,0 is displayed as 0,9
I have a 96x16 Hanover sign. This code works perfectly except that it starts on the 9 dot from the top. 

To replicate I push a numpy array that is only the first pixel as true. Such as: 

      [[ True False False ... False False False]
      [False False False ... False False False]
      [False False False ... False False False]
      ...
      [False False False ... False False False]
      [False False False ... False False False]
      [False False False ... False False False]]

The result is that the one dot is rendered mid sign instead of 0,0 as i would expect. 

Photo: 

![Screenshot from 2019-06-24 15-03-13](https://user-images.githubusercontent.com/18504/60048206-4004ee00-9691-11e9-8092-a51ed23cb217.png)

here it is using the textwriter.py to display the time: 
![Screenshot from 2019-06-24 15-03-23](https://user-images.githubusercontent.com/18504/60048227-4b581980-9691-11e9-926c-9ffc906b9d67.png)

Let me know if you have ideas on how to fix. I don't mind doing the work - but don't know where to start without starting from scratch. 

Thanks for the lib. it is much better than the alternatives ;)

Comments:

Patch:
diff --git a/docs/usage.rst b/docs/usage.rst
index 9b0494f..e840f22 100644
--- a/docs/usage.rst
+++ b/docs/usage.rst
@@ -32,6 +32,6 @@ Once you've confirmed this is working, you'll want to send specific images to a
     image[1::2, 1::2] = True
 
     # Write the image
-    controller.write(image)
+    controller.draw_image(image)
 
 Refer to the :ref:`api` for full documentation.
diff --git a/pyflipdot/data.py b/pyflipdot/data.py
index df3ccf7..b26b05f 100644
--- a/pyflipdot/data.py
+++ b/pyflipdot/data.py
@@ -148,10 +148,16 @@ class ImagePacket(Packet):
         message_image = np.zeros((data_rows, columns), dtype=bool)
         message_image[:rows, :columns] = image
 
-        # Flip image (we send column major, starting 'bottom left')
+        # Flip image vertically
+        # Our image is little-endian (0,0 contains least significant bit)
+        # Packbits expects array to be big-endian
         message_image = np.flipud(message_image)
 
-        # Flatten 'column major', so a whole column of pixels are sent together
+        # Interpret the boolean array as bits in a byte
         # Note: we 'view' as uin8 for numpy versions < 1.10 that don't accept
         # boolean arrays to packbits
-        return bytes(np.packbits(message_image.flatten('F').view(np.uint8)))
+        byte_values = np.packbits(message_image.view(np.uint8), axis=0)
+
+        # Flip vertically so that we send the least significant byte first
+        # Flatten 'column major', so a whole column of pixels are sent together
+        return bytes(np.flipud(byte_values).flatten("F"))


Test patch:
diff --git a/tests/test_data.py b/tests/test_data.py
index 791b2a0..011a49f 100644
--- a/tests/test_data.py
+++ b/tests/test_data.py
@@ -21,14 +21,10 @@ class TestPackets(object):
 
     def test_image(self):
         # Send an image as below ('p' indicates byte alignment padding)
-        # (0) | 1, 0 |    | p, p |
-        # (1) | 0, 0 | -> | p, p |
-        # (2) | 0, 0 |    | p, p |
-        # (3) | 0, 0 |    | p, p |
-        # (4)             | p, p |
-        # (5)             | 0, 0 |
-        # (6)             | 0, 0 |
-        # (7)             | 1, 0 |
+        # (0) | 1, 0 |
+        # (1) | 0, 0 | -> [0x01, 0x00]
+        # (2) | 0, 0 |
+        # (3) | 0, 0 |
         image = np.full((3, 2), False)
         image[0, 0] = True
 
@@ -38,26 +34,25 @@ class TestPackets(object):
 
     def test_tall_image(self):
         # Send an image as below ('p' indicates byte alignment padding)
-        # (0)  | 1, 0 |    | p, p |
-        # (1)  | 0, 0 |    | 0, 0 |
-        # (2)  | 0, 0 |    | 0, 0 |
-        # (3)  | 0, 0 |    | 0, 0 |
-        # (4)  | 0, 0 |    | 0, 0 |
-        # (5)  | 0, 0 |    | 0, 0 |
-        # (6)  | 0, 0 |    | 1, 0 |
-        # (7)  | 0, 0 | -> | 0, 0 |
-        # (8)  | 0, 0 |    | 0, 0 |
-        # (9)  | 1, 0 |    | 0, 0 |
-        # (10) | 0, 0 |    | 0, 0 |
-        # (11) | 0, 0 |    | 0, 0 |
-        # (12) | 0, 0 |    | 0, 0 |
-        # (13) | 0, 0 |    | 0, 0 |
-        # (14) | 0, 0 |    | 0, 0 |
-        # (15)             | 1, 0 |
+        # (0)  | 1, 0 |
+        # (1)  | 0, 0 |
+        # (2)  | 0, 0 |
+        # (3)  | 0, 0 |
+        # (4)  | 0, 0 |
+        # (5)  | 0, 0 |
+        # (6)  | 0, 0 |
+        # (7)  | 0, 0 | -> | 0x01, 0x00 | -> [0x01, 0x02, 0x00, 0x00]
+        # (8)  | 0, 0 |    | 0x02, 0x00 |
+        # (9)  | 1, 0 |
+        # (10) | 0, 0 |
+        # (11) | 0, 0 |
+        # (12) | 0, 0 |
+        # (13) | 0, 0 |
+        # (14) | 0, 0 |
         image = np.full((15, 2), False)
-        image[0, 0] = True  # MSbit of MSbyte
-        image[9, 0] = True  # MSbit for LSbyte
+        image[0, 0] = True
+        image[9, 0] = True
 
         packet = ImagePacket(1, image)
         packet_data = packet.get_bytes()
-        assert packet_data == b'\x02110402010000\x03B4'
+        assert packet_data == b'\x02110401020000\x03B4'