Skip to content

Working P1-P6 formats #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 113 commits into from
May 22, 2019
Merged
Show file tree
Hide file tree
Changes from 109 commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
c1f5b2e
start PNM support
May 6, 2019
b4bb4a2
adding ppm test image
Errolyn May 6, 2019
883a6b1
update pbm test
May 6, 2019
bdbb27e
Merge branch 'master' of https://github.com/crookedstorm/Adafruit_Cir…
May 6, 2019
4e2bde4
added ascii test files
Errolyn May 6, 2019
bd1daf5
Merge branch 'master' of https://github.com/crookedstorm/Adafruit_Cir…
Errolyn May 6, 2019
ec5f6da
added ascii test files
Errolyn May 6, 2019
e001f6c
Add the pnm load kwargs
May 6, 2019
3414d18
Merge remote-tracking branch 'origin/master' into ppm
May 6, 2019
b57dadf
Fix the pnm init
May 6, 2019
1822cb3
Merge remote-tracking branch 'origin/master' into ppm
May 6, 2019
8294e85
Gather the header information at pnm module level
May 6, 2019
456d9ca
Merge remote-tracking branch 'origin/master' into ppm
May 6, 2019
8efb0b1
remove re
May 6, 2019
ce7646e
fix the comment-remover loop
May 6, 2019
541084f
Merge remote-tracking branch 'origin/master' into ppm
May 6, 2019
b18dfb7
Not supporting 16 bit until we sort that out
May 6, 2019
e0808b0
Merge remote-tracking branch 'origin/master' into ppm
May 6, 2019
aa1bc7c
Actually remove re
May 6, 2019
eff1912
Merge remote-tracking branch 'origin/master' into ppm
May 6, 2019
d8b34e2
some fixes on pnm type selections
May 6, 2019
d2a2e32
Merge remote-tracking branch 'origin/master' into ppm
May 6, 2019
35ea55f
fix sense of test for newline
May 6, 2019
dd0f846
actually assign in the comment loop
May 6, 2019
13153a8
patch
May 6, 2019
f531e9e
Try to fit larger ints
May 6, 2019
70b707b
what happens with bytes array
May 6, 2019
f47d201
We support 16 bits now
May 6, 2019
f74c329
Merge remote-tracking branch 'origin/master' into ppm
May 6, 2019
dc6e3ae
addtests
May 6, 2019
b008a72
Add pbm
May 6, 2019
157ded5
test cleanup
May 6, 2019
201064b
Saving progress
Errolyn May 6, 2019
1663263
remove reads that loose data
May 7, 2019
bda7572
Merge remote-tracking branch 'origin/master' into ppm
May 7, 2019
06efb03
This may be working
May 7, 2019
e1b2aaa
add all authors
May 7, 2019
95fce9e
Update __init__.py
Errolyn May 7, 2019
0ce27af
Merge pull request #1 from crookedstorm/ppm
crookedstorm May 7, 2019
ccccfc0
Reposition ascii branch
May 7, 2019
7ddca29
do NOT read the whole file at once
May 7, 2019
47eb167
correct loop logic
May 7, 2019
42c8945
test runner for PPM, PBM
May 7, 2019
2dbad05
contuing the quest for correct ascii images
May 7, 2019
43980cb
Merge branch 'master' of github.com:crookedstorm/Adafruit_CircuitPyth…
May 7, 2019
4bc7fc4
fixed load binary P4
May 7, 2019
def7809
p1 works again, new interface
May 7, 2019
458cbc8
Progress from testing on the binary, but ascii won't work yet
May 7, 2019
d4e33c2
save progress
Errolyn May 7, 2019
ad2dd87
Use struct to pack ascii into usable binary
May 7, 2019
5c065e0
Merge branch 'master' of github.com:crookedstorm/Adafruit_CircuitPyth…
May 7, 2019
cead809
From the docs: offset is a required argument
May 7, 2019
3e7d725
Merge branch 'master' of github.com:crookedstorm/Adafruit_CircuitPyth…
May 7, 2019
a18ff8e
set size of array to 3
May 7, 2019
8270e3a
Merge branch 'master' of github.com:crookedstorm/Adafruit_CircuitPyth…
May 7, 2019
78bc0f4
p6 test failing
May 7, 2019
c1a0d0b
Stop dividing by zero
May 7, 2019
5208c80
Merge branch 'master' of github.com:crookedstorm/Adafruit_CircuitPyth…
May 7, 2019
ae14baf
be more adafruit friendly
May 7, 2019
b69745c
Merge branch 'master' of github.com:crookedstorm/Adafruit_CircuitPyth…
May 7, 2019
0c9823f
removing thing that makes no sense
May 7, 2019
bc2afb4
Merge branch 'master' of github.com:crookedstorm/Adafruit_CircuitPyth…
May 7, 2019
b7e294a
Trying line size
May 7, 2019
f260784
Merge branch 'master' of github.com:crookedstorm/Adafruit_CircuitPyth…
May 7, 2019
551d40a
Crazy hack to make ascii into int
May 7, 2019
b58e648
Merge branch 'master' of github.com:crookedstorm/Adafruit_CircuitPyth…
May 7, 2019
51cf99e
just saving some of what we've learned
May 7, 2019
6fb1375
commiting what's broken
May 7, 2019
9f63c18
use integers in mono
May 8, 2019
44c3d80
Merge branch 'master' of github.com:crookedstorm/Adafruit_CircuitPyth…
May 8, 2019
2baaef7
fan out
May 8, 2019
02be5b8
black run
May 8, 2019
1874fa0
less files
May 8, 2019
61d3849
.
May 8, 2019
149061c
working, white/black
May 8, 2019
79b9f6b
remove kw arg, now two work
May 8, 2019
0a2e93c
Merge branch 'master' into Riddlerat/pgm-work
Errolyn May 8, 2019
efeff7a
Merge branch 'feature-tests' of https://github.com/crookedstorm/Adafr…
Errolyn May 8, 2019
ff9113d
🤖👽
Errolyn May 8, 2019
1665ecf
Image displaying now, but colors are inversed
Errolyn May 8, 2019
0ca9b1c
screen size example
May 8, 2019
d984ca0
add test image
Errolyn May 8, 2019
531951c
starting binary pgm work
Errolyn May 8, 2019
8e385b4
test it
May 8, 2019
1c1a164
Merge branch 'Riddlerat/pgm-work' of github.com:crookedstorm/Adafruit…
May 8, 2019
8cb69c4
Place saving update
Errolyn May 8, 2019
0d9d5b8
working commit before merge
May 11, 2019
58fd496
images
May 11, 2019
44facc3
Merge branch 'Riddlerat/pgm-work' into feature-tests
May 11, 2019
0b94799
split test files
May 11, 2019
ce05f6b
.
May 11, 2019
5cf152e
Add doc for delveloping for imageload
May 11, 2019
c43d11b
p2 ascii working
May 11, 2019
f6a63e3
working p5 type images
May 11, 2019
bfb89b7
p3 format (RGB ascii) working
May 11, 2019
c710a8d
working P6 format
May 11, 2019
37e23a8
error msg
May 11, 2019
6726ea0
remove vscode
May 11, 2019
6038440
remove test images
May 11, 2019
0269c39
optimize
May 12, 2019
065722b
optimize binary loads
May 12, 2019
31fb576
fix mono, not blue
May 12, 2019
1f0afd6
rename variables
May 12, 2019
11da972
ignore test folder for pylint
May 12, 2019
5dbb0ac
run tests
May 12, 2019
86ea43a
Merge branch 'master' of github.com:adafruit/Adafruit_CircuitPython_I…
May 15, 2019
b3150b1
add test for byte order
May 15, 2019
a3e8240
move this to examples
May 15, 2019
e23760f
add explain
May 15, 2019
743ce77
add copyright MIT license
May 18, 2019
188dc47
Merge branch 'master' of github.com:adafruit/Adafruit_CircuitPython_I…
May 18, 2019
82509d5
refactor, improve testing validate, pass pylint
May 18, 2019
115716d
bugfix of mono bitshifter
matt-land May 18, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ _build
.env
build*
bundles
.idea/
venv/

