# -*- coding: utf-8 -*-
"""
in-situ TEM Toolbox - Input Output

Assembles of functions related to movie input output and format conversion.

Example:
    
    import insitu_IO as IO
    IO.f2tif(path,1)

Created on Tue Jun 11 10:25:25 2019
@author: Meng Li
Update 20200303:
        Add stroke to scalebar and text
"""


import cv2
import tifffile
import tqdm #not necessary just provides a progress bar and timer
import numpy as np
import moviepy.editor as mp

def tiff2mp4(path,fps):
    """
    function to convert any input file to H264 High quality mp4 using openCV
    Inputs: filepath
    Output: file in the same folder named '..._fps.mp4'
    """
    video = tifffile.imread(path)
    nFrames, h,w = video.shape[:3]
    # dur=1/fps    
    pathout =path[:-4]+'_'+str(fps)+'.mp4'    
    # pathout2 =path[:-4]+'_St.tif'
    codec  = cv2.VideoWriter_fourcc(*'H264')
    out = cv2.VideoWriter(pathout, codec , fps, (w,  h))
    print("---------------------------------------------")
    print('Converting Tiff stack to mp4')    
    for i in tqdm.tqdm(range(nFrames)):        
        img=video[i]  
        out.write(img)
    out.release()
    cv2.destroyAllWindows()
    print("==============================================")
    print("MP4 convertion Done!")

def tiff2avi(path,fps,is_color=False):
    #convert tiff stack to movie
    import tifffile
    import cv2
    
    # path = 
    stack = tifffile.imread(path)
    nFrames,h,w = stack.shape[:3]
    
    # # fps = int(input('Input desired output fps:'))
    # # dur=1/fps    
    # pathout =path[:-4]+'_'+str(fps)+'.avi'    
       
    
    # codec  = cv2.VideoWriter_fourcc(*'MJPG')
    
    # video_out = cv2.VideoWriter(pathout, codec , fps, (w,  h))
    # print("---------------------------------------------")
    # print('Converting Tiff stack to avi')    
    # for i in tqdm.tqdm(range(nFrames)):        
    #     img=stack[i] 
    #     video_out.write(img)
        
    # video_out.release()
    # cv2.destroyAllWindows()
    # print("==============================================")
    # print("AVI convertion Done!")
    size=(int(w),int(h))


    pathout =path[:-4]+'_'+str(fps)+'.avi'    

    # # Check if the image stack is grayscale or color
    is_color = len(stack.shape) == 4 and stack.shape[3] == 3

    codec  = cv2.VideoWriter_fourcc(*'MJPG')
    video_out = cv2.VideoWriter(pathout, codec , fps, size,isColor=is_color)
    print("---------------------------------------------")
    print('Converting Tiff stack to avi')    
    for i in tqdm.tqdm(range(nFrames)):        
        img=stack[i]

        # Ensure the image is in 8-bit format
        
        if img.dtype != np.uint8:
            img = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX)
            img = np.uint8(img)
        # Convert RGB to BGR if the image is in color
        if is_color ==True:
            img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
        # else:
        #     img = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX)
        #     img = np.uint8(img)
        # Convert RGB to BGR if the image is in color
        
            
        video_out.write(img)
        
    video_out.release()
    cv2.destroyAllWindows()
    print("==============================================")
    print("AVI convertion Done!")

def movie2tif(path,is_gray=1,exp_time=0.2):
    """
    function to convert any input movie file to tif stack
    Inputs: filepath of movie, is_gray: 1 for grayscale, 0 for rgb
            exp_time= exposure time of real movie, remove dup frame if fps > exp_time
    
    Output: file in the same folder named '..._cv.tif'
    """   
    import moviepy.editor as mp
    import tifffile
    import tqdm
    print("==============================================")
    print("Convert file to tif stack!")
    pathout = path[:-4]+'_'+str(is_gray)+'.tif'    
    video = mp.VideoFileClip(path)
    fps = int(video.fps)
    w = int(video.w)
    h = int(video.h)
    nFrames = int(fps*video.duration)
    dup= fps*exp_time
    nFramesOut=int(nFrames/dup)
    with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
        for j in tqdm.tqdm(range(nFramesOut)):
            i=int(j*dup)
            fr = video.get_frame(mp.cvsecs(i/fps))
            if is_gray==1:
                fr = cv2.cvtColor(fr, cv2.COLOR_BGR2GRAY)
            tif.write(fr, contiguous=True)


    video.reader.close()
        # for fr in tqdm.tqdm(video.iter_frames()):
        #     if is_gray==1:
        #         fr = cv2.cvtColor(fr, cv2.COLOR_BGR2GRAY) 
        #     tif.write(fr,continuous=True)

    print("==============================================")
    print("TIF convertion Done!")
    video.reader.close()# To fix handel error problem

def folder2tif(path,isGray=True):
    """
    Function to convert folder of single images into tif stack
    Input: path: folder path
    Output: tif stack with the same name as the folder in the parent folder.
    """
    import os
    import tifffile
    img_name=os.listdir(path) 
    nFrames= len(img_name)
    pathout=path+'.tif'


    with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
        for i in tqdm.tqdm(range(nFrames)):
            # img_name = f'{i:03d}.tif'
            compare_path=os.path.join(path,f'{i:03d}.tif')
            overlay =cv2.imread(compare_path)
            if isGray==True:
                overlay = cv2.cvtColor(overlay,cv2.COLOR_BGR2GRAY)
            else:
                overlay = cv2.cvtColor(overlay, cv2.COLOR_BGR2RGB) #tifffile usedRGB, cv2 used BGR
        
            tif.write(overlay, contiguous=True)

def f2gif(path,fps):
    """
    function to convert any input file to gif animation
    Inputs: filepath, output fps, is_gray: 1 for grayscale, 0 for rgb
    
    Output: file in the same folder named '..._cv.mp4'
    """
    
    print("==============================================")
    print("Convert file to GIF!")
    pathout = path[:-4]+'_'+str(fps)+'.gif'
    if path.endswith('.tif'):            
#        import tifffile
        im = tifffile.imread(path)
        nFrames, h,w = im.shape
        dur=1/fps
        clip = []
        for i in range(nFrames):
            fr = cv2.cvtColor(im[i],cv2.COLOR_GRAY2RGB)
            clip.append(mp.ImageClip(fr).set_duration(dur))
        video = mp.concatenate_videoclips(clip, method="compose",ismask=False)#ismask=True to make grayscale

    else:
        video = mp.VideoFileClip(path)
        fpsIn = int(video.fps)
        if fps != fpsIn:
            print("Conflict in fps! \n",              "[0] Use fps of input file;\n",              "[1] Use desired fps w/o speedup;\n",
              "[2] Use desired fps w/ speedup:")
            k = input('Input your selection: ')
            if k == 2:
                sf = fps/fpsIn
                video =video.fx(mp.vfx.speedx, sf)# Not working when sf<1
            elif k == 0:
                fps = fpsIn

        video.write_gif(pathout,fps=fps)
        video.reader.close()# To fix handel error problem
#    if path.endswith('.gif'):
#        clip.write_videofile(pathout,fps=fps,codec='libx264', bitrate='32 M',preset='ultrafast')
    print("==============================================")
    print("MP4 convertion Done!")

def gifmp4converter(path,fpsOut):
    """
    Function to convert between mp4 and gif files
    Inputs: file path; Output fps
    Output: mp4/gif file in the same folder named '..._cv.mp4/gif'
        
    Example: 
        gifmp4converter(path,25)
    """
