added get_pixel_at() method to the GimpPickable interface. This gives

2007-04-27  Sven Neumann  <sven@gimp.org>

	* app/core/gimppickable.[ch]: added get_pixel_at() method to the
	GimpPickable interface. This gives direct access to the pixel
	without converting it to an RGB color.

	* app/core/gimpdrawable.c
	* app/core/gimpimagemap.c
	* app/core/gimpprojection.c: implement the new method and also use
	it to reimplement get_color_at().

	* app/core/gimpimage-crop.c (gimp_image_crop_guess_bgcolor): use
	gimp_pickable_get_pixel_at(). Fixes auto-shrink on indexed and
	grayscale images.

svn path=/trunk/; revision=22359
This commit is contained in:
Sven Neumann 2007-04-27 16:07:49 +00:00 committed by Sven Neumann
parent 7b7affa9b0
commit 7c1fc759f5
7 changed files with 154 additions and 68 deletions

View File

@ -1,3 +1,18 @@
2007-04-27 Sven Neumann <sven@gimp.org>
* app/core/gimppickable.[ch]: added get_pixel_at() method to the
GimpPickable interface. This gives direct access to the pixel
without converting it to an RGB color.
* app/core/gimpdrawable.c
* app/core/gimpimagemap.c
* app/core/gimpprojection.c: implement the new method and also use
it to reimplement get_color_at().
* app/core/gimpimage-crop.c (gimp_image_crop_guess_bgcolor): use
gimp_pickable_get_pixel_at(). Fixes auto-shrink on indexed and
grayscale images.
2007-04-27 Sven Neumann <sven@gimp.org>
* plug-ins/common/sunras.c (set_color_table): guard against a

View File

@ -115,6 +115,10 @@ static void gimp_drawable_transform (GimpItem *item,
GimpTransformResize clip_result,
GimpProgress *progress);
static gboolean gimp_drawable_get_pixel_at (GimpPickable *pickable,
gint x,
gint y,
guchar *pixel);
static guchar * gimp_drawable_get_color_at (GimpPickable *pickable,
gint x,
gint y);
@ -236,6 +240,7 @@ gimp_drawable_pickable_iface_init (GimpPickableInterface *iface)
iface->get_image_type = (GimpImageType (*) (GimpPickable *pickable)) gimp_drawable_type;
iface->get_bytes = (gint (*) (GimpPickable *pickable)) gimp_drawable_bytes;
iface->get_tiles = (TileManager * (*) (GimpPickable *pickable)) gimp_drawable_get_tiles;
iface->get_pixel_at = gimp_drawable_get_pixel_at;
iface->get_color_at = gimp_drawable_get_color_at;
}
@ -588,37 +593,47 @@ gimp_drawable_transform (GimpItem *item,
}
}
static gboolean
gimp_drawable_get_pixel_at (GimpPickable *pickable,
gint x,
gint y,
guchar *pixel)
{
GimpDrawable *drawable = GIMP_DRAWABLE (pickable);
/* do not make this a g_return_if_fail() */
if (x < 0 || x >= GIMP_ITEM (drawable)->width ||
y < 0 || y >= GIMP_ITEM (drawable)->height)
return FALSE;
read_pixel_data_1 (gimp_drawable_get_tiles (drawable), x, y, pixel);
return TRUE;
}
static guchar *
gimp_drawable_get_color_at (GimpPickable *pickable,
gint x,
gint y)
{
GimpDrawable *drawable = GIMP_DRAWABLE (pickable);
GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));
Tile *tile;
guchar *src;
guchar *dest;
guchar pixel[4];
/* do not make this a g_return_if_fail() */
if (x < 0 || x >= GIMP_ITEM (drawable)->width ||
y < 0 || y >= GIMP_ITEM (drawable)->height)
if (! gimp_drawable_get_pixel_at (pickable, x, y, pixel))
return NULL;
dest = g_new (guchar, 5);
tile = tile_manager_get_tile (gimp_drawable_get_tiles (drawable), x, y,
TRUE, FALSE);
src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimp_image_get_color (image, gimp_drawable_type (drawable), src, dest);
gimp_image_get_color (gimp_item_get_image (GIMP_ITEM (drawable)),
gimp_drawable_type (drawable),
pixel, dest);
if (gimp_drawable_is_indexed (drawable))
dest[4] = src[0];
dest[4] = pixel[0];
else
dest[4] = 0;
tile_release (tile, FALSE);
return dest;
}

View File

