Last active
January 22, 2016 09:26
-
-
Save kasperkamperman/b0d0d8058246d674dd01 to your computer and use it in GitHub Desktop.
Test with sqrt blending color values using FastLED functions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// sqrt blending test | |
// http://scottsievert.com/blog/2015/04/24/image-sqrt/ | |
// https://plus.google.com/+KasperKamperman/posts/jkACVWijSDN | |
// algorithms sqrt32 from: http://stackoverflow.com/questions/1100090/looking-for-an-efficient-integer-square-root-algorithm-for-arm-thumb2 | |
#include "FastLED.h" | |
// How many leds in your strip? | |
#define NUM_LEDS 128 | |
#define DATA_PIN 11 | |
#define CLOCK_PIN 14 | |
CRGB red = CRGB(255,0,0); | |
CRGB green = CRGB(0,255,0); | |
CRGB leds[NUM_LEDS]; | |
unsigned long t1; // for measuring purposes | |
unsigned long t2; // for measuring purposes | |
unsigned long t3 = 0; // for measuring purposes | |
void setup() { | |
Serial.begin(57600); | |
LEDS.addLeds<APA102, DATA_PIN, CLOCK_PIN, BGR, DATA_RATE_MHZ(16)>(leds, NUM_LEDS); | |
LEDS.setBrightness(255); | |
LEDS.setDither(0); | |
delay(2000); | |
} | |
void loop() { | |
// setTime(); | |
// for(int i = 0; i < 256; i++) { | |
// leds[i] = blend(red, green, i); | |
// } | |
// printTime(); | |
Serial.println("sqrt16"); | |
setTime(); | |
for(int i = 0; i < 64; i++) { | |
leds[i] = sqrtBlend(red, green, i*4); | |
} | |
printTime(); | |
Serial.println("sqrt32"); | |
setTime(); | |
for(int i = 64; i < 128; i++) { | |
leds[i] = sqrt32Blend(red, green, (i-64)*2); | |
} | |
printTime(); | |
LEDS.show(); | |
delay(5000); | |
} | |
CRGB sqrtBlend(CRGB a, CRGB b, uint8_t t) { | |
CRGB rgb; | |
rgb.r = sqrt16(scale16by8( a.r * a.r, (255 - t) ) + scale16by8( b.r * b.r, t )); | |
rgb.g = sqrt16(scale16by8( a.g * a.g, (255 - t) ) + scale16by8( b.g * b.g, t )); | |
rgb.b = sqrt16(scale16by8( a.b * a.b, (255 - t) ) + scale16by8( b.b * b.b, t )); | |
return rgb; | |
} | |
CRGB sqrt32Blend(CRGB a, CRGB b, uint8_t t) { | |
CRGB rgb; | |
uint16_t r1 = a.r <<8; | |
uint16_t r2 = b.r <<8; | |
uint16_t g1 = a.g <<8; | |
uint16_t g2 = b.g <<8; | |
uint16_t b1 = a.b <<8; | |
uint16_t b2 = b.b <<8; | |
// typecast to uint64_t | |
// https://forum.pjrc.com/threads/27622-try-to-multiply-two-uint32_t-into-a-uint64_t-seems-not-to-work | |
uint16_t ro = sqrt32(scale32by8( (uint64_t) r1 * r1, (255 - t) ) + scale32by8( (uint64_t) r2 * r2, t )); | |
uint16_t go = sqrt32(scale32by8( (uint64_t) g1 * g1, (255 - t) ) + scale32by8( (uint64_t) g2 * g2, t )); | |
uint16_t bo = sqrt32(scale32by8( (uint64_t) b1 * b1, (255 - t) ) + scale32by8( (uint64_t) b2 * b2, t )); | |
rgb.r = ro >> 8; | |
rgb.g = go >> 8; | |
rgb.b = bo >> 8; | |
return rgb; | |
} | |
// typecast | |
// https://forum.pjrc.com/threads/27622-try-to-multiply-two-uint32_t-into-a-uint64_t-seems-not-to-work | |
uint32_t scale32by8( uint32_t i, uint8_t scale ) { | |
return (i * (uint64_t) scale) / 256; | |
} | |
/* | |
* Tested different algorithms from: | |
* http://stackoverflow.com/questions/1100090/looking-for-an-efficient-integer-square-root-algorithm-for-arm-thumb2 | |
* This one (from Craig McQueen) was the fastest (tested in a blend from red to green with a Teensy 3.0) | |
* rounded version doesn't cost really much more: 464us vs 446us (not rounded version) | |
* fastled sqrt16 takes 652 | |
* so we stick with the rounded version | |
* Fractional parts of the answer are discarded. | |
*/ | |
uint16_t sqrt32(uint32_t a_nInput) | |
{ | |
uint32_t op = a_nInput; | |
uint32_t res = 0; | |
uint32_t one = 1uL << 30; // The second-to-top bit is set: use 1u << 14 for uint16_t type; use 1uL<<30 for uint32_t type | |
// "one" starts at the highest power of four <= than the argument. | |
while (one > op) { | |
one >>= 2; | |
} | |
while (one != 0) { | |
if (op >= res + one) { | |
op = op - (res + one); | |
res = res + 2 * one; | |
} | |
res >>= 1; | |
one >>= 2; | |
} | |
/* Do arithmetic rounding to nearest integer */ | |
if (op > res) { | |
res++; | |
} | |
return res; | |
} | |
void setTime() | |
{ t1 = micros(); | |
} | |
void printTime() | |
{ | |
t2 = micros()-t1; | |
if(t2>t3) t3 = t2; | |
Serial.print(F("time used: ")); | |
Serial.print(t3); | |
Serial.print(" "); | |
Serial.print(t2); | |
Serial.println(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment