Improve /shape/shape_round.py to include enhancement based on a weight matrix, delete...
authorNick Downing <nick.downing@lifx.co>
Fri, 19 Jul 2024 11:20:09 +0000 (03:20 -0800)
committerNick Downing <nick.downing@lifx.co>
Fri, 19 Jul 2024 13:06:52 +0000 (05:06 -0800)
.gitignore
shape/Makefile
shape/shape_enhance.py [deleted file]
shape/shape_mono_to_grey.py [deleted file]
shape/shape_round.py

index e830bcc..4712116 100644 (file)
@@ -45,7 +45,6 @@
 /shape/shape1.png
 /shape/shape2.png
 /shape/shape3.png
-/shape/shape4.png
 /shape/shape_data.inc
 /shape/shape_index.inc
 /shape/sky_blazer_shape.png
index 6829d9a..c199a84 100644 (file)
@@ -18,7 +18,6 @@ shape0d.png \
 shape1.png \
 shape2.png \
 shape3.png \
-shape4.png \
 sky_blazer_shape.png
 
 dhgr_pixel_shape_index.inc: pixel.txt dhgr_shape.txt shape0c.png
@@ -57,10 +56,7 @@ shape2.png: shape0.png
        ./shape_mono_to_color.py $< $@
 
 shape3.png: shape2.png
-       ./shape_round.py $< $@
-
-shape4.png: shape3.png
-       ./shape_enhance.py $< $@
+       ./shape_round.py --enhance $< $@
 
 shape0a.png: shape_hgr.png
        ./shape_color_to_mono.py --hgr $< $@
@@ -124,7 +120,7 @@ pixel_shape_data.inc \
 shape_index.inc \
 shape_data.inc \
 shape0[abcd].png \
-shape[0-4].png \
+shape[0123].png \
 sky_blazer_shape.png \
 Sky\ Blazer\ \(4am\ and\ san\ inc\ crack\).dsk \
 Sky\ Blazer\ \(4am\ and\ san\ inc\ crack\).nib
