Resize jpg and convert to bmp in RGB888 and RGB565 mode, using Python/GIMP

This video show how to resize jpg and convert to bmp in RGB888 and RGB565 mode, in two approach:
- Using Python code
- Using GIMP


Approach 1 using Python:

Tested on Python 3.13.0 with cv2 4.10.0 (OpenCV) installed, run on Python virtual environment/Windows 11. To create Python virtual environment in Windows 11, and install libraries, read https://coxxect.blogspot.com/2024/10/create-python-virtual-environment-in.html.

py_cv_batch_resize_RGB888.py

"""
Python/cv2 to resize all jpg in 'images' folder,
and save to 'resized_images_rgb888' folder
in RGB888 mode.

This code was generated by Copilot mainly.

Run on Windows 11/Python 3.13.0 in virtualenvironment, with OpebCV/cv2 installed. 

To create Python virtual environment in Windows 11, and libraries include OpenCV/cv2, ref:
https://coxxect.blogspot.com/2024/10/create-python-virtual-environment-in.html
"""

import os
import cv2

TARGET_WIDTH = 240
TARGET_HEIGHT = 240

def resize_and_save_as_bmp(input_folder, output_folder, size):
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)
    
    for filename in os.listdir(input_folder):
        if filename.endswith('.jpg'):
            img_path = os.path.join(input_folder, filename)
            img = cv2.imread(img_path)
            resized_img = cv2.resize(img, size)
            
            # Save as RGB888 BMP
            bmp_filename = os.path.splitext(filename)[0] + '_' +\
                           str(resized_img.shape[0]) + 'x' + str(resized_img.shape[1]) +\
                           '_rgb888.bmp'
            
            bmp_path = os.path.join(output_folder, bmp_filename)
            cv2.imwrite(bmp_path, resized_img)
            
            print(filename, "converted to", bmp_filename)

input_folder = 'images'
output_folder = 'resized_images_rgb888'
size = (TARGET_WIDTH, TARGET_HEIGHT)

resize_and_save_as_bmp(input_folder, output_folder, size)



py_cv_batch_resize_RGB565.py
"""
Python/cv2 to resize all jpg in 'images' folder,
and save to 'resized_images_rgb565' folder
in RGB565 mode.

To save a JPG image as a BMP file in RGB565 format, we need to do some additional
processing because OpenCV does not support the RGB565 format by default.

This code was generated by Copilot mainly.

Run on Windows 11/Python 3.13.0 in virtualenvironment, with OpebCV/cv2 installed. 

To create Python virtual environment in Windows 11, and libraries include OpenCV/cv2, ref:
https://coxxect.blogspot.com/2024/10/create-python-virtual-environment-in.html
"""

import os
import cv2
import numpy as np

TARGET_WIDTH = 240
TARGET_HEIGHT = 240

def convert_to_rgb565(image):
    b = (image[..., 0] >> 3).astype(np.uint16)
    g = (image[..., 1] >> 2).astype(np.uint16)
    r = (image[..., 2] >> 3).astype(np.uint16)
    rgb565 = (r << 11) | (g << 5) | b
    return rgb565

def save_rgb565_bmp(filename, image):
    height, width = image.shape[:2]
    with open(filename, 'wb') as f:
        # Write BMP header
        f.write(b'BM')
        file_size = 54 + width * height * 2
        f.write(file_size.to_bytes(4, 'little'))
        f.write((0).to_bytes(4, 'little'))  # Unused
        f.write((54).to_bytes(4, 'little'))  # Offset to image data
        f.write((40).to_bytes(4, 'little'))  # Header size
        f.write(width.to_bytes(4, 'little'))
        f.write(height.to_bytes(4, 'little'))
        f.write((1).to_bytes(2, 'little'))  # Planes
        f.write((16).to_bytes(2, 'little'))  # Bits per pixel
        f.write((3).to_bytes(4, 'little'))  # Compression (BI_BITFIELDS)
        f.write((width * height * 2).to_bytes(4, 'little'))  # Image size
        f.write((0).to_bytes(4, 'little'))  # X pixels per meter
        f.write((0).to_bytes(4, 'little'))  # Y pixels per meter
        f.write((0).to_bytes(4, 'little'))  # Total colors
        f.write((0).to_bytes(4, 'little'))  # Important colors
        f.write((0xF800).to_bytes(4, 'little'))  # Red mask
        f.write((0x07E0).to_bytes(4, 'little'))  # Green mask
        f.write((0x001F).to_bytes(4, 'little'))  # Blue mask
        # Write image data (flip vertically to correct upside down issue)
        flipped_image = np.flipud(image)
        f.write(flipped_image.tobytes())

def process_images(input_folder, output_folder, size):
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)
    
    for filename in os.listdir(input_folder):
        if filename.endswith('.jpg'):
            img_path = os.path.join(input_folder, filename)
            img = cv2.imread(img_path)
            resized_img = cv2.resize(img, size)
            rgb565_img = convert_to_rgb565(resized_img)
            
            bmp_filename = os.path.splitext(filename)[0] + '_' +\
                           str(resized_img.shape[0]) + 'x' + str(resized_img.shape[1]) +\
                           '_rgb565.bmp'
 
            bmp_path = os.path.join(output_folder, bmp_filename)
            save_rgb565_bmp(bmp_path, rgb565_img)
            
            print(filename, "converted to", bmp_filename)

input_folder = 'images'
output_folder = 'resized_images_rgb565'
size = (TARGET_WIDTH, TARGET_HEIGHT)

process_images(input_folder, output_folder, size)



Approach 2 using GIMP:

Open jpg image with GIMP.

To resize:
> Image > Scale Image...

Make sure it's in RGB mode:
> Image > Mode > RGB

Export bmp:
> File > Export As...
Enter the new name with .bmp extension. (with 'Select File Type (By Extension)' checked)
> Export

To export in RGB565 mode:
> Run-Length Encoded (Unchecked)
> Compatibility Optios > Do not write color space information (Checked)
> Advanced Options > 16 bits > R5 G6 B5 (Checked)
> Export

To export in RGB888 mode:
> Run-Length Encoded (Unchecked)
> Compatibility Optios > Do not write color space information (Checked)
> Advanced Options > 24 bits > R8 G8 B8 (Checked)
> Export











Comments

Popular posts from this blog

480x320 TFT/ILI9488 SPI wih EP32C3 (arduino-esp32) using Arduino_GFX Library

my dev.tools - FNIRSI 2C23T 3-in-1 Dual Channel Oscilloscope/Multimeter/Signal Generator