mirror of
https://github.com/KrisKennaway/ii-pix.git
synced 2024-06-03 05:29:32 +00:00
Add some comments and docstrings
This commit is contained in:
parent
a7d734f2b0
commit
2bbd65a079
12
convert.py
12
convert.py
|
@ -1,3 +1,5 @@
|
||||||
|
"""Image converter to Apple II Double Hi-Res format."""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os.path
|
import os.path
|
||||||
import time
|
import time
|
||||||
|
@ -13,11 +15,8 @@ import screen as screen_py
|
||||||
|
|
||||||
|
|
||||||
# TODO:
|
# TODO:
|
||||||
# - support alternate palettes properly
|
|
||||||
# - compare to bmp2dhr and a2bestpix
|
|
||||||
# - support LR/DLR
|
# - support LR/DLR
|
||||||
# - support HGR
|
# - support HGR
|
||||||
# - README
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -62,6 +61,7 @@ def main():
|
||||||
screen = screen_py.DHGR140Screen(palette)
|
screen = screen_py.DHGR140Screen(palette)
|
||||||
lookahead = 0
|
lookahead = 0
|
||||||
|
|
||||||
|
# Open and resize source image
|
||||||
image = image_py.open(args.input)
|
image = image_py.open(args.input)
|
||||||
resized = np.array(
|
resized = np.array(
|
||||||
image_py.resize(image, screen.X_RES, screen.Y_RES)).astype(np.float32)
|
image_py.resize(image, screen.X_RES, screen.Y_RES)).astype(np.float32)
|
||||||
|
@ -70,10 +70,10 @@ def main():
|
||||||
|
|
||||||
dither = dither_pattern.PATTERNS[args.dither]()
|
dither = dither_pattern.PATTERNS[args.dither]()
|
||||||
|
|
||||||
start = time.time()
|
# start = time.time()
|
||||||
output_4bit, output_rgb = dither_pyx.dither_image(
|
output_4bit, output_rgb = dither_pyx.dither_image(
|
||||||
screen, resized, dither, lookahead)
|
screen, resized, dither, lookahead)
|
||||||
print(time.time() - start)
|
# print(time.time() - start)
|
||||||
|
|
||||||
if args.resolution == 140:
|
if args.resolution == 140:
|
||||||
# Show un-fringed 140px output image
|
# Show un-fringed 140px output image
|
||||||
|
@ -92,9 +92,9 @@ def main():
|
||||||
if args.show_output:
|
if args.show_output:
|
||||||
out_image.show()
|
out_image.show()
|
||||||
|
|
||||||
|
# Save Double hi-res image
|
||||||
outfile = os.path.join(os.path.splitext(args.output)[0] + "-preview.png")
|
outfile = os.path.join(os.path.splitext(args.output)[0] + "-preview.png")
|
||||||
out_image.save(outfile, "PNG")
|
out_image.save(outfile, "PNG")
|
||||||
|
|
||||||
with open(args.output, "wb") as f:
|
with open(args.output, "wb") as f:
|
||||||
f.write(bytes(screen.main))
|
f.write(bytes(screen.main))
|
||||||
f.write(bytes(screen.aux))
|
f.write(bytes(screen.aux))
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
"""Error diffusion dither patterns."""
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
|
3
image.py
3
image.py
|
@ -1,3 +1,5 @@
|
||||||
|
"""Image transformation functions."""
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
|
@ -34,7 +36,6 @@ def resize(image: Image, x_res, y_res, srgb_output: bool = False) -> Image:
|
||||||
# Convert to linear RGB before rescaling so that colour interpolation is
|
# Convert to linear RGB before rescaling so that colour interpolation is
|
||||||
# in linear space
|
# in linear space
|
||||||
linear = srgb_to_linear(np.asarray(image)).astype(np.uint8)
|
linear = srgb_to_linear(np.asarray(image)).astype(np.uint8)
|
||||||
# linear = np.asarray(image).astype(np.uint8)
|
|
||||||
res = Image.fromarray(linear).resize((x_res, y_res), Image.LANCZOS)
|
res = Image.fromarray(linear).resize((x_res, y_res), Image.LANCZOS)
|
||||||
if srgb_output:
|
if srgb_output:
|
||||||
return Image.fromarray(
|
return Image.fromarray(
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
"""RGB colour palettes to target for Apple II image conversions."""
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import image
|
import image
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
"""Precompute CIE2000 perceptual colour distance matrices.
|
||||||
|
|
||||||
|
The matrix of delta-E values is computed for all pairs of 24-bit RGB values,
|
||||||
|
and 4-bit Apple II target palette. This is a 256MB file that is mmapped at
|
||||||
|
runtime for efficient access.
|
||||||
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import image
|
import image
|
||||||
import palette as palette_py
|
import palette as palette_py
|
||||||
|
|
19
screen.py
19
screen.py
|
@ -1,3 +1,5 @@
|
||||||
|
"""Representation of Apple II screen memory."""
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import palette as palette_py
|
import palette as palette_py
|
||||||
|
|
||||||
|
@ -23,9 +25,15 @@ class Screen:
|
||||||
return 1024 * c + 128 * b + 40 * a
|
return 1024 * c + 128 * b + 40 * a
|
||||||
|
|
||||||
def _image_to_bitmap(self, image: np.ndarray) -> np.ndarray:
|
def _image_to_bitmap(self, image: np.ndarray) -> np.ndarray:
|
||||||
|
"""Converts 4-bit image to 2-bit image bitmap.
|
||||||
|
|
||||||
|
Each 4-bit colour value maps to a sliding window of 4 successive pixels,
|
||||||
|
via x%4.
|
||||||
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def pack(self, image: np.ndarray):
|
def pack(self, image: np.ndarray):
|
||||||
|
"""Packs an image into memory format (8k AUX + 8K MAIN)."""
|
||||||
bitmap = self._image_to_bitmap(image)
|
bitmap = self._image_to_bitmap(image)
|
||||||
# The DHGR display encodes 7 pixels across interleaved 4-byte sequences
|
# The DHGR display encodes 7 pixels across interleaved 4-byte sequences
|
||||||
# of AUX and MAIN memory, as follows:
|
# of AUX and MAIN memory, as follows:
|
||||||
|
@ -53,6 +61,12 @@ class Screen:
|
||||||
return bitmap
|
return bitmap
|
||||||
|
|
||||||
def bitmap_to_image_rgb(self, bitmap: np.ndarray) -> np.ndarray:
|
def bitmap_to_image_rgb(self, bitmap: np.ndarray) -> np.ndarray:
|
||||||
|
"""Convert our 2-bit bitmap image into a RGB image.
|
||||||
|
|
||||||
|
Colour at every pixel is determined by the value of a 4-bit sliding
|
||||||
|
window indexed by x % 4, which gives the index into our 16-colour RGB
|
||||||
|
palette.
|
||||||
|
"""
|
||||||
image_rgb = np.empty((192, 560, 3), dtype=np.uint8)
|
image_rgb = np.empty((192, 560, 3), dtype=np.uint8)
|
||||||
for y in range(self.Y_RES):
|
for y in range(self.Y_RES):
|
||||||
pixel = [False, False, False, False]
|
pixel = [False, False, False, False]
|
||||||
|
@ -63,6 +77,7 @@ class Screen:
|
||||||
return image_rgb
|
return image_rgb
|
||||||
|
|
||||||
def pixel_palette_options(self, last_pixel_4bit, x: int):
|
def pixel_palette_options(self, last_pixel_4bit, x: int):
|
||||||
|
"""Returns available colours for given x pos and 4-bit colour of x-1"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,6 +100,7 @@ class DHGR140Screen(Screen):
|
||||||
return bitmap
|
return bitmap
|
||||||
|
|
||||||
def pixel_palette_options(self, last_pixel_4bit, x: int):
|
def pixel_palette_options(self, last_pixel_4bit, x: int):
|
||||||
|
# All 16 colour choices are available at every x position.
|
||||||
return (
|
return (
|
||||||
np.array(list(self.palette.RGB.keys()), dtype=np.uint8),
|
np.array(list(self.palette.RGB.keys()), dtype=np.uint8),
|
||||||
np.array(list(self.palette.RGB.values()), dtype=np.uint8))
|
np.array(list(self.palette.RGB.values()), dtype=np.uint8))
|
||||||
|
@ -107,6 +123,9 @@ class DHGR560Screen(Screen):
|
||||||
return bitmap
|
return bitmap
|
||||||
|
|
||||||
def pixel_palette_options(self, last_pixel_4bit, x: int):
|
def pixel_palette_options(self, last_pixel_4bit, x: int):
|
||||||
|
# The two available colours for position x are given by the 4-bit
|
||||||
|
# value of position x-1, and the 4-bit value produced by toggling the
|
||||||
|
# value of the x % 4 bit (the current value of NTSC phase)
|
||||||
last_dots = self.palette.DOTS[last_pixel_4bit]
|
last_dots = self.palette.DOTS[last_pixel_4bit]
|
||||||
other_dots = list(last_dots)
|
other_dots = list(last_dots)
|
||||||
other_dots[x % 4] = not other_dots[x % 4]
|
other_dots[x % 4] = not other_dots[x % 4]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user