Compare commits

..

3 Commits

Author SHA1 Message Date
jlw4049
824a83752e feat: v1.0.1 2024-01-29 22:35:48 -05:00
jlw4049
fd61e4e325 feat: reference/sync frames are now a neon green color in text and the text is positioned to the top right hand corner of the screen
refactor: added 2 more sync images for each reference frame
refactor: optimized the code substantially
2024-01-29 22:35:39 -05:00
jlw4049
fe6a5247bc feat: added a work around to attempt to position text to the top right of the image for different fonts/sizes dynamically, while not 100% accurate it's close enough 2024-01-29 22:34:20 -05:00
4 changed files with 114 additions and 54 deletions

@ -6,7 +6,7 @@ from frame_forge.utils import exit_application
program_name = "FrameForge" program_name = "FrameForge"
__version__ = "1.0.0" __version__ = "1.0.1"
if __name__ == "__main__": if __name__ == "__main__":

@ -2,11 +2,13 @@ import re
import shutil import shutil
from random import choice from random import choice
from pathlib import Path from pathlib import Path
from typing import Tuple
from numpy import linspace from numpy import linspace
from unidecode import unidecode from unidecode import unidecode
import awsmfunc import awsmfunc
import vapoursynth as vs import vapoursynth as vs
from frame_forge.exceptions import FrameForgeError from frame_forge.exceptions import FrameForgeError
from frame_forge.font_scaler import FontScaler
from frame_forge.utils import get_working_dir, hex_to_bgr from frame_forge.utils import get_working_dir, hex_to_bgr
@ -83,6 +85,10 @@ class GenerateImages:
"1,0,0,0,100,100,0,0,1,1,0,7,5,0,0,1" "1,0,0,0,100,100,0,0,1,1,0,7,5,0,0,1"
) )
selected_sub_style_ref, selected_sub_style_sync = self.sync_font_scaling(
num_source_frames=num_source_frames, scaling_factor=1.35
)
self.check_de_interlaced(num_source_frames, num_encode_frames) self.check_de_interlaced(num_source_frames, num_encode_frames)
b_frames = self.get_b_frames(num_source_frames) b_frames = self.get_b_frames(num_source_frames)
@ -103,7 +109,8 @@ class GenerateImages:
vs_encode_info, vs_encode_info,
screenshot_comparison_dir, screenshot_comparison_dir,
screenshot_sync_dir, screenshot_sync_dir,
selected_sub_style, selected_sub_style_ref,
selected_sub_style_sync,
) )
return img_job return img_job
@ -115,6 +122,67 @@ class GenerateImages:
flush=True, flush=True,
) )
def sync_font_scaling(
self, num_source_frames, scaling_factor: float
) -> Tuple[str, str]:
calculate_str_len = max(
len("frame: reference"), len(str(f"frame: {num_source_frames}"))
)
scale_position = FontScaler().get_adjusted_scale(
self.sub_size + 2, scaling_factor
)
calculate_right_subs = int(
self.source_node.width
- ((calculate_str_len + self.sub_size + 2) * scale_position)
)
selected_sub_style_ref = (
f"Segoe UI,{self.sub_size + 2},&H31FF31&,&H00000000,&H00000000,&H00000000,"
f"1,0,0,0,100,100,0,0,1,1,0,7,{calculate_right_subs},0,0,1"
)
selected_sub_style_sync = (
f"Segoe UI,{self.sub_size + 2},&H31FF31&,&H00000000,&H00000000,&H00000000,"
f"1,0,0,0,100,100,0,0,1,1,0,7,{calculate_right_subs},0,0,1"
)
return selected_sub_style_ref, selected_sub_style_sync
def generate_ref_screens(
self, selected_sub_style_ref, frames: list, screenshot_sync_dir
):
"""Generates reference frames"""
for ref_frame in frames:
vs_encode_ref_info = self.core.sub.Subtitle(
clip=self.encode_node,
text=f"Reference\nFrame: {ref_frame}",
style=selected_sub_style_ref,
)
awsmfunc.ScreenGen(
vs_encode_ref_info,
frame_numbers=[ref_frame],
fpng_compression=1,
folder=screenshot_sync_dir,
suffix="b_encode__%d",
callback=self.screen_gen_callback,
)
def generate_sync_screens(
self, frame_list, selected_sub_style_sync, screenshot_sync_dir
):
"""Generates sync frames"""
for sync_frame in frame_list:
vs_sync_info = self.core.sub.Subtitle(
clip=self.source_node,
text=f"Sync\nFrame: {sync_frame}",
style=selected_sub_style_sync,
)
awsmfunc.ScreenGen(
vs_sync_info,
frame_numbers=[sync_frame],
fpng_compression=1,
folder=Path(screenshot_sync_dir),
suffix="a_source__%d",
callback=self.screen_gen_callback,
)
def generate_screens( def generate_screens(
self, self,
b_frames, b_frames,
@ -122,8 +190,9 @@ class GenerateImages:
vs_encode_info, vs_encode_info,
screenshot_comparison_dir, screenshot_comparison_dir,
screenshot_sync_dir, screenshot_sync_dir,
selected_sub_style, selected_sub_style_ref,
): selected_sub_style_sync,
) -> str:
print("\nGenerating screenshots, please wait", flush=True) print("\nGenerating screenshots, please wait", flush=True)
# handle re_sync if needed # handle re_sync if needed
@ -169,60 +238,26 @@ class GenerateImages:
sync_2 = choice(remove_sync1) sync_2 = choice(remove_sync1)
# reference subs # reference subs
vs_source_ref_info = self.core.sub.Subtitle( self.generate_ref_screens(
clip=self.source_node, text="Sync", style=selected_sub_style selected_sub_style_ref, [sync_1, sync_2], screenshot_sync_dir
)
vs_encode_ref_info = self.core.sub.Subtitle(
clip=self.encode_node, text="Reference", style=selected_sub_style
) )
# generate screens for the two reference frames # sync subs 1
awsmfunc.ScreenGen( sync_subs_1 = [sync_1 + i for i in range(-5, 6)]
vs_encode_ref_info,
frame_numbers=[sync_1, sync_2], self.generate_sync_screens(
fpng_compression=1, sync_subs_1,
folder=screenshot_sync_dir, selected_sub_style_sync,
suffix="b_encode__%d", Path(Path(screenshot_sync_dir) / "sync1"),
callback=self.screen_gen_callback,
) )
# generate 10 source frames around those reference frames # sync subs 2
awsmfunc.ScreenGen( sync_subs_2 = [sync_2 + i for i in range(-5, 6)]
vs_source_ref_info,
frame_numbers=[
sync_1 - 4,
sync_1 - 3,
sync_1 - 2,
sync_1 - 1,
sync_1,
sync_1 + 1,
sync_1 + 2,
sync_1 + 3,
sync_1 + 4,
],
fpng_compression=1,
folder=Path(Path(screenshot_sync_dir) / "sync1"),
suffix="a_source__%d",
callback=self.screen_gen_callback,
)
awsmfunc.ScreenGen( self.generate_sync_screens(
vs_source_ref_info, sync_subs_2,
frame_numbers=[ selected_sub_style_sync,
sync_2 - 4, Path(Path(screenshot_sync_dir) / "sync2"),
sync_2 - 3,
sync_2 - 2,
sync_2 - 1,
sync_2,
sync_2 + 1,
sync_2 + 2,
sync_2 + 3,
sync_2 + 4,
],
fpng_compression=1,
folder=Path(Path(screenshot_sync_dir) / "sync2"),
suffix="a_source__%d",
callback=self.screen_gen_callback,
) )
print("Screen generation completed", flush=True) print("Screen generation completed", flush=True)

