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 gimp_operation_cage_transform_prepare (GeglOperation *operation) { GimpOperationCageTransform *oct = GIMP_OPERATION_CAGE_TRANSFORM (operation); GimpCageConfig *config = GIMP_CAGE_CONFIG (oct->config); gegl_operation_set_format (operation, "input", babl_format_n (babl_type ("float"), 2 * gimp_cage_config_get_n_points (config))); gegl_operation_set_format (operation, "output", babl_format_n (babl_type ("float"), 2)); }
static void gimp_cage_tool_compute_coef (GimpCageTool *ct) { GimpCageConfig *config = ct->config; GimpProgress *progress; const Babl *format; GeglNode *gegl; GeglNode *input; GeglNode *output; GeglProcessor *processor; GeglBuffer *buffer; gdouble value; progress = gimp_progress_start (GIMP_PROGRESS (ct), _("Computing Cage Coefficients"), FALSE); if (ct->coef) { g_object_unref (ct->coef); ct->coef = NULL; } format = babl_format_n (babl_type ("float"), gimp_cage_config_get_n_points (config) * 2); gegl = gegl_node_new (); input = gegl_node_new_child (gegl, "operation", "gimp:cage-coef-calc", "config", ct->config, NULL); output = gegl_node_new_child (gegl, "operation", "gegl:buffer-sink", "buffer", &buffer, "format", format, NULL); gegl_node_connect_to (input, "output", output, "input"); processor = gegl_node_new_processor (output, NULL); while (gegl_processor_work (processor, &value)) { if (progress) gimp_progress_set_value (progress, value); } if (progress) gimp_progress_end (progress); g_object_unref (processor); ct->coef = buffer; g_object_unref (gegl); ct->dirty_coef = FALSE; }
static void gimp_warp_tool_start (GimpWarpTool *wt, GimpDisplay *display) { GimpTool *tool = GIMP_TOOL (wt); GimpImage *image = gimp_display_get_image (display); GimpDrawable *drawable = gimp_image_get_active_drawable (image); const Babl *format; GeglRectangle bbox; tool->display = display; tool->drawable = drawable; /* Create the coords buffer, with the size of the selection */ format = babl_format_n (babl_type ("float"), 2); gimp_item_mask_intersect (GIMP_ITEM (drawable), &bbox.x, &bbox.y, &bbox.width, &bbox.height); #ifdef WARP_DEBUG g_printerr ("Initialize coordinate buffer (%d,%d) at %d,%d\n", bbox.width, bbox.height, bbox.x, bbox.y); #endif wt->coords_buffer = gegl_buffer_new (&bbox, format); gimp_warp_tool_create_image_map (wt, drawable); if (! gimp_draw_tool_is_active (GIMP_DRAW_TOOL (wt))) gimp_draw_tool_start (GIMP_DRAW_TOOL (wt), display); }
static void prepare (GeglOperation *operation) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *src_format = gegl_operation_get_source_format (operation, "input"); const Babl *input_format = babl_format ("RGB double"); gint n_components = 3; const Babl *output_format; if (src_format) { const Babl *model = babl_format_get_model (src_format); if (model == babl_model ("RGB") || model == babl_model ("R'G'B'") || model == babl_model ("RGBA") || model == babl_model ("R'G'B'A")) { input_format = babl_format ("RGB double"); n_components = 3; } else if (model == babl_model ("Y") || model == babl_model ("Y'") || model == babl_model ("YA") || model == babl_model ("Y'A")) { input_format = babl_format ("Y double"); n_components = 1; } } if (o->squared) n_components *= 2; output_format = babl_format_n (babl_type ("double"), n_components); gegl_operation_set_format (operation, "input", input_format); gegl_operation_set_format (operation, "output", output_format); }
static void prepare (GeglOperation *operation) { const Babl *format = babl_format ("RGBA float"); gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "aux", babl_format_n (babl_type ("float"), 2)); gegl_operation_set_format (operation, "output", format); }
static void gimp_operation_scalar_multiply_prepare (GeglOperation *operation) { GimpOperationScalarMultiply *self = GIMP_OPERATION_SCALAR_MULTIPLY (operation); const Babl *format; format = babl_format_n (babl_type ("float"), self->n_components); gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "output", format); }
static void gimp_operation_cage_coef_calc_prepare (GeglOperation *operation) { GimpOperationCageCoefCalc *occc = GIMP_OPERATION_CAGE_COEF_CALC (operation); GimpCageConfig *config = GIMP_CAGE_CONFIG (occc->config); gegl_operation_set_format (operation, "output", babl_format_n (babl_type ("float"), 2 * gimp_cage_config_get_n_points (config))); }
static void prepare (GeglOperation *operation) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *format = babl_format_n (babl_type ("float"), 2); gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "output", format); if (!o->user_data) o->user_data = g_slice_new0 (WarpPrivate); }
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); }
static void prepare (GeglOperation *operation) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); WarpPrivate *priv; const Babl *format = babl_format_n (babl_type ("float"), 2); gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "output", format); if (!o->chant_data) { o->chant_data = g_slice_new (WarpPrivate); } priv = (WarpPrivate*) o->chant_data; priv->last_point_set = FALSE; priv->lookup = NULL; priv->buffer = NULL; }
static void gimp_warp_tool_start (GimpWarpTool *wt, GimpDisplay *display) { GimpTool *tool = GIMP_TOOL (wt); GimpWarpOptions *options = GIMP_WARP_TOOL_GET_OPTIONS (wt); GimpImage *image = gimp_display_get_image (display); GimpDrawable *drawable = gimp_image_get_active_drawable (image); const Babl *format; GeglRectangle bbox; tool->display = display; tool->drawable = drawable; /* Create the coords buffer, with the size of the selection */ format = babl_format_n (babl_type ("float"), 2); gimp_item_mask_intersect (GIMP_ITEM (drawable), &bbox.x, &bbox.y, &bbox.width, &bbox.height); #ifdef WARP_DEBUG g_printerr ("Initialize coordinate buffer (%d,%d) at %d,%d\n", bbox.width, bbox.height, bbox.x, bbox.y); #endif wt->coords_buffer = gegl_buffer_new (&bbox, format); gimp_warp_tool_create_image_map (wt, drawable); if (! gimp_draw_tool_is_active (GIMP_DRAW_TOOL (wt))) gimp_draw_tool_start (GIMP_DRAW_TOOL (wt), display); if (options->animate_button) { g_signal_connect_swapped (options->animate_button, "clicked", G_CALLBACK (gimp_warp_tool_animate), wt); gtk_widget_set_sensitive (options->animate_button, TRUE); } }
static gboolean gimp_operation_cage_transform_process (GeglOperation *operation, GeglBuffer *in_buf, GeglBuffer *aux_buf, GeglBuffer *out_buf, const GeglRectangle *roi, gint level) { GimpOperationCageTransform *oct = GIMP_OPERATION_CAGE_TRANSFORM (operation); GimpCageConfig *config = GIMP_CAGE_CONFIG (oct->config); GeglRectangle cage_bb; gfloat *coords; gfloat *coef; const Babl *format_coef; GimpVector2 plain_color; GeglBufferIterator *it; gint x, y; gboolean output_set; GimpCagePoint *point; guint n_cage_vertices; /* pre-fill the out buffer with no-displacement coordinate */ it = gegl_buffer_iterator_new (out_buf, roi, 0, NULL, GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE); cage_bb = gimp_cage_config_get_bounding_box (config); point = &(g_array_index (config->cage_points, GimpCagePoint, 0)); plain_color.x = (gint) point->src_point.x; plain_color.y = (gint) point->src_point.y; n_cage_vertices = gimp_cage_config_get_n_points (config); while (gegl_buffer_iterator_next (it)) { /* iterate inside the roi */ gint n_pixels = it->length; gfloat *output = it->data[0]; x = it->roi->x; /* initial x */ y = it->roi->y; /* and y coordinates */ while (n_pixels--) { output_set = FALSE; if (oct->fill_plain_color) { if (x > cage_bb.x && y > cage_bb.y && x < cage_bb.x + cage_bb.width && y < cage_bb.y + cage_bb.height) { if (gimp_cage_config_point_inside (config, x, y)) { output[0] = plain_color.x; output[1] = plain_color.y; output_set = TRUE; } } } if (!output_set) { output[0] = x; output[1] = y; } output += 2; /* update x and y coordinates */ x++; if (x >= (it->roi->x + it->roi->width)) { x = it->roi->x; y++; } } } oct->progress = 0.0; g_object_notify (G_OBJECT (oct), "progress"); /* pre-allocate memory outside of the loop */ coords = g_slice_alloc (2 * sizeof (gfloat)); coef = g_malloc (n_cage_vertices * 2 * sizeof (gfloat)); format_coef = babl_format_n (babl_type ("float"), 2 * n_cage_vertices); /* compute, reverse and interpolate the transformation */ for (y = cage_bb.y; y < cage_bb.y + cage_bb.height - 1; y++) { GimpVector2 p1_d, p2_d, p3_d, p4_d; GimpVector2 p1_s, p2_s, p3_s, p4_s; p1_s.y = y; p2_s.y = y+1; p3_s.y = y+1; p3_s.x = cage_bb.x; p4_s.y = y; p4_s.x = cage_bb.x; p3_d = gimp_cage_transform_compute_destination (config, coef, format_coef, aux_buf, p3_s); p4_d = gimp_cage_transform_compute_destination (config, coef, format_coef, aux_buf, p4_s); for (x = cage_bb.x; x < cage_bb.x + cage_bb.width - 1; x++) { p1_s = p4_s; p2_s = p3_s; p3_s.x = x+1; p4_s.x = x+1; p1_d = p4_d; p2_d = p3_d; p3_d = gimp_cage_transform_compute_destination (config, coef, format_coef, aux_buf, p3_s); p4_d = gimp_cage_transform_compute_destination (config, coef, format_coef, aux_buf, p4_s); if (gimp_cage_config_point_inside (config, x, y)) { gimp_operation_cage_transform_interpolate_source_coords_recurs (oct, out_buf, roi, p1_s, p1_d, p2_s, p2_d, p3_s, p3_d, 0, coords); gimp_operation_cage_transform_interpolate_source_coords_recurs (oct, out_buf, roi, p1_s, p1_d, p3_s, p3_d, p4_s, p4_d, 0, coords); } } if ((y - cage_bb.y) % 20 == 0) { gdouble fraction = ((gdouble) (y - cage_bb.y) / (gdouble) (cage_bb.height)); /* 0.0 and 1.0 indicate progress start/end, so avoid them */ if (fraction > 0.0 && fraction < 1.0) { oct->progress = fraction; g_object_notify (G_OBJECT (oct), "progress"); } } } g_free (coef); g_slice_free1 (2 * sizeof (gfloat), coords); oct->progress = 1.0; g_object_notify (G_OBJECT (oct), "progress"); return TRUE; }
static gboolean gimp_operation_cage_coef_calc_process (GeglOperation *operation, GeglBuffer *output, const GeglRectangle *roi) { GimpOperationCageCoefCalc *occc = GIMP_OPERATION_CAGE_COEF_CALC (operation); GimpCageConfig *config = GIMP_CAGE_CONFIG (occc->config); Babl *format = babl_format_n (babl_type ("float"), 2 * gimp_cage_config_get_n_points (config)); GeglBufferIterator *it; guint n_cage_vertices; GimpCagePoint *current, *last; if (! config) return FALSE; n_cage_vertices = gimp_cage_config_get_n_points (config); it = gegl_buffer_iterator_new (output, roi, format, GEGL_BUFFER_READWRITE); while (gegl_buffer_iterator_next (it)) { /* iterate inside the roi */ gint n_pixels = it->length; gint x = it->roi->x; /* initial x */ gint y = it->roi->y; /* and y coordinates */ gint j; gfloat *coef = it->data[0]; while(n_pixels--) { if (gimp_cage_config_point_inside(config, x, y)) { last = &(g_array_index (config->cage_points, GimpCagePoint, 0)); for( j = 0; j < n_cage_vertices; j++) { GimpVector2 v1,v2,a,b,p; gdouble BA,SRT,L0,L1,A0,A1,A10,L10, Q,S,R, absa; current = &(g_array_index (config->cage_points, GimpCagePoint, (j+1) % n_cage_vertices)); v1 = last->src_point; v2 = current->src_point; p.x = x; p.y = y; a.x = v2.x - v1.x; a.y = v2.y - v1.y; absa = gimp_vector2_length (&a); b.x = v1.x - x; b.y = v1.y - y; Q = a.x * a.x + a.y * a.y; S = b.x * b.x + b.y * b.y; R = 2.0 * (a.x * b.x + a.y * b.y); BA = b.x * a.y - b.y * a.x; SRT = sqrt(4.0 * S * Q - R * R); L0 = log(S); L1 = log(S + Q + R); A0 = atan2(R, SRT) / SRT; A1 = atan2(2.0 * Q + R, SRT) / SRT; A10 = A1 - A0; L10 = L1 - L0; /* edge coef */ coef[j + n_cage_vertices] = (-absa / (4.0 * G_PI)) * ((4.0*S-(R*R)/Q) * A10 + (R / (2.0 * Q)) * L10 + L1 - 2.0); if (isnan(coef[j + n_cage_vertices])) { coef[j + n_cage_vertices] = 0.0; } /* vertice coef */ if (!gimp_operation_cage_coef_calc_is_on_straight (&v1, &v2, &p)) { coef[j] += (BA / (2.0 * G_PI)) * (L10 /(2.0*Q) - A10 * (2.0 + R / Q)); coef[(j+1)%n_cage_vertices] -= (BA / (2.0 * G_PI)) * (L10 / (2.0 * Q) - A10 * (R / Q)); } last = current; } } coef += 2 * n_cage_vertices; /* update x and y coordinates */ x++; if (x >= (it->roi->x + it->roi->width)) { x = it->roi->x; y++; } } } return TRUE; }
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; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *aux, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *format_io, *format_coords; GeglSampler *sampler; GeglBufferIterator *it; gint index_in, index_out, index_coords; format_io = babl_format ("RGBA float"); format_coords = babl_format_n (babl_type ("float"), 2); sampler = gegl_buffer_sampler_new_at_level (input, format_io, o->sampler_type, level); if (aux != NULL) { it = gegl_buffer_iterator_new (output, result, level, format_io, GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); index_out = 0; index_coords = gegl_buffer_iterator_add (it, aux, result, level, format_coords, GEGL_ACCESS_READ, GEGL_ABYSS_NONE); index_in = gegl_buffer_iterator_add (it, input, result, level, format_io, GEGL_ACCESS_READ, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (it)) { gint i; gint n_pixels = it->length; gint x = it->roi->x; /* initial x */ gint y = it->roi->y; /* and y coordinates */ gdouble scaling = GEGL_PROPERTIES (operation)->scaling; gfloat *in = it->data[index_in]; gfloat *out = it->data[index_out]; gfloat *coords = it->data[index_coords]; for (i=0; i<n_pixels; i++) { /* if the coordinate asked is an exact pixel, we fetch it * directly, to avoid the blur of sampling */ if (coords[0] == 0 && coords[1] == 0) { out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; out[3] = in[3]; } else { gegl_sampler_get (sampler, x+coords[0] * scaling, y+coords[1] * scaling, NULL, out, GEGL_ABYSS_NONE); } coords += 2; in += 4; out += 4; /* update x and y coordinates */ x++; if (x >= (it->roi->x + it->roi->width)) { x = it->roi->x; y++; } } } } else { gegl_buffer_copy (input, result, GEGL_ABYSS_NONE, output, result); } g_object_unref (sampler); return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); cmsHTRANSFORM transform; const Babl *in_format, *out_format; gboolean alpha; gint bpp; in_format = babl_format_n (babl_type ("float"), babl_format_get_n_components (gegl_buffer_get_format (input))); bpp = babl_format_get_bytes_per_pixel (in_format); /* create the transformation */ { cmsHPROFILE in_profile, out_profile; cmsUInt32Number format; in_profile = o->src_profile; format = determine_lcms_format (in_format, in_profile); if (format == 0) return FALSE; if (format & EXTRA_SH (1)) alpha = TRUE; else alpha = FALSE; out_profile = create_lcms_linear_rgb_profile (); transform = cmsCreateTransform (in_profile, format, out_profile, alpha ? TYPE_RGBA_FLT : TYPE_RGB_FLT, o->intent, o->black_point_compensation ? cmsFLAGS_BLACKPOINTCOMPENSATION : 0); cmsCloseProfile (out_profile); } out_format = alpha ? babl_format ("RGBA float") : babl_format ("RGB float"); /* iterate over the pixels */ { GeglBufferIterator *gi; gi = gegl_buffer_iterator_new (input, result, 0, in_format, GEGL_BUFFER_READ, GEGL_ABYSS_NONE); gegl_buffer_iterator_add (gi, output, result, 0, out_format, GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (gi)) { if (alpha) memcpy (gi->data[1], gi->data[0], bpp * gi->length); cmsDoTransform (transform, gi->data[0], gi->data[1], gi->length); } } cmsDeleteTransform (transform); return TRUE; }
static void gimp_operation_cage_transform_init (GimpOperationCageTransform *self) { self->format_coords = babl_format_n(babl_type("float"), 2); }
static void stamp (GeglChantO *o, const GeglRectangle *result, gdouble x, gdouble y) { WarpPrivate *priv = (WarpPrivate*) o->chant_data; GeglBufferIterator *it; const Babl *format; gdouble influence; gdouble x_mean = 0.0; gdouble y_mean = 0.0; gint x_iter, y_iter; GeglRectangle area = {x - o->size / 2.0, y - o->size / 2.0, o->size, o->size}; /* first point of the stroke */ if (!priv->last_point_set) { priv->last_x = x; priv->last_y = y; priv->last_point_set = TRUE; return; } /* don't stamp if outside the roi treated */ if (!gegl_rectangle_intersect (NULL, result, &area)) return; 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_BUFFER_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; } it = gegl_buffer_iterator_new (priv->buffer, &area, 0, format, GEGL_BUFFER_READWRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (it)) { /* iterate inside the stamp roi */ gint n_pixels = it->length; gfloat *coords = it->data[0]; x_iter = it->roi->x; /* initial x */ y_iter = it->roi->y; /* and y coordinates */ while (n_pixels--) { influence = 0.01 * o->strength * get_stamp_force (o, x_iter - x, y_iter - y); switch (o->behavior) { case GEGL_WARP_BEHAVIOR_MOVE: coords[0] += influence * (priv->last_x - x); coords[1] += influence * (priv->last_y - y); break; case GEGL_WARP_BEHAVIOR_GROW: coords[0] -= 2.0 * influence * (x_iter - x) / o->size; coords[1] -= 2.0 * influence * (y_iter - y) / o->size; break; case GEGL_WARP_BEHAVIOR_SHRINK: coords[0] += 2.0 * influence * (x_iter - x) / o->size; coords[1] += 2.0 * influence * (y_iter - y) / o->size; break; case GEGL_WARP_BEHAVIOR_SWIRL_CW: coords[0] += 3.0 * influence * (y_iter - y) / o->size; coords[1] -= 5.0 * influence * (x_iter - x) / o->size; break; case GEGL_WARP_BEHAVIOR_SWIRL_CCW: coords[0] -= 3.0 * influence * (y_iter - y) / o->size; coords[1] += 5.0 * influence * (x_iter - x) / o->size; break; case GEGL_WARP_BEHAVIOR_ERASE: coords[0] *= 1.0 - MIN (influence, 1.0); coords[1] *= 1.0 - MIN (influence, 1.0); break; case GEGL_WARP_BEHAVIOR_SMOOTH: coords[0] -= influence * (coords[0] - x_mean); coords[1] -= influence * (coords[1] - y_mean); break; } coords += 2; /* update x and y coordinates */ x_iter++; if (x_iter >= (it->roi->x + it->roi->width)) { x_iter = it->roi->x; y_iter++; } } } /* Memorize the stamp location for movement dependant behavior like move */ priv->last_x = x; priv->last_y = y; }
static gboolean gimp_warp_tool_start (GimpWarpTool *wt, GimpDisplay *display) { GimpTool *tool = GIMP_TOOL (wt); GimpWarpOptions *options = GIMP_WARP_TOOL_GET_OPTIONS (wt); GimpImage *image = gimp_display_get_image (display); GimpDrawable *drawable = gimp_image_get_active_drawable (image); const Babl *format; GeglRectangle bbox; if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable))) { gimp_tool_message_literal (tool, display, _("Cannot warp layer groups.")); return FALSE; } if (gimp_item_is_content_locked (GIMP_ITEM (drawable))) { gimp_tool_message_literal (tool, display, _("The active layer's pixels are locked.")); return FALSE; } if (! gimp_item_is_visible (GIMP_ITEM (drawable))) { gimp_tool_message_literal (tool, display, _("The active layer is not visible.")); return FALSE; } tool->display = display; tool->drawable = drawable; /* Create the coords buffer, with the size of the selection */ format = babl_format_n (babl_type ("float"), 2); gimp_item_mask_intersect (GIMP_ITEM (drawable), &bbox.x, &bbox.y, &bbox.width, &bbox.height); #ifdef WARP_DEBUG g_printerr ("Initialize coordinate buffer (%d,%d) at %d,%d\n", bbox.width, bbox.height, bbox.x, bbox.y); #endif wt->coords_buffer = gegl_buffer_new (&bbox, format); gimp_warp_tool_create_filter (wt, drawable); if (! gimp_draw_tool_is_active (GIMP_DRAW_TOOL (wt))) gimp_draw_tool_start (GIMP_DRAW_TOOL (wt), display); if (options->animate_button) { g_signal_connect_swapped (options->animate_button, "clicked", G_CALLBACK (gimp_warp_tool_animate), wt); gtk_widget_set_sensitive (options->animate_button, TRUE); } return TRUE; }