diff options
author | Pablo Dobarro <pablodp606@gmail.com> | 2021-02-04 20:03:42 +0300 |
---|---|---|
committer | Pablo Dobarro <pablodp606@gmail.com> | 2021-02-05 21:15:43 +0300 |
commit | 7d874b03433d19695f9e4e4bffb297d02c66c6eb (patch) | |
tree | 3d5fcf0634689395b7eff3b68da4265e11e90c14 | |
parent | faf45091b454bb99089e82533b12b549efb1a5c7 (diff) |
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
-rw-r--r-- | release/scripts/startup/bl_ui/space_image.py | 9 | ||||
-rw-r--r-- | source/blender/editors/space_image/image_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/space_image/image_ops.c | 120 | ||||
-rw-r--r-- | source/blender/editors/space_image/space_image.c | 1 |
4 files changed, 131 insertions, 0 deletions
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 @@ -2661,6 +2661,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); |