diff --git a/docs/assets/hacking.png b/docs/assets/hacking.png index 4298390..03f4fc6 100644 Binary files a/docs/assets/hacking.png and b/docs/assets/hacking.png differ diff --git a/docs/assets/productivity.png b/docs/assets/productivity.png index f061036..72a4c18 100644 Binary files a/docs/assets/productivity.png and b/docs/assets/productivity.png differ diff --git a/docs/assets/selfhosting.png b/docs/assets/selfhosting.png index 784b968..be5de86 100644 Binary files a/docs/assets/selfhosting.png and b/docs/assets/selfhosting.png differ diff --git a/docs/graphs/tor deanonymizations.png b/docs/graphs/tor deanonymizations.png index 5b8b600..c6fde82 100644 Binary files a/docs/graphs/tor deanonymizations.png and b/docs/graphs/tor deanonymizations.png differ diff --git a/blogfix.sh b/scripts/blogfix.sh similarity index 100% rename from blogfix.sh rename to scripts/blogfix.sh diff --git a/convert_old_blog.py b/scripts/convert_old_blog.py similarity index 100% rename from convert_old_blog.py rename to scripts/convert_old_blog.py diff --git a/exp/blogtranslate.py b/scripts/exp/blogtranslate.py similarity index 100% rename from exp/blogtranslate.py rename to scripts/exp/blogtranslate.py diff --git a/scripts/imagecompressv2.py b/scripts/imagecompressv2.py new file mode 100644 index 0000000..c1087eb --- /dev/null +++ b/scripts/imagecompressv2.py @@ -0,0 +1,63 @@ +#!/usr/bin/python3 + +# requires imagemagick, avifenc, svt-av1 + +import os +import subprocess +import concurrent.futures + +# below this threshold, it won't be compressed with avif +MIN_FILE_SIZE = 30000 + +def detect_compressible(fpath): + mimetype = subprocess.check_output(["file", "--mime-type", "-b", fpath]).strip().decode('utf-8') + + if mimetype in ('image/png', 'image/jpeg'): + return True + + if mimetype == 'image/webp': + fileout = subprocess.check_output(["file", fpath]).decode('utf-8') + if 'lossless' in fileout: + return True + + return False + +def compress(fpath): + rtpath = '/tmp/'+os.urandom(4).hex()+'.png' + subprocess.run(["magick", fpath, rtpath]) + subprocess.run(["avifenc", rtpath, "--yuv", "420", "--range", "l", "-q", "50", "-c", "svt", "-j", "1", "--speed", "0", "--ignore-exif", "-o", fpath]) + try: + os.remove(rtpath) + except: + pass + +def process_files_in_directory(directory): + compressible_files = [] + + for root, _, files in os.walk(directory): + for fi in files: + full_path = os.path.join(root, fi) + print(f"Checking file: {full_path}") + if os.path.getsize(full_path) < MIN_FILE_SIZE: + continue + if detect_compressible(full_path): + compressible_files.append(full_path) + + return compressible_files + +def main(directory, max_workers): + compressible_files = process_files_in_directory(directory) + + with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor: + futures = {executor.submit(compress, fpath): fpath for fpath in compressible_files} + + for future in concurrent.futures.as_completed(futures): + fpath = futures[future] + try: + future.result() + print(f"Successfully compressed: {fpath}") + except Exception as exc: + print(f"Compression failed for {fpath}: {exc}") + +if __name__ == "__main__": + main('../docs/', max_workers=32)