Skip to content

Commit

Permalink
First Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Timforce committed Feb 10, 2019
0 parents commit 18d5b88
Show file tree
Hide file tree
Showing 8 changed files with 589 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
*.o
*.jpg
*.png
*.bmp
*.user
build/
ui_interface.h
moc_interface.cpp
Basic_image_processing
40 changes: 40 additions & 0 deletions Basic_image_processing.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#-------------------------------------------------
#
# Project created by QtCreator 2019-02-08T15:58:23
#
#-------------------------------------------------

QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = Basic_image_processing
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

CONFIG += c++11

SOURCES += \
main.cpp \
interface.cpp

HEADERS += \
interface.h

FORMS += \
interface.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
41 changes: 41 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
### Specify your qt install location here
### Ex. /opt/qt/5.12.0/gcc_64
QT_DIR = /opt/qt/5.12.1/gcc_64

CXX = g++
UIC = $(QT_DIR)/bin/uic
MOC = $(QT_DIR)/bin/moc
BUILD_DIR = ./build/
DEFINES = -DQT_DEPRECATED_WARNINGS -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB
CXXFLAGS = -pipe -O2 -std=gnu++11 -Wall -W -D_REENTRANT -fPIC $(DEFINES)
INCPATH = -I. -I$(QT_DIR)/include -I$(QT_DIR)/include/QtWidgets -I$(QT_DIR)/include/QtGui -I$(QT_DIR)/include/QtCore
LFLAGS = -Wl,-O1 -Wl,-rpath,$(QT_DIR)/lib
LIBS = -L$(QT_DIR)/lib -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread
SOURCES = main.cpp interface.cpp moc_interface.cpp
OBJECTS = $(patsubst %.cpp, %.o, $(SOURCES))
EXEOJBS = $(addprefix $(BUILD_DIR), $(OBJECTS))
UIHEADER = ui_interface.h
MOCCXX = moc_interface.cpp
TARGET = Basic_image_processing

all: build_dir $(TARGET)

$(TARGET): $(UIHEADER) $(EXEOJBS)
$(CXX) $(LFLAGS) -o $(TARGET) $(EXEOJBS) $(LIBS)

$(BUILD_DIR)%.o: %.cpp
$(CXX) $(CXXFLAGS) $(INCPATH) -c $< -o $@

$(MOCCXX): interface.h
$(MOC) $(DEFINES) $(INCPATH) interface.h -o $@

$(UIHEADER): interface.ui
$(UIC) interface.ui -o $@

build_dir:
mkdir -p $(BUILD_DIR)

clean:
rm -rf $(BUILD_DIR) $(TARGET) $(MOCCXX) $(UIHEADER)

.PHONY: clean
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Basic Image Processing - Qt
This is a basic linux GUI written with [Qt][qt-link] that do some basic image processing task. \
At current state it contains following functionalities:
1. Loading and saving .jpg .png .bmp image files.
2. Image inversion.
3. Histogram equalization.
4. Gamma correction based on user input gamma value.

[qt-link]: https://www.qt.io/

### Requirements:
GNU-g++, make, Qt community version>=4

### Program compile:
Specify the Qt installation location in Makefile and type ```make``` under the project directory.

### Downloads
Check the [release][release-link] page

[release-link]: https://github.com/timforce/Basic_Image_Processing-Qt/releases
196 changes: 196 additions & 0 deletions interface.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
#include "interface.h"
#include "ui_interface.h"
#include <math.h>

Interface::Interface(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Interface)
{
ui->setupUi(this);
ui->status->setText("Welcome!");
this->setFixedSize(QSize(850, 550));
}

Interface::~Interface()
{
delete ui;
}

void Interface::on_actionOpen_triggered()
{
QString filename = QFileDialog::getOpenFileName(this, "Open Image File", nullptr,
"Images (*.jpg *.jpeg *.JPG *.png *.PNG *.bmp *.BMP );;"
"JPG (*.jpg *.jpeg *.JPG);;"
"PNG (*.png *.PNG);;"
"BMP (*.bmp *.BMP)");
if(!original_img.load(filename))
{
if(static_cast<bool>(proc_stat & img_loaded))
return;
ui->status->setText("Didn't load the image!");
proc_stat = 0;
return;
}
else {
processed_img = original_img.copy();
ui->orig_frame->setPixmap(original_img.scaled(ui->orig_frame->size(), Qt::KeepAspectRatio));
ui->proc_frame->setPixmap(processed_img.scaled(ui->proc_frame->size(), Qt::KeepAspectRatio));
ui->status->setText("Loaded image: " + filename);
proc_stat = 1;
}
}

void Interface::on_imgInv_clicked()
{
if (check_status(inv_done))
return;
QImage proc = original_img.copy().toImage();
uchar *bit = proc.bits();
int h = proc.height();
int w = proc.width();
int i, j, dest_index;
for(i = 0; i < w; ++i){
for(j = 0; j < h; ++j){
dest_index = 4*i + 4*w*j;
bit[dest_index + 0 ] = ~(bit[dest_index + 0]);
bit[dest_index + 1 ] = ~(bit[dest_index + 1]);
bit[dest_index + 2 ] = ~(bit[dest_index + 2]);
}
}
processed_img = processed_img.fromImage(proc);
ui->proc_frame->setPixmap(processed_img.scaled(ui->proc_frame->size(), Qt::KeepAspectRatio));
ui->status->setText("Image inversion done!");
proc_stat |= inv_done;
}

