파이썬 코드임
다른 사람이 뿌린 오픈소스에 오류 안생기게 조금 수정했음
오류는 없고 오류가 뜬다면 이미지 파일 자체가 손상돼서 변환이 되지않는 경우라서
원래 그것도 변환되게 할 수 있는데 안하는게 나아서 패스함
# -*- coding:utf-8 -*-
from PIL import Image
import zipfile
from zipfile import ZipFile
import glob
import os
import shutil
import multiprocessing
import sys
import chardet # 인코딩 확인
from ctypes import windll, wintypes, byref
THUMBNAIL_NAME = '_thumbnail.png'
def unzip(source_file, dest_path):
with zipfile.ZipFile(source_file, 'r') as zf:
zipInfo = zf.infolist()
for member in zipInfo:
try:
#print(chardet.detect(member.filename.encode()))
#member.filename = member.filename.encode('cp437', errors='replace').decode('cp949', 'ignore')
member.filename = member.filename.encode('cp437').decode('euc-kr', 'ignore')
zf.extract(member, dest_path) #압축해제할 파일명, 압축해제할 경로
except:
try:
zf.extract(member, dest_path) #한글로 변환이 안 될시 그대로 변환
except:
raise Exception(source_file + ' 파일명과 ' + dest_path + ' 경로가 잘못되었습니다.')
#zf.extract(member, dest_path)
#print(source_file)
#raise Exception('what?!')
def modify_ctime(path, ctime):
#https://stackoverflow.com/questions/4996405/how-do-i-change-the-file-creation-date-of-a-windows-file
# Arbitrary example of a file and a date
filepath = path
epoch = ctime
# Convert Unix timestamp to Windows FileTime using some magic numbers
# See documentation: https://support.microsoft.com/en-us/help/167296
timestamp = int((epoch * 10000000) + 116444736000000000)
ctime = wintypes.FILETIME(timestamp & 0xFFFFFFFF, timestamp >> 32)
# Call Win32 API to modify the file creation date
handle = windll.kernel32.CreateFileW(filepath, 256, 0, None, 3, 128, None)
windll.kernel32.SetFileTime(handle, byref(ctime), None, None)
windll.kernel32.CloseHandle(handle)
def get_thread_number():
number_of_thread = multiprocessing.cpu_count() - 1
if number_of_thread == 0:
return 1
else:
return number_of_thread
def split_to_chunks(image_paths, n):
return [image_paths[i::n] for i in range(n)]
def convert_images(image_paths, options, shared_queue):
for image_path in image_paths:
image = Image.open(image_path)
image.save(os.path.splitext(image_path)[0] + '.webp', method=6, lossless=options['lossless'], quality=options['quality'])
for image_path in image_paths:
os.remove(image_path)
shared_queue.put(True)
return
def generate_thumbnail(folder_path):
MAX_SIZE = 640
file_paths = []
image_path = get_file_paths_by_extensions(folder_path, ['jpg', 'png', 'webp', 'gif'], file_paths)[0]
# Generate thumbnail only if images exist
if not image_path:
return
image = Image.open(image_path)
width, height = image.size
resize_ratio = min(MAX_SIZE/width, MAX_SIZE/height)
resized_resolution = (int(width*resize_ratio), int(height*resize_ratio))
thumbnail = image.resize(resized_resolution)
thumbnail.save(os.path.join(folder_path, THUMBNAIL_NAME))
def get_file_paths_by_extensions(folder_path, extensions, file_paths):
sub_folder_paths = os.listdir(folder_path)
for sub_folder_path in sub_folder_paths:
full_folder_path = os.path.join(folder_path, sub_folder_path)
if os.path.isdir(full_folder_path):
get_file_paths_by_extensions(full_folder_path, extensions, file_paths)
elif os.path.isfile(full_folder_path):
full_folder_name, full_folder_path_extension = os.path.splitext(full_folder_path)
for extension in extensions:
if full_folder_path_extension == "." + extension:
if not os.path.basename(full_folder_path) == THUMBNAIL_NAME: # 썸네일 파일 제외
file_paths.append(full_folder_path)
return file_paths
def recover_zip(folder_path, backup_path, zip_file_path):
os.rename(backup_path, zip_file_path)
shutil.rmtree(folder_path)
raise NameError('Error during processing images')
def slimify(zip_file_path, options):
print('Processing', zip_file_path)
# Save file time info
file_time = (os.stat(zip_file_path).st_atime, os.stat(zip_file_path).st_mtime)
ctime = os.stat(zip_file_path).st_ctime
# Unzip and make backup
folder_path, extension = os.path.splitext(zip_file_path)
#zip_path, zip_name = os.path.split(os.path.realpath(zip_file_path))
#zip_file_path = os.path.join(zip_path, folder_path)
#shutil.unpack_archive(zip_file_path, folder_path, 'zip') # 압축 파일의 전체 경로, 압축 해체할 폴더의 경로, 압축파일 형식
unzip(zip_file_path, folder_path) # 압축 해제할 파일명, 압축 해제할 경로
if not os.path.exists(folder_path):
raise NameError('File name cannot be folder name')
backup_path = zip_file_path + '.back'
os.rename(zip_file_path, backup_path)
# Find jpg or png
file_paths = []
image_paths = get_file_paths_by_extensions(folder_path, ['jpg', 'png', 'jpeg'], file_paths)
image_path_chunks = split_to_chunks(image_paths, get_thread_number())
# Generate thumbnail if needed
if options['thumbnail']:
generate_thumbnail(folder_path)
# Convert images
processes = []
shared_queue = multiprocessing.Queue()
for i in range(get_thread_number()):
p = multiprocessing.Process(target=convert_images, args=(image_path_chunks[i], options, shared_queue))
processes.append(p)
p.start()
for process in processes:
process.join()
# Check if error occured in multiprocessing
if shared_queue.qsize() != get_thread_number():
recover_zip(folder_path, backup_path, zip_file_path)
return
# Rezip the folder
converted_zip_path = shutil.make_archive(folder_path, 'zip', folder_path)
# Recover file time info
os.utime(converted_zip_path, file_time)
modify_ctime(converted_zip_path, ctime)
# Remove old zip file and folder
shutil.rmtree(folder_path)
os.remove(backup_path)
def get_lossless_option():
print('Select lossy or lossless (Default = lossy)')
print('1. Lossy')
print('2. Lossless')
answer = input()
if answer == '2':
return True
else:
return False
def get_quality_option():
DEFAULT = 80
print('Select quality parameter 1-100 (Default = 80)')
answer = input()
if answer.isdecimal() == False:
return DEFAULT
answer_number = int(answer)
if 0 < answer_number <= 100:
return answer_number
else:
return DEFAULT
def get_thumbnail_option():
print('Generate thumbnail? (for CBXShell) (Default = No)')
print('1. Yes')
print('2. No')
answer = input()
if answer == '1':
return True
else:
return False
if __name__ == '__main__':
# Windows exe support
multiprocessing.freeze_support()
options = {
'lossless': get_lossless_option(),
'quality': get_quality_option(),
'thumbnail': get_thumbnail_option()
}
# In lossless mode, quality means speed
if options['lossless']:
options['quality'] = 100
# Find zip files
zip_file_paths = glob.glob('**/*.zip', recursive=True)
print(zip_file_paths)
# Process zip files
for index, zip_file_path in enumerate(zip_file_paths):
print('Processing', index, '/', len(zip_file_paths))
try:
slimify(zip_file_path, options)
except Exception as err:
print(f'Error during {zip_file_path}', err)
with open('errorlog.txt', 'a+') as f:
f.write(f'Error during {zip_file_path} {err}\n')
print('Process finished')
print('Press Enter to exit')
input()
방주작업할 때 좆같이 느린 쓰레기 변환 프로그램에 고통 받으신 분들 이거 쓰세요
아래 이미지 파일 다운 받아서 jpg를 zip로 확장자 변경한 후 풀어서 압축파일과 실행파일 같이 넣어서 실행하세요