diff --git a/src/main.rs b/src/main.rs index 1ad2b3e..0e767a1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,24 +1,15 @@ -use gtk::builders::ImageBuilder; -use gtk::gio::Cancellable; use gtk::prelude::*; -use gtk::{Application, ApplicationWindow, Picture, Scale, Label, FileDialog}; +use gtk::{Application, ApplicationWindow, Button, FileDialog, Picture, Scale, Box as GtkBox}; use image::{DynamicImage, ImageBuffer, RgbImage}; -use gtk::{Button, Box as GtkBox, Orientation}; -use gtk::glib::Propagation; -use gtk::gdk_pixbuf::Pixbuf; -use std::fs; -use std::path::Path; -use gtk::gio::File; +use std::path::{Path, PathBuf}; use std::rc::Rc; use std::cell::RefCell; fn main() { - // Инициализация приложения let app = Application::builder() .application_id("ru.risdeveau.imageeditor") .build(); - // Запуск приложения app.connect_activate(|app| { build_ui(app); }); @@ -27,7 +18,6 @@ fn main() { } fn build_ui(app: &Application) { - // Создание окна let window = ApplicationWindow::builder() .application(app) .title("Image Editor") @@ -36,141 +26,95 @@ fn build_ui(app: &Application) { .build(); window.set_resizable(false); - let selected_file = Rc::new(RefCell::new(None::)); + let container = GtkBox::new(gtk::Orientation::Vertical, 5); + let open_button = Button::with_label("Open Image"); + let picture = Picture::new(); + let brightness_slider = Scale::with_range(gtk::Orientation::Horizontal, -100.0, 100.0, 1.0); + brightness_slider.set_value(0.); - // Создание кнопки для открытия диалога выбора файла - let button = Button::with_label("Select Image"); - // let picture = Picture::new(); - // picture.set_size_request(400, 400); + // Храним путь и оригинальное изображение + let image_data = Rc::new(RefCell::new(None::<(PathBuf, ImageBuffer, Vec>)>)); + // Функция для редактирования изображения + fn edit_image(image: &mut RgbImage, brightness: i8) { + for pixel in image.pixels_mut() { + pixel.0 = [ + (pixel.0[0] as i16 + brightness as i16).clamp(0, 255) as u8, + (pixel.0[1] as i16 + brightness as i16).clamp(0, 255) as u8, + (pixel.0[2] as i16 + brightness as i16).clamp(0, 255) as u8, + ]; + } + } + + // Открытие изображения { let window = window.clone(); - let selected_file = selected_file.clone(); - // let picture = picture.clone(); - button.connect_clicked(move |_| { - // Создание FileDialog + let image_data = image_data.clone(); + let picture = picture.clone(); + open_button.connect_clicked(move |_| { let dialog = FileDialog::builder() - .title("Select an Image") - .accept_label("Open") + .title("Select Image") .build(); - // Фильтр для изображений let filter = gtk::FileFilter::new(); - filter.add_mime_type("image/png"); // Разрешить только изображения - filter.set_name(Some("Image Files")); + filter.add_mime_type("image/*"); dialog.set_default_filter(Some(&filter)); - // Показ диалога и обработка результата let window = window.clone(); - let selected_file = selected_file.clone(); - // let picture = picture.clone(); - dialog.open(Some(&window), None::<>k::gio::Cancellable>, move |result| { - if let Ok(file) = result { - // Получение выбранного файла - let path = file.path().unwrap(); - println!("Selected image: {:?}", path); - - // Загрузка изображения (опционально) - if let Ok(pixbuf) = Pixbuf::from_file(&path) { - println!("Image loaded successfully: {}x{}", pixbuf.width(), pixbuf.height()); - let _ = fs::copy(&path, "/tmp/modified.png"); - *selected_file.borrow_mut() = Some(file.clone()); - // picture.set_pixbuf(Some(&pixbuf)); - - } else { - eprintln!("Failed to load image."); + let image_data = image_data.clone(); + let picture = picture.clone(); + dialog.open( + Some(&window), + None::<>k::gio::Cancellable>, + move |result| { + if let Ok(file) = result { + if let Some(path) = file.path() { + match image::open(&path) { + Ok(img) => { + let mut rgb_img = img.to_rgb8(); + *image_data.borrow_mut() = Some((path.to_path_buf(), rgb_img.clone())); + + // Сохраняем временную копию для отображения + let temp_path = Path::new("/tmp/gtk_temp_img.png"); + if rgb_img.save(temp_path).is_ok() { + picture.set_filename(Some(temp_path)); + } + } + Err(e) => eprintln!("Failed to load image: {}", e), + } + } } - } else { - eprintln!("File selection canceled."); } - }); + ); }); } - if selected_file.borrow().is_some() { - button.set_visible(false); - } - - let picture = Picture::for_filename("/tmp/modified.png"); - let image = image::open("/tmp/modified.png") - .map(|img| img.to_rgb8()) - .map_err(|e| eprintln!("Failed to load image: {}", e)) - .ok().unwrap(); - - let br_slider = Scale::with_range(Orientation::Horizontal, -128., 128., 10.); - br_slider.set_value(0.); - br_slider.set_hexpand(true); - - let br_text = Label::new(Some("Brightness: +000")); - - let br_container = GtkBox::new(Orientation::Horizontal, 5); - br_container.append(&br_text); - br_container.append(&br_slider); - + // Регулировка яркости { - br_slider.clone().connect_change_value(move |_, _, _| { - let mut value = br_slider.value(); - value = value.round(); - br_slider.set_value(value); - br_text.set_text(&format!("Brightness: {:+04.0}", value)); - edit_image(&mut image, value as i8); - - // Продолжаем обработку события - Propagation::Proceed + let image_data = image_data.clone(); + let picture = picture.clone(); + brightness_slider.connect_value_changed(move |slider| { + if let Some((path, ref mut image)) = image_data.borrow_mut().as_mut() { + let value = slider.value() as i8; + + // Редактируем копию оригинального изображения + if let Ok(original) = image::open(path) { + let mut edited = original.to_rgb8(); + edit_image(&mut edited, value); + + // Сохраняем и отображаем + let temp_path = Path::new("/tmp/gtk_temp_img.png"); + if edited.save(temp_path).is_ok() { + picture.set_filename(Some(temp_path)); + } + } + } }); } - - - let container = GtkBox::new(Orientation::Vertical, 8); - container.append(&button); + + container.append(&open_button); container.append(&picture); - container.append(&br_container); - + container.append(&brightness_slider); window.set_child(Some(&container)); - - // // Загрузка изображения - // let mut img: RgbImage = ImageBuffer::new(256, 256); // Пример: пустое изображение - // let mut dynamic_img = DynamicImage::ImageRgb8(img.clone()); - - // // Сохранение изображения во временный файл - // let temp_path = "temp_image.png"; - // dynamic_img.save(temp_path).unwrap(); - - // // Создание виджета Picture для отображения изображения - // let picture = Picture::for_filename(temp_path); - - // // Создание кнопки - // let button = Button::with_label("Edit Image"); - - // // Контейнер для размещения виджетов - // let container = GtkBox::new(Orientation::Vertical, 5); - // container.append(&picture); - // container.append(&button); - - // // Обработка нажатия кнопки - // button.connect_clicked(move |_| { - // // Редактирование изображения - // edit_image(&mut img); - // dynamic_img = DynamicImage::ImageRgb8(img.clone()); - - // // Обновление изображения в интерфейсе - // update_image(&picture, &dynamic_img); - // }); - - // // Добавление контейнера в окно - // window.set_child(Some(&container)); - - // Отображение окна window.show(); } - -fn edit_image(img: &mut RgbImage, brightness: i8) { - for (x, y, pixel) in img.enumerate_pixels_mut() { - pixel[0] = (pixel[0] as i16 + brightness as i16) as u8; - } -} - -// fn update_image(picture: &Picture, img: &DynamicImage) { -// img.save("tmp.png").unwrap(); -// picture.set_filename(Some(temp_path)); -// }