#1. GIF contrast adjustment |
Published: 2025-06-09 [Mon] 11:27, by |
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ gifedit.py - Adjust contrast of a GIF by modifying its color palette. Shouldn't touch anything but palette. Usage:./gifedit.py input.gif contrast_factor - input.gif: Path to the input GIF file. - contrast_factor: Floating point number where 1.0 is identity, >1.0 increases contrast, and <1.0 decreases contrast. Output: A new GIF file with the contrast-adjusted palette, named after the input file with '_contrast_{factor}.gif' appended. """ import sys import os import struct def adjust_contrast(rgb, factor): """ Apply contrast adjustment to a given RGB value. :param rgb: The RGB value to adjust (as a tuple). :param factor: Contrast factor (1.0 = no change, >1.0 increase, <1.0 decrease). :return: Adjusted RGB value. """ r, g, b = rgb r = int(((r / 255.0 - 0.5) * factor + 0.5) * 255.0) g = int(((g / 255.0 - 0.5) * factor + 0.5) * 255.0) b = int(((b / 255.0 - 0.5) * factor + 0.5) * 255.0) return (max(0, min(255, r)), max(0, min(255, g)), max(0, min(255, b))) def main(): if len(sys.argv)!= 3: print("Usage:./gifedit.py input.gif contrast_factor") sys.exit(1) input_file = sys.argv[1] try: contrast_factor = float(sys.argv[2]) except ValueError: print("Error: Contrast factor must be a floating point number.") sys.exit(1) if contrast_factor <= 0: print("Warning: Contrast factor should be greater than zero. Proceeding with value:", contrast_factor) # Load the GIF try: with open(input_file, 'rb') as f_in: gif_data = f_in.read() # Verify the GIF magic bytes if gif_data[:6] not in [b'GIF87a', b'GIF89a']: print("Error: Not a GIF file.") sys.exit(1) # Get the original file name without extension filename, file_extension = os.path.splitext(input_file) output_file = f"{filename}_contrast_{contrast_factor:.2f}{file_extension}" # Determine the GCT size gct_size_byte = gif_data[10] # 10th byte indicates GCT size (2^(N+1)) gct_size = 2 ** ((gct_size_byte & 0x07) + 1) # Extract the lower 3 bits gct_start = 13 # GCT starts after the 12th byte (header + gct_size_byte) gct_end = gct_start + gct_size * 3 # Extract and adjust the Global Color Table gct = gif_data[gct_start:gct_end] adjusted_gct = bytearray() for i in range(0, len(gct), 3): rgb = struct.unpack('<BBB', gct[i:i+3]) adjusted_rgb = adjust_contrast(rgb, contrast_factor) adjusted_gct.extend(adjusted_rgb) # Replace the original GCT with the adjusted one gif_data = gif_data[:gct_start] + adjusted_gct + gif_data[gct_end:] # Save the modified GIF data with open(output_file, 'wb') as f_out: f_out.write(gif_data) print(f"Output saved to: {output_file}") except IOError as e: print(f"Error opening or processing the file: {e}") if __name__ == "__main__": main() |