@ -429,12 +429,11 @@ gimp_image_crop_guess_bgcolor (GimpPickable *pickable,
gint y1,
gint y2)
{
AutoCropType retval = AUTO_CROP_NOTHING;
guchar *tl = NULL;
guchar *tr = NULL;
guchar *bl = NULL;
guchar *br = NULL;
gint i;
guchar tl[4];
guchar tr[4];
guchar bl[4];
guchar br[4];
gint i;
for (i = 0; i < bytes; i++)
color[i] = 0;
@ -443,11 +442,13 @@ gimp_image_crop_guess_bgcolor (GimpPickable *pickable,
* background-color to see if at least 2 corners are equal.
*/
if (! (tl = gimp_pickable_get_color_at (pickable, x1, y1)) ||
! (tr = gimp_pickable_get_color_at (pickable, x1, y2)) ||
! (bl = gimp_pickable_get_color_at (pickable, x2, y1)) ||
! (br = gimp_pickable_get_color_at (pickable, x2, y2)))
goto done;
if (! gimp_pickable_get_pixel_at (pickable, x1, y1, tl) ||
! gimp_pickable_get_pixel_at (pickable, x1, y2, tr) ||
! gimp_pickable_get_pixel_at (pickable, x2, y1, bl) ||
! gimp_pickable_get_pixel_at (pickable, x2, y2, br))
{
return AUTO_CROP_NOTHING;
}
if (has_alpha)
{
@ -458,8 +459,7 @@ gimp_image_crop_guess_bgcolor (GimpPickable *pickable,
(tr[alpha] == 0 && br[alpha] == 0) ||
(bl[alpha] == 0 && br[alpha] == 0))
{
retval = AUTO_CROP_ALPHA;
goto done;
return AUTO_CROP_ALPHA;
}
}
@ -467,22 +467,17 @@ gimp_image_crop_guess_bgcolor (GimpPickable *pickable,
gimp_image_crop_colors_equal (tl, bl, bytes))
{
memcpy (color, tl, bytes);
retval = AUTO_CROP_COLOR;
return AUTO_CROP_COLOR;
}
else if (gimp_image_crop_colors_equal (br, bl, bytes) ||
if (gimp_image_crop_colors_equal (br, bl, bytes) ||
gimp_image_crop_colors_equal (br, tr, bytes))
{
memcpy (color, br, bytes);
retval = AUTO_CROP_COLOR;
return AUTO_CROP_COLOR;
}
done:
g_free (tl);
g_free (tr);
g_free (bl);
g_free (br);
return retval;
return AUTO_CROP_NOTHING;
}
static int

View File

@ -69,6 +69,10 @@ static GimpImage * gimp_image_map_get_image (GimpPickable *pickable);
static GimpImageType gimp_image_map_get_image_type (GimpPickable *pickable);
static gint gimp_image_map_get_bytes (GimpPickable *pickable);
static TileManager * gimp_image_map_get_tiles (GimpPickable *pickable);
static gboolean gimp_image_map_get_pixel_at (GimpPickable *pickable,
gint x,
gint y,
guchar *pixel);
static guchar * gimp_image_map_get_color_at (GimpPickable *pickable,
gint x,
gint y);
@ -109,6 +113,7 @@ gimp_image_map_pickable_iface_init (GimpPickableInterface *iface)
iface->get_image_type = gimp_image_map_get_image_type;
iface->get_bytes = gimp_image_map_get_bytes;
iface->get_tiles = gimp_image_map_get_tiles;
iface->get_pixel_at = gimp_image_map_get_pixel_at;
iface->get_color_at = gimp_image_map_get_color_at;
}
@ -190,10 +195,11 @@ gimp_image_map_get_tiles (GimpPickable *pickable)
return gimp_pickable_get_tiles (GIMP_PICKABLE (image_map->drawable));
}
static guchar *
gimp_image_map_get_color_at (GimpPickable *pickable,
static gboolean
gimp_image_map_get_pixel_at (GimpPickable *pickable,
gint x,
gint y)
gint y,
guchar *pixel)
{
GimpImageMap *image_map = GIMP_IMAGE_MAP (pickable);
GimpItem *item = GIMP_ITEM (image_map->drawable);
@ -212,38 +218,50 @@ gimp_image_map_get_color_at (GimpPickable *pickable,
if (x >= offset_x && x < offset_x + width &&
y >= offset_y && y < offset_y + height)
{
guchar src[5];
guchar *dest;
dest = g_new (guchar, 5);
read_pixel_data_1 (image_map->undo_tiles,
x - offset_x,
y - offset_y,
src);
pixel);
gimp_image_get_color (gimp_item_get_image (item),
gimp_drawable_type (image_map->drawable),
src, dest);
if (gimp_drawable_is_indexed (image_map->drawable))
dest[4] = src[0];
else
dest[4] = 0;
return dest;
return TRUE;
}
}
return gimp_pickable_get_color_at (GIMP_PICKABLE (image_map->drawable),
x, y);
return gimp_pickable_get_pixel_at (GIMP_PICKABLE (image_map->drawable),
x, y, pixel);
}
else /* out of bounds error */
{
return NULL;
return FALSE;
}
}
static guchar *
gimp_image_map_get_color_at (GimpPickable *pickable,
gint x,
gint y)
{
GimpImageMap *image_map = GIMP_IMAGE_MAP (pickable);
guchar *dest;
guchar pixel[4];
if (! gimp_image_map_get_pixel_at (pickable, x, y, pixel))
return NULL;
dest = g_new (guchar, 5);
gimp_image_get_color (gimp_item_get_image (GIMP_ITEM (image_map->drawable)),
gimp_drawable_type (image_map->drawable),
pixel, dest);
if (gimp_drawable_is_indexed (image_map->drawable))
dest[4] = pixel[0];
else
dest[4] = 0;
return dest;
}
GimpImageMap *
gimp_image_map_new (GimpDrawable *drawable,
const gchar *undo_desc)

