added new API gimp_drawable_estimate_memsize() and virtual function

2007-12-04  Michael Natterer  <mitch@gimp.org>

	* app/core/gimpdrawable.[ch]: added new API
	gimp_drawable_estimate_memsize() and virtual function
	GimpDrawable::estimate_memsize() which estimate the memsize of a
	drawable after scaling/resizing.

	* app/core/gimplayer.c: implement the virtual function and take
	the layer mask into account.

	* app/core/gimpimage-item-list.[ch] (gimp_image_item_list_get_list):
	added const qualifiers.

	* app/core/gimpimage-scale.c (gimp_image_scale_check): use the new
	function to correctly estimate the new size instead of scaling the
	drawables' memsizes including all constant parts. Fixes bug #329468.

	* app/gimp-log.[ch]: added IMAGE_SCALE log domain.

	* app/core/gimpimage-scale.c: use it here for debugging output.


svn path=/trunk/; revision=24260
This commit is contained in:
Michael Natterer 2007-12-04 11:30:31 +00:00 committed by Michael Natterer
parent 4fe0a3a613
commit dd80b4c263
9 changed files with 186 additions and 67 deletions

View File

@ -1,3 +1,24 @@
2007-12-04 Michael Natterer <mitch@gimp.org>
* app/core/gimpdrawable.[ch]: added new API
gimp_drawable_estimate_memsize() and virtual function
GimpDrawable::estimate_memsize() which estimate the memsize of a
drawable after scaling/resizing.
* app/core/gimplayer.c: implement the virtual function and take
the layer mask into account.
* app/core/gimpimage-item-list.[ch] (gimp_image_item_list_get_list):
added const qualifiers.
* app/core/gimpimage-scale.c (gimp_image_scale_check): use the new
function to correctly estimate the new size instead of scaling the
drawables' memsizes including all constant parts. Fixes bug #329468.
* app/gimp-log.[ch]: added IMAGE_SCALE log domain.
* app/core/gimpimage-scale.c: use it here for debugging output.
2007-12-04 Sven Neumann <sven@gimp.org>
* modules/Makefile.am

View File

