static gboolean gimp_operation_posterize_process (GeglOperation *operation, void *in_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { GimpOperationPointFilter *point = GIMP_OPERATION_POINT_FILTER (operation); GimpPosterizeConfig *config = GIMP_POSTERIZE_CONFIG (point->config); gfloat *src = in_buf; gfloat *dest = out_buf; gfloat levels; if (! config) return FALSE; levels = config->levels - 1.0; while (samples--) { dest[RED] = RINT (src[RED] * levels) / levels; dest[GREEN] = RINT (src[GREEN] * levels) / levels; dest[BLUE] = RINT (src[BLUE] * levels) / levels; dest[ALPHA] = src[ALPHA]; src += 4; dest += 4; } return TRUE; }
static gboolean gimp_operation_colorize_process (GeglOperation *operation, void *in_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { GimpOperationPointFilter *point = GIMP_OPERATION_POINT_FILTER (operation); GimpColorizeConfig *config = GIMP_COLORIZE_CONFIG (point->config); gfloat *src = in_buf; gfloat *dest = out_buf; GimpHSL hsl; if (! config) return FALSE; hsl.h = config->hue; hsl.s = config->saturation; hsl.a = src[ALPHA]; while (samples--) { GimpRGB rgb; gfloat lum = GIMP_RGB_LUMINANCE (src[RED], src[GREEN], src[BLUE]); if (config->lightness > 0) { lum = lum * (1.0 - config->lightness); lum += 1.0 - (1.0 - config->lightness); } else if (config->lightness < 0) { lum = lum * (config->lightness + 1.0); } hsl.l = lum; gimp_hsl_to_rgb (&hsl, &rgb); /* the code in base/colorize.c would multiply r,b,g with lum, * but this is a bug since it should multiply with 255. We * don't repeat this bug here (this is the reason why the gegl * colorize is brighter than the legacy one). */ dest[RED] = rgb.r; /* * lum; */ dest[GREEN] = rgb.g; /* * lum; */ dest[BLUE] = rgb.b; /* * lum */; dest[ALPHA] = rgb.a; src += 4; dest += 4; } return TRUE; }
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 gboolean gimp_operation_curves_process (GeglOperation *operation, void *in_buf, void *out_buf, glong samples, const GeglRectangle *roi) { GimpOperationPointFilter *point = GIMP_OPERATION_POINT_FILTER (operation); GimpCurvesConfig *config = GIMP_CURVES_CONFIG (point->config); gfloat *src = in_buf; gfloat *dest = out_buf; if (! config) return FALSE; gimp_curve_map_pixels (config->curve[0], config->curve[1], config->curve[2], config->curve[3], config->curve[4], src, dest, samples); return TRUE; }
static gboolean gimp_operation_hue_saturation_process (GeglOperation *operation, void *in_buf, void *out_buf, glong samples, const GeglRectangle *roi) { GimpOperationPointFilter *point = GIMP_OPERATION_POINT_FILTER (operation); GimpHueSaturationConfig *config = GIMP_HUE_SATURATION_CONFIG (point->config); gfloat *src = in_buf; gfloat *dest = out_buf; gfloat overlap; if (! config) return FALSE; overlap = config->overlap / 2.0; while (samples--) { GimpRGB rgb; GimpHSL hsl; gdouble h; gint hue_counter; gint hue = 0; gint secondary_hue = 0; gboolean use_secondary_hue = FALSE; gfloat primary_intensity = 0.0; gfloat secondary_intensity = 0.0; rgb.r = src[RED]; rgb.g = src[GREEN]; rgb.b = src[BLUE]; gimp_rgb_to_hsl (&rgb, &hsl); h = hsl.h * 6.0; for (hue_counter = 0; hue_counter < 7; hue_counter++) { gdouble hue_threshold = (gdouble) hue_counter + 0.5; if (h < ((gdouble) hue_threshold + overlap)) { hue = hue_counter; if (overlap > 0.0 && h > ((gdouble) hue_threshold - overlap)) { use_secondary_hue = TRUE; secondary_hue = hue_counter + 1; secondary_intensity = (h - (gdouble) hue_threshold + overlap) / (2.0 * overlap); primary_intensity = 1.0 - secondary_intensity; } else { use_secondary_hue = FALSE; } break; } } if (hue >= 6) { hue = 0; use_secondary_hue = FALSE; } if (secondary_hue >= 6) { secondary_hue = 0; } /* transform into GimpHueRange values */ hue++; secondary_hue++; if (use_secondary_hue) { gdouble mapped_primary_hue; gdouble mapped_secondary_hue; gdouble diff; mapped_primary_hue = map_hue (config, hue, hsl.h); mapped_secondary_hue = map_hue (config, secondary_hue, hsl.h); /* Find nearest hue on the circle between primary and * secondary hue */ diff = mapped_primary_hue - mapped_secondary_hue; if (diff < -0.5) { mapped_secondary_hue -= 1.0; } else if (diff >= 0.5) { mapped_secondary_hue += 1.0; } hsl.h = (mapped_primary_hue * primary_intensity + mapped_secondary_hue * secondary_intensity); hsl.s = (map_saturation (config, hue, hsl.s) * primary_intensity + map_saturation (config, secondary_hue, hsl.s) * secondary_intensity); hsl.l = (map_lightness (config, hue, hsl.l) * primary_intensity + map_lightness (config, secondary_hue, hsl.l) * secondary_intensity); } else { hsl.h = map_hue (config, hue, hsl.h); hsl.s = map_saturation (config, hue, hsl.s); hsl.l = map_lightness (config, hue, hsl.l); } gimp_hsl_to_rgb (&hsl, &rgb); dest[RED] = rgb.r; dest[GREEN] = rgb.g; dest[BLUE] = rgb.b; dest[ALPHA] = src[ALPHA]; src += 4; dest += 4; } return TRUE; }
static gboolean gimp_operation_color_balance_process (GeglOperation *operation, void *in_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { GimpOperationPointFilter *point = GIMP_OPERATION_POINT_FILTER (operation); GimpColorBalanceConfig *config = GIMP_COLOR_BALANCE_CONFIG (point->config); gfloat *src = in_buf; gfloat *dest = out_buf; if (! config) return FALSE; while (samples--) { gfloat r = src[RED]; gfloat g = src[GREEN]; gfloat b = src[BLUE]; gfloat r_n; gfloat g_n; gfloat b_n; GimpRGB rgb = { r, g, b}; GimpHSL hsl; gimp_rgb_to_hsl (&rgb, &hsl); r_n = gimp_operation_color_balance_map (r, hsl.l, config->cyan_red[GIMP_SHADOWS], config->cyan_red[GIMP_MIDTONES], config->cyan_red[GIMP_HIGHLIGHTS]); g_n = gimp_operation_color_balance_map (g, hsl.l, config->magenta_green[GIMP_SHADOWS], config->magenta_green[GIMP_MIDTONES], config->magenta_green[GIMP_HIGHLIGHTS]); b_n = gimp_operation_color_balance_map (b, hsl.l, config->yellow_blue[GIMP_SHADOWS], config->yellow_blue[GIMP_MIDTONES], config->yellow_blue[GIMP_HIGHLIGHTS]); if (config->preserve_luminosity) { GimpHSL hsl2; rgb.r = r_n; rgb.g = g_n; rgb.b = b_n; gimp_rgb_to_hsl (&rgb, &hsl); rgb.r = r; rgb.g = g; rgb.b = b; gimp_rgb_to_hsl (&rgb, &hsl2); hsl.l = hsl2.l; gimp_hsl_to_rgb (&hsl, &rgb); r_n = rgb.r; g_n = rgb.g; b_n = rgb.b; } dest[RED] = r_n; dest[GREEN] = g_n; dest[BLUE] = b_n; dest[ALPHA] = src[ALPHA]; src += 4; dest += 4; } return TRUE; }
static gboolean gimp_operation_desaturate_process (GeglOperation *operation, void *in_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { GimpOperationPointFilter *point = GIMP_OPERATION_POINT_FILTER (operation); GimpDesaturateConfig *config = GIMP_DESATURATE_CONFIG (point->config); gfloat *src = in_buf; gfloat *dest = out_buf; if (! config) return FALSE; switch (config->mode) { case GIMP_DESATURATE_LIGHTNESS: while (samples--) { gfloat min, max, value; max = MAX (src[0], src[1]); max = MAX (max, src[2]); min = MIN (src[0], src[1]); min = MIN (min, src[2]); value = (max + min) / 2; dest[0] = value; dest[1] = value; dest[2] = value; dest[3] = src[3]; src += 4; dest += 4; } break; case GIMP_DESATURATE_LUMINOSITY: while (samples--) { gfloat value = GIMP_RGB_LUMINANCE (src[0], src[1], src[2]); dest[0] = value; dest[1] = value; dest[2] = value; dest[3] = src[3]; src += 4; dest += 4; } break; case GIMP_DESATURATE_AVERAGE: while (samples--) { gfloat value = (src[0] + src[1] + src[2]) / 3; dest[0] = value; dest[1] = value; dest[2] = value; dest[3] = src[3]; src += 4; dest += 4; } break; } return TRUE; }