gboolean gimp_babl_format_get_linear (const Babl *format) { const Babl *model; g_return_val_if_fail (format != NULL, FALSE); model = babl_format_get_model (format); if (model == babl_model ("Y") || model == babl_model ("YA") || model == babl_model ("RGB") || model == babl_model ("RGBA")) { return TRUE; } else if (model == babl_model ("Y'") || model == babl_model ("Y'A") || model == babl_model ("R'G'B'") || model == babl_model ("R'G'B'A")) { return FALSE; } else if (babl_format_is_palette (format)) { return FALSE; } g_return_val_if_reached (FALSE); }
static GimpTempBuf * gimp_buffer_get_new_preview (GimpViewable *viewable, GimpContext *context, gint width, gint height) { GimpBuffer *buffer = GIMP_BUFFER (viewable); const Babl *format = gimp_buffer_get_format (buffer); GimpTempBuf *preview; if (babl_format_is_palette (format)) format = gimp_babl_format (GIMP_RGB, GIMP_PRECISION_U8_GAMMA, babl_format_has_alpha (format)); else format = gimp_babl_format (gimp_babl_format_get_base_type (format), gimp_babl_precision (GIMP_COMPONENT_TYPE_U8, gimp_babl_format_get_linear (format)), babl_format_has_alpha (format)); preview = gimp_temp_buf_new (width, height, format); gegl_buffer_get (buffer->buffer, GEGL_RECTANGLE (0, 0, width, height), MIN ((gdouble) width / (gdouble) gimp_buffer_get_width (buffer), (gdouble) height / (gdouble) gimp_buffer_get_height (buffer)), format, gimp_temp_buf_get_data (preview), GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); return preview; }
GimpImageBaseType gimp_babl_format_get_base_type (const Babl *format) { const Babl *model; g_return_val_if_fail (format != NULL, -1); model = babl_format_get_model (format); if (model == babl_model ("Y") || model == babl_model ("Y'") || model == babl_model ("YA") || model == babl_model ("Y'A")) { return GIMP_GRAY; } else if (model == babl_model ("RGB") || model == babl_model ("R'G'B'") || model == babl_model ("RGBA") || model == babl_model ("R'G'B'A")) { return GIMP_RGB; } else if (babl_format_is_palette (format)) { return GIMP_INDEXED; } g_return_val_if_reached (-1); }
const Babl * gimp_babl_compat_u8_format (const Babl *format) { g_return_val_if_fail (format != NULL, NULL); /* indexed images only exist in u8, return the same format */ if (babl_format_is_palette (format)) return format; return gimp_babl_format (gimp_babl_format_get_base_type (format), GIMP_PRECISION_U8, babl_format_has_alpha (format)); }
GimpImageType gimp_babl_format_get_image_type (const Babl *format) { const gchar *name; g_return_val_if_fail (format != NULL, -1); name = babl_get_name (babl_format_get_model (format)); if (! strcmp (name, "Y") || ! strcmp (name, "Y'") || ! strcmp (name, "Y~")) { return GIMP_GRAY_IMAGE; } else if (! strcmp (name, "YA") || ! strcmp (name, "Y'A") || ! strcmp (name, "Y~A")) { return GIMP_GRAYA_IMAGE; } else if (! strcmp (name, "RGB") || ! strcmp (name, "R'G'B'") || ! strcmp (name, "R~G~B~")) { return GIMP_RGB_IMAGE; } else if (! strcmp (name, "RGBA") || ! strcmp (name, "R'G'B'A") || ! strcmp (name, "R~G~B~A")) { return GIMP_RGBA_IMAGE; } else if (babl_format_is_palette (format)) { if (babl_format_has_alpha (format)) return GIMP_INDEXEDA_IMAGE; else return GIMP_INDEXED_IMAGE; } g_return_val_if_reached (-1); }
static const Babl * choose_format (GeglBuffer *buffer, GimpSelectCriterion select_criterion, gint *n_components, gboolean *has_alpha) { const Babl *format = gegl_buffer_get_format (buffer); *has_alpha = babl_format_has_alpha (format); switch (select_criterion) { case GIMP_SELECT_CRITERION_COMPOSITE: if (babl_format_is_palette (format)) format = babl_format ("R'G'B'A float"); else format = gimp_babl_format (gimp_babl_format_get_base_type (format), GIMP_PRECISION_FLOAT_GAMMA, *has_alpha); break; case GIMP_SELECT_CRITERION_R: case GIMP_SELECT_CRITERION_G: case GIMP_SELECT_CRITERION_B: case GIMP_SELECT_CRITERION_A: format = babl_format ("R'G'B'A float"); break; case GIMP_SELECT_CRITERION_H: case GIMP_SELECT_CRITERION_S: case GIMP_SELECT_CRITERION_V: format = babl_format ("HSVA float"); break; default: g_return_val_if_reached (NULL); break; } *n_components = babl_format_get_n_components (format); return format; }
int main (int argc, char **argv) { int OK = 1; babl_init (); OK = ! babl_format_is_palette (babl_format_n (babl_type ("double"), 3)); if(1) { unsigned char in[][1] = {{ 0},{ 1},{ 2},{15}}; unsigned char out[][4] = {{0,0,0,255},{127,0,0,255},{0,127,0,255},{255,255,255,255}}; const Babl *palA;// = babl_new_palette (NULL, 0); //Babl *palB = babl_new_palette (NULL, 0); // babl_new_palette (NULL, &palA, NULL); assert (palA); CHECK_CONV("pal to rgba", unsigned char, palA, babl_format("RGBA u8"), in, out); }
GimpImageType gimp_babl_format_get_image_type (const Babl *format) { const Babl *model; g_return_val_if_fail (format != NULL, -1); model = babl_format_get_model (format); if (model == babl_model ("Y") || model == babl_model ("Y'")) { return GIMP_GRAY_IMAGE; } else if (model == babl_model ("YA") || model == babl_model ("Y'A")) { return GIMP_GRAYA_IMAGE; } else if (model == babl_model ("RGB") || model == babl_model ("R'G'B'")) { return GIMP_RGB_IMAGE; } else if (model == babl_model ("RGBA") || model == babl_model ("R'G'B'A")) { return GIMP_RGBA_IMAGE; } else if (babl_format_is_palette (format)) { if (babl_format_has_alpha (format)) return GIMP_INDEXEDA_IMAGE; else return GIMP_INDEXED_IMAGE; } g_return_val_if_reached (-1); }
const gchar * gimp_babl_get_description (const Babl *babl) { const gchar *description; g_return_val_if_fail (babl != NULL, NULL); if (G_UNLIKELY (! babl_description_hash)) { gint i; babl_description_hash = g_hash_table_new (g_str_hash, g_str_equal); for (i = 0; i < G_N_ELEMENTS (babl_descriptions); i++) g_hash_table_insert (babl_description_hash, (gpointer) babl_descriptions[i].name, gettext (babl_descriptions[i].description)); } if (babl_format_is_palette (babl)) { if (babl_format_has_alpha (babl)) return _("Indexed-alpha"); else return _("Indexed"); } description = g_hash_table_lookup (babl_description_hash, babl_get_name (babl)); if (description) return description; return g_strconcat ("ERROR: unknown Babl format ", babl_get_name (babl), NULL); }
gboolean gimp_pickable_pick_color (GimpPickable *pickable, gint x, gint y, gboolean sample_average, gdouble average_radius, GimpRGB *color, gint *color_index) { const Babl *format; gdouble pixel[4]; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), FALSE); format = babl_format ("RGBA double"); if (! gimp_pickable_get_pixel_at (pickable, x, y, format, pixel)) return FALSE; if (sample_average) { gint count = 0; gdouble color_avg[4] = { 0.0, 0.0, 0.0, 0.0 }; gint radius = (gint) average_radius; gint i, j; for (i = x - radius; i <= x + radius; i++) for (j = y - radius; j <= y + radius; j++) if (gimp_pickable_get_pixel_at (pickable, i, j, format, pixel)) { count++; color_avg[RED] += pixel[RED]; color_avg[GREEN] += pixel[GREEN]; color_avg[BLUE] += pixel[BLUE]; color_avg[ALPHA] += pixel[ALPHA]; } pixel[RED] = color_avg[RED] / count; pixel[GREEN] = color_avg[GREEN] / count; pixel[BLUE] = color_avg[BLUE] / count; pixel[ALPHA] = color_avg[ALPHA] / count; } gimp_rgba_set_pixel (color, format, pixel); if (color_index) { format = gimp_pickable_get_format (pickable); if (babl_format_is_palette (format) && ! sample_average) { guchar indexed_pixel[4]; gimp_pickable_get_pixel_at (pickable, x, y, format, indexed_pixel); *color_index = indexed_pixel[0]; } else { *color_index = -1; } } return TRUE; }
static void gimp_color_tool_real_picked (GimpColorTool *color_tool, GimpColorPickState pick_state, gdouble x, gdouble y, const Babl *sample_format, const GimpRGB *color, gint color_index) { GimpTool *tool = GIMP_TOOL (color_tool); GimpContext *context; /* use this tool's own options here (NOT color_tool->options) */ context = GIMP_CONTEXT (gimp_tool_get_options (tool)); if (color_tool->pick_mode == GIMP_COLOR_PICK_MODE_FOREGROUND || color_tool->pick_mode == GIMP_COLOR_PICK_MODE_BACKGROUND) { GtkWidget *widget; if (babl_format_is_palette (sample_format)) { widget = gimp_dialog_factory_find_widget (gimp_dialog_factory_get_singleton (), "gimp-indexed-palette"); if (widget) { GimpColormapEditor *editor; editor = GIMP_COLORMAP_EDITOR (gtk_bin_get_child (GTK_BIN (widget))); gimp_colormap_editor_set_index (editor, color_index, NULL); } } if (TRUE) { widget = gimp_dialog_factory_find_widget (gimp_dialog_factory_get_singleton (), "gimp-palette-editor"); if (widget) { GimpPaletteEditor *editor; gint index; editor = GIMP_PALETTE_EDITOR (gtk_bin_get_child (GTK_BIN (widget))); index = gimp_palette_editor_get_index (editor, color); if (index != -1) gimp_palette_editor_set_index (editor, index, NULL); } } } switch (color_tool->pick_mode) { case GIMP_COLOR_PICK_MODE_NONE: break; case GIMP_COLOR_PICK_MODE_FOREGROUND: gimp_context_set_foreground (context, color); break; case GIMP_COLOR_PICK_MODE_BACKGROUND: gimp_context_set_background (context, color); break; case GIMP_COLOR_PICK_MODE_PALETTE: { GimpDisplayShell *shell = gimp_display_get_shell (tool->display); GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (shell)); GtkWidget *dockable; dockable = gimp_window_strategy_show_dockable_dialog (GIMP_WINDOW_STRATEGY (gimp_get_window_strategy (tool->display->gimp)), tool->display->gimp, gimp_dialog_factory_get_singleton (), screen, "gimp-palette-editor"); if (dockable) { GtkWidget *palette_editor; GimpData *data; /* don't blink like mad when updating */ if (pick_state == GIMP_COLOR_PICK_STATE_UPDATE) gimp_dockable_blink_cancel (GIMP_DOCKABLE (dockable)); palette_editor = gtk_bin_get_child (GTK_BIN (dockable)); data = gimp_data_editor_get_data (GIMP_DATA_EDITOR (palette_editor)); if (! data) { data = GIMP_DATA (gimp_context_get_palette (context)); gimp_data_editor_set_data (GIMP_DATA_EDITOR (palette_editor), data); } gimp_palette_editor_pick_color (GIMP_PALETTE_EDITOR (palette_editor), color, pick_state); } } break; } }
static void gimp_color_frame_update (GimpColorFrame *frame) { const gchar *names[GIMP_COLOR_FRAME_ROWS] = { NULL, }; gchar **values = NULL; gboolean has_alpha; gint i; has_alpha = babl_format_has_alpha (frame->sample_format); if (frame->sample_valid) { gimp_color_area_set_color (GIMP_COLOR_AREA (frame->color_area), &frame->color); } switch (frame->frame_mode) { case GIMP_COLOR_FRAME_MODE_PIXEL: { GimpImageBaseType base_type; base_type = gimp_babl_format_get_base_type (frame->sample_format); if (frame->sample_valid) { const Babl *print_format = NULL; guchar print_pixel[32]; switch (gimp_babl_format_get_precision (frame->sample_format)) { case GIMP_PRECISION_U8_GAMMA: if (babl_format_is_palette (frame->sample_format)) { print_format = gimp_babl_format (GIMP_RGB, GIMP_PRECISION_U8_GAMMA, has_alpha); break; } /* else fall thru */ case GIMP_PRECISION_U8_LINEAR: case GIMP_PRECISION_U16_LINEAR: case GIMP_PRECISION_U16_GAMMA: case GIMP_PRECISION_U32_LINEAR: case GIMP_PRECISION_U32_GAMMA: case GIMP_PRECISION_FLOAT_LINEAR: case GIMP_PRECISION_FLOAT_GAMMA: case GIMP_PRECISION_DOUBLE_LINEAR: case GIMP_PRECISION_DOUBLE_GAMMA: print_format = frame->sample_format; break; case GIMP_PRECISION_HALF_GAMMA: print_format = gimp_babl_format (base_type, GIMP_PRECISION_FLOAT_GAMMA, has_alpha); break; case GIMP_PRECISION_HALF_LINEAR: print_format = gimp_babl_format (base_type, GIMP_PRECISION_FLOAT_LINEAR, has_alpha); break; } if (frame->sample_average) { /* FIXME: this is broken: can't use the averaged sRGB GimpRGB * value for displaying pixel values when color management * is enabled */ gimp_rgba_get_pixel (&frame->color, print_format, print_pixel); } else { babl_process (babl_fish (frame->sample_format, print_format), frame->pixel, print_pixel, 1); } values = gimp_babl_print_pixel (print_format, print_pixel); } if (base_type == GIMP_GRAY) { names[0] = _("Value:"); if (has_alpha) names[1] = _("Alpha:"); } else { names[0] = _("Red:"); names[1] = _("Green:"); names[2] = _("Blue:"); if (has_alpha) names[3] = _("Alpha:"); if (babl_format_is_palette (frame->sample_format)) { names[4] = _("Index:"); if (frame->sample_valid) { gchar **v = g_new0 (gchar *, 6); gchar **tmp = values; memcpy (v, values, 4 * sizeof (gchar *)); values = v; g_free (tmp); if (! frame->sample_average) values[4] = g_strdup_printf ("%d", frame->pixel[0]); } } } }
/** * gimp_color_profile_get_format: * @format: a #Babl format * @lcms_format: return location for an lcms format * * This function takes a #Babl format and returns the lcms format to * be used with that @format. It also returns a #Babl format to be * used instead of the passed @format, which usually is the same as * @format, unless lcms doesn't support @format. * * Note that this function currently only supports RGB, RGBA, R'G'B', * R'G'B'A, Y, YA, Y', Y'A and the cairo-RGB24 and cairo-ARGB32 formats. * * Return value: the #Babl format to be used instead of @format, or %NULL * is the passed @format is not supported at all. * * Since: 2.10 **/ const Babl * gimp_color_profile_get_format (const Babl *format, guint32 *lcms_format) { const Babl *output_format = NULL; const Babl *type; const Babl *model; gboolean has_alpha; gboolean gray; gboolean linear; g_return_val_if_fail (format != NULL, NULL); g_return_val_if_fail (lcms_format != NULL, NULL); has_alpha = babl_format_has_alpha (format); type = babl_format_get_type (format, 0); model = babl_format_get_model (format); if (format == babl_format ("cairo-RGB24")) { *lcms_format = TYPE_RGB_8; return babl_format ("R'G'B' u8"); } else if (format == babl_format ("cairo-ARGB32")) { *lcms_format = TYPE_RGBA_8; return babl_format ("R'G'B'A u8"); } else if (model == babl_model ("RGB") || model == babl_model ("RGBA")) { gray = FALSE; linear = TRUE; } else if (model == babl_model ("R'G'B'") || model == babl_model ("R'G'B'A")) { gray = FALSE; linear = FALSE; } else if (model == babl_model ("Y") || model == babl_model ("YA")) { gray = TRUE; linear = TRUE; } else if (model == babl_model ("Y'") || model == babl_model ("Y'A")) { gray = TRUE; linear = FALSE; } else if (babl_format_is_palette (format)) { if (has_alpha) { *lcms_format = TYPE_RGBA_8; return babl_format ("R'G'B'A u8"); } else { *lcms_format = TYPE_RGB_8; return babl_format ("R'G'B' u8"); } } else { g_printerr ("format: %s\n" "has_alpha = %s\n" "type = %s\n" "model = %s\n", babl_get_name (format), has_alpha ? "TRUE" : "FALSE", babl_get_name (type), babl_get_name (model)); g_return_val_if_reached (NULL); } *lcms_format = 0; if (type == babl_type ("u8")) { if (has_alpha) { if (gray) *lcms_format = TYPE_GRAYA_8; else *lcms_format = TYPE_RGBA_8; } else { if (gray) *lcms_format = TYPE_GRAY_8; else *lcms_format = TYPE_RGB_8; } output_format = format; } else if (type == babl_type ("u16")) { if (has_alpha) { if (gray) *lcms_format = TYPE_GRAYA_16; else *lcms_format = TYPE_RGBA_16; } else { if (gray) *lcms_format = TYPE_GRAY_16; else *lcms_format = TYPE_RGB_16; } output_format = format; } else if (type == babl_type ("half")) /* 16-bit floating point (half) */ { if (has_alpha) { if (gray) *lcms_format = TYPE_GRAYA_HALF_FLT; else *lcms_format = TYPE_RGBA_HALF_FLT; } else { if (gray) *lcms_format = TYPE_GRAY_HALF_FLT; else *lcms_format = TYPE_RGB_HALF_FLT; } output_format = format; } else if (type == babl_type ("float")) { if (has_alpha) { if (gray) *lcms_format = TYPE_GRAYA_FLT; else *lcms_format = TYPE_RGBA_FLT; } else { if (gray) *lcms_format = TYPE_GRAY_FLT; else *lcms_format = TYPE_RGB_FLT; } output_format = format; } else if (type == babl_type ("double")) { if (has_alpha) { if (gray) *lcms_format = TYPE_GRAYA_DBL; else *lcms_format = TYPE_RGBA_DBL; } else { if (gray) *lcms_format = TYPE_GRAY_DBL; else *lcms_format = TYPE_RGB_DBL; } output_format = format; } if (*lcms_format == 0) { g_printerr ("%s: layer format %s not supported, " "falling back to float\n", G_STRFUNC, babl_get_name (format)); if (has_alpha) { if (gray) { *lcms_format = TYPE_GRAYA_FLT; if (linear) output_format = babl_format ("YA float"); else output_format = babl_format ("Y'A float"); } else { *lcms_format = TYPE_RGBA_FLT; if (linear) output_format = babl_format ("RGBA float"); else output_format = babl_format ("R'G'B'A float"); } } else { if (gray) { *lcms_format = TYPE_GRAY_FLT; if (linear) output_format = babl_format ("Y float"); else output_format = babl_format ("Y' float"); } else { *lcms_format = TYPE_RGB_FLT; if (linear) output_format = babl_format ("RGB float"); else output_format = babl_format ("R'G'B' float"); } } } return output_format; }
void gimp_gegl_convolve (GeglBuffer *src_buffer, const GeglRectangle *src_rect, GeglBuffer *dest_buffer, const GeglRectangle *dest_rect, const gfloat *kernel, gint kernel_size, gdouble divisor, GimpConvolutionType mode, gboolean alpha_weighting) { GeglBufferIterator *iter; GeglRectangle *src_roi; GeglRectangle *dest_roi; const Babl *src_format; const Babl *dest_format; gint src_components; gint dest_components; src_format = gegl_buffer_get_format (src_buffer); if (babl_format_is_palette (src_format)) src_format = gimp_babl_format (GIMP_RGB, GIMP_PRECISION_FLOAT_LINEAR, babl_format_has_alpha (src_format)); else src_format = gimp_babl_format (gimp_babl_format_get_base_type (src_format), GIMP_PRECISION_FLOAT_LINEAR, babl_format_has_alpha (src_format)); dest_format = gegl_buffer_get_format (dest_buffer); if (babl_format_is_palette (dest_format)) dest_format = gimp_babl_format (GIMP_RGB, GIMP_PRECISION_FLOAT_LINEAR, babl_format_has_alpha (dest_format)); else dest_format = gimp_babl_format (gimp_babl_format_get_base_type (dest_format), GIMP_PRECISION_FLOAT_LINEAR, babl_format_has_alpha (dest_format)); src_components = babl_format_get_n_components (src_format); dest_components = babl_format_get_n_components (dest_format); iter = gegl_buffer_iterator_new (src_buffer, src_rect, 0, src_format, GEGL_BUFFER_READ, GEGL_ABYSS_NONE); src_roi = &iter->roi[0]; gegl_buffer_iterator_add (iter, dest_buffer, dest_rect, 0, dest_format, GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE); dest_roi = &iter->roi[1]; while (gegl_buffer_iterator_next (iter)) { /* Convolve the src image using the convolution kernel, writing * to dest Convolve is not tile-enabled--use accordingly */ const gfloat *src = iter->data[0]; gfloat *dest = iter->data[1]; const gint components = src_components; const gint a_component = components - 1; const gint rowstride = src_components * src_roi->width; const gint margin = kernel_size / 2; const gint x1 = src_roi->x; const gint y1 = src_roi->y; const gint x2 = src_roi->x + src_roi->width - 1; const gint y2 = src_roi->y + src_roi->height - 1; gint x, y; gfloat offset; /* If the mode is NEGATIVE_CONVOL, the offset should be 128 */ if (mode == GIMP_NEGATIVE_CONVOL) { offset = 0.5; mode = GIMP_NORMAL_CONVOL; } else { offset = 0.0; } for (y = 0; y < dest_roi->height; y++) { gfloat *d = dest; if (alpha_weighting) { for (x = 0; x < dest_roi->width; x++) { const gfloat *m = kernel; gdouble total[4] = { 0.0, 0.0, 0.0, 0.0 }; gdouble weighted_divisor = 0.0; gint i, j, b; for (j = y - margin; j <= y + margin; j++) { for (i = x - margin; i <= x + margin; i++, m++) { gint xx = CLAMP (i, x1, x2); gint yy = CLAMP (j, y1, y2); const gfloat *s = src + yy * rowstride + xx * components; const gfloat a = s[a_component]; if (a) { gdouble mult_alpha = *m * a; weighted_divisor += mult_alpha; for (b = 0; b < a_component; b++) total[b] += mult_alpha * s[b]; total[a_component] += mult_alpha; } } } if (weighted_divisor == 0.0) weighted_divisor = divisor; for (b = 0; b < a_component; b++) total[b] /= weighted_divisor; total[a_component] /= divisor; for (b = 0; b < components; b++) { total[b] += offset; if (mode != GIMP_NORMAL_CONVOL && total[b] < 0.0) total[b] = - total[b]; *d++ = CLAMP (total[b], 0.0, 1.0); } } } else { for (x = 0; x < dest_roi->width; x++) { const gfloat *m = kernel; gdouble total[4] = { 0.0, 0.0, 0.0, 0.0 }; gint i, j, b; for (j = y - margin; j <= y + margin; j++) { for (i = x - margin; i <= x + margin; i++, m++) { gint xx = CLAMP (i, x1, x2); gint yy = CLAMP (j, y1, y2); const gfloat *s = src + yy * rowstride + xx * components; for (b = 0; b < components; b++) total[b] += *m * s[b]; } } for (b = 0; b < components; b++) { total[b] = total[b] / divisor + offset; if (mode != GIMP_NORMAL_CONVOL && total[b] < 0.0) total[b] = - total[b]; total[b] = CLAMP (total[b], 0.0, 1.0); } } } dest += dest_roi->width * dest_components; } } }
void gimp_histogram_calculate (GimpHistogram *histogram, GeglBuffer *buffer, const GeglRectangle *buffer_rect, GeglBuffer *mask, const GeglRectangle *mask_rect) { GeglBufferIterator *iter; const Babl *format; gint n_components; g_return_if_fail (histogram != NULL); g_return_if_fail (GEGL_IS_BUFFER (buffer)); g_return_if_fail (buffer_rect != NULL); format = gegl_buffer_get_format (buffer); if (babl_format_is_palette (format)) format = gimp_babl_format (GIMP_RGB, GIMP_PRECISION_U8, babl_format_has_alpha (format)); else format = gimp_babl_format (gimp_babl_format_get_base_type (format), GIMP_PRECISION_U8, babl_format_has_alpha (format)); n_components = babl_format_get_n_components (format); gimp_histogram_alloc_values (histogram, n_components); iter = gegl_buffer_iterator_new (buffer, buffer_rect, 0, format, GEGL_BUFFER_READ, GEGL_ABYSS_NONE); if (mask) gegl_buffer_iterator_add (iter, mask, mask_rect, 0, babl_format ("Y float"), GEGL_BUFFER_READ, GEGL_ABYSS_NONE); #define VALUE(c,i) (histogram->values[(c) * 256 + (i)]) while (gegl_buffer_iterator_next (iter)) { const guchar *data = iter->data[0]; gint max; if (mask) { const gfloat *mask_data = iter->data[1]; switch (n_components) { case 1: while (iter->length) { const gdouble masked = *mask_data; VALUE (0, data[0]) += masked; data += n_components; mask_data += 1; } break; case 2: while (iter->length--) { const gdouble masked = *mask_data; const gdouble weight = data[1] / 255.0; VALUE (0, data[0]) += weight * masked; VALUE (1, data[1]) += masked; data += n_components; mask_data += 1; } break; case 3: /* calculate separate value values */ while (iter->length--) { const gdouble masked = *mask_data; VALUE (1, data[0]) += masked; VALUE (2, data[1]) += masked; VALUE (3, data[2]) += masked; max = MAX (data[0], data[1]); max = MAX (data[2], max); VALUE (0, max) += masked; data += n_components; mask_data += 1; } break; case 4: /* calculate separate value values */ while (iter->length--) { const gdouble masked = *mask_data; const gdouble weight = data[3] / 255.0; VALUE (1, data[0]) += weight * masked; VALUE (2, data[1]) += weight * masked; VALUE (3, data[2]) += weight * masked; VALUE (4, data[3]) += masked; max = MAX (data[0], data[1]); max = MAX (data[2], max); VALUE (0, max) += weight * masked; data += n_components; mask_data += 1; } break; } } else /* no mask */ { switch (n_components) { case 1: while (iter->length--) { VALUE (0, data[0]) += 1.0; data += n_components; } break; case 2: while (iter->length--) { const gdouble weight = data[1] / 255; VALUE (0, data[0]) += weight; VALUE (1, data[1]) += 1.0; data += n_components; } break; case 3: /* calculate separate value values */ while (iter->length--) { VALUE (1, data[0]) += 1.0; VALUE (2, data[1]) += 1.0; VALUE (3, data[2]) += 1.0; max = MAX (data[0], data[1]); max = MAX (data[2], max); VALUE (0, max) += 1.0; data += n_components; } break; case 4: /* calculate separate value values */ while (iter->length--) { const gdouble weight = data[3] / 255; VALUE (1, data[0]) += weight; VALUE (2, data[1]) += weight; VALUE (3, data[2]) += weight; VALUE (4, data[3]) += 1.0; max = MAX (data[0], data[1]); max = MAX (data[2], max); VALUE (0, max) += weight; data += n_components; } break; } } } #undef VALUE }