No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

convert_sparkmaker.py 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #!/usr/bin/env python
  2. import sys
  3. import os
  4. from zipfile import ZipFile
  5. import re
  6. import pprint
  7. import png
  8. ###############################################################################
  9. screen_size = (854, 480)
  10. max_height = 120
  11. initial_params = {
  12. 'layer_height': 0.1,
  13. 'first_layer_height': 0.1,
  14. 'exposure_time': 15.0,
  15. 'first_exposure_time': 120.0,
  16. 'lift_height': 5.0,
  17. 'lift_speed': 30.0,
  18. 'sink_speed': 100.0
  19. }
  20. ###############################################################################
  21. def read_prusaslicer_ini(f, params):
  22. lines = f.decode("utf-8").split("\n")
  23. for l in lines:
  24. if l.startswith("exposure_time"):
  25. params["exposure_time"] = float(l.split(" = ")[1])
  26. elif l.startswith("initial_exposure_time"):
  27. params["first_exposure_time"] = float(l.split(" = ")[1])
  28. elif l.startswith("layer_height"):
  29. params["layer_height"] = float(l.split(" = ")[1])
  30. elif l.startswith("initial_layer_height"):
  31. params["first_layer_height"] = float(l.split(" = ")[1])
  32. def read_config_ini(f, params):
  33. lines = f.decode("utf-8").split("\n")
  34. for l in lines:
  35. if l.startswith("expTimeFirst"):
  36. params["first_exposure_time"] = float(l.split(" = ")[1])
  37. elif l.startswith("expTime"):
  38. params["exposure_time"] = float(l.split(" = ")[1])
  39. elif l.startswith("layerHeight"):
  40. params["layer_height"] = float(l.split(" = ")[1])
  41. def read_sl1(f):
  42. params = initial_params
  43. files = f.namelist()
  44. if "prusaslicer.ini" in files:
  45. read_prusaslicer_ini(f.read("prusaslicer.ini"), params)
  46. else:
  47. print("No prusaslicer.ini found in file")
  48. if "config.ini" in files:
  49. read_config_ini(f.read("config.ini"), params)
  50. else:
  51. print("No config.ini found in file")
  52. sys.exit(1)
  53. imgs = [x for x in files if x.endswith(".png")]
  54. imgs = [x for x in imgs if not x.startswith("thumbnail/")]
  55. if len(imgs) <= 0:
  56. print("No slices found in file. Aborting.")
  57. sys.exit(1)
  58. res = re.findall('(\D*)\d*.*', imgs[0])[0]
  59. print("Internal name: \"" + res + "\"")
  60. print("Found " + str(len(imgs)) + " slices")
  61. images = []
  62. for img in imgs:
  63. images.append(f.read(img))
  64. return params, images
  65. ###############################################################################
  66. def write_image(f, img):
  67. p = png.Reader(bytes = img)
  68. width, height, rows, info = p.read()
  69. if width != screen_size[0]:
  70. print("Error: layer has wrong width " + str(width) + " != " + str(screen_size[0]))
  71. sys.exit(1)
  72. if height != screen_size[1]:
  73. print("Error: layer has wrong height " + str(height) + " != " + str(screen_size[1]))
  74. sys.exit(1)
  75. if (not info['greyscale']) or info['alpha']:
  76. print("Error: invalid image encoding")
  77. sys.exit(1)
  78. data = [0] * int(width * height / 8)
  79. y = 0 # width is 854
  80. x = 0 # height is 480
  81. for row in rows:
  82. for v in row:
  83. if v > 0x7F:
  84. data[int(height / 8) * y + int(x / 8)] |= (1 << x % 8)
  85. y += 1
  86. x += 1
  87. y = 0
  88. for d in data:
  89. f.write(d.to_bytes(1, 'big'))
  90. def write_wow(f, params, imgs):
  91. def write(s):
  92. #print(s)
  93. f.write((s + "\n").encode())
  94. write("G21;")
  95. write("G91;")
  96. write("M17;")
  97. write("M106 S0;")
  98. write("G28 Z0;")
  99. first_layer = True
  100. for i in range(0, len(imgs)):
  101. write(";L:" + str(int(i)) + ";")
  102. write("M106 S0;")
  103. lift_up = params['lift_height']
  104. lift_down = -(lift_up - params['layer_height'])
  105. exposure_time = params['exposure_time']
  106. if first_layer:
  107. lift_down = -(lift_up - params['first_layer_height'])
  108. exposure_time = params['first_exposure_time']
  109. first_layer = False
  110. write("G1 Z" + str(lift_up) + " F" + str(params['lift_speed']) + ";")
  111. write("G1 Z" + str(lift_down) + " F" + str(params['sink_speed']) + ";")
  112. write("{{")
  113. write_image(f, imgs[i])
  114. write("}}")
  115. write("M106 S255;")
  116. write("G4 S" + str(exposure_time) + ";")
  117. write("G4 S1;")
  118. object_height = params['layer_height'] * (len(imgs) - 1) + params['first_layer_height']
  119. final_move = max_height - object_height
  120. write("M106 S0;")
  121. write("G1 Z" + str(final_move) + " F25;")
  122. write("M18;")
  123. ###############################################################################
  124. def main():
  125. if len(sys.argv) < 2:
  126. print("Usage:")
  127. print(" " + sys.argv[0] + " input.sl1 [output.wow]")
  128. sys.exit(1)
  129. in_file_name = sys.argv[1]
  130. out_file_name = "print.wow"
  131. if len(sys.argv) >= 3:
  132. out_file_name = sys.argv[2]
  133. if os.path.exists(out_file_name):
  134. print("File already exists: \"" + out_file_name + "\". Aborting.")
  135. sys.exit(1)
  136. with ZipFile(in_file_name, 'r') as sl1:
  137. params, imgs = read_sl1(sl1)
  138. print("Using following parameters:")
  139. pprint.pprint(params)
  140. print("Writing output to \"" + out_file_name + "\"")
  141. with open(out_file_name, 'wb') as wow:
  142. write_wow(wow, params, imgs)
  143. if __name__ == '__main__':
  144. main()