| 1 | # https://github.com/raplin/HexaWS2811/blob/master/gamma.py |
| 2 | # Lookup table generator |
| 3 | # |
| 4 | # Really it's correcting for the eye's luminance response, it's not actually gamma correction (it's misnamed!) |
| 5 | # |
| 6 | # We're generating a set of 256-entry lookup tables which you use to (separately) convert the 8-bit R, G and B components of your color |
| 7 | # into something you output, typically with an intelligent RGB LED such as a WS2812B; but a simple CPU-based PWM will give the same results (and benefit from this correction) |
| 8 | # |
| 9 | # We generate several sets (2,4,8...) of 256-entry tables so you can cycle through them, using a successive 8-bit lookup table each successive output frame. |
| 10 | # This is 'temporal dithering', which aims to give you better color resolution at the dark end of the scale. |
| 11 | # If you update at e.g. 100hz, try using two or three 'ditherBits' (i.e. 2^^2 or 2^^3=8 tables. The faster your update the more tables you can use |
| 12 | # and you get better color resolution. More than 5 ditherbits is probably excessive, even 2 will help somewhat. |
| 13 | # |
| 14 | # If you get objectionable flickering when displaying low-intensity pixels, you should either update your leds faster or reduce ditherBits |
| 15 | # |
| 16 | # |
| 17 | # |
| 18 | fout=open("gamma.h","wt") |
| 19 | |
| 20 | #adjust me! Each extra bit doubles the table size |
| 21 | ditherBits=1 |
| 22 | |
| 23 | ditherMSB=1<<(ditherBits-1) |
| 24 | |
| 25 | res="/* Dithered luminance correction table - autogenerated by gamma.py */\n#define DITHER_BITS %d\nconst prog_uchar PROGMEM gammaTable[]={" % ditherBits |
| 26 | |
| 27 | useRealLuminanceCalcuation=True # CIE 1931 formula |
| 28 | |
| 29 | finalAdjust=0 #set this to 1 if you want your values to start at one (1..255). This is a quirky request for FastLED users only |
| 30 | |
| 31 | for dither in range(1<<ditherBits): |
| 32 | out=[] |
| 33 | |
| 34 | #reverse the low order bits so the dithering is less flickery |
| 35 | ditherValue=0 |
| 36 | dread=1<<ditherBits |
| 37 | dout=1 |
| 38 | for d in range(ditherBits): |
| 39 | dread>>=1 |
| 40 | if dither & dread: |
| 41 | ditherValue|=dout |
| 42 | dout<<=1; |
| 43 | |
| 44 | ditherValue=(ditherValue<<(8-ditherBits)) |
| 45 | |
| 46 | for n in range(256): |
| 47 | if useRealLuminanceCalcuation: |
| 48 | # CIE 1931 |
| 49 | brightness=n/2.56 |
| 50 | if brightness > 8: |
| 51 | pwmValue= pow( ((brightness + 16) / 116) , 3 ) |
| 52 | else: |
| 53 | pwmValue = brightness / 903.3 |
| 54 | pwmValue*=256 |
| 55 | else: |
| 56 | #use simple power |
| 57 | pwmValue=pow(255,(n/256.0))-1 |
| 58 | pwmValue=int(pwmValue*256) |
| 59 | pwmValue+=ditherValue |
| 60 | pwmValue=min(255, (pwmValue>>8)+finalAdjust) |
| 61 | out.append( pwmValue ) |
| 62 | if dither: |
| 63 | res+="," |
| 64 | res+="\n\t"+(",".join([ "0x%x"%n for n in out])) |
| 65 | |
| 66 | res+="\n\t};\n" |
| 67 | |
| 68 | print >>fout,res |
| 69 | fout.close() |