mainwindow.cpp 6.25 KB
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <iostream>
#include <QFileDialog>

#include "stim/visualization/colormap.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);		
	s = new SpectrumWindow(this);
}

void MainWindow::loadImage(QString fileName){

	std::string file = fileName.toUtf8().constData();
	//load a dummy hyperspectral image for debugging
	if(!hsi.open(file, file + ".hdr")){
		std::cout<<"ERROR opening file "<<file<<std::endl;
		exit(1);
	}

	//initialize the size of the main window
	//resize(hsi.header.samples+2, hsi.header.lines + ui->menuBar->size().height());

	//fill the x axis with wavelength numbers from the hsi
	x = QVector<double>::fromStdVector(hsi.header.wavelength);

	//load the middle band as the default
	load_band(x.size()/2);

	//set the pick position to the center of the image
	px = py = 0.5;

	//create a graphics scene to store the image and any drawn UI elements
	scene = new QGraphicsScene(this);
	//send the scene to the QGraphicsView object for display
    ui->graphicsView->setScene(scene);

	//create and show the spectrum window
	load_spectrum();
	s->initPlot(x.first(), x.last(), 0, 1, hsi.header.wavelength_units.c_str(), "Absorbance");
	s->show();

	//draw everything
	draw_viewport();
}


/// Update the image viewing widget so that it always fills the main window
void MainWindow::resizeEvent(QResizeEvent* event){

	//get the current window size
	QSize winsize = event->size();

	//get the current position of the QGraphicsView object
	QPoint imagepos = ui->graphicsView->pos();

	//calculate the maximum allowable image width and height given the user's selected window size
	unsigned int maxwidth = winsize.width() - imagepos.x();
	unsigned int maxheight = winsize.height() - imagepos.y();

	//get the size of the image
	QSize imagesize = image.size();

	//calculate the aspect ratio
	//float aspect = imagesize.width() / imagesize.height();
	float width_ratio = imagesize.width() / maxwidth;
	float height_ratio = imagesize.height() / maxheight;

	//if the width requires the largest scaling
	if(width_ratio >= height_ratio)
		main_image = image.scaledToWidth(maxwidth);
	else
		main_image = image.scaledToHeight(maxheight);
		
	//update the size of the QGraphicsView object
	//	the QGraphicsView will be either the size of the image or
	//	the size of the window (whichever is smaller)
	QSize viewsize = QSize( main_image.width()+2, main_image.height()+2 );
	ui->graphicsView->setFixedSize(viewsize.width(), viewsize.height());

	draw_viewport();
}

/// Update everything associated with when the image is clicked
void MainWindow::mousePressEvent(QMouseEvent * event){
	
	//get the window position of the click
	QPoint winp = event->pos();

	//get the position of the QGraphicsView object (upper left corner of the image)
	QPoint viewp = ui->graphicsView->pos();

	//get the size of the menu bar
	int menu_height = ui->menuBar->size().height();

	//calculate the position of the click in the graphics view
	QPoint imagep = winp - viewp - QPoint(0, menu_height);

	//get the size of the graphics view object
	QSize viewsize = ui->graphicsView->size();

	//calculate the position of the point in the image space [0, 1]
	px = (float)imagep.x() / (float) viewsize.width();
	py = (float)imagep.y() / (float) viewsize.height();

	//load the spectrum associated with p
	load_spectrum();
	draw_viewport();	
}

void MainWindow::mousePressSpectrum(double px, double py){

	//calculate the band to be loaded
	//	this will be the closest band to x
	unsigned int c = 0;
	double diff = abs(px - x[0]);
	for(unsigned int i=1; i<x.size(); i++){
		if( abs(px - x[i]) < diff ){
			c = i;
			diff = px - x[i];
		}
	}

	//load the correct band
	load_band(c);

	//re-draw the viewport to display it
	draw_viewport();
}

void MainWindow::load_band(unsigned int i){

	//calculate the number of values in the band image
	unsigned int N = hsi.header.samples * hsi.header.lines;

	//allocate space to store the band data
	float* band = (float*) malloc(N * sizeof(float));

	//allocate space to store the image (colormap) data
	unsigned char* buffer = (unsigned char*) malloc(N * 3 * sizeof(unsigned char));

	//load the band data from the HSI
	hsi.band_index(band, i);

	//convert the band data to an image
	stim::cpu2cpu<float>(band, buffer, N, stim::cmBrewer);

	//store the color data in the image member variable
	image = QPixmap::fromImage(
		QImage(
			buffer,
			hsi.header.samples,
			hsi.header.lines,
			QImage::Format_RGB888
			)
		);

	//get the main image size
	QSize main_size = main_image.size();

	//scale the band image
	main_image = image.scaledToHeight(main_size.height());

	//free the buffer and band memory
	free(buffer);
	free(band);
}

void MainWindow::draw_viewport(){

	scene->clear();

	//add the image to the scene
    scene->addPixmap(main_image);

	//I'm not sure what this does...
    scene->setSceneRect(main_image.rect());

	//draw the overlay indicating the selected pixel
	draw_overlay();

	//draw the spectrum
	draw_spectrum();
}

//draws an overlay over the image showing details that include the selected pixel
void MainWindow::draw_overlay(){

	//get the size of the QGraphicsView object
	QSize image_size = ui->graphicsView->size();

	//calculate the pixel position (index) into the main image
	QPoint pi = QPoint(px * image_size.width(), py * image_size.height());

	scene->addLine(0, pi.y(), image_size.width(), pi.y());
	scene->addLine(pi.x(), 0, pi.x(), image_size.height());
}

/// Loads the spectrum from the picked point of the HSI and stores it in the member variable y
void MainWindow::load_spectrum(){

	//allocate the appropriate amount of memory for the spectrum
	float* temp_y = (float*) malloc(x.size() * sizeof(float));

	//pixel position in the band image
	QPoint pi = QPoint(px * image.width(), py * image.height());

	//load the spectrum from the HSI
	hsi.spectrum(temp_y, pi.x(), pi.y());

	//clear the previous spectrum
	y.clear();

	//copy the values into the member variable y
	for(int i = 0; i < x.size(); i++)
		y.push_back(temp_y[i]);
}

void MainWindow::draw_spectrum(){
	
	//plot the saved spectrum
	s->plotSpectrum(x, y);
}

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

void MainWindow::on_actionLoad_triggered()
{
    QString fileName = QFileDialog::getOpenFileName(0, "Open ENVI File");
	loadImage(fileName);
}