static void gimp_histogram_editor_info_update (GimpHistogramEditor *editor) { GimpHistogramView *view = GIMP_HISTOGRAM_BOX (editor->box)->view; GimpHistogram *hist = editor->histogram; if (hist) { gint n_bins; gdouble pixels; gdouble count; gchar text[12]; n_bins = gimp_histogram_n_bins (hist); pixels = gimp_histogram_get_count (hist, view->channel, 0, n_bins - 1); count = gimp_histogram_get_count (hist, view->channel, view->start, view->end); g_snprintf (text, sizeof (text), "%.3f", gimp_histogram_get_mean (hist, view->channel, view->start, view->end)); gtk_label_set_text (GTK_LABEL (editor->labels[0]), text); g_snprintf (text, sizeof (text), "%.3f", gimp_histogram_get_std_dev (hist, view->channel, view->start, view->end)); gtk_label_set_text (GTK_LABEL (editor->labels[1]), text); g_snprintf (text, sizeof (text), "%.3f", gimp_histogram_get_median (hist, view->channel, view->start, view->end)); gtk_label_set_text (GTK_LABEL (editor->labels[2]), text); g_snprintf (text, sizeof (text), "%d", (gint) pixels); gtk_label_set_text (GTK_LABEL (editor->labels[3]), text); g_snprintf (text, sizeof (text), "%d", (gint) count); gtk_label_set_text (GTK_LABEL (editor->labels[4]), text); g_snprintf (text, sizeof (text), "%.1f", (pixels > 0 ? (100.0 * count / pixels) : 0.0)); gtk_label_set_text (GTK_LABEL (editor->labels[5]), text); } else { gint i; for (i = 0; i < 6; i++) gtk_label_set_text (GTK_LABEL (editor->labels[i]), NULL); } }
static void equalize_lut_setup (GimpLut *lut, GimpHistogram *hist, gint n_channels) { gint i, k, j; hist_lut_struct hlut; gdouble pixels_per_value; gdouble desired; gdouble sum, dif; g_return_if_fail (lut != NULL); g_return_if_fail (hist != NULL); /* Find partition points */ pixels_per_value = gimp_histogram_get_count (hist, GIMP_HISTOGRAM_VALUE, 0, 255) / 256.0; for (k = 0; k < n_channels; k++) { /* First and last points in partition */ hlut.part[k][0] = 0; hlut.part[k][256] = 256; /* Find intermediate points */ j = 0; sum = (gimp_histogram_get_channel (hist, k, 0) + gimp_histogram_get_channel (hist, k, 1)); for (i = 1; i < 256; i++) { desired = i * pixels_per_value; while (sum < desired && j < 256) { j++; sum += gimp_histogram_get_channel (hist, k, j + 1); } /* Nearest sum */ dif = sum - gimp_histogram_get_channel (hist, k, j); if ((sum - desired) > (dif / 2.0)) hlut.part[k][i] = j; else hlut.part[k][i] = j + 1; } } gimp_lut_setup (lut, (GimpLutFunc) equalize_lut_func, &hlut, n_channels); }
gdouble gimp_histogram_get_std_dev (GimpHistogram *histogram, GimpHistogramChannel channel, gint start, gint end) { gint i; gdouble dev = 0.0; gdouble count; gdouble mean; g_return_val_if_fail (histogram != NULL, 0.0); /* the gray alpha channel is in slot 1 */ if (histogram->n_channels == 3 && channel == GIMP_HISTOGRAM_ALPHA) channel = 1; if (! histogram->values || start > end || (channel == GIMP_HISTOGRAM_RGB && histogram->n_channels < 4) || (channel != GIMP_HISTOGRAM_RGB && channel >= histogram->n_channels)) return 0.0; mean = gimp_histogram_get_mean (histogram, channel, start, end); count = gimp_histogram_get_count (histogram, channel, start, end); if (count == 0.0) count = 1.0; for (i = start; i <= end; i++) { gdouble value; if (channel == GIMP_HISTOGRAM_RGB) { value = (HISTOGRAM_VALUE (GIMP_HISTOGRAM_RED, i) + HISTOGRAM_VALUE (GIMP_HISTOGRAM_GREEN, i) + HISTOGRAM_VALUE (GIMP_HISTOGRAM_BLUE, i)); } else { value = gimp_histogram_get_value (histogram, channel, i); } dev += value * SQR (i - mean); } return sqrt (dev / count); }
gdouble gimp_histogram_get_count (GimpHistogram *histogram, GimpHistogramChannel channel, gint start, gint end) { gint i; gdouble count = 0.0; g_return_val_if_fail (histogram != NULL, 0.0); /* the gray alpha channel is in slot 1 */ if (histogram->n_channels == 3 && channel == GIMP_HISTOGRAM_ALPHA) channel = 1; if (channel == GIMP_HISTOGRAM_RGB) return (gimp_histogram_get_count (histogram, GIMP_HISTOGRAM_RED, start, end) + gimp_histogram_get_count (histogram, GIMP_HISTOGRAM_GREEN, start, end) + gimp_histogram_get_count (histogram, GIMP_HISTOGRAM_BLUE, start, end)); if (! histogram->values || start > end || channel >= histogram->n_channels) return 0.0; start = CLAMP (start, 0, 255); end = CLAMP (end, 0, 255); for (i = start; i <= end; i++) count += HISTOGRAM_VALUE (channel, i); return count; }
gint gimp_histogram_get_median (GimpHistogram *histogram, GimpHistogramChannel channel, gint start, gint end) { gint i; gdouble sum = 0.0; gdouble count; g_return_val_if_fail (histogram != NULL, -1); /* the gray alpha channel is in slot 1 */ if (histogram->n_channels == 3 && channel == GIMP_HISTOGRAM_ALPHA) channel = 1; if (! histogram->values || start > end || (channel == GIMP_HISTOGRAM_RGB && histogram->n_channels < 4) || (channel != GIMP_HISTOGRAM_RGB && channel >= histogram->n_channels)) return 0; start = CLAMP (start, 0, 255); end = CLAMP (end, 0, 255); count = gimp_histogram_get_count (histogram, channel, start, end); if (channel == GIMP_HISTOGRAM_RGB) for (i = start; i <= end; i++) { sum += (HISTOGRAM_VALUE (GIMP_HISTOGRAM_RED, i) + HISTOGRAM_VALUE (GIMP_HISTOGRAM_GREEN, i) + HISTOGRAM_VALUE (GIMP_HISTOGRAM_BLUE, i)); if (sum * 2 > count) return i; } else for (i = start; i <= end; i++) { sum += HISTOGRAM_VALUE (channel, i); if (sum * 2 > count) return i; } return -1; }
gdouble gimp_histogram_get_mean (GimpHistogram *histogram, GimpHistogramChannel channel, gint start, gint end) { gint i; gdouble mean = 0.0; gdouble count; g_return_val_if_fail (histogram != NULL, 0.0); /* the gray alpha channel is in slot 1 */ if (histogram->n_channels == 3 && channel == GIMP_HISTOGRAM_ALPHA) channel = 1; if (! histogram->values || start > end || (channel == GIMP_HISTOGRAM_RGB && histogram->n_channels < 4) || (channel != GIMP_HISTOGRAM_RGB && channel >= histogram->n_channels)) return 0.0; start = CLAMP (start, 0, 255); end = CLAMP (end, 0, 255); if (channel == GIMP_HISTOGRAM_RGB) { for (i = start; i <= end; i++) mean += (i * HISTOGRAM_VALUE (GIMP_HISTOGRAM_RED, i) + i * HISTOGRAM_VALUE (GIMP_HISTOGRAM_GREEN, i) + i * HISTOGRAM_VALUE (GIMP_HISTOGRAM_BLUE, i)); } else { for (i = start; i <= end; i++) mean += i * HISTOGRAM_VALUE (channel, i); } count = gimp_histogram_get_count (histogram, channel, start, end); if (count > 0.0) return mean / count; return mean; }
void gimp_levels_config_stretch_channel (GimpLevelsConfig *config, GimpHistogram *histogram, GimpHistogramChannel channel) { gdouble count; gdouble bias = 0.006; gint n_bins; gint i; g_return_if_fail (GIMP_IS_LEVELS_CONFIG (config)); g_return_if_fail (histogram != NULL); g_object_freeze_notify (G_OBJECT (config)); config->gamma[channel] = 1.0; config->low_output[channel] = 0.0; config->high_output[channel] = 1.0; n_bins = gimp_histogram_n_bins (histogram); count = gimp_histogram_get_count (histogram, channel, 0, n_bins - 1); if (count == 0.0) { config->low_input[channel] = 0.0; config->high_input[channel] = 0.0; } else { gdouble new_count; gdouble percentage; gdouble next_percentage; /* Set the low input */ new_count = 0.0; for (i = 0; i < (n_bins - 1); i++) { new_count += gimp_histogram_get_value (histogram, channel, i); percentage = new_count / count; next_percentage = (new_count + gimp_histogram_get_value (histogram, channel, i + 1)) / count; if (fabs (percentage - bias) < fabs (next_percentage - bias)) { config->low_input[channel] = (gdouble) (i + 1) / (n_bins - 1); break; } } /* Set the high input */ new_count = 0.0; for (i = (n_bins - 1); i > 0; i--) { new_count += gimp_histogram_get_value (histogram, channel, i); percentage = new_count / count; next_percentage = (new_count + gimp_histogram_get_value (histogram, channel, i - 1)) / count; if (fabs (percentage - bias) < fabs (next_percentage - bias)) { config->high_input[channel] = (gdouble) (i - 1) / (n_bins - 1); break; } } } g_object_notify (G_OBJECT (config), "gamma"); g_object_notify (G_OBJECT (config), "low-input"); g_object_notify (G_OBJECT (config), "high-input"); g_object_notify (G_OBJECT (config), "low-output"); g_object_notify (G_OBJECT (config), "high-output"); g_object_thaw_notify (G_OBJECT (config)); }