diff --git a/.idea/Trac3r.iml b/.idea/Trac3r.iml new file mode 100644 index 0000000..6711606 --- /dev/null +++ b/.idea/Trac3r.iml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index e4b0da7..0000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..a4ec689 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..10d63ed --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/other.xml b/.idea/other.xml new file mode 100644 index 0000000..a708ec7 --- /dev/null +++ b/.idea/other.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Renderer.py b/GCodeRenderer.py similarity index 53% rename from Renderer.py rename to GCodeRenderer.py index ffd3678..af683a1 100644 --- a/Renderer.py +++ b/GCodeRenderer.py @@ -1,33 +1,32 @@ import cairo, os, math +import Svg2GcodeConverter - +# This renderer takes the generated GCODE and turns it into two images +# One is an SVG of the tool paths, the other a png image class Renderer(): def __init__(self, settings): self.settings = settings - self.svg_surface = cairo.SVGSurface("tmp/rendered-output-t.svg", self.settings.bed_actual_x, self.settings.bed_actual_y) + self.svg_surface = cairo.SVGSurface("tmp/rendered-output-t.svg", self.settings.canvas_x, self.settings.canvas_y) self.svg_context = cairo.Context(self.svg_surface) self.svg_context.scale(1, 1) self.svg_context.set_line_width(0.1) def clear_screen(self): - self.svg_context.rectangle(0, 0, self.settings.bed_actual_x, self.settings.bed_actual_y) - self.svg_context.set_source_rgba(1, 1, 1, 1.0) - self.svg_context.fill() - self.svg_context.set_source_rgba(0, 0, 0, 1.0) - self.svg_context.stroke() - - self.svg_context.set_source_rgba(1, 0, 0, 1.0) - self.svg_context.line_to(self.settings.bed_min_x - self.settings.head_x_offset, self.settings.bed_min_y) - self.svg_context.line_to(self.settings.bed_max_x - self.settings.head_x_offset, self.settings.bed_min_y) - self.svg_context.line_to(self.settings.bed_max_x - self.settings.head_x_offset, self.settings.bed_max_y) - self.svg_context.line_to(self.settings.bed_min_x - self.settings.head_x_offset, self.settings.bed_max_y) - self.svg_context.line_to(self.settings.bed_min_x - self.settings.head_x_offset, self.settings.bed_min_y) - self.svg_context.stroke() - self.svg_context.set_source_rgba(0, 0, 0, 1.0) + self.svg_surface.finish() + self.svg_surface = cairo.SVGSurface("tmp/rendered-output-t.svg", self.settings.canvas_x, self.settings.canvas_y) + self.svg_context = cairo.Context(self.svg_surface) + self.svg_context.scale(1, 1) + self.svg_context.set_line_width(0.1) + + # self.svg_context.rectangle(0, 0, self.settings.canvas_x, self.settings.canvas_y) + # self.svg_context.set_source_rgba(1, 1, 1, 1.0) + # self.svg_context.fill() + # self.svg_context.set_source_rgba(0, 0, 0, 1.0) + # self.svg_context.stroke() # Render GCODE from the gcode-output.gcode output file that was generated in convert_gcode def render_gcode(self): @@ -36,8 +35,8 @@ class Renderer(): largest_x = 0 largest_y = 0 - smallest_x = 300 - smallest_y = 300 + smallest_x = 99999999 + smallest_y = 99999999 x = None y = None @@ -60,14 +59,16 @@ class Renderer(): y = float(operand[1:]) if y > largest_y: largest_y = y if y < smallest_y: smallest_y = y - elif operand.startswith("Z{}".format(self.settings.touch_height + self.settings.raise_height)): + elif operand.startswith("Z{}".format(1)): # signify a lift if prev_x is not None and prev_y is not None and self.settings.lift_markers: - self.svg_context.arc(prev_x - self.settings.head_x_offset, prev_y, 0.5, 0, 2 * math.pi) + # draw a cirlce at the lift + self.svg_context.arc(prev_x, prev_y, 0.5, 0, 2 * math.pi) self.svg_context.stroke() + # And draw the lift number self.svg_context.set_source_rgba(1, 1, 1, 1.0) self.svg_context.select_font_face("Purisa", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) @@ -84,8 +85,12 @@ class Renderer(): y = None if (prev_x != x and prev_x is not None) or (prev_y != y and prev_y is not None): - self.svg_context.line_to(prev_x - self.settings.head_x_offset, prev_y) - self.svg_context.line_to(x - self.settings.head_x_offset, y) + prev = Svg2GcodeConverter.untriangulate_lengths(self.settings, prev_x, prev_y) + this = Svg2GcodeConverter.untriangulate_lengths(self.settings, x, y) + #self.svg_context.line_to(prev_x, prev_y) + #self.svg_context.line_to(x, y) + self.svg_context.line_to(prev[0], prev[1]) + self.svg_context.line_to(this[0], this[1]) self.svg_context.stroke() print("Largest X : " + str(largest_x)) @@ -94,25 +99,16 @@ class Renderer(): print("Largest Y : " + str(largest_y)) print("Smallest Y : " + str(smallest_y)) - if largest_x > self.settings.bed_max_x: + if largest_x > self.settings.canvas_x: print("X OVERFLOW") - if largest_y > self.settings.bed_max_y: + if largest_y > self.settings.canvas_y: print("Y OVERFLOW") - if smallest_x < self.settings.bed_min_x: + if smallest_x < 0: print("X_UNDERFLOW") - if smallest_y < self.settings.bed_min_y: + if smallest_y < 0: print("Y_UNDERFLOW") - self.svg_context.set_source_rgba(0, 0, 1, 1.0) - self.svg_context.line_to(smallest_x - self.settings.head_x_offset, smallest_y) - self.svg_context.line_to(largest_x - self.settings.head_x_offset, smallest_y) - self.svg_context.line_to(largest_x - self.settings.head_x_offset, largest_y) - self.svg_context.line_to(smallest_x - self.settings.head_x_offset, largest_y) - self.svg_context.line_to(smallest_x - self.settings.head_x_offset, smallest_y) - self.svg_context.stroke() - self.svg_context.set_source_rgba(0, 0, 0, 1.0) - self.save_surfaces() # self.init_surfaces() @@ -123,21 +119,8 @@ class Renderer(): # Save the SVG so we can view it, then immediately reopen it so it's ready for a re-render self.svg_surface.finish() os.rename("tmp/rendered-output-t.svg", "tmp/rendered-output.svg") - self.svg_surface = cairo.SVGSurface("tmp/rendered-output-t.svg", self.settings.bed_actual_x, self.settings.bed_actual_y) + self.svg_surface = cairo.SVGSurface("tmp/rendered-output-t.svg", self.settings.canvas_x, self.settings.canvas_y) self.svg_context = cairo.Context(self.svg_surface) - # def render(self): - # self.clear_screen() - # # self.render_gcode() - # # - # # if self.label is not None: - # # self.label.pack_forget() - # # - # # # Apply the rendered gcode image to the UI - # # self.image_ref = ImageTk.PhotoImage( - # # Image.frombuffer("RGBA", (self.bed_actual_x, self.bed_actual_y), self.png_surface.get_data().tobytes(), "raw", "BGRA", 0, 1)) - # # self.label = Label(self, image=self.image_ref) - # # self.label.pack(expand=True, fill="both") - def toggle_flip_markers(self): self.settings.lift_markers = not self.settings.lift_markers \ No newline at end of file diff --git a/ImageConverter.py b/ImageConverter.py new file mode 100644 index 0000000..a20073f --- /dev/null +++ b/ImageConverter.py @@ -0,0 +1,57 @@ +import subprocess, os, time + +class ImageConverter: + + class ConverterSettings: + def __init__(self): + # mkbitmap settings + self.highpass_filter = 0 + self.blur = 0 + # potrace settings + self.turd = 0 + + # This function takes a file and runs it through mogrify, mkbitmap, and finally potrace. + # The flow of the intermediate files is + # input_file.extension : The input file + # input_file.bmp : The input file converted to bmp + # input_file-n.bmp : The bmp file after running through some filters + # input_file.svg : The output svg render + def convert_image(self, file_name, settings): + base_name = file_name.split(".")[0] + + print("Converting input file [{}]".format(file_name)) + + print("Running mogrify...") + start = time.time() + subprocess.call(["mogrify", "-format", "bmp", "input-images/{}".format(file_name)]) + print("Run took [{:.2f}] seconds".format(time.time() - start)) + + print("Running mkbitmap...") + start = time.time() + mkbitmap_args = ["mkbitmap", "input-images/{}.bmp".format(base_name), + "-o", "input-images/{}-n.pbm".format(base_name)] + if settings.highpass_filter > 0: + mkbitmap_args.append(["-f", settings.highpass_filter]) + + if settings.blur > 0: + mkbitmap_args.append(["-b", settings.blur]) + + subprocess.call(mkbitmap_args) + print("Run took [{:.2f}] seconds".format(time.time() - start)) + + print("Running potrace...") + start = time.time() + + potrace_args = ["potrace", + "-z", "white", + "-b", "svg", + "input-images/{}-n.pbm".format(base_name), + "--rotate", "0", + "-o", "tmp/conversion-output.svg"] + + if settings.turd > 0: + potrace_args.append(["-t", settings.turd]) + + subprocess.call(potrace_args) + + print("Run took [{:.2f}] seconds\n".format(time.time() - start)) \ No newline at end of file diff --git a/Simulator.py b/Simulator.py new file mode 100644 index 0000000..8fd4312 --- /dev/null +++ b/Simulator.py @@ -0,0 +1,45 @@ +import sys, pygame +import threading + + + +class EventThread(threading.Thread): + def __init__(self): + super(EventThread, self).__init__() + + def run(self): + while True: + for events in pygame.event.get(): + if events.type == pygame.QUIT: + pygame.display.quit() + pygame.quit() + + +class Simulator: + def __init__(self): + + pygame.init() + + self.size = width, height = 320, 240 + self.black = 0, 0, 0 + self.red=(255,0,0) + + self.screen = pygame.display.set_mode(self.size) + + def render(self): + + self.screen.fill(self.black) + pygame.draw.line(self.screen, self.red, (60, 80), (130, 100)) + pygame.display.flip() + t = EventThread() + t.start() + + + + + + + + + + diff --git a/Svg2GcodeConverter.py b/Svg2GcodeConverter.py index b560694..8915c93 100644 --- a/Svg2GcodeConverter.py +++ b/Svg2GcodeConverter.py @@ -1,6 +1,40 @@ from svgpathtools import svg2paths, Line, QuadraticBezier, CubicBezier import numpy as np -import bezier +import bezier, math + + +def triangulate_lengths(settings, dest_xy): + + left_pulley_position = (settings.left_pulley_x_offset, -settings.pulley_y_droop) + right_pulley_position = (settings.right_pulley_x_offset + settings.canvas_x, -settings.pulley_y_droop) + + right_squared_x = pow(right_pulley_position[0] - dest_xy[0], 2) + right_squared_y = pow(right_pulley_position[1] - dest_xy[1], 2) + + left_squared_x = pow(left_pulley_position[0] - dest_xy[0], 2) + left_squared_y = pow(left_pulley_position[1] - dest_xy[1], 2) + + right_pulley_length = math.sqrt(right_squared_x + right_squared_y) + left_pulley_length = math.sqrt(left_squared_x + left_squared_y) + + return left_pulley_length, right_pulley_length + +# http://paulbourke.net/geometry/circlesphere/ +# https://math.stackexchange.com/questions/187107/calculate-coordinates-of-3rd-point-vertex-of-a-scalene-triangle-if-angles-and +# http://xaktly.com/MathNonRightTrig.html +def untriangulate_lengths(settings, x, y): + + r0 = x + r1 = y + r2 = settings.distance_between_centers + + a = (pow(r0, 2) - pow(r1, 2) + pow(r2, 2)) / (2 * r2) + h = math.sqrt(pow(r0, 2) - pow(a, 2)) + + a = a + settings.left_pulley_x_offset + h = h - settings.pulley_y_droop + + return a, h class Svg2GcodeConverter: @@ -12,24 +46,20 @@ class Svg2GcodeConverter: # First cycle base case flag self.started = False + starting_xy = triangulate_lengths(self.settings, (self.settings.canvas_x/2, 0)) + self.gcode_preamble = ''' G91 ; Set to relative mode for the initial pen lift - G1 Z20 ; Lift head by 20 - G90 ; Set back to absolute position mode - M107 ; Fan off - M190 S0 ; Set bed temp - M104 S0 ; Set nozzle temp - G28 ; home all axes + G1 Z1 ; Lift head by 1 G0 F{1} ; Set the feed rate G1 Z{0} ; Move the pen to just above the paper - '''.format(self.settings.touch_height + self.settings.raise_height, self.settings.speed) + G90 + G92 X{2} Y{3} + '''.format(1, self.settings.speed, starting_xy[0], starting_xy[1]) self.gcode_end = ''' - G1 Z{0} F7000 ; Raise the pen high up so we can fit a cap onto it - M104 S0 ; Set the nozzle to 0 - G28 X0 Y0 ; Home back to (0,0) for (x,y) - M84 ; Turn off the motors - '''.format(75) + G1 Z{0} F7000 ; Raise the pen + '''.format(1) # From an input svg file, convert the vector svg paths to gcode tool paths def convert_gcode(self): @@ -70,8 +100,8 @@ class Svg2GcodeConverter: max_x_dim = max(bounding_x_max, bounding_x_min) max_y_dim = max(bounding_y_max, bounding_y_min) - scale_x = (self.settings.bed_max_x - self.settings.bed_min_x) / max_x_dim - scale_y = (self.settings.bed_max_y - self.settings.bed_min_y) / max_y_dim + scale_x = self.settings.canvas_x / max_x_dim + scale_y = self.settings.canvas_y / max_y_dim scale = min(scale_x, scale_y) print("Scaling to : {:.5f}\n".format(scale)) @@ -91,11 +121,11 @@ class Svg2GcodeConverter: start = part.start end = part.end - start_x = start.real * scale + self.settings.offset_x - start_y = start.imag * scale + self.settings.offset_y + start_x = start.real * scale + start_y = start.imag * scale - end_x = end.real * scale + self.settings.offset_x - end_y = end.imag * scale + self.settings.offset_y + end_x = end.real * scale + end_y = end.imag * scale # Check to see if the endpoint of the last cycle continues and whether we need to lift the pen or not lift = True @@ -109,9 +139,9 @@ class Svg2GcodeConverter: previous_y = end.imag if lift: - gcode += "G1 Z{:.3f}\n".format(self.settings.raise_height + self.settings.touch_height) + gcode += "G1 Z{:.3f}\n".format(1) else: - gcode += ";# NOT LIFTING [{}]\n".format(self.settings.lift_counter) + gcode += "; NOT LIFTING [{}]\n".format(self.settings.lift_counter) if isinstance(part, CubicBezier): @@ -127,18 +157,27 @@ class Svg2GcodeConverter: for i in pos: evals.append(curve.evaluate(i)) - gcode += "G1 X{:.3f} Y{:.3f}\n".format(start_x, start_y) - gcode += "G1 Z{:.3f} \n".format(self.settings.touch_height) + lengths = triangulate_lengths(self.settings, (start_x, start_y)) + # gcode += "; Setting down tip at beginning of line ({}, {})\n".format(start_x, start_y) + gcode += "G1 X{:.3f} Y{:.3f}\n".format(lengths[0], lengths[1]) + gcode += "G1 Z{:.3f} \n".format(0) for i in evals: x = i[0][0] y = i[1][0] - gcode += "G1 X{:.3f} Y{:.3f}\n".format(x * scale + self.settings.offset_x, y * scale + self.settings.offset_y) + tmp_len = triangulate_lengths(self.settings, (x * scale, y * scale)) + # gcode += "; Continuing the line ({}, {})\n".format(x * scale, y * scale) + gcode += "G1 X{:.3f} Y{:.3f}\n".format(tmp_len[0], tmp_len[1]) if isinstance(part, Line): - gcode += "G1 X{:.3f} Y{:.3f}\n".format(start_x, start_y) - gcode += "G1 Z{:.3f} \n".format(self.settings.touch_height) - gcode += "G1 X{:.3f} Y{:.3f}\n".format(end_x, end_y) + start_len = triangulate_lengths(self.settings, (start_x, start_y)) + end_len = triangulate_lengths(self.settings, (end_x, end_y)) + + # gcode += "; Setting down tip at beginning of line ({}, {})\n".format(start_x, start_y) + gcode += "G1 X{:.3f} Y{:.3f}\n".format(start_len[0], start_len[1]) + gcode += "G1 Z{:.3f} \n".format(0) + # gcode += "; Moving tip to the end of the line ({}, {})\n".format(end_x, end_y) + gcode += "G1 X{:.3f} Y{:.3f}\n".format(end_len[0], end_len[1]) gcode += self.gcode_end diff --git a/input-images/funky-bird.jpg b/input-images/funky-bird.jpg new file mode 100755 index 0000000..d4d1dc1 Binary files /dev/null and b/input-images/funky-bird.jpg differ diff --git a/input-images/leaf.jpg b/input-images/leaf.jpg new file mode 100755 index 0000000..21d9015 Binary files /dev/null and b/input-images/leaf.jpg differ diff --git a/input-images/new-york.jpg b/input-images/new-york.jpg new file mode 100755 index 0000000..a7899e4 Binary files /dev/null and b/input-images/new-york.jpg differ diff --git a/main.py b/main.py index a6e6d09..f5e9e6a 100644 --- a/main.py +++ b/main.py @@ -3,43 +3,44 @@ from tkinter import filedialog from tkinter.ttk import Notebook from PIL import Image, ImageTk -import subprocess, os, time +import os -from Renderer import Renderer -from Svg2GcodeConverter import Svg2GcodeConverter +from GCodeRenderer import Renderer +from Svg2GcodeConverter import Svg2GcodeConverter, triangulate_lengths, untriangulate_lengths +from ImageConverter import ImageConverter +from Simulator import Simulator class Settings: def __init__(self): - # Height at which the pen touches and draws on the surface - self.touch_height = 12 - # How far to raise the pen tip to raise it off the page - self.raise_height = 2 - # The inherent offset from true 0 we have from the pen bracket - self.head_x_offset = 50 - # XY movement speed - self.speed = 1000 - # Whether we render lift markers - self.lift_markers = False + # ============ HARDCODED VALUES =========== - # X and Y offsets to place the image on A11 paper - self.offset_x = 70 + self.head_x_offset - self.offset_y = 20 + # Canvas size + self.canvas_x = 200 + self.canvas_y = 200 - # Bed dimensions to fit A11 paper - self.bed_max_x = 300 - 70 + self.head_x_offset + 20 # 20 is to adjust for the misalignment of print bed - self.bed_min_x = self.offset_x - self.bed_max_y = 280 - self.bed_min_y = 20 + # The position of the pulley centers in relation to the top left and right of the canvas + self.left_pulley_x_offset = -40 + self.right_pulley_x_offset = 40 + self.pulley_y_droop = 60 - self.bed_actual_x = 300 - self.bed_actual_y = 300 + # Diameter of the inner portion of the pulley in millimeters + self.pulley_diameter = 45 + # Feed rates + self.speed = 1000 + + # Whether we render lift markers + self.lift_markers = False self.lift_counter = 0 + # ============ CALCULATED VALUES =========== + + self.distance_between_centers = abs(self.left_pulley_x_offset) + self.canvas_x + self.right_pulley_x_offset +# Main GUI class and program entry point class Tracer(Tk): def update_highpass_value(self, value): @@ -48,6 +49,9 @@ class Tracer(Tk): def update_blur_value(self, value): self.blur = value + def update_turd_value(self, value): + self.turd = value + def __init__(self): super().__init__() @@ -58,15 +62,21 @@ class Tracer(Tk): if not os.path.exists("tmp"): os.makedirs("tmp") + # Settings for the printer are loaded, TODO: Customize for our dual motor printer self.settings = Settings() + # Image filename which we are converting self.filename = None + # GCODE -> SVG,PNG renderer self.cairo_renderer = Renderer(self.settings) + + # SVG -> GCODE converter self.gcode_converter = Svg2GcodeConverter(self.settings) - self.highpass_filter = 0 - self.blur = 0 + # FILE -> SVG converter + self.image_converter = ImageConverter() + self.image_converter_settings = ImageConverter.ConverterSettings() self.label = None self.pix = None @@ -74,38 +84,55 @@ class Tracer(Tk): self.image_ref = None # Initialize TK - self.geometry("{}x{}".format(500, 500)) + self.geometry("{}x{}".format(800, 800)) - self.n = Notebook(self, width= 400, height =400) - self.n.pack(fill=BOTH, expand=1) + self.tab_bar = Notebook(self, width= 400, height =400) + self.tab_bar.pack(fill=BOTH, expand=1) - self.f1 = Frame(self.n) - self.f2 = Frame(self.n) + self.converted_image_tab = Frame(self.tab_bar) + self.original_image_tab = Frame(self.tab_bar) self.rightframe = Frame(self) self.rightframe.pack(side=RIGHT) - self.button = Button(self.rightframe, text="Select Image", command=self.file_select_callback) - self.button.pack() + self.centerframe = Frame(self) + self.centerframe.pack(side=BOTTOM) + + self.image_select_button = Button(self.rightframe, text="Select Image", command=self.file_select_callback) + self.image_select_button.pack() - self.button = Button(self.rightframe, text="Re-Render", command=self.render) - self.button.pack() + self.rerender_button = Button(self.rightframe, text="Re-Render", command=self.render) + self.rerender_button.pack() + + self.render_simulation_button = Button(self.rightframe, text="Render Simulation", command=self.render_simulation) + self.render_simulation_button.pack() self.lift_markers_checkbox = Checkbutton(self.rightframe, text="Lift Markers", command=self.cairo_renderer.toggle_flip_markers) self.lift_markers_checkbox.pack() - self.highpass_slider = Scale(self.rightframe, command=self.update_highpass_value, resolution=0.1, to=15) - self.highpass_slider.set(self.highpass_filter) + self.highpass_label = Label(self.centerframe, text="Highpass filter", fg="black") + self.highpass_label.pack() + self.highpass_slider = Scale(self.centerframe, command=self.update_highpass_value, resolution=0.0, to=15, orient=HORIZONTAL) + self.highpass_slider.set(self.image_converter_settings.highpass_filter) self.highpass_slider.pack() - self.blur_slider = Scale(self.rightframe, command=self.update_blur_value, resolution=0.1, to=5) - self.blur_slider.set(self.blur) + self.blur_label = Label(self.centerframe, text="Blur", fg="black") + self.blur_label.pack() + self.blur_slider = Scale(self.centerframe, command=self.update_blur_value, resolution=0.0, to=5, orient=HORIZONTAL) + self.blur_slider.set(self.image_converter_settings.blur) self.blur_slider.pack() + self.turd_label = Label(self.centerframe, text="Turds", fg="black") + self.turd_label.pack() + self.turd_slider = Scale(self.centerframe, command=self.update_turd_value, resolution=0.0, to=5, orient=HORIZONTAL) + self.turd_slider.set(self.image_converter_settings.turd) + self.turd_slider.pack() + # Start TK self.mainloop() def file_select_callback(self): + filepath = filedialog.askopenfilename(initialdir=".", title="Select file", filetypes=(("jpeg files", "*.jpg"), ("all files", "*.*"))) @@ -120,14 +147,14 @@ class Tracer(Tk): self.render() def render(self): - self.convert_image(self.filename) + self.image_converter.convert_image(self.filename, self.image_converter_settings) self.gcode_converter.convert_gcode() self.cairo_renderer.clear_screen() self.cairo_renderer.render_gcode() - self.f1.pack_forget() - self.f2.pack_forget() + self.converted_image_tab.pack_forget() + self.original_image_tab.pack_forget() if self.label is not None: self.label.pack_forget() @@ -139,61 +166,26 @@ class Tracer(Tk): # scale = self.winfo_width() / pil_image.width # pil_image = pil_image.resize((int(scale * pil_image.width), int(scale * pil_image.height))) self.image_ref = ImageTk.PhotoImage(pil_image) - self.label = Label(self.f1, image=self.image_ref) - self.n.add(self.f1, text="Converted") + self.label = Label(self.converted_image_tab, image=self.image_ref) + self.tab_bar.add(self.converted_image_tab, text="Converted") self.label.pack(expand=True, fill="both") self.pic = ImageTk.PhotoImage(file="input-images/{}".format(self.filename)) - self.label1 = Label(self.f2, image=self.pic) - self.n.add(self.f2, text="Original") + self.label1 = Label(self.original_image_tab, image=self.pic) + self.tab_bar.add(self.original_image_tab, text="Original") self.label1.pack(expand=True, fill="both") + def render_simulation(self): - # This function takes a file and runs it through mogrify, mkbitmap, and finally potrace. - # The flow of the intermediate files is - # input_file.extension : The input file - # input_file.bmp : The input file converted to bmp - # input_file-n.bmp : The bmp file after running through some filters - # input_file.svg : The output svg render - def convert_image(self, file_name): - - base_name = file_name.split(".")[0] - - print("Converting input file [{}]".format(file_name)) - - print("Running mogrify...") - start = time.time() - subprocess.call(["mogrify", "-format", "bmp", "input-images/{}".format(file_name)]) - print("Run took [{:.2f}] seconds".format(time.time() - start)) - - print("Running mkbitmap...") - start = time.time() - mkbitmap_args = ["mkbitmap", "input-images/{}.bmp".format(base_name), - "-o", "input-images/{}-n.pbm".format(base_name)] - if self.highpass_filter > 0: - mkbitmap_args.append(["-f", self.highpass_filter]) - - if self.blur > 0: - mkbitmap_args.append(["-b", self.blur]) - - - subprocess.call(mkbitmap_args) - print("Run took [{:.2f}] seconds".format(time.time() - start)) + simulator = Simulator() + simulator.render() - print("Running potrace...") - start = time.time() - subprocess.call(["potrace", - #"-t", "0.1", - "-z", "white", - "-b", "svg", - "input-images/{}-n.pbm".format(base_name), - "--rotate", "0", - "-o", "tmp/conversion-output.svg", - ]) - print("Run took [{:.2f}] seconds\n".format(time.time() - start)) +settings = Settings() +print(triangulate_lengths(settings, (150, 0))) +# print(triangulate_lengths(settings, (300, 300))) if __name__ == "__main__": - Tracer() + Tracer() diff --git a/requirements.txt b/requirements.txt index a0e735d..27b2832 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,6 @@ idna==2.8 matplotlib==2.1.1 numpy==1.15.4 Pillow==5.1.0 -pkg-resources==0.0.0 pycairo==1.16.2 pycparser==2.19 pycrypto==2.6.1