#!/usr/bin/python3
# coding: utf-8
import os
import imageio.v2 as imageio
import cv2
from PIL import Image, ImageDraw, ImageFont

# ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")
ascii_char = list('MNHQ$OC?7>!:-;. ')


def get_char(r, g, b, alpha=256):
    if alpha == 0:
        return ' '
    # 这是一个优化，将浮点运算转成整型运算
    gray = (2126 * r + 7152 * g + 722 * b) / 10000
    # 为什么是1.0 因为alpha、gray是整型运算的时候按整型算如果小于1的话按0算
    char_idx = int((gray / (alpha + 1.0)) * len(ascii_char))
    return ascii_char[char_idx]


def text2image(content, width, height, filename):
    '''
    字符转图片
    :param content: 字符数组
    :param width: 输出的图片宽度
    :param height: 输出的图片高度
    :param filename: 输出的图片名称
    :return:
    '''
    image = Image.new("RGB", (width, height), (255, 255, 255))
    canvas = ImageDraw.Draw(image)
    font = ImageFont.truetype('JetBrainsMono-Thin.ttf')
    fillcolor = "#000000"

    x, y = 0, 0
    font_w, font_h = 6, 12          # 设置单个字符长款
    for i in range(len(content)):
        if content[i] == '\n':
            x = -font_w
            y += font_h
            continue
        canvas.text((x, y), content[i], fill=fillcolor, font=font)
        x += font_w
    image.save(filename)


def image2textimage(file_name="test.jpg", multiple=1.0, out_file_name='output.txt'):
    '''
    将图片转成字符图片
    :param file_name:
    :param multiple: 缩放比例
    :param out_file_name:
    :return:
    '''
    text = ''
    im = Image.open(file_name)
    width, height = int(im.size[0] * multiple), int(im.size[1] * multiple)
    width_text, height_text = int(width / 6), int(height / 12)     # 原始图片长款等比例缩放
    im = im.resize((width_text, height_text), Image.NEAREST)
    for i in range(height_text):
        for j in range(width_text):
            text += get_char(*im.getpixel((j, i)))
        text += '\n'
    # with open(out_file_name, 'w') as f:
    #     f.write(text)
    text2image(text, width, height, file_name + '_txt.png')
    return file_name + '_txt.png'

def video2images(source_video, start_time, end_time, interval=1.0):
    '''
    将视频转保存为图片s
    :param source_video: 视频文件
    :param start_time: 开始时间/s
    :param end_time: 结束时间/s
    :param interval: 时间间隔/s
    :return:
    '''
    # 创建零时目录
    tmppath = os.path.join(os.getcwd(), 'tmp')
    if not os.path.exists(tmppath):
        os.mkdir(tmppath)

    cap = cv2.VideoCapture(source_video)
    if not cap.isOpened():
        print("Error: Could not open video.")
        return []
    else:
        fps = cap.get(5)  # 帧速率
        frame_number = cap.get(7)  # 视频文件的帧数
        duration = frame_number / fps  # 视频总帧数/帧速率 是时间/秒

        print("总时长[%.2f]秒,开始时间[%.2f]秒结束时间[%.2f]秒" % (duration, start_time, end_time))
        if start_time > duration or end_time > duration:
            print("Error: 截取时间断异常.总时长[%d]秒,开始时间[%d]秒结束时间[%d]秒" % (duration, start_time, end_time))
            return []

        start_frame = int(fps * float(start_time))
        end_frame = int(fps * float(end_time))
        interval_frame = int(fps * float(interval))

        print("总帧数[%d],帧率[%d],开始帧数[%d]，结束帧数[%d]， 间隔[%d]" % (frame_number, fps, start_frame, end_frame, interval_frame))
        num = 0
        images = []
        while True:
            success, frame = cap.read()
            if success:
                if int(start_frame) <= int(num) <= int(end_frame):
                    if success and int(num) % int(interval_frame) == 0:
                        image_name = os.path.join(tmppath, f"frame_{num}.png")
                        cv2.imwrite(image_name, frame)
                        images.append(image_name)
            num += 1
            if num > frame_number:
                break
        cap.release()
        return images
    return texts


def image2gif(textimages, output, fps=2):
    images=[]
    for pic in textimages:
        images.append(imageio.imread(pic))
    imageio.mimsave(output, images, format='GIF', fps=fps, loop=0)

def fontText(path=''):
    '''
    查看文本字符宽度和高度
    :param path:
    :return:
    '''
    font = ImageFont.truetype(path)
    for t in ascii_char:
        fbox = font.getbbox(t)
        print(t, fbox[2]-fbox[0], fbox[3]-fbox[1])

if __name__ == '__main__':
    images = video2images('庆余年2.mov', start_time=0, end_time=10, interval=0.5)
    textImages = []
    for im in images:
        textImages.append(image2textimage(im))
    image2gif(textImages, 'output.gif')

