Compare commits
No commits in common. "c1ccad622952e8ca38dcac9452cb1373b753ed5f" and "662e8ee95ebe197693e971dd6718176041a1cae1" have entirely different histories.
c1ccad6229
...
662e8ee95e
2102
Cargo.lock
generated
2102
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -4,8 +4,5 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
gtk = { package = "gtk4", version = "0.9.6", features=["v4_10"] }
|
show-image = "0.14.0"
|
||||||
image = "0.24"
|
image2 = "1.9.2"
|
||||||
# gtk4 = "0.9.6"
|
|
||||||
# show-image = "0.14.0"
|
|
||||||
# image2 = "1.9.2"
|
|
||||||
|
@ -11,13 +11,10 @@ with pkgs; mkShell rec {
|
|||||||
libxkbcommon
|
libxkbcommon
|
||||||
egl-wayland
|
egl-wayland
|
||||||
vulkan-loader
|
vulkan-loader
|
||||||
gtk4
|
|
||||||
gsettings-desktop-schemas
|
|
||||||
];
|
];
|
||||||
|
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${lib.makeLibraryPath (buildInputs) }
|
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${lib.makeLibraryPath (buildInputs) }
|
||||||
export XDG_DATA_DIRS=${pkgs.gtk4}/share/gsettings-schemas/${pkgs.gtk4.name}:$XDG_DATA_DIRS
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
WINIT_UNIX_BACKEND="wayland";
|
WINIT_UNIX_BACKEND="wayland";
|
||||||
|
225
src/main.rs
225
src/main.rs
@ -1,176 +1,57 @@
|
|||||||
use gtk::builders::ImageBuilder;
|
use image2::*;
|
||||||
use gtk::gio::Cancellable;
|
use show_image::{ImageView, ImageInfo, event, create_window};
|
||||||
use gtk::prelude::*;
|
|
||||||
use gtk::{Application, ApplicationWindow, Picture, Scale, Label, FileDialog};
|
|
||||||
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::rc::Rc;
|
|
||||||
use std::cell::RefCell;
|
|
||||||
|
|
||||||
fn main() {
|
#[show_image::main]
|
||||||
// Инициализация приложения
|
fn main() -> Result<(), Error> {
|
||||||
let app = Application::builder()
|
println!("Hello, world!");
|
||||||
.application_id("ru.risdeveau.imageeditor")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// Запуск приложения
|
// Open the image
|
||||||
app.connect_activate(|app| {
|
// let image = Image::<u8, Rgb>::open("/home/sweetbread/nix/screenshot.png")?;
|
||||||
build_ui(app);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.run();
|
// // Show the image
|
||||||
|
// let img = ImageView::new(ImageInfo::rgb8(image.width().try_into().unwrap(), image.height().try_into().unwrap()), image.buffer());
|
||||||
|
// let win = create_window("image", Default::default()).unwrap();
|
||||||
|
// win.set_image("image-001", img).unwrap();
|
||||||
|
|
||||||
|
// // Wait until Escape will be pressed
|
||||||
|
// for event in win.event_channel().unwrap() {
|
||||||
|
// if let event::WindowEvent::KeyboardInput(event) = event {
|
||||||
|
// if event.input.key_code == Some(event::VirtualKeyCode::Escape) && event.input.state.is_pressed() {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Create new imahe
|
||||||
|
// let new_image = image.new_like();
|
||||||
|
// let mut new_image = new_image.with_color::<Hsv>();
|
||||||
|
|
||||||
|
// for x in 0..image.width() {
|
||||||
|
// for y in 0..image.height() {
|
||||||
|
// let p = image.get_pixel(Point::new(x, y));
|
||||||
|
// let mut hsv_p = Pixel::<Hsv>::new();
|
||||||
|
|
||||||
|
// for i in 0..3 {
|
||||||
|
// hsv_p[i] = p[i];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// new_image.set_pixel(Point::new(x, y), &hsv_p);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// new_image.save("result.png").expect("Failed to save resulting image");
|
||||||
|
|
||||||
|
let mut image = Image::<u8, Hsv>::new(Size::new(100, 100));
|
||||||
|
for x in 0..100 {
|
||||||
|
for y in 0..100 {
|
||||||
|
let mut p = Pixel::<Hsv>::new();
|
||||||
|
p[1] = 1.;
|
||||||
|
p[2] = 1.;
|
||||||
|
image.set_pixel(Point::new(x, y), &p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
image.save("result.jpg")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_ui(app: &Application) {
|
|
||||||
// Создание окна
|
|
||||||
let window = ApplicationWindow::builder()
|
|
||||||
.application(app)
|
|
||||||
.title("Image Editor")
|
|
||||||
.default_width(800)
|
|
||||||
.default_height(600)
|
|
||||||
.build();
|
|
||||||
window.set_resizable(false);
|
|
||||||
|
|
||||||
let selected_file = Rc::new(RefCell::new(None::<File>));
|
|
||||||
|
|
||||||
// Создание кнопки для открытия диалога выбора файла
|
|
||||||
let button = Button::with_label("Select Image");
|
|
||||||
// let picture = Picture::new();
|
|
||||||
// picture.set_size_request(400, 400);
|
|
||||||
|
|
||||||
{
|
|
||||||
let window = window.clone();
|
|
||||||
let selected_file = selected_file.clone();
|
|
||||||
// let picture = picture.clone();
|
|
||||||
button.connect_clicked(move |_| {
|
|
||||||
// Создание FileDialog
|
|
||||||
let dialog = FileDialog::builder()
|
|
||||||
.title("Select an Image")
|
|
||||||
.accept_label("Open")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// Фильтр для изображений
|
|
||||||
let filter = gtk::FileFilter::new();
|
|
||||||
filter.add_mime_type("image/png"); // Разрешить только изображения
|
|
||||||
filter.set_name(Some("Image Files"));
|
|
||||||
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.");
|
|
||||||
}
|
|
||||||
} 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 container = GtkBox::new(Orientation::Vertical, 8);
|
|
||||||
container.append(&button);
|
|
||||||
container.append(&picture);
|
|
||||||
container.append(&br_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();
|
|
||||||
}
|
|
||||||
|
|
||||||
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