[英]Fading between 2 colors in Curses (Python)
I'm trying to fade the background color of a Curses subwindow between 2 arbitrary RGB values passed to the setupColor() function in my code. 我试图在传递给我代码中的setupColor()函数的2个任意RGB值之间淡化Curses子窗口的背景色。
In some cases, the code behaves as expected and can satisfactorily fade between the colors, but most of the time it performs strangely. 在某些情况下,代码的行为符合预期,并且可以令人满意地在颜色之间淡入淡出,但是大多数情况下,它的执行效果很差。
setupColor((0,0,0),(0,255,55))
This will fade the subwindow between black and aqua, and works nicely. 这将淡化黑色和浅绿色之间的子窗口,并且效果很好。
However, if I try to fade between say, yellow and purple, like so: 但是,如果我尝试在黄色和紫色之间淡入淡出,就像这样:
setupColor((255,200,0),(200,0,200))
This will cycle between the 2 colors for the first few cycles, but seems to lose sync and eventually produces noticeably different colors then those passed to the function. 在最初的几个周期中,它将在两种颜色之间循环,但是似乎失去了同步性,最终产生的颜色与传递给函数的颜色明显不同。
As I based the original code on the Arduino LED Fade sketch, I searched to see if anyone had tried to do something similar with physical RGB LED's, which turned up this thread: c++ Fade between colors? 当我将原始代码建立在Arduino LED Fade草图的基础上时,我搜索是否有人试图对物理RGB LED进行类似的操作,从而发现了这个线程: c ++颜色之间的淡入淡出? (Arduino) . (Arduino) 。
The solution posted on the thread seems like it would be ideal for my needs, but I don't know C++ or JavaScript well enough to be able to follow, understand and port the code to Python. 线程上发布的解决方案似乎很适合我的需求,但是我对C ++或JavaScript的了解不深,无法跟踪,理解并将代码移植到Python。
Is it possible to adapt my code in order for the colors to fade properly, or is it worth scrapping it and starting over from scratch? 是否可以修改我的代码以使颜色正确地淡入淡出,还是值得对其进行剪贴并从头开始?
import curses,time
from curses import wrapper
def setupColor((red,green,blue),(red1,green1,blue1)):
global color1,color2 #initialise globals for use later on in the program.
global incrFloatRed,incrFloatGreen,incrFloatBlue
global minRed,minGreen,minBlue,maxRed,maxGreen,maxBlue
stepNumber = 60.00 # number of steps within each color transition.
color1 = (red,green,blue) # clone the input tuples for use later on...
color2 = (red1,green1,blue1)
differenceRed = red - red1 # subtract each channel of color1 from color2,
differenceGreen = green - green1 # this will return either a positive or negative float.
differenceBlue = blue - blue1
incrFloatRed = differenceRed / stepNumber # divide the difference between the 2 colors by the
incrFloatGreen = differenceGreen / stepNumber # step rate to obtain the color increments.
incrFloatBlue = differenceBlue / stepNumber
if red > red1: # if the red channel value of the 1st color is greater than
incrFloatRed = -incrFloatRed # that of the 2nd, invert the increment (to allow
maxRed = red # color subtraction), then set the top end of the range as
minRed = red1 # red 1st channel and the bottom as red 2nd channel.
else: # Else, perform the inverse operation.
incrFloatRed = abs(incrFloatRed)
maxRed = red1
minRed = red
if green > green1:
incrFloatGreen = -incrFloatGreen
maxGreen = green
minGreen = green1
elif green < green1:
incrFloatGreen = abs(incrFloatGreen)
maxGreen = green1
minGreen = green
if blue > blue1:
incrFloatBlue = -incrFloatBlue
maxBlue = blue
minBlue = blue1
else:
incrFloatBlue = abs(incrFloatBlue)
maxBlue = blue1
minBlue = blue
def main(stdscr):
global incrFloatRed,incrFloatGreen,incrFloatBlue
setupColor((0,0,0),(0,255,255))
red = color1[0] #red,green and blue are the variables used to control the fade.
green = color1[1] #To begin with, they is set to the colors contained in the first
blue = color1[2] #tuple that is passed to setupColor()
label = stdscr.subwin(10,50,1,4) # create a subwindow, draw a box around it, then add the string
label.box() # "Hello, World!" to the subwindow at position row 1, column 1.
label.addstr(1,1,"Hello, World!")
curses.curs_set(0) # Disable cursor visibility
while True:
red = red + incrFloatRed # color = colorValue + colorIncrement
green = green + incrFloatGreen
blue = blue + incrFloatBlue
if red <= minRed or red >= maxRed: # if color is less than the start of the color range or
incrFloatRed = -incrFloatRed # greater than end of the color range, invert the color increment
if green <= minGreen or green >= maxGreen:
incrFloatGreen = -incrFloatGreen
if blue <= minBlue or blue >= maxBlue:
incrFloatBlue = -incrFloatBlue
# curses.init_color takes a tuple of rgb values as it's argument,
cursesRed = int(int(red) / 0.255) # but uses funky 1000-point intensity values, instead of the usual
cursesGreen = int(int(green) / 0.255) # 255. e.g. rgb(1000,0,0) for full intensity red, instead of
cursesBlue = int(int(blue) / 0.255) # rgb(255,0,0).
# To convert between them, divide the integer of the color value float
# by 0.255, then obtain the integer of the resulting float.
if cursesRed >=1000: # Sometimes a color value is set to greater
cursesRed = 1000 # than 1k or less than 0. When a negative value or a value greater
if cursesGreen >=1000: # than 1k is passed to curses.init_color(), it will return ERR and
cursesGreen = 999 # Curses will crash.
if cursesBlue >=1000:
cursesBlue = 999
if cursesRed <=0:
cursesRed = 0
if cursesGreen <=0:
cursesGreen = 0
if cursesBlue <=0:
cursesBlue = 0
curses.init_color(1,cursesRed,cursesGreen,cursesBlue) # reassign Curses color (1) to the RGB1K color of the current step...
curses.init_pair(1,255,1) # then create a color pair with the dynamic value (1) as
# the BG color, and white (255) as the FG.
label.bkgd(curses.color_pair(1)) # set the background of the label subwindow to the current color pair..
label.refresh() # then refresh, so that we can see the change.
time.sleep(0.02) # Take a little snooze, then do it all again.
wrapper(main)
I figured this one out myself in the end, it was a relatively simple (but hacky and inelegant) fix. 最后,我自己弄清楚了这个问题,它是一个相对简单(但又笨拙又不雅致)的修复程序。 I printed the output of each of the color channels (variables red,green and blue in the code above) at this point in the program: 我在程序中的这一点上打印了每个颜色通道的输出(上面代码中的变量红色,绿色和蓝色):
if red <= minRed or red >= maxRed:
outFile.write("Red : " + str(int(red)) + "|Green : " + str(int(green)) + "|Blue : " + str(int(blue)) + "\n")
incrFloatRed = -incrFloatRed
This is the output for the first three cycles of the program: 这是程序的前三个循环的输出:
Red : 199|Green : 3 |Blue : 196
Red : 255|Green : 193|Blue : 0
Red : 199|Green : 9 |Blue : 196
Red : 255|Green : 186|Blue : 0
Red : 199|Green : 16 |Blue : 196
Red : 255|Green : 179|Blue : 0
As you can see, the green channel gradually drifts out of sync compared to the others, and the values for red and blue are slightly different to those passed to the setupColor() function. 如您所见,与其他通道相比,绿色通道逐渐不同步,并且红色和蓝色的值与传递给setupColor()函数的值略有不同。
The color value inaccuracy can be fixed by using if statements to directly set the values: 可以通过使用if语句直接设置值来解决颜色值不正确的问题:
while True:
red = red + incrFloatRed # color = colorValue + colorIncrement
green = green + incrFloatGreen
blue = blue + incrFloatBlue
##### Add the if statements after this ####
if red < minRed:
red = minRed
if red > maxRed:
red = maxRed
if blue < minBlue:
blue = minBlue
if blue > maxBlue:
blue = maxBlue
if green < minGreen:
green = minGreen
if green > maxGreen:
green = maxGreen
And the timing/synchronization issue can be fixed by using a single if statement to change the color fade direction. 通过使用单个if语句更改颜色淡入方向,可以解决定时/同步问题。 Instead of using a statement for each color like this... 而不是像这样对每种颜色使用声明...
if green <= minGreen or green >= maxGreen:
incrFloatGreen = -incrFloatGreen
...set all of them at once like this: ...像这样一次设置所有这些:
if green <= minGreen or green >=maxGreen:
incrFloatRed = -incrFloatRed
incrFloatGreen = -incrFloatGreen
incrFloatBlue = -incrFloatBlue
The eagle eyed will have probably spotted that if both maxGreen and minGreen are both set to 0 (eg, rgb(230,0,100) and rgb(100,0,200)), nothing will happen. 鹰眼可能已经发现,如果将maxGreen和minGreen都设置为0(例如rgb(230,0,100)和rgb(100,0,200)),则不会发生任何事情。 If you change green to a different color, it'll work fine. 如果将绿色更改为其他颜色,它将可以正常工作。
I doubt that it would be hard to add some logic to detect which color channels would work, but considering that this can be avoided simply by passing 1 instead of 0, I've not bothered. 我怀疑很难添加一些逻辑来检测哪些颜色通道有效,但是考虑到可以简单地通过传递1而不是0来避免这种情况,所以我没有打扰。
Another good move (efficiency wise) would be to dump all of the fade values into an array, and set the colors based on that, instead of going through the overhead of calculating the values each time. 另一个好的方法(从效率角度考虑)是将所有淡入淡出值都转储到一个数组中,并根据该值设置颜色,而不是每次都要花费计算值的开销。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.