#    import moviepy.editor as mp
    
    print("=========================================")
    print("GIF-MP4 Converter Started!")

    clip = mp.VideoFileClip(path)
    #Get output fps
    fpsIn = int(clip.fps)
    fps=fpsOut
    if fpsOut != fpsIn:
        print("Conflict in fps! \n",
              "[0] Use fps of input file;\n",
              "[1] Use desired fps w/o speedup;\n",
              "[2] Use desired fps w/ speedup:")
        k = input('Input your selection: ')
        if k == 2:
            sf = fpsOut/fpsIn
            fps = fpsOut                
            clip =clip.fx(mp.vfx.speedx, sf)
        elif k == 0:
            fps = fpsIn
         
# Converting formats
    if path.endswith('.gif'):
        pathout = path[:-4]+'_cv'+'.mp4'
        clip.write_videofile(pathout,fps=fps,codec='libx264', bitrate='32 M',preset='ultrafast')
    elif path.endswith('.mp4'):
        pathout = path[:-4]+'_cv'+'.gif'
        clip.write_gif(pathout,fps=fps)
    clip.reader.close()# To fix handel error problem
    print("=========================================")
    print("GIF-MP4 Converter Done!")
    
def GetInfo(path):
    """
    function to get movie info  from any file form: mp4 , tif, gif
    Inputs: filepath
    Output: nFrames, w, h, fps
    Example: w,h,nFrames,fps = GetInfo(path)

    """   
#    import tifffile
##    import tqdm
#    import moviepy.editor as mp
#    import cv2
    if path.endswith('.tif'):
        video = tifffile.imread(path) 
        nFrames, h,w = video.shape
        fps=int(input("Enter desired fps: "))
    else:
        video = mp.VideoFileClip(path)
        fps= int(video.fps)
        nFrames = int(fps*video.duration)
        w = int(video.w)
        h = int(video.h)
        video.reader.close()# To fix handel error problem
    return w,h,nFrames,fps

def RdFr(path,i,is_gray=1):
    """
    function to read frame from any file form: mp4 , tif, gif
    Inputs: filepath, is_gray: 1 for grayscale, 0 for rgb
    
    Output: frame image fr
    Example: 
IO.fr= RdFr(path,i)
cv2.imshow('Frame'+str(i),fr)
cv2.waitKey(0)
cv2.destroyAllWindows()
    """   
#    import tifffile
##    import tqdm
#    import moviepy.editor as mp
#    import cv2
    if path.endswith('.tif'):
        video = tifffile.imread(path)
        fr = video[i]                    
    else:
        video = mp.VideoFileClip(path)
        fps= int(video.fps)
        fr = video.get_frame(mp.cvsecs(i/fps))
        if is_gray == 1:
            fr= cv2.cvtColor(fr, cv2.COLOR_BGR2GRAY)
        video.reader.close()# To fix handel error problem
    return fr

def ExtractFrame(path,framelist,is_gray=1):
    """
    function to Extract frame from any file format: mp4 , tif, gif
    Inputs: filepath, list of frames to be extracted
    Output: frame images saved in original folder
    Example: 
        import insitu_IO as IO
        IO.ExtractFrame(path,[0,1,10,11],0)

    """ 
    if path.endswith('.tif'):
        video = tifffile.imread(path)
    else:
        video = mp.VideoFileClip(path)
        fps= int(video.fps)
    for i in tqdm.tqdm(framelist):
        if path.endswith('.tif'):
            fr = video[i]                  
        else:
            fr = video.get_frame(mp.cvsecs(i/fps))
            if is_gray == 1:            
                fr= cv2.cvtColor(fr, cv2.COLOR_BGR2GRAY)
#        fr=RdFr(path,int(i),is_gray)          
        pathout = path[:-4]+'_F'+str(i)+'.tif'
        tifffile.imwrite(pathout,fr, append=False)
    if path.endswith('.tif')==0:
        video.reader.close()
        
def writeCSV(pathout,data,fmt='%1.1d'):
#    import csv
    import numpy as np
#    (length,width)=np.shape(data)
    np.savetxt(pathout, data, fmt=fmt, delimiter=",")
     
def showFr(im):
    from PIL import Image
    img = Image. fromarray(im)
    img.show() 

#functions for scalebar
def readscale(path,dy=5):
    """
    Function to measure scale from movie first frame
    Input: path - movie path; dy: shift from the bottom in px
    scalebarcolr- 0 for black, 255 for white
    """
    import os
    os.environ["IMAGEIO_FFMPEG_EXE"] = "/opt/homebrew/bin/ffmpeg"
    import moviepy.editor as mp
    import cv2
    
    video = mp.VideoFileClip(path)
    fr = video.get_frame(mp.cvsecs(0))
    fr = cv2.cvtColor(fr, cv2.COLOR_BGR2GRAY)

    # Select ROI using cv2.selectROI()
    roi = cv2.selectROI('Select scalebar ROI, quit with SPACE', fr)
    cv2.waitKey(10)
    cv2.destroyWindow('Select scalebar ROI, quit with SPACE')

    # Crop the image based on the selected ROI
    cropped_image = fr[int(roi[1]):int(roi[1] + roi[3]), int(roi[0]):int(roi[0] + roi[2])]

    # # # Display the cropped image
    showFr(cropped_image)

    import numpy as np

    scalebar_color = int(input("Input the scalebar color,  0-black, 255-white: "))
    dy2=dy
    while dy2 != 0: 
        print(cropped_image[-dy,:])
        dy2=int(input("input 0 if the crop is correct, otherwise input the estimated distance from bottom to the scalebar: "))
        if dy2 !=0:
            dy=dy2
            
    scalebar_px =  np.count_nonzero(cropped_image[-dy,:]==scalebar_color)
    print("scalebar_px=", scalebar_px)
    scale_nm = int(input("Input the scalebar in nm: "))
    scale =scalebar_px/scale_nm
    print("==============")
    print("scale=",scale,"px/nm")
    return scale

def getScalePix(scale,barLenPix=250):
    """
    Function to convert truescale into str with correct format
    Input: 
        barLenPix : pixel length of the scalebar region
        scale: scale: px/nm
    Output: 
        text: string of the scalebar text, in the format such as 100, 200, 500 nm .
        scalepix: pixel distance of the realoutput scalebar
    """
    truescale= barLenPix/scale
    
    # Find the nearest power of 10 to the truescale
    nearest_power = 10 ** np.floor(np.log10(truescale))

    # Determine the most appropriate scale bar value
    if truescale >= 5 * nearest_power:
        scalebar = 5 * nearest_power
    elif truescale >= 2 * nearest_power:
        scalebar = 2 * nearest_power
    else:
        scalebar = nearest_power

    # Calculate the scale in pixels
    scalepix = int(scalebar * scale)

    # Determine the appropriate unit for the scale bar text
    if scalebar >= 1000:
        text = f"{int(scalebar/1000)} um"
    else:
        text = f"{int(scalebar)} nm"
    return scalepix, text

def AddScalePix(img,barLenPix =250, scale = 34.5, px=0.02,py=0.96, barthick=5,lw=1,stroke=True,tscale=1,textThick=4):
    """
    Function to add scale to image
    Input:
        img: greyscale image
        scaleLen: desired scale length
        scale: scale of the image: px/nm: 1000kX- 49.5; 700kX - 34.5
        (px,py): position of the scale bar: r(0-1)
        lw: boarder of the text
        stroke=1: add stroke; stroke=0 No stroke
 
    """
    import cv2
    h,w=img.shape

    scalepix, text = getScalePix(barLenPix, scale)

    # w_scale=int(scale*barLen)
    x1=int(w*px)
    y1=int(h*py)
    x2=x1+scalepix
    y2=y1+barthick


    #find bcakground color and make the reverse as scalebar color
    img_bg=img[y1:y2,x1:x2]
    mean_intensity=np.mean(img_bg)

    if mean_intensity<128:
        color = 255
    else:
        color = 0

    
    bcolor=255-color

    font = cv2.FONT_HERSHEY_SIMPLEX#CV_FONT_HERSHEY_SIMPLEX normal size sans-serif font
    if stroke == True:
        cv2.putText(img,text,(x1,y1-8), font, tscale, bcolor,int(textThick+lw), cv2.LINE_AA) #Stroke  
        cv2.rectangle(img,(x1,y1),(x2,y2),bcolor,2)#boarder color

        
    cv2.rectangle(img,(x1,y1),(x2,y2),color,-1)
    
    cv2.putText(img,text,(x1,y1-8), font,tscale, color, textThick, cv2.LINE_AA)

