Commit e6975ed0 authored by Michael Natterer's avatar Michael Natterer 😴

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".
parent a61885f3
......@@ -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;
for (i = 0; i < bytes; 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 < 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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment