summaryrefslogtreecommitdiff
path: root/color-converter.py
diff options
context:
space:
mode:
authorSimon <vesspa0330@gmail.com>2024-12-01 18:22:59 -0500
committerSimon <vesspa0330@gmail.com>2024-12-01 18:22:59 -0500
commit810552638d8466fb1f9166f2bec9057538815fc0 (patch)
tree7ddf4dc34cc3e65c9b1f0c75f40a041c1f3bbd14 /color-converter.py
parent2982d6516239fdac146613285858168ed6e109ce (diff)
CMY now fully supported, plus refactoring + organization
Diffstat (limited to 'color-converter.py')
-rw-r--r--color-converter.py234
1 files changed, 146 insertions, 88 deletions
diff --git a/color-converter.py b/color-converter.py
index 25ab90b..e933209 100644
--- a/color-converter.py
+++ b/color-converter.py
@@ -1,9 +1,9 @@
-# import sys
+import math
import argparse
# Order of types must match order of arguments defined
# (or else arg validation will no longer work properly)
-TYPES = ['hex', 'rgb', 'cmyk']
+TYPES = ['hex', 'rgb', 'cmy', 'cmyk']
# look into CMY, HSL, HSV
HEX_LETTERS = ['a', 'b', 'c', 'd', 'e', 'f']
@@ -13,11 +13,11 @@ def main():
# Set up arguments
parser = argparse.ArgumentParser()
- parser.add_argument('-hex', action='store_true', help='convert from hex (accepts hexadecimal input [ffffff] or string ["#ffffff"] (both are case insensitive)')
+ parser.add_argument('-hex', action='store_true', help='convert from hex (accepts hexadecimal input [ffffff] or string ["#ffffff"] (case insensitive, "#" is optional in string)')
parser.add_argument('-rgb', action='store_true', help='convert from RGB (accepts integer input [R G B], or string [\"rgb(R, G, B)\"] (case/whitespace insensitive)')
+ parser.add_argument('-cmy', action='store_true', help='convert from CMY (accepts integer input [C M Y], or string [\"cmy(C, M, Y)\"] (case/whitespace insensitive)')
parser.add_argument('-cmyk', action='store_true', help='convert from CMYK (accepts integer input [C M Y K], or string [\"cmyk(C, M, Y, K)\"] (case/whitespace insensitive)')
-
- parser.add_argument('color', nargs='*', help='accepts a color in Hex, RGB, CMYK, or HSL and performs format conversions (does not support CMYK profiles, conversions are uncalibrated)')
+ parser.add_argument('color', nargs='*', help='accepts a color in Hex, RGB, CMY, CMYK, or HSL and performs format conversions (does not support CMYK profiles, conversions are uncalibrated)')
args = parser.parse_args()
@@ -33,57 +33,47 @@ def main():
# HANDLE HEX INPUT
if args.hex :
- color = color[0].lower().replace(' ', '').strip('#')
- if not validateHex(color) :
- return
-
- convertFromHex(color)
+ handleHex(color)
# HANDLE RGB INPUT
if args.rgb :
-
- convertFromRGB(color)
+ handleRGB(color)
+
+ if args.cmy :
+ handleCMY(color)
# HANDLE CMYK INPUT
if args.cmyk :
- convertFromCMYK(color)
+ handleCMYK(color)
##
-# HEX CONVERSION SECTION
+# COLOR HANDLERS
##
# Takes in valid RGB code and converts it to the other formats
-def convertFromHex(hexCode) :
+def handleHex(color) :
+ # cleanse hex code
+ hexCode = color[0].lower().replace(' ', '').strip('#')
+ if not validateHex(hexCode) :
+ return
+
print('convert hex: ', hexCode, '\n')
-
- rgbValues = hexToRGB(hexCode)
- print("RGB: ", rgbValues)
+ rgbValues = hexToRGB(hexCode)
+ cmyValues = rgbToCMY(rgbValues)
cmykValues = rgbToCMYK(rgbValues)
- print("CMYK: ", cmykValues)
-
- # convertToHSL('hex', code)
-
-def rgbToHex(rgbValues) :
- hexValue = ''
-
- for rgbValue in rgbValues :
- hexValue += hex(int(rgbValue / 16))
- hexValue += hex(int(rgbValue % 16))
-
- return hexValue
-
+ print("RGB: ", rgbValues)
+ print("CMY: ", cmyValues)
+ print("CMYK: ", cmykValues)
- ##
-# RGB CONVERSION SECTION
-##
+ # convertToHSL('hex', code)
# Takes in valid RGB code and converts it to the other formats
-def convertFromRGB(color) :
+def handleRGB(color) :
# cleanse any non-numerical stuff
if len(color) == 1 :
color = color[0].lower().strip('rgb(').strip(')').replace(' ', '').split(',')
@@ -92,19 +82,66 @@ def convertFromRGB(color) :
if rgbValues is None :
return
- for i in range(len(rgbValues)) :
- rgbValues[i] = int(rgbValues[i])
+ # for i in range(len(rgbValues)) :
+ # rgbValues[i] = int(rgbValues[i])
print('convert RGB: ', rgbValues, '\n')
hexCode = rgbToHex(rgbValues)
+ cmyValues = rgbToCMY(rgbValues)
+ cmykValues = rgbToCMYK(rgbValues)
+
+ print('CMYK: ', cmykValues)
print('Hex: ', hexCode)
+ print('CMY: ', cmyValues)
+
+ # convertToHSL('rgb', rgbValues)
+def handleCMY(color) :
+ # cleanse any non-numerical stuff
+ if len(color) == 1 :
+ color = color[0].lower().strip('cmy(').strip(')').replace('%', '').replace(' ', '').split(',')
+ cmyValues = validateCMYK(color, False)
+ if cmyValues is None :
+ return
+
+ print('convert CMY: ', cmyValues, '\n')
+
+ rgbValues = cmyToRGB(cmyValues)
+ hexCode = rgbToHex(rgbValues)
cmykValues = rgbToCMYK(rgbValues)
+
+ print('Hex: ', hexCode)
+ print('RGB: ', rgbValues)
print('CMYK: ', cmykValues)
- # convertToHSL('rgb', rgbValues)
+def handleCMYK(color) :
+ # cleanse any non-numerical stuff
+ if len(color) == 1 :
+ color = color[0].lower().strip('cmyk(').strip(')').replace('%', '').replace(' ', '').split(',')
+ cmykValues = validateCMYK(color, True)
+ if cmykValues is None :
+ return
+
+ print('convert CMYK: ', cmykValues, '\n')
+
+ rgbValues = cmykToRGB(cmykValues)
+ hexCode = rgbToHex(rgbValues)
+ cmyValues = rgbToCMY(rgbValues)
+
+ print('Hex: ', hexCode)
+ print('RGB: ', rgbValues)
+ print('CMY: ', cmyValues)
+
+
+
+
+##
+# CONVERSION SECTION
+##
+
+# Takes in a string, returns a list of 3 integers
def hexToRGB(hexCode) :
rgbValues = []
@@ -119,65 +156,77 @@ def hexToRGB(hexCode) :
return rgbValues
-def cmykToRGB(cmykValues) :
- x = 1 - (cmykValues[3] / 100)
- red = 255 * (1 - (cmykValues[0] / 100)) * x
- green = 255 * (1 - (cmykValues[1] / 100)) * x
- blue = 255 * (1 - (cmykValues[2] / 100)) * x
-
- return [int(red), int(green), int(blue)]
-
-
-
-
-##
-# CMYK CONVERSION SECTION
-##
-
-def convertFromCMYK(color) :
- # cleanse any non-numerical stuff
- if len(color) == 1 :
- color = color[0].lower().strip('cmyk(').strip(')').replace('%', '').replace(' ', '').split(',')
+# Takes in a list of 3 integers, returns a string
+def rgbToHex(rgbValues) :
+ hexValue = ''
- cmykValues = validateCMYK(color)
- if cmykValues is None :
- return
+ for rgbValue in rgbValues :
+ hexValue += hex(rgbValue / 16)
+ hexValue += hex(rgbValue % 16)
+
+ return hexValue
- print('convert CMYK: ', cmykValues, '\n')
+# Takes in a list of 3 integers, returns a list of 3 floats (percentages)
+def rgbToCMY(rgbValues) :
+ # Normalize RGB values
+ normalRed = rgbValues[0] / 255
+ normalGreen = rgbValues[1] / 255
+ normalBlue = rgbValues[2] / 255
- rgbValues = cmykToRGB(cmykValues)
- print('RGB: ', rgbValues)
+ # Convert
+ cyan = 1 - normalRed
+ magenta = 1 - normalGreen
+ yellow = 1 - normalBlue
- hexCode = rgbToHex(rgbValues)
- print('Hex: ', hexCode)
+ return [round(cyan * 100, 2), round(magenta * 100, 2), round(yellow * 100, 2)]
+# Takes in a list of 3 integers, returns a list of 4 floats (percentages)
def rgbToCMYK(rgbValues) :
# Normalize RGB values
normalRed = rgbValues[0] / 255
normalGreen = rgbValues[1] / 255
normalBlue = rgbValues[2] / 255
- # Establish black
- black = 1 - max(normalRed, normalGreen, normalBlue)
- x = 1 - black
+ black = 1 - max(normalRed, normalGreen, normalBlue)
+ x = 1 - black
# Convert
- cyan = (1 - normalRed - black) / x
- magenta = (1 - normalGreen - black) / x
- yellow = (1 - normalBlue - black) / x
+ if x == 0 :
+ return [0, 0, 0, round(black * 100, 2)]
+ else :
+ cyan = (1 - normalRed - black) / x
+ magenta = (1 - normalGreen - black) / x
+ yellow = (1 - normalBlue - black) / x
return [round(cyan * 100, 2), round(magenta * 100, 2), round(yellow * 100, 2), round(black * 100, 2)]
+# Takes in a list of 3 floats, returns a list of 3 integers
+def cmyToRGB(cmyValues) :
+ red = (1 - (cmyValues[0] / 100)) * 255
+ green = (1 - (cmyValues[1] / 100)) * 255
+ blue = (1 - (cmyValues[2] / 100)) * 255
+
+ return [smartRound(red), smartRound(green), smartRound(blue)]
+
+# Takes in a list of 4 floats, returns a list of 3 integers
+def cmykToRGB(cmykValues) :
+ x = 1 - (cmykValues[3] / 100)
+ red = 255 * (1 - (cmykValues[0] / 100)) * x
+ green = 255 * (1 - (cmykValues[1] / 100)) * x
+ blue = 255 * (1 - (cmykValues[2] / 100)) * x
+
+ return [smartRound(red), smartRound(green), smartRound(blue)]
##
-# INPUT VALIDATION SECTION
+# VALIDATION SECTION
##
# Takes in a string. Returns True if valid Hex color code.
def validateHex(value) :
+
if len(value) != 6 :
- print('ERROR: Improper number of values for hex (should be 6 digits)')
+ print('ERROR: Improper format for hex code (see --help)')
return False
for i in range(len(value)):
@@ -212,28 +261,32 @@ def validateRGB(values) :
return intValues
# Takes in a list of strings. Returns same list as integers if valid CMYK values.
-def validateCMYK(values) :
- intValues = []
+def validateCMYK(values, include_K) :
+ floatValues = []
- if len(values) != 4 :
+ if (include_K and len(values) != 4) :
print('ERROR: Improper number of values for CMYK (should be 4)')
return
-
+
+ if (not include_K and len(values) != 3) :
+ print('ERROR: Improper number of values for CMY (should be 3)')
+ return
+
for value in values :
- if not value.isnumeric() :
- print('ERROR: Improper format for CMYK value(s). All values must be numeric and between 0-100(%)!')
+ if not value.replace('.', '').isnumeric() :
+ print('ERROR: Improper format for CMY(K) value(s). All values must be numeric and between 0.0-100.0(%)!')
return
- value = int(value)
- intValues.append(value)
+ value = float(value)
+ floatValues.append(value)
if (value < 0) or (value > 100) :
- print('ERROR: Each CMYK value must be between 0-100(%)')
+ print('ERROR: Each CMY(K) value must be between 0,0-100.0(%)')
return
- return intValues
+ return floatValues
# Takes in the program's arguments generated by argparse. Returns True if valid arguments
def validateArguments(args) :
- # First, check that only one input flag is being used
+ # ck that only one input flag is being used
flagsActive = 0
for flag in range(len(vars(args))-1) :
# this uses our TYPES list to key into the args dictionary and determine how many flags are True
@@ -243,8 +296,7 @@ def validateArguments(args) :
print('ERROR: Currently this tool only supports one input type at a time. Too many flags!')
return False
- # Second, check that there is a color code to convert
- if len(args.color) == 0 :
+ if (flagsActive == 0) or (len(args.color) == 0) :
print('ERROR: Must enter both an input flag and color code (did you forget to wrap color code in quotes?)\nFor more info, use the \'-h\' or \'--help\' flag.')
return False
@@ -258,6 +310,13 @@ def validateArguments(args) :
# GENERAL UTILITIES
##
+# Takes in a float, returns the nearest integer
+def smartRound(value) :
+ if (value % 1) > .50 :
+ return math.ceil(value)
+ else :
+ return math.floor(value)
+
# Takes in a decimal number and converts it to hexadecimal
def hex(number) :
number = int(number)
@@ -268,7 +327,6 @@ def hex(number) :
return str(number)
return HEX_LETTERS[number % 10]
-
-
+# init
if __name__ == '__main__' :
main()