static int test_buffer_cast (void) { gint result = SUCCESS; GeglBuffer *buffer = gegl_buffer_new (GEGL_RECTANGLE (0,0,1,1), babl_format ("R'G'B'A u8")); GeglBuffer *cbuffer = gegl_buffer_new (GEGL_RECTANGLE (0,0,1,1), babl_format ("Y u8")); guchar srcpix[4] = {1,2,3,4}; guchar dstpix[4] = {0}; gegl_buffer_set (buffer, NULL, 0, NULL, srcpix, GEGL_AUTO_ROWSTRIDE); gegl_buffer_set_format (cbuffer, babl_format_new ("name", "B' u8", babl_model ("R'G'B'A"), babl_type ("u8"), babl_component ("B'"), NULL)); gegl_buffer_copy (buffer, NULL, cbuffer, NULL); gegl_buffer_set_format (cbuffer, NULL); gegl_buffer_get (cbuffer, NULL, 1.0, NULL, dstpix, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); if (dstpix[0] != 3) result = FAILURE; g_object_unref (buffer); g_object_unref (cbuffer); return result; }
static void cpn_affine_transform_clamp (GeglBuffer *buffer, gdouble min, gdouble max) { GeglBufferIterator *gi; gdouble scale = 1.0 / (max - min); gdouble offset = - min; /* We want to scale values linearly, regardless of the format of the buffer */ gegl_buffer_set_format (buffer, babl_format ("Y double")); gi = gegl_buffer_iterator_new (buffer, NULL, 0, NULL, GEGL_BUFFER_READWRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (gi)) { guint k; double *data; data = (double*) gi->data[0]; for (k = 0; k < gi->length; k++) { data[k] = CLAMP ((data[k] + offset) * scale, 0.0, 1.0); } } }
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 gboolean process (GeglOperation *operation, GeglOperationContext *context, const gchar *output_prop, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); GeglBuffer *input; GeglBuffer *output; if (! o->input_format || ! o->output_format) { g_warning ("cast-format: input-format or output-format are not set"); return FALSE; } if (babl_format_get_bytes_per_pixel (o->input_format) != babl_format_get_bytes_per_pixel (o->output_format)) { g_warning ("cast-format: input-format and output-format have different bpp"); return FALSE; } if (strcmp (output_prop, "output")) { g_warning ("cast-format: requested processing of %s pad", output_prop); return FALSE; } input = gegl_operation_context_get_source (context, "input"); if (! input) { g_warning ("cast: received NULL input"); return FALSE; } output = gegl_buffer_new (roi, o->input_format); gegl_buffer_copy (input, roi, GEGL_ABYSS_NONE, output, roi); gegl_buffer_set_format (output, o->output_format); g_object_unref (input); gegl_operation_context_take_object (context, "output", G_OBJECT (output)); return TRUE; }
static GeglBuffer * gradient_precalc_shapeburst (GimpImage *image, GimpDrawable *drawable, const GeglRectangle *region, gdouble dist, GimpProgress *progress) { GimpChannel *mask; GeglBuffer *dist_buffer; GeglBuffer *temp_buffer; GeglNode *shapeburst; gdouble max; gfloat max_iteration; gimp_progress_set_text (progress, _("Calculating distance map")); /* allocate the distance map */ dist_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, region->width, region->height), babl_format ("Y float")); /* allocate the selection mask copy * XXX: its format should be the same of gimp:shapeburst input buffer * porting the op to 'float' should be reflected here as well */ temp_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, region->width, region->height), babl_format ("Y u8")); mask = gimp_image_get_mask (image); /* If the image mask is not empty, use it as the shape burst source */ if (! gimp_channel_is_empty (mask)) { gint x, y, width, height; gint off_x, off_y; gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height); gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); /* copy the mask to the temp mask */ gegl_buffer_copy (gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)), GEGL_RECTANGLE (x + off_x, y + off_y, width, height), temp_buffer, GEGL_RECTANGLE (0, 0, 0, 0)); } else { /* If the intended drawable has an alpha channel, use that */ if (gimp_drawable_has_alpha (drawable)) { const Babl *component_format; component_format = babl_format ("A u8"); /* extract the aplha into the temp mask */ gegl_buffer_set_format (temp_buffer, component_format); gegl_buffer_copy (gimp_drawable_get_buffer (drawable), GEGL_RECTANGLE (region->x, region->y, region->width, region->height), temp_buffer, GEGL_RECTANGLE (0, 0, 0, 0)); gegl_buffer_set_format (temp_buffer, NULL); } else { GeglColor *white = gegl_color_new ("white"); /* Otherwise, just fill the shapeburst to white */ gegl_buffer_set_color (temp_buffer, NULL, white); g_object_unref (white); } } shapeburst = gegl_node_new_child (NULL, "operation", "gimp:shapeburst", NULL); gimp_gegl_progress_connect (shapeburst, progress, NULL); gimp_gegl_apply_operation (temp_buffer, NULL, NULL, shapeburst, dist_buffer, NULL); gegl_node_get (shapeburst, "max-iterations", &max, NULL); g_object_unref (shapeburst); max_iteration = max; g_object_unref (temp_buffer); /* normalize the shapeburst with the max iteration */ if (max_iteration > 0) { GeglBufferIterator *iter; iter = gegl_buffer_iterator_new (dist_buffer, NULL, 0, NULL, GEGL_BUFFER_READWRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) { gint count = iter->length; gfloat *data = iter->data[0]; while (count--) *data++ /= max_iteration; } } return dist_buffer; }
static void gimp_brush_clipboard_buffer_changed (Gimp *gimp, GimpBrush *brush) { gint width; gint height; if (brush->mask) { gimp_temp_buf_unref (brush->mask); brush->mask = NULL; } if (brush->pixmap) { gimp_temp_buf_unref (brush->pixmap); brush->pixmap = NULL; } if (gimp->global_buffer) { GeglBuffer *buffer = gimp_buffer_get_buffer (gimp->global_buffer); const Babl *format = gegl_buffer_get_format (buffer); GeglBuffer *dest_buffer; width = MIN (gimp_buffer_get_width (gimp->global_buffer), 512); height = MIN (gimp_buffer_get_height (gimp->global_buffer), 512); brush->mask = gimp_temp_buf_new (width, height, babl_format ("Y u8")); brush->pixmap = gimp_temp_buf_new (width, height, babl_format ("R'G'B' u8")); /* copy the alpha channel into the brush's mask */ if (babl_format_has_alpha (format)) { dest_buffer = gimp_temp_buf_create_buffer (brush->mask); gegl_buffer_set_format (dest_buffer, babl_format ("A u8")); gegl_buffer_copy (buffer, NULL, dest_buffer, NULL); g_object_unref (dest_buffer); } else { memset (gimp_temp_buf_get_data (brush->mask), 255, width * height); } /* copy the color channels into the brush's pixmap */ dest_buffer = gimp_temp_buf_create_buffer (brush->pixmap); gegl_buffer_copy (buffer, NULL, dest_buffer, NULL); g_object_unref (dest_buffer); } else { width = 17; height = 17; brush->mask = gimp_temp_buf_new (width, height, babl_format ("Y u8")); gimp_temp_buf_data_clear (brush->mask); } brush->x_axis.x = width / 2; brush->x_axis.y = 0; brush->y_axis.x = 0; brush->y_axis.y = height / 2; gimp_data_dirty (GIMP_DATA (brush)); }
static GeglBuffer * gradient_precalc_shapeburst (GimpImage *image, GimpDrawable *drawable, const GeglRectangle *region, gdouble dist, GimpProgress *progress) { GimpChannel *mask; GeglBuffer *dist_buffer; GeglBuffer *temp_buffer; GeglNode *shapeburst; gimp_progress_set_text (progress, _("Calculating distance map")); /* allocate the distance map */ dist_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, region->width, region->height), babl_format ("Y float")); /* allocate the selection mask copy */ temp_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, region->width, region->height), babl_format ("Y float")); mask = gimp_image_get_mask (image); /* If the image mask is not empty, use it as the shape burst source */ if (! gimp_channel_is_empty (mask)) { gint x, y, width, height; gint off_x, off_y; gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height); gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); /* copy the mask to the temp mask */ gegl_buffer_copy (gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)), GEGL_RECTANGLE (x + off_x, y + off_y, width, height), temp_buffer, GEGL_RECTANGLE (0, 0, 0, 0)); } else { /* If the intended drawable has an alpha channel, use that */ if (gimp_drawable_has_alpha (drawable)) { const Babl *component_format; component_format = babl_format ("A float"); /* extract the aplha into the temp mask */ gegl_buffer_set_format (temp_buffer, component_format); gegl_buffer_copy (gimp_drawable_get_buffer (drawable), GEGL_RECTANGLE (region->x, region->y, region->width, region->height), temp_buffer, GEGL_RECTANGLE (0, 0, 0, 0)); gegl_buffer_set_format (temp_buffer, NULL); } else { GeglColor *white = gegl_color_new ("white"); /* Otherwise, just fill the shapeburst to white */ gegl_buffer_set_color (temp_buffer, NULL, white); g_object_unref (white); } } shapeburst = gegl_node_new_child (NULL, "operation", "gimp:shapeburst", "normalize", TRUE, NULL); gimp_gegl_progress_connect (shapeburst, progress, NULL); gimp_gegl_apply_operation (temp_buffer, NULL, NULL, shapeburst, dist_buffer, NULL); g_object_unref (shapeburst); g_object_unref (temp_buffer); return dist_buffer; }
static void gegl_buffer_set_property (GObject *gobject, guint property_id, const GValue *value, GParamSpec *pspec) { GeglBuffer *buffer = GEGL_BUFFER (gobject); switch (property_id) { case PROP_X: buffer->extent.x = g_value_get_int (value); break; case PROP_Y: buffer->extent.y = g_value_get_int (value); break; case PROP_WIDTH: buffer->extent.width = g_value_get_int (value); break; case PROP_HEIGHT: buffer->extent.height = g_value_get_int (value); break; case PROP_TILE_HEIGHT: buffer->tile_height = g_value_get_int (value); break; case PROP_TILE_WIDTH: buffer->tile_width = g_value_get_int (value); break; case PROP_PATH: if (buffer->path) g_free (buffer->path); buffer->path = g_value_dup_string (value); break; case PROP_SHIFT_X: buffer->shift_x = g_value_get_int (value); break; case PROP_SHIFT_Y: buffer->shift_y = g_value_get_int (value); break; case PROP_ABYSS_X: buffer->abyss.x = g_value_get_int (value); break; case PROP_ABYSS_Y: buffer->abyss.y = g_value_get_int (value); break; case PROP_ABYSS_WIDTH: buffer->abyss.width = g_value_get_int (value); break; case PROP_ABYSS_HEIGHT: buffer->abyss.height = g_value_get_int (value); break; case PROP_FORMAT: /* Do not set to NULL even if asked to do so by a non-overriden * value, this is needed since a default value can not be specified * for a gpointer paramspec */ if (g_value_get_pointer (value)) { const Babl *format = g_value_get_pointer (value); /* XXX: need to check if the internal format matches, should * perhaps do different things here depending on whether * we are during construction or not */ if (buffer->soft_format) { gegl_buffer_set_format (buffer, format); } else { buffer->format = format; } } break; case PROP_BACKEND: if (g_value_get_pointer (value)) buffer->backend = g_value_get_pointer (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec); break; } }