dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
encode_images.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 
3 from string import Template
4 from itertools import chain, repeat
5 
6 import numpy as np
7 import matplotlib.pyplot as plt
8 import matplotlib.image as mpimg
9 
10 img_c_typedef_split = """
11 
12 struct Image {
13 \tuint16_t width;
14 \tuint16_t height;
15 \tuint8_t* mask;
16 \tuint8_t* level;
17 };
18 
19 """
20 
21 img_c_template_split = Template("""
22 static const struct Image image_$name = {
23 \t.width = $width,
24 \t.height = $height,
25 \t.mask = (uint8_t*)mask_$name,
26 \t.level = (uint8_t*)level_$name,
27 };
28 
29 """)
30 
31 img_c_typedef = """
32 
33 struct Image {
34 \tuint16_t width;
35 \tuint16_t height;
36 \tuint8_t* data;
37 };
38 
39 """
40 
41 img_c_template = Template("""
42 static const struct Image image_$name = {
43 \t.width = $width,
44 \t.height = $height,
45 \t.data = (uint8_t*)data_$name,
46 };
47 
48 """)
49 
50 def grouper(n, iterable, padvalue=None):
51  "grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x')"
52  return zip(*[chain(iterable, repeat(padvalue, n-1))]*n)
53 
54 def encode_image(fname):
55  img = img=mpimg.imread(fname)
56  height, width, depth = img.shape
57  print('Encoding %s: %d x %d pixels' % (fname, width, height))
58  gray = np.max(img[:, :, :3], axis=-1)
59  bw = gray > 0.9
60 
61  if depth == 4:
62  alpha = img[:, :, -1]
63  mask = alpha > 0.5
64  elif depth == 3:
65  mask = np.logical_or(gray < 0.1, gray > 0.9)
66 
67  # width in bytes
68  byte_width_split = int(np.ceil(width / float(8)))
69  # buffers for OSDs with split level/mask buffers
70  mask_buffer = np.zeros((height, byte_width_split), dtype=np.uint8)
71  level_buffer = np.zeros((height, byte_width_split), dtype=np.uint8)
72  # buffer for OSDs with a single buffer
73  byte_width = int(np.ceil(width / float(4)))
74  data_buffer = np.zeros((height, byte_width), dtype=np.uint8)
75 
76  for row in range(height):
77  for col in range(width):
78  if mask[row, col]:
79  pos = int(col / 8)
80  mask_buffer[row, pos] |= 0x01 << (7 - (col % 8))
81  level_buffer[row, pos] |= bw[row, col] << (7 - (col % 8))
82  pos = int(col / 4)
83  data_buffer[row, pos] |= (bw[row, col] << (7 - 2 * (col % 4))) | (0x01 << (6 - 2 * (col % 4)))
84  image = dict(width=4*byte_width, width_split=8*byte_width_split, height=height, mask=mask_buffer,
85  level=level_buffer, data=data_buffer)
86  return image
87 
88 
89 
90 def c_format_image(fid, name, image, buffers, row_width=16):
91  """Format image as a C header"""
92  for buf in buffers:
93  fid.write('static const uint8_t %s_%s[] = {\n' % (buf, name))
94  n_rows = np.ceil(len(image[buf].ravel()) / float(row_width))
95  for ii, row in enumerate(grouper(row_width, image[buf].ravel())):
96  row = [val for val in row if val is not None]
97  fid.write('\t')
98 
99  for byte in row[:-1]:
100  fid.write('0x%0.2x, ' % byte)
101  if ii < n_rows - 1:
102  fid.write('0x%0.2x,\n' % row[-1])
103  else:
104  fid.write('0x%0.2x\n};\n' % row[-1])
105 
106 if __name__ == '__main__':
107  from optparse import OptionParser
108  parser = OptionParser()
109  parser.add_option('-o', '--out', dest='filename_out',
110  help='Output file', metavar='FILE')
111 
112  options, args = parser.parse_args()
113 
114  in_files = args
115  print('Input images: %s' % str(in_files))
116  images = dict()
117  for fname in in_files:
118  images[fname[:-4]] = encode_image(fname)
119 
120  with open(options.filename_out, 'w') as fid:
121  fid.write('#ifndef IMAGES_H\n#define IMAGES_H\n')
122  fid.write('#if defined(PIOS_VIDEO_SPLITBUFFER)\n')
123  fid.write(img_c_typedef_split)
124  for name, image in images.items():
125  c_format_image(fid, name, image, buffers=('level', 'mask'))
126  fid.write(img_c_template_split.substitute(width=image['width_split'],
127  height=image['height'], name=name))
128  fid.write('#else /* defined(PIOS_VIDEO_SPLITBUFFER) */\n')
129  fid.write(img_c_typedef)
130  for name, image in images.items():
131  c_format_image(fid, name, image, buffers=('data',))
132  fid.write(img_c_template.substitute(width=image['width'],
133  height=image['height'], name=name))
134  fid.write('#endif /* defined(PIOS_VIDEO_SPLITBUFFER) */\n')
135  fid.write('#endif /* IMAGES_H */\n')
static int print(char **out, const char *format, va_list args)