void Interface::on_imgHistEql_clicked()
{
if (check_status(hist_done))
return;
QImage proc = original_img.copy().toImage();
uchar *bit = proc.bits();
int h = proc.height();
int w = proc.width();
int pixels = w*h;
int i, j, dest_index;
float *crfR = new float[256] ();
float *crfG = new float[256] ();
float *crfB = new float[256] ();
for(i = 0; i < w; ++i){
for(j = 0; j < h; ++j){
dest_index = 4*i + 4*w*j;
crfR[static_cast<int>(bit[dest_index + 0])]++;
crfG[static_cast<int>(bit[dest_index + 1])]++;
crfB[static_cast<int>(bit[dest_index + 2])]++;
}
}
for(i = 1; i <= 255; i++)
{
crfR[i] += crfR[i-1];
crfG[i] += crfG[i-1];
crfB[i] += crfB[i-1];
}
for(i = 0; i < w; ++i){
for(j = 0; j < h; ++j){
dest_index = 4*i + 4*w*j;
bit[dest_index+0] = static_cast<uchar>(
static_cast<int>((crfR[static_cast<int>(bit[dest_index+0])] / pixels * 255)));
bit[dest_index+1] = static_cast<uchar>(
static_cast<int>((crfG[static_cast<int>(bit[dest_index+1])] / pixels * 255)));
bit[dest_index+2] = static_cast<uchar>(
static_cast<int>((crfB[static_cast<int>(bit[dest_index+2])] / pixels * 255)));
}
}
delete[] crfR;
delete[] crfG;
delete[] crfB;
processed_img = processed_img.fromImage(proc);
ui->proc_frame->setPixmap(processed_img.scaled(ui->proc_frame->size(), Qt::KeepAspectRatio));
ui->status->setText("Histogram equalization done!");
proc_stat |= hist_done;
}

void Interface::on_imgGammaCor_clicked()
{
if(check_status())
return;
QRegExp reg("[-+]?[0-9.]*");
QString gamma_in = ui->gamma_input->text();
double gamma_val;
if(reg.exactMatch(gamma_in))
gamma_val = gamma_in.toDouble();
else{
ui->status->setText("Please set a valid value for gamma");
return;
}
QImage proc = original_img.copy().toImage();
uchar *bit = proc.bits();
int h = proc.height();
int w = proc.width();
int i, j, dest_index;
for(i = 0; i < w; ++i){
for(j = 0; j < h; ++j){
dest_index = 4*i + 4*w*j;
bit[dest_index+0] = static_cast<uchar>(
static_cast<int>(255 * pow(static_cast<double>(bit[dest_index+0]) / 255, gamma_val)));
bit[dest_index+1] = static_cast<uchar>(
static_cast<int>(255 * pow(static_cast<double>(bit[dest_index+1]) / 255, gamma_val)));
bit[dest_index+2] = static_cast<uchar>(
static_cast<int>(255 * pow(static_cast<double>(bit[dest_index+2]) / 255, gamma_val)));
}
}
processed_img = processed_img.fromImage(proc);
ui->proc_frame->setPixmap(processed_img.scaled(ui->proc_frame->size(), Qt::KeepAspectRatio));
ui->status->setText("Gamma correction done! Input gamma value: " + QString::number(gamma_val));
proc_stat |= gamma_done;
}


void Interface::on_imgReset_clicked()
{
if(check_status())
return;
processed_img = original_img.copy();
ui->proc_frame->setPixmap(processed_img.scaled(ui->proc_frame->size(), Qt::KeepAspectRatio));
ui->status->setText("Image reset to default state.");
}

void Interface::on_actionSave_as_triggered()
{
if(check_status())
return;
QString saveFileName = QFileDialog::getSaveFileName(this, "Save processed image as..", "output.jpg",
"jpg, png, bmp (*.jpg, *.png *.bmp)");
QString ext = QFileInfo(saveFileName).suffix();
QPixmap pixmap;
if(ext=="jpg" || ext=="png" || ext=="bmp")
{
QFile outfile(saveFileName);
if (!outfile.open(QFile::WriteOnly)){
QMessageBox::warning(this, "Warning", "Cannot save file: " + outfile.errorString());
return;
}
processed_img.save(&outfile);
ui->status->setText("Saved processed image to: " + saveFileName);
}
}

bool Interface::check_status(void)
{
if(!static_cast<bool>(proc_stat & img_loaded))
{
QMessageBox::information(this, "Info", "Please load an image file first");
return true;
}
proc_stat = 1;
return false;
}

bool Interface::check_status(const uchar proc)
{
if(static_cast<bool>(proc_stat & proc))
return true;
if(check_status())
return true;
return false;
}
50 changes: 50 additions & 0 deletions interface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#ifndef INTERFACE_H
#define INTERFACE_H

#include <QMainWindow>
#include <QFile>
#include <QFileDialog>
#include <QBuffer>
#include <QImage>
#include <QPixmap>
#include <QMessageBox>

namespace Ui {
class Interface;
}

class Interface : public QMainWindow
{
Q_OBJECT

public:
explicit Interface(QWidget *parent = nullptr);
~Interface();

private slots:
void on_actionOpen_triggered();

void on_imgInv_clicked();

void on_imgHistEql_clicked();

void on_imgGammaCor_clicked();

void on_actionSave_as_triggered();

void on_imgReset_clicked();

private:
Ui::Interface *ui;
QPixmap original_img;
QPixmap processed_img;
uchar proc_stat = 0;
const uchar img_loaded = 1 << 0;
const uchar hist_done = 1 << 1;
const uchar gamma_done = 1 << 2;
const uchar inv_done = 1 << 3;
bool check_status(void);
bool check_status(const uchar);
};

#endif // INTERFACE_H
Loading

0 comments on commit 18d5b88

Please sign in to comment.