Größe einer Pixmap variabel bestimmen

Alles rund um die Programmierung mit Qt
Antworten
Moritz
Beiträge: 16
Registriert: 26. März 2009 18:00
Wohnort: Aachen

Größe einer Pixmap variabel bestimmen

Beitrag von Moritz »

Hallo,

ich weiß nicht ob es das alles bringt was ich hier tippe aber ich probier es trotzdem mal, weil ihr glaub ich nicht den ganzen gdcm klassenverband zur hand habt. Naja probieren wirs mal.
Also ich habe folgendes problem. Mein programm soll CT Bilder im Dicom format in eine Pixmap schreiben. Klappt auch schon. Eines kann mein programm jedoch noch nicht und zwar die größe dieser pixmap automatisch bestimmen. Mal 512*512 mal 256*256 je nach gegebendem bild halt.
Ich habe mir mein programm mehr oder weniger aus dem programm was ich ebenfalls poste, wie gesagt ich weiß nicht ob ihr was damit anfangen könnt, HelloVizWorld.cxx zusammengeklaubt. Da kommt auch der Befehl
const unsigned int *dims = image.GetDimensions(); vor.
Und damit habe ich auch mittels breakpoint bisher festgestellt das es mir damit möglich ist die größe des Feldes auf Variablen abzulegen z.b.:
m_iWidth = dims[0];
m_iHeight = dims[1];
so weit so gut jetzt der kern des problems. Da ich mein programm in insgesamt drei klassen unterteilt habe weiß ich nun nicht wie ich es machen kann das ich diese werte aus iWidth und iHeight in die klasse eight_bit_image (name passt nicht mehr so recht programm hat sich etwas größer entwickelt als ich dachte ) transferieren kann. Muss ich die werte in CDicomFile bestimmen und dann übergeben, wenn ja wie. Bis jetzt hab ich das immer über die Construktoren und vererbung gemacht aber irgendwie passt das meiner meinung nach hier nicht. Oder muss ich die werte erst in eight_bit_image einlesen und dann verwenden. Kann aber auch alles anders sein, ich versteh bis jetzt noch nicht so viel davon und lerne noch. Bin erst 7 wochen bei der c++ programmierung. Ich poste jede menge quellcode. Ich weiß ist wahrscheinlich recht kompliziert. Hoffe ihr könnt was damit anfangen.
Danke schoneinmal
Moritz

Code: Alles auswählen

#pragma once

class CDicomFile
{
public:
CDicomFile(int x, int y, int z);
~CDicomFile(void);

public:
int m_iWidth;
int m_iHeight;
short* m_pImageBuffer;
void OpenImage();
};

Code: Alles auswählen

#include "DicomFile.h"
#include <QFile>
#include <QMessageBox>
#include <QApplication>
#include <QFileDialog>

#include "gdcmImageReader.h"
#include "gdcmImageWriter.h"
#include "gdcmImage.h"
#include "gdcmPhotometricInterpretation.h"

CDicomFile::CDicomFile(int x, int y, int z)
{
m_pImageBuffer = NULL;
m_iWidth = x;
m_iHeight = y;
}

CDicomFile::~CDicomFile(void)
{
if (m_pImageBuffer != NULL)
delete[] m_pImageBuffer;
}

void CDicomFile::OpenImage()
{
QFile DataFile(QFileDialog::getOpenFileName(NULL, ("Open File"),
qApp->applicationDirPath(),
("Images (*.png *.xpm *.jpg *.raw *.dcm *.*)")));
gdcm::ImageReader reader;
reader.SetFileName( DataFile.fileName().toAscii() );

if( !reader.Read() )
{
QMessageBox::critical(NULL, "ACHTUNG", "Could not read File");
return;
}
gdcm::File &file = reader.GetFile();
const gdcm::Image &image = reader.GetImage();
unsigned int ndim = image.GetNumberOfDimensions();
const unsigned int *dims = image.GetDimensions();

if (m_pImageBuffer != NULL)
delete [] m_pImageBuffer;
m_pImageBuffer = new short[dims[0]*dims[1]];
m_iWidth = dims[0];  //<---- DIESE WERTE MUESSEN IN DIE KLASSE eight_bit_image
m_iHeight = dims[1]; //<-----
int iNum = image.GetBuffer((char*)(m_pImageBuffer));
}

