from pyaxidraw import axidraw import time import subprocess import io from PIL import Image import datetime import tqdm import colorsys # TODO: argparse: skip_draw, skip_scan, loop [n times] class Level(object): def __init__(self, minv, maxv, gamma): self.minv= minv/255.0 self.maxv= maxv/255.0 self._interval= self.maxv - self.minv self._invgamma= 1.0/gamma def new_level(self, value): if value <= self.minv: return 0.0 if value >= self.maxv: return 1.0 return ((value - self.minv)/self._interval)**self._invgamma def convert_and_level(self, band_values): h, s, v= colorsys.rgb_to_hsv(*(i/255.0 for i in band_values)) new_v= self.new_level(v) return tuple(int(255*i) for i in colorsys.hsv_to_rgb(h, s, new_v)) def level_image(image, minv=0, maxv=255, gamma=1.0): """Level the brightness of image (a PIL.Image instance) All values ≤ minv will become 0 All values ≥ maxv will become 255 gamma controls the curve for all values between minv and maxv""" if image.mode != "RGB": raise ValueError("this works with RGB images only") new_image= image.copy() leveller= Level(minv, maxv, gamma) levelled_data= [ leveller.convert_and_level(data) for data in image.getdata()] new_image.putdata(levelled_data) return new_image now = datetime.datetime.now().isoformat() print(f"test plotter/scanner/pen at {now}") absPlotWidth = 26.5/2.54 topLeft = absPlotWidth / (245/ 10 / 2.54) parkX = (1/2.54)/absPlotWidth + topLeft parkPos = [26.5/2.54,2,0] print(parkPos) ad = axidraw.AxiDraw() ad.interactive() ad.connect() ad.pen_raise() ad.disconnect() ad = axidraw.AxiDraw() ad.plot_setup('test_drawing.svg') # Load file & configure plot context # Plotting options can be set, here after plot_setup(). ad.plot_run() ad.disconnect() ad = axidraw.AxiDraw() # park ad.interactive() ad.connect() ad.pen_raise() ad.moveto(parkPos[0], parkPos[1]) try: sleeptime = 2 print(f"plotted, now wait for the ink to dry {sleeptime}s") for i in tqdm.tqdm(range(sleeptime)): time.sleep(1) cmd = [ 'sudo', 'scanimage', '-d', 'epkowa', '--format', 'tiff', '--resolution=100', # lower res, faster (more powerful) scan & wipe '-l','25' #y axis, margin from top of the scanner, hence increasing this, moves the scanned image upwards ,'-t','22', # x axis, margin from left side scanner (seen from the outside) '-x',str(181), '-y',str(245) ] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # opens connection to scanner, but only starts scanning when output becomes ready: o, e = proc.communicate(80) print('scanned') f = io.BytesIO(o) img = Image.open(f) img = img.transpose(Image.ROTATE_90).transpose(Image.FLIP_TOP_BOTTOM) img.save(f'test-{now}.png') print(f'\tsaved to test-{now}.png') print('effects:') leveldImg = level_image(img, 0, 125, 0.95) leveldImg.save(f'test-{now}-leveled.png') print(f'\tsaved to test-{now}-leveled.png') except Exception as e: print(e) finally: time.sleep(5) # scanner says its done before it slides back print('reset pen') ad.moveto(0,0) ad.disconnect() print('disable motors') # disable motors ad = axidraw.AxiDraw() ad.plot_setup() ad.options.mode = "manual" ad.options.manual_cmd = "disable_xy" ad.plot_run()