def extract_image_primary_secondary_colors(self, logo, white_threshold=225, mitigate=175): """ Identifies dominant colors First resizes the original image to improve performance, then discards transparent colors and white-ish colors, then calls the averaging method twice to evaluate both primary and secondary colors. :param logo: logo to process :param white_threshold: arbitrary value defining the maximum value a color can reach :param mitigate: arbitrary value defining the maximum value a band can reach :return colors: hex values of primary and secondary colors """ if not logo: return False, False # The "===" gives different base64 encoding a correct padding logo += b'===' if type(logo) == bytes else '===' try: # Catches exceptions caused by logo not being an image image = tools.image_fix_orientation(tools.base64_to_image(logo)) except Exception: return False, False base_w, base_h = image.size w = int(50 * base_w / base_h) h = 50 # Converts to RGBA (if already RGBA, this is a noop) image_converted = image.convert('RGBA') image_resized = image_converted.resize((w, h), resample=Image.NEAREST) colors = [] for color in image_resized.getcolors(w * h): if not(color[1][0] > white_threshold and color[1][1] > white_threshold and color[1][2] > white_threshold) and color[1][3] > 0: colors.append(color) if not colors: # May happen when the whole image is white return False, False primary, remaining = tools.average_dominant_color(colors, mitigate=mitigate) secondary = tools.average_dominant_color(remaining, mitigate=mitigate)[0] if remaining else primary # Lightness and saturation are calculated here. # - If both colors have a similar lightness, the most colorful becomes primary # - When the difference in lightness is too great, the brightest color becomes primary l_primary = tools.get_lightness(primary) l_secondary = tools.get_lightness(secondary) if (l_primary < 0.2 and l_secondary < 0.2) or (l_primary >= 0.2 and l_secondary >= 0.2): s_primary = tools.get_saturation(primary) s_secondary = tools.get_saturation(secondary) if s_primary < s_secondary: primary, secondary = secondary, primary elif l_secondary > l_primary: primary, secondary = secondary, primary return tools.rgb_to_hex(primary), tools.rgb_to_hex(secondary)
def _orientation_test(self, orientation, colors, size, expected): # Generate the test image based on orientation and order of colors. image = self._get_exif_colored_square(orientation, colors, size) # The image is read again now that it has orientation added. fixed_image = tools.image_fix_orientation(img_open(image)) # Ensure colors are in the right order (blue, yellow, green, pink). self._assertAlmostEqualSequence(fixed_image.getpixel((0, 0)), expected[0]) # top/left self._assertAlmostEqualSequence(fixed_image.getpixel((size - 1, 0)), expected[1]) # top/right self._assertAlmostEqualSequence(fixed_image.getpixel((0, size - 1)), expected[2]) # bottom/left self._assertAlmostEqualSequence( fixed_image.getpixel((size - 1, size - 1)), expected[3]) # bottom/right
def test_03_image_fix_orientation_exif(self): """Test that a jpg image with exif orientation tag gets rotated""" image = img_open(self.img_exif_jpg) self.assertEqual(image.size, (6, 3)) image = tools.image_fix_orientation(image) self.assertEqual(image.size, (3, 6))