@ -0,0 +1,25 @@
import math
class FontScaler:
def __init__(self, original_font_size=100, original_scale=3.5):
self.original_font_size = original_font_size
self.original_scale = original_scale
def calculate_scale_factor(self, desired_font_size):
"""Calculate the scale factor based on the desired font size."""
return math.log(desired_font_size) / math.log(self.original_font_size)
def adjust_scale_factor(self, scale_factor, multiplier):
"""Adjust the scale factor with a multiplier."""
return scale_factor * multiplier
def scale_font(self, scale_factor):
"""Scale the font size based on the original scale and scale factor."""
return self.original_scale * scale_factor
def get_adjusted_scale(self, desired_font_size, multiplier=1.0):
"""Get the adjusted font scale based on the desired font size and multiplier."""
scale_factor = self.calculate_scale_factor(desired_font_size)
adjusted_scale_factor = self.adjust_scale_factor(scale_factor, multiplier)
return self.scale_font(adjusted_scale_factor)

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "frame-forge" name = "frame-forge"
version = "1.0.0" version = "1.0.1"
description = "CLI to offload image generation to" description = "CLI to offload image generation to"
authors = ["jlw4049 <jlw_4049@hotmail.com>"] authors = ["jlw4049 <jlw_4049@hotmail.com>"]
license = "MIT" license = "MIT"