Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Transpose #313

Merged
merged 2 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion resize_frames.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ def main():
parser.add_argument("--crop_type", default="none", type=str,
help="Cropping type 'crop' (default), 'none'")

parser.add_argument("--type", default="png", type=str,
help="File type for frame files (Default 'png')")

parser.add_argument("--verbose", dest="verbose", default=False, action="store_true",
help="Show extra details")
args = parser.parse_args()
Expand All @@ -50,7 +53,7 @@ def main():
args.crop_offset_x,
args.crop_offset_y,
args.crop_type,
).resize()
).resize(type=args.type)

class ResizeFrames:
"""Encapsulate logic for Resize Frames feature"""
Expand Down
4 changes: 3 additions & 1 deletion tabs/transpose_png_files_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from webui_utils.simple_config import SimpleConfig
from webui_utils.simple_icons import SimpleIcons
from webui_utils.file_utils import get_directories
from webui_utils.video_utils import determine_input_format
from webui_utils.mtqdm import Mtqdm
from webui_tips import WebuiTips
from interpolate_engine import InterpolateEngine
Expand Down Expand Up @@ -76,5 +77,6 @@ def transpose_png_batch(self, input_path : str, input_type : str):
def transpose_png_files(self, input_path : str, input_type : str):
"""Transpose button handler"""
if input_path:
type = determine_input_format(input_path)
input_type = TransposePngFiles.UI_TYPES_TO_INTERNAL[input_type]
_TransposePngFiles(input_path, input_type, self.log_fn).transpose()
_TransposePngFiles(input_path, input_type, self.log_fn).transpose(type=type)
84 changes: 62 additions & 22 deletions transpose_png_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,43 @@
from webui_utils.simple_log import SimpleLog
from webui_utils.mtqdm import Mtqdm
from PIL import Image
import numpy as np
import cv2

def main():
"""Use the Transpose PNG Files feature from the command line"""
parser = argparse.ArgumentParser(description='Transpose video frame PNG files')
parser = argparse.ArgumentParser(description='Transpose video frame image files')
parser.add_argument("--path", default="./images", type=str,
help="Path to PNG files to simplify")
parser.add_argument("--type", type=str,
help=f"Transformation type: {', '.join(TransposePngFiles.TYPES)}")
parser.add_argument("--operation", type=str,
help=f"Transformation operation: {', '.join(TransposePngFiles.OPERATIONS)}")
parser.add_argument("--type", default="png", type=str,
help="File type for frame files (Default 'png')")
parser.add_argument("--verbose", dest="verbose", default=False, action="store_true",
help="Show extra details")
args = parser.parse_args()

try:
args.type = args.type.lower()
_ = TransposePngFiles.TYPES.index(args.type)
args.operation = args.operation.lower()
_ = TransposePngFiles.OPERATIONS.index(args.operation)
except:
print(f"'type' must be one of: {', '.join(TransposePngFiles.TYPES)}")
print(f"'operation' must be one of: {', '.join(TransposePngFiles.OPERATIONS)}")
return

log = SimpleLog(args.verbose)
TransposePngFiles(args.path, args.type, log.log).transpose()
TransposePngFiles(args.path, args.operation, log.log).transpose(type=args.type)

class TransposePngFiles:
"""Encapsulate logic for Resequence Files feature"""
def __init__(self,
path : str,
type: str,
operation: str,
log_fn : Callable | None):
self.path = path
self.type = type.lower()
self.operation = operation.lower()
self.log_fn = log_fn

TYPES = ["fliph", "flipv", "ccw90", "rot180", "cw90", "transp", "transv"]
OPERATIONS = ["fliph", "flipv", "ccw90", "rot180", "cw90", "transp", "transv"]
PIL_TYPES = {
"fliph" : Image.Transpose.FLIP_LEFT_RIGHT,
"flipv" : Image.Transpose.FLIP_TOP_BOTTOM,
Expand All @@ -49,23 +53,59 @@ def __init__(self,
"transv" : Image.Transpose.TRANSVERSE
}

def transpose(self) -> None:
"""Invoke the Simplify PNG Files feature"""
files = sorted(glob.glob(os.path.join(self.path, "*.png")))
num_files = len(files)
self.log(f"Found {num_files} files")
METHODS = {
"fliph" : "opencv",
"flipv" : "opencv",
"ccw90" : "pillow",
"rot180" : "opencv",
"cw90" : "pillow",
"transp" : "pillow",
"transv" : "pillow"
}

def pillow_transpose(self, file) -> bool:
try:
method = self.PIL_TYPES[self.type]
except:
raise ValueError(f"Transpose type '{self.type}' is not valid")
pil_method = self.PIL_TYPES[self.operation]
img = Image.open(file)
new_img = img.transpose(method=pil_method)
new_img.save(file)
except Exception as error:
raise ValueError(f"pillow_transpose() failed for file {file} with error '{error}'.")

def opencv_transpose(self, file) -> bool:
try:
frame = cv2.imread(file)
data = np.array(frame, np.uint8)

if self.operation == "fliph":
data = np.flip(data, axis = 1)
elif self.operation == "flipv":
data = np.flip(data, axis = 0)
elif self.operation == "rot180":
data = np.flip(data, axis = 1)
data = np.flip(data, axis = 0)
data = np.flip(data, axis = 1)

img = data.astype(np.uint8)
cv2.imwrite(file, img)
except Exception as error:
raise ValueError(f"opencv_transpose() failed for file {file} with error '{error}'.")

def transpose(self, type) -> None:
"""Invoke the Transpose Image Files feature"""
if not self.operation in self.OPERATIONS:
raise ValueError(f"Transpose type '{self.operation}' is not valid")

files = sorted(glob.glob(os.path.join(self.path, "*." + type)))
num_files = len(files)

with Mtqdm().open_bar(len(files), desc="Transposing") as bar:
for file in files:
self.log(f"removing image info from {file}")
img = Image.open(file)
new_img = img.transpose(method=method)
new_img.save(file)
method = self.METHODS[self.operation]
if method == "pillow":
self.pillow_transpose(file)
else:
self.opencv_transpose(file)
Mtqdm().update_bar(bar)

def log(self, message : str) -> None:
Expand Down
Loading