View File

@ -129,6 +129,25 @@ gimp_pickable_get_tiles (GimpPickable *pickable)
return NULL;
}
gboolean
gimp_pickable_get_pixel_at (GimpPickable *pickable,
gint x,
gint y,
guchar *pixel)
{
GimpPickableInterface *pickable_iface;
g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), FALSE);
g_return_val_if_fail (pixel != NULL, FALSE);
pickable_iface = GIMP_PICKABLE_GET_INTERFACE (pickable);
if (pickable_iface->get_pixel_at)
return pickable_iface->get_pixel_at (pickable, x, y, pixel);
return FALSE;
}
guchar *
gimp_pickable_get_color_at (GimpPickable *pickable,
gint x,

View File

@ -41,6 +41,10 @@ struct _GimpPickableInterface
GimpImageType (* get_image_type) (GimpPickable *pickable);
gint (* get_bytes) (GimpPickable *pickable);
TileManager * (* get_tiles) (GimpPickable *pickable);
gboolean (* get_pixel_at) (GimpPickable *pickable,
gint x,
gint y,
guchar *pixel);
guchar * (* get_color_at) (GimpPickable *pickable,
gint x,
gint y);
@ -57,6 +61,10 @@ GimpImage * gimp_pickable_get_image (GimpPickable *pickable);
GimpImageType gimp_pickable_get_image_type (GimpPickable *pickable);
gint gimp_pickable_get_bytes (GimpPickable *pickable);
TileManager * gimp_pickable_get_tiles (GimpPickable *pickable);
gboolean gimp_pickable_get_pixel_at (GimpPickable *pickable,
gint x,
gint y,
guchar *pixel);
guchar * gimp_pickable_get_color_at (GimpPickable *pickable,
gint x,
gint y);

View File

@ -51,6 +51,10 @@ static gint64 gimp_projection_get_memsize (GimpObject *object,
gint64 *gui_size);
static void gimp_projection_pickable_flush (GimpPickable *pickable);
static gboolean gimp_projection_get_pixel_at (GimpPickable *pickable,
gint x,
gint y,
guchar *pixel);
static guchar * gimp_projection_get_color_at (GimpPickable *pickable,
gint x,
gint y);
@ -158,6 +162,7 @@ gimp_projection_pickable_iface_init (GimpPickableInterface *iface)
iface->get_image_type = (GimpImageType (*) (GimpPickable *pickable)) gimp_projection_get_image_type;
iface->get_bytes = (gint (*) (GimpPickable *pickable)) gimp_projection_get_bytes;
iface->get_tiles = (TileManager * (*) (GimpPickable *pickable)) gimp_projection_get_tiles;
iface->get_pixel_at = gimp_projection_get_pixel_at;
iface->get_color_at = gimp_projection_get_color_at;
iface->get_opacity_at = gimp_projection_get_opacity_at;
}
@ -211,28 +216,39 @@ gimp_projection_pickable_flush (GimpPickable *pickable)
gimp_projection_flush_now (proj);
}
static gboolean
gimp_projection_get_pixel_at (GimpPickable *pickable,
gint x,
gint y,
guchar *pixel)
{
GimpProjection *proj = GIMP_PROJECTION (pickable);
if (x < 0 || y < 0 || x >= proj->image->width || y >= proj->image->height)
return FALSE;
read_pixel_data_1 (gimp_projection_get_tiles (proj), x, y, pixel);
return TRUE;
}
static guchar *
gimp_projection_get_color_at (GimpPickable *pickable,
gint x,
gint y)
{
GimpProjection *proj = GIMP_PROJECTION (pickable);
Tile *tile;
guchar *src;
guchar *dest;
guchar pixel[4];
if (x < 0 || y < 0 || x >= proj->image->width || y >= proj->image->height)
if (! gimp_projection_get_pixel_at (pickable, x, y, pixel))
return NULL;
dest = g_new (guchar, 5);
tile = tile_manager_get_tile (gimp_projection_get_tiles (proj),
x, y, TRUE, FALSE);
src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimp_image_get_color (proj->image, gimp_projection_get_image_type (proj),
src, dest);
gimp_image_get_color (proj->image, gimp_projection_get_image_type (proj),
pixel, dest);
dest[4] = 0;
tile_release (tile, FALSE);
return dest;
}