Attached scripts:
jpg_to_reshaped_png.py
from PIL import Image
import argparse
import os
''' Example usage:
For default output PNG path (rgb_x.png):
$ python jpg_to_reshaped_png.py path/to/input.tiff path/to/input.jpg
To specify output PNG path:
$ python jpg_to_reshaped_png.py path/to/input.tiff path/to/input.jpg --output_png_path path/to/output.png
'''
def reshape_jpg_to_match_tiff(tiff_path, jpg_path, output_png_path = "rgb_x.png"):
"""
Reshape a JPG file to match the dimensions of a TIFF file,
then convert and save as PNG.
Args:
tiff_path: Path to the TIFF file (source for dimensions)
jpg_path: Path to the JPG file to be reshaped
output_png_path: Path to save the output PNG file
"""
try:
# Validate file extensions
if not tiff_path.lower().endswith(('.tiff', '.tif')):
raise ValueError(f"TIFF file must have .tiff or .tif extension, got: {tiff_path}")
if not jpg_path.lower().endswith(('.jpg', '.jpeg')):
raise ValueError(f"JPG file must have .jpg or .jpeg extension, got: {jpg_path}")
# Validate files exist
if not os.path.isfile(tiff_path):
raise FileNotFoundError(f"TIFF file not found: {tiff_path}")
if not os.path.isfile(jpg_path):
raise FileNotFoundError(f"JPG file not found: {jpg_path}")
print(f"Loading TIFF: {tiff_path}")
tiff_image = Image.open(tiff_path)
tiff_width, tiff_height = tiff_image.size
print(f" TIFF dimensions: {tiff_width}x{tiff_height}")
print(f"\nLoading JPG: {jpg_path}")
jpg_image = Image.open(jpg_path)
jpg_width, jpg_height = jpg_image.size
print(f" JPG dimensions: {jpg_width}x{jpg_height}")
# Reshape (resize) JPG to match TIFF dimensions
print(f"\nResizing JPG to {tiff_width}x{tiff_height}...")
resized_jpg = jpg_image.resize((tiff_width, tiff_height), Image.Resampling.LANCZOS)
# Add alpha channel (convert to RGBA)
print(f"Adding alpha channel...")
if resized_jpg.mode != 'RGBA':
resized_jpg = resized_jpg.convert('RGBA')
# Save as PNG
print(f"Saving as PNG: {output_png_path}")
resized_jpg.save(output_png_path, format="PNG")
print(f"\nSuccess! PNG saved with dimensions: {tiff_width}x{tiff_height} (RGBA)\nat location: {os.path.abspath(output_png_path)}")
except FileNotFoundError as e:
print(f"Error: File not found - {e}")
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Reshape JPG to match TIFF dimensions and save as PNG")
parser.add_argument("tiff_path", help="Path to the TIFF file (source for dimensions)")
parser.add_argument("jpg_path", help="Path to the JPG file to be reshaped")
parser.add_argument("--output_png_path", default="rgb_x.png", help="Path to save the output PNG file (default: rgb_x.png)")
args = parser.parse_args()
reshape_jpg_to_match_tiff(args.tiff_path, args.jpg_path, args.output_png_path)
tiff_to_http_payload.py
import numpy as np
from PIL import Image
import argparse
import os
''' Example usage:
For default output path (depth_x.data):
$ python tiff_to_http_payload.py path/to/input.tiff
To specify output path and read centre depth value:
$ python tiff_to_http_payload.py path/to/input.tiff --output_path path/to/output.data --centre
'''
def convert_tiff_to_http_payload(tiff_file_path, output_filename = "depth_x.data"):
"""
Convert a TIFF depth map to HTTP payload (raw bytes) format.
The output is a binary file containing the depth values as raw bytes, with no header or metadata. The depth values are stored as 32-bit floats.
- HTTP payload written as raw bytes with no header
- Format: 32-bit float (converted from Float16 if needed)
- Layout: flat 1D array of length width * height
- Units: metres
"""
try:
print(f"Processing TIFF: {tiff_file_path}")
# 1. Load the TIFF file
tiff_image = Image.open(tiff_file_path)
width, height = tiff_image.size
# 2. Convert to numpy array
depth_array = np.array(tiff_image)
# 3. If TIFF contains Float16 data, convert to Float32
if depth_array.dtype == np.float16:
depth_float32 = depth_array.astype(np.float32)
print(f"Converted Float16 to Float32")
elif depth_array.dtype in [np.uint8, np.uint16, np.uint32]:
# If integer data, convert to float
depth_float32 = depth_array.astype(np.float32)
print(f"Converted {depth_array.dtype} to Float32")
else:
# Already float or other format
depth_float32 = depth_array.astype(np.float32)
# 4. Flatten to 1D array (width * height)
flat_payload = depth_float32.flatten()
# Verify dimensions
expected_size = width * height
assert len(flat_payload) == expected_size, \
f"Size mismatch: expected {expected_size}, got {len(flat_payload)}"
# 5. Save as raw bytes (no header)
raw_bytes = flat_payload.tobytes()
with open(output_filename, "wb") as f:
f.write(raw_bytes)
print(f" Saved {len(raw_bytes)} bytes ({width}x{height}) to '{output_filename}'")
print(f" Data range: {flat_payload.min():.6f} to {flat_payload.max():.6f}")
print(f" Units: metres (assumed)")
print(f" File saved to: {os.path.abspath(output_filename)}")
return raw_bytes, width, height
except Exception as e:
print(f"Error: {e}")
import traceback
traceback.print_exc()
return None, None, None
def read_centre_depth(tiff_file_path):
"""
Read the depth value at the centre of the TIFF image.
Useful for verifying if the depth value is as expected (in metres).
"""
try:
print(f"\nReading centre value from: {tiff_file_path}")
# 1. Load the TIFF file
tiff_image = Image.open(tiff_file_path)
width, height = tiff_image.size
# 2. Convert to numpy array
depth_array = np.array(tiff_image)
# 3. Convert to float32 if needed
depth_float32 = depth_array.astype(np.float32)
# 4. Calculate centre coordinates
centre_x = width // 2
centre_y = height // 2
# 5. Read centre pixel value
centre_value = depth_float32[centre_y, centre_x]
print(f" Image size: {width}x{height}")
print(f" centre position: ({centre_x}, {centre_y})")
print(f" centre depth value: {centre_value} metres")
print(f" Data range: {depth_float32.min():.6f} to {depth_float32.max():.6f} metres\n")
return centre_value
except Exception as e:
print(f"Error reading centre value: {e}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Convert TIFF depth map to HTTP payload (raw bytes)")
parser.add_argument("tiff_path", help="Path to the TIFF depth map file")
parser.add_argument("--output_path", default="depth_x.data", help="Path to save the output binary file (default: depth_x.data)")
parser.add_argument("--centre", action="store_true", help="Read and display centre depth value")
args = parser.parse_args()
# Read centre value to verify depth if requested
if args.centre:
read_centre_depth(args.tiff_path)
# Convert and save
convert_tiff_to_http_payload(args.tiff_path, args.output_path)