def AddScale(img,barLen =2, scale = 34.5, px=0.02,py=0.96, color = 255,fontScale=1.5, barthick=5,textthick=2,stroke=1):
    """
    Function to add scale to image
    Input:
        img: greyscale image
        barLen: desired scale length
        scale: scale of the image: px/nm: 1000kX- 49.5; 700kX - 34.5
        (px,py): position of the scale bar: r(0-1)
        color: color of the scalebar
        stroke=1: add stroke with thickness,  stroke=0 No stroke
  
        fontScale: scale of the text, default is 1.
        barthick: scalebar thickness
        textthick: thickness of the text without stroke
 
    """
    h,w=img.shape
    w_scale=int(scale*barLen)
    x1=int(w*px)
    y1=int(h*py)
    x2=x1+w_scale
    y2=y1+barthick

    bcolor=255-color
    
    text = str(barLen)+' nm'
    font = cv2.FONT_HERSHEY_SIMPLEX#CV_FONT_HERSHEY_SIMPLEX normal size sans-serif font
    shifty=int(8*fontScale)
    if stroke != 0:
        strokethick = int(stroke + textthick)
        rectangle_thickness = max(1, strokethick // 2)  # halve it for visual match
        cv2.putText(img, text, (x1, y1 - shifty), font, fontScale, bcolor, strokethick, lineType=cv2.LINE_AA)  # Stroke  
        cv2.rectangle(img, (x1, y1), (x2, y2), bcolor, rectangle_thickness)  # Border color

    cv2.rectangle(img, (x1, y1), (x2, y2), color, -1)
    cv2.putText(img, text, (x1, y1 - shifty), font, fontScale, color, textthick, cv2.LINE_AA)

def AddText(img,text, px=0.98,py=0.96, color = 255,fontScale=0.9,thickness=2,stroke=1):
    """
    Function to add text str to image
    Input:
        img: greyscale image
        text: textstr to display
        (px,py): position of the text: right,middle corner
        fontScale: scale of the text
        thickness: line thickness of the text
  
        stroke=1: add stroke width of 1; stroke=0 No stroke
 
    """
    h,w=img.shape
 
    font = cv2.FONT_HERSHEY_SIMPLEX#CV_FONT_HERSHEY_SIMPLEX normal size sans-serif font
    D,sd=cv2.getTextSize(text, font, fontScale,thickness)
    wt=int(D[0])
    bcolor=255-color #color of stroke
    # bw =lw+1 #stroke thickness
    strokethick=thickness+stroke
 
    x=int(w*px-wt)
    y=int(h*py)
    if stroke !=0:
        cv2.putText(img,text,(x,y), font, fontScale, bcolor, strokethick, cv2.LINE_AA) #Stroke      
    cv2.putText(img,text,(x,y), font, fontScale, color, thickness, cv2.LINE_AA)   

def AddScaleTime2Stack(path,bar,Scale,dt=0.2,fps=15,color=255, time_txt_scale=1.2,textthick=2,stroke=1):
    """
    Function to add scalebar and timestamp to stack
    Input:
        path: path to tiff stack
        bar: scale bar to show in nm
        Scale: scale for the image stack: px/nm
        dt: time interval of each frame
        others: parameters for adjusting scalebar text size
    Output:
        Tiff stack and avi movie of the added scale&time

    Example: 
    AddScaleTime2Stack(path,bar=20,Scale=22.2,dt=0.5,fps=15,color=255, time_txt_scale=1.2)

    """
    stack=tifffile.imread(path)
    nFrames, h,w = stack.shape
    
    pathout =path[:-4]+'_St.tif'    

    print("---------------------------------------------")
    print('Testing positions! ')
    fr=stack[0]
    px=0.96
    py=0.96

    text='0.0 s'
    AddScale(fr,barLen=bar,fontScale=time_txt_scale,scale=Scale,color=color,textthick=textthick,stroke=stroke)
    AddText(fr,text,px=px,py=py,fontScale=time_txt_scale,color=color,thickness=textthick,stroke=stroke)
    showFr(fr)

    prompt = input("Check the position, press 0 if you are satisfied, any other key to exit: ")
    print("---------------------------------------------")

    if prompt == "0":
        print("Adding scalebar and timestamp to full stack")
        with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
        
            for i in tqdm.tqdm(range(nFrames)):        
                img=stack[i]        
                time = i * dt    
                text=str('%02.1f' %time)+' s'  
                AddScale(img,barLen=bar,fontScale=time_txt_scale,scale=Scale,color=color,textthick=textthick,stroke=stroke)
                AddText(img,text,px=px,py=py,fontScale=time_txt_scale,color=color,thickness=textthick,stroke=stroke)        
                
                tif.write(img, contiguous=True)
        
        
        tiff2avi(pathout,fps=fps)
        print("Done adding scalebar and timestamp to tiff stack! ")
    else:
        print("Exit to change settings")

def apply_colormap(image,cmap='viridis'):
    """
    Function to apply false color to grayscale image
    input: 
    Image: grayscale image
    camp: colormap string. such as 'viridis'
    """
    import matplotlib.pyplot as plt
    colormap = plt.get_cmap(cmap)
    colored_image = colormap(image / 255.0)  # Normalize the image and apply colormap
    colored_image = (colored_image[:, :, :3] * 255).astype(np.uint8)  # Convert to 8-bit RGB
    return colored_image

def tiff2avi_falsecolor(path,cmap='viridis',fps=15):
    """
    Function to convert tiff to false color avi movie
    input: path : path of tiff stack
    cmap: colormap of the falsecolor
    """

    import tifffile
    import numpy as np
    import cv2
    import matplotlib.pyplot as plt
    import tqdm

    print("------------------------------------------")
    print("Convert stack to faulse color avi")
    stack = tifffile.imread(path)
    nFrames,h,w = stack.shape #make sure the order of h and w!
    
 
    pathout =path[:-4]+'_c_'+str(fps)+'.avi'    
    
    
    #Check the colormap effect
    fr = stack[0]
    fr_color=apply_colormap(fr,cmap)
    plt.imshow(fr_color)
    
    
    fourcc = cv2.VideoWriter_fourcc(*'MJPG')
    
    video_writer = cv2.VideoWriter(pathout, fourcc, fps, (w, h),isColor=True)
    
    # Process each frame and write to the video
    for i in tqdm.tqdm(range(nFrames)):
        grayscale_image = stack[i]
        colored_image = apply_colormap(grayscale_image,cmap)
        colored_image = cv2.cvtColor(colored_image, cv2.COLOR_RGB2BGR)  # Convert RGB to BGR
    
        video_writer.write(colored_image)
    
    # Release the video writer
    video_writer.release()

def AverageFrame(path,AveN):
    #Average frames by AveN to increase SNR
    import math
    im = tifffile.imread(path)
    nFrames, h,w = im.shape
    pathout = path[:-4]+'_'+str(AveN)+'ave.tif'
    nFramesOut=math.floor(nFrames/AveN)
    
    with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
        for i in tqdm.tqdm(range(nFramesOut)):
            AveFr= im[i*AveN]-im[i*AveN]
            for m in range(AveN):
                fr=im[i*AveN+m]
                AveFr=AveFr+fr/AveN
            img = AveFr.astype(np.uint8)
            tif.write(fr,continuous=True)

def apply_colormap(image,cmap='viridis'):
    """
    Function to apply false color to grayscale image
    input: 
    Image: grayscale image
    camp: colormap string. such as 'viridis'
    """
    import matplotlib.pyplot as plt
    colormap = plt.get_cmap(cmap)
    colored_image = colormap(image / 255.0)  # Normalize the image and apply colormap
    colored_image = (colored_image[:, :, :3] * 255).astype(np.uint8)  # Convert to 8-bit RGB
    return colored_image

def falsecolorstack(path,cmap='viridis',fps=15):
    import tifffile
    import numpy as np
    import cv2
    import tqdm
    print('Convert tiff stack to false color movie')
     

    stack = tifffile.imread(path)
    nFrames,h,w = stack.shape #make sure the order of h and w!
  
    pathout =path[:-4]+'_c_'+str(fps)+'.avi'    
    

    fourcc = cv2.VideoWriter_fourcc(*'MJPG')
    
    video_writer = cv2.VideoWriter(pathout, fourcc, fps, (w, h),isColor=True)
    
    # Process each frame and write to the video
    for i in tqdm.tqdm(range(nFrames)):
        grayscale_image = stack[i]
        colored_image = apply_colormap(grayscale_image,cmap)
        colored_image = cv2.cvtColor(colored_image, cv2.COLOR_RGB2BGR)  # Convert RGB to BGR
    
        video_writer.write(colored_image)
    
    # Release the video writer
    video_writer.release()
    print('Convertion done!')

def convertAVIcodec(path,fpsout=0,exp_t=0.2,nFrames=None,isColor=False):
    """
    Function to Directly convert screen recording avi to avi that mac can read
    If fpsout=0, the framerate will not be changed (same as original)
    exp_t: actual exposure time, to remove dupulicate frames
    else fpsout will be changed to set value
    """

    import moviepy.editor as mp
    print("======================")
    print("Convert AVI codec!")
    video = mp.VideoFileClip(path)
    fps = int(video.fps)
    w = int(video.w)
    h = int(video.h)
    if nFrames==None:
        nFrames = int(fps*video.duration)
        duration =video.duration
    print("fps=", fps, "   w =",w, "   h=", h)
    print("Total number of Frames=", nFrames)
    #Remove duplic frames
    if fpsout==0:
        fpsout=fps
        nFramesOut=nFrames
        dup=1
    else:
        dup=fps*exp_t
        nFramesOut=int(nFrames/dup)
  
    # Export avi
    if nFrames==None:
        pathout2 =path[:-4]+'_'+str(fpsout)+'.avi'      
        pathout= path[:-4]+'_DB.tif'    
    else:
        pathout2 =path[:-4]+'_Trim_'+str(fpsout)+'.avi'      
        pathout= path[:-4]+'_Trim_DB.tif'   
    codec  = cv2.VideoWriter_fourcc(*'MJPG')
    video_out = cv2.VideoWriter(pathout2, codec , fpsout, (w,  h),isColor=isColor)
    
    with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
        for j in tqdm.tqdm(range(nFramesOut)):
            i=j*dup
            fr = video.get_frame(mp.cvsecs(i/fps))
            if isColor==False:
                fr = cv2.cvtColor(fr, cv2.COLOR_BGR2GRAY)

            tif.write(fr, contiguous=True)
            if isColor== True:
                fr = cv2.cvtColor(fr,cv2.COLOR_BGR2RGB)#since open cv uses different color sequence
            video_out.write(fr)
        
    
    video.reader.close()
    video_out.release()
    print("Conversion done!")


def invertLUT(path):
    import tifffile
    import tqdm

    video = tifffile.imread(path)
    nFrames, h,w = video.shape[:3]
    pathout =path[:-4]+'_Inv.tiff'    

    with tifffile.TiffWriter(pathout,bigtiff=True) as tif:
        
        print("---------------------------------------------")
        print('Inverting Tiff stack LUT')    
        for i in tqdm.tqdm(range(nFrames)):        
            img=video[i]  
            img_IV=255-img
            tif.write(img_IV, contiguous=True)
        print("Invert LUT done!")










