0

My program receives two numbers from the user as follows...

first_color = int(input("Input first color: "), 16)
second_color = int(input("Input second color: "), 16)
generate = int(input("Enter the number of colors I will make between the two input numbers"))

For example, if the user enters 0x030303, 0x454545 and 3; there should be five outputs (all in hexadecimal); the two input numbers and the three numbers evenly spread out between the two input numbers.

To be clear about the numbers my program aims to make between the two input numbers; I'll use a similar example with decimal numbers...

User enters 10, 2 and 3. The program outputs 2, 4, 6, 8, 10 (the original two input numbers and the three numbers evenly spread out between the two input numbers).

I'm having a lot of trouble trying to generate the hexadecimal numbers evenly spread out between the two input numbers. I don't want to import anything to achieve this. I want to split the smaller hexadecimal number (from user) into the RGB components and then increment into the successive hexadecimal numbers.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Mezza
  • 31
  • 4

2 Answers2

1

If what you are concerned with are colors, you do not want numbers evenly spread out between the inputs. You want to convert the colors to coordinates, find evenly spread out points between them and then turn those back to strings.

Code

# Do not convert input to integers yet
first_color = input("Input first color: ")
second_color = input("Input second color: ")
generate = int(input("Enter the number of colors: "))

def get_colors_from_input(color1, color2, n):
    # Extract color coordinates
    r1, g1, b1 = [int(x, 16)
                  for x in [color1[i:i+2] for i in range(2, 8, 2)]]
    r2, g2, b2 = [int(x, 16)
                  for x in [color2[i:i+2] for i in range(2, 8, 2)]]

    # Build the coordinate-wise distribution
    # We could have used `range`, but using floats prevents some rounding errors
    dec_cols = zip(
        [int(r1 + x * (r2 - r1) / (n + 1)) for x in range(n + 2)],
        [int(g1 + x * (g2 - g1) / (n + 1)) for x in range(n + 2)],
        [int(b1 + x * (b2 - b1) / (n + 1)) for x in range(n + 2)])

    # Format back the coordinates to strings.
    # We used a small hack with `str.replace` to make sure coordinates have two digits
    return ['0x' + ''.join(hex(x).replace('x', '')[-2:]
                             for x in color) for color in dec_cols]

print(*get_colors_from_input(first_color, second_color, generate))

Example

Input first color: 0x000000
Input second color: 0xffffff
Enter the number of colors: 3
0x000000 0x3f3f3f 0x7e7e7e 0xbdbdbd 0xffffff

Validate input format with re

You might want to add so guard clause to make sure the inputs are properly formatted. Despite the fact you prefer to use no import in your code, let me recommend using the re module like so.

import re

...

# Extract color coordinates
color_coords1 = re.fullmatch(r'0x([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})', color1)
color_coords2 = re.fullmatch(r'0x([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})', color2)

# If there is no match, some color was malformatted
if not color_coords1 or not color_coords2:
    raise ValueError('Wrong color format')

r1, g1, b1 = [int(x, 16) for x in color_coords1.groups()]
r2, g2, b2 = [int(x, 16) for x in color_coords2.groups()]
Olivier Melançon
  • 21,584
  • 4
  • 41
  • 73
0

Applying this code to yours: https://pyfiddle.io/fiddle/2bda2f7c-7bf1-4fe2-86e0-9492546e5add/

def get_rgb(int_value):
    blue  = int_value & 255
    green = (int_value >> 8) & 255
    red   = (int_value >> 16) & 255
    return red, green, blue

def get_int(rgb):
    red = rgb[0]
    green = rgb[1]
    blue = rgb[2]
    int_value = (red<<16) + (green<<8) + blue
    return int_value

def get_step(first_rgb, rgb_steps, step):
    current_rgb = [
        int(first_rgb[c] + ((step+1) * rgb_steps[c]))
        for c in range(3)
    ]
    return get_int(current_rgb)

first_color = int(input("Input first color: "), 16)
second_color = int(input("Input second color: "), 16)
generate = int(input("Enter the number of colors I will make between the two input numbers"))

first_rgb = get_rgb(first_color)
second_rgb = get_rgb(second_color)

rgb_steps = [(second_rgb[i] - first_rgb[i]) / (generate + 1)
    for i in range(3)]

gradient_color_list = [first_color] \
    + list(map(
        lambda step: get_step(first_rgb, rgb_steps, step),
        range(generate)
    )) + [second_color]


print("\n".join([ hex(v) for v in gradient_color_list ]))

With values 0x450031, 0x9000ff, 5, the output is:

0x450031
0x510053
0x5d0075
0x690097
0x7500b9
0x8100db
0x9000ff
raul.vila
  • 1,984
  • 1
  • 11
  • 24