/** * gimp_image_scale_check: * @image: A #GimpImage. * @new_width: The new width. * @new_height: The new height. * @max_memsize: The maximum new memory size. * @new_memsize: The new memory size. * * Inventory the layer list in image and check that it may be * scaled to @new_height and @new_width without problems. * * Return value: #GIMP_IMAGE_SCALE_OK if scaling the image will shrink none * of its layers completely away, and the new image size * is smaller than @max_memsize. * #GIMP_IMAGE_SCALE_TOO_SMALL if scaling would remove some * existing layers. * #GIMP_IMAGE_SCALE_TOO_BIG if the new image size would * exceed the maximum specified in the preferences. **/ GimpImageScaleCheckType gimp_image_scale_check (GimpImage *image, gint new_width, gint new_height, gint64 max_memsize, gint64 *new_memsize) { GList *all_layers; GList *list; gint64 current_size; gint64 undo_size; gint64 redo_size; gint64 new_size; g_return_val_if_fail (GIMP_IS_IMAGE (image), GIMP_IMAGE_SCALE_TOO_SMALL); g_return_val_if_fail (new_memsize != NULL, GIMP_IMAGE_SCALE_TOO_SMALL); current_size = gimp_object_get_memsize (GIMP_OBJECT (image), NULL); new_size = gimp_image_estimate_memsize (image, gimp_image_get_component_type (image), new_width, new_height); undo_size = gimp_object_get_memsize (GIMP_OBJECT (gimp_image_get_undo_stack (image)), NULL); redo_size = gimp_object_get_memsize (GIMP_OBJECT (gimp_image_get_redo_stack (image)), NULL); current_size -= undo_size + redo_size; new_size -= undo_size + redo_size; GIMP_LOG (IMAGE_SCALE, "old_size = %"G_GINT64_FORMAT" new_size = %"G_GINT64_FORMAT, current_size, new_size); *new_memsize = new_size; if (new_size > current_size && new_size > max_memsize) return GIMP_IMAGE_SCALE_TOO_BIG; all_layers = gimp_image_get_layer_list (image); for (list = all_layers; list; list = g_list_next (list)) { GimpItem *item = list->data; /* group layers are updated automatically */ if (gimp_viewable_get_children (GIMP_VIEWABLE (item))) continue; if (! gimp_item_check_scaling (item, new_width, new_height)) { g_list_free (all_layers); return GIMP_IMAGE_SCALE_TOO_SMALL; } } g_list_free (all_layers); return GIMP_IMAGE_SCALE_OK; }
/** * gimp_image_scale_check: * @image: A #GimpImage. * @new_width: The new width. * @new_height: The new height. * @max_memsize: The maximum new memory size. * @new_memsize: The new memory size. * * Inventory the layer list in image and check that it may be * scaled to @new_height and @new_width without problems. * * Return value: #GIMP_IMAGE_SCALE_OK if scaling the image will shrink none * of its layers completely away, and the new image size * is smaller than @max_memsize. * #GIMP_IMAGE_SCALE_TOO_SMALL if scaling would remove some * existing layers. * #GIMP_IMAGE_SCALE_TOO_BIG if the new image size would * exceed the maximum specified in the preferences. **/ GimpImageScaleCheckType gimp_image_scale_check (const GimpImage *image, gint new_width, gint new_height, gint64 max_memsize, gint64 *new_memsize) { GList *drawables; GList *all_layers; GList *list; gint64 current_size; gint64 scalable_size; gint64 scaled_size; gint64 undo_size; gint64 redo_size; gint64 fixed_size; gint64 new_size; g_return_val_if_fail (GIMP_IS_IMAGE (image), GIMP_IMAGE_SCALE_TOO_SMALL); g_return_val_if_fail (new_memsize != NULL, GIMP_IMAGE_SCALE_TOO_SMALL); current_size = gimp_object_get_memsize (GIMP_OBJECT (image), NULL); /* the part of the image's memsize that scales linearly with the image */ drawables = gimp_image_item_list_get_list (image, NULL, GIMP_ITEM_TYPE_LAYERS | GIMP_ITEM_TYPE_CHANNELS, GIMP_ITEM_SET_ALL); gimp_image_item_list_filter (NULL, drawables, TRUE, FALSE); drawables = g_list_prepend (drawables, gimp_image_get_mask (image)); scalable_size = 0; scaled_size = 0; for (list = drawables; list; list = g_list_next (list)) { GimpDrawable *drawable = list->data; gdouble width = gimp_item_get_width (GIMP_ITEM (drawable)); gdouble height = gimp_item_get_height (GIMP_ITEM (drawable)); scalable_size += gimp_drawable_estimate_memsize (drawable, width, height); scaled_size += gimp_drawable_estimate_memsize (drawable, width * new_width / gimp_image_get_width (image), height * new_height / gimp_image_get_height (image)); } g_list_free (drawables); scalable_size += gimp_projection_estimate_memsize (gimp_image_get_base_type (image), gimp_image_get_precision (image), gimp_image_get_width (image), gimp_image_get_height (image)); scaled_size += gimp_projection_estimate_memsize (gimp_image_get_base_type (image), gimp_image_get_precision (image), new_width, new_height); GIMP_LOG (IMAGE_SCALE, "scalable_size = %"G_GINT64_FORMAT" scaled_size = %"G_GINT64_FORMAT, scalable_size, scaled_size); undo_size = gimp_object_get_memsize (GIMP_OBJECT (gimp_image_get_undo_stack (image)), NULL); redo_size = gimp_object_get_memsize (GIMP_OBJECT (gimp_image_get_redo_stack (image)), NULL); /* the fixed part of the image's memsize w/o any undo information */ fixed_size = current_size - undo_size - redo_size - scalable_size; /* calculate the new size, which is: */ new_size = (fixed_size + /* the fixed part */ scaled_size); /* plus the part that scales... */ GIMP_LOG (IMAGE_SCALE, "old_size = %"G_GINT64_FORMAT" new_size = %"G_GINT64_FORMAT, current_size - undo_size - redo_size, new_size); *new_memsize = new_size; if (new_size > current_size && new_size > max_memsize) return GIMP_IMAGE_SCALE_TOO_BIG; all_layers = gimp_image_get_layer_list (image); for (list = all_layers; list; list = g_list_next (list)) { GimpItem *item = list->data; /* group layers are updated automatically */ if (gimp_viewable_get_children (GIMP_VIEWABLE (item))) continue; if (! gimp_item_check_scaling (item, new_width, new_height)) { g_list_free (all_layers); return GIMP_IMAGE_SCALE_TOO_SMALL; } } g_list_free (all_layers); return GIMP_IMAGE_SCALE_OK; }