问题
I want to make a color picker, which recolors a png texture while preserving transparency in python3.
I only want the brighter parts of the image to be recolored, but also keep the gradient.
The only option the I could think of was to adjust the color channel intensity, however I did not find anything like that in the PIL docs.
How do I change the color channel intensity? My PNG texture is loaded in ARGB mode and can be found >>here<<.
Original Image:
回答1:
I dreamt up an approach for this:
- Extract and save the Alpha/transparency channel
- Convert the image, minus Alpha, to HSV colourspace and save the V (lightness)
- Get a new Hue (and possibly Saturation) from your Colour Picker
- Synthesize a new Hue channel, and a new Saturation channel of 255 (fully saturated)
- Merge the new Hue, Saturation and original V (lightness) to a 3 channel HSV image
- Convert the HSV image back to RGB space
- Merge the original Alpha channel back in
That looks like this:
#!/usr/local/bin/python3
import numpy as np
from PIL import Image
# Open and ensure it is RGB, not palettised
img = Image.open("keyshape.png").convert('RGBA')
# Save the Alpha channel to re-apply at the end
A = img.getchannel('A')
# Convert to HSV and save the V (Lightness) channel
V = img.convert('RGB').convert('HSV').getchannel('V')
# Synthesize new Hue and Saturation channels using values from colour picker
colpickerH, colpickerS = 10, 255
newH=Image.new('L',img.size,(colpickerH))
newS=Image.new('L',img.size,(colpickerS))
# Recombine original V channel plus 2 synthetic ones to a 3 channel HSV image
HSV = Image.merge('HSV', (newH, newS, V))
# Add original Alpha layer back in
R,G,B = HSV.convert('RGB').split()
RGBA = Image.merge('RGBA',(R,G,B,A))
RGBA.save('result.png')
With colpickerH=10
you get this (try putting Hue=10
here):
With colpickerH=120
you get this (try putting Hue=120
here):
Just for fun, you can do it exactly the same without writing any Python, just at the command line with ImageMagick which is installed on most Linux distros and available for macOS and Windows:
# Split into Hue, Saturation, Lightness and Alpha channels
convert keyshape.png -colorspace hsl -separate ch-%d.png
# Make a new solid Hue channel filled with 40, a new solid Saturation channel filled with 255, take the original V channel (and darken it a little), convert from HSL to RGB, copy the Alpha channel from the original image
convert -size 73x320 xc:gray40 xc:white \( ch-2.png -evaluate multiply 0.5 \) -set colorspace HSL -combine -colorspace RGB ch-3.png -compose copyalpha -composite result.png
Yes, I could do it as a one-liner, but it would be harder to read.
来源:https://stackoverflow.com/questions/51520369/pil-change-color-channel-intensity