mirror of
https://github.com/KrisKennaway/ii-pix.git
synced 2025-01-18 00:32:19 +00:00
Add support for DHGR mono conversions
This commit is contained in:
parent
629104b933
commit
39e8eac8ed
11
README.md
11
README.md
@ -1,4 +1,4 @@
|
||||
# ][-pix 2.0
|
||||
# ][-pix 2.1
|
||||
|
||||
][-pix is an image conversion utility targeting Apple II graphics modes, currently Double Hi-Res
|
||||
(enhanced //e, //c, //gs) and Super Hi-Res (//gs).
|
||||
@ -39,11 +39,11 @@ To convert an image, the basic command is:
|
||||
python convert.py <mode> [<flags>] <input> <output>
|
||||
```
|
||||
where
|
||||
* `mode` is `dhr` for Double Hi-Res (560x192), or `shr` for Super Hi-Res (320x200)
|
||||
* `mode` is `dhr` for Double Hi-Res Colour (560x192), `dhr_mono` for Double Hi-Res Mono (560x192), or `shr` for Super Hi-Res (320x200)
|
||||
* `input` is the source image file to convert (e.g. `my-image.jpg`)
|
||||
* `output` is the output filename to produce (e.g. `my-image.dhr`)
|
||||
|
||||
The following flags are supported in both `dhr` and `shr` modes:
|
||||
The following flags are supported in all modes:
|
||||
|
||||
* `--show-input` Whether to show the input image before conversion. (default: False)
|
||||
* `--show-output` Whether to show the output image after conversion. (default: True)
|
||||
@ -158,6 +158,11 @@ python convert.py shr examples/shr/rabbit-kitten-original.png examples/shr/rabbi
|
||||
|
||||
# Version history
|
||||
|
||||
## v2.1 (2023-01-21)
|
||||
|
||||
* Added support for DHGR mono conversions
|
||||
* Fixed compatibility with python 3.10
|
||||
|
||||
## v2.0 (2022-07-16)
|
||||
|
||||
* Added support for Super Hi-Res 320x200 image conversions
|
||||
|
32
convert.py
32
convert.py
@ -79,6 +79,10 @@ def main():
|
||||
"value of --palette)")
|
||||
dhr_parser.set_defaults(func=convert_dhr)
|
||||
|
||||
dhr_mono_parser = subparsers.add_parser("dhr_mono")
|
||||
add_common_args(dhr_mono_parser)
|
||||
dhr_mono_parser.set_defaults(func=convert_dhr_mono)
|
||||
|
||||
shr_parser = subparsers.add_parser("shr")
|
||||
add_common_args(shr_parser)
|
||||
shr_parser.add_argument(
|
||||
@ -106,25 +110,29 @@ def prepare_image(image_filename: str, show_input: bool, screen,
|
||||
# Open and resize source image
|
||||
image = image_py.open(image_filename)
|
||||
if show_input:
|
||||
image_py.resize(image, screen.X_RES, screen.Y_RES,
|
||||
srgb_output=False).show()
|
||||
rgb = np.array(
|
||||
image_py.resize(image, screen.X_RES, screen.Y_RES,
|
||||
gamma=gamma_correct)).astype(np.float32) / 255
|
||||
return rgb
|
||||
|
||||
image_py.resize(image, screen.X_RES, screen.Y_RES * 2,
|
||||
srgb_output=True).show()
|
||||
return image_py.resize(image, screen.X_RES, screen.Y_RES,
|
||||
gamma=gamma_correct)
|
||||
|
||||
def convert_dhr(args):
|
||||
palette = palette_py.PALETTES[args.palette]()
|
||||
screen = screen_py.DHGRScreen(palette)
|
||||
rgb = prepare_image(args.input, args.show_input, screen, args.gamma_correct)
|
||||
convert_dhr_py.convert(screen, rgb, args)
|
||||
screen = screen_py.DHGRNTSCScreen(palette)
|
||||
image = prepare_image(args.input, args.show_input, screen,
|
||||
args.gamma_correct)
|
||||
convert_dhr_py.convert(screen, image, args)
|
||||
|
||||
|
||||
def convert_dhr_mono(args):
|
||||
screen = screen_py.DHGRScreen()
|
||||
image = prepare_image(args.input, args.show_input, screen, args.gamma_correct)
|
||||
convert_dhr_py.convert_mono(screen, image, args)
|
||||
|
||||
|
||||
def convert_shr(args):
|
||||
screen = screen_py.SHR320Screen()
|
||||
rgb = prepare_image(args.input, args.show_input, screen, args.gamma_correct)
|
||||
convert_shr_py.convert(screen, rgb, args)
|
||||
image = prepare_image(args.input, args.show_input, screen, args.gamma_correct)
|
||||
convert_shr_py.convert(screen, image, args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -10,7 +10,27 @@ import screen as screen_py
|
||||
import image as image_py
|
||||
|
||||
|
||||
def convert(screen: screen_py.DHGRScreen, rgb: np.ndarray, args):
|
||||
def _output(out_image: Image, args):
|
||||
if args.show_output:
|
||||
out_image.show()
|
||||
|
||||
if args.save_preview:
|
||||
# Save Double hi-res image
|
||||
outfile = os.path.join(
|
||||
os.path.splitext(args.output)[0] + "-preview.png")
|
||||
out_image.save(outfile, "PNG")
|
||||
|
||||
|
||||
def _write(screen: screen_py.DHGRScreen, bitmap: np.ndarray, args):
|
||||
screen.pack(bitmap)
|
||||
with open(args.output, "wb") as f:
|
||||
f.write(bytes(screen.aux))
|
||||
f.write(bytes(screen.main))
|
||||
|
||||
|
||||
def convert(screen: screen_py.DHGRNTSCScreen, image: Image, args):
|
||||
rgb = np.array(image).astype(np.float32) / 255
|
||||
|
||||
# Conversion matrix from RGB to CAM16UCS colour values. Indexed by
|
||||
# 24-bit RGB value
|
||||
base_dir = os.path.dirname(__file__)
|
||||
@ -24,7 +44,7 @@ def convert(screen: screen_py.DHGRScreen, rgb: np.ndarray, args):
|
||||
# Show output image by rendering in target palette
|
||||
output_palette_name = args.show_palette or args.palette
|
||||
output_palette = palette_py.PALETTES[output_palette_name]()
|
||||
output_screen = screen_py.DHGRScreen(output_palette)
|
||||
output_screen = screen_py.DHGRNTSCScreen(output_palette)
|
||||
if output_palette_name == "ntsc":
|
||||
output_srgb = output_screen.bitmap_to_image_ntsc(bitmap)
|
||||
else:
|
||||
@ -34,15 +54,15 @@ def convert(screen: screen_py.DHGRScreen, rgb: np.ndarray, args):
|
||||
Image.fromarray(output_srgb), screen.X_RES, screen.Y_RES * 2,
|
||||
srgb_output=True)
|
||||
|
||||
if args.show_output:
|
||||
out_image.show()
|
||||
_output(out_image, args)
|
||||
_write(screen, bitmap, args)
|
||||
|
||||
if args.save_preview:
|
||||
# Save Double hi-res image
|
||||
outfile = os.path.join(
|
||||
os.path.splitext(args.output)[0] + "-preview.png")
|
||||
out_image.save(outfile, "PNG")
|
||||
screen.pack(bitmap)
|
||||
with open(args.output, "wb") as f:
|
||||
f.write(bytes(screen.aux))
|
||||
f.write(bytes(screen.main))
|
||||
def convert_mono(screen: screen_py.DHGRScreen, image: Image, args):
|
||||
image = image.convert("1")
|
||||
|
||||
out_image = Image.fromarray((np.array(image) * 255).astype(np.uint8))
|
||||
out_image = image_py.resize(
|
||||
out_image, screen.X_RES, screen.Y_RES * 2, srgb_output=True)
|
||||
|
||||
_output(out_image, args)
|
||||
_write(screen, np.array(image).astype(bool), args)
|
||||
|
@ -362,7 +362,9 @@ class ClusterPalette:
|
||||
self._palette_lines[palette_idx] = [worst_line]
|
||||
|
||||
|
||||
def convert(screen, rgb: np.ndarray, args):
|
||||
def convert(screen, image: Image, args):
|
||||
rgb = np.array(image).astype(np.float32) / 255
|
||||
|
||||
# Conversion matrix from RGB to CAM16UCS colour values. Indexed by
|
||||
# 24-bit RGB value
|
||||
base_dir = os.path.dirname(__file__)
|
||||
|
3
image.py
3
image.py
@ -45,3 +45,6 @@ def resize(
|
||||
np.uint8))
|
||||
else:
|
||||
return res
|
||||
|
||||
def resize_mono(image: Image, x_res, y_res) -> Image:
|
||||
return image.resize((x_res, y_res), Image.LANCZOS)
|
||||
|
@ -71,10 +71,9 @@ class DHGRScreen:
|
||||
X_RES = 560
|
||||
Y_RES = 192
|
||||
|
||||
def __init__(self, palette: palette_py.Palette):
|
||||
def __init__(self):
|
||||
self.main = np.zeros(8192, dtype=np.uint8)
|
||||
self.aux = np.zeros(8192, dtype=np.uint8)
|
||||
self.palette = palette
|
||||
|
||||
@staticmethod
|
||||
def y_to_base_addr(y: int) -> int:
|
||||
@ -112,6 +111,11 @@ class DHGRScreen:
|
||||
self.main[addr:addr + 40] = main_col[y, :]
|
||||
return
|
||||
|
||||
class DHGRNTSCScreen(DHGRScreen):
|
||||
def __init__(self, palette: palette_py.Palette):
|
||||
self.palette = palette
|
||||
super(DHGRNTSCScreen, self).__init__()
|
||||
|
||||
def bitmap_to_image_rgb(self, bitmap: np.ndarray) -> np.ndarray:
|
||||
"""Convert our 2-bit bitmap image into a RGB image.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user