static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); GeglRectangle in_rect = *gegl_buffer_get_extent (input); GeglRectangle out_rect = *gegl_buffer_get_extent (output); PixelDuster *duster = pixel_duster_new (input, output, &in_rect, &out_rect, o->seek_distance, 1, o->min_neigh, o->min_iter, o->chance_try, o->chance_retry, 1.0, 1.0, operation); seed_db (duster); gegl_buffer_copy (input, NULL, GEGL_ABYSS_NONE, output, NULL); fprintf (stderr, "adding transparent probes"); pixel_duster_add_probes_for_transparent (duster); fprintf (stderr, "\n"); pixel_duster_fill (duster); pixel_duster_destroy (duster); return TRUE; }
static gboolean test_opacity_common (const Babl *in_format, const Babl *out_format) { /* Validate that gegl:opacity produces out_format when given in_format */ gboolean result = TRUE; GeglNode *ptn, *src, *opacity, *sink; GeglBuffer *src_buffer; GeglBuffer *sink_buffer = NULL; src_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, 10, 10), in_format); ptn = gegl_node_new (); src = gegl_node_new_child (ptn, "operation", "gegl:buffer-source", "buffer", src_buffer, NULL); opacity = gegl_node_new_child (ptn, "operation", "gegl:opacity", "value", 0.5, NULL); sink = gegl_node_new_child (ptn, "operation", "gegl:buffer-sink", "buffer", &sink_buffer, "format", NULL, NULL); gegl_node_link_many (src, opacity, sink, NULL); gegl_node_blit_buffer (sink, NULL, NULL, 0, GEGL_ABYSS_NONE); if (out_format != gegl_buffer_get_format (sink_buffer)) { printf ("Got %s expected %s\n", babl_get_name (gegl_buffer_get_format (sink_buffer)), babl_get_name (out_format)); result = FALSE; } if (!gegl_rectangle_equal (gegl_buffer_get_extent (src_buffer), gegl_buffer_get_extent (sink_buffer))) result = FALSE; g_object_unref (ptn); g_object_unref (src_buffer); g_object_unref (sink_buffer); return result; }
static int extract_mid_col (GeglBuffer *buffer, void *rgb_mid_col, int samples) { GeglRectangle mid_col; mid_col.x = 0; mid_col.y = gegl_buffer_get_extent (buffer)-> height * 1.0 * samples / gegl_buffer_get_extent (buffer)->width / 2.0; mid_col.height = 1; mid_col.width = samples; gegl_buffer_get (video_frame, &mid_col, 1.0 * samples / gegl_buffer_get_extent (buffer)->width, babl_format ("RGBA u8"), rgb_mid_col, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); return 3 * samples; }
static int extract_mid_row (GeglBuffer *buffer, void *rgb_mid_row, int samples) { GeglRectangle mid_row; mid_row.width = 1; mid_row.height = samples; mid_row.x = gegl_buffer_get_extent (buffer)-> width * 1.0 * samples / gegl_buffer_get_extent (buffer)->height / 2.0; mid_row.y = 0; gegl_buffer_get (buffer, &mid_row, 1.0 * samples / gegl_buffer_get_extent (buffer)->height, babl_format ("RGBA u8"), rgb_mid_row, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); return 3 * samples; }
static GeglRectangle get_bounding_box (GeglOperation *operation) { GeglRectangle result = {0,0,0,0}; GeglBuffer *buffer = ensure_buffer (operation); result = *gegl_buffer_get_extent (GEGL_BUFFER (buffer)); return result; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); WarpPrivate *priv = (WarpPrivate*) o->chant_data; gdouble dist; gdouble stamps; gdouble spacing = MAX (o->size * 0.01, 0.5); /*1% spacing for starters*/ GeglPathPoint prev, next, lerp; gulong i; GeglPathList *event; priv->buffer = gegl_buffer_dup (input); event = gegl_path_get_path (o->stroke); prev = *(event->d.point); while (event->next) { event = event->next; next = *(event->d.point); dist = gegl_path_point_dist (&next, &prev); stamps = dist / spacing; if (stamps < 1) { stamp (o, result, next.x, next.y); prev = next; } else { for (i = 0; i < stamps; i++) { gegl_path_point_lerp (&lerp, &prev, &next, (i * spacing) / dist); stamp (o, result, lerp.x, lerp.y); } prev = lerp; } } /* Affect the output buffer */ gegl_buffer_copy (priv->buffer, result, output, result); gegl_buffer_set_extent (output, gegl_buffer_get_extent (input)); g_object_unref (priv->buffer); /* prepare for the recomputing of the op */ priv->last_point_set = FALSE; return TRUE; }
static gboolean test_buffer_sink_001 (void) { /* Validate that gegl:buffer-sink doesn't modify the format of its input */ gboolean result = TRUE; GeglNode *ptn, *src, *sink; GeglBuffer *src_buffer; GeglBuffer *sink_buffer = NULL; src_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, 10, 10), babl_format ("RGB u8")); ptn = gegl_node_new (); src = gegl_node_new_child (ptn, "operation", "gegl:buffer-source", "buffer", src_buffer, NULL); sink = gegl_node_new_child (ptn, "operation", "gegl:buffer-sink", "buffer", &sink_buffer, "format", NULL, NULL); gegl_node_link_many (src, sink, NULL); gegl_node_blit_buffer (sink, NULL, NULL, 0, GEGL_ABYSS_NONE); if (gegl_buffer_get_format (src_buffer) != gegl_buffer_get_format (sink_buffer)) result = FALSE; if (!gegl_rectangle_equal (gegl_buffer_get_extent (src_buffer), gegl_buffer_get_extent (sink_buffer))) result = FALSE; g_object_unref (ptn); g_object_unref (src_buffer); g_object_unref (sink_buffer); return result; }
TEST () { GeglBuffer *buffer, *buffer2; GeglRectangle bound = {0, 0, 20, 20}; test_start (); buffer = gegl_buffer_new (&bound, babl_format ("Y float")); vgrad (buffer); { GeglRectangle rect = *gegl_buffer_get_extent(buffer); rect.width-=10; rect.height-=10; buffer2 = gegl_buffer_new (gegl_buffer_get_extent (buffer), gegl_buffer_get_format (buffer)); gegl_buffer_copy (buffer, &rect, buffer2, &rect); } print_buffer (buffer2); g_object_unref (buffer); g_object_unref (buffer2); test_end (); }
static GeglRectangle get_bounding_box (GeglOperation *operation) { GeglRectangle result = {0,0,0,0}; GeglProperties *o = GEGL_PROPERTIES (operation); if (!o->buffer) { return result; } result = *gegl_buffer_get_extent (GEGL_BUFFER (o->buffer)); return result; }
void gegl_apply_op_valist (GeglBuffer *buffer, const gchar *first_property_name, va_list var_args) { GeglBuffer *tempbuf = NULL; GeglNode *node; GeglNode *source; GeglNode *sink; g_return_if_fail (GEGL_IS_BUFFER (buffer)); g_object_ref (buffer); source = gegl_node_new_child (NULL, "operation", "gegl:buffer-source", "buffer", buffer, NULL); node = gegl_node_new_child (NULL, "operation", first_property_name, NULL); if (!GEGL_IS_OPERATION_POINT_FILTER (node->operation)) { tempbuf = gegl_buffer_new (gegl_buffer_get_extent (buffer), gegl_buffer_get_format (buffer)); sink = gegl_node_new_child (NULL, "operation", "gegl:write-buffer", "buffer", tempbuf, NULL); } else { sink = gegl_node_new_child (NULL, "operation", "gegl:write-buffer", "buffer", buffer, NULL); } gegl_node_link_many (source, node, sink, NULL); gegl_node_set_props (node, var_args); gegl_node_process (sink); g_object_unref (source); g_object_unref (node); g_object_unref (sink); if (tempbuf) { gegl_buffer_copy (tempbuf, NULL, buffer, NULL); g_object_unref (tempbuf); } g_object_unref (buffer); }
gboolean gegl_can_do_inplace_processing (GeglOperation *operation, GeglBuffer *input, const GeglRectangle *result) { if (!input) return FALSE; if (gegl_object_get_has_forked (G_OBJECT (input))) return FALSE; if (gegl_buffer_get_format (input) == gegl_operation_get_format (operation, "output") && gegl_rectangle_contains (gegl_buffer_get_extent (input), result)) return TRUE; return FALSE; }
static void copy_one_component (GeglBuffer *src, GeglBuffer *dst, const gchar *model, const COMPONENT component, gboolean clamp) { const Babl *component_format, *dst_format; GeglBuffer *temp; const GeglRectangle *extent; /* We are working in linear double precison*/ component_format = babl_format_new (babl_model (model), babl_type ("double"), babl_component (component.babl_name), NULL); /* We need to enforce linearity here * If the output is "Y'", the ouput of temp is already ok * If the output is "Y" , it will enforce gamma-decoding. * A bit tricky and suboptimal... */ if (component.perceptual_channel) dst_format = babl_format ("Y' double"); else dst_format = babl_format ("Y double"); extent = gegl_buffer_get_extent (src); temp = gegl_buffer_new (extent, dst_format); /* we want to copy the component as is */ gegl_buffer_set_format (temp, component_format); gegl_buffer_copy (src, NULL, temp, NULL); if (component.range_min != 0.0 || component.range_max != 1.0 || clamp) cpn_affine_transform_clamp (temp, component.range_min, component.range_max); /* This is our new "Y(') double" component buffer */ gegl_buffer_set_format (temp, NULL); /* Now we let babl convert it back to the format that dst needs */ gegl_buffer_copy (temp, NULL, dst, NULL); g_object_unref (temp); }
static void gimp_channel_combine_end (GimpChannel *mask, GimpChannelCombineData *data) { GeglBuffer *buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)); gegl_buffer_set_abyss (buffer, gegl_buffer_get_extent (buffer)); gegl_buffer_thaw_changed (buffer); mask->bounds_known = data->bounds_known; if (data->bounds_known) { mask->empty = data->empty; if (data->empty) { mask->x1 = 0; mask->y1 = 0; mask->x2 = gimp_item_get_width (GIMP_ITEM (mask)); mask->y2 = gimp_item_get_height (GIMP_ITEM (mask)); } else { mask->x1 = data->bounds.x; mask->y1 = data->bounds.y; mask->x2 = data->bounds.x + data->bounds.width; mask->y2 = data->bounds.y + data->bounds.height; } } gimp_drawable_update (GIMP_DRAWABLE (mask), data->rect.x, data->rect.y, data->rect.width, data->rect.height); }
/* this should only be possible if this buffer matches all the buffers down to * storage, all of those parent buffers would change size as well, no tiles * would be voided as a result of changing the extent. */ gboolean gegl_buffer_set_extent (GeglBuffer *buffer, const GeglRectangle *extent) { g_return_val_if_fail(GEGL_IS_BUFFER(buffer), FALSE); (*(GeglRectangle*)gegl_buffer_get_extent (buffer))=*extent; if ((GeglBufferHeader*)(gegl_buffer_backend (buffer)->priv->header)) { GeglBufferHeader *header = ((GeglBufferHeader*)(gegl_buffer_backend (buffer)->priv->header)); header->x = buffer->extent.x; header->y = buffer->extent.y; header->width = buffer->extent.width; header->height = buffer->extent.height; } if (buffer->abyss_tracks_extent) { buffer->abyss = *extent; } return TRUE; }
static int extract_thumb (GeglBuffer *buffer, void *rgb_thumb, int samples, int samples2) { GeglRectangle thumb_scan; static float vpos = 0.0; if (horizontal) { thumb_scan.y = 0; thumb_scan.x = gegl_buffer_get_extent (buffer)-> width * 1.0 * samples / gegl_buffer_get_extent (buffer)->width * vpos; vpos += (1.0/samples2); if (vpos > 1.0) vpos = 0.0; thumb_scan.width = 1; thumb_scan.height = samples; } else { thumb_scan.x = 0; thumb_scan.y = gegl_buffer_get_extent (buffer)-> height * 1.0 * samples / gegl_buffer_get_extent (buffer)->width * vpos; vpos += (1.0/samples2); if (vpos > 1.0) vpos = 0.0; thumb_scan.height = 1; thumb_scan.width = samples; } gegl_buffer_get (buffer, &thumb_scan, horizontal?1.0 * samples/ gegl_buffer_get_extent (buffer)->height: 1.0 * samples/ gegl_buffer_get_extent (buffer)->width, babl_format ("RGBA u8"), (void*)rgb_thumb, //(void*)&(info->rgb_thumb)[0], GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); return 3 * samples; }
static void copy_through_lens (LensCorrectionModel *oip, GeglBuffer *src, GeglBuffer *dst) { const GeglRectangle *src_extent; const GeglRectangle *dst_extent; gfloat *src_buf; gfloat *dst_buf; gint x,y; /* Coordinate of current dst pixel. */ gint rgb; /* Color channel of dst pixel being processed. */ gint doffset; /* Buffer offset of current dst pixel. */ gint tmpx, tmpy, toff; ChannelCorrectionModel *ccm[3]; /* Allow access to red,green,blue models in loop. */ src_extent = gegl_buffer_get_extent (src); #ifdef TRACE g_warning ("> copy_through_lens src_extent = %dx%d+%d+%d", src_extent->width, src_extent->height, src_extent->x,src_extent->y); #endif if (dst == NULL) { #ifdef TRACE g_warning (" dst is NULL"); g_warning ("< copy_through_lens"); #endif return; } dst_extent = gegl_buffer_get_extent (dst); if (dst_extent == NULL) { #ifdef TRACE g_warning (" dst_extent is NULL"); g_warning ("< copy_through_lens"); #endif return; } /* Get src pixels. */ src_buf = g_new0 (gfloat, gegl_buffer_get_pixel_count (src) * 3); gegl_buffer_get (src, 1.0, NULL, babl_format ("RGB float"), src_buf, GEGL_AUTO_ROWSTRIDE); /* Get buffer in which to place dst pixels. */ dst_buf = g_new0 (gfloat, gegl_buffer_get_pixel_count (dst) * 3); /* Compute each dst pixel in turn and store into dst buffer. */ ccm[0] = &oip->red; ccm[1] = &oip->green; ccm[2] = &oip->blue; doffset = 0; for (y=dst_extent->y; y<dst_extent->height + dst_extent->y; y++) { for (x=dst_extent->x; x<dst_extent->width + dst_extent->x; x++) { for (rgb = 0; rgb < 3; rgb++) { gfloat gx, gy; gfloat val = 0.0; gint xx, yy; gfloat wx[2], wy[2], wt = 0.0; find_src_pixel (oip, ccm[rgb], (gfloat)x, (gfloat)y, &gx, &gy); tmpx = gx; tmpy = gy; wx[1] = gx - tmpx; wx[0] = 1.0 - wx[1]; wy[1] = gy - tmpy; wy[0] = 1.0 - wy[1]; tmpx -= src_extent->x; tmpy -= src_extent->y; toff = (tmpy * ROW + tmpx) * 3; for (xx = 0; xx < 2; xx++) { for (yy = 0; yy < 2; yy++) { if (tmpx+xx >= 0 && tmpx+xx < src_extent->width && tmpy+yy >= 0 && tmpy+yy < src_extent->height) { val += src_buf[toff+(yy*ROW+xx)*3+rgb] * wx[xx] * wy[yy]; wt += wx[xx] * wy[yy]; } } } if (wt <= 0) { g_warning ("gegl_lens_correct: mapped pixel %g,%g not in %dx%d+%d+%d", gx, gy, src_extent->width, src_extent->height, src_extent->x, src_extent->y); g_warning (" dst = %dx%d+%d+%d", dst_extent->width, dst_extent->height, dst_extent->x,dst_extent->y); dst_buf [doffset+rgb] = 0.0; } else { dst_buf [doffset+rgb] = val / wt; } } doffset+=3; } } /* Store dst pixels. */ gegl_buffer_set (dst, NULL, babl_format ("RGB float"), dst_buf, GEGL_AUTO_ROWSTRIDE); /* Free acquired storage. */ g_free (src_buf); g_free (dst_buf); #ifdef TRACE g_warning ("< copy_through_lens"); #endif }
static void gimp_n_point_deformation_tool_start (GimpNPointDeformationTool *npd_tool, GimpDisplay *display) { GimpTool *tool = GIMP_TOOL (npd_tool); GimpNPointDeformationOptions *npd_options; GimpImage *image; GeglBuffer *source_buffer; GeglBuffer *preview_buffer; NPDModel *model; npd_options = GIMP_N_POINT_DEFORMATION_TOOL_GET_OPTIONS (npd_tool); gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display); image = gimp_display_get_image (display); tool->display = display; tool->drawable = gimp_image_get_active_drawable (image); npd_tool->active = TRUE; /* create GEGL graph */ source_buffer = gimp_drawable_get_buffer (tool->drawable); preview_buffer = gegl_buffer_new (gegl_buffer_get_extent (source_buffer), babl_format ("cairo-ARGB32")); npd_tool->graph = gegl_node_new (); npd_tool->source = gegl_node_new_child (npd_tool->graph, "operation", "gegl:buffer-source", "buffer", source_buffer, NULL); npd_tool->npd_node = gegl_node_new_child (npd_tool->graph, "operation", "gegl:npd", NULL); npd_tool->sink = gegl_node_new_child (npd_tool->graph, "operation", "gegl:write-buffer", "buffer", preview_buffer, NULL); gegl_node_link_many (npd_tool->source, npd_tool->npd_node, npd_tool->sink, NULL); /* initialize some options */ g_object_set (G_OBJECT (npd_options), "mesh-visible", TRUE, NULL); gimp_n_point_deformation_options_set_sensitivity (npd_options, TRUE); /* compute and get model */ gegl_node_process (npd_tool->npd_node); gegl_node_get (npd_tool->npd_node, "model", &model, NULL); npd_tool->model = model; npd_tool->preview_buffer = preview_buffer; npd_tool->selected_cp = NULL; npd_tool->hovering_cp = NULL; npd_tool->selected_cps = NULL; npd_tool->rubber_band = FALSE; npd_tool->lattice_points = g_new (GimpVector2, 5 * model->hidden_model->num_of_bones); gimp_item_get_offset (GIMP_ITEM (tool->drawable), &npd_tool->offset_x, &npd_tool->offset_y); gimp_npd_debug (("offset: %f %f\n", npd_tool->offset_x, npd_tool->offset_y)); gimp_draw_tool_start (GIMP_DRAW_TOOL (npd_tool), display); gimp_n_point_deformation_tool_perform_deformation (npd_tool); /* hide original image */ gimp_item_set_visible (GIMP_ITEM (tool->drawable), FALSE, FALSE); gimp_image_flush (image); /* create and start a deformation thread */ npd_tool->deform_thread = g_thread_new ("deform thread", (GThreadFunc) gimp_n_point_deformation_tool_deform_thread_func, npd_tool); /* create and start canvas update timeout */ npd_tool->draw_timeout_id = gdk_threads_add_timeout_full (G_PRIORITY_DEFAULT_IDLE, GIMP_NPD_DRAW_INTERVAL, (GSourceFunc) gimp_n_point_deformation_tool_canvas_update_timeout, npd_tool, NULL); }
static int gimp_mypaint_surface_draw_dab (MyPaintSurface *base_surface, float x, float y, float radius, float color_r, float color_g, float color_b, float opaque, float hardness, float color_a, float aspect_ratio, float angle, float lock_alpha, float colorize) { GimpMybrushSurface *surface = (GimpMybrushSurface *)base_surface; GeglBufferIterator *iter; GeglRectangle dabRect; GimpComponentMask component_mask = surface->component_mask; const float one_over_radius2 = 1.0f / (radius * radius); const double angle_rad = angle / 360 * 2 * M_PI; const float cs = cos(angle_rad); const float sn = sin(angle_rad); float normal_mode; float segment1_slope; float segment2_slope; float r_aa_start; hardness = CLAMP (hardness, 0.0f, 1.0f); segment1_slope = -(1.0f / hardness - 1.0f); segment2_slope = -hardness / (1.0f - hardness); aspect_ratio = MAX (1.0f, aspect_ratio); r_aa_start = radius - 1.0f; r_aa_start = MAX (r_aa_start, 0); r_aa_start = (r_aa_start * r_aa_start) / aspect_ratio; normal_mode = opaque * (1.0f - colorize); colorize = opaque * colorize; /* FIXME: This should use the real matrix values to trim aspect_ratio dabs */ dabRect = calculate_dab_roi (x, y, radius); gegl_rectangle_intersect (&dabRect, &dabRect, gegl_buffer_get_extent (surface->buffer)); if (dabRect.width <= 0 || dabRect.height <= 0) return 0; gegl_rectangle_bounding_box (&surface->dirty, &surface->dirty, &dabRect); iter = gegl_buffer_iterator_new (surface->buffer, &dabRect, 0, babl_format ("R'G'B'A float"), GEGL_BUFFER_READWRITE, GEGL_ABYSS_NONE); if (surface->paint_mask) { GeglRectangle mask_roi = dabRect; mask_roi.x -= surface->paint_mask_x; mask_roi.y -= surface->paint_mask_y; gegl_buffer_iterator_add (iter, surface->paint_mask, &mask_roi, 0, babl_format ("Y float"), GEGL_ACCESS_READ, GEGL_ABYSS_NONE); } while (gegl_buffer_iterator_next (iter)) { float *pixel = (float *)iter->data[0]; float *mask; int iy, ix; if (surface->paint_mask) mask = iter->data[1]; else mask = NULL; for (iy = iter->roi[0].y; iy < iter->roi[0].y + iter->roi[0].height; iy++) { for (ix = iter->roi[0].x; ix < iter->roi[0].x + iter->roi[0].width; ix++) { float rr, base_alpha, alpha, dst_alpha, r, g, b, a; if (radius < 3.0f) rr = calculate_rr_antialiased (ix, iy, x, y, aspect_ratio, sn, cs, one_over_radius2, r_aa_start); else rr = calculate_rr (ix, iy, x, y, aspect_ratio, sn, cs, one_over_radius2); base_alpha = calculate_alpha_for_rr (rr, hardness, segment1_slope, segment2_slope); alpha = base_alpha * normal_mode; if (mask) alpha *= *mask; dst_alpha = pixel[ALPHA]; /* a = alpha * color_a + dst_alpha * (1.0f - alpha); * which converts to: */ a = alpha * (color_a - dst_alpha) + dst_alpha; r = pixel[RED]; g = pixel[GREEN]; b = pixel[BLUE]; if (a > 0.0f) { /* By definition the ratio between each color[] and pixel[] component in a non-pre-multipled blend always sums to 1.0f. * Originaly this would have been "(color[n] * alpha * color_a + pixel[n] * dst_alpha * (1.0f - alpha)) / a", * instead we only calculate the cheaper term. */ float src_term = (alpha * color_a) / a; float dst_term = 1.0f - src_term; r = color_r * src_term + r * dst_term; g = color_g * src_term + g * dst_term; b = color_b * src_term + b * dst_term; } if (colorize > 0.0f && base_alpha > 0.0f) { alpha = base_alpha * colorize; a = alpha + dst_alpha - alpha * dst_alpha; if (a > 0.0f) { GimpHSL pixel_hsl, out_hsl; GimpRGB pixel_rgb = {color_r, color_g, color_b}; GimpRGB out_rgb = {r, g, b}; float src_term = alpha / a; float dst_term = 1.0f - src_term; gimp_rgb_to_hsl (&pixel_rgb, &pixel_hsl); gimp_rgb_to_hsl (&out_rgb, &out_hsl); out_hsl.h = pixel_hsl.h; out_hsl.s = pixel_hsl.s; gimp_hsl_to_rgb (&out_hsl, &out_rgb); r = (float)out_rgb.r * src_term + r * dst_term; g = (float)out_rgb.g * src_term + g * dst_term; b = (float)out_rgb.b * src_term + b * dst_term; } } if (component_mask != GIMP_COMPONENT_MASK_ALL) { if (component_mask & GIMP_COMPONENT_MASK_RED) pixel[RED] = r; if (component_mask & GIMP_COMPONENT_MASK_GREEN) pixel[GREEN] = g; if (component_mask & GIMP_COMPONENT_MASK_BLUE) pixel[BLUE] = b; if (component_mask & GIMP_COMPONENT_MASK_ALPHA) pixel[ALPHA] = a; } else { pixel[RED] = r; pixel[GREEN] = g; pixel[BLUE] = b; pixel[ALPHA] = a; } pixel += 4; if (mask) mask += 1; } } } return 1; }
GeglBuffer * gimp_image_contiguous_region_by_color (GimpImage *image, GimpDrawable *drawable, gboolean sample_merged, gboolean antialias, gfloat threshold, gboolean select_transparent, GimpSelectCriterion select_criterion, const GimpRGB *color) { /* Scan over the image's active layer, finding pixels within the * specified threshold from the given R, G, & B values. If * antialiasing is on, use the same antialiasing scheme as in * fuzzy_select. Modify the image's mask to reflect the * additional selection */ GeglBufferIterator *iter; GimpPickable *pickable; GeglBuffer *src_buffer; GeglBuffer *mask_buffer; const Babl *format; gint n_components; gboolean has_alpha; gfloat start_col[MAX_CHANNELS]; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); g_return_val_if_fail (color != NULL, NULL); if (sample_merged) pickable = GIMP_PICKABLE (image); else pickable = GIMP_PICKABLE (drawable); gimp_pickable_flush (pickable); src_buffer = gimp_pickable_get_buffer (pickable); format = choose_format (src_buffer, select_criterion, &n_components, &has_alpha); gimp_rgba_get_pixel (color, format, start_col); if (has_alpha) { if (select_transparent) { /* don't select transparancy if "color" isn't fully transparent */ if (start_col[n_components - 1] > 0.0) select_transparent = FALSE; } } else { select_transparent = FALSE; } mask_buffer = gegl_buffer_new (gegl_buffer_get_extent (src_buffer), babl_format ("Y float")); iter = gegl_buffer_iterator_new (src_buffer, NULL, 0, format, GEGL_BUFFER_READ, GEGL_ABYSS_NONE); gegl_buffer_iterator_add (iter, mask_buffer, NULL, 0, babl_format ("Y float"), GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) { const gfloat *src = iter->data[0]; gfloat *dest = iter->data[1]; gint count = iter->length; while (count--) { /* Find how closely the colors match */ *dest = pixel_difference (start_col, src, antialias, threshold, n_components, has_alpha, select_transparent, select_criterion); src += n_components; dest += 1; } } return mask_buffer; }
static void stamp (GeglProperties *o, gdouble x, gdouble y) { WarpPrivate *priv = (WarpPrivate*) o->user_data; GeglBufferIterator *it; const Babl *format; gdouble stamp_force, influence; gdouble x_mean = 0.0; gdouble y_mean = 0.0; gint x_iter, y_iter; GeglRectangle area; const GeglRectangle *src_extent; gfloat *srcbuf, *stampbuf; gint buf_rowstride = 0; gfloat s = 0, c = 0; area.x = floor (x - o->size / 2.0); area.y = floor (y - o->size / 2.0); area.width = ceil (x + o->size / 2.0); area.height = ceil (y + o->size / 2.0); area.width -= area.x; area.height -= area.y; format = babl_format_n (babl_type ("float"), 2); /* If needed, compute the mean deformation */ if (o->behavior == GEGL_WARP_BEHAVIOR_SMOOTH) { gint pixel_count = 0; it = gegl_buffer_iterator_new (priv->buffer, &area, 0, format, GEGL_ACCESS_READ, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (it)) { gint n_pixels = it->length; gfloat *coords = it->data[0]; while (n_pixels--) { x_mean += coords[0]; y_mean += coords[1]; coords += 2; } pixel_count += it->roi->width * it->roi->height; } x_mean /= pixel_count; y_mean /= pixel_count; } else if (o->behavior == GEGL_WARP_BEHAVIOR_SWIRL_CW || o->behavior == GEGL_WARP_BEHAVIOR_SWIRL_CCW) { /* swirl by 5 degrees per stamp (for strength 100). * not exactly sin/cos factors, * since we calculate an off-center offset-vector */ /* note that this is fudged for stamp_force < 1.0 and * results in a slight upscaling there. It is a compromise * between exactness and calculation speed. */ s = sin (0.01 * o->strength * 5.0 / 180 * G_PI); c = cos (0.01 * o->strength * 5.0 / 180 * G_PI) - 1.0; } srcbuf = gegl_buffer_linear_open (priv->buffer, NULL, &buf_rowstride, NULL); buf_rowstride /= sizeof (gfloat); src_extent = gegl_buffer_get_extent (priv->buffer); stampbuf = g_new0 (gfloat, 2 * area.height * area.width); for (y_iter = 0; y_iter < area.height; y_iter++) { for (x_iter = 0; x_iter < area.width; x_iter++) { gfloat nvx, nvy; gfloat xi, yi; gfloat *vals; gint dx, dy; gfloat weight_x, weight_y; gfloat *srcptr; xi = area.x + x_iter; xi += -x + 0.5; yi = area.y + y_iter; yi += -y + 0.5; stamp_force = get_stamp_force (o, xi, yi); influence = 0.01 * o->strength * stamp_force; switch (o->behavior) { case GEGL_WARP_BEHAVIOR_MOVE: nvx = influence * (priv->last_x - x); nvy = influence * (priv->last_y - y); break; case GEGL_WARP_BEHAVIOR_GROW: nvx = influence * -0.1 * xi; nvy = influence * -0.1 * yi; break; case GEGL_WARP_BEHAVIOR_SHRINK: nvx = influence * 0.1 * xi; nvy = influence * 0.1 * yi; break; case GEGL_WARP_BEHAVIOR_SWIRL_CW: nvx = stamp_force * ( c * xi + s * yi); nvy = stamp_force * (-s * xi + c * yi); break; case GEGL_WARP_BEHAVIOR_SWIRL_CCW: nvx = stamp_force * ( c * xi - s * yi); nvy = stamp_force * ( s * xi + c * yi); break; case GEGL_WARP_BEHAVIOR_ERASE: case GEGL_WARP_BEHAVIOR_SMOOTH: default: nvx = 0.0; nvy = 0.0; break; } vals = stampbuf + (y_iter * area.width + x_iter) * 2; dx = floorf (nvx); dy = floorf (nvy); if (area.x + x_iter + dx < src_extent->x || area.x + x_iter + dx + 1 >= src_extent->x + src_extent->width || area.y + y_iter + dy < src_extent->y || area.y + y_iter + dy + 1 >= src_extent->y + src_extent->height) { continue; } srcptr = srcbuf + (area.y - src_extent->y + y_iter + dy) * buf_rowstride + (area.x - src_extent->x + x_iter + dx) * 2; if (o->behavior == GEGL_WARP_BEHAVIOR_ERASE) { vals[0] = srcptr[0] * (1.0 - MIN (influence, 1.0)); vals[1] = srcptr[1] * (1.0 - MIN (influence, 1.0)); } else if (o->behavior == GEGL_WARP_BEHAVIOR_SMOOTH) { vals[0] = (1.0 - influence) * srcptr[0] + influence * x_mean; vals[1] = (1.0 - influence) * srcptr[1] + influence * y_mean; } else { weight_x = nvx - dx; weight_y = nvy - dy; /* bilinear interpolation of the vectors */ vals[0] = srcptr[0] * (1.0 - weight_x) * (1.0 - weight_y); vals[1] = srcptr[1] * (1.0 - weight_x) * (1.0 - weight_y); vals[0] += srcptr[2] * weight_x * (1.0 - weight_y); vals[1] += srcptr[3] * weight_x * (1.0 - weight_y); vals[0] += srcptr[buf_rowstride + 0] * (1.0 - weight_x) * weight_y; vals[1] += srcptr[buf_rowstride + 1] * (1.0 - weight_x) * weight_y; vals[0] += srcptr[buf_rowstride + 2] * weight_x * weight_y; vals[1] += srcptr[buf_rowstride + 3] * weight_x * weight_y; vals[0] += nvx; vals[1] += nvy; } } } gegl_buffer_linear_close (priv->buffer, srcbuf); gegl_buffer_set (priv->buffer, &area, 0, format, stampbuf, GEGL_AUTO_ROWSTRIDE); g_free (stampbuf); /* Memorize the stamp location for movement dependant behavior like move */ priv->last_x = x; priv->last_y = y; }
gint main (gint argc, gchar **argv) { GeglBuffer *bufferA = NULL; GeglBuffer *bufferB = NULL; GeglBuffer *debug_buf = NULL; g_thread_init (NULL); gegl_init (&argc, &argv); if (argc != 3) { g_print ("This is simple image difference detection tool for use in regression testing" "return message is non zero if images are different, if they are equal" "the output will contain the string identical."); g_print ("Usage: %s <imageA> <imageB>\n", argv[0]); return 1; } { GeglNode *graph, *sink; graph = gegl_graph (sink=gegl_node ("gegl:buffer-sink", "buffer", &bufferA, NULL, gegl_node ("gegl:load", "path", argv[1], NULL))); gegl_node_process (sink); g_object_unref (graph); if (!bufferA) { g_printerr ("Failed to open %s\n", argv[1]); return 1; } graph = gegl_graph (sink=gegl_node ("gegl:buffer-sink", "buffer", &bufferB, NULL, gegl_node ("gegl:load", "path", argv[2], NULL))); gegl_node_process (sink); g_object_unref (graph); if (!bufferB) { g_printerr ("Failed to open %s\n", argv[2]); return 1; } } if (gegl_buffer_get_width (bufferA) != gegl_buffer_get_width (bufferB) || gegl_buffer_get_height (bufferA) != gegl_buffer_get_height (bufferB)) { g_printerr ("%s and %s differ in size\n", argv[1], argv[2]); g_printerr (" %ix%i vs %ix%i\n", gegl_buffer_get_width (bufferA), gegl_buffer_get_height (bufferA), gegl_buffer_get_width (bufferB), gegl_buffer_get_height (bufferB)); return 1; } debug_buf = gegl_buffer_new (gegl_buffer_get_extent (bufferA), babl_format ("R'G'B' u8")); { gfloat *bufA, *bufB; gfloat *a, *b; guchar *debug, *d; gint rowstrideA, rowstrideB, dRowstride; gint pixels; gint wrong_pixels=0; gint i; gdouble diffsum = 0.0; gdouble max_diff = 0.0; pixels = gegl_buffer_get_pixel_count (bufferA); bufA = (void*)gegl_buffer_linear_open (bufferA, NULL, &rowstrideA, babl_format ("CIE Lab float")); bufB = (void*)gegl_buffer_linear_open (bufferB, NULL, &rowstrideB, babl_format ("CIE Lab float")); debug = (void*)gegl_buffer_linear_open (debug_buf, NULL, &dRowstride, babl_format ("R'G'B' u8")); a = bufA; b = bufB; d = debug; for (i=0;i<pixels;i++) { gdouble diff = sqrt ( SQR(a[0]-b[0])+ SQR(a[1]-b[1])+ SQR(a[2]-b[2]) /*+SQR(a[3]-b[3])*/); if (diff>=0.01) { wrong_pixels++; diffsum += diff; if (diff > max_diff) max_diff = diff; d[0]=(diff/100.0 * 255); d[1]=0; d[2]=a[0]/100.0*255; } else { d[0]=a[0]/100.0*255; d[1]=a[0]/100.0*255; d[2]=a[0]/100.0*255; } a+=3; b+=3; d+=3; } a = bufA; b = bufB; d = debug; if (wrong_pixels) for (i=0;i<pixels;i++) { gdouble diff = sqrt ( SQR(a[0]-b[0])+ SQR(a[1]-b[1])+ SQR(a[2]-b[2]) /*+SQR(a[3]-b[3])*/); if (diff>=0.01) { d[0]=(100-a[0])/100.0*64+32; d[1]=(diff/max_diff * 255); d[2]=0; } else { d[0]=a[0]/100.0*255; d[1]=a[0]/100.0*255; d[2]=a[0]/100.0*255; } a+=3; b+=3; d+=3; } gegl_buffer_linear_close (bufferA, bufA); gegl_buffer_linear_close (bufferB, bufB); gegl_buffer_linear_close (debug_buf, debug); if (max_diff >= 0.1) { g_printerr ("%s and %s differ\n" " wrong pixels : %i/%i (%2.2f%%)\n" " max Δe : %2.3f\n" " avg Δe (wrong) : %2.3f(wrong) %2.3f(total)\n", argv[1], argv[2], wrong_pixels, pixels, (wrong_pixels*100.0/pixels), max_diff, diffsum/wrong_pixels, diffsum/pixels); if (max_diff > 1.5 && !strstr (argv[2], "broken")) { GeglNode *sink; gchar *debug_path = g_malloc (strlen (argv[2])+16); memcpy (debug_path, argv[2], strlen (argv[2])+1); memcpy (debug_path + strlen(argv[2])-4, "-diff.png", 11); gegl_graph (sink=gegl_node ("gegl:png-save", "path", debug_path, NULL, gegl_node ("gegl:buffer-source", "buffer", debug_buf, NULL))); gegl_node_process (sink); return 1; } if (strstr (argv[2], "broken")) g_print ("because the test is expected to fail "); else g_print ("because the error is small "); g_print ("we'll say "); } } g_print ("%s and %s are identical\n", argv[1], argv[2]); g_object_unref (debug_buf); g_object_unref (bufferA); g_object_unref (bufferB); gegl_exit (); return 0; }
GeglBuffer * gegl_operation_context_get_target (GeglOperationContext *context, const gchar *padname) { GeglBuffer *output; const GeglRectangle *result; const Babl *format; GeglNode *node; GeglOperation *operation; #if 0 g_return_val_if_fail (GEGL_IS_OPERATION_CONTEXT (context), NULL); #endif operation = context->operation; node = operation->node; /* <ick */ format = gegl_operation_get_format (operation, padname); if (format == NULL) { g_warning ("no format for %s presuming RGBA float\n", gegl_node_get_debug_name (node)); format = babl_format ("RGBA float"); } g_assert (format != NULL); g_assert (!strcmp (padname, "output")); result = &context->result_rect; if (result->width == 0 || result->height == 0) { output = g_object_ref (emptybuf()); } else if (node->dont_cache == FALSE && ! GEGL_OPERATION_CLASS (G_OBJECT_GET_CLASS (operation))->no_cache) { GeglBuffer *cache; cache = GEGL_BUFFER (gegl_node_get_cache (node)); /* Only use the cache if the result is within the cache * extent. This is certainly not optimal. My gut feeling is that * the current caching mechanism needs to be redesigned */ if (gegl_rectangle_contains (gegl_buffer_get_extent (cache), result)) { output = g_object_ref (cache); } else { output = gegl_buffer_new_ram (result, format); } } else { output = gegl_buffer_new_ram (result, format); } gegl_operation_context_take_object (context, padname, G_OBJECT (output)); return output; }
/* Save a layer from an image */ gboolean save_layer(gint32 drawable_ID, WebPWriterFunction writer, void *custom_ptr, #ifdef WEBP_0_5 gboolean animation, WebPAnimEncoder *enc, int frame_timestamp, #endif WebPSaveParams *params, GError **error) { gboolean status = FALSE; gint bpp; gint width; gint height; GimpImageType drawable_type; WebPConfig config; WebPPicture picture; guchar *buffer = NULL; #ifdef GIMP_2_9 GeglBuffer *geglbuffer; GeglRectangle extent; #else GimpDrawable *drawable = NULL; GimpPixelRgn region; #endif /* Retrieve the image data */ bpp = gimp_drawable_bpp(drawable_ID); width = gimp_drawable_width(drawable_ID); height = gimp_drawable_height(drawable_ID); drawable_type = gimp_drawable_type(drawable_ID); /* Initialize the WebP configuration with a preset and fill in the * remaining values */ WebPConfigPreset(&config, webp_preset_by_name(params->preset), params->quality); config.lossless = params->lossless; config.method = 6; /* better quality */ config.alpha_quality = params->alpha_quality; /* Prepare the WebP structure */ WebPPictureInit(&picture); picture.use_argb = 1; picture.width = width; picture.height = height; picture.writer = writer; picture.custom_ptr = custom_ptr; picture.progress_hook = webp_file_progress; do { /* Attempt to allocate a buffer of the appropriate size */ buffer = (guchar *)g_malloc(bpp * width * height); if(!buffer) { g_set_error(error, G_FILE_ERROR, 0, "Unable to allocate buffer for layer"); break; } #ifdef GIMP_2_9 /* Obtain the buffer and get its extent */ geglbuffer = gimp_drawable_get_buffer(drawable_ID); extent = *gegl_buffer_get_extent(geglbuffer); /* Read the layer buffer into our buffer */ gegl_buffer_get(geglbuffer, &extent, 1.0, NULL, buffer, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); g_object_unref(geglbuffer); #else /* Get the drawable */ drawable = gimp_drawable_get(drawable_ID); /* Obtain the pixel region for the drawable */ gimp_pixel_rgn_init(®ion, drawable, 0, 0, width, height, FALSE, FALSE); /* Read the region into the buffer */ gimp_pixel_rgn_get_rect(®ion, buffer, 0, 0, width, height); gimp_drawable_detach(drawable); #endif /* Use the appropriate function to import the data from the buffer */ if(drawable_type == GIMP_RGB_IMAGE) { WebPPictureImportRGB(&picture, buffer, width * bpp); } else { WebPPictureImportRGBA(&picture, buffer, width * bpp); } #ifdef WEBP_0_5 if (animation == TRUE) { if (!WebPAnimEncoderAdd(enc, &picture, frame_timestamp, &config)) { g_set_error(error, G_FILE_ERROR, picture.error_code, "WebP error: '%s'", webp_error_string(picture.error_code)); break; } } else { #endif if(!WebPEncode(&config, &picture)) { g_set_error(error, G_FILE_ERROR, picture.error_code, "WebP error: '%s'", webp_error_string(picture.error_code)); break; } #ifdef WEBP_0_5 } #endif /* Everything succeeded */ status = TRUE; } while(0); /* Free the buffer */ if (buffer) { free(buffer); } return status; }
static void affine_generic (GeglBuffer *dest, GeglBuffer *src, GeglMatrix3 *matrix, GeglSampler *sampler) { GeglBufferIterator *i; const GeglRectangle *dest_extent; gint x, y; gfloat * restrict dest_buf, *dest_ptr; GeglMatrix3 inverse; GeglMatrix2 inverse_jacobian; gdouble u_start, v_start, u_float, v_float; Babl *format; gint dest_pixels; format = babl_format ("RaGaBaA float"); /* XXX: fast paths as existing in files in the same dir as affine.c * should probably be hooked in here, and bailing out before using * the generic code. */ g_object_get (dest, "pixels", &dest_pixels, NULL); dest_extent = gegl_buffer_get_extent (dest); i = gegl_buffer_iterator_new (dest, dest_extent, format, GEGL_BUFFER_WRITE); while (gegl_buffer_iterator_next (i)) { GeglRectangle *roi = &i->roi[0]; dest_buf = (gfloat *)i->data[0]; gegl_matrix3_copy_into (&inverse, matrix); gegl_matrix3_invert (&inverse); inverse_jacobian.coeff[0][0] = inverse.coeff[0][0]; inverse_jacobian.coeff[0][1] = inverse.coeff[0][1]; inverse_jacobian.coeff[1][0] = inverse.coeff[1][0]; inverse_jacobian.coeff[1][1] = inverse.coeff[1][1]; /* set inverse_jacobian for samplers that support it */ u_start = inverse.coeff[0][0] * roi->x + inverse.coeff[0][1] * roi->y + inverse.coeff[0][2]; v_start = inverse.coeff[1][0] * roi->x + inverse.coeff[1][1] * roi->y + inverse.coeff[1][2]; /* correct rounding on e.g. negative scaling (is this sound?) */ if (inverse.coeff [0][0] < 0.) u_start -= .001; if (inverse.coeff [1][1] < 0.) v_start -= .001; for (dest_ptr = dest_buf, y = roi->height; y--;) { u_float = u_start; v_float = v_start; for (x = roi->width; x--;) { gegl_sampler_get (sampler, u_float, v_float, &inverse_jacobian, dest_ptr); dest_ptr+=4; u_float += inverse.coeff [0][0]; v_float += inverse.coeff [1][0]; } u_start += inverse.coeff [0][1]; v_start += inverse.coeff [1][1]; } } }
GeglBuffer * gimp_image_contiguous_region_by_seed (GimpImage *image, GimpDrawable *drawable, gboolean sample_merged, gboolean antialias, gfloat threshold, gboolean select_transparent, GimpSelectCriterion select_criterion, gint x, gint y) { GimpPickable *pickable; GeglBuffer *src_buffer; GeglBuffer *mask_buffer; const Babl *format; gint n_components; gboolean has_alpha; gfloat start_col[MAX_CHANNELS]; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); if (sample_merged) pickable = GIMP_PICKABLE (image); else pickable = GIMP_PICKABLE (drawable); gimp_pickable_flush (pickable); src_buffer = gimp_pickable_get_buffer (pickable); format = choose_format (src_buffer, select_criterion, &n_components, &has_alpha); gegl_buffer_sample (src_buffer, x, y, NULL, start_col, format, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); if (has_alpha) { if (select_transparent) { /* don't select transparent regions if the start pixel isn't * fully transparent */ if (start_col[n_components - 1] > 0) select_transparent = FALSE; } } else { select_transparent = FALSE; } mask_buffer = gegl_buffer_new (gegl_buffer_get_extent (src_buffer), babl_format ("Y float")); find_contiguous_region_helper (src_buffer, mask_buffer, format, n_components, has_alpha, select_transparent, select_criterion, antialias, threshold, x, y, start_col); return mask_buffer; }
gint main (gint argc, gchar **argv) { GeglRectangle terrain_rect; if (argc < 2) usage(); gegl_init (&argc, &argv); parse_args (argc, argv); gegl_decode = gegl_node_new (); store = gegl_node_new_child (gegl_decode, "operation", "gegl:buffer-sink", "buffer", &video_frame, NULL); load = gegl_node_new_child (gegl_decode, "operation", "gegl:ff-load", "frame", 0, "path", video_path, NULL); gegl_node_link_many (load, store, NULL); decode_frame_no (0); /* we issue a processing/decoding of a frame - to get metadata */ { gegl_node_get (load, "frame-rate", &frame_rate, NULL); total_frames = 0; gegl_node_get (load, "frames", &total_frames, NULL); if (frame_end == 0) frame_end = total_frames; } if (horizontal) terrain_rect = (GeglRectangle){0, 0, frame_end - frame_start + 1, 1024}; else terrain_rect = (GeglRectangle){0, 0, 1024, frame_end - frame_start + 1}; if (input_analysis_path && g_file_test (input_analysis_path, G_FILE_TEST_IS_REGULAR)) { GeglNode *load_graph = gegl_node_new (); GeglNode *load = gegl_node_new_child (load_graph, "operation", "gegl:load", "path", input_analysis_path, NULL); GeglNode *store = gegl_node_new_child (load_graph, "operation", "gegl:buffer-sink", "buffer", &terrain, NULL); gegl_node_link_many (load, store, NULL); gegl_node_process (store); g_object_unref (load_graph); frame_end = frame_start + gegl_buffer_get_extent (terrain)->height; /* the last frame aavilavle for analysis is the last one loaded rom cache,.. perhaps with some timeout */ } else { terrain = gegl_buffer_new (&terrain_rect, babl_format ("RGBA u8")); { gint frame; gint max_buf_pos = 0; for (frame = frame_start; frame <= frame_end; frame++) { FrameInfo info = {{0}}; uint8_t buffer[4096] = {0,}; int buffer_pos = 0; GeglRectangle terrain_row; char *p = format; GString *word = g_string_new (""); if (show_progress) { double percent_full = 100.0 * (frame-frame_start) / (frame_end-frame_start); double percent_time = time_out?100.0 * babl_ticks()/1000.0/1000.0 / time_out:0.0; fprintf (stdout, "\r%2.1f%% %i/%i (%i)", percent_full>percent_time?percent_full:percent_time, frame-frame_start, frame_end-frame_start, frame); fflush (stdout); } if (horizontal) terrain_row = (GeglRectangle){frame-frame_start, 0, 1, 1024}; else terrain_row = (GeglRectangle){0, frame-frame_start, 1024, 1}; decode_frame_no (frame); //for (int i=0;i<(signed)sizeof(buffer);i++)buffer[i]=0; while (*p == ' ') p++; for (p= format;p==format || p[-1]!='\0';p++) { if (*p != '\0' && *p != ' ') { g_string_append_c (word, *p); } else { if (!strcmp (word->str, "histogram")) { record_pix_stats (video_frame, previous_video_frame, &(info.rgb_hist[0]), &(info.rgb_square_diff)[0]); for (int i = 0; i < NEGL_RGB_HIST_SLOTS; i++) { buffer[buffer_pos] = info.rgb_hist[i]; buffer_pos++; } for (int i = 0; i < 3; i++) { buffer[buffer_pos] = info.rgb_square_diff[i]; buffer_pos++; } } else if (!strcmp (word->str, "mid-row")) { int samples = NEGL_RGB_HEIGHT; if (p[1] >= '0' && p[1] <= '9') { samples = g_strtod (&p[1], &p); } buffer_pos += extract_mid_row (video_frame, &(buffer)[buffer_pos], samples); } else if (!strcmp (word->str, "mid-col")) { int samples = NEGL_RGB_HEIGHT; if (p[1] >= '0' && p[1] <= '9') { samples = g_strtod (&p[1], &p); } buffer_pos += extract_mid_col (video_frame, &(buffer)[buffer_pos], samples); } else if (!strcmp (word->str, "thumb")) { int samples = NEGL_RGB_THEIGHT; int samples2; if (p[1] >= '0' && p[1] <= '9') { samples = g_strtod (&p[1], &p); } if (horizontal) samples2 = samples * gegl_buffer_get_width (video_frame)/gegl_buffer_get_height(video_frame); else samples2 = samples * gegl_buffer_get_height (video_frame)/gegl_buffer_get_width(video_frame); buffer_pos += extract_thumb (video_frame, &(buffer)[buffer_pos], samples, samples2); } else if (!strcmp (word->str, "audio")) { int dups = 1; GeglAudioFragment *audio = NULL; if (p[1] >= '0' && p[1] <= '9') { dups = g_strtod (&p[1], &p); } gegl_node_get (load, "audio", &audio, NULL); if (audio) { extract_audio_energy (audio, &buffer[buffer_pos], dups); g_object_unref (audio); } buffer_pos+=3 * dups; } g_string_assign (word, ""); } } max_buf_pos = buffer_pos; g_string_free (word, TRUE); gegl_buffer_set (terrain, &terrain_row, 0, babl_format("RGB u8"), buffer, GEGL_AUTO_ROWSTRIDE); if (time_out > 1.0 && babl_ticks()/1000.0/1000.0 > time_out) { frame_end = frame; if (horizontal) terrain_rect.width = frame_end - frame_start + 1; else terrain_rect.height = frame_end - frame_start + 1; // gegl_buffer_set_extent (terrain, &terrain_rect); } if (horizontal) terrain_rect.height = max_buf_pos/3; else terrain_rect.width = max_buf_pos/3; gegl_buffer_set_extent (terrain, &terrain_rect); } if (show_progress) { fprintf (stdout, "\n"); fflush (stdout); } } if (output_analysis_path) { GeglNode *save_graph = gegl_node_new (); GeglNode *readbuf = gegl_node_new_child (save_graph, "operation", "gegl:buffer-source", "buffer", terrain, NULL); GeglNode *save = gegl_node_new_child (save_graph, "operation", "gegl:png-save", "path", output_analysis_path, NULL); gegl_node_link_many (readbuf, save, NULL); gegl_node_process (save); g_object_unref (save_graph); } } if (thumb_path) { GeglNode *save_graph = gegl_node_new (); find_best_thumb (); if (frame_thumb != 0) decode_frame_no (frame_thumb-1); decode_frame_no (frame_thumb); { GeglNode *readbuf = gegl_node_new_child (save_graph, "operation", "gegl:buffer-source", "buffer", video_frame, NULL); GeglNode *save = gegl_node_new_child (save_graph, "operation", "gegl:png-save", "path", thumb_path, NULL); gegl_node_link_many (readbuf, save, NULL); gegl_node_process (save); g_object_unref (save_graph); } } if (video_frame) g_object_unref (video_frame); video_frame = NULL; if (previous_video_frame) g_object_unref (previous_video_frame); previous_video_frame = NULL; if (terrain) g_object_unref (terrain); terrain = NULL; g_object_unref (gegl_decode); gegl_exit (); return 0; }
static gboolean test_buffer_change_extent (void) { gboolean result = TRUE; gchar *tmpdir = NULL; gchar *buf_a_path = NULL; GeglBuffer *buf_a = NULL; const Babl *format = babl_format ("R'G'B'A u8"); GeglRectangle roi = {0, 0, 128, 128}; GeglRectangle roi2 = {0, 0, 64, 64}; tmpdir = g_dir_make_tmp ("test-backend-file-XXXXXX", NULL); g_return_val_if_fail (tmpdir, FALSE); buf_a_path = g_build_filename (tmpdir, "buf_a.gegl", NULL); buf_a = g_object_new (GEGL_TYPE_BUFFER, "format", format, "path", buf_a_path, "x", roi.x, "y", roi.y, "width", roi.width, "height", roi.height, NULL); gegl_buffer_flush (buf_a); g_object_unref (buf_a); buf_a = g_object_new (GEGL_TYPE_BUFFER, "format", babl_format ("RGBA u16"), "path", buf_a_path, NULL); if (!gegl_rectangle_equal (gegl_buffer_get_extent (buf_a), &roi)) { printf ("Extent does not match:\n"); gegl_rectangle_dump (gegl_buffer_get_extent (buf_a)); gegl_rectangle_dump (&roi); result = FALSE; } gegl_buffer_set_extent (buf_a, &roi2); gegl_buffer_flush (buf_a); g_object_unref (buf_a); buf_a = g_object_new (GEGL_TYPE_BUFFER, "format", babl_format ("RGBA u16"), "path", buf_a_path, NULL); if (!gegl_rectangle_equal (gegl_buffer_get_extent (buf_a), &roi2)) { printf ("Extent does not match:\n"); gegl_rectangle_dump (gegl_buffer_get_extent (buf_a)); gegl_rectangle_dump (&roi2); result = FALSE; } g_object_unref (buf_a); g_unlink (buf_a_path); g_remove (tmpdir); g_free (tmpdir); g_free (buf_a_path); return result; }
GeglBuffer * gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable, gboolean antialias, gfloat threshold, gboolean select_transparent, GimpSelectCriterion select_criterion, gboolean diagonal_neighbors, gint x, gint y) { GeglBuffer *src_buffer; GeglBuffer *mask_buffer; const Babl *format; GeglRectangle extent; gint n_components; gboolean has_alpha; gfloat start_col[MAX_CHANNELS]; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL); gimp_pickable_flush (pickable); src_buffer = gimp_pickable_get_buffer (pickable); format = choose_format (src_buffer, select_criterion, &n_components, &has_alpha); gegl_buffer_sample (src_buffer, x, y, NULL, start_col, format, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); if (has_alpha) { if (select_transparent) { /* don't select transparent regions if the start pixel isn't * fully transparent */ if (start_col[n_components - 1] > 0) select_transparent = FALSE; } } else { select_transparent = FALSE; } extent = *gegl_buffer_get_extent (src_buffer); mask_buffer = gegl_buffer_new (&extent, babl_format ("Y float")); if (x >= extent.x && x < (extent.x + extent.width) && y >= extent.y && y < (extent.y + extent.height)) { GIMP_TIMER_START(); find_contiguous_region (src_buffer, mask_buffer, format, n_components, has_alpha, select_transparent, select_criterion, antialias, threshold, diagonal_neighbors, x, y, start_col); GIMP_TIMER_END("foo"); } return mask_buffer; }
static gboolean test_buffer_same_path (void) { gboolean result = TRUE; gchar *tmpdir = NULL; gchar *buf_a_path = NULL; GeglBuffer *buf_a = NULL; const Babl *format = babl_format ("R'G'B'A u8"); GeglRectangle roi = {0, 0, 128, 128}; tmpdir = g_dir_make_tmp ("test-backend-file-XXXXXX", NULL); g_return_val_if_fail (tmpdir, FALSE); buf_a_path = g_build_filename (tmpdir, "buf_a.gegl", NULL); buf_a = g_object_new (GEGL_TYPE_BUFFER, "format", format, "path", buf_a_path, "x", roi.x, "y", roi.y, "width", roi.width, "height", roi.height, NULL); gegl_buffer_flush (buf_a); g_object_unref (buf_a); buf_a = g_object_new (GEGL_TYPE_BUFFER, /* FIXME: Currently the buffer must always have a format specified */ "format", babl_format ("RGBA u16"), "path", buf_a_path, NULL); if (!GEGL_IS_BUFFER (buf_a)) { printf ("Failed to load file:%s\n", buf_a_path); result = FALSE; } if (!gegl_rectangle_equal (gegl_buffer_get_extent (buf_a), &roi)) { printf ("Extent does not match:\n"); gegl_rectangle_dump (gegl_buffer_get_extent (buf_a)); gegl_rectangle_dump (&roi); result = FALSE; } if (gegl_buffer_get_format (buf_a) != format) { printf ("Formats do not match:\n%s\n%s\n", babl_get_name (gegl_buffer_get_format (buf_a)), babl_get_name (format)); result = FALSE; } g_object_unref (buf_a); g_unlink (buf_a_path); g_remove (tmpdir); g_free (tmpdir); g_free (buf_a_path); return result; }