From 96097b614d6af9951eb77de182d47344308d6a40 Mon Sep 17 00:00:00 2001 From: Vargha Csongor Date: Mon, 26 Jun 2023 22:19:05 +0200 Subject: [PATCH] Use qt as a graphical display --- src/main.cpp | 203 +++++++++++++++++++++++++-------------------------- 1 file changed, 100 insertions(+), 103 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 4c56b3a..2933676 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,24 +15,33 @@ Description: - is the number of iterations for TV denoising (optional, default: 10). */ #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include "tv_denoising.hpp" // Global variables for GUI elements -GtkLabel* originalImageLabel; -GtkLabel* resultImageLabel; -GtkEntry* inputImagePathEntry; -GtkEntry* outputImagePathEntry; -GtkScale* lambdaScale; -GtkScale* iterationsScale; +QLabel *originalImageLabel; +QLabel *resultImageLabel; +QLineEdit *inputImagePathEdit; +QLineEdit *outputImagePathEdit; +QSlider *lambdaSlider; +QSlider *iterationsSlider; -static void updateDenoisedImage(GtkWidget* widget, gpointer data) +void updateDenoisedImage() { - std::string inputImagePath = gtk_entry_get_text(inputImagePathEntry); - std::string outputImagePath = gtk_entry_get_text(outputImagePathEntry); - float lambda = gtk_range_get_value(GTK_RANGE(lambdaScale)) / 100.0; - int iterations = gtk_range_get_value(GTK_RANGE(iterationsScale)); + std::string inputImagePath = inputImagePathEdit->text().toStdString(); + std::string outputImagePath = outputImagePathEdit->text().toStdString(); + float lambda = lambdaSlider->value() / 100.0; + int iterations = iterationsSlider->value(); // Read the input image cv::Mat image = cv::imread(inputImagePath, cv::IMREAD_GRAYSCALE); @@ -40,10 +49,7 @@ static void updateDenoisedImage(GtkWidget* widget, gpointer data) // Check if the image was successfully loaded if (image.empty()) { - GtkWidget* dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, - "Failed to read the input image."); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); + QMessageBox::critical(nullptr, "Error", "Failed to read the input image."); return; } @@ -51,126 +57,117 @@ static void updateDenoisedImage(GtkWidget* widget, gpointer data) TVDenoising(image, lambda, iterations); // Display the denoised image - GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(image.data, GDK_COLORSPACE_RGB, FALSE, 8, image.cols, image.rows, - image.step, NULL, NULL); - gtk_image_set_from_pixbuf(GTK_IMAGE(resultImageLabel), pixbuf); - g_object_unref(pixbuf); + QImage resultImage(image.data, image.cols, image.rows, QImage::Format_Grayscale8); + resultImageLabel->setPixmap(QPixmap::fromImage(resultImage)); // Save the denoised image cv::imwrite(outputImagePath, image); } -static void openInputImage(GtkWidget* widget, gpointer data) +void openInputImage() { - GtkWidget* dialog = gtk_file_chooser_dialog_new("Select Input Image", GTK_WINDOW(data), GTK_FILE_CHOOSER_ACTION_OPEN, - "Cancel", GTK_RESPONSE_CANCEL, "Open", GTK_RESPONSE_ACCEPT, NULL); - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) - { - char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - gtk_entry_set_text(inputImagePathEntry, filename); - g_free(filename); - } - gtk_widget_destroy(dialog); + QString filePath = QFileDialog::getOpenFileName(nullptr, "Select Input Image"); + if (!filePath.isEmpty()) + inputImagePathEdit->setText(filePath); } -static void openOutputImage(GtkWidget* widget, gpointer data) +void openOutputImage() { - GtkWidget* dialog = gtk_file_chooser_dialog_new("Select Output Image", GTK_WINDOW(data), GTK_FILE_CHOOSER_ACTION_SAVE, - "Cancel", GTK_RESPONSE_CANCEL, "Save", GTK_RESPONSE_ACCEPT, NULL); - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) - { - char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - gtk_entry_set_text(outputImagePathEntry, filename); - g_free(filename); - } - gtk_widget_destroy(dialog); + QString filePath = QFileDialog::getSaveFileName(nullptr, "Select Output Image"); + if (!filePath.isEmpty()) + outputImagePathEdit->setText(filePath); } -int main(int argc, char** argv) +int main(int argc, char **argv) { - // Initialize GTK - gtk_init(&argc, &argv); + QApplication app(argc, argv); // Create the main window - GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(window), "TV Image Denoising"); - gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); - g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); + QWidget window; + window.setWindowTitle("TV Image Denoising"); + window.resize(800, 600); - // Create the main vertical box layout - GtkWidget* vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); - gtk_container_add(GTK_CONTAINER(window), vbox); + // Create the layout + QVBoxLayout *layout = new QVBoxLayout(&window); // Create the original image label - originalImageLabel = GTK_LABEL(gtk_label_new("Original Image")); - gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(originalImageLabel), FALSE, FALSE, 0); + originalImageLabel = new QLabel("Original Image"); + layout->addWidget(originalImageLabel); // Create the result image label - resultImageLabel = GTK_LABEL(gtk_label_new("Result Image")); - gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(resultImageLabel), FALSE, FALSE, 0); + resultImageLabel = new QLabel("Result Image"); + layout->addWidget(resultImageLabel); // Create the input image path input field - GtkWidget* inputImageHBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5); - gtk_box_pack_start(GTK_BOX(vbox), inputImageHBox, FALSE, FALSE, 0); - - GtkWidget* inputImageLabel = gtk_label_new("Input Image:"); - gtk_box_pack_start(GTK_BOX(inputImageHBox), inputImageLabel, FALSE, FALSE, 0); - - inputImagePathEntry = GTK_ENTRY(gtk_entry_new()); - gtk_box_pack_start(GTK_BOX(inputImageHBox), GTK_WIDGET(inputImagePathEntry), TRUE, TRUE, 0); - - GtkWidget* inputBrowseButton = gtk_button_new_with_label("Browse"); - g_signal_connect(inputBrowseButton, "clicked", G_CALLBACK(openInputImage), window); - gtk_box_pack_start(GTK_BOX(inputImageHBox), inputBrowseButton, FALSE, FALSE, 0); + QHBoxLayout *inputLayout = new QHBoxLayout; + QLabel *inputLabel = new QLabel("Input Image:"); + inputImagePathEdit = new QLineEdit; + QPushButton *inputBrowseButton = new QPushButton("Browse"); + QObject::connect(inputBrowseButton, &QPushButton::clicked, openInputImage); + inputLayout->addWidget(inputLabel); + inputLayout->addWidget(inputImagePathEdit); + inputLayout->addWidget(inputBrowseButton); + layout->addLayout(inputLayout); // Create the output image path input field - GtkWidget* outputImageHBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5); - gtk_box_pack_start(GTK_BOX(vbox), outputImageHBox, FALSE, FALSE, 0); + QHBoxLayout *outputLayout = new QHBoxLayout; + QLabel *outputLabel = new QLabel("Output Image:"); + outputImagePathEdit = new QLineEdit; + QPushButton *outputBrowseButton = new QPushButton("Browse"); + QObject::connect(outputBrowseButton, &QPushButton::clicked, openOutputImage); + outputLayout->addWidget(outputLabel); + outputLayout->addWidget(outputImagePathEdit); + outputLayout->addWidget(outputBrowseButton); + layout->addLayout(outputLayout); - GtkWidget* outputImageLabel = gtk_label_new("Output Image:"); - gtk_box_pack_start(GTK_BOX(outputImageHBox), outputImageLabel, FALSE, FALSE, 0); + // Create the lambda slider + QLabel *lambdaLabel = new QLabel("Lambda:"); + QSlider *lambdaSlider = new QSlider(Qt::Horizontal); + lambdaSlider->setObjectName("LambdaSlider"); // Set object name for styling + lambdaSlider->setMinimum(0); + lambdaSlider->setMaximum(100); - outputImagePathEntry = GTK_ENTRY(gtk_entry_new()); - gtk_box_pack_start(GTK_BOX(outputImageHBox), GTK_WIDGET(outputImagePathEntry), TRUE, TRUE, 0); + // Create the iterations slider + QLabel *iterationsLabel = new QLabel("Iterations:"); + QSlider *iterationsSlider = new QSlider(Qt::Horizontal); + iterationsSlider->setObjectName("IterationsSlider"); // Set object name for styling + iterationsSlider->setMinimum(1); + iterationsSlider->setMaximum(100); - GtkWidget* outputBrowseButton = gtk_button_new_with_label("Browse"); - g_signal_connect(outputBrowseButton, "clicked", G_CALLBACK(openOutputImage), window); - gtk_box_pack_start(GTK_BOX(outputImageHBox), outputBrowseButton, FALSE, FALSE, 0); + // Create labels to display slider values + QLabel *lambdaValueLabel = new QLabel(); + QLabel *iterationsValueLabel = new QLabel(); - // Create the lambda scale - GtkWidget* lambdaHBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5); - gtk_box_pack_start(GTK_BOX(vbox), lambdaHBox, FALSE, FALSE, 0); + // Set stylesheet for dark design + QString styleSheet = "QLabel { color: white; }" // Set label text color to white + "QSlider::groove:horizontal { background-color: #555555; height: 6px; }" // Set groove color and height + "QSlider::handle:horizontal { background-color: #ffffff; width: 10px; margin: -6px 0; }"; // Set handle color and size - GtkWidget* lambdaLabel = gtk_label_new("Lambda:"); - gtk_box_pack_start(GTK_BOX(lambdaHBox), lambdaLabel, FALSE, FALSE, 0); + lambdaSlider->setStyleSheet(styleSheet); + iterationsSlider->setStyleSheet(styleSheet); - lambdaScale = GTK_SCALE(gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 100, 1)); - gtk_scale_set_value_pos(lambdaScale, GTK_POS_RIGHT); - gtk_scale_set_digits(lambdaScale, 2); - gtk_box_pack_start(GTK_BOX(lambdaHBox), GTK_WIDGET(lambdaScale), TRUE, TRUE, 0); + // Create layout and add widgets + layout->addWidget(lambdaLabel); + layout->addWidget(lambdaSlider); + layout->addWidget(lambdaValueLabel); + layout->addWidget(iterationsLabel); + layout->addWidget(iterationsSlider); + layout->addWidget(iterationsValueLabel); - // Create the iterations scale - GtkWidget* iterationsHBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5); - gtk_box_pack_start(GTK_BOX(vbox), iterationsHBox, FALSE, FALSE, 0); + // Connect slider value changes to label updates + QObject::connect(lambdaSlider, &QSlider::valueChanged, [=](int value) + { lambdaValueLabel->setText(QString::number(value)); }); - GtkWidget* iterationsLabel = gtk_label_new("Iterations:"); - gtk_box_pack_start(GTK_BOX(iterationsHBox), iterationsLabel, FALSE, FALSE, 0); - - iterationsScale = GTK_SCALE(gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 1, 100, 1)); - gtk_scale_set_value_pos(iterationsScale, GTK_POS_RIGHT); - gtk_scale_set_digits(iterationsScale, 0); - gtk_box_pack_start(GTK_BOX(iterationsHBox), GTK_WIDGET(iterationsScale), TRUE, TRUE, 0); + QObject::connect(iterationsSlider, &QSlider::valueChanged, [=](int value) + { iterationsValueLabel->setText(QString::number(value)); }); // Create the denoise button - GtkWidget* denoiseButton = gtk_button_new_with_label("Denoise"); - g_signal_connect(denoiseButton, "clicked", G_CALLBACK(updateDenoisedImage), NULL); - gtk_box_pack_start(GTK_BOX(vbox), denoiseButton, FALSE, FALSE, 0); + QPushButton *denoiseButton = new QPushButton("Denoise"); + QObject::connect(denoiseButton, &QPushButton::clicked, updateDenoisedImage); + layout->addWidget(denoiseButton); - // Show all widgets - gtk_widget_show_all(window); + // Show the main window + window.show(); - // Run the GTK main loop - gtk_main(); - - return 0; + return app.exec(); } \ No newline at end of file