2023-10-21 17:51:38 +00:00
|
|
|
from jsonschema import validate
|
|
|
|
from json import dumps, loads
|
2023-11-21 18:28:49 +00:00
|
|
|
from common import convert_color, closest_color, create_colored_image, remove_from_list, closest_color_euclidean, closest_color_weighted_euclidean, euclidean_distance, weighted_euclidean_distance
|
2023-10-21 17:51:38 +00:00
|
|
|
|
|
|
|
class PalleteSchema :
|
|
|
|
colors = None
|
|
|
|
schema = {
|
|
|
|
"type" : "array",
|
|
|
|
"items" : {
|
|
|
|
"type" : "object",
|
|
|
|
"properties" : {
|
|
|
|
"name" : { "type" : "string" },
|
|
|
|
"color" : {
|
|
|
|
"type" : "array",
|
|
|
|
"items" : { "type" : "number" }
|
2023-10-24 02:05:58 +00:00
|
|
|
},
|
|
|
|
"space" : { "type" : "string" }
|
2023-10-21 17:51:38 +00:00
|
|
|
},
|
2023-10-24 02:05:58 +00:00
|
|
|
"required" : [ "name", "color", "space" ]
|
2023-10-21 17:51:38 +00:00
|
|
|
}
|
|
|
|
}
|
2023-10-24 02:05:58 +00:00
|
|
|
def __init__ (self, file = None, obj = None):
|
|
|
|
if file is not None and obj is None:
|
2023-10-21 17:51:38 +00:00
|
|
|
self.parse_file(file)
|
2023-10-24 20:14:56 +00:00
|
|
|
elif file is not None and obj is not None :
|
2023-10-24 02:05:58 +00:00
|
|
|
self.write(file, obj)
|
2023-10-24 20:14:56 +00:00
|
|
|
else :
|
|
|
|
print('Not sure what you\'re trying to do here')
|
2023-10-21 17:51:38 +00:00
|
|
|
|
|
|
|
def parse_file (self, file) :
|
|
|
|
with open(file) as f :
|
|
|
|
self.parse(f.read())
|
|
|
|
print(f'Parsed pallete file {file}')
|
|
|
|
|
|
|
|
def parse (self, jsonstr) :
|
|
|
|
obj = loads(jsonstr)
|
|
|
|
validate( instance = obj, schema = self.schema)
|
2023-10-24 02:05:58 +00:00
|
|
|
self.colors = obj
|
|
|
|
|
|
|
|
def write(self, filepath, obj) :
|
|
|
|
validate( instance = obj, schema = self.schema)
|
|
|
|
jsonstr = dumps(obj, indent = 4)
|
|
|
|
with open(filepath, 'w') as outfile :
|
2023-11-21 18:28:49 +00:00
|
|
|
outfile.write(jsonstr)
|
|
|
|
|
2023-11-25 14:40:13 +00:00
|
|
|
def closest (self, comparison, space = 'BGR', colors = None) :
|
|
|
|
c = colors if colors is not None else self.colors
|
|
|
|
colors = normalize_colors(space, c)
|
|
|
|
if space == 'RGB' or space == 'BGR' :
|
|
|
|
closest, dist = closest_color_weighted_euclidean(colors, comparison, space)
|
|
|
|
else :
|
|
|
|
closest, dist = closest_color_euclidean(colors, comparison)
|
|
|
|
print(f'Color [{space}] {comparison} closest to {closest} [{dist}]')
|
|
|
|
return closest
|
|
|
|
|
|
|
|
def closest_exclusive (self, comparisons, space = 'BGR', colors = None) :
|
|
|
|
c = colors if colors is not None else self.colors
|
|
|
|
colors = normalize_colors(space, c)
|
|
|
|
exclusive = []
|
|
|
|
for comparison in comparisons :
|
|
|
|
if space == 'RGB' or space == 'BGR' :
|
|
|
|
closest, dist = closest_color_weighted_euclidean(colors, comparison, space)
|
|
|
|
else :
|
|
|
|
closest, dist = closest_color_euclidean(colors, comparision)
|
|
|
|
colors = remove_from_list(colors, closest)
|
|
|
|
exclusive.append(closest)
|
|
|
|
return exclusive
|
|
|
|
|
|
|
|
def normalize_colors (self, space = 'BGR', colors = None) :
|
|
|
|
normalized = []
|
|
|
|
c = colors if colors is not None else self.colors
|
|
|
|
for color in c :
|
|
|
|
normalized.append(convert_color(color['color'], color['space'], space))
|
|
|
|
return normalized
|
2023-11-21 18:28:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
|