void LibRaw::recover_highlights()
{
  float *map, sum, wgt, grow;
  int hsat[4], count, spread, change, val, i;
  unsigned high, wide, mrow, mcol, row, col, kc, c, d, y, x;
  ushort *pixel;
  static const signed char dir[8][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, 1},
                                        {1, 1},   {1, 0},  {1, -1}, {0, -1}};

  grow = pow(2.0, 4 - highlight);
  FORCC hsat[c] = 32000 * pre_mul[c];
  for (kc = 0, c = 1; c < colors; c++)
    if (pre_mul[kc] < pre_mul[c])
      kc = c;
  high = height / SCALE;
  wide = width / SCALE;
  map = (float *)calloc(high, wide * sizeof *map);
  merror(map, "recover_highlights()");
  FORCC if (c != kc)
  {
    RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS, c - 1, colors - 1);
    memset(map, 0, high * wide * sizeof *map);
    for (mrow = 0; mrow < high; mrow++)
      for (mcol = 0; mcol < wide; mcol++)
      {
        sum = wgt = count = 0;
        for (row = mrow * SCALE; row < (mrow + 1) * SCALE; row++)
          for (col = mcol * SCALE; col < (mcol + 1) * SCALE; col++)
          {
            pixel = image[row * width + col];
            if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000)
            {
              sum += pixel[c];
              wgt += pixel[kc];
              count++;
            }
          }
        if (count == SCALE * SCALE)
          map[mrow * wide + mcol] = sum / wgt;
      }
    for (spread = 32 / grow; spread--;)
    {
      for (mrow = 0; mrow < high; mrow++)
        for (mcol = 0; mcol < wide; mcol++)
        {
          if (map[mrow * wide + mcol])
            continue;
          sum = count = 0;
          for (d = 0; d < 8; d++)
          {
            y = mrow + dir[d][0];
            x = mcol + dir[d][1];
            if (y < high && x < wide && map[y * wide + x] > 0)
            {
              sum += (1 + (d & 1)) * map[y * wide + x];
              count += 1 + (d & 1);
            }
          }
          if (count > 3)
            map[mrow * wide + mcol] = -(sum + grow) / (count + grow);
        }
      for (change = i = 0; i < high * wide; i++)
        if (map[i] < 0)
        {
          map[i] = -map[i];
          change = 1;
        }
      if (!change)
        break;
    }
    for (i = 0; i < high * wide; i++)
      if (map[i] == 0)
        map[i] = 1;
    for (mrow = 0; mrow < high; mrow++)
      for (mcol = 0; mcol < wide; mcol++)
      {
        for (row = mrow * SCALE; row < (mrow + 1) * SCALE; row++)
          for (col = mcol * SCALE; col < (mcol + 1) * SCALE; col++)
          {
            pixel = image[row * width + col];
            if (pixel[c] / hsat[c] > 1)
            {
              val = pixel[kc] * map[mrow * wide + mcol];
              if (pixel[c] < val)
                pixel[c] = CLIP(val);
            }
          }
      }
  }
  free(map);
}
Unknown