Skip to content

Commit

Permalink
Implement background option to converter
Browse files Browse the repository at this point in the history
  • Loading branch information
CommanderRedYT committed Oct 3, 2024
1 parent 3e023e1 commit 463f7db
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 19 deletions.
48 changes: 33 additions & 15 deletions rgb565_converter/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@

import argparse
import os
from typing import Tuple

from PIL import Image
from enum import Enum

def hex2rgb(value: str) -> Tuple[int, int, int]:
# value is "#5c5c5c" for example
value = value.lstrip('#')
return tuple(int(value[i:i+2], 16) for i in (0, 2, 4))

class Mode(Enum):
CPP = ".cpp"
PNG = ".png"
Expand Down Expand Up @@ -52,7 +59,9 @@ def main():
"-s",
"--swap",
dest="swap",
help="Swap bytes for 16-bit words."
help="Swap bytes for 16-bit words.",
default=False,
type=bool
)
parser.add_argument(
"-n",
Expand All @@ -76,6 +85,13 @@ def main():
default=None,
type=str
)
parser.add_argument(
"--background",
dest="background",
help="Replace transparency with a background color.",
default=None,
type=str
)
args = parser.parse_args()

h_template = DEFAULT_H_TEMPLATE
Expand Down Expand Up @@ -126,28 +142,30 @@ def main():
if mode == Mode.PNG:
convert_rgb565_to_png(args.input_file, args.output_file, args.swap)
else:
convert_png_to_rgb565(args.input_file, args.output_file, args.swap, args.namespace, cpp_template, h_template)
convert_png_to_rgb565(args.input_file, args.output_file, args.swap, args.namespace, args.background, cpp_template, h_template)

def convert_png_to_rgb565(input_file: str, output_file: str, swap: bool, namespace: str, cpp_template: str = DEFAULT_CPP_TEMPLATE, h_template: str = DEFAULT_H_TEMPLATE):
def convert_png_to_rgb565(input_file: str, output_file: str, swap: bool, namespace: str, background: str | None, cpp_template: str = DEFAULT_CPP_TEMPLATE, h_template: str = DEFAULT_H_TEMPLATE):
name = os.path.basename(output_file).rsplit('.', 1)[0]
png = Image.open(input_file)
width, height = png.size

max_line_width = min(width, 64)

# iterate over the pixels
image = png.getdata()
image_content = ""
for i, pixel in enumerate(image):
r = (pixel[0] >> 3) & 0x1F
g = (pixel[1] >> 2) & 0x3F
b = (pixel[2] >> 3) & 0x1F
rgb = r << 11 | g << 5 | b

if swap:
rgb = ((rgb & 0xFF) << 8) | ((rgb & 0xFF00) >> 8)

image_content += f"0x{rgb:04X}" + (",\n " if (i % max_line_width == max_line_width-1) else ",")
for y in range(height):
for x in range(width):
pixel = png.getpixel((x, y))
if background is not None and pixel[3] == 0:
pixel = hex2rgb(background)
r = (pixel[0] >> 3) & 0x1F
g = (pixel[1] >> 2) & 0x3F
b = (pixel[2] >> 3) & 0x1F
rgb = r << 11 | g << 5 | b

if swap:
rgb = ((rgb & 0xFF) << 8) | ((rgb & 0xFF00) >> 8)

image_content += f"0x{rgb:04X}" + (",\n " if (x % max_line_width == max_line_width-1) else ",")

