Commit bb769164 by xiaoqi

width

parent 7c519188
...@@ -198,13 +198,16 @@ def parse_anmf_data(webp_info): ...@@ -198,13 +198,16 @@ def parse_anmf_data(webp_info):
# 打开 WebP 动画文件并解析为 PNG 序列帧 # 打开 WebP 动画文件并解析为 PNG 序列帧
def webp2png(webp_file, dir_file): # 打开 WebP 动画文件并解析为 PNG 序列帧
def webp2png(webp_file, dir_file, target_width=None):
# 确保目标目录存在 # 确保目标目录存在
if Path(dir_file).exists(): # 不重新生成png,只生成一次 if Path(dir_file).exists(): # 不重新生成png,只生成一次
return True return True
os.makedirs(dir_file, exist_ok=True) os.makedirs(dir_file, exist_ok=True)
# 打开 WebP 文件 # 打开 WebP 文件
img = Image.open(webp_file) img = Image.open(webp_file)
# 检查是否是动画 # 检查是否是动画
if (not getattr(img, "is_animated", False)) | (img.n_frames <= 1): if (not getattr(img, "is_animated", False)) | (img.n_frames <= 1):
print("这不是一个动画 WebP 文件") print("这不是一个动画 WebP 文件")
...@@ -215,20 +218,29 @@ def webp2png(webp_file, dir_file): ...@@ -215,20 +218,29 @@ def webp2png(webp_file, dir_file):
img.seek(i) # 移动到第 i 帧 img.seek(i) # 移动到第 i 帧
frame = img.copy() # 复制当前帧 frame = img.copy() # 复制当前帧
width, height = frame.size width, height = frame.size
# 检查宽度和高度是否为偶数,如果不是,则调整大小
if width % 2 != 0: # 如果 target_width 为 None,则裁剪到最近的能被 8 整除的宽度
width -= 1 if target_width is None:
if height % 2 != 0: target_width = (width // 8) * 8 # 向下取整到最近的 8 的倍数
height -= 1 if target_width < 8: # 确保宽度至少为 8
# 调整图片大小 target_width = 8
if width < img.size[0] or height < img.size[1]:
frame = frame.crop((0, 0, width, height)) # 如果目标宽度大于原图宽度,添加透明背景居中
if target_width > width:
new_frame = Image.new("RGBA", (target_width, height), (0, 0, 0, 0))
offset = (target_width - width) // 2
new_frame.paste(frame, (offset, 0))
frame = new_frame
# 如果目标宽度小于原图宽度,裁剪图片
elif target_width < width:
frame = frame.crop(((width - target_width) // 2, 0, (width + target_width) // 2, height))
# 构造保存路径 # 构造保存路径
frame_path = os.path.join(dir_file, f"frame_{i:03d}.png") frame_path = os.path.join(dir_file, f"frame_{i:03d}.png")
# 保存为 PNG 文件 # 保存为 PNG 文件
frame.save(frame_path, "PNG") frame.save(frame_path, "PNG")
# enhance_png(frame_path)
return True return True
...@@ -484,7 +496,7 @@ if __name__ == '__main__': ...@@ -484,7 +496,7 @@ if __name__ == '__main__':
inputDirOrFile = inputDirOrFile.replace("\"", "") inputDirOrFile = inputDirOrFile.replace("\"", "")
start_time = time.time() start_time = time.time()
print(f"pvf={p_vf}") print(f"pvf={p_vf}")
check_file_or_dir(inputDirOrFile, "") check_file_or_dir(inputDirOrFile, "-2")
print(f"耗时:{time.time() - start_time}秒") print(f"耗时:{time.time() - start_time}秒")
print(f"mp4大小:{mp4_size_total}") print(f"mp4大小:{mp4_size_total}")
print(f"webp大小:{webp_size_total}") print(f"webp大小:{webp_size_total}")
......
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import os
import subprocess
import sys
import shutil
import argparse
import cv2
import numpy as np
isDebug = False
needZip = False
outputVideoPath = ""
imageDir = ""
srcPath = ""
maskPath = ""
outputPath = ""
oVideoFilePath = ""
fps = 25
bitrate = 2000
def main():
parser = argparse.ArgumentParser(description='manual to this script')
parser.add_argument('--file', type=str, default = None)
parser.add_argument('--dir', type=str, default = None)
parser.add_argument('--zip', type=str2bool, nargs='?', const=True, default = False, help="Activate zip mode.")
parser.add_argument('--fps', type=int, default = 25)
parser.add_argument('--bitrate', type=int, default = 2000)
args = parser.parse_args()
print("convertAlphaVideo.py running")
global needZip
needZip = args.zip
fps = args.fps
bitrate = args.bitrate
# print "args.zip: ", args.zip
if not args.file is None:
parseVideoFile(args.file)
elif not args.dir is None:
parseImageDir(args.dir)
else:
print("params is None!")
return
print("finish")
def str2bool(v):
if isinstance(v, bool):
return v
if v.lower() in ('yes', 'true', 't', 'y', '1'):
return True
elif v.lower() in ('no', 'false', 'f', 'n', '0'):
return False
else:
raise argparse.ArgumentTypeError('Boolean value expected.')
def help():
print("help ~")
def parseVideoFile(path):
print(">>>>>>> paraseVideoFile, file is %s" % path)
parentDir = os.path.basename(path)
parentDir = parentDir.split('.')[0] + "/"
initDir(parentDir)
videoToImage(path, imageDir)
parseImageList(imageDir)
imagesToVideo(outputPath, oVideoFilePath)
shutil.rmtree(parentDir + "temp/")
print(">>>>>> convert alpha video finish, video file path is : %s" % oVideoFilePath)
def parseImageDir(path):
parentDir = os.path.abspath(path) + "/"
print(">>>>>>> paraseImageDir, dirName is %s" % parentDir)
initDir(parentDir)
parseImageList(parentDir)
imagesToVideo(outputPath, oVideoFilePath)
shutil.rmtree(parentDir + "temp/")
print(">>>>>> convert alpha video finish, video file path is : %s" % oVideoFilePath)
def initDir(parentDir):
global imageDir
imageDir = parentDir + "temp/imageDir/"
mkdir(imageDir)
global srcPath
srcPath = parentDir + "temp/source/"
mkdir(srcPath)
global maskPath
maskPath = parentDir + "temp/mask/"
mkdir(maskPath)
global outputPath
outputPath = parentDir + "temp/output/"
mkdir(outputPath)
global outputVideoPath
outputVideoPath = parentDir + "output/"
mkdir(outputVideoPath)
global oVideoFilePath
oVideoFilePath = outputVideoPath + "video.mp4"
def parseImageList(inputPath):
fileList = os.listdir(inputPath)
totalLength = len(fileList)
progress = 0
for fileName in fileList:
if os.path.splitext(fileName)[1] == ".png":
inputImageFile = inputPath + fileName
srcImageFile = srcPath + os.path.splitext(fileName)[0] + ".jpg"
tempMaskImageFile = maskPath + os.path.splitext(fileName)[0] + "_temp.jpg"
maskImageFile = maskPath + os.path.splitext(fileName)[0] + ".jpg"
outputImageFile = outputPath + os.path.splitext(fileName)[0] + ".jpg"
removeAlpha(inputImageFile, srcImageFile)
if needZip:
separateAlphaChannel(inputImageFile, tempMaskImageFile)
zipAlphaChannelPro(tempMaskImageFile, maskImageFile)
else:
separateAlphaChannel(inputImageFile, maskImageFile)
appendImageLand(srcImageFile, maskImageFile, outputImageFile)
deleteTempFile(srcImageFile)
deleteTempFile(maskImageFile)
deleteTempFile(tempMaskImageFile)
progress += 1
updateProgress(progress, totalLength)
def videoToImage(videoPath, imageDir):
command = "ffmpeg -i {} -r {} {}%05d.png".format(videoPath, fps, imageDir)
if isDebug:
print (command)
ret = subprocess.Popen(command, shell = True)
ret.communicate()
def removeAlpha(imageSrc, imageDst):
command = "convert {} -background black -alpha remove {}".format(imageSrc, imageDst)
if isDebug:
print (command)
ret = subprocess.Popen(command, shell = True)
ret.communicate()
def separateAlphaChannel(imageFileOne, imageFileTwo):
command = "convert {} -channel A -separate {}".format(imageFileOne, imageFileTwo)
if isDebug:
print (command)
ret = subprocess.Popen(command, shell = True)
ret.communicate()
def zipAlphaChannel(imageSrc, imageDst):
srcImage = cv2.imread(imageSrc)
shape = srcImage.shape
dstImage = np.zeros((int(shape[0]), int(shape[1])/3, int(shape[2])), np.uint8)
dstShape = dstImage.shape
height = dstShape[0]
width = dstShape[1]
channels = dstShape[2]
for row in range(height):
for col in range(width):
for channel in range(channels):
dstImage[row][col][channel] = srcImage[row][col * 3 + channel][0]
cv2.imwrite(imageDst, dstImage)
def zipAlphaChannelPro(imageSrc, imageDst):
srcImage = cv2.imread(imageSrc)
shape = srcImage.shape
dstImage = np.zeros((int(shape[0]), int(shape[1])/3, int(shape[2])), np.uint8)
dstShape = dstImage.shape
height = dstShape[0]
width = dstShape[1]
channels = dstShape[2]
for row in range(height):
for col in range(width):
for channel in range(channels):
dstImage[row][col][channel] = srcImage[row][col + channel * width][0]
cv2.imwrite(imageDst, dstImage)
def appendImageLand(imageFileOne, imageFileTwo, imageFileAppend):
command = "convert +append {} {} {}".format(imageFileTwo, imageFileOne, imageFileAppend)
if isDebug:
print (command)
ret = subprocess.Popen(command, shell = True)
ret.communicate()
def deleteTempFile(filePath):
if os.path.exists(filePath):
os.remove(filePath)
def imagesToVideo(imagesPath, videoFile):
command = "ffmpeg -r {} -i {}%05d.jpg -vcodec libx264 -pix_fmt yuv420p -b {}k {}".format(fps, imagesPath, bitrate, videoFile)
if isDebug:
print (command)
ret = subprocess.Popen(command, shell = True)
ret.communicate()
def updateProgress(progress, total):
percent = round(1.0 * progress / total * 100,2)
sys.stdout.write('\rprogress : %s [%d/%d]'%(str(percent)+'%', progress, total))
sys.stdout.flush()
def mkdir(path):
folder = os.path.exists(path)
if not folder:
os.makedirs(path)
if __name__ == '__main__':
main()
\ No newline at end of file
...@@ -25,6 +25,7 @@ p_tune = "animation" ...@@ -25,6 +25,7 @@ p_tune = "animation"
p_pix_fmt = "yuv444p" p_pix_fmt = "yuv444p"
p_codec = "libx264" p_codec = "libx264"
p_enable_sharpening = "" # 5:5: 1.5:0: 0:0 // p_enable_sharpening = "" # 5:5: 1.5:0: 0:0 //
p_width = None
""" """
luma_msize_x:亮度矩阵的水平大小(X方向)。这个值定义了应用于亮度分量的模糊矩阵的宽度。 luma_msize_x:亮度矩阵的水平大小(X方向)。这个值定义了应用于亮度分量的模糊矩阵的宽度。
luma_msize_y:亮度矩阵的垂直大小(Y方向)。这个值定义了应用于亮度分量的模糊矩阵的高度。 luma_msize_y:亮度矩阵的垂直大小(Y方向)。这个值定义了应用于亮度分量的模糊矩阵的高度。
...@@ -158,7 +159,7 @@ def png2mp4(output_video, fps2, png_dir, target_fps: int = 1000): ...@@ -158,7 +159,7 @@ def png2mp4(output_video, fps2, png_dir, target_fps: int = 1000):
image_clip = ImageSequenceClip(image_arrays, fps=fps) image_clip = ImageSequenceClip(image_arrays, fps=fps)
# 创建纯色背景 # 创建纯色背景
background_color = (0, 0, 0) # 背景颜色(黑) background_color = (255, 255, 255) # 背景颜色(黑)
background = ColorClip( background = ColorClip(
size=image_clip.size, # 背景尺寸与图像帧一致 size=image_clip.size, # 背景尺寸与图像帧一致
color=background_color, # 背景颜色 color=background_color, # 背景颜色
...@@ -224,14 +225,21 @@ def parse_anmf_data(webp_info): ...@@ -224,14 +225,21 @@ def parse_anmf_data(webp_info):
return result return result
from PIL import Image, ImageOps
import os
from pathlib import Path
# 打开 WebP 动画文件并解析为 PNG 序列帧 # 打开 WebP 动画文件并解析为 PNG 序列帧
def webp2png(webp_file, dir_file): def webp2png(webp_file, dir_file, target_width=None):
# 确保目标目录存在 # 确保目标目录存在
if Path(dir_file).exists(): # 不重新生成png,只生成一次 if Path(dir_file).exists(): # 不重新生成png,只生成一次
return True return True
os.makedirs(dir_file, exist_ok=True) os.makedirs(dir_file, exist_ok=True)
# 打开 WebP 文件 # 打开 WebP 文件
img = Image.open(webp_file) img = Image.open(webp_file)
# 检查是否是动画 # 检查是否是动画
if (not getattr(img, "is_animated", False)) | (img.n_frames <= 1): if (not getattr(img, "is_animated", False)) | (img.n_frames <= 1):
print("这不是一个动画 WebP 文件") print("这不是一个动画 WebP 文件")
...@@ -242,22 +250,30 @@ def webp2png(webp_file, dir_file): ...@@ -242,22 +250,30 @@ def webp2png(webp_file, dir_file):
img.seek(i) # 移动到第 i 帧 img.seek(i) # 移动到第 i 帧
frame = img.copy() # 复制当前帧 frame = img.copy() # 复制当前帧
width, height = frame.size width, height = frame.size
# 检查宽度和高度是否为偶数,如果不是,则调整大小
if width % 2 != 0: # 如果 target_width 为 None,则裁剪到最近的能被 8 整除的宽度
width -= 1 if target_width is None:
if height % 2 != 0: target_width = (width // 8) * 8 # 向下取整到最近的 8 的倍数
height -= 1 if target_width < 8: # 确保宽度至少为 8
# 调整图片大小 target_width = 8
if width < img.size[0] or height < img.size[1]:
frame = frame.crop((0, 0, width, height)) # 如果目标宽度大于原图宽度,添加透明背景居中
if target_width > width:
new_frame = Image.new("RGBA", (target_width, height), (0, 0, 0, 0))
offset = (target_width - width) // 2
new_frame.paste(frame, (offset, 0))
frame = new_frame
# 如果目标宽度小于原图宽度,裁剪图片
elif target_width < width:
frame = frame.crop(((width - target_width) // 2, 0, (width + target_width) // 2, height))
# 构造保存路径 # 构造保存路径
frame_path = os.path.join(dir_file, f"frame_{i:03d}.png") frame_path = os.path.join(dir_file, f"frame_{i:03d}.png")
# 保存为 PNG 文件 # 保存为 PNG 文件
frame.save(frame_path, "PNG") frame.save(frame_path, "PNG")
# enhance_png(frame_path)
return True
return True
def enhance_png(png_file_path): def enhance_png(png_file_path):
# 打开原始图片 # 打开原始图片
...@@ -418,12 +434,17 @@ def webp2mp4core(input_webp_path_str, output_file_path: str = None, output_name: ...@@ -418,12 +434,17 @@ def webp2mp4core(input_webp_path_str, output_file_path: str = None, output_name:
return return
# 在临时目录下创建对应的临时文件夹路径 # 在临时目录下创建对应的临时文件夹路径
# 获取系统临时目录 # 获取系统临时目录
temp_dir = Path(tempfile.gettempdir()) / "convert_webp4"
if output_name is None:
dir_name_end = ""
else:
dir_name_end = output_name
temp_dir = Path(tempfile.gettempdir()) / f"convert_webp4-{dir_name_end}"
temp_png_dir = temp_dir / webp_path.stem temp_png_dir = temp_dir / webp_path.stem
temp_png_alpha_dir = temp_dir / f"alpha_{webp_path.stem}" temp_png_alpha_dir = temp_dir / f"alpha_{webp_path.stem}"
# 使用更新后的临时文件夹路径进行后续操作 # 使用更新后的临时文件夹路径进行后续操作
if not webp2png(input_webp_path_str, temp_png_dir): if not webp2png(input_webp_path_str, temp_png_dir,target_width=p_width):
return return
print(f"已经{input_webp_path_str}转成成png帧,保存在{temp_png_dir}") print(f"已经{input_webp_path_str}转成成png帧,保存在{temp_png_dir}")
convert_to_grayscale(temp_png_dir, temp_png_alpha_dir) convert_to_grayscale(temp_png_dir, temp_png_alpha_dir)
...@@ -498,7 +519,8 @@ if __name__ == '__main__': ...@@ -498,7 +519,8 @@ if __name__ == '__main__':
inputDirOrFile = inputDirOrFile.replace("\"", "") inputDirOrFile = inputDirOrFile.replace("\"", "")
start_time = time.time() start_time = time.time()
print(f"pvf={p_vf}") print(f"pvf={p_vf}")
check_file_or_dir(inputDirOrFile, "") check_file_or_dir(inputDirOrFile,output_name="-2")
print(f"耗时:{time.time() - start_time}秒") print(f"耗时:{time.time() - start_time}秒")
print(f"mp4大小:{mp4_size_total}") print(f"mp4大小:{mp4_size_total}")
print(f"webp大小:{webp_size_total}") print(f"webp大小:{webp_size_total}")
......
import cv2
import os
import sys
def encode_images_to_mp4(image_folder, output_file, fps=30):
# 获取图片路径列表
images = [img for img in os.listdir(image_folder) if img.endswith(('.png', '.jpg', '.jpeg'))]
images.sort() # 按文件名排序
if not images:
print("未找到图片文件,请检查路径和格式!")
return
# 读取第一张图片以获取尺寸
first_image_path = os.path.join(image_folder, images[0])
frame = cv2.imread(first_image_path)
if frame is None:
print(f"无法读取图片: {first_image_path}")
return
height, width, layers = frame.shape
size = (width, height)
# 定义视频编码器和输出文件
fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 使用 mp4 编码
video = cv2.VideoWriter(output_file, fourcc, fps, size)
# 将图片写入视频
for image_name in images:
image_path = os.path.join(image_folder, image_name)
frame = cv2.imread(image_path)
if frame is not None:
video.write(frame)
else:
print(f"跳过无法读取的图片: {image_path}")
# 释放资源
video.release()
print(f"视频已生成: {output_file}")
if __name__ == "__main__":
if len(sys.argv) != 4:
print("用法: python encode_to_mp4.py <图片文件夹路径> <输出文件路径> <帧率>")
else:
image_folder = sys.argv[1]
output_file = sys.argv[2]
fps = int(sys.argv[3])
encode_images_to_mp4(image_folder, output_file, fps)
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment