1+ #include " DicomMultiFrameStreamer.hpp"
2+ #include " dcmtk/dcmimage/diregist.h"
3+ #include < dcmtk/dcmdata/dcfilefo.h>
4+ #include < dcmtk/dcmdata/dcdeftag.h>
5+ #include < dcmtk/dcmimgle/dcmimage.h>
6+ #include < dcmtk/dcmdata/dcpixel.h>
7+ #include < dcmtk/dcmjpeg/djdecode.h>
8+ #include < FAST/Data/Image.hpp>
9+ #include < memory>
10+ #include < FAST/Algorithms/Color/ColorToGrayscale.hpp>
11+
12+ namespace fast {
13+
14+ /*
15+ template <>
16+ std::string DicomMultiFrameStreamer::getDicomTag<std::string>(ushort group, ushort element) {
17+ if(!m_dataset)
18+ load();
19+ OFString patientID;
20+ m_dataset->findAndGetOFString(DcmTagKey(group, element), patientID);
21+ return patientID.c_str();
22+ }
23+ */
24+
25+ DicomMultiFrameStreamer::DicomMultiFrameStreamer (std::string filename, bool loop, bool useFramerate, int framerate, bool convertToGrayscale, bool cropToROI) {
26+ createOutputPort (0 );
27+ m_filename = filename;
28+ m_convertToGrayscale = convertToGrayscale;
29+ m_cropToROI = cropToROI;
30+ m_useFramerate = useFramerate;
31+ setLooping (loop);
32+ setFramerate (framerate);
33+ DJDecoderRegistration::registerCodecs ();// register JPEG codecs
34+ }
35+
36+ void DicomMultiFrameStreamer::execute () {
37+ startStream ();
38+
39+ waitForFirstFrame ();
40+ }
41+
42+ void DicomMultiFrameStreamer::load () {
43+ if (!fileExists (m_filename))
44+ throw FileNotFoundException (m_filename);
45+
46+ m_image = std::make_shared<DicomImage>(m_filename.c_str ());
47+ if (m_image->getStatus () != EIS_Normal) {
48+ throw Exception (" Error creating dicom image object" );
49+ }
50+ m_fileFormat = std::make_shared<DcmFileFormat>();
51+ OFCondition status = m_fileFormat->loadFile (m_filename.c_str ());
52+ if (!status.good ()) {
53+ m_dataset = m_fileFormat->getDataset ();
54+ } else {
55+ throw Exception (" Unable to read dicom dataset" );
56+ }
57+ if (m_image->getNumberOfFrames () == 1 )
58+ throw Exception (" Dicom file given to DicomMultiFrameStreamer is not a multi frame file." );
59+ }
60+
61+ void DicomMultiFrameStreamer::generateStream () {
62+ if (!m_image)
63+ load ();
64+ const int width = m_image->getWidth ();
65+ const int height = m_image->getHeight ();
66+ const int frames = m_image->getNumberOfFrames ();
67+
68+ Vector3f spacing = Vector3f::Ones ();
69+ if (m_useFramerate && getFramerate () == -1 ) {
70+ // Use stored framerate
71+ OFString cineRate;
72+ OFCondition status = m_dataset->findAndGetOFString (DCM_CineRate, cineRate, 0 );
73+ if (status.good ())
74+ setFramerate (std::stoi (cineRate.c_str ()));
75+ }
76+
77+ // Get pixel spacing and ROI information from ultrasound roi sequence
78+ DcmElement *roiSequenceElement;
79+ m_dataset->findAndGetElement (DCM_SequenceOfUltrasoundRegions, roiSequenceElement);
80+
81+ Vector2i ROIOffset;
82+ Vector2i ROISize;
83+ bool ROIfound = false ;
84+ if (roiSequenceElement && roiSequenceElement->ident () == EVR_SQ) {
85+ DcmSequenceOfItems *roiSequence = OFstatic_cast (DcmSequenceOfItems *, roiSequenceElement);
86+
87+ int i = 0 ;
88+ DcmItem *roiItem = roiSequence->getItem (i);
89+
90+ long int x, y, x1, y1;
91+ roiItem->findAndGetLongInt (DCM_RegionLocationMinX0, x);
92+ roiItem->findAndGetLongInt (DCM_RegionLocationMinY0, y);
93+ roiItem->findAndGetLongInt (DCM_RegionLocationMaxX1, x1);
94+ roiItem->findAndGetLongInt (DCM_RegionLocationMaxY1, y1);
95+ Float64 spacingX, spacingY;
96+ roiItem->findAndGetFloat64 (DCM_PhysicalDeltaX, spacingX, 0 );
97+ roiItem->findAndGetFloat64 (DCM_PhysicalDeltaY, spacingY, 0 );
98+ spacing.x () = spacingX;
99+ spacing.y () = spacingY;
100+ ROIOffset = Vector2i (x, y);
101+ ROISize = Vector2i (x1 - x, y1 - y);
102+ ROIfound = true ;
103+ }
104+
105+ std::cout << " size: " << width << " " << height << " " << frames << std::endl;
106+
107+ auto previousTime = std::chrono::high_resolution_clock::now ();
108+ while (true ) {
109+ bool pause = getPause ();
110+ if (pause)
111+ waitForUnpause ();
112+ pause = getPause ();
113+
114+ {
115+ std::unique_lock<std::mutex> lock (m_stopMutex);
116+ if (m_stop) {
117+ m_streamIsStarted = false ;
118+ m_firstFrameIsInserted = false ;
119+ break ;
120+ }
121+ }
122+ int frameNr = getCurrentFrameIndex ();
123+ auto frameData = make_uninitialized_unique<uchar>(3 *width*height);
124+ m_image->getOutputData (frameData.get (), 3 *width*height, 0 , frameNr);
125+ auto imageFrame = Image::create (width, height, TYPE_UINT8, 3 , std::move (frameData));
126+ imageFrame->setSpacing (spacing);
127+ if (m_convertToGrayscale) {
128+ imageFrame = ColorToGrayscale::create ()->connect (imageFrame)->runAndGetOutputData <Image>();
129+ }
130+ if (m_cropToROI && ROIfound) {
131+ imageFrame = imageFrame->crop (ROIOffset, ROISize);
132+ }
133+ if (!pause) {
134+ if (m_framerate > 0 ) {
135+ std::chrono::duration<float , std::milli> passedTime = std::chrono::high_resolution_clock::now () - previousTime;
136+ std::chrono::duration<int , std::milli> sleepFor (1000 / m_framerate - (int )passedTime.count ());
137+ if (sleepFor.count () > 0 )
138+ std::this_thread::sleep_for (sleepFor);
139+ previousTime = std::chrono::high_resolution_clock::now ();
140+ }
141+ getCurrentFrameIndexAndUpdate (); // Update index
142+ }
143+
144+ try {
145+ addOutputData (0 , imageFrame);
146+ frameAdded ();
147+ if (frameNr == getNrOfFrames ()) {
148+ throw FileNotFoundException ();
149+ }
150+ } catch (FileNotFoundException &e) {
151+ break ;
152+ } catch (ThreadStopped &e) {
153+ break ;
154+ }
155+ }
156+ }
157+
158+ int DicomMultiFrameStreamer::getNrOfFrames () {
159+ if (!m_image)
160+ load ();
161+ return m_image->getNumberOfFrames ();
162+ }
163+
164+ DicomMultiFrameStreamer::DicomMultiFrameStreamer () {
165+
166+ }
167+
168+ DicomMultiFrameStreamer::~DicomMultiFrameStreamer () {
169+ DJDecoderRegistration::cleanup ();
170+ }
171+ }
0 commit comments