@ -87,7 +87,7 @@ static void gimp_drawable_scale (GimpItem *item,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interp_type,
GimpProgress *progress);
GimpProgress *progress);
static void gimp_drawable_resize (GimpItem *item,
GimpContext *context,
gint new_width,
@ -108,10 +108,10 @@ static void gimp_drawable_rotate (GimpItem *item,
static void gimp_drawable_transform (GimpItem *item,
GimpContext *context,
const GimpMatrix3 *matrix,
GimpTransformDirection direction,
GimpInterpolationType interpolation_type,
GimpTransformDirection direction,
GimpInterpolationType interpolation_type,
gint recursion_level,
GimpTransformResize clip_result,
GimpTransformResize clip_result,
GimpProgress *progress);
static gboolean gimp_drawable_get_pixel_at (GimpPickable *pickable,
@ -124,6 +124,10 @@ static void gimp_drawable_real_update (GimpDrawable *drawable,
gint width,
gint height);
static gint64 gimp_drawable_real_estimate_memsize (const GimpDrawable *drawable,
gint width,
gint height);
static void gimp_drawable_real_set_tiles (GimpDrawable *drawable,
gboolean push_undo,
const gchar *undo_desc,
@ -206,6 +210,7 @@ gimp_drawable_class_init (GimpDrawableClass *klass)
klass->update = gimp_drawable_real_update;
klass->alpha_changed = NULL;
klass->estimate_memsize = gimp_drawable_real_estimate_memsize;
klass->invalidate_boundary = NULL;
klass->get_active_components = NULL;
klass->apply_region = gimp_drawable_real_apply_region;
@ -612,6 +617,14 @@ gimp_drawable_real_update (GimpDrawable *drawable,
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (drawable));
}
static gint64
gimp_drawable_real_estimate_memsize (const GimpDrawable *drawable,
gint width,
gint height)
{
return (gint64) gimp_drawable_bytes (drawable) * width * height;
}
static void
gimp_drawable_real_set_tiles (GimpDrawable *drawable,
gboolean push_undo,
@ -758,6 +771,17 @@ gimp_drawable_real_swap_pixels (GimpDrawable *drawable,
/* public functions */
gint64
gimp_drawable_estimate_memsize (const GimpDrawable *drawable,
gint width,
gint height)
{
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), 0);
return GIMP_DRAWABLE_GET_CLASS (drawable)->estimate_memsize (drawable,
width, height);
}
void
gimp_drawable_configure (GimpDrawable *drawable,
GimpImage *image,

View File

@ -53,62 +53,69 @@ struct _GimpDrawableClass
GimpItemClass parent_class;
/* signals */
void (* update) (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height);
void (* alpha_changed) (GimpDrawable *drawable);
void (* update) (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height);
void (* alpha_changed) (GimpDrawable *drawable);
/* virtual functions */
void (* invalidate_boundary) (GimpDrawable *drawable);
void (* get_active_components) (const GimpDrawable *drawable,
gboolean *active);
void (* apply_region) (GimpDrawable *drawable,
PixelRegion *src2PR,
gboolean push_undo,
const gchar *undo_desc,
gdouble opacity,
GimpLayerModeEffects mode,
TileManager *src1_tiles,
gint x,
gint y);
void (* replace_region) (GimpDrawable *drawable,
PixelRegion *src2PR,
gboolean push_undo,
const gchar *undo_desc,
gdouble opacity,
PixelRegion *maskPR,
gint x,
gint y);
void (* set_tiles) (GimpDrawable *drawable,
gboolean push_undo,
const gchar *undo_desc,
TileManager *tiles,
GimpImageType type,
gint offset_x,
gint offset_y);
gint64 (* estimate_memsize) (const GimpDrawable *drawable,
gint width,
gint height);
void (* invalidate_boundary) (GimpDrawable *drawable);
void (* get_active_components) (const GimpDrawable *drawable,
gboolean *active);
void (* apply_region) (GimpDrawable *drawable,
PixelRegion *src2PR,
gboolean push_undo,
const gchar *undo_desc,
gdouble opacity,
GimpLayerModeEffects mode,
TileManager *src1_tiles,
gint x,
gint y);
void (* replace_region) (GimpDrawable *drawable,
PixelRegion *src2PR,
gboolean push_undo,
const gchar *undo_desc,
gdouble opacity,
PixelRegion *maskPR,
gint x,
gint y);
void (* set_tiles) (GimpDrawable *drawable,
gboolean push_undo,
const gchar *undo_desc,
TileManager *tiles,
GimpImageType type,
gint offset_x,
gint offset_y);
void (* push_undo) (GimpDrawable *drawable,
const gchar *undo_desc,
TileManager *tiles,
gboolean sparse,
gint x,
gint y,
gint width,
gint height);
void (* swap_pixels) (GimpDrawable *drawable,
TileManager *tiles,
gboolean sparse,
gint x,
gint y,
gint width,
gint height);
void (* push_undo) (GimpDrawable *drawable,
const gchar *undo_desc,
TileManager *tiles,
gboolean sparse,
gint x,
gint y,
gint width,
gint height);
void (* swap_pixels) (GimpDrawable *drawable,
TileManager *tiles,
gboolean sparse,
gint x,
gint y,
gint width,
gint height);
};
GType gimp_drawable_get_type (void) G_GNUC_CONST;
gint64 gimp_drawable_estimate_memsize (const GimpDrawable *drawable,
gint width,
gint height);
void gimp_drawable_configure (GimpDrawable *drawable,
GimpImage *image,
gint offset_x,

View File

@ -159,8 +159,8 @@ gimp_image_item_list_transform (GimpImage *image,
* Return value: The list of items, excluding @exclude.
**/
GList *
gimp_image_item_list_get_list (GimpImage *image,
GimpItem *exclude,
gimp_image_item_list_get_list (const GimpImage *image,
const GimpItem *exclude,
GimpItemTypeMask type,
GimpItemSet set)
{

View File

@ -48,8 +48,8 @@ void gimp_image_item_list_transform (GimpImage *image,
GimpTransformResize clip_result,
GimpProgress *progress);
GList * gimp_image_item_list_get_list (GimpImage *image,
GimpItem *exclude,
GList * gimp_image_item_list_get_list (const GimpImage *image,
const GimpItem *exclude,
GimpItemTypeMask type,
GimpItemSet set);

View File

@ -28,6 +28,7 @@
#include "gimpguide.h"
#include "gimpimage.h"
#include "gimpimage-guides.h"
#include "gimpimage-item-list.h"
#include "gimpimage-sample-points.h"
#include "gimpimage-scale.h"
#include "gimpimage-undo.h"
@ -35,9 +36,11 @@
#include "gimplayer.h"
#include "gimplist.h"
#include "gimpprogress.h"
#include "gimpprojection.h"
#include "gimpsamplepoint.h"
#include "gimpsubprogress.h"
#include "gimp-log.h"
#include "gimp-intl.h"
@ -234,9 +237,11 @@ gimp_image_scale_check (const GimpImage *image,
gint64 max_memsize,
gint64 *new_memsize)
{
GList *drawables;
GList *list;
gint64 current_size;
gint64 scalable_size;
gint64 scaled_size;
gint64 undo_size;
gint64 redo_size;
gint64 fixed_size;
@ -248,11 +253,47 @@ gimp_image_scale_check (const GimpImage *image,
current_size = gimp_object_get_memsize (GIMP_OBJECT (image), NULL);
/* the part of the image's memsize that scales linearly with the image */
scalable_size =
gimp_object_get_memsize (GIMP_OBJECT (image->layers), NULL) +
gimp_object_get_memsize (GIMP_OBJECT (image->channels), NULL) +
gimp_object_get_memsize (GIMP_OBJECT (image->selection_mask), NULL) +
gimp_object_get_memsize (GIMP_OBJECT (image->projection), NULL);
drawables = gimp_image_item_list_get_list (image, NULL,
GIMP_ITEM_TYPE_LAYERS |
GIMP_ITEM_TYPE_CHANNELS,
GIMP_ITEM_SET_ALL);
drawables = g_list_prepend (drawables, image->selection_mask);
scalable_size = 0;
scaled_size = 0;
for (list = drawables; list; list = g_list_next (list))
{
GimpDrawable *drawable = list->data;
gdouble width = gimp_item_width (GIMP_ITEM (drawable));
gdouble height = gimp_item_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_base_type (image),
gimp_image_get_width (image),
gimp_image_get_height (image));
scaled_size +=
gimp_projection_estimate_memsize (gimp_image_base_type (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 (image->undo_stack), NULL);
redo_size = gimp_object_get_memsize (GIMP_OBJECT (image->redo_stack), NULL);
@ -261,10 +302,12 @@ gimp_image_scale_check (const GimpImage *image,
fixed_size = current_size - undo_size - redo_size - scalable_size;
/* calculate the new size, which is: */
new_size = (fixed_size + /* the fixed part */
scalable_size * /* plus the part that scales... */
((gdouble) new_width / gimp_image_get_width (image)) *
((gdouble) new_height / gimp_image_get_height (image)));
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;

View File

@ -136,6 +136,10 @@ static void gimp_layer_transform (GimpItem *item,
gint recursion_level,
GimpTransformResize clip_result,
GimpProgress *progress);
static gint64 gimp_layer_estimate_memsize (const GimpDrawable *drawable,
gint width,
gint height);
static void gimp_layer_invalidate_boundary (GimpDrawable *drawable);
static void gimp_layer_get_active_components (const GimpDrawable *drawable,
gboolean *active);
@ -250,6 +254,7 @@ gimp_layer_class_init (GimpLayerClass *klass)
item_class->rotate_desc = _("Rotate Layer");
item_class->transform_desc = _("Transform Layer");
drawable_class->estimate_memsize = gimp_layer_estimate_memsize;
drawable_class->invalidate_boundary = gimp_layer_invalidate_boundary;
drawable_class->get_active_components = gimp_layer_get_active_components;
drawable_class->set_tiles = gimp_layer_set_tiles;
@ -798,6 +803,23 @@ gimp_layer_transform (GimpItem *item,
clip_result, progress);
}
static gint64
gimp_layer_estimate_memsize (const GimpDrawable *drawable,
gint width,
gint height)
{
GimpLayer *layer = GIMP_LAYER (drawable);
gint64 memsize = 0;
if (layer->mask)
memsize += gimp_drawable_estimate_memsize (GIMP_DRAWABLE (layer->mask),
width, height);
return memsize + GIMP_DRAWABLE_CLASS (parent_class)->estimate_memsize (drawable,
width,
height);
}
static void
gimp_layer_invalidate_boundary (GimpDrawable *drawable)
{

View File

@ -39,7 +39,8 @@ gimp_log_init (void)
{ "dnd", GIMP_LOG_DND },
{ "help", GIMP_LOG_HELP },
{ "dialog-factory", GIMP_LOG_DIALOG_FACTORY },
{ "save-dialog", GIMP_LOG_SAVE_DIALOG }
{ "save-dialog", GIMP_LOG_SAVE_DIALOG },
{ "image-scale", GIMP_LOG_IMAGE_SCALE }
};
gimp_log_flags = g_parse_debug_string (env_log_val,

View File

@ -26,7 +26,8 @@ typedef enum
GIMP_LOG_DND = 1 << 1,
GIMP_LOG_HELP = 1 << 2,
GIMP_LOG_DIALOG_FACTORY = 1 << 3,
GIMP_LOG_SAVE_DIALOG = 1 << 4
GIMP_LOG_SAVE_DIALOG = 1 << 4,
GIMP_LOG_IMAGE_SCALE = 1 << 5
} GimpLogFlags;