.vscode
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ extension-pkg-whitelist=

# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=CVS
ignore=CVS,adafruit_imageload/tests

# Add files or directories matching the regex patterns to the blacklist. The
# regex matches against base names, not paths.
Expand Down
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ install:
- pip install --force-reinstall pylint==1.9.2

script:
- pytest adafruit_imageload
- pylint adafruit_imageload/**
- ([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace examples/*.py)
- circuitpython-build-bundles --filename_prefix adafruit-circuitpython-imageload --library_location .
Expand Down
5 changes: 4 additions & 1 deletion adafruit_imageload/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ def load(filename, *, bitmap=None, palette=None):
"""
with open(filename, "rb") as file:
header = file.read(3)
file.seek(0)
if header.startswith(b"BM"):
from . import bmp
file.seek(0)
return bmp.load(file, bitmap=bitmap, palette=palette)
if header.startswith(b"P"):
from . import pnm
return pnm.load(file, header, bitmap=bitmap, palette=palette)
raise RuntimeError("Unsupported image format")
111 changes: 111 additions & 0 deletions adafruit_imageload/pnm/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""
`adafruit_imageload.pnm`
====================================================

Load pixel values (indices or colors) into a bitmap and colors into a palette.

* Author(s): Matt Land, Brooke Storm, Sam McGahan

"""

__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ImageLoad.git"


def load(file, header, *, bitmap=None, palette=None):
"""
Scan for netpbm format info, skip over comments, and and delegate to a submodule
to do the actual data loading.
Formats P1, P4 have two space padded pieces of information: width and height.
All other formats have three: width, height, and max color value.
"""
magic_number = header[:2]
file.seek(2)
pnm_header = []
while True:
# We have all we need at length 3 for formats P2, P3, P5, P6
if len(pnm_header) == 3:
break
if len(pnm_header) == 2 and magic_number in [b"P1", b"P4"]:
bitmap = bitmap(pnm_header[0], pnm_header[1], 1)
if palette:
palette = palette(1)
palette[0] = b"\xFF\xFF\xFF"
if magic_number.startswith(b"P1"):
from . import pbm_ascii

return pbm_ascii.load(
file, pnm_header[0], pnm_header[1], bitmap=bitmap, palette=palette
)

from . import pbm_binary

return pbm_binary.load(
file, pnm_header[0], pnm_header[1], bitmap=bitmap, palette=palette
)

next_byte = file.read(1)
if next_byte == b"#":
while True:
next_byte = file.read(1)
if not next_byte:
raise RuntimeError("Unsupported image format")
if next_byte == b"\n":
break
if next_byte.isdigit():
value = bytearray()
while True:
if not next_byte.isdigit():
break
value += next_byte
next_byte = file.read(1)
if not next_byte:
raise RuntimeError("Unsupported image format")

pnm_header.append(int("".join(["%c" % char for char in value])))
continue

if not next_byte:
raise RuntimeError("Unsupported image format")

if magic_number in [b"P2", b"P5"]:
from . import pgm

return pgm.load(file, magic_number, pnm_header, bitmap=bitmap, palette=palette)

if magic_number == b"P3":
from . import ppm_ascii

return ppm_ascii.load(
file, pnm_header[0], pnm_header[1], bitmap=bitmap, palette=palette
)

if magic_number == b"P6":
from . import ppm_binary

return ppm_binary.load(
file, pnm_header[0], pnm_header[1], bitmap=bitmap, palette=palette
)

raise RuntimeError("Unsupported image format {}".format(magic_number))
52 changes: 52 additions & 0 deletions adafruit_imageload/pnm/pbm_ascii.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""
`adafruit_imageload.pnm.pbm_ascii`
====================================================

Load pixel values (indices or colors) into a bitmap and for an ascii ppm,
return None for pallet.

* Author(s): Matt Land, Brooke Storm, Sam McGahan

"""

__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ImageLoad.git"


def load(file, width, height, bitmap=None, palette=None):
"""
Load a P1 'PBM' ascii image into the displayio.Bitmap
"""
next_byte = True
for y in range(height):
x = 0
while next_byte:
next_byte = file.read(1)
if not next_byte.isdigit():
continue
bitmap[x, y] = 1 if next_byte == b"1" else 0
if x == width - 1:
break
x += 1
return bitmap, palette
63 changes: 63 additions & 0 deletions adafruit_imageload/pnm/pbm_binary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""
`adafruit_imageload.pnm.pbm_binary`
====================================================

Load pixel values (indices or colors) into a bitmap and for an ascii ppm,
return None for pallet.

* Author(s): Matt Land, Brooke Storm, Sam McGahan

"""

__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ImageLoad.git"


def load(file, width, height, bitmap=None, palette=None):
"""
Load a P4 'PBM' binary image into the displayio.Bitmap
"""
x = 0
y = 0
while True:
next_byte = file.read(1)
if not next_byte:
break # out of bits
for bit in iterbits(int.from_bytes(next_byte, "little")):
bitmap[x, y] = bit
x += 1
if x > width - 1:
y += 1
x = 0
if y > height - 1:
break
return bitmap, palette


def iterbits(b):
"""
generator to iterate over the bits in a byte (character)
"""
for i in range(8):
yield (b >> i) & 1
50 changes: 50 additions & 0 deletions adafruit_imageload/pnm/pgm/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""
`adafruit_imageload.pnm.pgm`
====================================================

Load pixel values (indices or colors) into a bitmap and colors into a palette.

* Author(s): Matt Land, Brooke Storm, Sam McGahan

"""


def load(file, magic_number, header, *, bitmap=None, palette=None):
"""
Perform the load of Netpbm greyscale images (P2, P5)
"""
if header[2] > 256:
raise NotImplementedError("16 bit files are not supported")
width = header[0]
height = header[1]

if magic_number == b"P2": # To handle ascii PGM files.
from . import ascii as pgm_ascii
return pgm_ascii.load(file, width, height, bitmap=bitmap, palette=palette)

if magic_number == b"P5": # To handle binary PGM files.
from . import binary
return binary.load(file, width, height, bitmap=bitmap, palette=palette)

raise NotImplementedError("Was not able to send image")
76 changes: 76 additions & 0 deletions adafruit_imageload/pnm/pgm/ascii.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""
`adafruit_imageload.pnm.pgm.ascii`
====================================================

Load pixel values (indices or colors) into a bitmap and colors into a palette.

* Author(s): Matt Land, Brooke Storm, Sam McGahan

"""


def load(file, width, height, bitmap=None, palette=None):
"""
Load a PGM ascii file (P2)
"""
data_start = file.tell() # keep this so we can rewind
palette_colors = set()
pixel = bytearray()
# build a set of all colors present in the file, so palette and bitmap can be constructed
while True:
byte = file.read(1)
if byte == b"":
break
if not byte.isdigit():
int_pixel = int("".join(["%c" % char for char in pixel]))
palette_colors.add(int_pixel)
pixel = bytearray()
pixel += byte
if palette:
palette = build_palette(palette, palette_colors)
if bitmap:
bitmap = bitmap(width, height, len(palette_colors))
palette_colors = list(palette_colors)
file.seek(data_start)
for y in range(height):
for x in range(width):
pixel = bytearray()
while True:
byte = file.read(1)
if not byte.isdigit():
break
pixel += byte
int_pixel = int("".join(["%c" % char for char in pixel]))
bitmap[x, y] = palette_colors.index(int_pixel)
return bitmap, palette


def build_palette(palette_class, palette_colors):
"""
construct the Palette, and populate it with the set of palette_colors
"""
palette = palette_class(len(palette_colors))
for counter, color in enumerate(palette_colors):
palette[counter] = bytes([color, color, color])
return palette
Loading