mirror of https://github.com/GNOME/gimp.git
app: add format parameter to GimpPickable::get_pixel_at()
allowing NULL for the pickable's native format. Fix and simplify auto cropping to always use "R'G'B'A u8".
This commit is contained in:
parent
a61885f324
commit
e6975ed065
|
@ -118,7 +118,8 @@ static void gimp_drawable_transform (GimpItem *item,
|
|||
static gboolean gimp_drawable_get_pixel_at (GimpPickable *pickable,
|
||||
gint x,
|
||||
gint y,
|
||||
guchar *pixel);
|
||||
const Babl *format,
|
||||
gpointer pixel);
|
||||
static void gimp_drawable_real_update (GimpDrawable *drawable,
|
||||
gint x,
|
||||
gint y,
|
||||
|
@ -636,7 +637,8 @@ static gboolean
|
|||
gimp_drawable_get_pixel_at (GimpPickable *pickable,
|
||||
gint x,
|
||||
gint y,
|
||||
guchar *pixel)
|
||||
const Babl *format,
|
||||
gpointer pixel)
|
||||
{
|
||||
GimpDrawable *drawable = GIMP_DRAWABLE (pickable);
|
||||
|
||||
|
@ -646,8 +648,7 @@ gimp_drawable_get_pixel_at (GimpPickable *pickable,
|
|||
return FALSE;
|
||||
|
||||
gegl_buffer_sample (gimp_drawable_get_buffer (drawable),
|
||||
x, y, NULL, pixel,
|
||||
gimp_drawable_get_format (drawable),
|
||||
x, y, NULL, pixel, format,
|
||||
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
|
||||
|
||||
return TRUE;
|
||||
|
|
|
@ -48,26 +48,21 @@ typedef enum
|
|||
|
||||
|
||||
typedef AutoCropType (* ColorsEqualFunc) (guchar *col1,
|
||||
guchar *col2,
|
||||
gint bytes);
|
||||
guchar *col2);
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static AutoCropType gimp_image_crop_guess_bgcolor (GimpPickable *pickable,
|
||||
gint bytes,
|
||||
gboolean has_alpha,
|
||||
guchar *color,
|
||||
gint x1,
|
||||
gint x2,
|
||||
gint y1,
|
||||
gint y2);
|
||||
static gint gimp_image_crop_colors_equal (guchar *col1,
|
||||
guchar *col2,
|
||||
gint bytes);
|
||||
guchar *col2);
|
||||
static gint gimp_image_crop_colors_alpha (guchar *col1,
|
||||
guchar *col2,
|
||||
gint bytes);
|
||||
guchar *col2);
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
@ -310,11 +305,9 @@ gimp_image_crop_auto_shrink (GimpImage *image,
|
|||
GeglRectangle rect;
|
||||
ColorsEqualFunc colors_equal_func;
|
||||
guchar bgcolor[MAX_CHANNELS] = { 0, 0, 0, 0 };
|
||||
gboolean has_alpha;
|
||||
guchar *buf = NULL;
|
||||
gint width, height;
|
||||
const Babl *format;
|
||||
gint bytes;
|
||||
gint x, y, abort;
|
||||
gboolean retval = FALSE;
|
||||
|
||||
|
@ -349,13 +342,10 @@ gimp_image_crop_auto_shrink (GimpImage *image,
|
|||
|
||||
gimp_pickable_flush (pickable);
|
||||
|
||||
format = gimp_pickable_get_format (pickable);
|
||||
bytes = babl_format_get_bytes_per_pixel (format);
|
||||
has_alpha = babl_format_has_alpha (format);
|
||||
format = babl_format ("R'G'B'A u8");
|
||||
|
||||
switch (gimp_image_crop_guess_bgcolor (pickable,
|
||||
bytes, has_alpha, bgcolor,
|
||||
x1, x2-1, y1, y2-1))
|
||||
switch (gimp_image_crop_guess_bgcolor (pickable, bgcolor,
|
||||
x1, x2 - 1, y1, y2 - 1))
|
||||
{
|
||||
case AUTO_CROP_ALPHA:
|
||||
colors_equal_func = (ColorsEqualFunc) gimp_image_crop_colors_alpha;
|
||||
|
@ -377,7 +367,7 @@ gimp_image_crop_auto_shrink (GimpImage *image,
|
|||
* the smaller side first instead of defaulting to width --Sven
|
||||
*/
|
||||
|
||||
buf = g_malloc (MAX (width, height) * bytes);
|
||||
buf = g_malloc (MAX (width, height) * 4);
|
||||
|
||||
/* Check how many of the top lines are uniform/transparent. */
|
||||
rect.x = x1;
|
||||
|
@ -389,11 +379,10 @@ gimp_image_crop_auto_shrink (GimpImage *image,
|
|||
for (y = y1; y < y2 && !abort; y++)
|
||||
{
|
||||
rect.y = y;
|
||||
/* XXX use an appropriate format here */
|
||||
gegl_buffer_get (buffer, &rect, 1.0, NULL, buf,
|
||||
gegl_buffer_get (buffer, &rect, 1.0, format, buf,
|
||||
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
||||
for (x = 0; x < width && !abort; x++)
|
||||
abort = !(colors_equal_func) (bgcolor, buf + x * bytes, bytes);
|
||||
abort = ! colors_equal_func (bgcolor, buf + x * 4);
|
||||
}
|
||||
if (y == y2 && !abort)
|
||||
goto FINISH;
|
||||
|
@ -409,10 +398,10 @@ gimp_image_crop_auto_shrink (GimpImage *image,
|
|||
for (y = y2; y > y1 && !abort; y--)
|
||||
{
|
||||
rect.y = y - 1;
|
||||
gegl_buffer_get (buffer, &rect, 1.0, NULL, buf,
|
||||
gegl_buffer_get (buffer, &rect, 1.0, format, buf,
|
||||
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
||||
for (x = 0; x < width && !abort; x++)
|
||||
abort = !(colors_equal_func) (bgcolor, buf + x * bytes, bytes);
|
||||
abort = ! colors_equal_func (bgcolor, buf + x * 4);
|
||||
}
|
||||
y2 = y + 1;
|
||||
|
||||
|
@ -429,10 +418,10 @@ gimp_image_crop_auto_shrink (GimpImage *image,
|
|||
for (x = x1; x < x2 && !abort; x++)
|
||||
{
|
||||
rect.x = x;
|
||||
gegl_buffer_get (buffer, &rect, 1.0, NULL, buf,
|
||||
gegl_buffer_get (buffer, &rect, 1.0, format, buf,
|
||||
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
||||
for (y = 0; y < height && !abort; y++)
|
||||
abort = !(colors_equal_func) (bgcolor, buf + y * bytes, bytes);
|
||||
abort = ! colors_equal_func (bgcolor, buf + y * 4);
|
||||
}
|
||||
x1 = x - 1;
|
||||
|
||||
|
@ -446,10 +435,10 @@ gimp_image_crop_auto_shrink (GimpImage *image,
|
|||
for (x = x2; x > x1 && !abort; x--)
|
||||
{
|
||||
rect.x = x - 1;
|
||||
gegl_buffer_get (buffer, &rect, 1.0, NULL, buf,
|
||||
gegl_buffer_get (buffer, &rect, 1.0, format, buf,
|
||||
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
||||
for (y = 0; y < height && !abort; y++)
|
||||
abort = !(colors_equal_func) (bgcolor, buf + y * bytes, bytes);
|
||||
abort = ! colors_equal_func (bgcolor, buf + y * 4);
|
||||
}
|
||||
x2 = x + 1;
|
||||
|
||||
|
@ -472,59 +461,53 @@ gimp_image_crop_auto_shrink (GimpImage *image,
|
|||
|
||||
static AutoCropType
|
||||
gimp_image_crop_guess_bgcolor (GimpPickable *pickable,
|
||||
gint bytes,
|
||||
gboolean has_alpha,
|
||||
guchar *color,
|
||||
gint x1,
|
||||
gint x2,
|
||||
gint y1,
|
||||
gint y2)
|
||||
{
|
||||
guchar tl[4];
|
||||
guchar tr[4];
|
||||
guchar bl[4];
|
||||
guchar br[4];
|
||||
gint i;
|
||||
const Babl *format = babl_format ("R'G'B'A u8");
|
||||
guchar tl[4];
|
||||
guchar tr[4];
|
||||
guchar bl[4];
|
||||
guchar br[4];
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < bytes; i++)
|
||||
for (i = 0; i < 4; i++)
|
||||
color[i] = 0;
|
||||
|
||||
/* First check if there's transparency to crop. If not, guess the
|
||||
* background-color to see if at least 2 corners are equal.
|
||||
*/
|
||||
|
||||
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))
|
||||
if (! gimp_pickable_get_pixel_at (pickable, x1, y1, format, tl) ||
|
||||
! gimp_pickable_get_pixel_at (pickable, x1, y2, format, tr) ||
|
||||
! gimp_pickable_get_pixel_at (pickable, x2, y1, format, bl) ||
|
||||
! gimp_pickable_get_pixel_at (pickable, x2, y2, format, br))
|
||||
{
|
||||
return AUTO_CROP_NOTHING;
|
||||
}
|
||||
|
||||
if (has_alpha)
|
||||
if ((tl[ALPHA] == 0 && tr[ALPHA] == 0) ||
|
||||
(tl[ALPHA] == 0 && bl[ALPHA] == 0) ||
|
||||
(tr[ALPHA] == 0 && br[ALPHA] == 0) ||
|
||||
(bl[ALPHA] == 0 && br[ALPHA] == 0))
|
||||
{
|
||||
gint alpha = bytes - 1;
|
||||
|
||||
if ((tl[alpha] == 0 && tr[alpha] == 0) ||
|
||||
(tl[alpha] == 0 && bl[alpha] == 0) ||
|
||||
(tr[alpha] == 0 && br[alpha] == 0) ||
|
||||
(bl[alpha] == 0 && br[alpha] == 0))
|
||||
{
|
||||
return AUTO_CROP_ALPHA;
|
||||
}
|
||||
return AUTO_CROP_ALPHA;
|
||||
}
|
||||
|
||||
if (gimp_image_crop_colors_equal (tl, tr, bytes) ||
|
||||
gimp_image_crop_colors_equal (tl, bl, bytes))
|
||||
if (gimp_image_crop_colors_equal (tl, tr) ||
|
||||
gimp_image_crop_colors_equal (tl, bl))
|
||||
{
|
||||
memcpy (color, tl, bytes);
|
||||
memcpy (color, tl, 4);
|
||||
return AUTO_CROP_COLOR;
|
||||
}
|
||||
|
||||
if (gimp_image_crop_colors_equal (br, bl, bytes) ||
|
||||
gimp_image_crop_colors_equal (br, tr, bytes))
|
||||
if (gimp_image_crop_colors_equal (br, bl) ||
|
||||
gimp_image_crop_colors_equal (br, tr))
|
||||
{
|
||||
memcpy (color, br, bytes);
|
||||
memcpy (color, br, 4);
|
||||
return AUTO_CROP_COLOR;
|
||||
}
|
||||
|
||||
|
@ -533,12 +516,11 @@ gimp_image_crop_guess_bgcolor (GimpPickable *pickable,
|
|||
|
||||
static int
|
||||
gimp_image_crop_colors_equal (guchar *col1,
|
||||
guchar *col2,
|
||||
gint bytes)
|
||||
guchar *col2)
|
||||
{
|
||||
gint b;
|
||||
|
||||
for (b = 0; b < bytes; b++)
|
||||
for (b = 0; b < 4; b++)
|
||||
{
|
||||
if (col1[b] != col2[b])
|
||||
return FALSE;
|
||||
|
@ -549,8 +531,7 @@ gimp_image_crop_colors_equal (guchar *col1,
|
|||
|
||||
static gboolean
|
||||
gimp_image_crop_colors_alpha (guchar *dummy,
|
||||
guchar *col,
|
||||
gint bytes)
|
||||
guchar *col)
|
||||
{
|
||||
return (col[bytes - 1] == 0);
|
||||
return (col[ALPHA] == 0);
|
||||
}
|
||||
|
|
|
@ -96,7 +96,8 @@ static TileManager * gimp_image_map_get_tiles (GimpPickable *pick
|
|||
static gboolean gimp_image_map_get_pixel_at (GimpPickable *pickable,
|
||||
gint x,
|
||||
gint y,
|
||||
guchar *pixel);
|
||||
const Babl *format,
|
||||
gpointer pixel);
|
||||
|
||||
static void gimp_image_map_update_undo_buffer
|
||||
(GimpImageMap *image_map,
|
||||
|
@ -280,7 +281,8 @@ static gboolean
|
|||
gimp_image_map_get_pixel_at (GimpPickable *pickable,
|
||||
gint x,
|
||||
gint y,
|
||||
guchar *pixel)
|
||||
const Babl *format,
|
||||
gpointer pixel)
|
||||
{
|
||||
GimpImageMap *image_map = GIMP_IMAGE_MAP (pickable);
|
||||
GimpItem *item = GIMP_ITEM (image_map->drawable);
|
||||
|
@ -301,8 +303,7 @@ gimp_image_map_get_pixel_at (GimpPickable *pickable,
|
|||
{
|
||||
gegl_buffer_sample (image_map->undo_buffer,
|
||||
x - offset_x, y - offset_y,
|
||||
NULL, pixel,
|
||||
gimp_drawable_get_format (image_map->drawable),
|
||||
NULL, pixel, format,
|
||||
GEGL_SAMPLER_NEAREST,
|
||||
GEGL_ABYSS_NONE);
|
||||
|
||||
|
@ -311,7 +312,7 @@ gimp_image_map_get_pixel_at (GimpPickable *pickable,
|
|||
}
|
||||
|
||||
return gimp_pickable_get_pixel_at (GIMP_PICKABLE (image_map->drawable),
|
||||
x, y, pixel);
|
||||
x, y, format, pixel);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
|
|
@ -155,17 +155,21 @@ gboolean
|
|||
gimp_pickable_get_pixel_at (GimpPickable *pickable,
|
||||
gint x,
|
||||
gint y,
|
||||
guchar *pixel)
|
||||
const Babl *format,
|
||||
gpointer pixel)
|
||||
{
|
||||
GimpPickableInterface *pickable_iface;
|
||||
|
||||
g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), FALSE);
|
||||
g_return_val_if_fail (pixel != NULL, FALSE);
|
||||
|
||||
if (! format)
|
||||
format = gimp_pickable_get_format (pickable);
|
||||
|
||||
pickable_iface = GIMP_PICKABLE_GET_INTERFACE (pickable);
|
||||
|
||||
if (pickable_iface->get_pixel_at)
|
||||
return pickable_iface->get_pixel_at (pickable, x, y, pixel);
|
||||
return pickable_iface->get_pixel_at (pickable, x, y, format, pixel);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -181,7 +185,7 @@ gimp_pickable_get_color_at (GimpPickable *pickable,
|
|||
g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), FALSE);
|
||||
g_return_val_if_fail (color != NULL, FALSE);
|
||||
|
||||
if (! gimp_pickable_get_pixel_at (pickable, x, y, pixel))
|
||||
if (! gimp_pickable_get_pixel_at (pickable, x, y, NULL, pixel))
|
||||
return FALSE;
|
||||
|
||||
gimp_rgba_set_pixel (color, gimp_pickable_get_format (pickable), pixel);
|
||||
|
@ -216,17 +220,14 @@ gimp_pickable_pick_color (GimpPickable *pickable,
|
|||
gint *color_index)
|
||||
{
|
||||
const Babl *format;
|
||||
const Babl *fish;
|
||||
guchar pixel[4];
|
||||
guchar col[4];
|
||||
|
||||
g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), FALSE);
|
||||
|
||||
if (! gimp_pickable_get_pixel_at (pickable, x, y, pixel))
|
||||
return FALSE;
|
||||
format = babl_format ("R'G'B'A u8");
|
||||
|
||||
format = gimp_pickable_get_format (pickable);
|
||||
fish = babl_fish (format, babl_format ("R'G'B'A u8"));
|
||||
if (! gimp_pickable_get_pixel_at (pickable, x, y, format, pixel))
|
||||
return FALSE;
|
||||
|
||||
if (sample_average)
|
||||
{
|
||||
|
@ -237,41 +238,42 @@ gimp_pickable_pick_color (GimpPickable *pickable,
|
|||
|
||||
for (i = x - radius; i <= x + radius; i++)
|
||||
for (j = y - radius; j <= y + radius; j++)
|
||||
if (gimp_pickable_get_pixel_at (pickable, i, j, pixel))
|
||||
if (gimp_pickable_get_pixel_at (pickable, i, j, format, pixel))
|
||||
{
|
||||
count++;
|
||||
|
||||
babl_process (fish, pixel, col, 1);
|
||||
|
||||
color_avg[RED] += col[RED];
|
||||
color_avg[GREEN] += col[GREEN];
|
||||
color_avg[BLUE] += col[BLUE];
|
||||
color_avg[ALPHA] += col[ALPHA];
|
||||
color_avg[RED] += pixel[RED];
|
||||
color_avg[GREEN] += pixel[GREEN];
|
||||
color_avg[BLUE] += pixel[BLUE];
|
||||
color_avg[ALPHA] += pixel[ALPHA];
|
||||
}
|
||||
|
||||
col[RED] = (guchar) ((color_avg[RED] + count / 2) / count);
|
||||
col[GREEN] = (guchar) ((color_avg[GREEN] + count / 2) / count);
|
||||
col[BLUE] = (guchar) ((color_avg[BLUE] + count / 2) / count);
|
||||
col[ALPHA] = (guchar) ((color_avg[ALPHA] + count / 2) / count);
|
||||
pixel[RED] = (guchar) ((color_avg[RED] + count / 2) / count);
|
||||
pixel[GREEN] = (guchar) ((color_avg[GREEN] + count / 2) / count);
|
||||
pixel[BLUE] = (guchar) ((color_avg[BLUE] + count / 2) / count);
|
||||
pixel[ALPHA] = (guchar) ((color_avg[ALPHA] + count / 2) / count);
|
||||
}
|
||||
else
|
||||
{
|
||||
babl_process (fish, pixel, col, 1);
|
||||
}
|
||||
|
||||
|
||||
gimp_rgba_set_uchar (color,
|
||||
col[RED],
|
||||
col[GREEN],
|
||||
col[BLUE],
|
||||
col[ALPHA]);
|
||||
pixel[RED],
|
||||
pixel[GREEN],
|
||||
pixel[BLUE],
|
||||
pixel[ALPHA]);
|
||||
|
||||
if (color_index)
|
||||
{
|
||||
format = gimp_pickable_get_format (pickable);
|
||||
|
||||
if (babl_format_is_palette (format) && ! sample_average)
|
||||
*color_index = pixel[0];
|
||||
{
|
||||
gimp_pickable_get_pixel_at (pickable, x, y, format, pixel);
|
||||
|
||||
*color_index = pixel[0];
|
||||
}
|
||||
else
|
||||
*color_index = -1;
|
||||
{
|
||||
*color_index = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
|
@ -44,7 +44,8 @@ struct _GimpPickableInterface
|
|||
gboolean (* get_pixel_at) (GimpPickable *pickable,
|
||||
gint x,
|
||||
gint y,
|
||||
guchar *pixel);
|
||||
const Babl *format,
|
||||
gpointer pixel);
|
||||
gint (* get_opacity_at) (GimpPickable *pickable,
|
||||
gint x,
|
||||
gint y);
|
||||
|
@ -62,7 +63,8 @@ TileManager * gimp_pickable_get_tiles (GimpPickable *pickable);
|
|||
gboolean gimp_pickable_get_pixel_at (GimpPickable *pickable,
|
||||
gint x,
|
||||
gint y,
|
||||
guchar *pixel);
|
||||
const Babl *format,
|
||||
gpointer pixel);
|
||||
gboolean gimp_pickable_get_color_at (GimpPickable *pickable,
|
||||
gint x,
|
||||
gint y,
|
||||
|
|
|
@ -67,7 +67,8 @@ static TileManager * gimp_projection_get_tiles (GimpPickable *picka
|
|||
static gboolean gimp_projection_get_pixel_at (GimpPickable *pickable,
|
||||
gint x,
|
||||
gint y,
|
||||
guchar *pixel);
|
||||
const Babl *format,
|
||||
gpointer pixel);
|
||||
static gint gimp_projection_get_opacity_at (GimpPickable *pickable,
|
||||
gint x,
|
||||
gint y);
|
||||
|
@ -338,7 +339,8 @@ static gboolean
|
|||
gimp_projection_get_pixel_at (GimpPickable *pickable,
|
||||
gint x,
|
||||
gint y,
|
||||
guchar *pixel)
|
||||
const Babl *format,
|
||||
gpointer pixel)
|
||||
{
|
||||
GeglBuffer *buffer = gimp_projection_get_buffer (pickable);
|
||||
|
||||
|
@ -348,8 +350,7 @@ gimp_projection_get_pixel_at (GimpPickable *pickable,
|
|||
y >= gegl_buffer_get_height (buffer))
|
||||
return FALSE;
|
||||
|
||||
gegl_buffer_sample (buffer, x, y, NULL, pixel,
|
||||
gimp_projection_get_format (pickable),
|
||||
gegl_buffer_sample (buffer, x, y, NULL, pixel, format,
|
||||
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
|
||||
|
||||
return TRUE;
|
||||
|
|
Loading…
Reference in New Issue