<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Muhammad Usman</title>
    <description>The latest articles on DEV Community by Muhammad Usman (@usmaanshafiq).</description>
    <link>https://dev.to/usmaanshafiq</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1108162%2F901743f7-5f95-46b3-b0ac-b119611f00a2.png</url>
      <title>DEV Community: Muhammad Usman</title>
      <link>https://dev.to/usmaanshafiq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/usmaanshafiq"/>
    <language>en</language>
    <item>
      <title>Image Processing Script: PNG Converter and Resizer</title>
      <dc:creator>Muhammad Usman</dc:creator>
      <pubDate>Thu, 13 Feb 2025 10:00:36 +0000</pubDate>
      <link>https://dev.to/usmaanshafiq/image-processing-script-png-converter-and-resizer-59pk</link>
      <guid>https://dev.to/usmaanshafiq/image-processing-script-png-converter-and-resizer-59pk</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Image Processing Script:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This Python script allows you to automatically process images by ensuring transparency, cropping unused spaces, resizing to fit a 2:1 canvas, and cleaning up the filenames. Here's what it does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transparency Handling:&lt;/strong&gt; Ensures that images are in PNG format with transparency. If the image has a white background, it's replaced with transparency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Space Removal:&lt;/strong&gt; Removes spaces from image filenames and replaces them with underscores (_).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Filename Shortening:&lt;/strong&gt; If a filename is too long, it truncates it to a maximum length (30 characters).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cropping:&lt;/strong&gt; The script crops any extra unused space around the image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resizing:&lt;/strong&gt; Resizes the image to fit a 2:1 canvas (e.g., 400x200), ensuring the aspect ratio is preserved and the image is centered on the canvas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Logs Skipped Images:&lt;/strong&gt; If any image is skipped due to being unsupported, empty, or fully transparent, it logs the skipped filenames.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Dependencies:
&lt;/h2&gt;

&lt;p&gt;Pillow (Python Imaging Library fork)&lt;br&gt;
&lt;strong&gt;You can install it with:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;pip install Pillow&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Use:
&lt;/h2&gt;

&lt;p&gt;Place your images in a folder (e.g., &lt;strong&gt;images&lt;/strong&gt;).&lt;br&gt;
Run the script, and it will automatically process and save the images in a folder (e.g., &lt;strong&gt;edited_images&lt;/strong&gt;).&lt;br&gt;
The processed images will be resized, centered, and saved in PNG format.&lt;br&gt;
Note:&lt;br&gt;
The script ensures that only valid images are processed and any issues with unsupported formats or transparency are logged in the console.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Here the script started:&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from PIL import Image
import os

def ensure_transparency(image):
    # Convert the image to RGBA (if it's not already in that mode)
    if image.mode != 'RGBA':
        image = image.convert('RGBA')

    # If the image doesn't have a transparent background, add one
    if image.getchannel('A').getextrema()[0] != 0:
        # Replace the white or non-transparent background with transparency
        image = image.convert('RGBA')
        image_data = image.getdata()
        new_data = []
        for item in image_data:
            # Change all white (also shades of whites) pixels to transparent
            if item[0] in range(240, 256) and item[1] in range(240, 256) and item[2] in range(240, 256):
                new_data.append((255, 255, 255, 0))  # Replace white with transparency
            else:
                new_data.append(item)
        image.putdata(new_data)
    return image

def process_image(input_path, output_path, target_width, target_height):
    # Open the image
    try:
        image = Image.open(input_path)
    except IOError:
        print(f"Error opening {input_path}, skipping...")
        return None

    # Ensure the image is PNG and has transparency
    image = ensure_transparency(image)

    # Get the bounding box of the non-empty region (crops the unused space)
    bbox = image.getbbox()

    if bbox is None:
        print(f"Image {input_path} has no content or is fully transparent, skipping...")
        return None

    # Crop the image using the bounding box
    cropped_image = image.crop(bbox)

    # Get the dimensions of the cropped image
    img_width, img_height = cropped_image.size
    aspect_ratio = target_width / target_height

    # Calculate new dimensions to fit the image within the 2:1 aspect ratio
    if img_width / img_height &amp;gt; aspect_ratio:
        new_width = target_width
        new_height = int(new_width * (img_height / img_width))  # Scale based on width
    else:
        new_height = target_height
        new_width = int(new_height * (img_width / img_height))  # Scale based on height

    # Resize the image to fit into the 2:1 canvas without cutting
    resized_image = cropped_image.resize((new_width, new_height), Image.Resampling.LANCZOS)

    # Create a new blank canvas with the target size
    final_image = Image.new("RGBA", (target_width, target_height), (255, 255, 255, 0))  # Transparent background

    # Calculate the position to paste the resized image in the center
    x_offset = (target_width - new_width) // 2
    y_offset = (target_height - new_height) // 2

    # Paste the resized image onto the canvas
    final_image.paste(resized_image, (x_offset, y_offset))

    # Save the final image as PNG
    final_image.save(output_path, 'PNG')

def shorten_filename(filename, max_length=30):
    """
    Shortens the filename if it's too long, keeping the extension intact.
    """
    name, ext = os.path.splitext(filename)

    # If the filename is longer than the maximum length, truncate it
    if len(name) &amp;gt; max_length:
        name = name[:max_length]

    return f"{name}{ext}"

def batch_process_images(input_directory, output_directory, target_width, target_height):
    # Create the "edited_images" directory if it doesn't exist
    if not os.path.exists(output_directory):
        os.makedirs(output_directory)

    # Track if any image is missed
    missed_images = []

    # Loop through all images in the input directory
    for filename in os.listdir(input_directory):
        if filename.lower().endswith(('.jpg', '.jpeg', '.png')):  # Check image file types
            image_path = os.path.join(input_directory, filename)
            print(f"Processing: {filename}")

            # Remove spaces and make the filename more descriptive
            new_filename = filename.replace(" ", "_")  # Replace spaces with underscores
            new_filename = shorten_filename(new_filename, max_length=30)  # Shorten the filename if necessary

            # Define the output path for each processed image
            output_path = os.path.join(output_directory, new_filename)

            # Process the image (ensure transparency, crop, and resize)
            result = process_image(image_path, output_path, target_width, target_height)

            # If the result is None, the image was skipped
            if result is None:
                missed_images.append(filename)
        else:
            # If the image file doesn't have a valid extension, skip it and log the name
            missed_images.append(filename)

    # Print the missed images if any
    if missed_images:
        print("\nThe following images were skipped:")
        for img in missed_images:
            print(f" - {img}")

# Define the input and output directories
input_directory = './images'  # Input folder where unedited images are stored
output_directory = './edited_images'  # Output folder where edited images will be saved

# Call the function to process images
batch_process_images(input_directory, output_directory, 500, 250)  # 2:1 ratio (400x200)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>python</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
