static void chroma_pre_process (const Babl *format, const gfloat *in, const gfloat *layer, gfloat *out, glong samples) { gfloat tmp[4 * samples], *layer_lab = tmp; gint i; babl_process (babl_fish (format, "CIE Lab alpha float"), in, out, samples); babl_process (babl_fish (format, "CIE Lab alpha float"), layer, layer_lab, samples); for (i = 0; i < samples; ++i) { gfloat A1 = out[4 * i + 1]; gfloat B1 = out[4 * i + 2]; gfloat c1 = hypot (A1, B1); if (c1 != 0) { gfloat A2 = layer_lab[4 * i + 1]; gfloat B2 = layer_lab[4 * i + 2]; gfloat c2 = hypot (A2, B2); gfloat A = c2 * A1 / c1; gfloat B = c2 * B1 / c1; out[4 * i + 1] = A; out[4 * i + 2] = B; } } babl_process (babl_fish ("CIE Lab alpha float", format), out, out, samples); }
static BablPalette * make_pal (const Babl *pal_space, const Babl *format, const void *data, int count) { BablPalette *pal = NULL; int bpp = babl_format_get_bytes_per_pixel (format); babl_assert (count > 0); pal = babl_malloc (sizeof (BablPalette)); pal->count = count; pal->format = format; pal->data = babl_malloc (bpp * count); pal->data_double = babl_malloc (4 * sizeof(double) * count); pal->data_u8 = babl_malloc (4 * sizeof(char) * count); pal->radii = babl_malloc (sizeof (BablPaletteRadius) * (pal->count - 1) * pal->count); memcpy (pal->data, data, bpp * count); babl_process (babl_fish (format, babl_format_with_space ("RGBA double", pal_space)), data, pal->data_double, count); babl_process (babl_fish (format, babl_format_with_space ("R'G'B'A u8", pal_space)), data, pal->data_u8, count); babl_palette_init_radii (pal); babl_palette_reset_hash (pal); return pal; }
static void init_path_instrumentation (FishPathInstrumentation *fpi, Babl *fmt_source, Babl *fmt_destination) { long ticks_start = 0; long ticks_end = 0; if (!fpi->fmt_rgba_double) { fpi->fmt_rgba_double = babl_format_new ( babl_model ("RGBA"), babl_type ("double"), babl_component ("R"), babl_component ("G"), babl_component ("B"), babl_component ("A"), NULL); } if (!fpi->test) fpi->test = test_create (); // <- test_create utiliza var static dentro de la función fpi->fish_rgba_to_source = babl_fish_reference (fpi->fmt_rgba_double, fmt_source); fpi->fish_reference = babl_fish_reference (fmt_source, fmt_destination); fpi->fish_destination_to_rgba = babl_fish_reference (fmt_destination, fpi->fmt_rgba_double); fpi->source = babl_calloc (NUM_TEST_PIXELS, fmt_source->format.bytes_per_pixel); fpi->destination = babl_calloc (NUM_TEST_PIXELS, fmt_destination->format.bytes_per_pixel); fpi->ref_destination = babl_calloc (NUM_TEST_PIXELS, fmt_destination->format.bytes_per_pixel); fpi->destination_rgba_double = babl_calloc (NUM_TEST_PIXELS, fpi->fmt_rgba_double->format.bytes_per_pixel); fpi->ref_destination_rgba_double = babl_calloc (NUM_TEST_PIXELS, fpi->fmt_rgba_double->format.bytes_per_pixel); /* create sourcebuffer from testbuffer in the correct format */ babl_process (fpi->fish_rgba_to_source, fpi->test, fpi->source, NUM_TEST_PIXELS); /* calculate the reference buffer of how it should be */ ticks_start = babl_ticks (); babl_process (fpi->fish_reference, fpi->source, fpi->ref_destination, NUM_TEST_PIXELS); ticks_end = babl_ticks (); fpi->reference_cost = babl_process_cost (ticks_start, ticks_end); /* transform the reference destination buffer to RGBA */ babl_process (fpi->fish_destination_to_rgba, fpi->ref_destination, fpi->ref_destination_rgba_double, NUM_TEST_PIXELS); }
static int test (void) { int components; int OK = 1; for (components = 1; components < 2048; components ++) { const Babl *fish; const Babl *src_fmt; const Babl *dst_fmt; int i; src_fmt = babl_format_n (babl_type ("float"), components); dst_fmt = babl_format_n (babl_type ("u8"), components); fish = babl_fish (src_fmt, dst_fmt); babl_process (fish, source_buf, destination_buf, PIXELS); for (i = 0; i < PIXELS * components; i++) { if (abs (destination_buf[i] - reference_buf[i]) > TOLERANCE) { babl_log ("%i-components, pixel %i component %i is %i should be %i", components, i / components, i % components, destination_buf[i], reference_buf[i]); OK = 0; } } } if (!OK) return -1; return 0; }
static void transfer_registration_color (GeglBuffer *src, GeglBuffer **dst, gint count) { GimpRGB color, test; GeglBufferIterator *gi; const Babl *src_format, *dst_format; gint i, src_bpp, dst_bpp; gdouble white; gimp_context_get_foreground (&color); white = 1.0; src_format = gegl_buffer_get_format (src); src_bpp = babl_format_get_bytes_per_pixel (src_format); dst_format = gegl_buffer_get_format (dst[0]); dst_bpp = babl_format_get_bytes_per_pixel (dst_format); gi = gegl_buffer_iterator_new (src, NULL, 0, NULL, GEGL_BUFFER_READ, GEGL_ABYSS_NONE); for (i = 0; i < count; i++) { gegl_buffer_iterator_add (gi, dst[i], NULL, 0, NULL, GEGL_BUFFER_READWRITE, GEGL_ABYSS_NONE); } while (gegl_buffer_iterator_next (gi)) { guint j, k; gpointer src_data, dst_data[MAX_EXTRACT_IMAGES]; src_data = gi->data[0]; for (j = 0; j < count; j++) dst_data[j] = gi->data[j+1]; for (k = 0; k < gi->length; k++) { gulong pos; pos = k * src_bpp; gimp_rgba_set_pixel (&test, src_format, ((guchar *)src_data) + pos); if (gimp_rgb_distance (&test, &color) < 1e-6) { for (j = 0; j < count; j++) { gpointer data; data = dst_data[j]; babl_process (babl_fish (babl_format ("Y double"), dst_format), &white, (guchar *)data + (k * dst_bpp), 1); } } } } }
void gimp_operation_layer_mode_blend_luminance (const gfloat *in, const gfloat *layer, gfloat *comp, gint samples) { static const Babl *fish; gfloat *scratch; gfloat *in_Y; gfloat *layer_Y; if (! fish) fish = babl_fish ("RGBA float", "Y float"); scratch = gegl_scratch_new (gfloat, 2 * samples); in_Y = scratch; layer_Y = scratch + samples; babl_process (fish, in, in_Y, samples); babl_process (fish, layer, layer_Y, samples); while (samples--) { if (layer[ALPHA] != 0.0f && in[ALPHA] != 0.0f) { gfloat ratio = safe_div (layer_Y[0], in_Y[0]); gint c; for (c = 0; c < 3; c ++) comp[c] = in[c] * ratio; } comp[ALPHA] = layer[ALPHA]; comp += 4; in += 4; layer += 4; in_Y ++; layer_Y ++; } gegl_scratch_free (scratch); }
static BablPalette *make_pal (const Babl *format, const void *data, int count) { BablPalette *pal = NULL; int bpp = babl_format_get_bytes_per_pixel (format); pal = babl_malloc (sizeof (BablPalette)); pal->count = count; pal->format = format; pal->data = babl_malloc (bpp * count); pal->data_double = babl_malloc (4 * sizeof(double) * count); pal->data_u8 = babl_malloc (4 * sizeof(char) * count); memcpy (pal->data, data, bpp * count); babl_process (babl_fish (format, babl_format ("RGBA double")), data, pal->data_double, count); babl_process (babl_fish (format, babl_format ("RGBA u8")), data, pal->data_u8, count); babl_palette_reset_hash (pal); return pal; }
static void color_pre_process (const Babl *format, const gfloat *in, const gfloat *layer, gfloat *out, glong samples) { gfloat tmp[4 * samples], *layer_lab = tmp; gint i; babl_process (babl_fish (format, "CIE L alpha float"), in, &out[2 * samples], samples); babl_process (babl_fish (format, "CIE Lab alpha float"), layer, layer_lab, samples); for (i = 0; i < samples; ++i) { out[4 * i + 0] = out[2 * samples + 2 * i + 0]; out[4 * i + 1] = layer_lab[4 * i + 1]; out[4 * i + 2] = layer_lab[4 * i + 2]; out[4 * i + 3] = out[2 * samples + 2 * i + 1]; } babl_process (babl_fish ("CIE Lab alpha float", format), out, out, samples); }
static int test (void) { const Babl *fish; int i; int OK = 1; fish = babl_fish ( babl_format_new ( babl_model ("Y"), babl_type ("float"), babl_component ("Y"), NULL ), babl_format_new ( babl_model ("RGB"), babl_type ("float"), babl_component ("R"), babl_component ("G"), babl_component ("B"), NULL ) ); babl_process (fish, grayscale_buf, rgb_buf, PIXELS); for (i = 0; i < PIXELS * 3; i++) { if (rgb_buf[i] != rgb_buf_ref[i]) { babl_log ("index %i is problematic : %f instead of %f", i, rgb_buf[i], rgb_buf_ref[i]); OK = 0; } } if (!OK) return -1; return 0; }
static BablPalette * default_palette (void) { static BablPalette pal; static int inited = 0; babl_mutex_lock (babl_format_mutex); if (inited) { babl_mutex_unlock (babl_format_mutex); return &pal; } init_ceil_sqrt_u8 (); memset (&pal, 0, sizeof (pal)); pal.count = 16; pal.format = babl_format ("R'G'B'A u8"); /* dynamically generated, so the default palette can not be fully static. */ pal.data = defpal_data; pal.data_double = defpal_double; pal.data_u8 = defpal_data; pal.radii = defpal_radii; babl_process (babl_fish (pal.format, babl_format ("RGBA double")), pal.data, pal.data_double, pal.count); babl_palette_init_radii (&pal); babl_palette_reset_hash (&pal); inited = 1; babl_mutex_unlock (babl_format_mutex); return &pal; }
static int test (void) { const Babl *fish; int i; int OK = 1; fish = babl_fish ( babl_format_new ( babl_model ("RGB"), babl_type ("u8"), babl_component ("R"), babl_component ("G"), babl_component ("B"), NULL ), babl_format_new ( babl_model ("RGB"), babl_type ("u8"), babl_component ("B"), babl_component ("G"), babl_component ("R"), NULL ) ); babl_process (fish, source_buf, destination_buf, PIXELS); for (i = 0; i < PIXELS * 3; i++) { if (abs (destination_buf[i] - reference_buf[i]) > TOLERANCE) { babl_log ("%2i (%2i%%3=%i, %2i/3=%i) is %i should be %i", i, i, i % 3, i, i / 3, destination_buf[i], reference_buf[i]); OK = 0; } } if (!OK) return -1; return 0; }
static int test (void) { int i; int OK = 1; babl_process (babl_fish (babl_format_with_space ("R'G'B' u8", babl_space("Apple")), "R'G'B' u8"), source_buf, destination_buf, PIXELS); for (i = 0; i < PIXELS * 3; i++) { if (abs (destination_buf[i] - reference_buf[i]) > TOLERANCE) { babl_log ("%2i (%2i%%3=%i, %2i/3=%i) is %i should be %i", i, i, i % 3, i, i / 3, destination_buf[i], reference_buf[i]); OK = 0; } } if (!OK) return -1; return 0; }
static BablPalette *default_palette (void) { static BablPalette pal; static int inited = 0; if (inited) return &pal; memset (&pal, 0, sizeof (pal)); inited = 1; pal.count = 16; pal.format = babl_format ("RGBA u8"); /* dynamically generated, so the default palette can not be fully static. */ pal.data = defpal_data; pal.data_double = defpal_double; pal.data_u8 = defpal_data; babl_process (babl_fish (pal.format, babl_format ("RGBA double")), pal.data, pal.data_double, pal.count); babl_palette_reset_hash (&pal); return &pal; }
/* Returns 2048 samples of the gradient. Each sample is (R'G'B'A float) or (Y'A float), depending on the drawable */ static gdouble * get_samples_gradient (gint32 drawable_id) { gchar *gradient_name; gint n_d_samples; gdouble *d_samples = NULL; gradient_name = gimp_context_get_gradient (); /* FIXME: "reverse" hardcoded to FALSE. */ gimp_gradient_get_uniform_samples (gradient_name, NSAMPLES, FALSE, &n_d_samples, &d_samples); g_free (gradient_name); if (!gimp_drawable_is_rgb (drawable_id)) { const Babl *format_src = babl_format ("R'G'B'A double"); const Babl *format_dst = babl_format ("Y'A double"); const Babl *fish = babl_fish (format_src, format_dst); babl_process (fish, d_samples, d_samples, NSAMPLES); } return d_samples; }
static void gimp_view_render_temp_buf_to_surface (GimpViewRenderer *renderer, GtkWidget *widget, GimpTempBuf *temp_buf, gint temp_buf_x, gint temp_buf_y, gint channel, GimpViewBG inside_bg, GimpViewBG outside_bg, cairo_surface_t *surface, gint surface_width, gint surface_height) { cairo_t *cr; gint x, y; gint width, height; const Babl *temp_buf_format; gint temp_buf_width; gint temp_buf_height; g_return_if_fail (temp_buf != NULL); g_return_if_fail (surface != NULL); temp_buf_format = gimp_temp_buf_get_format (temp_buf); temp_buf_width = gimp_temp_buf_get_width (temp_buf); temp_buf_height = gimp_temp_buf_get_height (temp_buf); /* Here are the different cases this functions handles correctly: * 1) Offset temp_buf which does not necessarily cover full image area * 2) Color conversion of temp_buf if it is gray and image is color * 3) Background check buffer for transparent temp_bufs * 4) Using the optional "channel" argument, one channel can be extracted * from a multi-channel temp_buf and composited as a grayscale * Prereqs: * 1) Grayscale temp_bufs have bytes == {1, 2} * 2) Color temp_bufs have bytes == {3, 4} * 3) If image is gray, then temp_buf should have bytes == {1, 2} */ cr = cairo_create (surface); if (outside_bg == GIMP_VIEW_BG_CHECKS || inside_bg == GIMP_VIEW_BG_CHECKS) { if (! renderer->pattern) renderer->pattern = gimp_cairo_checkerboard_create (cr, GIMP_CHECK_SIZE_SM, gimp_render_light_check_color (), gimp_render_dark_check_color ()); } switch (outside_bg) { case GIMP_VIEW_BG_CHECKS: cairo_set_source (cr, renderer->pattern); break; case GIMP_VIEW_BG_WHITE: cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); break; } cairo_paint (cr); if (! gimp_rectangle_intersect (0, 0, surface_width, surface_height, temp_buf_x, temp_buf_y, temp_buf_width, temp_buf_height, &x, &y, &width, &height)) { cairo_destroy (cr); return; } if (inside_bg != outside_bg && babl_format_has_alpha (temp_buf_format) && channel == -1) { cairo_rectangle (cr, x, y, width, height); switch (inside_bg) { case GIMP_VIEW_BG_CHECKS: cairo_set_source (cr, renderer->pattern); break; case GIMP_VIEW_BG_WHITE: cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); break; } cairo_fill (cr); } if (babl_format_has_alpha (temp_buf_format) && channel == -1) { GeglBuffer *src_buffer; GeglBuffer *dest_buffer; cairo_surface_t *alpha_surface; alpha_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); src_buffer = gimp_temp_buf_create_buffer (temp_buf); dest_buffer = gimp_cairo_surface_create_buffer (alpha_surface); if (! renderer->profile_transform) gimp_view_renderer_transform_create (renderer, widget, src_buffer, dest_buffer); if (renderer->profile_transform) { gimp_gegl_convert_color_transform (src_buffer, GEGL_RECTANGLE (x - temp_buf_x, y - temp_buf_y, width, height), renderer->profile_src_format, dest_buffer, GEGL_RECTANGLE (0, 0, 0, 0), renderer->profile_dest_format, renderer->profile_transform); } else { gegl_buffer_copy (src_buffer, GEGL_RECTANGLE (x - temp_buf_x, y - temp_buf_y, width, height), GEGL_ABYSS_NONE, dest_buffer, GEGL_RECTANGLE (0, 0, 0, 0)); } g_object_unref (src_buffer); g_object_unref (dest_buffer); cairo_surface_mark_dirty (alpha_surface); cairo_translate (cr, x, y); cairo_rectangle (cr, 0, 0, width, height); cairo_set_source_surface (cr, alpha_surface, 0, 0); cairo_fill (cr); cairo_surface_destroy (alpha_surface); } else if (channel == -1) { GeglBuffer *src_buffer; GeglBuffer *dest_buffer; cairo_surface_flush (surface); src_buffer = gimp_temp_buf_create_buffer (temp_buf); dest_buffer = gimp_cairo_surface_create_buffer (surface); if (! renderer->profile_transform) gimp_view_renderer_transform_create (renderer, widget, src_buffer, dest_buffer); if (renderer->profile_transform) { gimp_gegl_convert_color_transform (src_buffer, GEGL_RECTANGLE (x - temp_buf_x, y - temp_buf_y, width, height), renderer->profile_src_format, dest_buffer, GEGL_RECTANGLE (x, y, 0, 0), renderer->profile_dest_format, renderer->profile_transform); } else { gegl_buffer_copy (src_buffer, GEGL_RECTANGLE (x - temp_buf_x, y - temp_buf_y, width, height), GEGL_ABYSS_NONE, dest_buffer, GEGL_RECTANGLE (x, y, 0, 0)); } g_object_unref (src_buffer); g_object_unref (dest_buffer); cairo_surface_mark_dirty (surface); } else { const Babl *fish; const guchar *src; guchar *dest; gint dest_stride; gint bytes; gint rowstride; gint i; cairo_surface_flush (surface); bytes = babl_format_get_bytes_per_pixel (temp_buf_format); rowstride = temp_buf_width * bytes; src = gimp_temp_buf_get_data (temp_buf) + ((y - temp_buf_y) * rowstride + (x - temp_buf_x) * bytes); dest = cairo_image_surface_get_data (surface); dest_stride = cairo_image_surface_get_stride (surface); dest += y * dest_stride + x * 4; fish = babl_fish (temp_buf_format, babl_format ("cairo-RGB24")); for (i = y; i < (y + height); i++) { const guchar *s = src; guchar *d = dest; gint j; for (j = x; j < (x + width); j++, d += 4, s += bytes) { if (bytes > 2) { guchar pixel[4] = { s[channel], s[channel], s[channel], 255 }; babl_process (fish, pixel, d, 1); } else { guchar pixel[2] = { s[channel], 255 }; babl_process (fish, pixel, d, 1); } } src += rowstride; dest += dest_stride; } cairo_surface_mark_dirty (surface); } cairo_destroy (cr); }
static void get_path_instrumentation (FishPathInstrumentation *fpi, BablList *path, double *path_cost, double *ref_cost, double *path_error) { long ticks_start = 0; long ticks_end = 0; Babl *babl_source = fpi->source; Babl *babl_destination = fpi->destination; int source_bpp = 0; int dest_bpp = 0; switch (babl_source->instance.class_type) { case BABL_FORMAT: source_bpp = babl_source->format.bytes_per_pixel; break; case BABL_TYPE: source_bpp = babl_source->type.bits / 8; break; default: babl_log ("=eeek{%i}\n", babl_source->instance.class_type - BABL_MAGIC); } switch (babl_destination->instance.class_type) { case BABL_FORMAT: dest_bpp = babl_destination->format.bytes_per_pixel; break; case BABL_TYPE: dest_bpp = babl_destination->type.bits / 8; break; default: babl_log ("-eeek{%i}\n", babl_destination->instance.class_type - BABL_MAGIC); } if (!fpi->init_instrumentation_done) { /* this initialization can be done only once since the * source and destination formats do not change during * the search */ init_path_instrumentation (fpi, babl_source, babl_destination); fpi->init_instrumentation_done = 1; } /* calculate this path's view of what the result should be */ ticks_start = babl_ticks (); process_conversion_path (path, fpi->source, source_bpp, fpi->destination, dest_bpp, NUM_TEST_PIXELS); ticks_end = babl_ticks (); *path_cost = babl_process_cost (ticks_start, ticks_end); /* transform the reference and the actual destination buffers to RGBA * for comparison with each other */ babl_process (fpi->fish_destination_to_rgba, fpi->destination, fpi->destination_rgba_double, NUM_TEST_PIXELS); *path_error = babl_rel_avg_error (fpi->destination_rgba_double, fpi->ref_destination_rgba_double, NUM_TEST_PIXELS * 4); #if 0 fpi->fish_rgba_to_source->fish.processings--; fpi->fish_reference->fish.processings--; fpi->fish_destination_to_rgba->fish.processings -= 2; fpi->fish_rgba_to_source->fish.pixels -= NUM_TEST_PIXELS; fpi->fish_reference->fish.pixels -= NUM_TEST_PIXELS; fpi->fish_destination_to_rgba->fish.pixels -= 2 * NUM_TEST_PIXELS; #endif *ref_cost = fpi->reference_cost; }
/** * gimp_color_transform_process_buffer: * @transform: * @src_format: * @src_rect: * @dest_format: * @dest_rect: * * This function transforms buffer into another buffer. * * Since: 2.10 **/ void gimp_color_transform_process_buffer (GimpColorTransform *transform, GeglBuffer *src_buffer, const GeglRectangle *src_rect, GeglBuffer *dest_buffer, const GeglRectangle *dest_rect) { GimpColorTransformPrivate *priv; GeglBufferIterator *iter; gint total_pixels; gint done_pixels = 0; g_return_if_fail (GIMP_IS_COLOR_TRANSFORM (transform)); g_return_if_fail (GEGL_IS_BUFFER (src_buffer)); g_return_if_fail (GEGL_IS_BUFFER (dest_buffer)); priv = transform->priv; if (src_rect) { total_pixels = src_rect->width * src_rect->height; } else { total_pixels = (gegl_buffer_get_width (src_buffer) * gegl_buffer_get_height (src_buffer)); } if (src_buffer != dest_buffer) { const Babl *fish = NULL; if (babl_format_has_alpha (priv->dest_format)) fish = babl_fish (priv->src_format, priv->dest_format); iter = gegl_buffer_iterator_new (src_buffer, src_rect, 0, priv->src_format, GEGL_ACCESS_READ, GEGL_ABYSS_NONE); gegl_buffer_iterator_add (iter, dest_buffer, dest_rect, 0, priv->dest_format, GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) { /* make sure the alpha channel is copied too, lcms doesn't copy it */ if (fish) babl_process (fish, iter->data[0], iter->data[1], iter->length); cmsDoTransform (priv->transform, iter->data[0], iter->data[1], iter->length); done_pixels += iter->roi[0].width * iter->roi[0].height; g_signal_emit (transform, gimp_color_transform_signals[PROGRESS], 0, (gdouble) done_pixels / (gdouble) total_pixels); } } else { iter = gegl_buffer_iterator_new (src_buffer, src_rect, 0, priv->src_format, GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) { cmsDoTransform (priv->transform, iter->data[0], iter->data[0], iter->length); done_pixels += iter->roi[0].width * iter->roi[0].height; g_signal_emit (transform, gimp_color_transform_signals[PROGRESS], 0, (gdouble) done_pixels / (gdouble) total_pixels); } } g_signal_emit (transform, gimp_color_transform_signals[PROGRESS], 0, 1.0); }
/** * gimp_color_transform_process_pixels: * @transform: * @src_format: * @src_pixels: * @dest_format: * @dest_pixels: * @length: * * This function transforms a contiguous line of pixels. * * Since: 2.10 **/ void gimp_color_transform_process_pixels (GimpColorTransform *transform, const Babl *src_format, gconstpointer src_pixels, const Babl *dest_format, gpointer dest_pixels, gsize length) { GimpColorTransformPrivate *priv; gpointer *src; gpointer *dest; g_return_if_fail (GIMP_IS_COLOR_TRANSFORM (transform)); g_return_if_fail (src_format != NULL); g_return_if_fail (src_pixels != NULL); g_return_if_fail (dest_format != NULL); g_return_if_fail (dest_pixels != NULL); priv = transform->priv; if (src_format != priv->src_format) { src = g_malloc (length * babl_format_get_bytes_per_pixel (priv->src_format)); babl_process (babl_fish (src_format, priv->src_format), src_pixels, src, length); } else { src = (gpointer) src_pixels; } if (dest_format != priv->dest_format) { dest = g_malloc (length * babl_format_get_bytes_per_pixel (priv->dest_format)); } else { dest = dest_pixels; } /* copy the alpha channel */ if (src != dest && babl_format_has_alpha (dest_format)) babl_process (babl_fish (src_format, priv->dest_format), src, dest, length); cmsDoTransform (priv->transform, src, dest, length); if (src_format != priv->src_format) { g_free (src); } if (dest_format != priv->dest_format) { babl_process (babl_fish (priv->dest_format, dest_format), dest, dest_pixels, length); g_free (dest); } }
static void inline gegl_sampler_get_pixel (GeglSampler *sampler, gint x, gint y, gpointer data, GeglAbyssPolicy repeat_mode) { GeglSamplerNearest *nearest_sampler = (GeglSamplerNearest*)(sampler); GeglBuffer *buffer = sampler->buffer; const GeglRectangle *abyss = &buffer->abyss; guchar *buf = data; if (y < abyss->y || x < abyss->x || y >= abyss->y + abyss->height || x >= abyss->x + abyss->width) { switch (repeat_mode) { case GEGL_ABYSS_CLAMP: x = CLAMP (x, abyss->x, abyss->x+abyss->width-1); y = CLAMP (y, abyss->y, abyss->y+abyss->height-1); break; case GEGL_ABYSS_LOOP: x = abyss->x + GEGL_REMAINDER (x - abyss->x, abyss->width); y = abyss->y + GEGL_REMAINDER (y - abyss->y, abyss->height); break; case GEGL_ABYSS_BLACK: { gfloat color[4] = {0.0, 0.0, 0.0, 1.0}; babl_process (babl_fish (gegl_babl_rgba_linear_float (), sampler->format), color, buf, 1); return; } case GEGL_ABYSS_WHITE: { gfloat color[4] = {1.0, 1.0, 1.0, 1.0}; babl_process (babl_fish (gegl_babl_rgba_linear_float (), sampler->format), color, buf, 1); return; } default: case GEGL_ABYSS_NONE: memset (buf, 0x00, babl_format_get_bytes_per_pixel (sampler->format)); return; } } gegl_buffer_lock (sampler->buffer); { gint tile_width = buffer->tile_width; gint tile_height = buffer->tile_height; gint tiledy = y + buffer->shift_y; gint tiledx = x + buffer->shift_x; gint indice_x = gegl_tile_indice (tiledx, tile_width); gint indice_y = gegl_tile_indice (tiledy, tile_height); GeglTile *tile = nearest_sampler->hot_tile; if (!(tile && tile->x == indice_x && tile->y == indice_y)) { if (gegl_config_threads()>1) g_rec_mutex_lock (&buffer->tile_storage->mutex); if (tile) gegl_tile_unref (tile); tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer), indice_x, indice_y, 0); nearest_sampler->hot_tile = tile; if (gegl_config_threads()>1) g_rec_mutex_unlock (&buffer->tile_storage->mutex); } if (tile) { gint tile_origin_x = indice_x * tile_width; gint tile_origin_y = indice_y * tile_height; gint offsetx = tiledx - tile_origin_x; gint offsety = tiledy - tile_origin_y; guchar *tp = gegl_tile_get_data (tile) + (offsety * tile_width + offsetx) * nearest_sampler->buffer_bpp; babl_process (sampler->fish, tp, buf, 1); } } gegl_buffer_unlock (sampler->buffer); }
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]); } } } }
void gegl_sampler_cubic_get (GeglSampler *self, gdouble x, gdouble y, void *output) { GeglSamplerCubic *cubic = (GeglSamplerCubic*)(self); GeglRectangle context_rect; const gint offsets[16]={-4-64*4, 4, 4, 4, (64-3)*4, 4, 4, 4, (64-3)*4, 4, 4, 4, (64-3)*4, 4, 4, 4}; gfloat *sampler_bptr; gfloat factor; #ifdef HAS_G4FLOAT g4float newval4 = g4float_zero; gfloat *newval = &newval4; #else gfloat newval[4] = {0.0, 0.0, 0.0, 0.0}; #endif gint u,v; gint dx,dy; gint i; context_rect = self->context_rect; dx = (gint) x; dy = (gint) y; sampler_bptr = gegl_sampler_get_ptr (self, dx, dy); #ifdef HAS_G4FLOAT if (G_LIKELY (gegl_cpu_accel_get_support () & (GEGL_CPU_ACCEL_X86_SSE| GEGL_CPU_ACCEL_X8&_MMX))) { for (v=dy+context_rect.y, i=0; v < dy+context_rect.y+context_rect.height ; v++) for (u=dx+context_rect.x ; u < dx+context_rect.x+context_rect.width ; u++, i++) { sampler_bptr += offsets[i]; factor = cubicKernel (y - v, cubic->b, cubic->c) * cubicKernel (x - u, cubic->b, cubic->c); newval4 += g4float_mul(&sampler_bptr[0], factor); } } else #endif { for (v=dy+context_rect.y, i=0; v < dy+context_rect.y+context_rect.height ; v++) for (u=dx+context_rect.x ; u < dx+context_rect.x+context_rect.width ; u++, i++) { /*sampler_bptr = gegl_sampler_get_from_buffer (self, u, v);*/ sampler_bptr += offsets[i]; factor = cubicKernel (y - v, cubic->b, cubic->c) * cubicKernel (x - u, cubic->b, cubic->c); newval[0] += factor * sampler_bptr[0]; newval[1] += factor * sampler_bptr[1]; newval[2] += factor * sampler_bptr[2]; newval[3] += factor * sampler_bptr[3]; } } babl_process (self->fish, newval, output, 1); }
void gegl_sampler_lanczos_get (GeglSampler *self, gdouble x, gdouble y, GeglMatrix2 *scale, void *output) { GeglSamplerLanczos *lanczos = GEGL_SAMPLER_LANCZOS (self); GeglRectangle context_rect = self->context_rect[0]; gfloat *sampler_bptr; gdouble x_sum, y_sum; gfloat newval[4] = {0.0, 0.0, 0.0, 0.0}; gint i, j; gint spp = lanczos->lanczos_spp; gint width = lanczos->lanczos_width; gint width2 = context_rect.width; gint dx,dy; gint u,v; /* FIXME: move the initialization of these arrays into the _prepare function * to speed up actual resampling */ gfloat *x_kernel, /* 1-D kernels of Lanczos window coeffs */ *y_kernel; x_kernel = g_newa (gfloat, width2); y_kernel = g_newa (gfloat, width2); self->interpolate_format = babl_format ("RaGaBaA float"); dx = (gint) ((x - ((gint) x)) * spp + 0.5); dy = (gint) ((y - ((gint) y)) * spp + 0.5); /* fill 1D kernels */ for (x_sum = y_sum = 0.0, i = width; i >= -width; i--) { gint pos = i * spp; x_sum += x_kernel[width + i] = lanczos->lanczos_lookup[ABS (dx - pos)]; y_sum += y_kernel[width + i] = lanczos->lanczos_lookup[ABS (dy - pos)]; } /* normalise the weighted arrays */ for (i = 0; i < width2; i++) { x_kernel[i] /= x_sum; y_kernel[i] /= y_sum; } dx = (gint) x; dy = (gint) y; for (v=dy+context_rect.y, j = 0; v < dy+context_rect.y+context_rect.height; j++, v++) for (u=dx+context_rect.x, i = 0; u < dx+context_rect.x+context_rect.width; i++, u++) { sampler_bptr = gegl_sampler_get_from_buffer (self, u, v); newval[0] += y_kernel[j] * x_kernel[i] * sampler_bptr[0]; newval[1] += y_kernel[j] * x_kernel[i] * sampler_bptr[1]; newval[2] += y_kernel[j] * x_kernel[i] * sampler_bptr[2]; newval[3] += y_kernel[j] * x_kernel[i] * sampler_bptr[3]; } babl_process (self->fish, newval, output, 1); }