Вернуться наверх
aco.ifmo.ru photonic
вернуться в оглавление предыдущая глава предыдущий параграф следующий параграф следующая глава


Пример 3.
Отображение и конвертация выборки/полутонового изображения

3.2. Реализация функций в диалоге (файл imagedialog.cpp)

///////////////////////////////////////////////////////////////////////////////////////////////////
// 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));
        }
    }   
}
//-------------------------------------------------------------------------------------------------