[Bf-blender-cvs] [7d874b03433] master: Image: Flip image operator

Pablo Dobarro noreply at git.blender.org
Fri Feb 5 19:16:16 CET 2021


Commit: 7d874b03433d19695f9e4e4bffb297d02c66c6eb
Author: Pablo Dobarro
Date:   Thu Feb 4 18:03:42 2021 +0100
Branches: master
https://developer.blender.org/rB7d874b03433d19695f9e4e4bffb297d02c66c6eb

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

===================================================================

M	release/scripts/startup/bl_ui/space_image.py
M	source/blender/editors/space_image/image_intern.h
M	source/blender/editors/space_image/image_ops.c
M	source/blender/editors/space_image/space_image.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 342b72acb8c..73cc674858c 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -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,
diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h
index 100556ad29a..0044c6072a4 100644
--- a/source/blender/editors/space_image/image_intern.h
+++ b/source/blender/editors/space_image/image_intern.h
@@ -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);
 
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 9b8bf3c2fee..e7f468f2f26 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -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
  * \{ */
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index b0571d47736..0dd99824dcd 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -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);



More information about the Bf-blender-cvs mailing list