diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/ChristianPostMaker.iml b/.idea/ChristianPostMaker.iml new file mode 100644 index 0000000..c444878 --- /dev/null +++ b/.idea/ChristianPostMaker.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..a2e120d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..154b2d1 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Fonts.py b/Fonts.py new file mode 100644 index 0000000..57de9e1 --- /dev/null +++ b/Fonts.py @@ -0,0 +1,9 @@ +class Fonts: + fonts_path: str + fonts_size: int + fonts_chars_limit: int + + def __init__(self, fonts_path, fonts_size, fonts_chars_limit): + self.fonts_path = fonts_path + self.fonts_size = fonts_size + self.fonts_chars_limit = fonts_chars_limit diff --git a/customers/0-0.jpg b/customers/0-0.jpg new file mode 100644 index 0000000..af8e989 Binary files /dev/null and b/customers/0-0.jpg differ diff --git a/customers/1-0.jpg b/customers/1-0.jpg new file mode 100644 index 0000000..6c049af Binary files /dev/null and b/customers/1-0.jpg differ diff --git a/customers/test1/0-0.jpg b/customers/test1/0-0.jpg new file mode 100644 index 0000000..bdfe7dd Binary files /dev/null and b/customers/test1/0-0.jpg differ diff --git a/customers/test1/1-0.jpg b/customers/test1/1-0.jpg new file mode 100644 index 0000000..cff3f3e Binary files /dev/null and b/customers/test1/1-0.jpg differ diff --git a/darkenVideos.py b/darkenVideos.py new file mode 100644 index 0000000..62fceb5 --- /dev/null +++ b/darkenVideos.py @@ -0,0 +1,45 @@ +import moviepy.video.io.VideoFileClip as vfc +import os +from moviepy import video + + +def generate_darken_video(video_file, output_path): + video_clip = (vfc.VideoFileClip(video_file, audio=False) + .without_audio()) + + # Save the final video + darken_clip = video_clip.fl_image(darken) + darken_clip.write_videofile(output_path, + threads=8, + codec="libx264") + # Clean up the temporary files + darken_clip.close() + + +# A defined function to darken the frames +def darken(frame): + return frame * DARK + + +def generate_darken_videos(video_folder, output_folder): + # Get a list of video files in the specified folder + video_files = [f"{video_folder}/{file}" for file in os.listdir(video_folder) if file.endswith(".mp4")] + for video_file in video_files: + video_num = video_file.split('/') + video_num = video_num[len(video_num) - 1].split('.') + video_num = video_num[0] + + generate_darken_video(video_file, f"{output_folder}/{video_num}.mp4") + + +video_folder = "E:/Bots/VideoMaker/videos/original/new ones" +output_folder = "E:/Bots/VideoMaker/videos" +DARK = 0.8 +generate_darken_videos(video_folder, output_folder) +# Specific video +# video_file = "E:/Bots/VideoMaker/videos/original/7.mp4" +# output_path = "E:/Bots/VideoMaker/videos/darken 40%/7.mp4" +# generate_darken_video(video_file, output_path) + + + diff --git a/ffmpeg.py b/ffmpeg.py new file mode 100644 index 0000000..d9cfba3 --- /dev/null +++ b/ffmpeg.py @@ -0,0 +1,201 @@ +import os +import random +import subprocess +import re +import time +import json_handler +import verse_handler +import Fonts +import cv2 + + +def create_dirs(output_folder, customer_name, posts=True): + # create a folder for this customer if it doesn't exist + output_path = f"{output_folder}/{customer_name}" + if not os.path.exists(output_path): + os.makedirs(output_path) + # Create folder inside for images + if not os.path.exists(f"{output_path}/verse_images"): + os.makedirs(f"{output_path}/verse_images") + if posts and not os.path.exists(f"{output_path}/post_images"): + os.makedirs(f"{output_path}/post_images") + return output_path + + +def create_videos(video_folder, audio_folder, json_file, fonts_dir, output_folder, text_source_font, image_file, + customer_name, number_of_videos, fonts: Fonts, posts=True): + run_time_average = 0 + if number_of_videos > 1: + start_time_total = time.time() + + json_data = json_handler.get_data(json_file) + verses: str = json_data[0] + refs: str = json_data[1] + + videos_num = list() + audios_num = list() + fonts_num = list() + + # Get lists of video and audio files in the specified folders + video_files = [f"{video_folder}/{file}" for file in os.listdir(video_folder) if file.endswith(".mp4")] + audio_files = [f"{audio_folder}/{file}" for file in os.listdir(audio_folder) if file.endswith(".mp3")] + random_for_video = random.randint(0, len(video_files) - 1) + random_for_audio = random.randint(0, len(audio_files) - 1) + random_for_font = random.randint(0, len(fonts.fonts_path) - 1) + for i in range(number_of_videos): + videos_num.append((random_for_video + i) % len(video_files)) + audios_num.append((random_for_audio + i) % len(audio_files)) + fonts_num.append((random_for_font + i) % len(fonts.fonts_path)) + random.shuffle(videos_num) + random.shuffle(audios_num) + random.shuffle(fonts_num) + + # Creating folder for customer + output_path = create_dirs(output_folder, customer_name, posts) + + for i in range(number_of_videos): + start_time = time.time() + print(f"Creating Video #{i}") + + text_verse = verses[i] + text_source = refs[i] + + # Choose a random video file from the list + random_video_num = videos_num[0] + del videos_num[0] + video_file = video_files[random_video_num] + # video_file = f"{video_folder}/30.mp4" + + # Choose a random font from list + random_font_num = fonts_num[0] + del fonts_num[0] + font_file = fonts.fonts_path[random_font_num] + font_size = fonts.fonts_size[random_font_num] + font_chars = fonts.fonts_chars_limit[random_font_num] + + # Choose a random audio file from the list + random_audio_num = audios_num[0] + del audios_num[0] + audio_file = audio_files[random_audio_num] + + # remove chars from versesource for the name + text_source_for_image = text_source.replace(":", "").rstrip('\n') + text_source_for_name = text_source_for_image.replace(' ', '') + + file_name = f"/{i}-{text_source_for_name}_{random_video_num}_{random_audio_num}_{random_font_num}.mp4" + + create_video(text_verse=text_verse, text_source=text_source, text_source_font=text_source_font, + text_source_for_image=text_source_for_image, + video_file=video_file, audio_file=audio_file, image_file=image_file, + font_file=font_file, font_size=font_size, font_chars=font_chars, + posts=posts, + output_path=output_path, file_name=file_name) + + end_time = time.time() + run_time = end_time - start_time + run_time_average += run_time + print(f"\033[0;34m DONE #{i}, Run time:", round(run_time, 2), "seconds! \033[0m", output_path) + + if number_of_videos > 1: + run_time_average /= number_of_videos + end_time_total = time.time() + run_time_total = end_time_total - start_time_total + print(f"\n\033[0;32mDone making {number_of_videos} videos for {customer_name}!" + f"\nTotal run time:", round(run_time_total, 2), "seconds!" + f"\nAverage run time:", round(run_time_average, 2), + "seconds = ", round(run_time_average / 60, 2), " minutes! \033[0m") + + +def create_video(text_verse, text_source, text_source_font, text_source_for_image, video_file, audio_file, image_file, + font_file, font_size, font_chars, output_path, file_name, posts=True): + # Coordinates of logo image and text2 clips + image_y = 1600 + text2_y = 1300 + + # Get the video size + result = subprocess.run( + ['ffprobe', '-v', 'error', '-show_entries', 'stream=width,height', '-of', 'csv=p=0:s=x', video_file], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + video_size = re.findall('\d+', result.stdout.decode())[0:2] + video_width, video_height = map(int, video_size) + + # Get video duration + ffprobe_command = f'ffprobe -i "{video_file}" -show_entries format=duration -v quiet -of csv="p=0"' + video_duration = subprocess.check_output(ffprobe_command, shell=True) + video_duration = float(video_duration.decode('utf-8').strip()) + + # Set the start time of text + text_start_time = 1 + + # Create image of verse + created_verse_image = verse_handler.create_image(text_verse, font_file, font_size, font_chars, + (int(video_width), int(video_height / 2)), output_path, + text_source_for_image) + + # fix bug that ':' and beyond wasn't showing on screen + text_source = text_source.replace(':', '\:') + output_path += f"/{file_name}" + # FFMPEG command to overlay images and text onto input video + ffmpeg_command = (f'ffmpeg -y -loop 1 -i "{image_file}" -i "{audio_file}" ' + f'-i "{video_file}" -i "{created_verse_image}" -r 24 -filter_complex ' + f'"[2:v][0:v]overlay=(W-w)/2:{image_y}[v1]; ' + # f'[v1]drawtext=fontfile={selected_font}:text=\'{text_verse}\':x=(w-text_w)/2:y=(h-text_h)/2:fontsize=60:fontcolor=white:' + # f'enable=\'between(t,{text_start_time},{video_duration})\'[v2]; ' + f'[v1]drawtext=fontfile=\'{text_source_font}\':text=\'{text_source}\':x=(w-text_w)/2:y={text2_y}:fontsize=42:fontcolor=white:' + f'enable=\'between(t,{text_start_time},{video_duration})\'[v2]; ' + f'[v2][3:v]overlay=(W-w)/2:{video_height}/4:enable=\'between(t,{text_start_time},{video_duration})\'[v3]" ' + f'-t {video_duration} -map "[v3]" -map 1:a -c:v libx264 -preset veryfast -crf 18 -c:a copy "{output_path}"') + + # WITHOUT LOGO + # ffmpeg_command = (f'ffmpeg -y -i "{audio_file}" ' + # f'-i "{video_file}" -i "{created_verse_image}" -r 24 -filter_complex ' + # # f'[v1]drawtext=fontfile={selected_font}:text=\'{text_verse}\':x=(w-text_w)/2:y=(h-text_h)/2:fontsize=60:fontcolor=white:' + # # f'enable=\'between(t,{text_start_time},{video_duration})\'[v2]; ' + # f'"drawtext=fontfile=\'{text_source_font}\':text=\'{text_source}\':x=(w-text_w)/2:y={text2_y}:fontsize=42:fontcolor=white:' + # f'enable=\'between(t,{text_start_time},{video_duration})\'[v1]; ' + # f'[v1][2:v]overlay=(W-w)/2:{video_height}/4:enable=\'between(t,{text_start_time},{video_duration})\'[v2]" ' + # f'-t {video_duration} -map "[v2]" -map 0:a -c:v libx264 -preset veryfast -crf 18 -c:a copy "{output_path}"') + + # Run FFMPEG command + subprocess.call(ffmpeg_command, shell=True) + + # if posts: + # verse_handler.create_post_images(video_path=output_path, output_folder=output_path.strip(f"/{file_name}"), + # verse_image_path=created_verse_image, text_source=text_source) + + +def create_post_images(video_path: str, verse_image_path, text_source, output_folder): + # Open the video file + video = cv2.VideoCapture(video_path) + + # Get the frame rate of the video + fps = int(video.get(cv2.CAP_PROP_FPS)) + + # Set the time in seconds to extract a frame from + time_in_seconds = 2 + + # Calculate the frame index to extract + frame_index = time_in_seconds * fps + + # Set the output image size + output_size = (1080, 1080) + + # Loop through the video frames until we reach the desired frame + for i in range(frame_index): + ret, frame = video.read() + + # Crop the middle square of the frame + height, width, channels = frame.shape + y = 325 + cropped_frame = frame[y:y + 1440, 0:width] + + # Resize the cropped frame to the output size + # resized_frame = cv2.resize(cropped_frame, output_size) + + # Save the frame as an image + output_name = video_path.split('/') + output_name = output_name[len(output_name) - 1].strip(".mp4") + cv2.imwrite(f"{output_folder}/post_images/{output_name}.jpg", cropped_frame) + + # Release the video file + video.release() diff --git a/helper_images.py b/helper_images.py new file mode 100644 index 0000000..2840713 --- /dev/null +++ b/helper_images.py @@ -0,0 +1,50 @@ +from PIL import Image, ImageEnhance +import os + + +def darken_images(images_folder, output_folder): + # Set desired darkness + dark = 0.5 + + # Loop through all the images in the directory + for filename in os.listdir(images_folder): + if filename.endswith(".jpg") or filename.endswith(".png"): + # Open the image + filepath = os.path.join(images_folder, filename) + img = Image.open(filepath) + + # Create an enhancer object for the image + enhancer = ImageEnhance.Brightness(img) + + # Reduce the brightness by a factor of 'dark' + dark_img = enhancer.enhance(dark) + + # Save the cropped image + dark_img.save(f"{output_folder}/{filename}") + + +def cut_images(images_folder, output_folder): + # Set the target size + target_size = (1080, 1350) + + # Loop through all the images in the directory + for filename in os.listdir(images_folder): + if filename.endswith(".jpg") or filename.endswith(".png"): + # Open the image + filepath = os.path.join(images_folder, filename) + img = Image.open(filepath) + + # Get the size of the image + width, height = img.size + + # Calculate the coordinates for cropping + left = (width - target_size[0]) // 2 + top = (height - target_size[1]) // 2 + right = left + target_size[0] + bottom = top + target_size[1] + + # Crop the image + img = img.crop((left, top, right, bottom)) + + # Save the cropped image + img.save(f"{output_folder}/{filename}") diff --git a/json_handler.py b/json_handler.py new file mode 100644 index 0000000..52fa49d --- /dev/null +++ b/json_handler.py @@ -0,0 +1,9 @@ +import json + + +def get_data(json_file): + with open(f'{json_file}', 'r', encoding='utf-8') as f: + jsonData = json.load(f) + verses: str = jsonData['verses'] + refs: str = jsonData['references'] + return verses, refs \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..e9e87db --- /dev/null +++ b/main.py @@ -0,0 +1,19 @@ +import post_handler +import helper_images + +# Define the paths and values to everything +number_of_posts = 2 +images_folder = "C:/Bots/ChristianPostMaker/sources/images/cropped/darken" +text_file = "C:/Bots/ChristianPostMaker/sources/quotes.txt" +font_dir = "C:/Users/samla/AppData/Local/Microsoft/Windows/Fonts/MouldyCheeseRegular-WyMWG.ttf" +output_folder = "C:/Bots/ChristianPostMaker/customers" +logo_file = "C:/Bots/ChristianPostMaker/sources/logo.png" +customer_name = "test1" + + +if __name__ == "__main__": + # helper_images.cut_images(images_folder, f"{images_folder}/cropped") + # helper_images.darken_images(images_folder, f"{images_folder}/darken") + post_handler.create_posts(images_folder=images_folder, text_file=text_file, + font_dir=font_dir, output_folder=output_folder, + logo_file=logo_file, customer_name=customer_name, number_of_posts=number_of_posts) diff --git a/post_handler.py b/post_handler.py new file mode 100644 index 0000000..1d1e389 --- /dev/null +++ b/post_handler.py @@ -0,0 +1,143 @@ +import os +import random +import textwrap +import time +from string import ascii_letters + +from PIL import Image, ImageDraw, ImageFont, ImageFilter, ImageEnhance + +import json_handler + + +def create_dirs(output_folder, customer_name): + # create a folder for this customer if it doesn't exist + output_path = f"{output_folder}/{customer_name}" + if not os.path.exists(output_path): + os.makedirs(output_path) + # Create folder inside for images + if not os.path.exists(f"{output_path}/verse_images"): + os.makedirs(f"{output_path}/verse_images") + return output_path + + +def create_posts(images_folder, text_file, font_dir, output_folder, customer_name, number_of_posts, logo_file: str = None): + run_time_average = 0 + if number_of_posts > 1: + start_time_total = time.time() + + # json_data = json_handler.get_data(json_file) + # verses: str = json_data[0] + # refs: str = json_data[1] + + quotes = ["test1", "test2"] + + + # Get list of photos in the specified folder and shuffle it + image_num = list() + image_files = [f"{images_folder}/{file}" for file in os.listdir(images_folder) if file.endswith(".jpg") or file.endswith(".png")] + random_for_image = random.randint(0, len(image_files) - 1) + for i in range(number_of_posts): + image_num.append((random_for_image + i) % len(image_files)) + random.shuffle(image_num) + + # Creating folder for customer + output_path = create_dirs(output_folder, customer_name) + + for i in range(number_of_posts): + start_time = time.time() + print(f"Creating Post #{i}") + + text = quotes[i] + + # Choose a random image file from the list + random_image_num = image_num[0] + del image_num[0] + image_file = image_files[random_image_num] + file_name = f"/{i}-{random_image_num}.jpg" + create_post(image_file=image_file, text=text, + font_dir=font_dir, output_path=output_path, file_name=file_name, + logo_file=logo_file, customer_name=customer_name) + + end_time = time.time() + run_time = end_time - start_time + run_time_average += run_time + print(f"\033[0;34m DONE #{i}, Run time:", round(run_time, 2), "seconds! \033[0m", output_path) + + if number_of_posts > 1: + run_time_average /= number_of_posts + end_time_total = time.time() + run_time_total = end_time_total - start_time_total + print(f"\n\033[0;32mDone making {number_of_posts} posts for {customer_name}!" + f"\nTotal run time:", round(run_time_total, 2), "seconds!" + f"\nAverage run time:", round(run_time_average, 2), + "seconds = ", round(run_time_average / 60, 2), " minutes! \033[0m") + + +def create_post(image_file, text, font_dir, output_path, file_name, logo_file, customer_name): + # Open specific image + img = Image.open(image_file) + + # Load selected font + font = ImageFont.truetype(font=f'{font_dir}', size=75) + + # Create DrawText object + draw = ImageDraw.Draw(im=img) + + # Define our text: + # Calculate the average length of a single character of our font. + # Note: this takes into account the specific font and font size. + avg_char_width = sum(font.getsize(char)[0] for char in ascii_letters) / len(ascii_letters) + + # Translate this average length into a character count + max_char_count = int(img.size[0] * .718 / avg_char_width) + + # Create a wrapped text object using scaled character count + new_text = textwrap.fill(text=text, width=max_char_count) + + # Define the positions of logo and text + x_logo = 0 + y_logo = 1100 + x_text = img.size[0] / 2 + y_text = img.size[1] / 2 + position = (x_text, y_text) + + # Draw the shadow text + shadow_color = (0, 0, 0, 128) + shadow_position = (x_text+5, y_text+5) + draw.text(shadow_position, text, font=font, fill=shadow_color, anchor='mm') + + # Add main text to the image + draw.text(position, text=new_text, font=font, fill=(255, 255, 255, 255), anchor='mm', + align='center') + + if logo_file is not None: + # Open logo file + img_logo = Image.open(logo_file) + + # Reduce the alpha of the overlay image by 50% + alpha = 0.5 + enhancer = ImageEnhance.Brightness(img_logo) + img_logo_darken = enhancer.enhance(alpha) + + # Create a new image object with the same size as the background image + img_with_logo = Image.new('RGBA', img.size, (0, 0, 0, 0)) + + # Draw the background image onto the new image + img_with_logo.paste(img, (0, 0)) + + # Draw the overlay image onto the new image + img_with_logo.paste(img_logo_darken, (int(x_logo), int(y_logo)), mask=img_logo_darken) + + # Convert from RGBA to RGB + img_with_logo_rgb = img_with_logo.convert("RGB") + + # Save the image + img_with_logo_rgb.save(f"{output_path}/{file_name}") + # combined.show() + return f"{output_path}/{file_name}" + + # If logo was off + # Save the image + img.save(f"{output_path}/{file_name}") + # combined.show() + return f"{output_path}/{file_name}" diff --git a/sources/ChristianQuotes.txt b/sources/ChristianQuotes.txt new file mode 100644 index 0000000..9b46ab2 --- /dev/null +++ b/sources/ChristianQuotes.txt @@ -0,0 +1,120 @@ +Don't worry about the future. +This is the day that the LORD has made. +Believe your prayers will be answered. +Everyday is a gift from God. +Where the Spirit of the Lord is, there is freedom. +When you stress it, pray about it. +Thank you God for another day. +At the right time, I, the Lord, will make it happen. +God says you are more than a conqueror. +Go to God first. +I can do all things through Him who strengthens me. +God's word never fails. +God is greater than your fears. +God is greater than the highs and lows. +He is risen. +God's ways > my ways +No prayer is too small for God. +I am not lucky, I am blessed. +I will refresh the weary and satisfy the faint. +Jesus loves you on your bad days too. +With God all things are possible. +Put your trust in the one who holds it all. +Keep God first. +God, thank you. +God is always on time. +God heard you. Be patient. +Thank God before it happens. +God will never let you down. +Jesus heals. +God is patient with you. +I will strengthen you and help you. +God makes no mistakes. +Love never fails. +I have hidden your word in my heart. +Always be joyful. Never stop praying. +Don't worry about the future. +Less on me, more of him. +Focus on God. +God has a plan. +God is with you. +Jesus changes everything. +My future is in God's hands. +God is for you. +Lord, guide me in every situation. +God is fighting for you. +Don't forget to pray today. +Pray in the good times too. +Every word of God proves true. +God so loved. +Be anxious for nothing. +One prayer can do a lot. +Lord, guide me. +Abide in Him. +God's plan is worthy waiting for. +Choose worship over worry. +God is always with you. +God's plan, not mine. +Prayer is a relationship with God. +When you wake up, pray. +Give it to God. +Jesus is the permanent fix to our problems. +God is able. +You have to let God handle it. +God listens when you pray. +Never get tired of doing good. +When everything else fails. God doesn't. +Set you minds on things above. +God keeps his promises. +You are never too lost to be found. +In His presence there is fullness of joy. +Let my life be an example. +Love casts out fear. +The LORD confides in those who fear him. +Quit overthinking and just pray. +Give God your weakness and He will give you His strength. +In him you have peace. +Trust God when he tells you to wait. +God knows everything and still he listens. +Jesus, I am all in. +God has a purpose for your life. +He turns my darkness into light. +The joy of the Lord is my strength. +God, I pray that I would draw closer to you. +Your comfort broughts joy to my soul. +God loves you unconditionally. +God hears your prayer. Trust him timing. +In you, LORD my God, I put my trust. +For no word from God will every fail. +Worry doesn't change anything. Prayer does. +Faith, Hope, Love. +Keep praying as you wait. +Reminder: God forgave you. +God has given you a spirit of power, of love and of a sound mind. +God has not given us a spirit of fear. +You are my defender, my place of safety in times of troubles. +We love because He first loved us. +Even when you are frustrated, seek God. +God is faithful. +God is all we need. +Lord, I can't do this on my own. +Walk by faith, not by sight. +Being a Christian doesn't change what you deal with. It changes how you deal with it. +In my weakness, you give me strength. +I will refresh the weary and satisfy the faint. +Anxiety comes from the world, peace comes from God. +If God's for you, It doesn't matter what's against you. +The Way, The Truth, The Life +God is most glorified in us when we are most satisfied in Him. +True faith means putting every hope in God's fidelity to His Promises. +Faith does not eliminate questions. But faith knows where to take them. +Some of God's greatest gifts are unanswered prayers. +What God intended for you goes far beyond anything you can imagine. +Life is God's novel. Let him write it. +Your word is a lamp to my feet and a light for my path. +Let us rejoice and be glad in the Lord. +Fear ends where faith begins. +God is my first priority. +Amazing grace. +What would Jesus do? +My lifeguard walked on water. \ No newline at end of file diff --git a/sources/images/autumn-111315_1920.jpg b/sources/images/autumn-111315_1920.jpg new file mode 100644 index 0000000..af7fac1 Binary files /dev/null and b/sources/images/autumn-111315_1920.jpg differ diff --git a/sources/images/cropped/autumn-111315_1920.jpg b/sources/images/cropped/autumn-111315_1920.jpg new file mode 100644 index 0000000..33af0a3 Binary files /dev/null and b/sources/images/cropped/autumn-111315_1920.jpg differ diff --git a/sources/images/cropped/darken/autumn-111315_1920.jpg b/sources/images/cropped/darken/autumn-111315_1920.jpg new file mode 100644 index 0000000..6ab027e Binary files /dev/null and b/sources/images/cropped/darken/autumn-111315_1920.jpg differ diff --git a/sources/logo.png b/sources/logo.png new file mode 100644 index 0000000..2593e17 Binary files /dev/null and b/sources/logo.png differ diff --git a/sources/logo.psd b/sources/logo.psd new file mode 100644 index 0000000..4d53f90 Binary files /dev/null and b/sources/logo.psd differ diff --git a/verse_handler.py b/verse_handler.py new file mode 100644 index 0000000..251c6a0 --- /dev/null +++ b/verse_handler.py @@ -0,0 +1,117 @@ +import os +from string import ascii_letters + +import cv2 +from PIL import Image, ImageDraw, ImageFont, ImageFilter +import textwrap + + +def create_image(text, font_path, font_size, max_char_count, image_size, save_path, text_source): + save_path += "/verse_images" + text = fix_fonts(text, font_path) + # Open a blank image + img = Image.new('RGBA', image_size, color=(190, 190, 190, 0)) + + # Load selected font + font = ImageFont.truetype(font=f'{font_path}', size=font_size) + + # Create DrawText object + draw = ImageDraw.Draw(im=img) + + # Define our text: + # Calculate the average length of a single character of our font. + # Note: this takes into account the specific font and font size. + avg_char_width = sum(font.getsize(char)[0] for char in ascii_letters) / len(ascii_letters) + + # Translate this average length into a character count + max_char_count = max(int(img.size[0] * .718 / avg_char_width), max_char_count) + + # Create a wrapped text object using scaled character count + new_text = textwrap.fill(text=text, width=max_char_count) + + # Draw the shadow text + shadow_image = Image.new('RGBA', img.size, color=(255, 255, 255, 0)) + shadow_draw = ImageDraw.Draw(im=shadow_image) + shadow_draw.text(xy=(img.size[0] / 2 - 1, img.size[1] / 2 + 4), text=new_text, font=font, fill=(0, 0, 0, 80), anchor='mm', + align='center') + # Add main text to the image + draw.text(xy=(img.size[0] / 2, img.size[1] / 2), text=new_text, font=font, fill=(255, 255, 255, 255), anchor='mm', + align='center') + # combine shadow and main + combined = Image.alpha_composite(shadow_image, img) + + # check if image of this source (bible reference) exists already + path_to_check = f"{save_path}/{text_source}.png" + i = 1 + while os.path.exists(path_to_check): + path_to_check = f"{save_path}/{text_source}-{i}.png" + i += 1 + # Save the image + combined.save(f"{path_to_check}") + # combined.show() + return f"{path_to_check}" + + +def create_post_images(video_path: str, verse_image_path, text_source, output_folder): + # Open the video file + video = cv2.VideoCapture(video_path) + + # Get the frame rate of the video + fps = int(video.get(cv2.CAP_PROP_FPS)) + + # Set the time in seconds to extract a frame from + time_in_seconds = 2 + + # Calculate the frame index to extract + frame_index = time_in_seconds * fps + + # Set the output image size + output_size = (1080, 1080) + + # Loop through the video frames until we reach the desired frame + for i in range(frame_index): + ret, frame = video.read() + + # Crop the middle square of the frame + height, width, channels = frame.shape + y = int((height - width) / 2) + cropped_frame = frame[y:y+1080, 0:width] + + background = Image.fromarray(cropped_frame) + verse = Image.open(verse_image_path) + + combined = Image.blend(background, verse, 1) + + # Create a drawing object + draw = ImageDraw.Draw(combined) + + # Define the text to add and the font to use + text = 'Hello, World!' + font = ImageFont.truetype(r"C\:/Users/Samurai/AppData/Local/Microsoft/Windows/Fonts/Aloevera-OVoWO.ttf", size=36) + + # Determine the position to place the text + text_width, text_height = draw.textsize(text, font=font) + x = (combined.width - text_width) / 2 + y = 1300 + + # Add the text to the image + draw.text((x, y), text, font=font, fill=(255, 255, 255)) + + output_name = video_path.split('/') + output_name = output_name[len(output_name) - 1].strip(".mp4") + combined.save(f"{output_folder}/post_images/{output_name}.jpg") + + # Save the frame as an image + # output_name = video_path.split('/') + # output_name = output_name[len(output_name) - 1].strip(".mp4") + # cv2.imwrite(f"{output_folder}/post_images/{output_name}.jpg", cropped_frame) + # + # Release the video file + video.release() + + +def fix_fonts(text, font): + # Font 6 can't display ' + if (font.__contains__("FlowersSunday")): + return text.replace("'", "") + return text \ No newline at end of file