Skip to content

Instantly share code, notes, and snippets.

@archydragon
Last active March 28, 2023 08:49
Show Gist options
  • Save archydragon/e9ad08d7a1f6d7d71f82708b0710a648 to your computer and use it in GitHub Desktop.
Save archydragon/e9ad08d7a1f6d7d71f82708b0710a648 to your computer and use it in GitHub Desktop.
A script to pack any file with zlib and embed them as C/C++ header file.
# A script to pack any file with zlib and embed them as C/C++ header file.
# Should work well with all Python versions starting from Python 3.6
# Basically you can achieve pretty much the same effect as this script with gzip | xxd wrapping on most of Unix systems.
import argparse
import os
from pathlib import Path
import re
import zlib
parser = argparse.ArgumentParser(
prog='zxd.py',
description='Pack any file with zlib and produce a C header')
parser.add_argument('input_file', type=Path)
parser.add_argument('-v', '--var', type=str, help='specify name of byte array variable (the derivative from input file name will be used otherwise)')
args = parser.parse_args()
########################################
# Load and compress.
file = open(args.input_file, "rb")
filebytes = bytearray(file.read())
compressed = zlib.compress(filebytes)
########################################
# Generate header file.
var_raw_name = args.var or args.input_file.name
# Sanitize variable name: only alphanumeric symbols are allowed to stay.
var_name = re.sub(r"[^a-z0-9]", "_", var_raw_name.lower())
print(f"unsigned char {var_name}[] = {{", end="")
# Pretty print hexadecimal sequence of bytes.
BYTES_PER_LINE = 16
cnt = 0
for b in compressed:
if cnt % BYTES_PER_LINE == 0:
print("\n ", end="")
end = ", "
if cnt == len(compressed) - 1:
end = "\n};\n"
print(f"0x{b:02x}", end=end)
cnt += 1
print(f"unsigned int {var_name}_len = {len(compressed)};")
# Just for the information.
print(f"// uncompressed len = {len(filebytes)}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment