wip
This commit is contained in:
parent
c1ccad6229
commit
33d6bb64e3
198
src/main.rs
198
src/main.rs
@ -1,24 +1,15 @@
|
|||||||
use gtk::builders::ImageBuilder;
|
|
||||||
use gtk::gio::Cancellable;
|
|
||||||
use gtk::prelude::*;
|
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 image::{DynamicImage, ImageBuffer, RgbImage};
|
||||||
use gtk::{Button, Box as GtkBox, Orientation};
|
use std::path::{Path, PathBuf};
|
||||||
use gtk::glib::Propagation;
|
|
||||||
use gtk::gdk_pixbuf::Pixbuf;
|
|
||||||
use std::fs;
|
|
||||||
use std::path::Path;
|
|
||||||
use gtk::gio::File;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Инициализация приложения
|
|
||||||
let app = Application::builder()
|
let app = Application::builder()
|
||||||
.application_id("ru.risdeveau.imageeditor")
|
.application_id("ru.risdeveau.imageeditor")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Запуск приложения
|
|
||||||
app.connect_activate(|app| {
|
app.connect_activate(|app| {
|
||||||
build_ui(app);
|
build_ui(app);
|
||||||
});
|
});
|
||||||
@ -27,7 +18,6 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn build_ui(app: &Application) {
|
fn build_ui(app: &Application) {
|
||||||
// Создание окна
|
|
||||||
let window = ApplicationWindow::builder()
|
let window = ApplicationWindow::builder()
|
||||||
.application(app)
|
.application(app)
|
||||||
.title("Image Editor")
|
.title("Image Editor")
|
||||||
@ -36,141 +26,95 @@ fn build_ui(app: &Application) {
|
|||||||
.build();
|
.build();
|
||||||
window.set_resizable(false);
|
window.set_resizable(false);
|
||||||
|
|
||||||
let selected_file = Rc::new(RefCell::new(None::<File>));
|
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 image_data = Rc::new(RefCell::new(None::<(PathBuf, ImageBuffer<image::Rgb<u8>, Vec<u8>>)>));
|
||||||
// let picture = Picture::new();
|
|
||||||
// picture.set_size_request(400, 400);
|
|
||||||
|
|
||||||
|
// Функция для редактирования изображения
|
||||||
|
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 window = window.clone();
|
||||||
let selected_file = selected_file.clone();
|
let image_data = image_data.clone();
|
||||||
// let picture = picture.clone();
|
let picture = picture.clone();
|
||||||
button.connect_clicked(move |_| {
|
open_button.connect_clicked(move |_| {
|
||||||
// Создание FileDialog
|
|
||||||
let dialog = FileDialog::builder()
|
let dialog = FileDialog::builder()
|
||||||
.title("Select an Image")
|
.title("Select Image")
|
||||||
.accept_label("Open")
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Фильтр для изображений
|
|
||||||
let filter = gtk::FileFilter::new();
|
let filter = gtk::FileFilter::new();
|
||||||
filter.add_mime_type("image/png"); // Разрешить только изображения
|
filter.add_mime_type("image/*");
|
||||||
filter.set_name(Some("Image Files"));
|
|
||||||
dialog.set_default_filter(Some(&filter));
|
dialog.set_default_filter(Some(&filter));
|
||||||
|
|
||||||
// Показ диалога и обработка результата
|
|
||||||
let window = window.clone();
|
let window = window.clone();
|
||||||
let selected_file = selected_file.clone();
|
let image_data = image_data.clone();
|
||||||
// let picture = picture.clone();
|
let picture = picture.clone();
|
||||||
dialog.open(Some(&window), None::<>k::gio::Cancellable>, move |result| {
|
dialog.open(
|
||||||
if let Ok(file) = result {
|
Some(&window),
|
||||||
// Получение выбранного файла
|
None::<>k::gio::Cancellable>,
|
||||||
let path = file.path().unwrap();
|
move |result| {
|
||||||
println!("Selected image: {:?}", path);
|
if let Ok(file) = result {
|
||||||
|
if let Some(path) = file.path() {
|
||||||
// Загрузка изображения (опционально)
|
match image::open(&path) {
|
||||||
if let Ok(pixbuf) = Pixbuf::from_file(&path) {
|
Ok(img) => {
|
||||||
println!("Image loaded successfully: {}x{}", pixbuf.width(), pixbuf.height());
|
let mut rgb_img = img.to_rgb8();
|
||||||
let _ = fs::copy(&path, "/tmp/modified.png");
|
*image_data.borrow_mut() = Some((path.to_path_buf(), rgb_img.clone()));
|
||||||
*selected_file.borrow_mut() = Some(file.clone());
|
|
||||||
// picture.set_pixbuf(Some(&pixbuf));
|
// Сохраняем временную копию для отображения
|
||||||
|
let temp_path = Path::new("/tmp/gtk_temp_img.png");
|
||||||
} else {
|
if rgb_img.save(temp_path).is_ok() {
|
||||||
eprintln!("Failed to load image.");
|
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 image_data = image_data.clone();
|
||||||
let mut value = br_slider.value();
|
let picture = picture.clone();
|
||||||
value = value.round();
|
brightness_slider.connect_value_changed(move |slider| {
|
||||||
br_slider.set_value(value);
|
if let Some((path, ref mut image)) = image_data.borrow_mut().as_mut() {
|
||||||
br_text.set_text(&format!("Brightness: {:+04.0}", value));
|
let value = slider.value() as i8;
|
||||||
edit_image(&mut image, value as i8);
|
|
||||||
|
// Редактируем копию оригинального изображения
|
||||||
// Продолжаем обработку события
|
if let Ok(original) = image::open(path) {
|
||||||
Propagation::Proceed
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
container.append(&open_button);
|
||||||
let container = GtkBox::new(Orientation::Vertical, 8);
|
|
||||||
container.append(&button);
|
|
||||||
container.append(&picture);
|
container.append(&picture);
|
||||||
container.append(&br_container);
|
container.append(&brightness_slider);
|
||||||
|
|
||||||
window.set_child(Some(&container));
|
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();
|
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));
|
|
||||||
// }
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user