From 91ebba6e9dc51b4e2ea647bbdebe81149e6d6a2e Mon Sep 17 00:00:00 2001 From: Krad Date: Tue, 20 Sep 2022 09:32:37 +0800 Subject: [PATCH] Thumbnail create logic. --- src/src/IO/DICOM/DICOMPixelDataHelper.cpp | 28 +++++------- src/src/IO/DICOM/DICOMPixelDataHelper.h | 4 +- src/src/UI/Dialog/exportdialog.h | 4 +- .../UI/Widget/Thumbnail/thumbnailImage.cpp | 27 ++++++++++-- src/src/UI/Widget/Thumbnail/thumbnailImage.h | 8 +--- .../Widget/Thumbnail/thumbnailbarwidget.cpp | 43 ++++--------------- 6 files changed, 49 insertions(+), 65 deletions(-) diff --git a/src/src/IO/DICOM/DICOMPixelDataHelper.cpp b/src/src/IO/DICOM/DICOMPixelDataHelper.cpp index 73a3eca..42449f8 100644 --- a/src/src/IO/DICOM/DICOMPixelDataHelper.cpp +++ b/src/src/IO/DICOM/DICOMPixelDataHelper.cpp @@ -35,27 +35,21 @@ void DICOMPixelDataHelper::FinalizeCodecs() { #endif } -void DICOMPixelDataHelper::GetThumbnailData(ExtendMedicalImageProperties *property, unsigned char* data, - unsigned long& length) { +void DICOMPixelDataHelper::GetThumbnailData(ExtendMedicalImageProperties *property, void*& data, + unsigned long& length, int & sample) { double *wlww = property->GetNthWindowLevelPreset(0); int ww = wlww ? ((int) wlww[0]) : (512); int wl = wlww ? ((int) wlww[1]) : (256); - int sample = property->GetSamplePerPixel(); - DcmFileFormat *fileFormat = new DcmFileFormat();//读取文件获取传输语法 - if (fileFormat->loadFile(property->GetThumbnailFileName()).good()) { - DcmDataset *dset = fileFormat->getDataset(); - DicomImage dcmImage(fileFormat, dset->getOriginalXfer()); - DicomImage *sdcmImage = dcmImage.createScaledImage(100.0, 0.0, 0, 1); - sdcmImage->setWindow(wl, ww); - sdcmImage->showAllOverlays(); - length = sdcmImage->getOutputDataSize(8); - unsigned char *outputData = (unsigned char *) sdcmImage->getOutputData(8);//按8位的位宽取数据 - data = new unsigned char[length]; - memcpy(data, outputData, length); - sdcmImage->deleteOutputData(); - delete sdcmImage; + sample = property->GetSamplePerPixel(); + DcmFileFormat fileFormat; + if (fileFormat.loadFile(property->GetThumbnailFileName()).good()) { + DcmDataset *dset = fileFormat.getDataset(); + DicomImage dcmImage(&fileFormat, dset->getOriginalXfer(), CIF_MayDetachPixelData); + dcmImage.setWindow(wl, ww); + length = dcmImage.getOutputDataSize(8); + data = new unsigned char[length]; + dcmImage.getOutputData(data, length, 8);//按8位的位宽取数据 } - delete fileFormat; } diff --git a/src/src/IO/DICOM/DICOMPixelDataHelper.h b/src/src/IO/DICOM/DICOMPixelDataHelper.h index 12366e8..6c37141 100644 --- a/src/src/IO/DICOM/DICOMPixelDataHelper.h +++ b/src/src/IO/DICOM/DICOMPixelDataHelper.h @@ -16,8 +16,8 @@ public: ~DICOMPixelDataHelper() { } - static void GetThumbnailData(ExtendMedicalImageProperties *property, unsigned char* data, - unsigned long& length); + static void GetThumbnailData(ExtendMedicalImageProperties *property, void*& data, + unsigned long& length,int& sample); /** * Get Pixel Data with Rescaled, result is calculate as integer, and arrange as integer. * @param path dcm file absolute path diff --git a/src/src/UI/Dialog/exportdialog.h b/src/src/UI/Dialog/exportdialog.h index 2b8b0bc..380f4c7 100644 --- a/src/src/UI/Dialog/exportdialog.h +++ b/src/src/UI/Dialog/exportdialog.h @@ -2,9 +2,9 @@ #define EXPORTDIALOG_H #include -#include "IO/Export/exportoptions.h" +#include "Deprecated/Export/exportoptions.h" #include "qdir.h" -#include "IO/Export/dicomexporterthread.h" +#include "Deprecated/Export/dicomexporterthread.h" #include "QFileDialog" #include "IO/DICOM/DicomLoader.h" #include "UI/Widget/ImageView/dicomimageview.h" diff --git a/src/src/UI/Widget/Thumbnail/thumbnailImage.cpp b/src/src/UI/Widget/Thumbnail/thumbnailImage.cpp index 5dd3744..575b647 100644 --- a/src/src/UI/Widget/Thumbnail/thumbnailImage.cpp +++ b/src/src/UI/Widget/Thumbnail/thumbnailImage.cpp @@ -1,8 +1,9 @@ #include "thumbnailImage.h" #include +#include #include "qstyleoption.h" #include "qpainter.h" -#include "IO/DICOM/QDicomUtility.h" +#include "IO/DICOM/DICOMPixelDataHelper.h" static QString unpick_style = "*{background-color:#7f7f7f;}" "QLabel#m_descri{color:white}"; @@ -11,6 +12,7 @@ static QString pick_style = "*{background-color:#c5c5c5;}" "QLabel#m_descri{color:black;}"; thumbnailImage::thumbnailImage(QWidget *parent, ExtendMedicalImageProperties* property) : QFrame(parent) +,seriesProperty(property) { this->setObjectName(QString::fromUtf8("frame")); @@ -55,9 +57,9 @@ thumbnailImage::thumbnailImage(QWidget *parent, ExtendMedicalImageProperties* pr m_pixmap->setMaximumSize(QSize(100, 100)); m_pixmap->setLayoutDirection(Qt::LeftToRight); m_pixmap->setFrameShape(QFrame::StyledPanel); - m_pixmap->setPixmap(DicomUtil::GetThumbnail(property)); m_pixmap->setScaledContents(true); m_pixmap->setAlignment(Qt::AlignCenter); + drawThumbnail(); horizontalLayout_2->addWidget(m_pixmap); QSpacerItem* horizontalSpacer_3 = new QSpacerItem(6, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); horizontalLayout_2->addItem(horizontalSpacer_3); @@ -88,7 +90,7 @@ thumbnailImage::thumbnailImage(QWidget *parent, ExtendMedicalImageProperties* pr m_descri->setText(property->GetSeriesDescription()); m_slicenum->setText(QString("%1").arg(property->GetSliceCount())); - seriesProperty = property; + this->setStyleSheet(unpick_style); } void thumbnailImage::setHighlight(bool yes) { @@ -126,5 +128,22 @@ void thumbnailImage::mouseMoveEvent(QMouseEvent *e) { thumbnailImage::~thumbnailImage() { - + if (m_Data) free(m_Data); +} + +void thumbnailImage::drawThumbnail() { + if (m_Data) free(m_Data); + m_Data = nullptr; + unsigned long length = 0; + int sample = 0; + DICOMPixelDataHelper::GetThumbnailData(seriesProperty, m_Data, length, sample); + QImage image( (uchar*)m_Data, seriesProperty->GetColumns(), seriesProperty->GetRows(), + sample == 1 ? QImage::Format_Grayscale8 : QImage::Format_RGB888);//使用8位深度的灰度图做输出 + image = image.scaledToHeight(100); + if (image.width() > 100) image.scaledToWidth(100); + QPixmap pixmap(100, 100); + pixmap.fill(Qt::black); + QPainter p(&pixmap); + p.drawPixmap(50 - image.width() / 2, 50 - image.height() / 2, QPixmap::fromImage(image)); + m_pixmap->setPixmap(pixmap); } diff --git a/src/src/UI/Widget/Thumbnail/thumbnailImage.h b/src/src/UI/Widget/Thumbnail/thumbnailImage.h index 3eedef3..6144e9b 100644 --- a/src/src/UI/Widget/Thumbnail/thumbnailImage.h +++ b/src/src/UI/Widget/Thumbnail/thumbnailImage.h @@ -30,15 +30,11 @@ protected: private: - - //void setBackgroundColor(QColor pickColor); - - - + void drawThumbnail(); QLabel *m_descri; QLabel *m_slicenum; QLabel *m_pixmap; ExtendMedicalImageProperties* seriesProperty = nullptr; QPoint drag_org_; - + void * m_Data = nullptr; }; diff --git a/src/src/UI/Widget/Thumbnail/thumbnailbarwidget.cpp b/src/src/UI/Widget/Thumbnail/thumbnailbarwidget.cpp index 6ece8b6..d037c4a 100644 --- a/src/src/UI/Widget/Thumbnail/thumbnailbarwidget.cpp +++ b/src/src/UI/Widget/Thumbnail/thumbnailbarwidget.cpp @@ -1,42 +1,14 @@ #include "thumbnailbarwidget.h" -#include "IO/DICOM/DicomLoader.h" -#include "Common/SeriesImageSet.h" + #include -#include #include -#include +#include +#include +#include "IO/DICOM/DicomLoader.h" +#include "IO/DICOM/DICOMPixelDataHelper.h" +#include "Common/SeriesImageSet.h" #include "UI/Widget/ImageView/dicomimageview.h" -#include "qstyleoption.h" -#include "qpainter.h" -/************************************************************************ -* Function List: -* 1. [Done][Action Open] update thumbnail bar whenever open a directory or file -* 2. [Abort][Click] create a seriesIntance showing on chosen DicomImageView -* 3. [Done][Highlight] when the relevant view is clicked,set thumbnail highlight -* 4. [Done][Drag Motion] the same as click -* 5. [Undone][Scroll] scroll bar to show all thumbnails -* -* Consider: -* the difference between action open and click. -* 1. [Done]improve the current map to support multiple instances -* 2. [Done]think about how different instances share the same image data - you may use smart pointer to address this problem, init a instance with another -* 3. [Done]updateThumbnailBar will remove all widget fist which costs high, need to be improved -* -* Notice : -* 1. Drag logic is confused with click, take place of click -* -* Replace Strategy -* 1. file->dir[same series uid] replace all the opening file -* 2. file->file[different instance number] replace all the opening file[Radiant:combine images together] -* 3. dir->dir[same series uid] do nothing -* 4. file->file[same instance number] do nothing -* Namely, existing instances are all dir or same single file -* -/************************************************************************/ - - class ThumbMessages { @@ -143,6 +115,8 @@ void ThumbnailBarWidget::updateThumbnailBar() SeriesMapType *series = it_st->second->series; + + DICOMPixelDataHelper::InitCodecs(); for (SeriesMapType::const_iterator it_se = series->cbegin(); it_se != series->cend(); it_se++) { thumbnailImage *thumbnail = createThumbnailImage(seriesPanel, it_se->second); @@ -154,6 +128,7 @@ void ThumbnailBarWidget::updateThumbnailBar() //save all thumbnail in one list LabelList << thumbnail; } + DICOMPixelDataHelper::FinalizeCodecs(); } } }