if image_content.endswith("\n "):
image_content = image_content[:-5]
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name='rgb565-converter',
version='1.3.0',
version='1.3.1',
description='Convert a file from png to rgb565 (cpp) and vice versa.',
url='https://github.com/CommanderRedYT/rgb565-converter',
author='CommanderRedYT',
Expand All @@ -13,7 +13,7 @@
'rgb565-converter=rgb565_converter.converter:main',
],
},
python_requires='>=3.6',
python_requires='>=3.7',
long_description=open('README.md').read(),
long_description_content_type='text/markdown',
install_requires=[
Expand Down
Binary file added tests/back.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
50 changes: 48 additions & 2 deletions tests/test_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@

TEST_DIRECTORY='tests'
TEST_INPUT_FILE=f'{TEST_DIRECTORY}/input_info.png'

TEST_OUTPUT_CPP_FILE=f'{TEST_DIRECTORY}/output_info.cpp'
TEST_OUTPUT_H_FILE=f'{TEST_DIRECTORY}/output_info.h'
TEST_OUTPUT_PNG_FILE=f'{TEST_DIRECTORY}/output_info_double.png'

TEST_INPUT_GREY_PNG_FILE=f'{TEST_DIRECTORY}/back.png'
TEST_OUTPUT_GREY_CPP_FILE=f'{TEST_DIRECTORY}/output_grey.cpp'
TEST_OUTPUT_GREY_H_FILE=f'{TEST_DIRECTORY}/output_grey.h'
TEST_OUTPUT_GREY_PNG_FILE=f'{TEST_DIRECTORY}/output_grey_double.png'
TEST_COMPARE_GREY_PNG_FILE=f'{TEST_DIRECTORY}/test_grey_back.png'

TEST_CUSTOM_CPP_TEMPLATE=f'{TEST_DIRECTORY}/custom_cpp_template.txt'
TEST_CUSTOM_H_TEMPLATE=f'{TEST_DIRECTORY}/custom_h_template.txt'

Expand All @@ -30,12 +37,22 @@ def tearDownClass(cls):
if os.path.exists(TEST_OUTPUT_PNG_FILE):
os.remove(TEST_OUTPUT_PNG_FILE)

if os.path.exists(TEST_OUTPUT_GREY_CPP_FILE):
os.remove(TEST_OUTPUT_GREY_CPP_FILE)

if os.path.exists(TEST_OUTPUT_GREY_H_FILE):
os.remove(TEST_OUTPUT_GREY_H_FILE)

if os.path.exists(TEST_OUTPUT_GREY_PNG_FILE):
os.remove(TEST_OUTPUT_GREY_PNG_FILE)

def test_converter(self):
args = {
'input_file': TEST_INPUT_FILE,
'output_file': TEST_OUTPUT_CPP_FILE,
'swap': False,
'namespace': 'foobar'
'namespace': 'foobar',
'background': None,
}

convert_png_to_rgb565(**args)
Expand Down Expand Up @@ -104,7 +121,8 @@ def test_converter_custom_template(self):
'swap': False,
'namespace': 'foobar',
'cpp_template': cpp_template,
'h_template': h_template
'h_template': h_template,
'background': None,
}

convert_png_to_rgb565(**args)
Expand Down Expand Up @@ -154,5 +172,33 @@ def test_converter_custom_template(self):
with open(TEST_INPUT_FILE, 'rb') as f1, open(TEST_OUTPUT_PNG_FILE, 'rb') as f2:
self.assertEqual(f1.read(), f2.read())

def test_converter_with_grey_mode(self):
args = {
'input_file': TEST_INPUT_GREY_PNG_FILE,
'output_file': TEST_OUTPUT_GREY_CPP_FILE,
'swap': False,
'namespace': 'foobar',
'background': '#5c5c5c'
}

convert_png_to_rgb565(**args)

# check if files exist
self.assertTrue(os.path.exists(TEST_OUTPUT_GREY_CPP_FILE))
self.assertTrue(os.path.exists(TEST_OUTPUT_GREY_H_FILE))

# convert back to png
args = {
'input_file': TEST_OUTPUT_GREY_CPP_FILE,
'output_file': TEST_OUTPUT_GREY_PNG_FILE,
'swap': False
}

convert_rgb565_to_png(**args)

# check if both png files are binary equal
with open(TEST_COMPARE_GREY_PNG_FILE, 'rb') as f1, open(TEST_OUTPUT_GREY_PNG_FILE, 'rb') as f2:
self.assertEqual(f1.read(), f2.read())

if __name__ == '__main__':
unittest.main()
Binary file added tests/test_grey_back.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 463f7db

Please sign in to comment.