static gboolean
gimp_brightness_contrast_config_equal (GimpConfig *a,
                                       GimpConfig *b)
{
  GimpBrightnessContrastConfig *config_a = GIMP_BRIGHTNESS_CONTRAST_CONFIG (a);
  GimpBrightnessContrastConfig *config_b = GIMP_BRIGHTNESS_CONTRAST_CONFIG (b);

  if (config_a->brightness != config_b->brightness ||
      config_a->contrast   != config_b->contrast)
    {
      return FALSE;
    }

  return TRUE;
}
static void
brightness_contrast_config_notify (GObject                    *object,
                                   GParamSpec                 *pspec,
                                   GimpBrightnessContrastTool *bc_tool)
{
  GimpBrightnessContrastConfig *config;

  config = GIMP_BRIGHTNESS_CONTRAST_CONFIG (object);

  if (! bc_tool->brightness_data)
    return;

  if (! strcmp (pspec->name, "brightness"))
    {
      gtk_adjustment_set_value (bc_tool->brightness_data,
                                config->brightness * 127.0);
    }
  else if (! strcmp (pspec->name, "contrast"))
    {
      gtk_adjustment_set_value (bc_tool->contrast_data,
                                config->contrast * 127.0);
    }

  gimp_image_map_tool_preview (GIMP_IMAGE_MAP_TOOL (bc_tool));
}
static void
brightness_contrast_to_levels_callback (GtkWidget        *widget,
                                        GimpImageMapTool *image_map_tool)
{
    GimpLevelsConfig *levels;

    levels = gimp_brightness_contrast_config_to_levels_config (GIMP_BRIGHTNESS_CONTRAST_CONFIG (image_map_tool->config));

    gimp_image_map_tool_edit_as (image_map_tool,
                                 "gimp-levels-tool",
                                 GIMP_CONFIG (levels));

    g_object_unref (levels);
}
static gboolean
gimp_operation_brightness_contrast_process (GeglOperation       *operation,
        void                *in_buf,
        void                *out_buf,
        glong                samples,
        const GeglRectangle *roi,
        gint                 level)
{
    GimpOperationPointFilter     *point  = GIMP_OPERATION_POINT_FILTER (operation);
    GimpBrightnessContrastConfig *config = GIMP_BRIGHTNESS_CONTRAST_CONFIG (point->config);
    gfloat                       *src    = in_buf;
    gfloat                       *dest   = out_buf;
    gdouble                       brightness;
    gdouble                       slant;

    if (! config)
        return FALSE;

    brightness = config->brightness / 2.0;
    slant = tan ((config->contrast + 1) * G_PI_4);

    while (samples--)
    {
        dest[RED] = gimp_operation_brightness_contrast_map (src[RED],
                    brightness,
                    slant);
        dest[GREEN] = gimp_operation_brightness_contrast_map (src[GREEN],
                      brightness,
                      slant);
        dest[BLUE] = gimp_operation_brightness_contrast_map (src[BLUE],
                     brightness,
                     slant);
        dest[ALPHA] = src[ALPHA];

        src  += 4;
        dest += 4;
    }

    return TRUE;
}
static void
gimp_brightness_contrast_config_set_property (GObject      *object,
                                              guint         property_id,
                                              const GValue *value,
                                              GParamSpec   *pspec)
{
  GimpBrightnessContrastConfig *self = GIMP_BRIGHTNESS_CONTRAST_CONFIG (object);

  switch (property_id)
    {
    case PROP_BRIGHTNESS:
      self->brightness = g_value_get_double (value);
      break;

    case PROP_CONTRAST:
      self->contrast = g_value_get_double (value);
      break;

   default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}