diff --git a/LICENSE b/LICENSE index 6471323..edcd9de 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2022 RichardErkhov - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2022 Richard Erkhov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/gui.py b/gui.py new file mode 100644 index 0000000..f0f748d --- /dev/null +++ b/gui.py @@ -0,0 +1,48 @@ +#simplt gui for archiver +import tkinter as tk +import threading +import time +import main as archiver +from tkinter import messagebox + + +def interface(): + root = tk.Tk() + root.title("Archiver") + root.geometry("300x500") + root.resizable(False, False) + root.configure(background='#f0f0f0') + Title = tk.Label(root, text="Archiver", font=("Helvetica", 16), bg='#f0f0f0') + Title.pack(pady=10) + input_folder = tk.StringVar() + input_folder.set("Input Folder") + input_folder_label = tk.Label(root, textvariable=input_folder, bg='#f0f0f0') + input_folder_label.pack(pady=10) + input_folder_entry = tk.Entry(root, width=30) + input_folder_entry.pack(pady=10) + output_folder = tk.StringVar() + output_folder.set("Output Folder") + output_folder_label = tk.Label(root, textvariable=output_folder, bg='#f0f0f0') + output_folder_label.pack(pady=10) + output_folder_entry = tk.Entry(root, width=30) + output_folder_entry.pack(pady=10) + password = tk.StringVar() + password.set("Password") + password_label = tk.Label(root, textvariable=password, bg='#f0f0f0') + password_label.pack(pady=10) + password_entry = tk.Entry(root, width=30) + password_entry.pack(pady=10) + archive_name = tk.StringVar() + archive_name.set("Archive Name") + archive_name_label = tk.Label(root, textvariable=archive_name, bg='#f0f0f0') + archive_name_label.pack(pady=10) + archive_name_entry = tk.Entry(root, width=30) + archive_name_entry.pack(pady=10) + make_archive_button = tk.Button(root, text="Make Archive", command=lambda: archiver.make_archive(archive_name_entry.get(), input_folder_entry.get(), password_entry.get(), output_folder_entry.get())) + make_archive_button.pack(pady=10) + open_archive_button = tk.Button(root, text="Open Archive", command=lambda: archiver.open_archive(archive_name_entry.get(), output_folder_entry.get(), password_entry.get())) + open_archive_button.pack(pady=10) + root.mainloop() + +if __name__ == "__main__": + interface() diff --git a/main.py b/main.py new file mode 100644 index 0000000..550052f --- /dev/null +++ b/main.py @@ -0,0 +1,165 @@ +import os +import shutil +import subprocess +import sys +import time +import zipfile +import glob +import numpy as np +import cv2 +from PIL import Image +import pyAesCrypt +import skvideo.io +import tqdm +import io +import imageio +def get_files(folder): + files = [] + for filename in os.listdir(folder): + if filename.endswith(".png"): + files.append(os.path.join(filename)) + return files + +def create_video(folder, files, video_name, output_folder='.'): + with open(os.path.join(output_folder, "files.txt"), mode='w') as f: + out = skvideo.io.FFmpegWriter(os.path.join(output_folder,video_name), outputdict={ + '-vcodec': 'libx264', #use the h.264 codec + '-crf': '0', #set the constant rate factor to 0, which is lossless + '-preset':'veryslow' #the slower the better compression, in princple, try + #other options see https://trac.ffmpeg.org/wiki/Encode/H.264 +}) + for filename in tqdm.tqdm(files, desc="compressing files"): + img = cv2.imread(os.path.join(folder,filename)) + f.write(filename + "\n") + out.writeFrame(img[:,:,::-1]) + out.close() + +def create_archive(video_name, archive_name, output_folder='.'): + with zipfile.ZipFile(os.path.join(output_folder, archive_name), 'w') as myzip: + myzip.write(os.path.join(output_folder, video_name)) + myzip.write(os.path.join(output_folder, "files.txt")) + +def encrypt_archive(archive_name, password='password', output_folder='.'): + bufferSize = 64 * 1024 + pyAesCrypt.encryptFile(os.path.join(output_folder, archive_name), + os.path.join(output_folder, archive_name + ".aes"), + str(password), bufferSize) + os.remove(os.path.join(output_folder, archive_name)) + +def decrypt_archive(archive_name, password='password'): + bufferSize = 64 * 1024 + pyAesCrypt.decryptFile(archive_name + ".aes", archive_name, str(password), bufferSize) + +#in memory we need to decrypt archive +#and read get files.txt without extracting it to drive +def get_filesx(arhive_name, password='password'): + #decrypt archive + #use pyAesCrypt.decryptStream + decypted_archive = io.BytesIO() + with open(arhive_name, 'rb') as f: + length = os.path.getsize(arhive_name) + pyAesCrypt.decryptStream(f, decypted_archive, password, 64 * 1024, length) + decypted_archive.seek(0) + #read files.txt + with zipfile.ZipFile(decypted_archive) as myzip: + with myzip.open("files.txt") as f: + files = f.read().decode().splitlines() + return files + +#get random frame from video from aes archive +#you can do the same that we did with files.txt +def get_random_frame(archive_name, password='password'): + #decrypt archive + #use pyAesCrypt.decryptStream + decypted_archive = io.BytesIO() + with open(archive_name, 'rb') as f: + length = os.path.getsize(archive_name) + pyAesCrypt.decryptStream(f, decypted_archive, password, 64 * 1024, length) + decypted_archive.seek(0) + #read files.txt + with zipfile.ZipFile(decypted_archive) as myzip: + with myzip.open("video.avi") as video: + print(type(video.read())) + #using imageio iterate over frames in the videio + + for frame in imageio.get_reader(video.read(), 'ffmpeg'): + print(frame.shape) + + #videogen = skvideo.io.vreader(video.read()) + #e, img = cap.read() + #for frame in vid: + # cv2.imshow("frame", frame) + # cv2.waitKey(0) + #if e: + #show images + #cap.release() + #cap.release() + #return img + #else: + #cap.release() + #return None + #get random frame + rand_file = np.random.choice(files) + return rand_file + +def unpack_archive(archive_name): + with zipfile.ZipFile(archive_name, 'r') as myzip: + myzip.extractall() + os.remove(archive_name) + + +def extract_frames(video_name, folder): + if not os.path.exists(folder): + if folder.strip() == '': + folder = 'test' + os.makedirs(folder) + cap = cv2.VideoCapture(video_name) + + with open("files.txt", mode='r') as f: + for line in tqdm.tqdm(f, desc='extracting images'): + line = line.strip() + e, img = cap.read() + if e: + cv2.imwrite(os.path.join(folder,line), img) + else: + cap.release() + break + try: cap.release() + except: pass + time.sleep(1) + os.remove(video_name) + os.remove("files.txt") +def make_archive(archive_name: str, folder_name: str, password=None, output_folder='.'): + #check if folder exists, if not create it + if not os.path.exists(folder_name): + os.makedirs(folder_name) + #get files + files = get_files(folder_name) + #create video + video_name = "video.avi" + create_video(folder_name, files, video_name, output_folder=output_folder) + #create archive + create_archive(video_name, archive_name, output_folder=output_folder) + #encrypt archive + if password is not None: + encrypt_archive(archive_name, password = password, output_folder=output_folder) + else: + encrypt_archive(archive_name, password='password', output_folder=output_folder) + #remove video + os.remove(os.path.join(output_folder, video_name)) + os.remove(os.path.join(output_folder, "files.txt")) +def open_archive(archive_name, folder_name, password=None): + #decrypt archive + if password is not None: + decrypt_archive(archive_name, password = password) + else: + decrypt_archive(archive_name, password='password') + #unpack archive + unpack_archive(archive_name) + #extract frames + video_name = "video.avi" + extract_frames(video_name, folder_name) + +if __name__ == "__main__": + make_archive("test.zip", "test", password='password') + open_archive("test.zip", "test", password='password') diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e69de29