Rory Gross Razor-G
Rory Gross Razor-G

Reputation: 1

Colour Gradients for QR Codes in Excel using Python

I am new to Python, so please be patient with me.

I am working on a small project to create QR Codes using MS Excel's built-in Python mode, and apply customisations to them.

For this question, I am looking for an easy method to create a class "Colour" that will store the hex value for a given colour. I then want to be able to create 2 objects of this class and use them to fill a square image (such as a QR Code) with a gradient going from colour1 to colour2.

I already have a code that works with the primary colours, but I am hoping to be able to use the corporate colours of several different companies we are affiliated with, hence the ask. I wasn't sure if using the hex value or RGB value for the colours would be easier for this kind of challenge.

Here's the code I have that works with basic RGB (apologies if this seems very basic):

# Creates the image
qr = qrcode.QRCode()
qr.add_data(xl("B2")) # References the weblink in cell B2
qr.make()
img = qr.make_image(fill_color="black",back_color="white").convert("RGB")

# Creates a gradient overlay
width, height = img.size
gradient = Image.new("RGB", (width, height), color=0)

# Defines the gradient
for y in range(height):
`    `for x in range(width):
`        `r = int(255 * (1 - y / height)) # Red decreases from top to bottom
`        `b = int(255 * (y / height)) # Blue increases from top to bottom
`        `g = xl("C2") # References the value in cell C2
`        `gradient.putpixel((x, y), (r, g, b))

# Applies the gradient to the Image
pixels = img.load()
gradient_pixels = gradient.load()

# Replaces black pixels with gradient overlay
for y in range(height):
`    `for x in range(width):
`        `if pixels[x,y] == (0,0,0): # pixel is black (QR Code foreground)
`            `pixels[x,y] = gradient_pixels[x,y]

# Shows the image with gradient overlay
img.show()

Upvotes: 0

Views: 46

Answers (1)

Matheus Lemos
Matheus Lemos

Reputation: 1

Unless you need a more complex gradient pattern, I believe you can use the built-in gradiants (with an 'a').

Take this gradiant from their github repo for example. It has a vertical gradient with black more intense at the top and blue more intense at the bottom, similar to the one you were already implementing. If you want that exact same result, you can use this code based on their example:

import qrcode
from qrcode.image.styledpil import StyledPilImage
from qrcode.image.styles.moduledrawers.pil import RoundedModuleDrawer
from qrcode.image.styles.colormasks import VerticalGradiantColorMask

qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_H)
qr.add_data('Some data')

img_1 = qr.make_image(image_factory=StyledPilImage, module_drawer=RoundedModuleDrawer())
img_2 = qr.make_image(image_factory=StyledPilImage, color_mask=VerticalGradiantColorMask())
img_3 = qr.make_image(image_factory=StyledPilImage, embeded_image_path="/path/to/image.png")

According to their implementation in colormasks.py, their default top color is black (0, 0, 0) and their default bottom color is blue (0, 0, 255). Since the constructor __init__ expects a tuple of three values that represent the desired color, if you wanted to change that to be like your implementation with blue starting at the top and red starting at the bottom, you could call the gradient/gradiant passing their RGB values as tuples like so:

img_2 = qr.make_image(image_factory=StyledPilImage, color_mask=VerticalGradiantColorMask(top_color=(0, 0, 255), bottom_color=(255, 0, 0)))

That should do the job as long as you don't need too many colors on your gradients.

Upvotes: 0

Related Questions