static GimpTempBuf * gimp_buffer_get_new_preview (GimpViewable *viewable, GimpContext *context, gint width, gint height) { GimpBuffer *buffer = GIMP_BUFFER (viewable); const Babl *format = gimp_buffer_get_format (buffer); GimpTempBuf *preview; if (babl_format_is_palette (format)) format = gimp_babl_format (GIMP_RGB, GIMP_PRECISION_U8_GAMMA, babl_format_has_alpha (format)); else format = gimp_babl_format (gimp_babl_format_get_base_type (format), gimp_babl_precision (GIMP_COMPONENT_TYPE_U8, gimp_babl_format_get_linear (format)), babl_format_has_alpha (format)); preview = gimp_temp_buf_new (width, height, format); gegl_buffer_get (buffer->buffer, GEGL_RECTANGLE (0, 0, width, height), MIN ((gdouble) width / (gdouble) gimp_buffer_get_width (buffer), (gdouble) height / (gdouble) gimp_buffer_get_height (buffer)), format, gimp_temp_buf_get_data (preview), GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); return preview; }
static void prepare (GeglOperation *operation) { GeglOperationAreaFilter *area = GEGL_OPERATION_AREA_FILTER (operation); GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *in_format = gegl_operation_get_source_format (operation, "input"); const Babl *format = babl_format ("RGB float"); area->left = area->right = area->top = area->bottom = o->radius; o->user_data = g_renew (gint, o->user_data, o->radius + 1); init_neighborhood_outline (o->neighborhood, o->radius, o->user_data); if (in_format) { if (babl_format_has_alpha (in_format)) format = babl_format ("RGBA float"); } gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "output", format); }
static void prepare (GeglOperation *operation) { const Babl *src_format = gegl_operation_get_source_format (operation, "input"); const char *format = "RGB float"; if (src_format) { const Babl *model = babl_format_get_model (src_format); if (model == babl_model ("RGB")) format = "RGB float"; else if (model == babl_model ("RGBA")) format = "RGBA float"; else if (model == babl_model ("R'G'B'")) format = "R'G'B' float"; else if (model == babl_model ("R'G'B'A")) format = "R'G'B'A float"; else if (babl_format_has_alpha (src_format)) format = "RGBA float"; } gegl_operation_set_format (operation, "input", babl_format (format)); gegl_operation_set_format (operation, "output", babl_format (format)); }
GimpTempBuf * gimp_image_get_new_preview (GimpViewable *viewable, GimpContext *context, gint width, gint height) { GimpImage *image = GIMP_IMAGE (viewable); const Babl *format; gboolean linear; GimpTempBuf *buf; gdouble scale_x; gdouble scale_y; scale_x = (gdouble) width / (gdouble) gimp_image_get_width (image); scale_y = (gdouble) height / (gdouble) gimp_image_get_height (image); format = gimp_projectable_get_format (GIMP_PROJECTABLE (image)); linear = gimp_babl_format_get_linear (format); format = gimp_babl_format (gimp_babl_format_get_base_type (format), gimp_babl_precision (GIMP_COMPONENT_TYPE_U8, linear), babl_format_has_alpha (format)); buf = gimp_temp_buf_new (width, height, format); gegl_buffer_get (gimp_pickable_get_buffer (GIMP_PICKABLE (image)), GEGL_RECTANGLE (0, 0, width, height), MIN (scale_x, scale_y), gimp_temp_buf_get_format (buf), gimp_temp_buf_get_data (buf), GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); return buf; }
GimpTransformResize gimp_drawable_transform_get_effective_clip (GimpDrawable *drawable, GeglBuffer *orig_buffer, GimpTransformResize clip_result) { g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), clip_result); g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), clip_result); g_return_val_if_fail (orig_buffer == NULL || GEGL_IS_BUFFER (orig_buffer), clip_result); /* Always clip unfloated buffers since they must keep their size */ if (GIMP_IS_CHANNEL (drawable)) { if (orig_buffer) { if (! babl_format_has_alpha (gegl_buffer_get_format (orig_buffer))) clip_result = GIMP_TRANSFORM_RESIZE_CLIP; } else { GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); if (gimp_channel_is_empty (gimp_image_get_mask (image))) clip_result = GIMP_TRANSFORM_RESIZE_CLIP; } } return clip_result; }
const Babl * gimp_babl_compat_u8_format (const Babl *format) { g_return_val_if_fail (format != NULL, NULL); /* indexed images only exist in u8, return the same format */ if (babl_format_is_palette (format)) return format; return gimp_babl_format (gimp_babl_format_get_base_type (format), GIMP_PRECISION_U8, babl_format_has_alpha (format)); }
static gboolean process (GeglOperation *operation, GeglBuffer *input, const GeglRectangle *result, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); if (o->pixbuf) { GdkPixbuf **pixbuf = o->pixbuf; const Babl *babl; const Babl *format; guchar *temp; GeglRectangle *rect = gegl_operation_source_get_bounding_box (operation, "input"); gchar *name; gboolean has_alpha; gint bps; g_object_get (input, "format", &format, NULL); has_alpha = babl_format_has_alpha (format); /* pixbuf from data only support 8bit bps */ bps = 8; name = g_strdup_printf ("R'G'B'%s u%i", has_alpha ? "A" : "", bps); babl = babl_format (name); temp = g_malloc (rect->width * rect->height * bps); gegl_buffer_get (input, rect, 1.0, babl, temp, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); if (temp) { *pixbuf = gdk_pixbuf_new_from_data (temp, GDK_COLORSPACE_RGB, has_alpha, bps, rect->width, rect->height, rect->width * (has_alpha ? 4 : 3) * bps/8, (GdkPixbufDestroyNotify) g_free, NULL); } else { g_warning (G_STRLOC ": inexistant data, unable to create GdkPixbuf."); } g_free (name); } return TRUE; }
static gboolean gimp_drawable_edit_can_fill_direct (GimpDrawable *drawable, GimpFillOptions *options) { GimpImage *image; GimpContext *context; gdouble opacity; GimpComponentMask affect; GimpLayerMode mode; GimpLayerCompositeMode composite_mode; GimpLayerCompositeRegion composite_region; image = gimp_item_get_image (GIMP_ITEM (drawable)); context = GIMP_CONTEXT (options); opacity = gimp_context_get_opacity (context); affect = gimp_drawable_get_active_mask (drawable); mode = gimp_context_get_paint_mode (context); composite_mode = gimp_layer_mode_get_paint_composite_mode (mode); composite_region = gimp_layer_mode_get_included_region (mode, composite_mode); if (gimp_channel_is_empty (gimp_image_get_mask (image)) && opacity == GIMP_OPACITY_OPAQUE && affect == GIMP_COMPONENT_MASK_ALL && gimp_layer_mode_is_trivial (mode) && (! gimp_layer_mode_is_subtractive (mode) ^ ! (composite_region & GIMP_LAYER_COMPOSITE_REGION_SOURCE))) { switch (gimp_fill_options_get_style (options)) { case GIMP_FILL_STYLE_SOLID: return TRUE; case GIMP_FILL_STYLE_PATTERN: { GimpPattern *pattern; GimpTempBuf *mask; const Babl *format; pattern = gimp_context_get_pattern (context); mask = gimp_pattern_get_mask (pattern); format = gimp_temp_buf_get_format (mask); return ! babl_format_has_alpha (format); } } } return FALSE; }
static void prepare (GeglOperation *operation) { GeglOperationAreaFilter *area = GEGL_OPERATION_AREA_FILTER (operation); //GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); const Babl *source_format = gegl_operation_get_source_format (operation, "input"); area->left = area->right = area->top = area->bottom = SOBEL_RADIUS; gegl_operation_set_format (operation, "input", babl_format ("RGBA float")); if (source_format && !babl_format_has_alpha (source_format)) gegl_operation_set_format (operation, "output", babl_format ("RGB float")); else gegl_operation_set_format (operation, "output", babl_format ("RGBA float")); }
static void prepare (GeglOperation *operation) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *format; const Babl *input_format; const Babl *input_model; const Babl *lch_model; input_format = gegl_operation_get_source_format (operation, "input"); if (input_format == NULL) return; input_model = babl_format_get_model (input_format); if (babl_format_has_alpha (input_format)) { lch_model = babl_model ("CIE LCH(ab) alpha"); if (input_model == lch_model) { format = babl_format ("CIE LCH(ab) alpha float"); o->user_data = process_lch_alpha; } else { format = babl_format ("CIE Lab alpha float"); o->user_data = process_lab_alpha; } } else { lch_model = babl_model ("CIE LCH(ab)"); if (input_model == lch_model) { format = babl_format ("CIE LCH(ab) float"); o->user_data = process_lch; } else { format = babl_format ("CIE Lab float"); o->user_data = process_lab; } } gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "output", format); }
GimpImageType gimp_babl_format_get_image_type (const Babl *format) { const gchar *name; g_return_val_if_fail (format != NULL, -1); name = babl_get_name (babl_format_get_model (format)); if (! strcmp (name, "Y") || ! strcmp (name, "Y'") || ! strcmp (name, "Y~")) { return GIMP_GRAY_IMAGE; } else if (! strcmp (name, "YA") || ! strcmp (name, "Y'A") || ! strcmp (name, "Y~A")) { return GIMP_GRAYA_IMAGE; } else if (! strcmp (name, "RGB") || ! strcmp (name, "R'G'B'") || ! strcmp (name, "R~G~B~")) { return GIMP_RGB_IMAGE; } else if (! strcmp (name, "RGBA") || ! strcmp (name, "R'G'B'A") || ! strcmp (name, "R~G~B~A")) { return GIMP_RGBA_IMAGE; } else if (babl_format_is_palette (format)) { if (babl_format_has_alpha (format)) return GIMP_INDEXEDA_IMAGE; else return GIMP_INDEXED_IMAGE; } g_return_val_if_reached (-1); }
static const Babl * choose_format (GeglBuffer *buffer, GimpSelectCriterion select_criterion, gint *n_components, gboolean *has_alpha) { const Babl *format = gegl_buffer_get_format (buffer); *has_alpha = babl_format_has_alpha (format); switch (select_criterion) { case GIMP_SELECT_CRITERION_COMPOSITE: if (babl_format_is_palette (format)) format = babl_format ("R'G'B'A float"); else format = gimp_babl_format (gimp_babl_format_get_base_type (format), GIMP_PRECISION_FLOAT_GAMMA, *has_alpha); break; case GIMP_SELECT_CRITERION_R: case GIMP_SELECT_CRITERION_G: case GIMP_SELECT_CRITERION_B: case GIMP_SELECT_CRITERION_A: format = babl_format ("R'G'B'A float"); break; case GIMP_SELECT_CRITERION_H: case GIMP_SELECT_CRITERION_S: case GIMP_SELECT_CRITERION_V: format = babl_format ("HSVA float"); break; default: g_return_val_if_reached (NULL); break; } *n_components = babl_format_get_n_components (format); return format; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); GeglRectangle compute; gboolean has_alpha; compute = gegl_operation_get_required_for_output (operation, "input", result); has_alpha = babl_format_has_alpha (gegl_operation_get_format (operation, "output")); if (gegl_operation_use_opencl (operation)) if (cl_process (operation, input, output, result, has_alpha)) return TRUE; edge_sobel (input, &compute, output, result, o->horizontal, o->vertical, o->keep_signal, has_alpha); return TRUE; }
static void prepare (GeglOperation *operation) { const Babl *input_format = gegl_operation_get_source_format (operation, "input"); const Babl *format; GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation); if (input_format == NULL || babl_format_has_alpha (input_format)) format = babl_format ("R'G'B'A float"); else format = babl_format ("R'G'B' float"); gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "output", format); op_area->left = op_area->right = op_area->top = op_area->bottom = 1; }
static void prepare (GeglOperation *operation) { const Babl *input_format = gegl_operation_get_source_format (operation, "input"); GeglProperties *o = GEGL_PROPERTIES (operation); CmParamsType *mix; const Babl *format; if (o->user_data == NULL) o->user_data = g_slice_new0 (CmParamsType); mix = (CmParamsType*) o->user_data; mix->preserve_luminosity = o->preserve_luminosity; mix->red.red_gain = o->rr_gain; mix->red.green_gain = o->rg_gain; mix->red.blue_gain = o->rb_gain; mix->green.red_gain = o->gr_gain; mix->green.green_gain = o->gg_gain; mix->green.blue_gain = o->gb_gain; mix->blue.red_gain = o->br_gain; mix->blue.green_gain = o->bg_gain; mix->blue.blue_gain = o->bb_gain; if (input_format == NULL || babl_format_has_alpha (input_format)) { mix->has_alpha = TRUE; format = babl_format ("R'G'B'A float"); } else { mix->has_alpha = FALSE; format = babl_format ("R'G'B' float"); } gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "output", format); }
GimpImageType gimp_babl_format_get_image_type (const Babl *format) { const Babl *model; g_return_val_if_fail (format != NULL, -1); model = babl_format_get_model (format); if (model == babl_model ("Y") || model == babl_model ("Y'")) { return GIMP_GRAY_IMAGE; } else if (model == babl_model ("YA") || model == babl_model ("Y'A")) { return GIMP_GRAYA_IMAGE; } else if (model == babl_model ("RGB") || model == babl_model ("R'G'B'")) { return GIMP_RGB_IMAGE; } else if (model == babl_model ("RGBA") || model == babl_model ("R'G'B'A")) { return GIMP_RGBA_IMAGE; } else if (babl_format_is_palette (format)) { if (babl_format_has_alpha (format)) return GIMP_INDEXEDA_IMAGE; else return GIMP_INDEXED_IMAGE; } g_return_val_if_reached (-1); }
static void prepare (GeglOperation *operation) { GeglOperationAreaFilter *area = GEGL_OPERATION_AREA_FILTER (operation); GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *in_format = gegl_operation_get_source_format (operation, "input"); const Babl *format = babl_format ("RGB float");; area->left = area->right = area->top = area->bottom = o->radius; if (in_format) { if (babl_format_has_alpha (in_format)) format = babl_format ("RGBA float"); } gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "output", format); }
static void prepare (GeglOperation *operation) { GeglOperationAreaFilter *area = GEGL_OPERATION_AREA_FILTER (operation); const Babl *input_f = gegl_operation_get_source_format (operation, "input"); const Babl *format = babl_format ("R'G'B' float"); area->left = area->right = area->top = area->bottom = 1; if (input_f) { if (babl_format_has_alpha (input_f)) format = babl_format ("R'G'B'A float"); } gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "output", format); }
const gchar * gimp_babl_get_description (const Babl *babl) { const gchar *description; g_return_val_if_fail (babl != NULL, NULL); if (G_UNLIKELY (! babl_description_hash)) { gint i; babl_description_hash = g_hash_table_new (g_str_hash, g_str_equal); for (i = 0; i < G_N_ELEMENTS (babl_descriptions); i++) g_hash_table_insert (babl_description_hash, (gpointer) babl_descriptions[i].name, gettext (babl_descriptions[i].description)); } if (babl_format_is_palette (babl)) { if (babl_format_has_alpha (babl)) return _("Indexed-alpha"); else return _("Indexed"); } description = g_hash_table_lookup (babl_description_hash, babl_get_name (babl)); if (description) return description; return g_strconcat ("ERROR: unknown Babl format ", babl_get_name (babl), NULL); }
GimpDrawable * gimp_drawable_transform_affine (GimpDrawable *drawable, GimpContext *context, const GimpMatrix3 *matrix, GimpTransformDirection direction, GimpInterpolationType interpolation_type, gint recursion_level, GimpTransformResize clip_result, GimpProgress *progress) { GimpImage *image; GeglBuffer *orig_buffer; gint orig_offset_x; gint orig_offset_y; gboolean new_layer; GimpDrawable *result = NULL; g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); g_return_val_if_fail (matrix != NULL, NULL); g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL); image = gimp_item_get_image (GIMP_ITEM (drawable)); /* Start a transform undo group */ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_TRANSFORM, C_("undo-type", "Transform")); /* Cut/Copy from the specified drawable */ orig_buffer = gimp_drawable_transform_cut (drawable, context, &orig_offset_x, &orig_offset_y, &new_layer); if (orig_buffer) { GeglBuffer *new_buffer; gint new_offset_x; gint new_offset_y; /* always clip unfloated buffers so they keep their size */ if (GIMP_IS_CHANNEL (drawable) && ! babl_format_has_alpha (gegl_buffer_get_format (orig_buffer))) clip_result = GIMP_TRANSFORM_RESIZE_CLIP; /* also transform the mask if we are transforming an entire layer */ if (GIMP_IS_LAYER (drawable) && gimp_layer_get_mask (GIMP_LAYER (drawable)) && gimp_channel_is_empty (gimp_image_get_mask (image))) { GimpLayerMask *mask = gimp_layer_get_mask (GIMP_LAYER (drawable)); gimp_item_transform (GIMP_ITEM (mask), context, matrix, direction, interpolation_type, recursion_level, clip_result, progress); } /* transform the buffer */ new_buffer = gimp_drawable_transform_buffer_affine (drawable, context, orig_buffer, orig_offset_x, orig_offset_y, matrix, direction, interpolation_type, recursion_level, clip_result, &new_offset_x, &new_offset_y, progress); /* Free the cut/copied buffer */ g_object_unref (orig_buffer); if (new_buffer) { result = gimp_drawable_transform_paste (drawable, new_buffer, new_offset_x, new_offset_y, new_layer); g_object_unref (new_buffer); } } /* push the undo group end */ gimp_image_undo_group_end (image); return result; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, const GeglRectangle *result, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *input_format; const Babl *data_format; gint bps; gint row_stride; gint n_components; guchar *data; CoglPixelFormat cogl_pixel_format; g_object_get (input, "format", &input_format, NULL); /* cogl doesnt support anything more than 8bit bps */ bps = 8; n_components = babl_format_get_n_components (input_format); switch (n_components) { case 1: data_format = babl_format ("Y'"); cogl_pixel_format = COGL_PIXEL_FORMAT_G_8; break; default: if (babl_format_has_alpha (input_format)) { data_format = babl_format_new (babl_model ("R'G'B'A"), babl_type ("u8"), babl_component ("B'"), babl_component ("G'"), babl_component ("R'"), babl_component ("A"), NULL); cogl_pixel_format = COGL_PIXEL_FORMAT_BGRA_8888; n_components = 4; } else { data_format = babl_format_new (babl_model ("R'G'B'"), babl_type ("u8"), babl_component ("B'"), babl_component ("G'"), babl_component ("R'"), NULL); cogl_pixel_format = COGL_PIXEL_FORMAT_BGR_888; n_components = 3; } break; } row_stride = result->width * n_components * bps/8; data = g_malloc (result->height * row_stride); gegl_buffer_get (input, result, /* rect */ 1.0, /* scale */ data_format, data, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); if (data) { if (o->texture == NULL) { CoglTextureFlags flags = COGL_TEXTURE_NONE; if (result->width >= 512 && result->height >= 512) { flags |= COGL_TEXTURE_NO_ATLAS; } o->texture = cogl_texture_new_from_data (result->width, result->height, flags, cogl_pixel_format, COGL_PIXEL_FORMAT_ANY, row_stride, data); } else { gboolean success; success = cogl_texture_set_region (COGL_TEXTURE (o->texture), 0, 0, result->x, result->y, result->width, result->height, result->width, result->height, cogl_pixel_format, row_stride, data); if (!success) { cogl_object_unref (o->texture); o->texture = NULL; } } } else { g_warning (G_STRLOC ": inexistant data, unable to create CoglTexture."); } return TRUE; }
static gboolean process (GeglOperation *operation, void *in_buf, void *out_buf, glong n_pixels, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *format = gegl_operation_get_format (operation, "input"); gboolean has_alpha = babl_format_has_alpha (format); gint n_components = has_alpha ? 4 : 3; gfloat *input = in_buf; gfloat *output = out_buf; if (o->clip_low && o->clip_high) { while (n_pixels--) { output[0] = CLAMP (input[0], o->low_limit, o->high_limit); output[1] = CLAMP (input[1], o->low_limit, o->high_limit); output[2] = CLAMP (input[2], o->low_limit, o->high_limit); if (has_alpha) output[3] = input[3]; input += n_components; output += n_components; } } else if (o->clip_high) { while (n_pixels--) { output[0] = input[0] > o->high_limit ? o->high_limit : input[0]; output[1] = input[1] > o->high_limit ? o->high_limit : input[1]; output[2] = input[2] > o->high_limit ? o->high_limit : input[2]; if (has_alpha) output[3] = input[3]; input += n_components; output += n_components; } } else if (o->clip_low) { while (n_pixels--) { output[0] = input[0] < o->low_limit ? o->low_limit : input[0]; output[1] = input[1] < o->low_limit ? o->low_limit : input[1]; output[2] = input[2] < o->low_limit ? o->low_limit : input[2]; if (has_alpha) output[3] = input[3]; input += n_components; output += n_components; } } return TRUE; }
/** * 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); } }
GimpDrawable * gimp_drawable_transform_rotate (GimpDrawable *drawable, GimpContext *context, GimpRotationType rotate_type, gdouble center_x, gdouble center_y, gboolean clip_result) { GimpImage *image; GeglBuffer *orig_buffer; gint orig_offset_x; gint orig_offset_y; gboolean new_layer; GimpDrawable *result = NULL; g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); image = gimp_item_get_image (GIMP_ITEM (drawable)); /* Start a transform undo group */ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_TRANSFORM, C_("undo-type", "Rotate")); /* Cut/Copy from the specified drawable */ orig_buffer = gimp_drawable_transform_cut (drawable, context, &orig_offset_x, &orig_offset_y, &new_layer); if (orig_buffer) { GeglBuffer *new_buffer; gint new_offset_x; gint new_offset_y; /* always clip unfloated buffers so they keep their size */ if (GIMP_IS_CHANNEL (drawable) && ! babl_format_has_alpha (gegl_buffer_get_format (orig_buffer))) clip_result = TRUE; /* also transform the mask if we are transforming an entire layer */ if (GIMP_IS_LAYER (drawable) && gimp_layer_get_mask (GIMP_LAYER (drawable)) && gimp_channel_is_empty (gimp_image_get_mask (image))) { GimpLayerMask *mask = gimp_layer_get_mask (GIMP_LAYER (drawable)); gimp_item_rotate (GIMP_ITEM (mask), context, rotate_type, center_x, center_y, clip_result); } /* transform the buffer */ new_buffer = gimp_drawable_transform_buffer_rotate (drawable, context, orig_buffer, orig_offset_x, orig_offset_y, rotate_type, center_x, center_y, clip_result, &new_offset_x, &new_offset_y); /* Free the cut/copied buffer */ g_object_unref (orig_buffer); if (new_buffer) { result = gimp_drawable_transform_paste (drawable, new_buffer, new_offset_x, new_offset_y, new_layer); g_object_unref (new_buffer); } } /* push the undo group end */ gimp_image_undo_group_end (image); return result; }
GeglBuffer * gimp_drawable_transform_buffer_affine (GimpDrawable *drawable, GimpContext *context, GeglBuffer *orig_buffer, gint orig_offset_x, gint orig_offset_y, const GimpMatrix3 *matrix, GimpTransformDirection direction, GimpInterpolationType interpolation_type, gint recursion_level, GimpTransformResize clip_result, gint *new_offset_x, gint *new_offset_y, GimpProgress *progress) { GeglBuffer *new_buffer; GimpMatrix3 m; GimpMatrix3 inv; gint u1, v1, u2, v2; /* source bounding box */ gint x1, y1, x2, y2; /* target bounding box */ GeglNode *affine; GimpMatrix3 gegl_matrix; g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); g_return_val_if_fail (GEGL_IS_BUFFER (orig_buffer), NULL); g_return_val_if_fail (matrix != NULL, NULL); g_return_val_if_fail (new_offset_x != NULL, NULL); g_return_val_if_fail (new_offset_y != NULL, NULL); g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL); m = *matrix; inv = *matrix; if (direction == GIMP_TRANSFORM_BACKWARD) { /* keep the original matrix here, so we dont need to recalculate * the inverse later */ gimp_matrix3_invert (&inv); } else { /* Find the inverse of the transformation matrix */ gimp_matrix3_invert (&m); } u1 = orig_offset_x; v1 = orig_offset_y; u2 = u1 + gegl_buffer_get_width (orig_buffer); v2 = v1 + gegl_buffer_get_height (orig_buffer); /* Always clip unfloated buffers since they must keep their size */ if (G_TYPE_FROM_INSTANCE (drawable) == GIMP_TYPE_CHANNEL && ! babl_format_has_alpha (gegl_buffer_get_format (orig_buffer))) clip_result = GIMP_TRANSFORM_RESIZE_CLIP; /* Find the bounding coordinates of target */ gimp_transform_resize_boundary (&inv, clip_result, u1, v1, u2, v2, &x1, &y1, &x2, &y2); /* Get the new temporary buffer for the transformed result */ new_buffer = gimp_gegl_buffer_new (GEGL_RECTANGLE (0, 0, x2 - x1, y2 - y1), gegl_buffer_get_format (orig_buffer)); gimp_matrix3_identity (&gegl_matrix); gimp_matrix3_translate (&gegl_matrix, u1, v1); gimp_matrix3_mult (&inv, &gegl_matrix); gimp_matrix3_translate (&gegl_matrix, -x1, -y1); affine = gegl_node_new_child (NULL, "operation", "gegl:transform", "filter", gimp_interpolation_to_gegl_filter (interpolation_type), "hard-edges", TRUE, NULL); gimp_gegl_node_set_matrix (affine, &gegl_matrix); gimp_apply_operation (orig_buffer, progress, NULL, affine, new_buffer, NULL); g_object_unref (affine); *new_offset_x = x1; *new_offset_y = y1; return new_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]); } } } }
gint gegl_buffer_export_png (GeglBuffer *gegl_buffer, const gchar *path, gint compression, gint bd, gint src_x, gint src_y, gint width, gint height) { FILE *fp; gint i; png_struct *png; png_info *info; guchar *pixels; png_color_16 white; int png_color_type; gchar format_string[16]; const Babl *format; gint bit_depth = 8; if (!strcmp (path, "-")) { fp = stdout; } else { fp = fopen (path, "wb"); } if (!fp) { return -1; } { const Babl *babl = gegl_buffer_get_format (gegl_buffer); if (bd == 16) bit_depth = 16; else bit_depth = 8; if (babl_format_has_alpha (babl)) if (babl_format_get_n_components (babl) != 2) { png_color_type = PNG_COLOR_TYPE_RGB_ALPHA; strcpy (format_string, "R'G'B'A "); } else { png_color_type = PNG_COLOR_TYPE_GRAY_ALPHA; strcpy (format_string, "Y'A "); } else if (babl_format_get_n_components (babl) != 1) { png_color_type = PNG_COLOR_TYPE_RGB; strcpy (format_string, "R'G'B' "); } else { png_color_type = PNG_COLOR_TYPE_GRAY; strcpy (format_string, "Y' "); } } if (bit_depth == 16) strcat (format_string, "u16"); else strcat (format_string, "u8"); png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png == NULL) { if (stdout != fp) fclose (fp); return -1; } info = png_create_info_struct (png); if (setjmp (png_jmpbuf (png))) { if (stdout != fp) fclose (fp); return -1; } png_set_compression_level (png, compression); png_init_io (png, fp); png_set_IHDR (png, info, width, height, bit_depth, png_color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_DEFAULT); if (png_color_type == PNG_COLOR_TYPE_RGB || png_color_type == PNG_COLOR_TYPE_RGB_ALPHA) { white.red = 0xff; white.blue = 0xff; white.green = 0xff; } else white.gray = 0xff; png_set_bKGD (png, info, &white); png_write_info (png, info); #if BYTE_ORDER == LITTLE_ENDIAN if (bit_depth > 8) png_set_swap (png); #endif format = babl_format (format_string); pixels = g_malloc0 (width * babl_format_get_bytes_per_pixel (format)); for (i=0; i< height; i++) { GeglRectangle rect; rect.x = src_x; rect.y = src_y+i; rect.width = width; rect.height = 1; gegl_buffer_get (gegl_buffer, &rect, 1.0, babl_format (format_string), pixels, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); png_write_rows (png, &pixels, 1); } png_write_end (png, info); png_destroy_write_struct (&png, &info); g_free (pixels); if (stdout != fp) fclose (fp); return 0; }
static void lcms_layers_transform_rgb (gint *layers, gint num_layers, cmsHPROFILE src_profile, cmsHPROFILE dest_profile, GimpColorRenderingIntent intent, gboolean bpc) { gint i; for (i = 0; i < num_layers; i++) { gint32 layer_id = layers[i]; const Babl *layer_format; gboolean has_alpha; const Babl *type; const Babl *iter_format = NULL; cmsUInt32Number lcms_format = 0; cmsHTRANSFORM transform = NULL; gint *children; gint num_children; children = gimp_item_get_children (layer_id, &num_children); if (children) { lcms_layers_transform_rgb (children, num_children, src_profile, dest_profile, intent, bpc); g_free (children); continue; } layer_format = gimp_drawable_get_format (layer_id); has_alpha = babl_format_has_alpha (layer_format); type = babl_format_get_type (layer_format, 0); if (type == babl_type ("u8")) { if (has_alpha) { lcms_format = TYPE_RGBA_8; iter_format = babl_format ("R'G'B'A u8"); } else { lcms_format = TYPE_RGB_8; iter_format = babl_format ("R'G'B' u8"); } } else if (type == babl_type ("u16")) { if (has_alpha) { lcms_format = TYPE_RGBA_16; iter_format = babl_format ("R'G'B'A u16"); } else { lcms_format = TYPE_RGB_16; iter_format = babl_format ("R'G'B' u16"); } } else if (type == babl_type ("half")) /* 16-bit floating point (half) */ { #ifdef TYPE_RGB_HALF_FLT /* half float types are only in lcms 2.4 and newer */ if (has_alpha) { lcms_format = TYPE_RGBA_HALF_FLT; iter_format = babl_format ("R'G'B'A half"); } else { lcms_format = TYPE_RGB_HALF_FLT; iter_format = babl_format ("R'G'B' float"); } #endif /* TYPE_RGB_HALF_FLT */ } else if (type == babl_type ("float")) { if (has_alpha) { lcms_format = TYPE_RGBA_FLT; iter_format = babl_format ("R'G'B'A float"); } else { lcms_format = TYPE_RGB_FLT; iter_format = babl_format ("R'G'B' float"); } } else if (type == babl_type ("double")) { if (has_alpha) { #ifdef TYPE_RGBA_DBL /* RGBA double not implemented in lcms */ lcms_format = TYPE_RGBA_DBL; iter_format = babl_format ("R'G'B'A double"); #endif /* TYPE_RGBA_DBL */ } else { lcms_format = TYPE_RGB_DBL; iter_format = babl_format ("R'G'B' double"); } } if (lcms_format == 0) { g_printerr ("lcms: layer format %s not supported, " "falling back to float\n", babl_get_name (layer_format)); if (has_alpha) { lcms_format = TYPE_RGBA_FLT; iter_format = babl_format ("R'G'B'A float"); } else { lcms_format = TYPE_RGB_FLT; iter_format = babl_format ("R'G'B' float"); } } transform = cmsCreateTransform (src_profile, lcms_format, dest_profile, lcms_format, intent, cmsFLAGS_NOOPTIMIZE | (bpc ? cmsFLAGS_BLACKPOINTCOMPENSATION : 0)); if (transform) { GeglBuffer *src_buffer; GeglBuffer *dest_buffer; GeglBufferIterator *iter; gint layer_width; gint layer_height; gint layer_bpp; gboolean layer_alpha; gdouble progress_start = (gdouble) i / num_layers; gdouble progress_end = (gdouble) (i + 1) / num_layers; gdouble range = progress_end - progress_start; gint count = 0; gint done = 0; src_buffer = gimp_drawable_get_buffer (layer_id); dest_buffer = gimp_drawable_get_shadow_buffer (layer_id); layer_width = gegl_buffer_get_width (src_buffer); layer_height = gegl_buffer_get_height (src_buffer); layer_bpp = babl_format_get_bytes_per_pixel (iter_format); layer_alpha = babl_format_has_alpha (iter_format); iter = gegl_buffer_iterator_new (src_buffer, NULL, 0, iter_format, GEGL_ACCESS_READ, GEGL_ABYSS_NONE); gegl_buffer_iterator_add (iter, dest_buffer, NULL, 0, iter_format, GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) { /* lcms doesn't touch the alpha channel, simply * copy everything to dest before the transform */ if (layer_alpha) memcpy (iter->data[1], iter->data[0], iter->length * layer_bpp); cmsDoTransform (transform, iter->data[0], iter->data[1], iter->length); } g_object_unref (src_buffer); g_object_unref (dest_buffer); gimp_drawable_merge_shadow (layer_id, TRUE); gimp_drawable_update (layer_id, 0, 0, layer_width, layer_height); if (count++ % 32 == 0) { gimp_progress_update (progress_start + (gdouble) done / (layer_width * layer_height) * range); } cmsDeleteTransform (transform); } } }
/** * 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); }
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)); }