Ejemplo n.º 1
0
void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const void *const i, void *const o,
             const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
{
  dt_iop_lowlight_data_t *d = (dt_iop_lowlight_data_t *)(piece->data);
  const int ch = piece->colors;

  // empiric coefficient
  const float c = 0.5f;
  const float threshold = 0.01f;

  // scotopic white, blue saturated
  float Lab_sw[3] = { 100.0f, 0, -d->blueness };
  float XYZ_sw[3];

  dt_Lab_to_XYZ(Lab_sw, XYZ_sw);

#ifdef _OPENMP
#pragma omp parallel for default(none) schedule(static) shared(d, XYZ_sw)
#endif
  for(size_t k = 0; k < (size_t)roi_out->width * roi_out->height; k++)
  {
    float *in = (float *)i + ch * k;
    float *out = (float *)o + ch * k;
    float XYZ[3], XYZ_s[3];
    float V;
    float w;

    dt_Lab_to_XYZ(in, XYZ);

    // calculate scotopic luminance
    if(XYZ[0] > threshold)
    {
      // normal flow
      V = XYZ[1] * (1.33f * (1.0f + (XYZ[1] + XYZ[2]) / XYZ[0]) - 1.68f);
    }
    else
    {
      // low red flow, avoids "snow" on dark noisy areas
      V = XYZ[1] * (1.33f * (1.0f + (XYZ[1] + XYZ[2]) / threshold) - 1.68f);
    }

    // scale using empiric coefficient and fit inside limits
    V = fminf(1.0f, fmaxf(0.0f, c * V));

    // blending coefficient from curve
    w = lookup(d->lut, in[0] / 100.f);

    XYZ_s[0] = V * XYZ_sw[0];
    XYZ_s[1] = V * XYZ_sw[1];
    XYZ_s[2] = V * XYZ_sw[2];

    XYZ[0] = w * XYZ[0] + (1.0f - w) * XYZ_s[0];
    XYZ[1] = w * XYZ[1] + (1.0f - w) * XYZ_s[1];
    XYZ[2] = w * XYZ[2] + (1.0f - w) * XYZ_s[2];

    dt_XYZ_to_Lab(XYZ, out);

    out[3] = in[3];
  }
}
Ejemplo n.º 2
0
int
process_cl (struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out)
{
  dt_iop_colorize_data_t *data = (dt_iop_colorize_data_t *)piece->data;
  dt_iop_colorize_global_data_t *gd = (dt_iop_colorize_global_data_t *)self->data;

  cl_int err = -999;
  const int devid = piece->pipe->devid;
  const int width = roi_in->width;
  const int height = roi_in->height;

  /* create Lab */
  float rgb[3]={0}, XYZ[3]={0}, Lab[3]={0};
  hsl2rgb(rgb,data->hue, data->saturation, data->lightness/100.0);

  XYZ[0] = (rgb[0] * 0.5767309) + (rgb[1] * 0.1855540) + (rgb[2] * 0.1881852);
  XYZ[1] = (rgb[0] * 0.2973769) + (rgb[1] * 0.6273491) + (rgb[2] * 0.0752741);
  XYZ[2] = (rgb[0] * 0.0270343) + (rgb[1] * 0.0706872) + (rgb[2] * 0.9911085);
  
  dt_XYZ_to_Lab(XYZ,Lab);


  /* a/b components */
  const float L = Lab[0];
  const float a = Lab[1];
  const float b = Lab[2];
  const float mix = data->source_lightness_mix/100.0f;

  size_t sizes[] = { ROUNDUPWD(width), ROUNDUPHT(height), 1};

  dt_opencl_set_kernel_arg(devid, gd->kernel_colorize, 0, sizeof(cl_mem), (void *)&dev_in);
  dt_opencl_set_kernel_arg(devid, gd->kernel_colorize, 1, sizeof(cl_mem), (void *)&dev_out);
  dt_opencl_set_kernel_arg(devid, gd->kernel_colorize, 2, sizeof(int), (void *)&width);
  dt_opencl_set_kernel_arg(devid, gd->kernel_colorize, 3, sizeof(int), (void *)&height);
  dt_opencl_set_kernel_arg(devid, gd->kernel_colorize, 4, sizeof(float), (void *)&mix);
  dt_opencl_set_kernel_arg(devid, gd->kernel_colorize, 5, sizeof(float), (void *)&L);
  dt_opencl_set_kernel_arg(devid, gd->kernel_colorize, 6, sizeof(float), (void *)&a);
  dt_opencl_set_kernel_arg(devid, gd->kernel_colorize, 7, sizeof(float), (void *)&b);
  err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_colorize, sizes);
  if(err != CL_SUCCESS) goto error;
  return TRUE;

error:
  dt_print(DT_DEBUG_OPENCL, "[opencl_colorize] couldn't enqueue kernel! %d\n", err);
  return FALSE;
}
Ejemplo n.º 3
0
void process (struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, void *ivoid, void *ovoid, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out)
{
  float *in, *out;
  dt_iop_colorize_data_t *d = (dt_iop_colorize_data_t *)piece->data;
  const int ch = piece->colors;

  /* create Lab */
  float rgb[3]={0}, XYZ[3]={0}, Lab[3]={0};
  hsl2rgb(rgb,d->hue, d->saturation, d->lightness/100.0);

  XYZ[0] = (rgb[0] * 0.5767309) + (rgb[1] * 0.1855540) + (rgb[2] * 0.1881852);
  XYZ[1] = (rgb[0] * 0.2973769) + (rgb[1] * 0.6273491) + (rgb[2] * 0.0752741);
  XYZ[2] = (rgb[0] * 0.0270343) + (rgb[1] * 0.0706872) + (rgb[2] * 0.9911085);
  
  dt_XYZ_to_Lab(XYZ,Lab);


  /* a/b components */
  const float L = Lab[0];
  const float a = Lab[1];
  const float b = Lab[2];

  const float mix = d->source_lightness_mix/100.0;

#ifdef _OPENMP
#pragma omp parallel for default(none) shared(ivoid,ovoid,roi_out) private(in,out) schedule(static)
#endif
  for(int k=0; k<roi_out->height; k++)
  {
    float lmix=(mix*100.0)/2.0;
    int stride = ch*roi_out->width;

    in = (float *)ivoid+(k*stride);
    out = (float *)ovoid+(k*stride);

    for(int l=0; l < stride; l+=ch)
    {
      out[l+0] = L-lmix + in[l+0]*mix;
      out[l+1] = a;
      out[l+2] = b;
      out[l+3] = in[l+3];
    }
  }
}
Ejemplo n.º 4
0
// see http://www.brucelindbloom.com/Eqn_RGB_XYZ_Matrix.html for the transformation matrices
void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, void *i, void *o,
             const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out)
{
  dt_iop_colorbalance_data_t *d = (dt_iop_colorbalance_data_t *)piece->data;
  const int ch = piece->colors;

  // these are RGB values!
  const float lift[3] = { 2.0 - (d->lift[CHANNEL_RED] * d->lift[CHANNEL_FACTOR]),
                          2.0 - (d->lift[CHANNEL_GREEN] * d->lift[CHANNEL_FACTOR]),
                          2.0 - (d->lift[CHANNEL_BLUE] * d->lift[CHANNEL_FACTOR]) },
              gamma[3] = { d->gamma[CHANNEL_RED] * d->gamma[CHANNEL_FACTOR],
                           d->gamma[CHANNEL_GREEN] * d->gamma[CHANNEL_FACTOR],
                           d->gamma[CHANNEL_BLUE] * d->gamma[CHANNEL_FACTOR] },
              gamma_inv[3] = { (gamma[0] != 0.0) ? 1.0 / gamma[0] : 1000000.0,
                               (gamma[1] != 0.0) ? 1.0 / gamma[1] : 1000000.0,
                               (gamma[2] != 0.0) ? 1.0 / gamma[2] : 1000000.0 },
              gain[3] = { d->gain[CHANNEL_RED] * d->gain[CHANNEL_FACTOR],
                          d->gain[CHANNEL_GREEN] * d->gain[CHANNEL_FACTOR],
                          d->gain[CHANNEL_BLUE] * d->gain[CHANNEL_FACTOR] };

  // sRGB -> XYZ matrix, D65
  const float srgb_to_xyz[3][3] = {
    { 0.4360747, 0.3850649, 0.1430804 },
    { 0.2225045, 0.7168786, 0.0606169 },
    { 0.0139322, 0.0971045, 0.7141733 }
    //     {0.4124564, 0.3575761, 0.1804375},
    //     {0.2126729, 0.7151522, 0.0721750},
    //     {0.0193339, 0.1191920, 0.9503041}
  };
  // XYZ -> sRGB matrix, D65
  const float xyz_to_srgb[3][3] = {
    { 3.1338561, -1.6168667, -0.4906146 },
    { -0.9787684, 1.9161415, 0.0334540 },
    { 0.0719453, -0.2289914, 1.4052427 }
    //     {3.2404542, -1.5371385, -0.4985314},
    //     {-0.9692660,  1.8760108,  0.0415560},
    //     {0.0556434, -0.2040259,  1.0572252}
  };

#ifdef _OPENMP
#pragma omp parallel for default(none) schedule(static) shared(i, o, roi_in, roi_out)
#endif
  for(int j = 0; j < roi_out->height; j++)
  {
    float *in = ((float *)i) + (size_t)ch * roi_in->width * j;
    float *out = ((float *)o) + (size_t)ch * roi_out->width * j;
    for(int i = 0; i < roi_out->width; i++)
    {
      // transform the pixel to sRGB:
      // Lab -> XYZ
      float XYZ[3];
      dt_Lab_to_XYZ(in, XYZ);
      // XYZ -> sRGB
      float rgb[3] = { 0, 0, 0 };
      for(int r = 0; r < 3; r++)
        for(int c = 0; c < 3; c++) rgb[r] += xyz_to_srgb[r][c] * XYZ[c];
      // linear sRGB -> gamma corrected sRGB
      for(int c = 0; c < 3; c++)
        rgb[c] = rgb[c] <= 0.0031308 ? 12.92 * rgb[c] : (1.0 + 0.055) * powf(rgb[c], 1.0 / 2.4) - 0.055;

      // do the calculation in RGB space
      for(int c = 0; c < 3; c++)
      {
        float tmp = (((rgb[c] - 1.0f) * lift[c]) + 1.0f) * gain[c];
        if(tmp < 0.0f) tmp = 0.0f;
        rgb[c] = powf(tmp, gamma_inv[c]);
      }

      // transform the result back to Lab
      // sRGB -> XYZ
      XYZ[0] = XYZ[1] = XYZ[2] = 0.0;
      // gamma corrected sRGB -> linear sRGB
      for(int c = 0; c < 3; c++)
        rgb[c] = rgb[c] <= 0.04045 ? rgb[c] / 12.92 : powf((rgb[c] + 0.055) / (1 + 0.055), 2.4);
      for(int r = 0; r < 3; r++)
        for(int c = 0; c < 3; c++) XYZ[r] += srgb_to_xyz[r][c] * rgb[c];
      // XYZ -> Lab
      dt_XYZ_to_Lab(XYZ, out);
      out[3] = in[3];

      in += ch;
      out += ch;
    }
  }
}