import os import subprocess import shutil import signal import tempfile import time from PIL import Image try: from pyA20.gpio import gpio, port except ImportError: from unittest.mock import Mock gpio = Mock() class Tmpobj(): pass port = Tmpobj() port.PB3 = 42 port.PB4 = 42 port.PB5 = 42 port.PB6 = 42 port.PB7 = 42 from bureau import Bureau, add_api class Photography(Bureau): """ The Photography dept. provides document camera and other image capture services for other bureaus. """ name = "Photography Dept." prefix = "PX" version = 0 landscape_pin = port.PB3 a5_pin = port.PB5 a4_pin = port.PB4 a6_pin = port.PB6 doc_light_pin = port.PB7 def __init__(self): Bureau.__init__(self) # set up the gpios for lamp & knobs gpio.init() gpio.setcfg(self.doc_light_pin, gpio.OUTPUT) gpio.output(self.doc_light_pin, gpio.LOW) # set pins and pullups for switches gpio.setcfg(self.landscape_pin, gpio.INPUT) gpio.pullup(self.landscape_pin, gpio.PULLUP) gpio.setcfg(self.a4_pin, gpio.INPUT) gpio.pullup(self.a4_pin, gpio.PULLUP) gpio.setcfg(self.a5_pin, gpio.INPUT) gpio.pullup(self.a5_pin, gpio.PULLUP) gpio.setcfg(self.a6_pin, gpio.INPUT) gpio.pullup(self.a6_pin, gpio.PULLUP) # make sure tmp dir exists tmpdir = "/tmp/webcam" if not os.path.exists(tmpdir): os.mkdir(tmpdir) def _doc_light_on(self): gpio.output(self.doc_light_pin, gpio.HIGH) def _doc_light_off(self): gpio.output(self.doc_light_pin, gpio.LOW) @add_api("photo", "Get Document Photo") def photo(self): """ Takes a photograph using the document camera. Returns the file name. """ self._doc_light_on() tmpimg = tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) tmpimg.close() # TODO: make more reliable # TODO: make resolution config variable # this is a dirty hack to keep the webcam system calls from hanging #cmd1 = "fswebcam --jpeg 95 --no-banner --resolution 320x240 /dev/null" #cmd2 = "fswebcam --jpeg 95 --no-banner --resolution 1920x1080 " #cmd2 += "-F 2 -S 1" + tmpimg.name #cmd1 = "uvccapture -d/dev/video1 -x320 -y240 -o /dev/null" #cmd2 = "/usr/local/bin/uvccapture -m -x3264 -y2448 -o" + tmpimg.name #subprocess.check_output(cmd1.split()) modpath = os.path.dirname(__file__) mjpg = os.path.join(modpath, "..", "..", "lib", "mjpg-streamer", "mjpg-streamer-experimental", "run.sh") mjpg_dir = os.path.dirname(mjpg) cmd = mjpg.split() + ["-i", "input_uvc.so -r 1920x1080 -n", "-o", "output_file.so -f /tmp/webcam -d 500 -s 2"] print(cmd) #proc = subprocess.Popen(cmd, shell=True, env={"LD_LIBRARY_PATH": mjpg_dir}) proc = subprocess.Popen(cmd) time.sleep(2) killer_cmd = "killall -s SIGINT mjpg_streamer" subprocess.Popen(killer_cmd.split()) time.sleep(2) # copy last image to the tmpfile filelist = os.listdir("/tmp/webcam") for i, f in enumerate(filelist): filelist[i] = os.path.join("/tmp/webcam", f) newest = max(filelist, key=lambda x: os.stat(x).st_mtime) print("copying ", newest, "to", tmpimg.name) shutil.copyfile(newest, tmpimg.name) # crop img = Image.open(tmpimg.name) img = img.transpose(Image.ROTATE_180) xsize, ysize = img.size #crop here to trim calibrated extra pixels loffset = int(round(xsize * (float(23) / 257))) roffset = xsize - int(round(xsize * (float(8) / 257))) box = (loffset, 0, roffset, ysize) img = img.crop(box) xsize, ysize = img.size if gpio.input(self.a4_pin) == 0: print("scanning as A4") offset = (xsize - ysize) / 2 box = (offset, 0, (offset + ysize), xsize / 2) img = img.crop(box) elif gpio.input(self.a5_pin) == 0: print("scanning as A5") offset = xsize / 4 box = (offset, 0, (offset + (xsize / 2)), ysize / 2) img = img.crop(box) elif gpio.input(self.a6_pin) == 0: print("scanning as A6") offset = (xsize - (ysize / 2)) / 2 box = (offset, 0, (offset + (ysize / 2)), xsize / 4) img = img.crop(box) else: print("scanning as A3") # rotate if gpio.input(self.landscape_pin) == 0: img = img.transpose(Image.ROTATE_90) img.save(tmpimg.name) img.close() self._doc_light_off() return {"photo": tmpimg.name} def main(): px = Photography() px.run() if __name__ == "__main__": main()