Skip to content

Commit 29d847d

Browse files
author
Lorena Mesa
committed
Add resize logic for identicon
1 parent e95e686 commit 29d847d

File tree

3 files changed

+50
-17
lines changed

3 files changed

+50
-17
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Users often work collaboratively in digital environments where a profile picture
1717

1818
## Identicon Requirements
1919
1. The identicon's should be symmetrical meaning the left horizontal half is equal to the right horizontal half.
20-
2. The identicon is 5X5 pixels, following the standard specified for [GitHub identicons](https://github.blog/2013-08-14-identicons/)
20+
2. The identicon is 5X5 pixels, following the standard specified for [GitHub identicons](https://github.blog/2013-08-14-identicons/), so we'll generate square identicons only with a default of 250X250 pixels
2121
3. Identicon's should use accessible colors as specified by [W3](https://www.w3.org/WAI/WCAG21/Techniques/general/G207)
2222

2323
## TODO:

src/main.py

+32-15
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,12 @@ def _generate_image_fill_color(self, md5hash_str: str) -> tuple:
5353
"""
5454
return tuple(int(md5hash_str[i:i+2], base=16) for i in range(0, 2*3, 2))
5555

56-
def draw_image(self, filename: str=None) -> Image:
56+
def draw_image(self, filename: str=None, dimensions: int=0) -> Image:
5757
"""
5858
Function that generates a grid - a list of lists - indicating which pixels are to be filled
5959
and uses the md5hash_str to generate an image fill color. Function creates a PIL Image, drawing it,
60-
and saving it.
60+
and saving it. By default a 250 pixel by 250 pixel identicon is created, if upon executing the code
61+
a dimensions parameter is passed in the image will be resized.
6162
6263
:param filename: filename of PIL png image generated
6364
:return: None
@@ -66,6 +67,7 @@ def draw_image(self, filename: str=None) -> Image:
6667
fill_color: tuple = self._generate_image_fill_color(self.md5hash_str)
6768
grid: list[list] = self._build_grid()
6869

70+
# Default to a 250X250 pixel image
6971
SQUARE: int = 50
7072
size: tuple = (5 * 50, 5 * 50)
7173
bg_color: tuple = (214,214,214)
@@ -88,40 +90,55 @@ def draw_image(self, filename: str=None) -> Image:
8890

8991
if not filename:
9092
filename: str = 'example'
91-
92-
# TODO: Confirm overwrite file is one of same name exists
93+
94+
if dimensions:
95+
wpercent: float = (dimensions / float(image.size[0]))
96+
hsize: int = int((float(image.size[1]) * float(wpercent)))
97+
image = image.resize((dimensions, hsize), Image.Resampling.LANCZOS)
98+
9399
image.save(f'{filename}.png')
94100

101+
95102
if __name__ == '__main__':
96103
parser = argparse.ArgumentParser(
97104
description="Generate an identicon with Python 3.",
98105
usage="""Example: python main.py -s='931D387731bBbC988B31220' or add the optional -o flag to specify name of identicon
99-
image generated such as python main.py -s='931D387731bBbC988B31220' -o='my_identicon.jpg'."""
106+
image generated such as python main.py -s='931D387731bBbC988B31220' -o='my_identicon.jpg'." Additionally can specify the
107+
square dimensions in pixels for the identicon such as python main.py -s='931D387731bBbC988B31220' -d 150."""
100108
)
101-
102109
def len_gt_zero(input_str: str):
103110
if len(input_str) > 0:
104111
return input_str
105-
raise argparse.ArgumentTypeError("Input string must have length greater than 0 in order to generate an identicon.")
106-
112+
else:
113+
raise argparse.ArgumentTypeError("Outfile filename must have length greater than 0 in order to generate an identicon.")
114+
def dimensions_gt_zero(input_dimensions: str):
115+
if not input_dimensions.isdigit():
116+
raise argparse.ArgumentTypeError("Input square dimension (same height and width) must be a legal int value.")
117+
elif int(input_dimensions) >= 1:
118+
return int(input_dimensions)
119+
else:
120+
raise argparse.ArgumentTypeError("Input square dimension (same height and width) must be greater than 1.")
107121
parser.add_argument(
108122
"-s",
109123
"--string",
110-
default="",
111124
type=str,
112125
required=True,
113-
help="An input string used to generate an identicon.",
126+
help="An input string used to generate a squaer identicon.",
114127
)
115128
parser.add_argument(
116129
"-o",
117130
"--output",
118-
default="",
119-
type=str,
120-
required=False,
121-
help="Name for output identicon image generated.",
131+
type=len_gt_zero,
132+
help="Name for output square identicon image generated.",
133+
)
134+
parser.add_argument(
135+
"-d",
136+
"--dimensions",
137+
type=dimensions_gt_zero,
138+
help="Optional dimensionals parameter for outputing square identicon image generated."
122139
)
123140

124141
args = parser.parse_args()
125142

126143
identicon = Identicon(input_str=args.string)
127-
identicon.draw_image(filename=args.output)
144+
identicon.draw_image(filename=args.output, dimensions=args.dimensions)

test/sample_cases_test.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ def test_ui_fails_to_create_identicon_with_input_string_missing(self):
1919
with self.assertRaises(subprocess.CalledProcessError) as context:
2020
subprocess.check_output(f"python3 {PROJECT_ROOT}/src/main.py", shell=True, stderr=subprocess.STDOUT).strip()
2121
self.assertIn("main.py: error: the following arguments are required: -s/--string", context.exception.output.decode('utf-8'))
22+
23+
def test_ui_fails_to_create_identicon_with_dimensions_lt_1(self):
24+
with self.assertRaises(subprocess.CalledProcessError) as context:
25+
subprocess.check_output(f"python3 {PROJECT_ROOT}/src/main.py -d 0", shell=True, stderr=subprocess.STDOUT).strip()
26+
self.assertIn("main.py: error: argument -d/--dimensions: Input square dimension (same height and width) must be greater than 1.", context.exception.output.decode('utf-8'))
2227

2328

2429
class TestHappyPath(unittest.TestCase):
@@ -71,7 +76,18 @@ def test_does_not_create_same_identicon_for_different_input_strings(self):
7176
remove(f"{PROJECT_ROOT}/john.png")
7277
remove(f"{PROJECT_ROOT}/jane.png")
7378

79+
def test_successfully_resizes_identicon_gt_250_when_dimensions_provided(self):
80+
identicon_john = Identicon("john")
81+
identicon_john.draw_image(filename="john", dimensions=300)
82+
83+
# Assertions
84+
generated_john = Image.open(f"{PROJECT_ROOT}/john.png", mode="r")
85+
self.assertIsInstance(generated_john, PngImagePlugin.PngImageFile)
86+
self.assertEqual(generated_john.size, (300, 300))
87+
88+
# Cleanup
89+
remove(f"{PROJECT_ROOT}/john.png")
7490

7591

76-
if __name__ == '__maipython -m unittest__':
92+
if __name__ == "__main__":
7793
unittest.main()

0 commit comments

Comments
 (0)