Compare commits

..

3 Commits

Author SHA1 Message Date
8633c5eafd
crop lr works too 2023-10-05 16:24:51 +02:00
440489f228
sanitize crop 2023-10-05 14:54:42 +02:00
bb824a9fb7
cropping ui partly done (upper left cropper works) 2023-10-05 14:23:39 +02:00
2 changed files with 180 additions and 20 deletions

View File

@ -33,6 +33,10 @@ void SendImagePopup::reset(void) {
_tu.destroy(tex_id);
}
preview_image = {};
cropping = false;
dragging_last_frame_ul = false;
dragging_last_frame_lr = false;
}
bool SendImagePopup::load(void) {
@ -43,19 +47,20 @@ bool SendImagePopup::load(void) {
continue;
}
#if 1
#if 0
crop_rect.x = 0;
crop_rect.y = 0;
crop_rect.w = original_image.width;
crop_rect.h = original_image.height;
#else
crop_rect.x = original_image.width * 0.1f;
crop_rect.y = original_image.height * 0.1f;
crop_rect.w = original_image.width * 0.8f;
crop_rect.h = original_image.height * 0.8f;
crop_rect.x = original_image.width * 0.05f;
crop_rect.y = original_image.height * 0.05f;
crop_rect.w = original_image.width * 0.9f;
crop_rect.h = original_image.height * 0.9f;
#endif
crop_rect = sanitizeCrop(crop_rect, original_image.width, original_image.height);
crop_before_drag = crop_rect;
original_file_ext = ".";
if (original_image.file_ext != nullptr) {
@ -191,20 +196,32 @@ ImageLoaderI::ImageResult SendImagePopup::crop(const ImageLoaderI::ImageResult&
return new_image;
}
SendImagePopup::Rect SendImagePopup::sanitizeCrop(Rect crop_rect, uint32_t image_width, uint32_t image_height) {
SendImagePopup::Rect SendImagePopup::sanitizeCrop(Rect crop_rect, int32_t image_width, int32_t image_height) {
// w and h min is 1 -> x/y need to be smaller so the img is atleast 1px in any dim
if (crop_rect.x >= image_width-1) {
crop_rect.x = image_width-2;
} else if (crop_rect.x < 0) {
crop_rect.x = 0;
}
if (crop_rect.y >= image_height-1) {
crop_rect.y = image_height-2;
} else if (crop_rect.y < 0) {
crop_rect.y = 0;
}
if (crop_rect.w > crop_rect.x + image_width) {
crop_rect.w = crop_rect.x + image_width;
} else if (crop_rect.w < 1) {
crop_rect.w = 1;
// TODO: adjust X
}
if (crop_rect.h > crop_rect.y + image_height) {
crop_rect.h = crop_rect.y + image_height;
} else if (crop_rect.h < 1) {
crop_rect.h = 1;
// TODO: adjust Y
}
return crop_rect;
@ -269,18 +286,156 @@ void SendImagePopup::render(void) {
height = max_height;
}
// TODO: propergate texture id type
// save curser pos
// TODO: propergate type
const auto pre_img_curser_screen = ImGui::GetCursorScreenPos();
const auto pre_img_curser = ImGui::GetCursorPos();
if (cropping) { // if cropping
// display full image
ImGui::Image(
preview_image.getID<void*>(),
ImVec2{static_cast<float>(width), static_cast<float>(height)}
);
const auto post_img_curser = ImGui::GetCursorPos();
// TODO: crop input here
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{0.5f, 0.5f, 0.5f, 0.2f});
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{0.5f, 0.5f, 0.5f, 0.4f});
auto ul_clipper_pos = ImVec2{float(crop_rect.x)/original_image.width, float(crop_rect.y)/original_image.height};
{ // crop upper left clipper
ImGui::SetCursorPos({
pre_img_curser.x + ul_clipper_pos.x * width,
pre_img_curser.y + ul_clipper_pos.y * height
});
ImGui::Button("##ul_clipper", {TEXT_BASE_HEIGHT, TEXT_BASE_HEIGHT});
if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
if (dragging_last_frame_ul) {
auto drag_total = ImGui::GetMouseDragDelta();
drag_total.x = (drag_total.x / width) * original_image.width;
drag_total.y = (drag_total.y / height) * original_image.height;
crop_rect.x = std::max<float>(crop_before_drag.x + drag_total.x, 0.01f);
crop_rect.y = std::max<float>(crop_before_drag.y + drag_total.y, 0.01f);
crop_rect.x = std::min<int32_t>(crop_rect.x, original_image.width-2);
crop_rect.y = std::min<int32_t>(crop_rect.y, original_image.height-2);
crop_rect.w = crop_before_drag.w - (crop_rect.x - crop_before_drag.x);
crop_rect.h = crop_before_drag.h - (crop_rect.y - crop_before_drag.y);
} else {
if (ImGui::IsItemActive()) {
dragging_last_frame_ul = true;
// drag started on button, start drag
}
}
} else if (dragging_last_frame_ul) { // was dragging
dragging_last_frame_ul = false;
crop_before_drag = crop_rect;
}
}
auto lr_clipper_pos = ImVec2{float(crop_rect.x+crop_rect.w)/original_image.width, float(crop_rect.y+crop_rect.h)/original_image.height};
{ // crop lower right clipper
ImGui::SetCursorPos({
pre_img_curser.x + lr_clipper_pos.x * width - TEXT_BASE_HEIGHT,
pre_img_curser.y + lr_clipper_pos.y * height - TEXT_BASE_HEIGHT
});
ImGui::Button("##lr_clipper", {TEXT_BASE_HEIGHT, TEXT_BASE_HEIGHT});
if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
if (dragging_last_frame_lr) {
auto drag_total = ImGui::GetMouseDragDelta();
drag_total.x = (drag_total.x / width) * original_image.width;
drag_total.y = (drag_total.y / height) * original_image.height;
crop_rect.w = std::min<float>(crop_before_drag.w + drag_total.x, original_image.width);
crop_rect.h = std::min<float>(crop_before_drag.h + drag_total.y, original_image.height);
} else {
if (ImGui::IsItemActive()) {
dragging_last_frame_lr = true;
// drag started on button, start drag
}
}
} else if (dragging_last_frame_lr) { // was dragging
dragging_last_frame_lr = false;
crop_before_drag = crop_rect;
}
}
// sanitzie after tool
crop_rect = sanitizeCrop(crop_rect, original_image.width, original_image.height);
{ // 4 lines delimiting the crop result
// x vertical
ImGui::GetWindowDrawList()->AddLine(
{pre_img_curser_screen.x + ul_clipper_pos.x * width, pre_img_curser_screen.y},
{pre_img_curser_screen.x + ul_clipper_pos.x * width, pre_img_curser_screen.y + height},
0xffffffff,
1.f
);
// y horizontal
ImGui::GetWindowDrawList()->AddLine(
{pre_img_curser_screen.x, pre_img_curser_screen.y + ul_clipper_pos.y * height},
{pre_img_curser_screen.x + width, pre_img_curser_screen.y + ul_clipper_pos.y * height},
0xffffffff,
1.f
);
// w vertical
ImGui::GetWindowDrawList()->AddLine(
{pre_img_curser_screen.x + lr_clipper_pos.x * width, pre_img_curser_screen.y},
{pre_img_curser_screen.x + lr_clipper_pos.x * width, pre_img_curser_screen.y + height},
0xffffffff,
1.f
);
// h horizontal
ImGui::GetWindowDrawList()->AddLine(
{pre_img_curser_screen.x, pre_img_curser_screen.y + lr_clipper_pos.y * height},
{pre_img_curser_screen.x + width, pre_img_curser_screen.y + lr_clipper_pos.y * height},
0xffffffff,
1.f
);
}
// cancel/ok buttons in the img center?
ImGui::PopStyleColor(2);
ImGui::SetCursorPos(post_img_curser);
} else {
crop_rect = sanitizeCrop(crop_rect, original_image.width, original_image.height);
// display cropped area
ImGui::Image(
preview_image.getID<void*>(),
ImVec2{static_cast<float>(width), static_cast<float>(height)},
ImVec2{float(crop_rect.x)/original_image.width, float(crop_rect.y)/original_image.height},
ImVec2{float(crop_rect.x+crop_rect.w)/original_image.width, float(crop_rect.y+crop_rect.h)/original_image.height}
);
const auto post_img_curser = ImGui::GetCursorPos();
ImGui::SetCursorPos(pre_img_curser);
// TODO: fancy cropping toggle
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{0.5f, 0.5f, 0.5f, 0.2f});
if (ImGui::Button("crop", {TEXT_BASE_WIDTH*8, TEXT_BASE_HEIGHT*2})) {
cropping = true;
}
ImGui::PopStyleColor();
ImGui::SetCursorPos(post_img_curser);
}
}
const bool cropped = crop_rect.x != 0 || crop_rect.y != 0 || crop_rect.w != original_image.width || crop_rect.h != original_image.height;
ImGui::Text("crop: x:%d y:%d w:%d h:%d", crop_rect.x, crop_rect.y, crop_rect.w, crop_rect.h);
bool recalc_size = false;
if (cropped) {

View File

@ -22,13 +22,18 @@ struct SendImagePopup {
ImageLoaderI::ImageResult original_image;
struct Rect {
uint32_t x {0};
uint32_t y {0};
int32_t x {0};
int32_t y {0};
uint32_t w {0};
uint32_t h {0};
int32_t w {0};
int32_t h {0};
};
Rect crop_rect;
Rect crop_before_drag;
bool cropping {false};
bool dragging_last_frame_ul {false};
bool dragging_last_frame_lr {false};
// texture to render (orig img)
TextureEntry preview_image;
@ -50,7 +55,7 @@ struct SendImagePopup {
static std::vector<uint8_t> compressWebp(const ImageLoaderI::ImageResult& input_image, uint32_t quality = 80u);
static ImageLoaderI::ImageResult crop(const ImageLoaderI::ImageResult& input_image, const Rect& crop_rect);
static Rect sanitizeCrop(Rect crop_rect, uint32_t image_width, uint32_t image_height);
static Rect sanitizeCrop(Rect crop_rect, int32_t image_width, int32_t image_height);
public:
SendImagePopup(TextureUploaderI& tu);