file2video / modules /img_gen.py
ar08's picture
Upload 17 files
8f0cb79 verified
import numpy as np
import cv2
import os
from tqdm import tqdm
import logging
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def decode_img(image_path, output_file_path):
"""
Decode an image using the size header to remove padding.
"""
if not os.path.isfile(image_path):
raise FileNotFoundError(f"The image at {image_path} does not exist.")
img = cv2.imread(image_path)
if img is None:
raise ValueError(f"Could not read the image at {image_path}.")
height, width, _ = img.shape
binary_str = []
# Extract binary string from image
for y in tqdm(range(height), desc="Decoding image"):
for x in range(width):
b, g, r = img[y, x]
r_bit = '0' if r == 0 else '1'
g_bit = '0' if g == 0 else '1'
b_bit = '0' if b == 0 else '1'
binary_str.extend([r_bit, g_bit, b_bit])
binary_str = ''.join(binary_str)
# Split into bytes
byte_array = bytearray()
for i in range(0, len(binary_str), 8):
byte_bits = binary_str[i:i+8]
byte = int(byte_bits, 2)
byte_array.append(byte)
# Extract size from the first 4 bytes (header)
original_size = int.from_bytes(byte_array[:4], byteorder='big')
decoded_data = byte_array[4:4+original_size] # Truncate to original size
# Write to file
with open(output_file_path, 'wb') as f:
f.write(decoded_data)
logging.info(f"INFO! Decoded data written to {output_file_path}")
def gen_image(file_path, output_path, width=1280, height=720):
"""
Convert a file to a binary string (with size header) and encode it into an image.
"""
if not os.path.isfile(file_path):
raise FileNotFoundError(f"The file at {file_path} does not exist.")
with open(file_path, 'rb') as f:
binary_data = f.read()
# Add 4-byte header containing the original data size (big-endian)
original_size = len(binary_data)
size_header = original_size.to_bytes(4, byteorder='big')
binary_data = size_header + binary_data # Prepend header to data
# Convert to binary string
binary_str = ''.join(format(byte, '08b') for byte in binary_data)
# Calculate required length and pad with zeros
required_length = width * height * 3
if len(binary_str) > required_length:
raise ValueError(f"Data too large for image: {len(binary_str)} > {required_length}")
binary_str = binary_str.ljust(required_length, '0')
# Create and populate image
image = np.zeros((height, width, 3), dtype=np.uint8)
for y in tqdm(range(height), desc="Generating image"):
for x in range(width):
index = (y * width + x) * 3
r = int(binary_str[index], 2) * 255
g = int(binary_str[index + 1], 2) * 255
b = int(binary_str[index + 2], 2) * 255
image[y, x] = [b, g, r]
cv2.imwrite(output_path, image)
logging.info(f"INFO:πŸ‘ Image generated and saved to {output_path}")
if __name__ == "__main__":
# Example usage
input_file = 'x.png'
output_image = 'output.png'
decoded_file = 'decoded.txt'
gen_image(input_file, output_image)
decode_img(output_image, decoded_file)