diff --git a/shape/shape_enhance.py b/shape/shape_enhance.py
deleted file mode 100755 (executable)
index d47897c..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-#!/usr/bin/env python3
-
-import numpy
-import sys
-import PIL.Image
-
-EXIT_SUCCESS = 0
-EXIT_FAILURE = 1
-
-PITCH_X = 256
-PITCH_Y = 64
-
-# see palette.py
-PALETTE = numpy.array(
-  [
-    [0x00, 0x00, 0x00],
-    [0xbc, 0x00, 0x89],
-    [0x00, 0x00, 0xbc],
-    [0xbc, 0x00, 0xe1],
-    [0x00, 0xbc, 0x89],
-    [0x80, 0x80, 0x80], #[0xbc, 0xbc, 0xbc],
-    [0x00, 0xbc, 0xe1],
-    [0xbc, 0xbc, 0xff],
-    [0xbc, 0xbc, 0x00],
-    [0xff, 0xbc, 0x89],
-    [0xc0, 0xc0, 0xc0], #[0xbc, 0xbc, 0xbc],
-    [0xff, 0xbc, 0xe1],
-    [0xbc, 0xff, 0x89],
-    [0xff, 0xff, 0xbc],
-    [0xbc, 0xff, 0xe1],
-    [0xff, 0xff, 0xff],
-  ],
-  numpy.uint8
-)
-
-if len(sys.argv) < 3:
-  print(f'usage: {sys.argv[0]:s} in.png out.png')
-  sys.exit(EXIT_FAILURE)
-in_png = sys.argv[1]
-out_png = sys.argv[2]
-
-image_in_pil = PIL.Image.open(in_png)
-assert image_in_pil.mode == 'P'
-image_in = numpy.frombuffer(
-  image_in_pil.tobytes(),
-  dtype = numpy.uint8
-).reshape((image_in_pil.size[1], image_in_pil.size[0]))
-
-image_out = numpy.zeros((PITCH_Y * 32, PITCH_X * 8), numpy.uint8)
-assert image_out.shape == image_in.shape
-
-for i in range(0x100):
-  j = i & 7
-  k = i >> 3
-  x = j * PITCH_X
-  y = k * PITCH_Y
-  bg = 0xa if (j ^ k) & 1 else 5
-  image_out[y:y + PITCH_Y, x:x + PITCH_X] = bg
-
-  shape = image_in[y:y + PITCH_Y, x:x + PITCH_X]
-  xs = shape.shape[1]
-  while xs:
-    if numpy.any(shape[:, xs - 1] != bg):
-      break
-    xs -= 1
-  else:
-    continue
-  ys = shape.shape[0]
-  while ys:
-    if numpy.any(shape[ys - 1, :] != bg):
-      break
-    ys -= 1
-  else:
-    continue
-  shape = shape[:ys, :xs]
-
-  shape1 = numpy.zeros((ys + 2, xs + 2), numpy.uint8)
-  shape1[1:-1, 1:-1] = shape
-  shape = shape1
-  xs += 2
-  ys += 2
-
-  shape = (
-    (
-      shape[:, :, numpy.newaxis] >>
-        numpy.arange(
-          4,
-          dtype = numpy.int32
-        )[numpy.newaxis, numpy.newaxis, :]
-    ) & 1
-  ).astype(bool)
-
-  T = True
-  F = False
-  shape1 = numpy.copy(shape)
-  for mask, find, _set in [
-    (
-      numpy.array(
-        [
-          [T, T, T, T, F, F],
-          [F, F, T, T, T, T],
-          [T, T, T, T, T, T],
-          [T, T, T, F, F, T],
-        ],
-        bool
-      ),
-      numpy.array(
-        [
-          [F, F, F, F, F, F],
-          [F, F, T, F, F, F],
-          [T, T, T, T, T, F],
-          [T, T, T, F, F, F],
-        ],
-        bool
-      ),
-      numpy.array(
-        [
-          [F, F, F, F, F, F],
-          [F, F, T, T, F, F],
-          [T, T, T, T, T, F],
-          [T, T, T, F, F, F],
-        ],
-        bool
-      )
-    ),
-  ]:
-    yr, xr = mask.shape
-    assert find.shape == (yr, xr)
-    assert _set.shape == (yr, xr)
-  
-    mask = [mask, mask[::-1, :], mask[:, ::-1], mask[::-1, ::-1]]
-    find = [find, find[::-1, :], find[:, ::-1], find[::-1, ::-1]]
-    _set = [_set, _set[::-1, :], _set[:, ::-1], _set[::-1, ::-1]]
-  
-    for j in range(ys + 1 - yr):
-      for k in range(0, xs + 1 - xr):
-        for l in range(4):
-          for m in range(4):
-            if numpy.all(
-              numpy.logical_and(shape[j:j + yr, k:k + xr, l], mask[m]) ==
-                find[m]
-            ):
-              #print('.', end = '')
-              shape1[j:j + yr, k:k + xr, l] |= _set[m]
-  shape = shape1
-
-  shape = shape[1:-1, 1:-1]
-  xs -= 2
-  ys -= 2
-
-  shape = numpy.bitwise_or.reduce(
-    shape <<
-      numpy.arange(
-        4,
-        dtype = numpy.int32
-      )[numpy.newaxis, numpy.newaxis, :],
-    2
-  ).astype(numpy.uint8)
-
-  image_out[y:y + ys, x:x + xs] = shape
-
-image_out_pil = PIL.Image.new(
-  'P',
-  (image_out.shape[1], image_out.shape[0]),
-  None
-)
-image_out_pil.frombytes(image_out.tobytes())
-image_out_pil.putpalette(list(PALETTE.reshape((0x30,))))
-image_out_pil.save(out_png)
diff --git a/shape/shape_mono_to_grey.py b/shape/shape_mono_to_grey.py
deleted file mode 100755 (executable)
index 6ab7e28..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/env python3
-
-import numpy
-import sys
-import PIL.Image
-
-EXIT_SUCCESS = 0
-EXIT_FAILURE = 1
-
-PITCH_X = 256
-PITCH_Y = 64
-
-# see palette.py
-PALETTE = numpy.array(
-  [
-    [0x00, 0x00, 0x00],
-    [0xbc, 0x00, 0x89],
-    [0x00, 0x00, 0xbc],
-    [0xbc, 0x00, 0xe1],
-    [0x00, 0xbc, 0x89],
-    [0x80, 0x80, 0x80], #[0xbc, 0xbc, 0xbc],
-    [0x00, 0xbc, 0xe1],
-    [0xbc, 0xbc, 0xff],
-    [0xbc, 0xbc, 0x00],
-    [0xff, 0xbc, 0x89],
-    [0xc0, 0xc0, 0xc0], #[0xbc, 0xbc, 0xbc],
-    [0xff, 0xbc, 0xe1],
-    [0xbc, 0xff, 0x89],
-    [0xff, 0xff, 0xbc],
-    [0xbc, 0xff, 0xe1],
-    [0xff, 0xff, 0xff],
-  ],
-  numpy.uint8
-)
-
-if len(sys.argv) < 3:
-  print(f'usage: {sys.argv[0]:s} in.png out.png')
-  sys.exit(EXIT_FAILURE)
-in_png = sys.argv[1]
-out_png = sys.argv[2]
-
-image_in_pil = PIL.Image.open(in_png)
-assert image_in_pil.mode == 'P'
-image_in = numpy.frombuffer(
-  image_in_pil.tobytes(),
-  dtype = numpy.uint8
-).reshape((image_in_pil.size[1], image_in_pil.size[0]))
-
-image_out = numpy.zeros((PITCH_Y * 32, PITCH_X * 8), numpy.uint8)
-assert image_out.shape == image_in.shape
-
-for i in range(0x100):
-  j = i & 7
-  k = i >> 3
-  x = j * PITCH_X
-  y = k * PITCH_Y
-  bg = 0xa if (j ^ k) & 1 else 5
-  image_out[y:y + PITCH_Y, x:x + PITCH_X] = bg
-
-  shape = image_in[y:y + PITCH_Y, x:x + PITCH_X]
-  xs = shape.shape[1]
-  while xs:
-    if numpy.any(shape[:, xs - 1] != bg):
-      break
-    xs -= 1
-  else:
-    continue
-  ys = shape.shape[0]
-  while ys:
-    if numpy.any(shape[ys - 1, :] != bg):
-      break
-    ys -= 1
-  else:
-    continue
-  shape = shape[:ys, :xs]
-
-  # only mono input is accepted, convert to bool
-  shape = (
-    (
-      shape >>
-        (numpy.arange(xs, dtype = numpy.int32) & 3)[numpy.newaxis, :]
-    ) & 1
-  ).astype(bool)
-
-  # shrink by one pixel
-  shape = numpy.logical_and(shape[:, :-1], shape[:, 1:])
-  xs -= 1
-
-  # expand by 2 pixels
-  shape1 = numpy.zeros((ys, xs + 4), bool)
-  shape1[:, 2:-2] = shape
-  shape = numpy.logical_or(shape1[:, :-2], shape1[:, 2:])
-  xs += 2
-
-  # for now just lop off overflow
-  shape = shape[:, :-1]
-  xs -= 1
-
-  image_out[y:y + ys, x:x + xs] = shape * 0xf
-
-image_out_pil = PIL.Image.new(
-  'P',
-  (image_out.shape[1], image_out.shape[0]),
-  None
-)
-image_out_pil.frombytes(image_out.tobytes())
-image_out_pil.putpalette(list(PALETTE.reshape((0x30,))))
-image_out_pil.save(out_png)
index 88a92d7..b767d6a 100755 (executable)
@@ -33,16 +33,40 @@ PALETTE = numpy.array(
   numpy.uint8
 )
 
+enhance = False
 mono = False
-if len(sys.argv) >= 2 and sys.argv[1] == '--mono':
-  mono = True
-  del sys.argv[1]
+while True:
+  if len(sys.argv) >= 2 and sys.argv[1] == '--enhance':
+    enhance = True
+    del sys.argv[1]
+  elif len(sys.argv) >= 2 and sys.argv[1] == '--mono':
+    mono = True
+    del sys.argv[1]
+  else:
+    break
 if len(sys.argv) < 3:
-  print(f'usage: {sys.argv[0]:s} [--mono] in.png out.png')
+  print(f'usage: {sys.argv[0]:s} [--enhance] [--mono] in.png out.png')
   sys.exit(EXIT_FAILURE)
 in_png = sys.argv[1]
 out_png = sys.argv[2]
 
+weight = numpy.array(
+  [
+    [0, 0, 1, 0, 0],
+    [1, 1, 1, 1, 1],
+    [1, 1, 1, 1, 1],
+    [0, 0, 1, 0, 0],
+  ],
+  numpy.uint8
+)
+if mono:
+  weight = weight[:, 1:-1]
+if not enhance:
+  weight = weight[1:-1, :]
+threshold = numpy.sum(weight)
+if enhance:
+  threshold -= 2
+
 image_in_pil = PIL.Image.open(in_png)
 assert image_in_pil.mode == 'P'
 image_in = numpy.frombuffer(
@@ -78,19 +102,6 @@ for i in range(0x100):
     continue
   shape = shape[:ys, :xs]
 
-  if mono:
-    shape1 = numpy.zeros((ys + 2, xs + 2), numpy.uint8)
-    shape1[1:-1, 1:-1] = shape
-    shape = shape1
-    xs += 2
-    ys += 2
-  else:
-    shape1 = numpy.zeros((ys + 2, xs + 4), numpy.uint8)
-    shape1[1:-1, 2:-2] = shape
-    shape = shape1
-    xs += 4
-    ys += 2
-
   shape = (
     (
       shape[:, :, numpy.newaxis] >>
@@ -99,35 +110,23 @@ for i in range(0x100):
           dtype = numpy.int32
         )[numpy.newaxis, numpy.newaxis, :]
     ) & 1
-  ).astype(numpy.uint8)
+  ).astype(bool)
 
