///////////////////////////////////////////////////////////////////////////////////////////////////
// imagedialog.cpp
// Пример диалогового окна для отображения и конвертации выборки/полутонового изображения.
// Примечание: в этом диалоговом окне все ресурсы создаются в коде, файл с ресурсами *.ui отсутствует.
//
// Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru
// Университет ИТМО
///////////////////////////////////////////////////////////////////////////////////////////////////
#include <QRgb>
#include <QVBoxLayout>
#include <QFileDialog>
#include <QMessageBox>
#include <fstream>
#include <vector>
#include "imagedialog.h"
using namespace std;
//-------------------------------------------------------------------------------------------------
// конструктор
DQtImageDialog::DQtImageDialog()
{
// заголовок диалогового окна
setWindowTitle("Конвертор выборки");
// инициализация всех указателей на пункты меню
CreateActions();
// создание меню
m_pqMenuBar = new QMenuBar();
CreateMenus();
// инициализация изображения (задаем размер в пикселях и формат)
m_pqImage=new QImage(200,200,QImage::Format_RGB32);
// устанавливаем изображения на элемент управления
m_pqLabel = new QLabel;
m_pqLabel->setPixmap(QPixmap::fromImage(*m_pqImage));
// задаем выравнивание по центру и SizePolycy (чтобы при масштабировании диалога размер меню по вертикали не изменялся)
m_pqLabel->setAlignment(Qt::AlignCenter);
m_pqMenuBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
// создаем вертикальный Layout и добавляем в него меню и элемент уравления с изображением
QVBoxLayout* poVLayout = new QVBoxLayout(this);
poVLayout->addWidget(m_pqMenuBar);
poVLayout->addWidget(m_pqLabel);
}
//-------------------------------------------------------------------------------------------------
DQtImageDialog::~DQtImageDialog()
{
}
//-------------------------------------------------------------------------------------------------
// инициализация всех пунктов меню
void DQtImageDialog::CreateActions()
{
m_pqReadImage = new QAction("Открыть изображениe ...", this);
m_pqReadImage->setToolTip("Загрузить изображение в графическом формате");
connect(m_pqReadImage, SIGNAL(triggered()), this, SLOT(onReadImage()));
m_pqSaveImage = new QAction("Сохранить изображение как ...", this);
m_pqSaveImage->setToolTip("Сохранить изображение в графическом формате");
connect(m_pqSaveImage, SIGNAL(triggered()), this, SLOT(onSaveImage()));
m_pqReadSample = new QAction("Открыть выборку ...", this);
m_pqReadSample->setToolTip("Открыть изображение в текстовом формате");
connect(m_pqReadSample, SIGNAL(triggered()), this, SLOT(onReadSample()));
m_pqSaveSample = new QAction("Сохранить выборку ...", this);
m_pqSaveSample->setToolTip("Сохранить изображение в текстовом формате");
connect(m_pqSaveSample, SIGNAL(triggered()), this, SLOT(onSaveSample()));
m_pqConvertSamples = new QAction("Выборки в изображение ...", this);
m_pqConvertSamples->setToolTip("Прочитать изображения в текстовом формате и сохранить в той же папке в формте *.phg");
connect(m_pqConvertSamples, SIGNAL(triggered()), this, SLOT(onConvertSamples()));
}
//-------------------------------------------------------------------------------------------------
// создание меню
void DQtImageDialog::CreateMenus()
{
QMenu* pqFileMenu = new QMenu("Файл", this);
pqFileMenu->addAction(m_pqReadImage);
pqFileMenu->addAction(m_pqSaveImage);
pqFileMenu->addSeparator();
pqFileMenu->addAction(m_pqReadSample);
pqFileMenu->addAction(m_pqSaveSample);
m_pqMenuBar->addMenu(pqFileMenu);
QMenu* pqConvertMenu = new QMenu("Конвертация", this);
pqConvertMenu->addAction(m_pqConvertSamples);
m_pqMenuBar->addMenu(pqConvertMenu);
} // createMenus
//-------------------------------------------------------------------------------------------------
// обработка пункта меню "Открыть изображение"
void DQtImageDialog::onReadImage()
{
// создаем диалоговое окно для выбора имени файла
QString sFileName = QFileDialog::getOpenFileName(this, "Открыть изображение", "", "Image (*.png *.jpg)");
// загружаем изображение и устанавливаем его на элемент управления
m_pqImage->load(sFileName);
m_pqLabel->setPixmap(QPixmap::fromImage(*m_pqImage));
// подгоняем размер окна под изображение
adjustSize();
}
//-------------------------------------------------------------------------------------------------
// обработка пункта меню "Сохранить изображение"
void DQtImageDialog::onSaveImage()
{
// создаем диалоговое окно для выбора имени файла
QString sFileName = QFileDialog::getSaveFileName(this, "Сохранить изображение", "untitled.png", "Image (*.png *.jpg)");
// сохраняем файл в нужном формате средствами Qt
m_pqImage->save(sFileName);
}
//-------------------------------------------------------------------------------------------------
// обработка пункта меню "Открыть выборку"
void DQtImageDialog::onReadSample()
{
// создаем диалоговое окно для выбора имени файла
QString sFileName = QFileDialog::getOpenFileName(this, "Открыть выборку", "", "Text file (*.txt)");
// читаем выборку и конвертируем ее в изображение
ReadSample(sFileName, *m_pqImage);
// изображение и устанавливаем изображение на элемент управления
m_pqLabel->setPixmap(QPixmap::fromImage(*m_pqImage));
// подгоняем размер окна под изображение
adjustSize();
}
//-------------------------------------------------------------------------------------------------
// обработка пункта меню "Сохранить выборку"
void DQtImageDialog::onSaveSample()
{
// создаем диалоговое окно для выбора имени файла и файл для чтения выборки
QString sFileName = QFileDialog::getSaveFileName(this, "Сохранить выборку", "untitled.txt", "Text file (*.txt)");
ofstream out(sFileName.toStdString());
// заполняем изображение значениями из выборки
// при этом считаем, что в выборке записана интенсивность (значения от 0 до 1)
int w=m_pqImage->width();
int h=m_pqImage->height();
for(int j=0; j<h; ++j)
{
for(int i=0; i<w; ++i)
{
// вычисление интенсивности полутонового изображения (по формуле перевода цветного изображения в grayscale)
QColor qColor(m_pqImage->pixel(i,j));
double dValue=(qColor.red()*0.2989 + qColor.red()*0.5870 + qColor.red()*0.1140)/255.;
out<<dValue;
if(i!=h-1)
out<<" ";
}
if(j!=w-1)
out<<endl;
}
}
//-------------------------------------------------------------------------------------------------
// обработка пункта меню "Конвертация выборки в изображение"
void DQtImageDialog::onConvertSamples()
{
// создаем диалоговое окно для выбора имени файлов
QStringList files = QFileDialog::getOpenFileNames(this, "Выберите файлы с выборками для конвертации",
"", "Text file (*.txt)");
// для каждого из выборанных файлов:
QStringList::Iterator it;
for(it=files.begin(); it != files.end(); ++it)
{
// читаем выборку и конвертируем ее в изображение
QImage qTempImage;
ReadSample(*it, qTempImage);
// имя файл с изображением делаем точно такое же как с выборкой, но с другим расширением
QString sImageFile=(*it).left((*it).indexOf(".")+1);
sImageFile+="png";
// сохраняем изоражение
qTempImage.save(sImageFile);
}
}
//-------------------------------------------------------------------------------------------------
// чтение выборки из файла SampleFile (размерности по X и Y считаем одинаковыми) и создание изображения rImage_p
void DQtImageDialog::ReadSample(const QString& SampleFile, QImage& rImage_p)
{
// чтение конейнера из файла
ifstream in(SampleFile.toAscii());
std::vector<double> data;
double value;
// цикл будет выполняться до тех пор, пока не встретиться конец файла
while(!in.eof())
{
in>>value; // читаем число из файла
data.push_back(value);// записываем прочитанное число в конец контейнера
}
// проверка размерности прочитанного контейнера (выборка должна быть квадратной)
int iSize=int(std::sqrt(double(data.size())));
if(iSize*iSize!=data.size())
{
QString sText="Неправильный размер файла: " + SampleFile + " невозможно создать квадратную выборку.";
QMessageBox::critical(this, "Ошибка при чтении файла",
"Неправильный размер файла: невозможно создать квадратную выборку.");
return;
}
// создаем новое изображение такого же размера, что и выборка
rImage_p=QImage(iSize, iSize, QImage::Format_RGB32);
// заполняем изображения значениями из выборки
// при этом считаем, что в выборке записана интенсивность (значения от 0 до 1)
for(int i=0; i<iSize; ++i)
{
for(int j=0; j<iSize; ++j)
{
int iValue=data[j*iSize+i]*255;
rImage_p.setPixel(i, j, qRgb(iValue, iValue, iValue));
}
}
}
//-------------------------------------------------------------------------------------------------