Image: Flip image operator
This implements an operator to flip the contents of an image buffer. It supports flipping the image horizontally and vertically. Reviewed By: JacquesLucke Differential Revision: https://developer.blender.org/D10310
This commit is contained in:
parent
faf45091b4
commit
7d874b0343
|
@ -235,6 +235,7 @@ class IMAGE_MT_image(Menu):
|
|||
|
||||
layout.menu("IMAGE_MT_image_invert")
|
||||
layout.operator("image.resize", text="Resize")
|
||||
layout.menu("IMAGE_MT_image_flip")
|
||||
|
||||
if ima and not show_render:
|
||||
if ima.packed_file:
|
||||
|
@ -250,6 +251,13 @@ class IMAGE_MT_image(Menu):
|
|||
layout.operator("palette.extract_from_image", text="Extract Palette")
|
||||
layout.operator("gpencil.image_to_grease_pencil", text="Generate Grease Pencil")
|
||||
|
||||
class IMAGE_MT_image_flip(Menu):
|
||||
bl_label = "Flip"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
layout.operator("image.flip", text="Horizontally").use_flip_horizontal = True
|
||||
layout.operator("image.flip", text="Vertically").use_flip_vertical = True
|
||||
|
||||
class IMAGE_MT_image_invert(Menu):
|
||||
bl_label = "Invert"
|
||||
|
@ -1584,6 +1592,7 @@ classes = (
|
|||
IMAGE_MT_select,
|
||||
IMAGE_MT_select_linked,
|
||||
IMAGE_MT_image,
|
||||
IMAGE_MT_image_flip,
|
||||
IMAGE_MT_image_invert,
|
||||
IMAGE_MT_uvs,
|
||||
IMAGE_MT_uvs_showhide,
|
||||
|
|
|
@ -71,6 +71,7 @@ void IMAGE_OT_save_all_modified(struct wmOperatorType *ot);
|
|||
void IMAGE_OT_pack(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_unpack(struct wmOperatorType *ot);
|
||||
|
||||
void IMAGE_OT_flip(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_invert(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_resize(struct wmOperatorType *ot);
|
||||
|
||||
|
|
|
@ -2660,6 +2660,126 @@ void IMAGE_OT_new(wmOperatorType *ot)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Flip Operator
|
||||
* \{ */
|
||||
|
||||
static int image_flip_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Image *ima = image_from_context(C);
|
||||
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
const bool is_paint = ((sima != NULL) && (sima->mode == SI_MODE_PAINT));
|
||||
|
||||
if (ibuf == NULL) {
|
||||
/* TODO: this should actually never happen, but does for render-results -> cleanup. */
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
const bool flip_horizontal = RNA_boolean_get(op->ptr, "use_flip_horizontal");
|
||||
const bool flip_vertical = RNA_boolean_get(op->ptr, "use_flip_vertical");
|
||||
|
||||
if (!flip_horizontal && !flip_vertical) {
|
||||
BKE_image_release_ibuf(ima, ibuf, NULL);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, &sima->iuser);
|
||||
|
||||
if (is_paint) {
|
||||
ED_imapaint_clear_partial_redraw();
|
||||
}
|
||||
|
||||
const int size_x = ibuf->x;
|
||||
const int size_y = ibuf->y;
|
||||
|
||||
if (ibuf->rect_float) {
|
||||
float *float_pixels = (float *)ibuf->rect_float;
|
||||
|
||||
float *orig_float_pixels = MEM_dupallocN(float_pixels);
|
||||
for (int x = 0; x < size_x; x++) {
|
||||
for (int y = 0; y < size_y; y++) {
|
||||
const int source_pixel_x = flip_horizontal ? size_x - x - 1 : x;
|
||||
const int source_pixel_y = flip_vertical ? size_y - y - 1 : y;
|
||||
|
||||
float *source_pixel = &orig_float_pixels[4 * (source_pixel_x + source_pixel_y * size_x)];
|
||||
float *target_pixel = &float_pixels[4 * (x + y * size_x)];
|
||||
|
||||
copy_v4_v4(target_pixel, source_pixel);
|
||||
}
|
||||
}
|
||||
MEM_freeN(orig_float_pixels);
|
||||
|
||||
if (ibuf->rect) {
|
||||
IMB_rect_from_float(ibuf);
|
||||
}
|
||||
}
|
||||
else if (ibuf->rect) {
|
||||
char *char_pixels = (char *)ibuf->rect;
|
||||
char *orig_char_pixels = MEM_dupallocN(char_pixels);
|
||||
for (int x = 0; x < size_x; x++) {
|
||||
for (int y = 0; y < size_y; y++) {
|
||||
const int source_pixel_x = flip_horizontal ? size_x - x - 1 : x;
|
||||
const int source_pixel_y = flip_vertical ? size_y - y - 1 : y;
|
||||
|
||||
char *source_pixel = &orig_char_pixels[4 * (source_pixel_x + source_pixel_y * size_x)];
|
||||
char *target_pixel = &char_pixels[4 * (x + y * size_x)];
|
||||
|
||||
copy_v4_v4_char(target_pixel, source_pixel);
|
||||
}
|
||||
}
|
||||
MEM_freeN(orig_char_pixels);
|
||||
}
|
||||
else {
|
||||
BKE_image_release_ibuf(ima, ibuf, NULL);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
|
||||
BKE_image_mark_dirty(ima, ibuf);
|
||||
|
||||
if (ibuf->mipmap[0]) {
|
||||
ibuf->userflags |= IB_MIPMAP_INVALID;
|
||||
}
|
||||
|
||||
ED_image_undo_push_end();
|
||||
|
||||
/* force GPU reupload, all image is invalid. */
|
||||
BKE_image_free_gputextures(ima);
|
||||
|
||||
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
|
||||
|
||||
BKE_image_release_ibuf(ima, ibuf, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void IMAGE_OT_flip(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Flip Image";
|
||||
ot->idname = "IMAGE_OT_flip";
|
||||
ot->description = "Flip the image";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = image_flip_exec;
|
||||
ot->poll = image_from_context_has_data_poll_no_image_user;
|
||||
|
||||
/* properties */
|
||||
PropertyRNA *prop;
|
||||
prop = RNA_def_boolean(
|
||||
ot->srna, "use_flip_horizontal", false, "Horizontal", "Flip the image horizontally");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
prop = RNA_def_boolean(
|
||||
ot->srna, "use_flip_vertical", false, "Vertical", "Flip the image vertically");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Invert Operators
|
||||
* \{ */
|
||||
|
|
|
@ -234,6 +234,7 @@ static void image_operatortypes(void)
|
|||
WM_operatortype_append(IMAGE_OT_pack);
|
||||
WM_operatortype_append(IMAGE_OT_unpack);
|
||||
|
||||
WM_operatortype_append(IMAGE_OT_flip);
|
||||
WM_operatortype_append(IMAGE_OT_invert);
|
||||
WM_operatortype_append(IMAGE_OT_resize);
|
||||
|
||||
|
|
Loading…
Reference in New Issue