Code: Alles auswählen

#pragma once

#include "DicomFile.h"

class CDicomImage : public CDicomFile
{

public:
CDicomImage(int x, int y, int z);
~CDicomImage(void);

public:
int GetWindowedPixel(int iX, int iY, int iWindowStart, int iWindowEnd, int iWindowChange);
int GetPixel(int x, int y, int z);

};

Code: Alles auswählen

#include "DicomImage.h"
#include "DicomFile.h"


CDicomImage::CDicomImage(int x, int y, int z) : CDicomFile(x, y, z)
{
}

CDicomImage::~CDicomImage(void)
{
}

int CDicomImage::GetWindowedPixel(int iX, int iY, int iWindowStart, int iWindowEnd, int iWindowChange)
{
int iOriginal = GetPixel(iX, iY, iWindowChange);
if (iOriginal < iWindowStart)
{
return 0;
}
else if (iOriginal > iWindowEnd)
{
return 255;
}
else
{
return (iOriginal - iWindowStart) * (255.0/(iWindowEnd-iWindowStart));
}
}

int CDicomImage::GetPixel(int x, int y, int z)
{
return m_pImageBuffer[x+y*512+z*512*512];
}

#ifndef EIGHT_BIT_IMAGE_H
#define EIGHT_BIT_IMAGE_H

Code: Alles auswählen

#include <QtGui/QWidget>
#include "ui_eight_bit_image.h"
#include "DicomImage.h"
#include "DicomFile.h"

class Eight_Bit_Image : public QWidget
{
Q_OBJECT

public:
Eight_Bit_Image(QWidget *parent = 0, Qt::WFlags flags = 0);
~Eight_Bit_Image();
CDicomImage* m_CDicom;

private:
Ui::Eight_Bit_ImageClass ui;

private slots:
void on_pushButton_loadImage_clicked();
void on_horizontalScrollBar_WindowStart_valueChanged(int iWindowStart);
void on_horizontalScrollBar_WindowEnd_valueChanged(int iWindowEnd);
void on_horizontalScrollBar_WindowChange_valueChanged(int iWindowChange);
void load_eight_bit();

};

#endif // EIGHT_BIT_IMAGE_H

Code: Alles auswählen

#include "eight_bit_image.h"
#include "dicomimage.h"

Eight_Bit_Image::Eight_Bit_Image(QWidget *parent, Qt::WFlags flags)
: QWidget(parent, flags)
{
ui.setupUi(this);
//m_iHeight = image.GetDimensions(); -> includes für GetDimensions einfügen (#include "gdcmPhotometricInterpretation.h")
//m_iWidth =
m_CDicom = new CDicomImage(512,512,130); //m_iWidth, m_iHeight, 130 // HIER WIRD DIE GRÖßE DER PIXMAP FESTGELEGT
}

Eight_Bit_Image::~Eight_Bit_Image()
{
delete m_CDicom;
}

void Eight_Bit_Image::on_pushButton_loadImage_clicked()
{
m_CDicom->OpenImage();
load_eight_bit();
}

void Eight_Bit_Image::load_eight_bit()
{
int iWindowStart = ui.horizontalScrollBar_WindowStart->value();
int iWindowEnd = ui.horizontalScrollBar_WindowEnd->value();
int iWindowChange = ui.horizontalScrollBar_WindowChange->value();

QImage image(512,512,QImage::Format_RGB32);

for (int x = 0; x<512; x++) // x<Width
{
for (int y = 0; y<512; y++) // y<Height
{
int iGrayValue = m_CDicom->CDicomImage::GetWindowedPixel(x,y, iWindowStart, iWindowEnd, iWindowChange);
image.setPixel(x, y, qRgb(iGrayValue, iGrayValue, iGrayValue));
}
}

ui.label_image->setPixmap(QPixmap::fromImage(image));
}

void Eight_Bit_Image::on_horizontalScrollBar_WindowStart_valueChanged(int)
{
if (ui.horizontalScrollBar_WindowStart->value() > ui.horizontalScrollBar_WindowEnd->value())
ui.horizontalScrollBar_WindowStart->setValue(ui.horizontalScrollBar_WindowEnd->value());

ui.lineEdit_WindowStart->setText(QString::number(ui.horizontalScrollBar_WindowStart->value()));
load_eight_bit();
}

void Eight_Bit_Image::on_horizontalScrollBar_WindowEnd_valueChanged(int)
{
ui.lineEdit_WindowEnd->setText(QString::number(ui.horizontalScrollBar_WindowEnd->value()));
load_eight_bit();
}

void Eight_Bit_Image::on_horizontalScrollBar_WindowChange_valueChanged(int)
{
ui.lineEdit_WindowChange->setText(QString::number(ui.horizontalScrollBar_WindowChange->value()));
load_eight_bit();
}
für euch von bedeutung werden sicher nur CDicomFile und Eight_bit_image sein. sorry das es soviel ist aber ich komme einfach schon seit tagen nicht mehr weiter.
habe jetzt einfach mal alle header und cpps hintereinander gepostet hoffe jetzt nicht allzuviel verwirrung gestiftet zu haben
danke sehr nochmal
Zuletzt geändert von Moritz am 25. Mai 2009 11:17, insgesamt 6-mal geändert.
AuE
Beiträge: 918
Registriert: 5. August 2008 10:58

Beitrag von AuE »

CODETAGS!!!!!
Das ja abscheulich so!!
Moritz
Beiträge: 16
Registriert: 26. März 2009 18:00
Wohnort: Aachen

Beitrag von Moritz »

HelloVizWorld.cxx

Code: Alles auswählen

#include "gdcmImageReader.h"
#include "gdcmImageWriter.h"
#include "gdcmImage.h"
#include "gdcmPhotometricInterpretation.h"

#include <iostream>

int main(int argc, char *argv[])
{
  if( argc < 3 )
    {
    std::cerr << argv[0] << " input.dcm output.dcm" << std::endl;
    return 1;
    }
  const char *filename = argv[1];
  const char *outfilename = argv[2];

  // Instanciate the image reader:
  gdcm::ImageReader reader;
  reader.SetFileName( filename ); // Dateiname angeben und Datei einlesen
  if( !reader.Read() )
    {
    std::cerr << "Could not read: " << filename << std::endl;
    return 1; // Prüfung ob Datei geöffnet werden konnte
    }
  // If we reach here, we know for sure 2 things:
  // 1. It is a valid DICOM
  // 2. And it contains an Image !

  // The output of superclass gdcm::Reader is a gdcm::File
  gdcm::File &file = reader.GetFile(); 

  // The other output of gdcm::ImageReader is a gdcm::Image
  const gdcm::Image &image = reader.GetImage();


  // Let's get some property from the image:
 unsigned int ndim = image.GetNumberOfDimensions();
  // Dimensions of the image:
  const unsigned int *dims = image.GetDimensions(); //wie hole ich die dims?

  short *pImageBuffer = new short[dims[0]*dims[1]];
  image.GetBuffer((char*)(pImageBuffer));

  // Origin
  const double *origin = image.GetOrigin();
  const gdcm::PhotometricInterpretation &pi = image.GetPhotometricInterpretation();
  for(unsigned int i = 0; i < ndim; ++i)
    {
    std::cout << "Dim(" << i << "): " << dims[i] << std::endl;
    }
  for(unsigned int i = 0; i < ndim; ++i)
    {
    std::cout << "Origin(" << i << "): " << origin[i] << std::endl;
    }
  std::cout << "PhotometricInterpretation: " << pi << std::endl;

  // Write the modified DataSet back to disk
  gdcm::ImageWriter writer;
  writer.SetImage( image );
  writer.SetFileName( outfilename );
  //writer.SetFile( file ); // We purposely NOT copy the meta information from the input
                            // file, and instead only pass the image
  if( !writer.Write() )
    {
    std::cerr << "Could not write: " << outfilename << std::endl;
    return 1;
    }

  return 0;
}
Zuletzt geändert von Moritz am 25. Mai 2009 11:09, insgesamt 4-mal geändert.
AuE
Beiträge: 918
Registriert: 5. August 2008 10:58

Beitrag von AuE »

super!

