Problems creating QT widgets together with DCMTK
Moderator: Moderator Team
Problems creating QT widgets together with DCMTK
Hello,
I am new here on the Forum hope to find some answers. First of all, I like the dcmtk toolkit very much!
My plan is to write some qt (see www.trolltech.com) widgets to embed them in there GUI designer. The idea is to make a environment for click and go medical viewers. This video demonstrates the environment of QT creating some HTML viewer: http://www.trolltech.com/video/index.html
Exchange in this video the HTML widget for a set of dcmtk-widgets for different images, slices, run's etc. and you get a nice environment to develop medical related software.
Some weeks ago I started coding and the first widget is almost ready. It can handle monochrome, color, frames.
To test the widget, I downloaded some dicom images from several sites.
I noticed however that not all images can be opened. Sometimes I got EIR_MissingAttribute and the image could not be opened.
To find the problem the library is built in debug mode. Next SetDebugLevel is used to see the library messages.
Currently I do not see any library messages occur. I do not understand that the messages do not occur. Is building in debug mode and setting the SetDebugLevel not enough?
Secondly I like to know what I should do if an image can not be opened. Is it a problem of the image or can dcmtk not handle it or is it a configuration problem etc.
Kind regards,
Spirit
I am new here on the Forum hope to find some answers. First of all, I like the dcmtk toolkit very much!
My plan is to write some qt (see www.trolltech.com) widgets to embed them in there GUI designer. The idea is to make a environment for click and go medical viewers. This video demonstrates the environment of QT creating some HTML viewer: http://www.trolltech.com/video/index.html
Exchange in this video the HTML widget for a set of dcmtk-widgets for different images, slices, run's etc. and you get a nice environment to develop medical related software.
Some weeks ago I started coding and the first widget is almost ready. It can handle monochrome, color, frames.
To test the widget, I downloaded some dicom images from several sites.
I noticed however that not all images can be opened. Sometimes I got EIR_MissingAttribute and the image could not be opened.
To find the problem the library is built in debug mode. Next SetDebugLevel is used to see the library messages.
Currently I do not see any library messages occur. I do not understand that the messages do not occur. Is building in debug mode and setting the SetDebugLevel not enough?
Secondly I like to know what I should do if an image can not be opened. Is it a problem of the image or can dcmtk not handle it or is it a configuration problem etc.
Kind regards,
Spirit
-
- DCMTK Developer
- Posts: 2072
- Joined: Fri, 2004-11-05, 13:47
- Location: Oldenburg, Germany
- Contact:
Hi Spirit,
first of all: Using DCMTK and QT together should work well, we did some projects with this. In the current version of QT, some adaptions may be necessary, but it seems you managed all that, fine
As I think you should get some debug messages when setting the debug level. But this is not really your problem, if you encounter messages like "missing tag" or something similar. DICOM stores all information in attributes identified by tags. The pixel data is stored in such an attribute too. To interpret this pixel data correctly, DICOM specifies some additional attributes, like number of rows and columns, colour model, compression details etc. If some of this (mandatory) tags are missing, it's not possible to interpret the pixel data, i. e. the DCMTK fails, because it could only guess how the pixel data is encoded. So, this is not a problem in DCMTK but the files are not valid DICOM files.
Regards,
Michael
first of all: Using DCMTK and QT together should work well, we did some projects with this. In the current version of QT, some adaptions may be necessary, but it seems you managed all that, fine
As I think you should get some debug messages when setting the debug level. But this is not really your problem, if you encounter messages like "missing tag" or something similar. DICOM stores all information in attributes identified by tags. The pixel data is stored in such an attribute too. To interpret this pixel data correctly, DICOM specifies some additional attributes, like number of rows and columns, colour model, compression details etc. If some of this (mandatory) tags are missing, it's not possible to interpret the pixel data, i. e. the DCMTK fails, because it could only guess how the pixel data is encoded. So, this is not a problem in DCMTK but the files are not valid DICOM files.
Regards,
Michael
Hi Michael,
Thanks for the fast response! Nice to hear other people using qt and dcmtk together too.
I am working to integrate dicom in the KDE environment. I like to get the konqueror browser of kde showing dicom thumbnails, showing meta data like patient name and other related data. Next a simple viewer should be available when clicking on a image. For this reason I wrote a qDicomImage class that reads dicom files using dcmtk and delivers qimages.
Kind regards,
Spirit
Thanks for the fast response! Nice to hear other people using qt and dcmtk together too.
I am working to integrate dicom in the KDE environment. I like to get the konqueror browser of kde showing dicom thumbnails, showing meta data like patient name and other related data. Next a simple viewer should be available when clicking on a image. For this reason I wrote a qDicomImage class that reads dicom files using dcmtk and delivers qimages.
Kind regards,
Spirit
progress and new questions
Hello,
I am happy to say things are starting to work! First I created a class to convert a dcmtk image buffer to a QT QImage. This works for some images (not all!) and I wrote for the KDE environment an thumbnail plug-in. The result can be seen via next link.
http://home.kabelfoon.nl/~jwaal/
Next, I like to make some widgets to add to the designer of qt and create viewers for different dicom studies.
The question I have, is that only some images are correctly converted by my class. I saw e.g. that compressed Images (JPG) are not converted. If I use dcmj2pnm I am able to convert the image. So that should be possible I guess. Maybe it's the code I wrote, who can have a look at it?
Header of conversion class dcmtk -> QT
Source code of conversion class
[/b]
Kind regards,
Jeroen van der Waal
I am happy to say things are starting to work! First I created a class to convert a dcmtk image buffer to a QT QImage. This works for some images (not all!) and I wrote for the KDE environment an thumbnail plug-in. The result can be seen via next link.
http://home.kabelfoon.nl/~jwaal/
Next, I like to make some widgets to add to the designer of qt and create viewers for different dicom studies.
The question I have, is that only some images are correctly converted by my class. I saw e.g. that compressed Images (JPG) are not converted. If I use dcmj2pnm I am able to convert the image. So that should be possible I guess. Maybe it's the code I wrote, who can have a look at it?
Header of conversion class dcmtk -> QT
Code: Select all
#ifndef QDICOMIMAGE_H
#define QDICOMIMAGE_H
/**
@author Jeroen van der Waal <jwaal@kabelfoon.nl>
*/
#include "qimage.h"
#include <dcmtk/config/cfunix.h>
#include <dcmtk/config/osconfig.h>
#include <dcmtk/ofstd/ofstring.h>
#include <dcmtk/ofstd/ofconsol.h>
#include <dcmtk/dcmdata/dcdeftag.h>
#include <dcmtk/dcmdata/dcfilefo.h>
#include <dcmtk/dcmimgle/dcmimage.h>
#include "dcmtk/dcmimage/diregist.h" /* include to support color images */
class QGrayColorTable
{
public:
static const unsigned int GRAY_LEVELS = 256;
QGrayColorTable();
virtual ~QGrayColorTable() {}
QRgb* getGrayColorTable() { return m_colortable; }
private:
static QRgb m_colortable[GRAY_LEVELS];
};
class QDicomImage
{
public:
QDicomImage(const char* filename, const unsigned long flags=0,
const unsigned long fstart=0, const unsigned long fcount=0);
virtual ~QDicomImage();
QImage getOutputData(const unsigned long p_frame=0, const int p_planar=0);
unsigned long getFrameCount() const;
private:
///Dcmtk attributes
DicomImage* m_dicomImage;
EI_Status m_status;
///Qt related attributes
static QGrayColorTable m_grayColorTable;
static const int IMG_DEPTH = 8;
unsigned long m_qimageSize;
///Image buffer is maintained by this class instead of dcmtk or qt.
///It is to prevent create/delete of buffer for every frame in case
///of a multi frame dicom file.
uchar* m_qimageBuffer;
};
#endif
Code: Select all
#include "qdicomimage.h"
QGrayColorTable::QGrayColorTable()
{
//color table for monochroom images.
for(unsigned int i=0; i < GRAY_LEVELS; i++) {
m_colortable[i] = qRgb(i,i,i);
}
}
QRgb QGrayColorTable::m_colortable[GRAY_LEVELS];
QDicomImage::QDicomImage(const char* filename, const unsigned long flags,
const unsigned long fstart, const unsigned long fcount)
:m_dicomImage(NULL)
,m_status(EIS_Normal)
,m_qimageSize(0)
,m_qimageBuffer(NULL)
{
m_dicomImage = new DicomImage(filename, flags, fstart, fcount);
m_status = m_dicomImage->getStatus();
if(EIS_Normal == m_status) {
m_qimageSize = m_dicomImage->getWidth() * m_dicomImage->getHeight();
if(!m_dicomImage->isMonochrome()) {
/// color images needs 4 times the amount of memory (RGBA)
m_qimageSize = m_qimageSize * 4;
}
m_qimageBuffer = new uchar[m_qimageSize];
}
}
QDicomImage::~QDicomImage()
{
if(m_dicomImage) {
delete m_dicomImage;
}
if(m_qimageBuffer) {
delete[] m_qimageBuffer;
}
}
QImage QDicomImage::getOutputData(const unsigned long p_frame, const int p_planar)
{
QImage image;
if(EIS_Normal == m_status) {
if (m_dicomImage->isMonochrome()) {
///Monochroom images
m_dicomImage->setMinMaxWindow(); //??
m_dicomImage->getOutputData(m_qimageBuffer, m_qimageSize, IMG_DEPTH, p_frame, p_planar);
image = QImage(m_qimageBuffer, m_dicomImage->getWidth(), m_dicomImage->getHeight(),
IMG_DEPTH, m_grayColorTable.getGrayColorTable(), QGrayColorTable::GRAY_LEVELS,
QImage::BigEndian);
} else {
///color images
uchar* pixelData = (uchar *)(m_dicomImage->getOutputData(IMG_DEPTH, p_frame, p_planar));
///transform representation from dcmtk(RGB) to qimage (RGBA)
unsigned long y = 0;
for(unsigned long x = 0; x < m_qimageSize; x+=4) {
m_qimageBuffer[x] = pixelData[y]; //R
m_qimageBuffer[x+1] = pixelData[y+1]; //G
m_qimageBuffer[x+2] = pixelData[y+2]; //B
m_qimageBuffer[x+3] = 0xFF; //Alpha
y += 3;
}
image = QImage(m_qimageBuffer, m_dicomImage->getWidth(), m_dicomImage->getHeight(),
32, 0, 0, QImage::BigEndian);
}
}
return image; ///< is ok to return, qimage supports shallow copy
}
unsigned long QDicomImage::getFrameCount() const
{
return m_dicomImage->getFrameCount();
}
QGrayColorTable QDicomImage::m_grayColorTable;
Kind regards,
Jeroen van der Waal
-
- OFFIS DICOM Team
- Posts: 1493
- Joined: Tue, 2004-11-02, 17:22
- Location: Oldenburg, Germany
- Contact:
In order to work correctly with compressed images, your code should register one or more decompression codecs before the first DicomImage instance is created. For JPEG compression, the code looks like this:
Note that there is also a corresponding cleanup call that should be issued before the tool terminates. A similar structure exists for the RLE codec and the JPEG 2000 codec, the latter of which is not part of the public toolkit, however.
Code: Select all
#include "dcmtk/dcmjpeg/djdecode.h" /* for jpeg decoder */
[...]
// register JPEG decompression codecs
DJDecoderRegistration::registerCodecs();
QT designer is extended with plugin for dicom, and question.
Hi,
I am happy to say that I now have a plugin for QT designer that is able to show (color/monochrome, jpeg/rle) and plays dicom images / loops / runs. Via slots the widget can play, reverse play, frame forward/back, zoom and change the speed of playing. The widget itself is a scrollview, so if the image does not fit it can be scrolled.
It works smooth for about 25 frames / sec for images of size 1024x1024. For this I use a single study of size 100 Mb. The load time for this study takes about 10 seconds. I like to not immediately load all the content in one strike, and my question is, is it possible to load it piece by piece?
Kind regards,
Jeroen van der Waal
I am happy to say that I now have a plugin for QT designer that is able to show (color/monochrome, jpeg/rle) and plays dicom images / loops / runs. Via slots the widget can play, reverse play, frame forward/back, zoom and change the speed of playing. The widget itself is a scrollview, so if the image does not fit it can be scrolled.
It works smooth for about 25 frames / sec for images of size 1024x1024. For this I use a single study of size 100 Mb. The load time for this study takes about 10 seconds. I like to not immediately load all the content in one strike, and my question is, is it possible to load it piece by piece?
Kind regards,
Jeroen van der Waal
-
- OFFIS DICOM Team
- Posts: 1493
- Joined: Tue, 2004-11-02, 17:22
- Location: Oldenburg, Germany
- Contact:
If you are loading single frame images such as the conventional CT and MR SOP classes, you control the behaviour completely on your own. If you are working with multiframe images, there is unfortunately no way to tell DCMTK to only load a certain number of frames. Opening the file (DcmFileFormat::loadFile) will not load everything - all attributes larger than 4K remain in the file and are loaded on demand. However, once you try to access any piece of the pixel data, all pixel data is loaded and there is no way to prevent this. Changing this part of DCMTK's API to allow partial loading and partial decompression is one of the most favourite feature requests, but is not trivial and has not yet happened.I like to not immediately load all the content in one strike, and my question is, is it possible to load it piece by piece?
Hi Marco,
Nice hearing from you so soon. Not that bad that this way of loading is not yet supported. I guess the sign 'please wait...' should be enough for the moment . After all Dcmtk is really great, I enjoy working with it very much.
I am recording some gui building with the dicom qt widget and will post it on this site.
Kind regards,
Jeroen van der Waal
Nice hearing from you so soon. Not that bad that this way of loading is not yet supported. I guess the sign 'please wait...' should be enough for the moment . After all Dcmtk is really great, I enjoy working with it very much.
I am recording some gui building with the dicom qt widget and will post it on this site.
Kind regards,
Jeroen van der Waal
Some results of dicom widget set based on dcmtk / qt
Hi,
I worked the last two months using all my sparetime creating a set of three QT widgets. The widgets extending the qt designer environment and can be used to create dicom viewers by dragging components and connecting them with eachother. In only five minutes without compiling a dicom viewer can play, zoom, change contrast etc.
This is a link to a presentation (and demo) I gave to an audience of MFC programmers in an medical environment (they had a hard time ).
http://home.kabelfoon.nl/~jwaal/present ... idgets.pdf
The following components are available extends the components within the QT designer (please visit trolltech site for more information):
All widgets supports dropping of files, just drop a DICOMDIR and it is shown in the qdicomdirwidget. All kinds of dicom image files can be dropped on the QDicomWidget for viewing/playing.
I have plenty of ideas to extend the widget set to make it a nice set of building blocks for medical viewing.
Kind regards,
Jeroen van der Waal
I worked the last two months using all my sparetime creating a set of three QT widgets. The widgets extending the qt designer environment and can be used to create dicom viewers by dragging components and connecting them with eachother. In only five minutes without compiling a dicom viewer can play, zoom, change contrast etc.
This is a link to a presentation (and demo) I gave to an audience of MFC programmers in an medical environment (they had a hard time ).
http://home.kabelfoon.nl/~jwaal/present ... idgets.pdf
The following components are available extends the components within the QT designer (please visit trolltech site for more information):
- qdicomdirwidget, show tree view of dicomdir
- qdicomdiriconwidget, shows all icons of dicomdir
- qdicomwidget, show dicom images, zoom, contrast, brightness, play, reverse play, single step (mouse/button), mouse zoom/pan.
All widgets supports dropping of files, just drop a DICOMDIR and it is shown in the qdicomdirwidget. All kinds of dicom image files can be dropped on the QDicomWidget for viewing/playing.
I have plenty of ideas to extend the widget set to make it a nice set of building blocks for medical viewing.
Kind regards,
Jeroen van der Waal
-
- ICSMED DICOM Services
- Posts: 2217
- Joined: Fri, 2004-10-29, 21:38
- Location: Oldenburg, Germany
-
- DCMTK Developer
- Posts: 2072
- Joined: Fri, 2004-11-05, 13:47
- Location: Oldenburg, Germany
- Contact:
Hey Spirit,
When I look at your perf ratings I'm a bit puzzled...
I did my own dicomdir usage object and perf is really bad :
For 20 patients, i get around 20 secs to write a 21th.
I may miss some things...
I use the DicomDirInterface to take advantage of the addFile method.
I also need to specify specific tags so i need to reparse my dicom dir file.
This time i use a DcmDirectoryRecord object and manually look for correct record (parse all patients, then studies then series) to get the serie i need and add required information (by example body part examined)
This takes really a long time and I would be really happy to see it shortened by half ^^
When I look at your perf ratings I'm a bit puzzled...
I did my own dicomdir usage object and perf is really bad :
For 20 patients, i get around 20 secs to write a 21th.
I may miss some things...
I use the DicomDirInterface to take advantage of the addFile method.
I also need to specify specific tags so i need to reparse my dicom dir file.
This time i use a DcmDirectoryRecord object and manually look for correct record (parse all patients, then studies then series) to get the serie i need and add required information (by example body part examined)
This takes really a long time and I would be really happy to see it shortened by half ^^
Last edited by Tsunamis on Tue, 2011-02-01, 14:40, edited 2 times in total.
Hello Tsunamis,
Currently I only parse an existing dicomdir. To do that you need to go through the records of the DICOMDIR. The next part are some lines from one of the widgets. I guess further explanation is not needed. I like know what you're findings are concerning the speed. Success!
Kind regards,
Spirit
Currently I only parse an existing dicomdir. To do that you need to go through the records of the DICOMDIR. The next part are some lines from one of the widgets. I guess further explanation is not needed. I like know what you're findings are concerning the speed. Success!
Kind regards,
Spirit
Code: Select all
bool QDicomDirWidget::loadFile(const QString& filename)
{
DcmDicomDir dicomdir(filename);
if(dicomdir.error().bad())
{
return false;
}
DcmDirectoryRecord* root = &(dicomdir.getRootRecord());
for(DcmDirectoryRecord* patient = root->nextSub(NULL); patient != NULL; patient = root->nextSub(patient))
{
const char *value;
patient->findAndGetString (DCM_PatientsName, value);
for(DcmDirectoryRecord* study = patient->nextSub(NULL); study != NULL; study = patient->nextSub(study))
{
study->findAndGetString (DCM_StudyDate, value);
for(DcmDirectoryRecord* series = study->nextSub(NULL); series != NULL; series = study->nextSub(series))
{
series->findAndGetString (DCM_Modality, value);
for(DcmDirectoryRecord* images = series->nextSub(NULL); images != NULL; images = series->nextSub(images))
{
images->findAndGetString(DCM_ImageType, value);
}
}
}
}
return true;
}
Who is online
Users browsing this forum: Bing [Bot] and 1 guest