pdc_gen.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. # Copyright 2024 Google LLC
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. '''
  15. PDC_GEN converts SVG images, SVG sequences, or JSON sequences to a PDC (Pebble Draw Command) binary format image or sequence. The PDC file format
  16. consists of a header, followed by the binary representation of a PDC image or sequence.
  17. The file header is as follows:
  18. Magic Word (4 bytes) - 'PDCI' for image, 'PDCS' for sequence
  19. Size (4 bytes) - size of PDC image or sequence following the header in bytes
  20. '''
  21. import os
  22. import argparse
  23. from . import pebble_commands
  24. from . import svg2commands
  25. from . import json2commands
  26. def create_pdc_data_from_path(path, viewbox_size, verbose, duration, play_count,
  27. precise=False, raise_error=False):
  28. dir_name = path
  29. output = ''
  30. errors = []
  31. if not os.path.exists(path):
  32. raise Exception("Invalid path")
  33. if verbose:
  34. print(path + ":")
  35. if os.path.isfile(path):
  36. dir_name = os.path.dirname(path)
  37. frames = []
  38. commands = []
  39. if os.path.isfile(path):
  40. ext = os.path.splitext(path)[-1]
  41. if ext == '.json':
  42. # JSON file
  43. result = json2commands.parse_json_sequence(path, viewbox_size, precise, raise_error)
  44. if result:
  45. frames = result[0]
  46. errors += result[1]
  47. frame_duration = result[2]
  48. output = pebble_commands.serialize_sequence(
  49. frames, viewbox_size, frame_duration, play_count)
  50. elif ext == '.svg':
  51. # SVG file
  52. size, commands, error = svg2commands.parse_svg_image(path, verbose, precise,
  53. raise_error)
  54. if commands:
  55. output = pebble_commands.serialize_image(commands, size)
  56. if error:
  57. errors += [path]
  58. else:
  59. # SVG files
  60. # get all .svg files in directory
  61. result = svg2commands.parse_svg_sequence(dir_name, verbose, precise, raise_error)
  62. if result:
  63. frames = result[1]
  64. size = result[0]
  65. errors += result[2]
  66. output = pebble_commands.serialize_sequence(frames, size, duration, play_count)
  67. if verbose:
  68. if frames:
  69. pebble_commands.print_frames(frames)
  70. elif commands:
  71. pebble_commands.print_commands(commands)
  72. return output, errors
  73. def create_pdc_from_path(path, out_path, viewbox_size, verbose, duration, play_count,
  74. precise=False, raise_error=False):
  75. output, errors = create_pdc_data_from_path(path, viewbox_size, verbose, duration, play_count,
  76. precise=False, raise_error=False)
  77. if output != '':
  78. if out_path is None:
  79. if sequence:
  80. f = os.path.basename(dir_name.rstrip('/')) + '.pdc'
  81. else:
  82. base = os.path.basename(path)
  83. f = '.'.join(base.split('.')[:-1]) + '.pdc'
  84. out_path = os.path.join(dir_name, f)
  85. with open(out_path, 'wb') as out_file:
  86. out_file.write(output)
  87. out_file.close()
  88. return errors
  89. def main(args):
  90. path = os.path.abspath(args.path)
  91. viewbox_size = (args.viewbox_x, args.viewbox_y)
  92. errors = create_pdc_from_path(path, args.output, viewbox_size, args.verbose, args.duration,
  93. args.play_count, args.precise)
  94. if errors:
  95. print("Errors in the following files or frames:")
  96. for ef in errors:
  97. print("\t" + str(ef))
  98. if __name__ == '__main__':
  99. parser = argparse.ArgumentParser()
  100. parser.add_argument('path', type=str,
  101. help="Path to svg file or directory (with multiple svg files)")
  102. parser.add_argument('-o', '--output', type=str,
  103. help="Output file path (.pdc will be appended to file name if it is not included in the path "
  104. "specified")
  105. parser.add_argument('-v', '--verbose', action='store_true',
  106. help="Verbose output")
  107. parser.add_argument('-d', '--duration', type=int, default=33,
  108. help="Duration (ms) of each frame in a sequence (SVG sequence only) - default = 33ms")
  109. parser.add_argument('-c', '--play_count', type=int, default=1,
  110. help="Number of times the sequence should play - default = 1")
  111. parser.add_argument('-p', '--precise', action='store_true',
  112. help="Use sub-pixel precision for paths")
  113. parser.add_argument('-x', '--viewbox_x', help="Viewbox length (JSON sequence only)",
  114. type=int, default=json2commands.DISPLAY_DIM_X)
  115. parser.add_argument('-y', '--viewbox_y', help="Viewbox height (JSON sequence only)",
  116. type=int, default=json2commands.DISPLAY_DIM_Y)
  117. args = parser.parse_args()
  118. main(args)