在之前笔记中使用VS读取了JPEG格式的DICOM文件DICOM笔记-解析JPEG压缩格式DCM文件;
现在使用Qt写一个读取DICOM文件的Demo;
代码
在Qt的pro文件中增加DCMTK库的头文件和lib文件所在位置以及lib名称;
INCLUDEPATH+="G:/DCMTK-3.6.6/out-vs2017-win32/Debug/include/"
LIBS+= -L$$quote("G:/DCMTK-3.6.6/out-vs2017-win32/Debug/lib/")
LIBS+=cmr.lib\
dcmdata.lib\
dcmdsig.lib\
dcmect.lib\
dcmfg.lib\
dcmimage.lib\
dcmimgle.lib\
dcmiod.lib\
dcmjpeg.lib\
dcmjpls.lib\
dcmnet.lib\
dcmpmap.lib\
dcmpstat.lib\
dcmqrdb.lib\
dcmrt.lib\
dcmseg.lib\
dcmsr.lib\
dcmtkcharls.lib\
dcmtls.lib\
dcmtract.lib\
dcmwlm.lib\
i2d.lib\
ijg12.lib\
ijg16.lib\
ijg8.lib\
oflog.lib\
ofstd.lib
在MainWindow.h中增加相应打开QAction的槽函数on_actionOpen_triggered;
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
void ConvertDigitImageToGrayImageByWindowLevelAndWindowWidth(short* digitImage, short* grayImage, int size, int window_level, int window_width);
private slots:
void on_actionOpen_triggered();
private:
Ui::MainWindow *ui;
QString dcm_file_path;
};
#endif // MAINWINDOW_H
在打开对应的QAction的槽函数on_actionOpen_triggered中增加读取解析DICOM功能;
1.读取DICOM文件的宽和高;
2.解码JPEG格式;
3.在QLabel下显示图像;
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <iostream>
#include "dcmtk\config\osconfig.h"
#include "dcmtk\dcmdata\dctk.h"
#include <dcmtk/dcmjpeg/djdecode.h> /* for dcmjpeg decoders */
#include <dcmtk/dcmjpeg/djencode.h>
#include <dcmtk/dcmjpls/djdecode.h> //for JPEG-LS decode
#include <dcmtk/dcmjpls/djencode.h> //for JPEG-LS encode
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow){
ui->setupUi(this);
}
MainWindow::~MainWindow(){
delete ui;
}
void MainWindow::on_actionOpen_triggered(){
this->dcm_file_path = QFileDialog::getOpenFileName(this,tr("选择DICOM图像"),"",tr("Files (*.dcm )"));
DJDecoderRegistration::registerCodecs();
DJLSEncoderRegistration::registerCodecs(); //JPEG-LS encoder registerCodecs
DJLSDecoderRegistration::registerCodecs(); //JPEG-LS decoder registerCodecs
DcmFileFormat *myFileFormat = new DcmFileFormat;
OFCondition cond = myFileFormat->loadFile(dcm_file_path.toStdString().c_str());
Uint16 height = 0;
Uint16 width = 0;
if (cond.good()){
if (myFileFormat->getDataset()->findAndGetUint16(DCM_Rows, height).bad()) {
std::cout << "No Row Data!\n";
}
if (myFileFormat->getDataset()->findAndGetUint16(DCM_Columns, width).bad()) {
std::cout << "No Columns Data!\n";
}
}
unsigned long size = 0;
int all_point_size = height * width;
short* pix_buf = new short[all_point_size];
DcmElement* pElement = nullptr;
myFileFormat->getDataset()->chooseRepresentation(EXS_DeflatedLittleEndianExplicit, NULL);
myFileFormat->getDataset()->findAndGetElement(DCM_PixelData, pElement);
if (pElement != NULL) {
size = pElement->getLength()/2;
OFCondition cond = pElement->loadAllDataIntoMemory();
if (cond.good()) {
Uint16 * ptr;
cond = pElement->getUint16Array(ptr);
if (cond.good()) {
ConvertDigitImageToGrayImageByWindowLevelAndWindowWidth((short*)ptr, pix_buf, size, 400, 2000);
}
}
}
char* pBuf = new char[all_point_size]{0};
int single_row_size = width;
for (int i = 0; i< height;i++){
char* row_ptr = pBuf+i*single_row_size;
for (int j = 0; j < width; j++) {
row_ptr[j] = pix_buf[i*width+j];
}
}
QImage images = QImage((uchar*)pBuf, width, height, QImage::Format_Indexed8);
ui->label->setPixmap(QPixmap::fromImage(images));
delete[] pBuf;
delete[] pix_buf;
DJEncoderRegistration::cleanup();
DJDecoderRegistration::cleanup();
DJLSEncoderRegistration::cleanup(); //JPEG-LS encoder cleanup
DJLSDecoderRegistration::cleanup(); //JPEG-LS decoder cleanup
}
void MainWindow::ConvertDigitImageToGrayImageByWindowLevelAndWindowWidth(short* digitImage, short* grayImage,
int size, int window_level, int window_width){
double rate = 256.0 / window_width;
for (int i = 0; i < size; i++){
int tmp = 128.0 + (digitImage[i] - window_level)*rate;
if (tmp < 0){
tmp = 0;
}
else if (tmp > 255){
tmp = 255;
}
grayImage[i] = tmp;
}
}
代码以及项目所在位置:打开JEPG格式DICOM文件的DemoMyDicom.rar
知识点
QString转换char*
先将 QString 转为标准库中的 string 类型,然后将 string 转为 char *。
QString filename;
std::string str = filename.toStdString();
const char* ch = str.c_str();
二维数据矩阵转换图像
先将二维数组转换为QImage对象,然后调用QPixmap::fromImage函数生成QPixmap对象;
QImage images = QImage((uchar*)pBuf, 512, 512, QImage::Format_Indexed8);
ui->label->setPixmap(QPixmap::fromImage(images));
参考资料
1.QT 二维数组转BMP BMP转二维数组 QImage转二维数组 的简便方法
2.QT显示图片的几种方法
3.文件数据通过qt将二维数组中的像素点显示成一张图片
4.QString 转换为 char *