#!/usr/bin/env python
# coding: utf-8

import os

os.environ["PYLON_CAMEMU"] = "3"


from pypylon import pylon
from pypylon import genicam
import cv2
import sys
import time




# converter class that is a drop-in replacement for the pylon converter used in many examples
class CV2_BGRConverter(object):
    # bayer conversion ( !! format definition is different in pylon and opencv !!)
    # https://docs.opencv.org/4.5.1/de/d25/imgproc_color_conversions.html
    conversion = {
        pylon.PixelType_BayerRG8:    lambda img: cv2.cvtColor(img, cv2.COLOR_BAYER_BG2BGR),
        pylon.PixelType_BayerRG12:   lambda img: cv2.cvtColor(img, cv2.COLOR_BAYER_BG2BGR),
        pylon.PixelType_BayerRG12p:  lambda img: cv2.cvtColor(img, cv2.COLOR_BAYER_BG2BGR),
        pylon.PixelType_BayerBG8:    lambda img: cv2.cvtColor(img, cv2.COLOR_BAYER_RG2BGR),
        pylon.PixelType_BayerBG12:   lambda img: cv2.cvtColor(img, cv2.COLOR_BAYER_RG2BGR),
        pylon.PixelType_BayerBG12p:  lambda img: cv2.cvtColor(img, cv2.COLOR_BAYER_RG2BGR),
        pylon.PixelType_BayerGR8:    lambda img: cv2.cvtColor(img, cv2.COLOR_BAYER_GB2BGR),
        pylon.PixelType_BayerGR12:   lambda img: cv2.cvtColor(img, cv2.COLOR_BAYER_GB2BGR),
        pylon.PixelType_BayerGR12p:  lambda img: cv2.cvtColor(img, cv2.COLOR_BAYER_GB2BGR),
        pylon.PixelType_BayerGB8:    lambda img: cv2.cvtColor(img, cv2.COLOR_BAYER_GR2BGR),
        pylon.PixelType_BayerGB12:   lambda img: cv2.cvtColor(img, cv2.COLOR_BAYER_GR2BGR),
        pylon.PixelType_BayerGB12p:  lambda img: cv2.cvtColor(img, cv2.COLOR_BAYER_GR2BGR),
        pylon.PixelType_RGB8packed:  lambda img: cv2.cvtColor(img, cv2.COLOR_RGB2BGR),
        pylon.PixelType_BGR8packed:  lambda img: np.copy(img),
        pylon.PixelType_YUV422packed: lambda img: cv2.cvtColor(img, cv2.COLOR_YUV2BGR_UYVY),
        pylon.PixelType_YUV422_YUYV_Packed: lambda img: cv2.cvtColor(img, cv2.COLOR_YUV2BGR_YUYV),
    }
 
    def __init__(self):
        pass
        
    def Convert(self, res : pylon.GrabResult):
        assert res.PixelType in self.conversion
        with res.GetArrayZeroCopy() as img:
            res_img = self.conversion[res.PixelType](img)
        return res_img




# Number of images to be grabbed.
countOfImagesToGrab = 5

cv_BGR = CV2_BGRConverter()

converter = pylon.ImageFormatConverter()

# converting to opencv bgr format
converter.OutputPixelFormat = pylon.PixelType_BGR8packed
converter.OutputBitAlignment = pylon.OutputBitAlignment_MsbAligned

# The exit code of the sample application.
exitCode = 0

try:
    dinfo = pylon.DeviceInfo()
    dinfo.SetSerialNumber("0815-0000")
    # Create an instant camera object with the camera device found first.
    camera = pylon.InstantCamera(pylon.TlFactory.GetInstance().CreateFirstDevice(dinfo))
    camera.Open()
    print(camera.PixelFormat.Symbolics)
    camera.PixelFormat = 'BayerGB8'

    # Print the model name of the camera.
    print("Using device ", camera.GetDeviceInfo().GetModelName())

    # demonstrate some feature access
    #new_width = camera.Width.GetValue() - camera.Width.GetInc()
    #if new_width >= camera.Width.GetMin():
        #camera.Width.SetValue(new_width)

    # The parameter MaxNumBuffer can be used to control the count of buffers
    # allocated for grabbing. The default value of this parameter is 10.
    camera.MaxNumBuffer = 5

    # Start the grabbing of c_countOfImagesToGrab images.
    # The camera device is parameterized with a default configuration which
    # sets up free-running continuous acquisition.
    camera.StartGrabbingMax(countOfImagesToGrab)

    # Camera.StopGrabbing() is called automatically by the RetrieveResult() method
    # when c_countOfImagesToGrab images have been retrieved.
    while camera.IsGrabbing():
        # Wait for an image and then retrieve it. A timeout of 5000 ms is used.
        grabResult = camera.RetrieveResult(5000, pylon.TimeoutHandling_ThrowException)

        # Image grabbed successfully?
        if grabResult.GrabSucceeded():
            get_ipython().run_line_magic('debug', '')
            # Access the image data.
            print("SizeX: ", grabResult.Width)
            print("SizeY: ", grabResult.Height)
            
            start = time.time()
            #image = converter.Convert(grabResult)
            image = cv_BGR.Convert(grabResult)
            #img = image.GetArray()
            end = time.time()
            print((end - start)*1000)
            cv2.namedWindow('title', cv2.WINDOW_NORMAL)
            cv2.imshow('title', image)
            k = cv2.waitKey(1)
            if k == 27:
                break
            

        else:
            print("Error: ", grabResult.ErrorCode, grabResult.ErrorDescription)
        grabResult.Release()
    camera.Close()

    cv2.destroyAllWindows()

except genicam.GenericException as e:
    # Error handling.
    print("An exception occurred.")
    print(e.GetDescription())
    exitCode = 1





