diff options
Diffstat (limited to 'source/blender/editors')
-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 |
3 files changed, 122 insertions, 0 deletions
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); |