# -*- coding: utf-8 -*-
# MIT License
#
# Copyright (c) 2016, Dr. Sven Kochmann
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
#
# Description:
# 1.1 Camera settings (GUI program)
#
# This program helps the user to set up the camera for the measurement. Settings are saved
# to an ini file, which is used by the recording script later.
#

# Import modules
import wx               # wxPython (wxWidgets)
import cv2              # OpenCV
import numpy as np      # Numpy - You always need this.
import ConfigParser     # Reading/Writing config files
import time             # Time functions

# Main dialog
class MyDialog(wx.Dialog):
    # Init function (onInitDialog)
    def __init__(self, parent):
        # This layout code was generated by wxFormBuilder
        # -----------------------------------------------
        wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title=u"Camera settings", pos=wx.DefaultPosition,
                           size=wx.Size(978, 742), style=wx.DEFAULT_DIALOG_STYLE)

        self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)

        bSizer1 = wx.BoxSizer(wx.HORIZONTAL)

        self.campanel = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(640, 480), wx.TAB_TRAVERSAL)
        bSizer1.Add(self.campanel, 1, wx.ALL, 5)

        gSizer1 = wx.GridSizer(0, 2, 0, 0)

        self.text_brightness = wx.StaticText(self, wx.ID_ANY, u"Brightness", wx.DefaultPosition, wx.DefaultSize, 0)
        self.text_brightness.Wrap(-1)
        gSizer1.Add(self.text_brightness, 0, wx.ALL, 5)

        self.spin_brightness = wx.SpinCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize,
                                           wx.SP_ARROW_KEYS | wx.TE_PROCESS_ENTER, -255, 255, 0)
        gSizer1.Add(self.spin_brightness, 0, wx.ALL, 5)

        self.text_contrast = wx.StaticText(self, wx.ID_ANY, u"Contrast", wx.DefaultPosition, wx.DefaultSize, 0)
        self.text_contrast.Wrap(-1)
        gSizer1.Add(self.text_contrast, 0, wx.ALL, 5)

        self.spin_contrast = wx.SpinCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize,
                                         wx.SP_ARROW_KEYS | wx.TE_PROCESS_ENTER, -255, 255, 0)
        gSizer1.Add(self.spin_contrast, 0, wx.ALL, 5)

        self.text_saturation = wx.StaticText(self, wx.ID_ANY, u"Saturation", wx.DefaultPosition, wx.DefaultSize, 0)
        self.text_saturation.Wrap(-1)
        gSizer1.Add(self.text_saturation, 0, wx.ALL, 5)

        self.spin_saturation = wx.SpinCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize,
                                           wx.SP_ARROW_KEYS | wx.TE_PROCESS_ENTER, -255, 255, 0)
        gSizer1.Add(self.spin_saturation, 0, wx.ALL, 5)

        self.text_sharpness = wx.StaticText(self, wx.ID_ANY, u"Sharpness", wx.DefaultPosition, wx.DefaultSize, 0)
        self.text_sharpness.Wrap(-1)
        gSizer1.Add(self.text_sharpness, 0, wx.ALL, 5)

        self.spin_sharpness = wx.SpinCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize,
                                          wx.SP_ARROW_KEYS | wx.TE_PROCESS_ENTER, -255, 255, 0)
        gSizer1.Add(self.spin_sharpness, 0, wx.ALL, 5)

        self.text_gain = wx.StaticText(self, wx.ID_ANY, u"Gain", wx.DefaultPosition, wx.DefaultSize, 0)
        self.text_gain.Wrap(-1)
        gSizer1.Add(self.text_gain, 0, wx.ALL, 5)

        self.spin_gain = wx.SpinCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize,
                                     wx.SP_ARROW_KEYS | wx.TE_PROCESS_ENTER, -255, 255, 0)
        gSizer1.Add(self.spin_gain, 0, wx.ALL, 5)

        self.text_hue = wx.StaticText(self, wx.ID_ANY, u"Hue", wx.DefaultPosition, wx.DefaultSize, 0)
        self.text_hue.Wrap(-1)
        gSizer1.Add(self.text_hue, 0, wx.ALL, 5)

        self.spin_hue = wx.SpinCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize,
                                    wx.SP_ARROW_KEYS | wx.TE_PROCESS_ENTER, -255, 255, 0)
        gSizer1.Add(self.spin_hue, 0, wx.ALL, 5)

        self.check_backlight = wx.CheckBox(self, wx.ID_ANY, u"Backlight", wx.DefaultPosition, wx.DefaultSize, 0)
        gSizer1.Add(self.check_backlight, 0, wx.ALL, 5)

        gSizer1.AddSpacer((0, 0), 1, wx.EXPAND, 5)

        self.text_exposure = wx.StaticText(self, wx.ID_ANY, u"Exposure", wx.DefaultPosition, wx.DefaultSize, 0)
        self.text_exposure.Wrap(-1)
        gSizer1.Add(self.text_exposure, 0, wx.ALL, 5)

        self.edit_exposure = wx.TextCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize,
                                         wx.TE_PROCESS_ENTER)
        gSizer1.Add(self.edit_exposure, 0, wx.ALL, 5)

        self.button_autoexposure = wx.Button(self, wx.ID_ANY, u"Auto exposure", wx.DefaultPosition, wx.DefaultSize, 0)
        gSizer1.Add(self.button_autoexposure, 0, wx.ALL, 5)

        self.button_setexposure = wx.Button(self, wx.ID_ANY, u"Set exposure", wx.DefaultPosition, wx.DefaultSize, 0)
        gSizer1.Add(self.button_setexposure, 0, wx.ALL, 5)

        self.m_staticline11 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(100, -1), wx.LI_HORIZONTAL)
        self.m_staticline11.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))

        gSizer1.Add(self.m_staticline11, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)

        gSizer1.AddSpacer((0, 0), 1, wx.EXPAND, 5)

        self.static_width = wx.StaticText(self, wx.ID_ANY, u"Frame width", wx.DefaultPosition, wx.DefaultSize, 0)
        self.static_width.Wrap(-1)
        gSizer1.Add(self.static_width, 0, wx.ALL, 5)

        self.spin_width = wx.SpinCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize,
                                      wx.SP_ARROW_KEYS | wx.TE_PROCESS_ENTER, 0, 2048, 0)
        gSizer1.Add(self.spin_width, 0, wx.ALL, 5)

        self.static_height = wx.StaticText(self, wx.ID_ANY, u"Frame height", wx.DefaultPosition, wx.DefaultSize, 0)
        self.static_height.Wrap(-1)
        gSizer1.Add(self.static_height, 0, wx.ALL, 5)

        self.spin_height = wx.SpinCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize,
                                       wx.SP_ARROW_KEYS | wx.TE_PROCESS_ENTER, 0, 2048, 0)
        gSizer1.Add(self.spin_height, 0, wx.ALL, 5)

        gSizer1.AddSpacer((0, 0), 1, wx.EXPAND, 5)

        self.button_changeres = wx.Button(self, wx.ID_ANY, u"Change resolution", wx.DefaultPosition, wx.DefaultSize, 0)
        gSizer1.Add(self.button_changeres, 0, wx.ALL, 5)

        self.m_staticline1 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(100, -1), wx.LI_HORIZONTAL)
        self.m_staticline1.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))

        gSizer1.Add(self.m_staticline1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL | wx.FIXED_MINSIZE, 5)

        gSizer1.AddSpacer((0, 0), 1, wx.EXPAND, 5)

        self.toggle_recordmode = wx.ToggleButton(self, wx.ID_ANY, u"Record mode", wx.DefaultPosition, wx.DefaultSize, 0)
        gSizer1.Add(self.toggle_recordmode, 0, wx.ALL, 5)

        gSizer1.AddSpacer((0, 0), 1, wx.EXPAND, 5)

        self.text_flipping = wx.StaticText(self, wx.ID_ANY, u"Flip the image", wx.DefaultPosition, wx.DefaultSize, 0)
        self.text_flipping.Wrap(-1)
        gSizer1.Add(self.text_flipping, 0, wx.ALL, 5)

        choice_flippingChoices = [u"No flipping", u"Flip vertically", u"Flip horizontally", u"Flip both axes"]
        self.choice_flipping = wx.Choice(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, choice_flippingChoices, 0)
        self.choice_flipping.SetSelection(0)
        gSizer1.Add(self.choice_flipping, 0, wx.ALL, 5)

        self.text_channels = wx.StaticText(self, wx.ID_ANY, u"Channels", wx.DefaultPosition, wx.DefaultSize, 0)
        self.text_channels.Wrap(-1)
        gSizer1.Add(self.text_channels, 0, wx.ALL, 5)

        self.check_red = wx.CheckBox(self, wx.ID_ANY, u"Red", wx.DefaultPosition, wx.DefaultSize, 0)
        self.check_red.SetValue(True)
        gSizer1.Add(self.check_red, 0, wx.ALL, 5)

        gSizer1.AddSpacer((0, 0), 1, wx.EXPAND, 5)

        self.check_green = wx.CheckBox(self, wx.ID_ANY, u"Green", wx.DefaultPosition, wx.DefaultSize, 0)
        self.check_green.SetValue(True)
        gSizer1.Add(self.check_green, 0, wx.ALL, 5)

        gSizer1.AddSpacer((0, 0), 1, wx.EXPAND, 5)

        self.check_blue = wx.CheckBox(self, wx.ID_ANY, u"Blue", wx.DefaultPosition, wx.DefaultSize, 0)
        self.check_blue.SetValue(True)
        gSizer1.Add(self.check_blue, 0, wx.ALL, 5)

        self.text_integratetime = wx.StaticText(self, wx.ID_ANY, u"Integration time [s]", wx.DefaultPosition,
                                                wx.DefaultSize, 0)
        self.text_integratetime.Wrap(-1)
        gSizer1.Add(self.text_integratetime, 0, wx.ALL, 5)

        self.spin_integratetime = wx.SpinCtrl(self, wx.ID_ANY, u"5", wx.DefaultPosition, wx.DefaultSize,
                                              wx.SP_ARROW_KEYS, 0, 100, 0)
        gSizer1.Add(self.spin_integratetime, 0, wx.ALL, 5)

        self.m_staticline2 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(100, -1), wx.LI_HORIZONTAL)
        self.m_staticline2.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))

        gSizer1.Add(self.m_staticline2, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL | wx.FIXED_MINSIZE, 5)

        gSizer1.AddSpacer((0, 0), 1, wx.EXPAND, 5)

        self.button_camsettings = wx.Button(self, wx.ID_ANY, u"Camera settings", wx.DefaultPosition, wx.DefaultSize, 0)
        gSizer1.Add(self.button_camsettings, 0, wx.ALL, 5)

        gSizer1.AddSpacer((0, 0), 1, wx.EXPAND, 5)

        self.button_reload = wx.Button(self, wx.ID_ANY, u"Reload settings", wx.DefaultPosition, wx.DefaultSize, 0)
        gSizer1.Add(self.button_reload, 0, wx.ALL, 5)

        self.button_save = wx.Button(self, wx.ID_ANY, u"Save settings", wx.DefaultPosition, wx.DefaultSize, 0)
        gSizer1.Add(self.button_save, 0, wx.ALL, 5)

        bSizer1.Add(gSizer1, 1, wx.ALL | wx.SHAPED, 5)

        self.SetSizer(bSizer1)
        self.Layout()

        self.Centre(wx.BOTH)

        # Connect Events
        self.Bind(wx.EVT_CLOSE, self.onClose)
        self.campanel.Bind(wx.EVT_ERASE_BACKGROUND, self.onEraseBackground)
        self.campanel.Bind(wx.EVT_PAINT, self.onPaint)
        self.spin_brightness.Bind(wx.EVT_TEXT_ENTER, self.changeSettings)
        self.spin_contrast.Bind(wx.EVT_TEXT_ENTER, self.changeSettings)
        self.spin_saturation.Bind(wx.EVT_TEXT_ENTER, self.changeSettings)
        self.spin_sharpness.Bind(wx.EVT_TEXT_ENTER, self.changeSettings)
        self.spin_gain.Bind(wx.EVT_TEXT_ENTER, self.changeSettings)
        self.spin_hue.Bind(wx.EVT_TEXT_ENTER, self.changeSettings)
        self.check_backlight.Bind(wx.EVT_CHECKBOX, self.changeSettings)
        self.button_autoexposure.Bind(wx.EVT_BUTTON, self.autoExposure)
        self.button_setexposure.Bind(wx.EVT_BUTTON, self.setExposure)
        self.button_changeres.Bind(wx.EVT_BUTTON, self.changeResolution)
        self.choice_flipping.Bind(wx.EVT_CHOICE, self.changeSettings)
        self.check_red.Bind(wx.EVT_CHECKBOX, self.changeSettings)
        self.check_green.Bind(wx.EVT_CHECKBOX, self.changeSettings)
        self.check_blue.Bind(wx.EVT_CHECKBOX, self.changeSettings)
        self.spin_integratetime.Bind(wx.EVT_TEXT_ENTER, self.changeSettings)
        self.button_camsettings.Bind(wx.EVT_BUTTON, self.cameraSettings)
        self.button_reload.Bind(wx.EVT_BUTTON, self.reloadSettings)
        self.button_save.Bind(wx.EVT_BUTTON, self.saveSettings)
        # -----------------------------------------------

        # Initialize camera
        self.cam = cv2.VideoCapture(0)

        # Get initial width and height
        self.framewidth = self.cam.get(cv2.CAP_PROP_FRAME_WIDTH)
        self.frameheight = self.cam.get(cv2.CAP_PROP_FRAME_HEIGHT)

        # Try to get very first frame from camera
        ret, img = self.cam.read()

        # Successful? (i.e. is there a camera?)
        if ret == True:
            # Cameras like Blue-green-red, but panels like Red-green-blue, so we have to convert
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            # Get dimensions of Image
            row, col, c = img.shape
            # Convert to a bitmap
            self.bmp = wx.BitmapFromBuffer(col, row, img)

            # Create timer for frame grabbing
            self.playTimer = wx.Timer(self)
            self.Bind(wx.EVT_TIMER, self.onTimer)
            self.playTimer.Start(50)  # 50ms

            # Getting initial values from camera
            self.updateLabels()

            # Create empty array for integrated frames
            self.lastframe = np.zeros((self.frameheight, self.framewidth), np.uint32)  # 32-bit integer for integrating
            self.showframe = np.zeros((self.frameheight, self.framewidth), np.uint8)   # 8-bit integer for actual frame
            self.latesttime = time.clock()

        # No camera? Get out of here
        else:
            # Show message to user
            wx.MessageBox("Error reading frames from camera. Is the camera connected?", "Camera settings", wx.ICON_STOP)
            # Destroy dialog
            self.EndModal()

    # onClose: Release camera, kill timer, destroy window
    def onClose(self, evt):
        # Stop timer
        self.playTimer.Stop()
        # Release camera
        self.cam.release()
        # Destroy window
        self.Destroy()

    # onEraseBackground: Do nothing. Absolutely nothing.
    def onEraseBackground(self, evt):
        pass

    # onPaint
    def onPaint(self, evt):
        # If there is a bitmap to draw
        if self.bmp:
            # Paint it on myself (i.e. the panel)
            dc = wx.BufferedPaintDC(self.campanel)
            dc.DrawBitmap(self.bmp, 0, 0, True)
        # Skip
        evt.Skip()

    # onTimer
    def onTimer(self, evt):
        # Read a frame
        ret, img = self.cam.read()
        # Successful?
        if ret == True:
            # Record mode?
            if self.toggle_recordmode.GetValue() == 1:
                # Flipping?
                if self.choice_flipping.GetSelection() > 0:
                    # Choice: No flipping (0), Flip vertically (1), flip horizontal (2), flip both (3)
                    flip = self.choice_flipping.GetSelection() - 1
                    # Flip both
                    if flip == 2:
                        flip = -1
                    img = cv2.flip(img,flip)

                # Splitting frame into channels
                blue, green, red = cv2.split(img)

                # Channels
                if self.check_blue.IsChecked():
                    self.lastframe = self.lastframe + np.array(blue, dtype=np.uint32)
                if self.check_green.IsChecked():
                    self.lastframe = self.lastframe + np.array(green, dtype=np.uint32)
                if self.check_red.IsChecked():
                    self.lastframe = self.lastframe + np.array(red, dtype=np.uint32)

                # Elapsed time
                elapsed = time.clock() - self.latesttime

                # Have reached the integrated frames?
                if elapsed > self.spin_integratetime.Value:
                    if self.lastframe.max() > 0:
                        self.lastframe = np.multiply(self.lastframe, 255) / (self.lastframe.max())
                    self.showframe = np.array(self.lastframe, dtype=np.uint8)
                    self.lastframe = np.zeros((self.frameheight, self.framewidth), np.uint32)
                    self.latesttime = time.clock()

                # Show last showframe
                colorframe = np.zeros((self.frameheight, self.framewidth, 3), dtype=np.uint8)
                colorframe[:, :, 1] = self.showframe
                img = cv2.cvtColor(colorframe, cv2.COLOR_BGR2RGB)
                self.bmp.CopyFromBuffer(img)
                self.campanel.Refresh()
            # No record mode
            else:
                # Reset record mode
                self.lastframe = np.zeros((self.frameheight, self.framewidth), np.uint32)  # 32-bit Integer!
                self.showframe = np.zeros((self.frameheight, self.framewidth), np.uint8)  # 32-bit Integer!
                self.latesttime = time.clock()

                # Show just the picture
                img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
                self.bmp.CopyFromBuffer(img)
                self.campanel.Refresh()
        evt.Skip()

    # Calls the auto exposure feature of the camera
    def autoExposure(self, evt):
        self.cam.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0)
        self.updateLabels()
        evt.Skip()

    # Sets the exposure of the camera. For some cameras this will trigger (internally) an auto-exposure function
    def setExposure(self, evt):
        self.cam.set(cv2.CAP_PROP_EXPOSURE, float(self.edit_exposure.Value))  # see list
        evt.Skip()

    # Open camera settings dialog (depends on OS and driver)
    def cameraSettings(self, evt):
        self.cam.set(cv2.CAP_PROP_SETTINGS, 0)
        self.updateLabels()
        evt.Skip()

    # Change Resolution
    def changeResolution(self, evt):
        # Positive values
        if (int(self.spin_width.Value) > 0) and (int(self.spin_height.Value) > 0):
            # Tell the camera the new resolution
            self.cam.set(cv2.CAP_PROP_FRAME_WIDTH, int(self.spin_width.Value))
            self.cam.set(cv2.CAP_PROP_FRAME_HEIGHT, int(self.spin_height.Value))
            # Grab an image from the camera
            ret, img = self.cam.read()

            # Successful?
            if ret == True:
                # Cameras like Blue-green-red, but panels like Red-green-blue, so we have to convert
                img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
                # Get dimensions of Image
                row, col, c = img.shape
                self.bmp = wx.BitmapFromBuffer(col, row, img)
            # Update labels
            self.updateLabels()
        evt.Skip()

    # Called when of these settings is changed; tell camera to change
    def changeSettings(self, evt):
        self.cam.set(cv2.CAP_PROP_BRIGHTNESS, self.spin_brightness.Value)  # 0-255
        self.cam.set(cv2.CAP_PROP_CONTRAST, self.spin_contrast.Value)  # 0-255
        self.cam.set(cv2.CAP_PROP_SATURATION, self.spin_saturation.Value)  # 0-255
        self.cam.set(cv2.CAP_PROP_SHARPNESS, self.spin_sharpness.Value)  # 0-255
        self.cam.set(cv2.CAP_PROP_GAIN, self.spin_gain.Value)  # 0-100
        self.cam.set(cv2.CAP_PROP_HUE, self.spin_hue.Value)  # fixed on 13?
        self.cam.set(cv2.CAP_PROP_BACKLIGHT, self.check_backlight .IsChecked())
        self.updateLabels()
        evt.Skip()

    # Get the actual values from the camera (the camera might not accept a setting)
    def updateLabels(self):
        # Ask the values from the camera!
        self.spin_brightness.Value = self.cam.get(cv2.CAP_PROP_BRIGHTNESS)
        self.spin_contrast.Value = self.cam.get(cv2.CAP_PROP_CONTRAST)
        self.spin_saturation.Value = self.cam.get(cv2.CAP_PROP_SATURATION)
        self.spin_sharpness.Value = self.cam.get(cv2.CAP_PROP_SHARPNESS)
        self.spin_gain.Value = self.cam.get(cv2.CAP_PROP_GAIN)
        self.spin_hue.Value = self.cam.get(cv2.CAP_PROP_HUE)
        self.check_backlight.SetValue(self.cam.get(cv2.CAP_PROP_BACKLIGHT))
        self.edit_exposure.Value = "%.1f" % (self.cam.get(cv2.CAP_PROP_EXPOSURE))
        self.spin_width.Value = self.cam.get(cv2.CAP_PROP_FRAME_WIDTH)
        self.spin_height.Value = self.cam.get(cv2.CAP_PROP_FRAME_HEIGHT)
        # Adjust size of campanel
        self.campanel.Size = (int(self.spin_width.Value),int(self.spin_height.Value))

    # Save the settings in a file
    def saveSettings(self, evt):
        self.updateLabels()
        Config = ConfigParser.ConfigParser()
        Config.add_section("Camera")
        Config.set("Camera", "Brightness", self.spin_brightness.Value)
        Config.set("Camera", "Contrast", self.spin_contrast.Value)
        Config.set("Camera", "Saturation", self.spin_saturation.Value)
        Config.set("Camera", "Sharpness", self.spin_sharpness.Value)
        Config.set("Camera", "Gain", self.spin_gain.Value)
        Config.set("Camera", "Hue", self.spin_hue.Value)
        Config.set("Camera", "Backlight", int(self.check_backlight.IsChecked()))
        Config.set("Camera", "Exposure", self.edit_exposure.Value)
        Config.set("Camera", "Framewidth", self.spin_width.Value)
        Config.set("Camera", "Frameheight", self.spin_height.Value)
        Config.add_section("Recording")
        Config.set("Recording", "Flipping", self.choice_flipping.GetSelection())
        Config.set("Recording", "Integratetime", self.spin_integratetime.Value)
        selectedchannels = []
        if self.check_blue.IsChecked():
            selectedchannels.append("blue")
        if self.check_green.IsChecked():
            selectedchannels.append("green")
        if self.check_red.IsChecked():
            selectedchannels.append("red")
        if len(selectedchannels) == 0:
            selectedchannels = "None"
        else:
            selectedchannels = ','.join(selectedchannels)
        Config.set("Recording", "Channels", selectedchannels)
        with open("camera.ini", "w") as fp:
            Config.write(fp)
        evt.Skip()

    # Load the settings from a file
    def reloadSettings(self, evt):
        self.updateLabels()
        Config = ConfigParser.ConfigParser()
        Config.read("camera.ini")
        self.spin_brightness.Value = int(Config.get("Camera", "Brightness"))
        self.spin_contrast.Value = int(Config.get("Camera", "Contrast"))
        self.spin_saturation.Value = int(Config.get("Camera", "Saturation"))
        self.spin_sharpness.Value = int(Config.get("Camera", "Sharpness"))
        self.spin_gain.Value = int(Config.get("Camera", "Gain"))
        self.spin_hue.Value = int(Config.get("Camera", "Hue"))
        if int(Config.get("Camera", "Backlight")) > 0:
            self.check_backlight.Value = 1

        self.spin_integratetime.Value = int(Config.get("Recording", "Integratetime"))
        self.choice_flipping.SetSelection(int(Config.get("Recording", "Flipping")))

        selectedchannels = Config.get("Recording", "Channels").split(",")
        self.check_blue.Value = 0
        self.check_green.Value = 0
        self.check_red.Value = 0
        if "blue" in selectedchannels:
            self.check_blue.Value = 1
        if "green" in selectedchannels:
            self.check_green.Value = 1
        if "red" in selectedchannels:
            self.check_red.Value = 1

        # Frame dimensions
        self.spin_width.Value = int(Config.get("Camera", "Framewidth"))
        self.spin_height.Value = int(Config.get("Camera", "Frameheight"))
        self.changeResolution(evt)

        # Exposure
        self.edit_exposure.Value = Config.get("Camera", "Exposure")
        self.setExposure(evt)

        # Update Settings
        self.changeSettings(evt)

        evt.Skip()

# Actual main program: Show the above dialog
if __name__=="__main__":
    app = wx.App()
    dlg = MyDialog(None)
    dlg.ShowModal()
    app.ExitMainLoop()

