commit b1296472306f7d61a354dda9a6c23c52206edabf Author: Chris Sewell Date: Wed Jun 4 17:25:32 2025 -0400 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4dfd701 --- /dev/null +++ b/.gitignore @@ -0,0 +1,52 @@ +# Ignore contents of input, logo, and output folders but keep the folders +input/* +logo/* +output/* + +# Keep the folder structure by not ignoring .gitkeep files +!input/.gitkeep +!logo/.gitkeep +!output/.gitkeep + +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# IDEs +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Temporary files +*.tmp +*.temp \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e7b4fee --- /dev/null +++ b/README.md @@ -0,0 +1,109 @@ +# TeamsFlipper - Image Processing Tool + +TeamsFlipper is a Python script that processes images for video conferencing backgrounds by cropping, resizing, and adding logo overlays. + +## Features + +- **Batch Processing**: Automatically processes all `.jpg` and `.png` files in the input folder +- **Smart Cropping**: Crops images to 16:9 aspect ratio while preserving the center content +- **Standard Sizing**: Resizes all images to 2560x1440 pixels for consistent output +- **Logo Overlay**: Adds PNG logo from the logo directory to the upper-right corner +- **High Quality Output**: Saves processed images as high-quality JPEGs + +## Installation + +1. Clone this repository or download the files +2. Install required dependencies: + ```bash + pip install -r requirements.txt + ``` + +## Project Structure + +``` +TeamsFlipper/ +├── flip_image.py # Main processing script +├── input/ # Place your source images here +├── logo/ # Place your logo PNG file here +│ └── cornerlogo.png # Example logo file +├── output/ # Processed images appear here +├── README.md # This file +├── requirements.txt # Python dependencies +└── .gitignore # Git ignore rules +``` + +## Usage + +1. **Prepare your files:** + - Place your source images (`.jpg` or `.png`) in the `input/` folder + - Ensure your logo PNG file is in the `logo/` folder + +2. **Run the script:** + ```bash + python3 flip_image.py + ``` + +3. **Get your results:** + - Processed images will be saved in the `output/` folder + - Output files are named `{original_filename}_logo.jpg` + +## Processing Pipeline + +The script performs the following operations on each image: + +1. **Crop to 16:9**: Centers and crops the image to 16:9 aspect ratio +2. **Resize**: Scales the image to exactly 2560x1440 pixels +3. **Logo Overlay**: Places the logo (480px tall) in the exact upper-right corner +4. **Save**: Outputs as high-quality JPEG (95% quality) + +## Logo Requirements + +- **Format**: PNG with transparency support +- **Sizing**: Logo will be automatically resized to 480 pixels tall while maintaining aspect ratio +- **Position**: Logo is placed in the exact upper-right corner with no padding + +## Supported Input Formats + +- JPEG (`.jpg`, `.jpeg`) +- PNG (`.png`) +- Case-insensitive file extensions + +## Output Format + +- All processed images are saved as JPEG files +- Quality: 95% (high quality) +- Naming: `{original_filename}_logo.jpg` +- Size: 2560x1440 pixels (16:9 aspect ratio) + +## Examples + +### Input +- `my_photo.jpg` (any size/aspect ratio) +- Logo: `logo/company_logo.png` + +### Output +- `output/my_photo_logo.jpg` (2560x1440 with logo overlay) + +## Requirements + +- Python 3.6+ +- Pillow (PIL) library for image processing + +## Troubleshooting + +### No images found +- Ensure images are placed in the `input/` folder +- Check that file extensions are `.jpg`, `.jpeg`, or `.png` + +### Logo not appearing +- Verify logo file exists in the `logo/` folder +- Ensure logo is in PNG format +- Check that logo file is not corrupted + +### Processing errors +- Ensure input images are valid image files +- Check that you have write permissions for the `output/` folder + +## License + +This project is open source and available under standard terms. \ No newline at end of file diff --git a/flip_image.py b/flip_image.py new file mode 100644 index 0000000..a698d96 --- /dev/null +++ b/flip_image.py @@ -0,0 +1,141 @@ +import os +import glob +from PIL import Image, ImageDraw + +def crop_to_16_9(image): + """Crop image to 16:9 aspect ratio, centering the crop.""" + width, height = image.size + target_ratio = 16 / 9 + current_ratio = width / height + + if current_ratio > target_ratio: + # Image is too wide, crop width + new_width = int(height * target_ratio) + left = (width - new_width) // 2 + right = left + new_width + cropped = image.crop((left, 0, right, height)) + else: + # Image is too tall, crop height + new_height = int(width / target_ratio) + top = (height - new_height) // 2 + bottom = top + new_height + cropped = image.crop((0, top, width, bottom)) + + return cropped + +def resize_to_target(image, target_width=2560, target_height=1440): + """Resize image to target dimensions.""" + return image.resize((target_width, target_height), Image.Resampling.LANCZOS) + +def overlay_logo(image, logo_path): + """Overlay logo on the upper-right corner of the image.""" + if not os.path.exists(logo_path): + print(f"Warning: Logo file {logo_path} not found. Skipping logo overlay.") + return image + + try: + logo = Image.open(logo_path).convert("RGBA") + + # Resize logo to be exactly 480 pixels tall while maintaining aspect ratio + logo_height = 480 + logo_ratio = logo.size[0] / logo.size[1] # width / height + logo_width = int(logo_height * logo_ratio) + logo = logo.resize((logo_width, logo_height), Image.Resampling.LANCZOS) + + # Get image dimensions + img_width, img_height = image.size + + # Position logo in exact upper-right corner with no padding + x = img_width - logo_width + y = 0 + + # Create a copy of the image to work with + result = image.copy().convert("RGBA") + + # Paste logo with transparency + result.paste(logo, (x, y), logo) + + # Convert back to RGB + return result.convert("RGB") + + except Exception as e: + print(f"Error overlaying logo: {e}") + return image + +def process_images(): + """Process all .jpg and .png images in the input folder.""" + input_folder = "input" + output_folder = "output" + logo_folder = "logo" + + # Create output folder if it doesn't exist + os.makedirs(output_folder, exist_ok=True) + + # Find logo file in logo directory + logo_files = glob.glob(os.path.join(logo_folder, "*.png")) + if not logo_files: + # Fallback to cornerlogo.png in root directory + if os.path.exists("cornerlogo.png"): + logo_path = "cornerlogo.png" + print("Using cornerlogo.png from root directory") + else: + logo_path = None + print("Warning: No logo file found") + else: + logo_path = logo_files[0] # Use first PNG found in logo directory + print(f"Using logo: {logo_path}") + + # Find all image files in input folder + image_extensions = ["*.jpg", "*.jpeg", "*.png", "*.JPG", "*.JPEG", "*.PNG"] + image_files = [] + + for extension in image_extensions: + image_files.extend(glob.glob(os.path.join(input_folder, extension))) + + if not image_files: + print(f"No image files found in {input_folder} folder.") + return + + print(f"Found {len(image_files)} image(s) to process:") + + for image_path in image_files: + try: + print(f"Processing: {os.path.basename(image_path)}") + + # Open and process the image + with Image.open(image_path) as img: + # Convert to RGB if necessary + if img.mode != 'RGB': + img = img.convert('RGB') + + # Step 1: Crop to 16:9 aspect ratio + cropped_img = crop_to_16_9(img) + + # Step 2: Resize to 2560x1440 + resized_img = resize_to_target(cropped_img) + + # Step 3: Overlay logo + if logo_path: + logo_img = overlay_logo(resized_img, logo_path) + else: + logo_img = resized_img + + # Step 4: Save as JPG in output folder + base_name = os.path.splitext(os.path.basename(image_path))[0] + output_path = os.path.join(output_folder, f"{base_name}_logo.jpg") + + logo_img.save(output_path, "JPEG", quality=95) + print(f"Saved: {output_path}") + + except Exception as e: + print(f"Error processing {image_path}: {e}") + +def main(): + """Main function to process images.""" + print("TeamsFlipper - Image Processing Tool") + print("=" * 40) + process_images() + print("Processing complete!") + +if __name__ == '__main__': + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..81fc143 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +Pillow>=9.0.0 \ No newline at end of file