Also um Klassen miteinander kommunizieren zu lassen gibts Signal/Slots

http://doc.qtsoftware.com/4.5/signalsandslots.html
Moritz
Beiträge: 16
Registriert: 26. März 2009 18:00
Wohnort: Aachen

Beitrag von Moritz »

hi dankeschön für die schnelle antwort und sorry wegen den codetags. kenne mich halt noch nicht so aus. kannst du mir das vielleicht am code erklären. kenne mich mit signals und slots noch gar nicht aus. ne deutsche version vom assistent gibts höchstwahrscheinlich nicht oder?
AuE
Beiträge: 918
Registriert: 5. August 2008 10:58

Beitrag von AuE »

Nein, den gibts meines Wissens nach nur English!

Nehmen wir an du hast Klasse1 und Klasse2

in Klasse1 hast du folgende Signale im Header:

Code: Alles auswählen

signals:
void setSize(int width, int heigth);
Klasse2 hat hierzu den Folgenden Slot implementiert:

Code: Alles auswählen

private slots:	
void on_newSize(int width, int heigth);
Jetzt connectest du die Signale und Slots via

Code: Alles auswählen

bool hatgeklappt = connect (objektvonKlass1, SIGNAL(setSize(int,int)), ObjektvonKlasse2, SLOT (on_newSize(int,int));
wenn du jetzt die neue größe setzen magst aus Klasse1 heraus:

Code: Alles auswählen

emit setSize(m_size, m_heigth)
und die Methode on_newSize wird mit dem Parametern angesprungen!

** alles nur aus dem kopf....



Oder dieses Bsp direkt aus der Doku, deren Link ich dir geschickt hatte:
A Small Example

A minimal C++ class declaration might read:
class Counter
{
public:
Counter() { m_value = 0; }

int value() const { return m_value; }
void setValue(int value);

private:
int m_value;
};

A small QObject-based class might read:
#include <QObject>

class Counter : public QObject
{
Q_OBJECT

public:
Counter() { m_value = 0; }

int value() const { return m_value; }

public slots:
void setValue(int value);

signals:
void valueChanged(int newValue);

private:
int m_value;
};

The QObject-based version has the same internal state, and provides public methods to access the state, but in addition it has support for component programming using signals and slots. This class can tell the outside world that its state has changed by emitting a signal, valueChanged(), and it has a slot which other objects can send signals to.

All classes that contain signals or slots must mention Q_OBJECT at the top of their declaration. They must also derive (directly or indirectly) from QObject.

Slots are implemented by the application programmer. Here is a possible implementation of the Counter::setValue() slot:
void Counter::setValue(int value)
{
if (value != m_value) {
m_value = value;
emit valueChanged(value);
}
}

The emit line emits the signal valueChanged() from the object, with the new value as argument.

In the following code snippet, we create two Counter objects and connect the first object's valueChanged() signal to the second object's setValue() slot using QObject::connect():
Counter a, b;
QObject::connect(&a, SIGNAL(valueChanged(int)),
&b, SLOT(setValue(int)));

a.setValue(12); // a.value() == 12, b.value() == 12
b.setValue(48); // a.value() == 12, b.value() == 48

Calling a.setValue(12) makes a emit a valueChanged(12) signal, which b will receive in its setValue() slot, i.e. b.setValue(12) is called. Then b emits the same valueChanged() signal, but since no slot has been connected to b's valueChanged() signal, the signal is ignored.

Note that the setValue() function sets the value and emits the signal only if value != m_value. This prevents infinite looping in the case of cyclic connections (e.g., if b.valueChanged() were connected to a.setValue()).

A signal is emitted for every connection you make; if you duplicate a connection, two signals will be emitted. You can always break a connection using QObject::disconnect().

This example illustrates that objects can work together without needing to know any information about each other. To enable this, the objects only need to be connected together, and this can be achieved with some simple QObject::connect() function calls, or with uic's automatic connections feature.
Moritz
Beiträge: 16
Registriert: 26. März 2009 18:00
Wohnort: Aachen

Beitrag von Moritz »

danke sehr, ich probier mal ein wenig mit deiner anleitung herum. ich hoffe dich hat das nicht zu viel zeit gekostet. bis dann moritz
Antworten