Gamma correction for LED diode

Zápisník experimentátora

I found an interesting article on how to set the gamma correction for LED diodes. The article publishes a known table of 256 values that allow to adjust the brightness of the LED for human eyes. I myself have used the table several times (LED strip dimmer, 1W LED dimmer), but I did not even know the author who created the table. Only when I found this page, I understood what formula was used.

There is a source code for the Processing, that will create this table. I tried to rewrite the code for Arduino and this is the result. I wrote two programs (sketches). The first is an exact copy of the original code. The second code creates the same table in 16-bit resolution.

Code 1

The exact transcription of the original source code. The result is a table of 8-bit values.

float    gamma   = 2.8; // Correction factor
uint16_t max_in  = 255; // Top end of INPUT range
uint16_t max_out = 255; // Top end of OUTPUT range

char output[10];

void setup() {
  Serial.begin(9600);
  Serial.print("const uint8_t PROGMEM gamma[] = {");
  for (int i = 0; i <= max_in; i++) {
    if (i > 0) Serial.print(',');
    if ((i % 16) == 0) Serial.print("\n  ");
    sprintf(output, "%3u", (uint16_t)(pow((float)i / (float)max_in, gamma) * max_out + 0.5));
    Serial.print(output);
  }
  Serial.println("");
  Serial.println("  };");
}

void loop() {
}

Result

const uint8_t PROGMEM gamma[] = {
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,
    1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,
    2,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  5,  5,  5,
    5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  9,  9,  9, 10,
   10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
   17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
   25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
   37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
   51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
   69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
   90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
  115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
  144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
  177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
  215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255
  };

Code 2

This program creates a table in 16-bit resolution. I'm planning to improve my code using this table. See the details in the article​ 16-bit PWM using timer1.

float    gamma   = 2.8; // Correction factor
uint16_t max_in  = 255; // Top end of INPUT range
uint16_t max_out = 65535; // Top end of OUTPUT range

char output[10];

void setup() {
  Serial.begin(9600);
  Serial.print("const uint16_t PROGMEM gamma[] = {");
  for (int i = 0; i <= max_in; i++) {
    if (i > 0) Serial.print(',');
    if ((i % 16) == 0) Serial.print("\n  ");
    sprintf(output, "%5u", (uint16_t)(pow((float)i / (float)max_in, gamma) * max_out + 0.5));
    Serial.print(output);
  }
  Serial.println("");
  Serial.println("  };");
}

void loop() {
}

Result

const uint16_t PROGMEM gamma[] = {
      0,    0,    0,    0,    1,    1,    2,    3,    4,    6,    8,   10,   13,   16,   19,   24,
     28,   33,   39,   46,   53,   60,   69,   78,   88,   98,  110,  122,  135,  149,  164,  179,
    196,  214,  232,  252,  273,  295,  317,  341,  366,  393,  420,  449,  478,  510,  542,  575,
    610,  647,  684,  723,  764,  806,  849,  894,  940,  988, 1037, 1088, 1140, 1194, 1250, 1307,
   1366, 1427, 1489, 1553, 1619, 1686, 1756, 1827, 1900, 1975, 2051, 2130, 2210, 2293, 2377, 2463,
   2552, 2642, 2734, 2829, 2925, 3024, 3124, 3227, 3332, 3439, 3548, 3660, 3774, 3890, 4008, 4128,
   4251, 4376, 4504, 4634, 4766, 4901, 5038, 5177, 5319, 5464, 5611, 5760, 5912, 6067, 6224, 6384,
   6546, 6711, 6879, 7049, 7222, 7397, 7576, 7757, 7941, 8128, 8317, 8509, 8704, 8902, 9103, 9307,
   9514, 9723, 9936,10151,10370,10591,10816,11043,11274,11507,11744,11984,12227,12473,12722,12975,
  13230,13489,13751,14017,14285,14557,14833,15111,15393,15678,15967,16259,16554,16853,17155,17461,
  17770,18083,18399,18719,19042,19369,19700,20034,20372,20713,21058,21407,21759,22115,22475,22838,
  23206,23577,23952,24330,24713,25099,25489,25884,26282,26683,27089,27499,27913,28330,28752,29178,
  29608,30041,30479,30921,31367,31818,32272,32730,33193,33660,34131,34606,35085,35569,36057,36549,
  37046,37547,38052,38561,39075,39593,40116,40643,41175,41711,42251,42796,43346,43899,44458,45021,
  45588,46161,46737,47319,47905,48495,49091,49691,50295,50905,51519,52138,52761,53390,54023,54661,
  55303,55951,56604,57261,57923,58590,59262,59939,60621,61308,62000,62697,63399,64106,64818,65535
  };

Source code

The source code is located on the GitHub server.


03.08.2017


Menu