'''
A module "picamera"-based script for the Raspberry Pi HQ camera microscope,
controlled by a Pimoroni Touchphat

Install required libraries before use
'''

from time import sleep
import picamera
import datetime as dt
import touchphat
import os
#from guizero import App, Text, TextBox, Picture, Slider, PushButton
#import gpiozero # for a physical button control version
#import signal
#import subprocess
#import sys


w_dir = os.getcwd()
print ('working directory: ', w_dir)

camera = picamera.PiCamera() #turns camera on

#General camera settings: loads of parameters to play with
camera.rotation= 180 # 90,180,270
#camera.hflip = True # default: False
#camera.vflip = True # default: False

camera.meter_mode = 'spot' # optimize illumination,
# alternative options: 'average', 'backlit', 'matrix', 'spot'

camera. awb_mode = 'auto' # automatic whithe balance.. You may play with setting fitting best to your setting
# alternatives: off, auto, sunlight, cloudy, shade, tungsten, fluorescent, incandelescent, flash, horizon, greyworld

#camera.iso =100 # 200,400, 800
#camera.contrast = 0.5 #
camera.brightness = 50 # 0 ...100, default 50
camera.sharpness = 0 #-100 to 100, default 0

# set annotation format in images
camera.annotate_background = picamera.Color ('blue') # sets background color for text
#camera.annotate_foreground = picamera.Color (Y=1, U=0, V=0) # sets brightness for text Y=0..1

#select effects to apply while capturing image
effect1 = 'negative'     #Touchpad "C"
effect2 = 'colorbalance'   #Touchpad "D"
'''
#further options: negative, solarize, sketch, denoise, emboss, oilpaint, hatch, pastel, watercolor, film, blur, saturation, colorswap, washedout, posterize, colorpoint, colorbalance, cartoon, deinterlace1, deinterlace2 
'''
#preview settings
preview_time_1 = 8 # duration for displaying preview in sec:
#for total view: optimize object placing & focus
preview_time_2 = 8 # 
#for total view  emboss: fine tuning
preview_time_3 = 8
#for ROI-view: fine tuning

#image capture settings
delay_time = 2 # delay between images taken, in sec

#video length settings

vga_time = 30 # for 640x480 video
hires_time = 20 # for 1080p video

# define position and size of preview window
preview_xy = (800,300) #position of upper left corner of preview window on screen
preview_size = (1014, 760) # size of preview window, here: 1/4 of max resolution HQ camera

#Zeitpunkt = "" # set as general variable for timestamp text

#check for type of camera installed
camera_version = camera.revision
print ('camera type: ', camera_version)
if (camera_version == 'imx477'):
    print ('HQ camera detected')
    print ('Modus 1: 2028 x 1080, Modus 2: 2028x1520, Modus 3: 4056x3040, Modus 4: 1012x760')
    modus = 3
    camera.sensor_mode = modus
    print ('Activated modus: ', modus)
    camera.resolution = (1014,760) # defines image size
    print ('Image size: ', camera.resolution)
    camera.framerate = 15 # 30
    print ('Framerate set to: ', camera.framerate, 'fps')
    
elif (camera.version == 'ov5647'):
    print ('version 1 camera detected')
    print ('modus 1: 1080p (30 fps), modi 2/3: 2592x1944, modus 4: 1296x972, modus 5: 1296x730, modi 6/7: VGA (60/90 fps)')
    print ('code may require some adaptation')
    camera.resolution = (1014,760) # defines image size
    print ('Image size: ', camera.resolution)
    camera.framerate = 30

elif (camera.version == 'imx219'):
    print ('version 2 camera detected')
    print ('Settings may require some adjustments')
    print ('modus 1: 1080p (30 fps), modi 2/3: 3280x2464 (15), modus 4: 1640x1232 (40), modus 5: 1640x922, modus 6: 720p (90), modus 7: VGA (90)')
    print ('code may require some adaptation')
    camera.resolution = (1014,760) # defines image size
    print ('Image size: ', camera.resolution)
    camera.framerate = 30

else:    
    print ('No HQ camera! Please modify settings manually') # code to be optimized for version 2 camera

# determine timestamp
def get_zeitpunkt():
    Time_info = dt.datetime.now().strftime('%Y-%m-%d %H:%M')
    print ('Timestamp: ', Time_info)
    return Time_info

#Routines for preview and taking images, evoked by touckphat

@touchphat.on_release('Enter') # button 'Enter' evokes Preview total for previewtime 1 seconds
def preview_ROI_none():
    touchphat.led_on(6)
    camera.zoom = (0.375, 0.375, 0.25, 0.25) #restrict to ROI: central 25 %, equals maximal resolution
    camera.annotate_text = 'Preview ROI'
    sleep (preview_time_3)
    camera.zoom = (0,0,0,0)
    camera.annotate_text ='Preview total'
    touchphat.led_off(6)
    
''' #not used here
def preview_Total_emboss():
    touchphat.led_on(1)
    camera.image_effect =('emboss') # 'none, 'cartoon', 'negative','sketch', 'emboss' ...
    camera.annotate_text = "Preview - emboss"
    sleep (preview_time_2)
    camera.image_effect =('none')# back to standard
    touchphat.led_off(1)
'''
@touchphat.on_release('A') # button 'A' evokes taing image of total area, no effects
def take_Total_none():  # take image of tolal view without applying any effect
    touchphat.led_on(2)    
    Zeitpunkt = get_zeitpunkt()
    Image_text = Zeitpunkt + ' - Total-none'
    camera.annotate_text = Image_text
    camera.capture (Image_text + '.jpg') # get total image, store as jpg
    print ('Image taken: ',Image_text)
    camera.annotate_text ='Preview total area'
    touchphat.led_off(2)
    
@touchphat.on_release('B') # button 'B' evokes taing image of ROI, no effects
def take_ROI_none():   #take image of ROI applying no effect
    # zoom to ROI
    camera.zoom = (0.375, 0.375, 0.25, 0.25) #restrict to ROI: central 25 %, equals maximal resolution
    sleep (2)
    Zeitpunkt = get_zeitpunkt()
    Image_text = Zeitpunkt + ' - ROI-none' # for unmodified image
    camera.annotate_text = Image_text
    camera.capture (Image_text +'.png') # store as png to reduce loss of information
    print ('Image taken: ',Image_text)
    camera.zoom = (0, 0, 0, 0)
    camera.annotate_text ='Preview total area'

@touchphat.on_release('C') # button 'C' evokes taking image of ROI, effect1 applied
def take_ROI_effect1():  #take image of ROI applying effect1
    camera.zoom = (0.375, 0.375, 0.25, 0.25) #restrict to ROI: central 25 %, equals maximal resolution       
    camera.image_effect = effect1
    sleep (1)
    Zeitpunkt = get_zeitpunkt()
    Image_text = Zeitpunkt + ' - ROI-' + effect1
    camera.annotate_text = Image_text
    camera.capture (Image_text +'.png') # store as png to reduce loss of information
    print ('Image taken: ',Image_text)
    camera.image_effect = 'none'
    camera.zoom = (0, 0, 0, 0)
    camera.annotate_text ='Preview total area'

@touchphat.on_release('D') # button 'D' evokes taking image of ROI, effect2: posterize applied
def take_ROI_effect2():  #take image of ROI applying effect = 'xxx'
    camera.zoom = (0.375, 0.375, 0.25, 0.25) #restrict to ROI: central 25 %, equals maximal resolution       
    camera.image_effect = effect2
    sleep (1)
    Zeitpunkt = get_zeitpunkt()
    Image_text = Zeitpunkt + ' - ROI-'+ effect2
    camera.annotate_text = Image_text
    camera.capture (Image_text +'.png') # store as png to reduce loss of information
    print ('Image taken: ',Image_text)
    camera.image_effect = 'none'
    camera.zoom = (0, 0, 0, 0)
    camera.annotate_text ='Preview total area'

@touchphat.on_release('Back') # button 'Back' evokes end of programm and cleaning of memory
def end_camera():   #end routine
    touchphat.led_on(1)
    camera.stop_preview()
    camera.close () # close camera, free storage
    print ("Camera closed")
    sleep (1)
    touchphat.led_off(1)
    print ('Stop script now manually!') # how to stop all processes from  tread?
    #sys.exit()
    #quit()
    #exit()

#instructions for use
print ()
print ('On Touch phat press: ')
print ('   "Enter" (right side) for a 10 sec preview of ROI (no effect applied)')
print ('   "A" to take an image of total area, no effect applied')
print ('   "B" to take an image of ROI, no effect applied')
print ('   "C" to take an image of ROI, effect1 "', effect1, '" applied')
print ('   "D" to take an image of ROI, effect2 "', effect2, '" applied')
print ('   "Back" (left side) to end program')
print ()

#start with total area preview w/o effects applied
#camera warm-up time 3 sec
touchphat.all_on() # turn all LEDs on
sleep (1)
touchphat.all_off() # turn them off

#start preview
camera.start_preview()
camera.preview.fullscreen = False # enables display of preview in defined window
camera.preview.window = (preview_xy[0], preview_xy[1], preview_size[0], preview_size[1]) # defines position of upper left corner and size of display window
camera.annotate_text = 'Preview total area'
#sleep (preview_time_1)