-  if mono:
-    shape = (
-      shape[:-1, :-2] +
-        shape[:-1, 1:-1] +
-        shape[:-1, 2:] +
-        shape[1:, :-2] +
-        shape[1:, 1:-1] +
-        shape[1:, 2:]
-    ) >= 3
-    xs -= 2
-    ys -= 1
-  else:
-    shape = (
-      shape[:-1, :-3] +
-        shape[:-1, 1:-2] +
-        shape[:-1, 2:-1] +
-        shape[:-1, 3:] +
-        shape[1:, :-3] +
-        shape[1:, 1:-2] +
-        shape[1:, 2:-1] +
-        shape[1:, 3:]
-    ) >= 4
-    xs -= 3
-    ys -= 1
+  ye = weight.shape[0] // 2
+  xe = weight.shape[1] // 2
+  shape1 = numpy.zeros((ys + ye * 2, xs + xe * 2, 4), bool)
+  shape1[ye:ye + ys, xe:xe + xs, :] = shape
+
+  ys += (weight.shape[0] & 1) == 0
+  xs += (weight.shape[1] & 1) == 0
+  shape = numpy.zeros((ys, xs, 4), numpy.uint8)
+  for i in range(weight.shape[0]):
+    for j in range(weight.shape[1]):
+      shape += weight[i, j] * shape1[i:ys + i, j:xs + j, :]
+  shape = shape * 2 >= threshold
 
   shape = numpy.bitwise_or.reduce(
-    shape <<
+    shape.astype(numpy.uint8) <<
       numpy.arange(
         4,
         dtype = numpy.int32