Skip to content

Commit 0b94799

Browse files
author
Matt Land
committed
split test files
1 parent 44facc3 commit 0b94799

8 files changed

Lines changed: 303 additions & 253 deletions

File tree

adafruit_imageload/pnm/pgm/__init__.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,15 @@
2828
* Author(s): Matt Land, Brooke Storm, Sam McGahan
2929
3030
"""
31-
#import logging
31+
3232

3333
def load(file, magic_number, header, *, bitmap=None, palette=None):
3434
# TODO: remove unused variables later
3535
width = header[0]
3636
height = header[1]
37-
max_colors = header[2]
37+
max_colors = 6 #header[2]
3838
bitmap = bitmap(width, height, max_colors)
3939
colors = set()
40-
pixel = bytearray()
4140

4241

4342
if max_colors > 256:
@@ -48,27 +47,24 @@ def load(file, magic_number, header, *, bitmap=None, palette=None):
4847
# Handle ascii
4948
for y in range(height):
5049
for x in range(width):
51-
# Takes int and converts to an 8 bit
50+
pixel = bytearray()
51+
# Takes int and converts to an 8 bit
5252
while True:
5353
byte = file.read(1) # type: byte
5454
if not byte.isdigit():
5555
break
5656
pixel += byte
57-
58-
int_pixel = int("".join(["%c" % char for char in pixel]))
57+
# convert b'255' to b'\xff'
58+
int_pixel = bytes([int("".join(["%c" % char for char in pixel]))])
5959
bitmap[x, y] = int_pixel
6060
colors.add(int_pixel)
6161
# logging.info(f'{x}, {y}, {byte}, {int_pixel}')
6262
if palette:
6363
palette = palette(len(colors))
6464
for counter, color in enumerate(colors):
65-
color_bytearray = bytearray()
66-
for i in range(3):
67-
color_bytearray += bytes([color])
68-
palette[counter] = color_bytearray
65+
palette[counter] = color
6966
return bitmap, palette
7067

71-
7268
if magic_number == b'P5': # To handle binary PGM files.
7369
for y in range(height):
7470
for x in range(width):
@@ -79,7 +75,6 @@ def load(file, magic_number, header, *, bitmap=None, palette=None):
7975
bitmap[x, y] = int_pixel
8076
colors.add(int_pixel)
8177

82-
8378
if palette:
8479
palette = palette(len(colors))
8580
for counter, color in enumerate(colors):
@@ -90,4 +85,4 @@ def load(file, magic_number, header, *, bitmap=None, palette=None):
9085

9186
return bitmap, palette
9287

93-
raise NotImplementedError("Was not able to send image")
88+
raise NotImplementedError("Was not able to send image")
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
2+
3+
class Bitmap_C_Interface(object):
4+
"""
5+
Simulates the displayio.Bitmap class for testing
6+
"""
7+
def __init__(self, width, height, colors):
8+
self.width = width
9+
self.height = height
10+
self.colors = colors
11+
self.data = {}
12+
13+
def _abs_pos(self, width: int, height: int) -> int:
14+
if height > self.height - 1:
15+
raise ValueError("height > max")
16+
if width > self.width - 1:
17+
raise ValueError("width > max")
18+
return width + (height * self.width)
19+
20+
def _decode(self, position: int) -> tuple:
21+
return position % self.width, position // self.width
22+
23+
def __setitem__(self, key: tuple, value: int):
24+
if isinstance(key, tuple):
25+
# order is X, Y from the docs https://github.com/adafruit/circuitpython/blob/master/shared-bindings/displayio/Bitmap.c
26+
self.__setitem__(self._abs_pos(key[0], key[1]), value)
27+
return
28+
if not isinstance(value, (int,bytes)):
29+
raise RuntimeError(f"set value as int or bytes, not {type(value)}")
30+
if isinstance(value, int) and value > 255:
31+
raise ValueError(f'pixel value {value} too large')
32+
if isinstance(value, bytes) and value > b'\xff':
33+
raise ValueError(f'pixel value {value} too large')
34+
self.data[key] = value
35+
36+
def __getitem__(self, item: tuple) -> bytearray:
37+
if isinstance(item, tuple):
38+
return self.__getitem__(self._abs_pos(item[0], item[1]))
39+
# if item > self.height * self.width:
40+
# raise RuntimeError('illegal item position {}'.format(item))
41+
try:
42+
return self.data[item]
43+
except KeyError:
44+
raise RuntimeError("no data at {} [{}]".format(self._decode(item), item))
45+
46+
def validate(self):
47+
if not self.data:
48+
raise ValueError("no rows were set / no data in memory")
49+
for i in range(self.height * self.width, 0):
50+
try:
51+
self.data[i]
52+
except KeyError:
53+
raise ValueError("missing data at {i}")
54+
55+
def __str__(self):
56+
out = "\n"
57+
for y in range(self.height):
58+
for x in range(self.width):
59+
data = self[x, y]
60+
out += f"{data:>4}"
61+
out += "\n"
62+
return out
63+
64+
65+
class Palette_C_Interface(object):
66+
"""
67+
Simulates the displayio.Palette class for testing
68+
"""
69+
def __init__(self, num_colors):
70+
self.num_colors = num_colors
71+
self.colors = {}
72+
73+
def __setitem__(self, key, value):
74+
self.colors[key] = value
75+
76+
def validate(self):
77+
if not self.colors:
78+
raise ValueError("no palette colors were set")
79+
if len(self.colors) > self.num_colors:
80+
raise ValueError("too many colors inserted into palette")
81+
if len(self.colors) < self.num_colors:
82+
raise ValueError("too few colors inserted into palette")
83+
for i in range(self.num_colors):
84+
try:
85+
self.colors
86+
except IndexError:
87+
raise ValueError('missing color `{}` in palette color list'.format(i))

adafruit_imageload/tests/shared_binding_interface.py

Whitespace-only changes.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
from unittest import TestCase
2+
from .displayio_shared_bindings import Bitmap_C_Interface
3+
4+
5+
class TestBitmap_C(TestCase):
6+
def test_init(self):
7+
b = Bitmap_C_Interface(2, 4, 1)
8+
self.assertEqual(2, b.width)
9+
self.assertEqual(4, b.height)
10+
self.assertEqual(1, b.colors)
11+
12+
def test_abs(self):
13+
b = Bitmap_C_Interface(5, 2, 1)
14+
self.assertEqual(9, b._abs_pos(4,1))
15+
16+
def test_set_tuple(self):
17+
b = Bitmap_C_Interface(2, 4, 1)
18+
b[1, 3] = 67
19+
self.assertEqual(b[1, 3], 67)
20+
21+
def test_set_abs(self):
22+
b = Bitmap_C_Interface(2, 4, 1)
23+
b[0] = 42
24+
self.assertEqual(b[0], 42)
25+
26+
def test_abs_and_tuple(self):
27+
b = Bitmap_C_Interface(2, 4, 1)
28+
b[7] = 101
29+
self.assertEqual(101, b[1, 3])
30+
31+
def test_non_zero(self):
32+
b = Bitmap_C_Interface(2, 4, 1)
33+
b[1, 1] = 100
34+
self.assertEqual(100, b[1, 1])
35+
36+
def test_throws_x_out_of_range(self):
37+
b = Bitmap_C_Interface(2, 4, 1)
38+
try:
39+
b[2, 1] = 100
40+
self.fail("should have thrown")
41+
except ValueError:
42+
pass
43+
44+
def test_max(self):
45+
b = Bitmap_C_Interface(2, 4, 1)
46+
b[1, 1] = 66
47+
self.assertEqual(66, b[1, 1])
48+
49+
def test_uninitialized(self):
50+
b = Bitmap_C_Interface(2, 4, 1)
51+
try:
52+
b[1, 1]
53+
self.fail("should have thrown")
54+
except RuntimeError:
55+
pass
56+
57+
def test_validate_throws(self):
58+
b = Bitmap_C_Interface(2, 4, 1)
59+
try:
60+
b.validate()
61+
except ValueError:
62+
pass
63+
64+
def test_repr(self):
65+
b = Bitmap_C_Interface(3, 2, 1)
66+
b[0, 0] = 1
67+
b[1, 0] = 0
68+
b[2, 0] = 0
69+
b[0, 1] = 1
70+
b[1, 1] = 1
71+
b[2, 1] = 0
72+
self.assertEqual("\n 1 0 0\n 1 1 0\n", str(b))
73+
74+
def test_decode(self):
75+
b = Bitmap_C_Interface(4, 4, 1)
76+
self.assertEqual((0, 0), b._decode(0))
77+
encoded = b._abs_pos(3, 3)
78+
self.assertEqual((3, 3), b._decode(encoded))
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
from unittest import TestCase
2+
from adafruit_imageload import pnm
3+
from io import BytesIO
4+
import os
5+
from .displayio_shared_bindings import Bitmap_C_Interface, Palette_C_Interface
6+
7+
8+
class TestPnmLoad(TestCase):
9+
def test_load_fails_with_no_header_data(self):
10+
f = BytesIO(b"some initial binary data: \x00\x01")
11+
try:
12+
pnm.load(f, b"P1", bitmap=Bitmap_C_Interface, palette=Palette_C_Interface)
13+
self.fail("should have failed")
14+
except Exception as e:
15+
if "Unsupported image format" not in str(e):
16+
raise
17+
18+
def test_load_works_p1_ascii(self):
19+
test_file = os.path.join(
20+
os.path.dirname(__file__),
21+
"..",
22+
"..",
23+
"examples",
24+
"images",
25+
"netpbm_p1_mono_ascii.pbm",
26+
)
27+
with open(test_file, "rb") as f:
28+
bitmap, palette = pnm.load(f, b"P1", bitmap=Bitmap_C_Interface, palette=Palette_C_Interface)
29+
self.assertTrue(isinstance(bitmap, Bitmap_C_Interface), bitmap)
30+
self.assertEqual(1, bitmap.colors)
31+
self.assertEqual(13, bitmap.width)
32+
self.assertEqual(21, bitmap.height)
33+
34+
bitmap.validate()
35+
self.assertEqual(0, bitmap[0]) # check first row
36+
self.assertEqual(1, bitmap[11, 1]) # check second row
37+
38+
self.assertEqual(1, palette.num_colors)
39+
palette.validate()
40+
41+
def test_load_works_p4_in_mem(self):
42+
f = BytesIO(b"P4\n4 2\n\x55")
43+
bitmap, palette = pnm.load(f, b"P4", bitmap=Bitmap_C_Interface)
44+
self.assertEqual(4, bitmap.width)
45+
self.assertEqual(2, bitmap.height)
46+
bitmap.validate()
47+
self.assertEqual("\n 1 0 1 0\n 1 0 1 0\n", str(bitmap))
48+
49+
def test_load_works_p4_binary(self):
50+
test_file = os.path.join(
51+
os.path.dirname(__file__),
52+
"..",
53+
"..",
54+
"examples",
55+
"images",
56+
"netpbm_p4_mono_binary.pbm",
57+
)
58+
with open(test_file, "rb") as f:
59+
bitmap, palette = pnm.load(f, b"P4", bitmap=Bitmap_C_Interface)
60+
self.assertTrue(isinstance(bitmap, Bitmap_C_Interface))
61+
self.assertEqual(1, bitmap.colors)
62+
self.assertEqual(32, bitmap.width)
63+
self.assertEqual(15, bitmap.height)
64+
bitmap.validate()
65+
66+
def test_load_works_p4_binary_high_res(self):
67+
test_file = os.path.join(
68+
os.path.dirname(__file__),
69+
"..",
70+
"..",
71+
"examples",
72+
"images",
73+
"netpbm_p4_mono_large.pbm",
74+
)
75+
with open(test_file, "rb") as f:
76+
bitmap, palette = pnm.load(f, b"P4", bitmap=Bitmap_C_Interface)
77+
self.assertTrue(isinstance(bitmap, Bitmap_C_Interface))
78+
self.assertEqual(1, bitmap.colors)
79+
self.assertEqual(320, bitmap.width)
80+
self.assertEqual(240, bitmap.height)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import os
2+
import logging
3+
from unittest import TestCase
4+
from adafruit_imageload import pnm
5+
from .displayio_shared_bindings import Bitmap_C_Interface, Palette_C_Interface
6+
7+
logging.getLogger().setLevel(logging.DEBUG)
8+
9+
10+
class TestPgmLoad(TestCase):
11+
def test_load_works_p2_ascii(self):
12+
test_file = os.path.join(
13+
os.path.dirname(__file__),
14+
"..",
15+
"..",
16+
"examples",
17+
"images",
18+
"netpbm_p2_ascii.pgm",
19+
)
20+
with open(test_file, "rb") as f:
21+
bitmap, palette = pnm.load(f, b"P2", bitmap=Bitmap_C_Interface, palette=Palette_C_Interface)
22+
self.assertTrue(isinstance(bitmap, Bitmap_C_Interface), bitmap)
23+
self.assertEqual(6, bitmap.colors)
24+
self.assertEqual(8, bitmap.width)
25+
self.assertEqual(8, bitmap.height)
26+
bitmap.validate()
27+
self.assertEqual(6, palette.num_colors)
28+
palette.validate()
29+
30+
def test_load_works_p5_binary(self):
31+
test_file = os.path.join(
32+
os.path.dirname(__file__),
33+
"..",
34+
"..",
35+
"examples",
36+
"images",
37+
"netpbm_p5_binary.pgm",
38+
)
39+
with open(test_file, "rb") as f:
40+
bitmap, palette = pnm.load(f, b"P5", bitmap=Bitmap_C_Interface, palette=Palette_C_Interface)
41+
self.assertTrue(isinstance(bitmap, Bitmap_C_Interface), bitmap)
42+
self.assertEqual(8, bitmap.colors)
43+
self.assertEqual(8, bitmap.width)
44+
self.assertEqual(8, bitmap.height)
45+
bitmap.validate()
46+
self.assertEqual(8, palette.num_colors)
47+
palette.validate()

0 commit comments

Comments
 (0)