fw4spl
DicomSeriesWriter.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwGdcmIO/helper/DicomSeriesWriter.hpp"
8 
9 #include "fwGdcmIO/helper/DicomAnonymizer.hpp"
10 
11 #include <fwCore/base.hpp>
12 
13 #include <fwDataIO/writer/registry/macros.hpp>
14 
15 #include <fwDataTools/helper/Array.hpp>
16 
17 #include <fwJobs/IJob.hpp>
18 #include <fwJobs/Observer.hpp>
19 
20 #include <fwMedData/DicomSeries.hpp>
21 
22 #include <fwZip/WriteZipArchive.hpp>
23 
24 #include <boost/foreach.hpp>
25 
26 fwDataIOWriterRegisterMacro( ::fwGdcmIO::helper::DicomSeriesWriter );
27 
28 namespace fwGdcmIO
29 {
30 namespace helper
31 {
32 
33 //------------------------------------------------------------------------------
34 
36  ::fwData::location::enableFolder< ::fwDataIO::writer::IObjectWriter >(this),
37  m_writeCount(0),
38  m_job(::fwJobs::Observer::New("Writing DICOM files"))
39 {
40 }
41 
42 //------------------------------------------------------------------------------
43 
45 {
46  m_anonymizer = anonymizer;
47 }
48 
49 //------------------------------------------------------------------------------
50 
51 void DicomSeriesWriter::setOutputArchive(const ::fwZip::IWriteArchive::sptr& archive, const std::string& subPath)
52 {
53  m_archive = archive;
54  m_subPath = subPath;
55 }
56 
57 //------------------------------------------------------------------------------
58 
60 {
61  if(m_archive)
62  {
63  this->processWriteArchive();
64  }
65  else
66  {
67  this->processWrite();
68  }
69 }
70 
71 //------------------------------------------------------------------------------
72 
73 std::string DicomSeriesWriter::getFilename(const size_t& instanceIndex)
74 {
75  std::stringstream ss;
76  ss << std::setfill('0') << std::setw(7);
77  if(m_anonymizer)
78  {
79  ss << m_anonymizer->getNextIndex();
80  }
81  else
82  {
83  ss << instanceIndex;
84  }
85 
86  return ss.str();
87 }
88 
89 //------------------------------------------------------------------------------
90 
91 void DicomSeriesWriter::processStream(std::istream& inputStream, std::ostream& outputStream)
92 {
93  if(m_anonymizer)
94  {
95  m_anonymizer->anonymize(inputStream, outputStream);
96  }
97  else
98  {
99  outputStream << inputStream.rdbuf();
100  }
101 }
102 
103 //------------------------------------------------------------------------------
104 
106 {
107  ::fwMedData::DicomSeries::csptr dicomSeries = this->getConcreteObject();
108 
109  // Create folder
110  ::boost::filesystem::path folder = this->getFolder();
111 
112  if(m_writeCount)
113  {
114  std::stringstream ss;
115  ss << "fwGdcmIO" << std::setfill('0') << std::setw(3) << m_writeCount;
116  folder /= ss.str();
117  }
118 
119  if (!::boost::filesystem::exists(folder))
120  {
121  ::boost::filesystem::create_directories(folder);
122  }
123 
124  std::size_t nbInstances = dicomSeries->getNumberOfInstances();
125 
126  m_job->setTotalWorkUnits(nbInstances);
127  unsigned int count = 0;
128 
129  // Write binary files
130  for(const auto& value : dicomSeries->getDicomContainer())
131  {
132  if(m_job->cancelRequested())
133  {
134  return;
135  }
136 
137  const std::string filename = this->getFilename(value.first);
138 
139  const ::fwMemory::BufferObject::sptr sourceBuffer = value.second;
140  ::fwMemory::BufferObject::Lock sourceLocker(sourceBuffer);
141  const ::fwMemory::BufferManager::StreamInfo& streamInfo = sourceBuffer->getStreamInfo();
142  SPTR(std::istream) stream = streamInfo.stream;
143 
144  const ::boost::filesystem::path& dest_dir = m_anonymizer ? folder/m_subPath : folder;
145 
146  if(!::boost::filesystem::exists(dest_dir))
147  {
148  ::boost::filesystem::create_directories(dest_dir);
149  }
150 
151  const ::boost::filesystem::path& dest_file = dest_dir / filename;
152 
153  ::boost::filesystem::ofstream fs(dest_file, std::ios::binary|std::ios::trunc);
154  FW_RAISE_IF("Can't open '" << dest_file.string() << "' for write.", !fs.good());
155 
156  this->processStream(*(stream.get()), fs);
157 
158  m_job->doneWork(++count);
159  }
160 
161  m_job->finish();
162  m_writeCount++;
163 }
164 
165 //------------------------------------------------------------------------------
166 
168 {
169  SLM_ASSERT("Output archive shall be set", m_archive);
170 
171  ::fwMedData::DicomSeries::csptr dicomSeries = this->getConcreteObject();
172 
173  const size_t nbInstances = dicomSeries->getNumberOfInstances();
174  unsigned int count = 0;
175 
176  m_job->setTotalWorkUnits(nbInstances);
177 
178  for(const auto& value : dicomSeries->getDicomContainer())
179  {
180  if(m_job->cancelRequested())
181  {
182  break;
183  }
184 
185  const std::string filename = this->getFilename(value.first);
186 
187  const ::fwMemory::BufferObject::sptr sourceBuffer = value.second;
188  ::fwMemory::BufferObject::Lock sourceLocker(sourceBuffer);
189  const ::fwMemory::BufferManager::StreamInfo& streamInfo = sourceBuffer->getStreamInfo();
190  SPTR(std::istream) stream = streamInfo.stream;
191 
192  const ::boost::filesystem::path& dest_dir =
193  m_anonymizer ? m_subPath : "";
194 
195  const ::boost::filesystem::path& dest_file = dest_dir / filename;
196  SPTR(std::ostream) fs = m_archive->createFile(dest_file);
197  FW_RAISE_IF("Can't open '" << dest_file.string() << "' for write.", !fs->good());
198 
199  this->processStream(*(stream.get()), *fs);
200 
201  m_job->doneWork(++count);
202  }
203 
204  m_job->done();
205  m_job->finish();
206  ++m_writeCount;
207 }
208 
209 //------------------------------------------------------------------------------
210 
212 {
213  return "";
214 }
215 
216 //------------------------------------------------------------------------------
217 
219 {
220  return m_job;
221 }
222 
223 //------------------------------------------------------------------------------
224 
225 } // namespace helper
226 } // namespace fwGdcmIO
#define SPTR(_cls_)
ILocation::PathType getFolder()
Get folder filesystem path.
Definition: Folder.hpp:99
FWGDCMIO_API void write() override
Write the image series in DICOM format.
void processWrite()
Process write with Standard output stream.
std::string getFilename(const size_t &instanceIndex)
Compute DICOM filename according to anonymizer or return default filename.
void processStream(std::istream &inputStream, std::ostream &outputStream)
Process inputStream to outputStream with anonymisation management.
Write a DicomSeries in DICOM format.
This class is an interface for class managing job.
Definition: IJob.hpp:28
std::string m_subPath
Optional subPath (related to write archive.
This namespace fwDataIO contains reader and writer for several framework&#39;s data.
virtual std::shared_ptr< const DataType > getConcreteObject() const
m_object getter.
FWGDCMIO_API std::string extension() override
Return an empty string.
std::shared_ptr< ::fwJobs::Observer > m_job
Job observer.
Key class used to restrict access to Object construction. See http://www.drdobbs.com/184402053.
base class for BufferObject Lock
The namespace fwGdcmIO contains reader, writer and helper for dicom data.
void processWriteArchive()
Process write on archive.
FWGDCMIO_API void setAnonymizer(const std::shared_ptr< helper::DicomAnonymizer > &anonymizer)
Defines optional anonymizer.
This class contains helpers to anonymize dicom files on filesystem. Anonymization is performed accord...
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
FWGDCMIO_API DicomSeriesWriter(::fwDataIO::writer::IObjectWriter::Key key)
Constructor. Does nothing.
std::shared_ptr< ::fwZip::IWriteArchive > m_archive
Optionnal output archive.
Contains the representation of the data objects used in the framework.
FWGDCMIO_API std::shared_ptr< ::fwJobs::IJob > getJob() const override
Get job observer.
FWGDCMIO_API void setOutputArchive(const std::shared_ptr< ::fwZip::IWriteArchive > &archive, const std::string &subPath="")
Defines output archive for DICOM files.
std::shared_ptr< DicomAnonymizer > m_anonymizer
Optionnal anonymiser.
This namespace fwJobs provides jobs management.