Files
comic_pdf_converter/comic-pc.py
T

211 lines
8.0 KiB
Python
Raw Normal View History

2026-08-04 20:50:53 -04:00
#!/usr/bin/env python3
from pdf2image import convert_from_path
import os
import shutil
import argparse
import threading
import tempfile
from pathlib import Path
##################################################
# to do:
# 1) √ Keep only the SMALLEST file. No need to keep the others
# 2) √ Have a concept of "working dir" and "target dir" Use the appropriate one (use tempfile for default working directory)
# 3) √ make extraction of PDF into a function
# 4) √ ability to skip portions of the program by args
# 5) Optimize code - loop things instead of calling them x times
# 6) √ Use other image file types (JPG, PNG, etc...)
#
##################################################
def zip_jpg(file, image_type):
print('Creating ZIP file from images')
try:
command = f"zip {file}.cbz ./*.{image_type} >/dev/null"
os.system(command)
except OSError as error:
print(f"Command {command} gave the following error: {error}")
def rar_jpg(file, image_type):
print('Creating RAR file from images')
try:
command = f"rar a {file}.cbr ./*.{image_type} >/dev/null"
os.system(command)
except OSError as error:
print(f"Command {command} gave the following error: {error}")
def sz_jpg(file, image_type):
print('Creating 7z file from images')
try:
command = f"7z a {file}.cb7 ./*.{image_type} >/dev/null"
os.system(command)
except OSError as error:
print(f"Command {command} gave the following error: {error}")
def gtar_jpg(file, image_type):
print('Creating GZ file from images')
try:
command = f"tar czfP {file}.gz.cbt ./*.{image_type} >/dev/null"
os.system(command)
except OSError as error:
print(f"Command {command} gave the following error: {error}")
def btar_jpg(file, image_type):
print('Creating BZ file from images')
try:
command = f"tar cjfP {file}.bz.cbt ./*.{image_type} >/dev/null"
os.system(command)
except OSError as error:
print(f"Command {command} gave the following error: {error}")
def xtar_jpg(file, image_type):
print('Creating XZ file from images')
try:
command = f"tar cJfP {file}.xz.cbt ./*.{image_type} >/dev/null"
os.system(command)
except OSError as error:
print(f"Command {command} gave the following error: {error}")
def convert_bytes(num):
"""
this function will convert bytes to MB.... GB... etc
"""
for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
if num < 1024.0:
return "%3.2f %s" % (num, x)
num /= 1024.0
def file_size(file_path):
"""
this function will return the file size
"""
if os.path.isfile(file_path):
file_info = os.stat(file_path)
return file_info.st_size
else:
return 'File Not found ' + file_path
def extract_pdf(origin_file, work_dir, image_type):
print ("Saving images from PDF to memory")
images = convert_from_path(origin_file)
num = len(images)
print (f"Saving {num} images from memory to disk ({image_type.upper()} {work_dir})")
for i in range(num):
images[i].save(f"{work_dir}/page{i}.{image_type}", image_type)
def report_save_smallest(type_dict, file, dest_dir):
print ("Reporting compressed file sizes")
small_size = 0.0
small_file = ''
for key, value in type_dict.items():
now_file = file + value
now_size = file_size(now_file)
if small_size == 0.0 or now_size < small_size:
small_size = now_size
small_file = now_file
size_str = convert_bytes(now_size)
print (f"Size of {key}: {size_str}")
print(f"Copying smallest file ({small_file}) to destination ({dest_dir})")
shutil.copy2(small_file, dest_dir)
def clean_work_dir(work_dir, filename, image_extension):
for p in Path(work_dir).glob(filename+".*"):
p.unlink()
for p in Path(work_dir).glob("page*."+image_extension):
p.unlink()
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Convert a PDF file to multiple Comic Book reading formats")
parser.add_argument('--pdf', type=str, help='Name of PDF to convert', required=True)
parser.add_argument('--ofn', type=str, help='Output File Name: Name of the comic book files to create (no extension! It will be added accordingly to the file type)', required=True)
parser.add_argument('--odn', default=os.getcwd(), type=str, help='Output Directory Name: Destination folder for the output file (default: current folder)')
parser.add_argument('--work_dir', default=None, type=str, help='Name of the folder to save the images and multiple compressed files (working folder). Contents in the folder will be aggressively deleted. If none, temp folder will be used.')
parser.add_argument('--skip_clean', default=None, action='store_const', const=True, help='do NOT clean up the working directory, leave the images and compressed files (only works if work_dir is specified)')
parser.add_argument('--skip_extract', default=None, action='store_const', const=True, help='do NOT extract the PDF. Go to work_dir and start compressing the images there.')
parser.add_argument('--skip_compress', default=None, action='store_const', const=True, help='do NOT create the compressed comic book files.')
parser.add_argument('--image_type', default='webp', choices=['webp', 'jpeg', 'png', 'tiff', 'bmp', 'ppm'], help='Convert PDF to this type of image. Default=webp')
args = parser.parse_args()
type_dict = {
'Zip': '.cbz',
'Rar': '.cbr',
'7zip': '.cb7',
'Gtar': '.gz.cbt',
'Btar': '.bz.cbt',
'Xtar': '.xz.cbt'
}
if args.skip_clean and (args.work_dir == None):
print("\nIf you want to skip_clean, you must give me a work_dir. Otherwise the app will use a 'temp system' that gets auto-deleted when the app exits\n")
exit()
if args.skip_extract and (args.work_dir == None):
print("\nIf you want to skip_extract, you must tell me where to start compressing the images - give me a word_dir\n")
exit()
initial_cwd = os.getcwd()
origin_file = args.pdf
target_name = args.ofn
image_type = args.image_type
if not os.path.exists(args.odn):
os.mkdir(args.odn)
if args.work_dir != None:
use_temp_dir = False
if not os.path.exists(args.work_dir):
os.mkdir(args.work_dir)
created_work = True
else:
created_work = False
work_dir = args.work_dir
else:
use_temp_dir = True
temp_obj = tempfile.TemporaryDirectory(dir=args.work_dir, delete=True)
work_dir = temp_obj.name
if not args.skip_extract:
extract_pdf(origin_file, work_dir, image_type)
if not args.skip_compress:
print (f"Compressing images into comic book files ({target_name}) on work folder: {work_dir}")
os.chdir(work_dir)
zip = threading.Thread(target=zip_jpg, args=(target_name,image_type))
rar = threading.Thread(target=rar_jpg, args=(target_name,image_type))
sz = threading.Thread(target=sz_jpg, args=(target_name,image_type))
gtar = threading.Thread(target=gtar_jpg, args=(target_name,image_type))
btar = threading.Thread(target=btar_jpg, args=(target_name,image_type))
xtar = threading.Thread(target=xtar_jpg, args=(target_name,image_type))
xtar.start()
btar.start()
sz.start()
zip.start()
rar.start()
gtar.start()
xtar.join()
btar.join()
sz.join()
zip.join()
rar.join()
gtar.join()
report_save_smallest(type_dict, target_name, args.odn)
os.chdir(initial_cwd)
size = convert_bytes(file_size(origin_file))
print (f"Size of source PDF: {size}")
if not args.skip_clean:
# print("____________________skip: "+args.skip_clean )
print("\nClean up of work_dir...")
if use_temp_dir:
temp_obj.cleanup()
else:
clean_work_dir(work_dir, target_name, image_type)
if created_work:
shutil.rmtree(work_dir)
print("\nWe be done")