mirror of https://github.com/GNOME/gimp.git
app: add gimp_image_flip_full()
... which takes the symmetry axis as a parameter, instead of hard- coding the axis to the middle of the image, and which additionally takes the clipping mode as a parameter, controlling whether to clip or resize the canvas. Note that the actual canvas size never changes, but it may be offset when flipped around an off-center axis, without clipping. Implement gimp_image_flip() in terms of gimp_image_flip_full().
This commit is contained in:
parent
d13c6ce3e0
commit
ae080f06f9
|
@ -20,9 +20,12 @@
|
|||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#include "libgimpmath/gimpmath.h"
|
||||
|
||||
#include "core-types.h"
|
||||
|
||||
#include "gimp.h"
|
||||
#include "gimpchannel.h"
|
||||
#include "gimpcontainer.h"
|
||||
#include "gimpcontext.h"
|
||||
#include "gimpguide.h"
|
||||
|
@ -38,38 +41,185 @@
|
|||
#include "gimpsamplepoint.h"
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void gimp_image_flip_guides (GimpImage *image,
|
||||
GimpOrientationType flip_type,
|
||||
gdouble axis);
|
||||
static void gimp_image_flip_sample_points (GimpImage *image,
|
||||
GimpOrientationType flip_type,
|
||||
gdouble axis);
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
static void
|
||||
gimp_image_flip_guides (GimpImage *image,
|
||||
GimpOrientationType flip_type,
|
||||
gdouble axis)
|
||||
{
|
||||
gint width = gimp_image_get_width (image);
|
||||
gint height = gimp_image_get_height (image);
|
||||
GList *iter;
|
||||
|
||||
for (iter = gimp_image_get_guides (image); iter;)
|
||||
{
|
||||
GimpGuide *guide = iter->data;
|
||||
gint position = gimp_guide_get_position (guide);
|
||||
|
||||
iter = g_list_next (iter);
|
||||
|
||||
position = SIGNED_ROUND (2.0 * axis - position);
|
||||
|
||||
switch (gimp_guide_get_orientation (guide))
|
||||
{
|
||||
case GIMP_ORIENTATION_HORIZONTAL:
|
||||
if (flip_type == GIMP_ORIENTATION_VERTICAL)
|
||||
{
|
||||
if (position >= 0 && position <= height)
|
||||
gimp_image_move_guide (image, guide, position, TRUE);
|
||||
else
|
||||
gimp_image_remove_guide (image, guide, TRUE);
|
||||
}
|
||||
break;
|
||||
|
||||
case GIMP_ORIENTATION_VERTICAL:
|
||||
if (flip_type == GIMP_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
if (position >= 0 && position <= width)
|
||||
gimp_image_move_guide (image, guide, position, TRUE);
|
||||
else
|
||||
gimp_image_remove_guide (image, guide, TRUE);
|
||||
}
|
||||
break;
|
||||
|
||||
case GIMP_ORIENTATION_UNKNOWN:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_image_flip_sample_points (GimpImage *image,
|
||||
GimpOrientationType flip_type,
|
||||
gdouble axis)
|
||||
{
|
||||
gint width = gimp_image_get_width (image);
|
||||
gint height = gimp_image_get_height (image);
|
||||
GList *iter;
|
||||
|
||||
for (iter = gimp_image_get_sample_points (image); iter;)
|
||||
{
|
||||
GimpSamplePoint *sample_point = iter->data;
|
||||
gint x;
|
||||
gint y;
|
||||
|
||||
iter = g_list_next (iter);
|
||||
|
||||
gimp_sample_point_get_position (sample_point, &x, &y);
|
||||
|
||||
switch (flip_type)
|
||||
{
|
||||
case GIMP_ORIENTATION_HORIZONTAL:
|
||||
x = SIGNED_ROUND (2.0 * axis - x);
|
||||
break;
|
||||
|
||||
case GIMP_ORIENTATION_VERTICAL:
|
||||
y = SIGNED_ROUND (2.0 * axis - y);
|
||||
break;
|
||||
|
||||
case GIMP_ORIENTATION_UNKNOWN:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
if (x >= 0 && x < width &&
|
||||
y >= 0 && y < height)
|
||||
{
|
||||
gimp_image_move_sample_point (image, sample_point, x, y, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_image_remove_sample_point (image, sample_point, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
void
|
||||
gimp_image_flip (GimpImage *image,
|
||||
GimpContext *context,
|
||||
GimpOrientationType flip_type,
|
||||
GimpProgress *progress)
|
||||
{
|
||||
GimpObjectQueue *queue;
|
||||
GimpItem *item;
|
||||
GList *list;
|
||||
gdouble axis;
|
||||
gdouble axis = 0.0;
|
||||
|
||||
g_return_if_fail (GIMP_IS_IMAGE (image));
|
||||
g_return_if_fail (GIMP_IS_CONTEXT (context));
|
||||
g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
|
||||
|
||||
gimp_set_busy (image->gimp);
|
||||
|
||||
switch (flip_type)
|
||||
{
|
||||
case GIMP_ORIENTATION_HORIZONTAL:
|
||||
axis = (gdouble) gimp_image_get_width (image) / 2.0;
|
||||
axis = gimp_image_get_width (image) / 2.0;
|
||||
break;
|
||||
|
||||
case GIMP_ORIENTATION_VERTICAL:
|
||||
axis = (gdouble) gimp_image_get_height (image) / 2.0;
|
||||
axis = gimp_image_get_height (image) / 2.0;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warning ("%s: unknown flip_type", G_STRFUNC);
|
||||
return;
|
||||
case GIMP_ORIENTATION_UNKNOWN:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
gimp_image_flip_full (image, context, flip_type, axis,
|
||||
GIMP_TRANSFORM_RESIZE_CLIP, progress);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_image_flip_full (GimpImage *image,
|
||||
GimpContext *context,
|
||||
GimpOrientationType flip_type,
|
||||
gdouble axis,
|
||||
gboolean clip_result,
|
||||
GimpProgress *progress)
|
||||
{
|
||||
GimpObjectQueue *queue;
|
||||
GimpItem *item;
|
||||
gint width;
|
||||
gint height;
|
||||
gint offset_x = 0;
|
||||
gint offset_y = 0;
|
||||
|
||||
g_return_if_fail (GIMP_IS_IMAGE (image));
|
||||
g_return_if_fail (GIMP_IS_CONTEXT (context));
|
||||
g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
|
||||
|
||||
width = gimp_image_get_width (image);
|
||||
height = gimp_image_get_height (image);
|
||||
|
||||
if (! clip_result)
|
||||
{
|
||||
switch (flip_type)
|
||||
{
|
||||
case GIMP_ORIENTATION_HORIZONTAL:
|
||||
offset_x = SIGNED_ROUND (2.0 * axis - width);
|
||||
axis = width / 2.0;
|
||||
break;
|
||||
|
||||
case GIMP_ORIENTATION_VERTICAL:
|
||||
offset_y = SIGNED_ROUND (2.0 * axis - height);
|
||||
axis = height / 2.0;
|
||||
break;
|
||||
|
||||
case GIMP_ORIENTATION_UNKNOWN:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
gimp_set_busy (image->gimp);
|
||||
|
||||
queue = gimp_object_queue_new (progress);
|
||||
progress = GIMP_PROGRESS (queue);
|
||||
|
||||
|
@ -83,67 +233,44 @@ gimp_image_flip (GimpImage *image,
|
|||
/* Flip all layers, channels (including selection mask), and vectors */
|
||||
while ((item = gimp_object_queue_pop (queue)))
|
||||
{
|
||||
gimp_item_flip (item, context, flip_type, axis, FALSE);
|
||||
gboolean clip = FALSE;
|
||||
|
||||
if (GIMP_IS_CHANNEL (item))
|
||||
clip = clip_result;
|
||||
|
||||
gimp_item_flip (item, context, flip_type, axis, clip);
|
||||
|
||||
gimp_progress_set_value (progress, 1.0);
|
||||
}
|
||||
|
||||
/* Flip all Guides */
|
||||
for (list = gimp_image_get_guides (image);
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
GimpGuide *guide = list->data;
|
||||
gint position = gimp_guide_get_position (guide);
|
||||
|
||||
switch (gimp_guide_get_orientation (guide))
|
||||
{
|
||||
case GIMP_ORIENTATION_HORIZONTAL:
|
||||
if (flip_type == GIMP_ORIENTATION_VERTICAL)
|
||||
gimp_image_move_guide (image, guide,
|
||||
gimp_image_get_height (image) - position,
|
||||
TRUE);
|
||||
break;
|
||||
|
||||
case GIMP_ORIENTATION_VERTICAL:
|
||||
if (flip_type == GIMP_ORIENTATION_HORIZONTAL)
|
||||
gimp_image_move_guide (image, guide,
|
||||
gimp_image_get_width (image) - position,
|
||||
TRUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
gimp_image_flip_guides (image, flip_type, axis);
|
||||
|
||||
/* Flip all sample points */
|
||||
for (list = gimp_image_get_sample_points (image);
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
gimp_image_flip_sample_points (image, flip_type, axis);
|
||||
|
||||
if (offset_x || offset_y)
|
||||
{
|
||||
GimpSamplePoint *sample_point = list->data;
|
||||
gint x;
|
||||
gint y;
|
||||
|
||||
gimp_sample_point_get_position (sample_point, &x, &y);
|
||||
|
||||
if (flip_type == GIMP_ORIENTATION_VERTICAL)
|
||||
gimp_image_move_sample_point (image, sample_point,
|
||||
x,
|
||||
gimp_image_get_height (image) - y,
|
||||
TRUE);
|
||||
|
||||
if (flip_type == GIMP_ORIENTATION_HORIZONTAL)
|
||||
gimp_image_move_sample_point (image, sample_point,
|
||||
gimp_image_get_width (image) - x,
|
||||
y,
|
||||
TRUE);
|
||||
gimp_image_undo_push_image_size (image,
|
||||
NULL,
|
||||
offset_x,
|
||||
offset_y,
|
||||
width,
|
||||
height);
|
||||
}
|
||||
|
||||
gimp_image_undo_group_end (image);
|
||||
|
||||
g_object_unref (queue);
|
||||
|
||||
if (offset_x || offset_y)
|
||||
{
|
||||
gimp_image_size_changed_detailed (image,
|
||||
-offset_x,
|
||||
-offset_y,
|
||||
width,
|
||||
height);
|
||||
}
|
||||
|
||||
gimp_unset_busy (image->gimp);
|
||||
}
|
||||
|
|
|
@ -19,10 +19,16 @@
|
|||
#define __GIMP_IMAGE_FLIP_H__
|
||||
|
||||
|
||||
void gimp_image_flip (GimpImage *image,
|
||||
GimpContext *context,
|
||||
GimpOrientationType flip_type,
|
||||
GimpProgress *progress);
|
||||
void gimp_image_flip (GimpImage *image,
|
||||
GimpContext *context,
|
||||
GimpOrientationType flip_type,
|
||||
GimpProgress *progress);
|
||||
void gimp_image_flip_full (GimpImage *image,
|
||||
GimpContext *context,
|
||||
GimpOrientationType flip_type,
|
||||
gdouble axis,
|
||||
gboolean clip_result,
|
||||
GimpProgress *progress);
|
||||
|
||||
|
||||
#endif /* __GIMP_IMAGE_FLIP_H__ */
|
||||
|
|
Loading…
Reference in New Issue