UsTK : Ultrasound ToolKit  version 2.0.1 under development (2023-12-07)
usSequenceWriter.h
1 /****************************************************************************
2  *
3  * This file is part of the ustk software.
4  * Copyright (C) 2016 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ustk with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * This software was developed at:
17  * Inria Rennes - Bretagne Atlantique
18  * Campus Universitaire de Beaulieu
19  * 35042 Rennes Cedex
20  * France
21  *
22  * If you have questions regarding the use of this file, please contact
23  * Inria at ustk@inria.fr
24  *
25  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27  *
28  * Authors:
29  * Marc Pouliquen
30  *
31  *****************************************************************************/
32 
40 #ifndef __usSequenceWriter_h_
41 #define __usSequenceWriter_h_
42 
43 #include <algorithm>
44 #include <cstring>
45 #include <iostream>
46 #include <vector>
47 
48 #include <visp3/core/vpDebug.h>
49 #include <visp3/core/vpException.h>
50 #include <visp3/core/vpImage.h>
51 #include <visp3/io/vpImageIo.h>
52 
53 #include <visp3/ustk_core/usImageIo.h>
54 #include <visp3/ustk_core/usImageSettingsXmlParser.h>
55 
63 template <class ImageType> class usSequenceWriter
64 {
65 public:
67  virtual ~usSequenceWriter();
68 
69  void close();
70 
71  double getFrameRate() const;
72 
73  void saveImage(const ImageType &image, uint64_t timestamp = 0);
74 
75  void setFirstFrameIndex(long firstIndex);
76  void setFrameRate(double frameRate);
77  void setImageFileName(const std::string &imageFileName);
78  void setSequenceFileName(const std::string &sequenceFileName);
79 
80 private:
82  ImageType m_frame;
83 
85  double m_frameRate;
86 
88  long m_firstFrame;
89  bool m_firstFrameIsSet;
91  long m_frameCount;
92 
94  std::string m_sequenceFileName;
95  std::string m_genericImageFileName;
96  bool m_headerFileNameIsSet;
97  bool m_imageFileNameIsSet;
98 
100  bool is_open;
101 
102  void open(const ImageType &image, uint64_t timestamp = 0);
103 };
104 
105 /****************************************************************************
106 * Template implementations.
107 ****************************************************************************/
108 
112 template <class ImageType>
114  : m_frame(), m_frameRate(0.0), m_firstFrame(0), m_firstFrameIsSet(false), m_frameCount(0), m_sequenceFileName(""),
115  m_genericImageFileName(""), m_headerFileNameIsSet(false), m_imageFileNameIsSet(false), is_open(false)
116 {
117 }
118 
122 template <class ImageType> usSequenceWriter<ImageType>::~usSequenceWriter() { close(); }
123 
128 template <class ImageType> void usSequenceWriter<ImageType>::setFrameRate(double frameRate) { m_frameRate = frameRate; }
129 
134 template <class ImageType> double usSequenceWriter<ImageType>::getFrameRate() const { return m_frameRate; }
135 
140 template <class ImageType> void usSequenceWriter<ImageType>::setSequenceFileName(const std::string &sequenceFileName)
141 {
142  m_sequenceFileName = sequenceFileName;
143  m_headerFileNameIsSet = true;
144 }
145 
153 template <class ImageType> void usSequenceWriter<ImageType>::setImageFileName(const std::string &imageFileName)
154 {
155  // create subdirectory if there is one
156  if (m_headerFileNameIsSet) {
157  std::string relativePathToHeader = vpIoTools::getParent(imageFileName);
158  if (!relativePathToHeader.empty()) {
159  std::string fullDirName = vpIoTools::getParent(m_sequenceFileName) + vpIoTools::path("/") + relativePathToHeader;
160  vpIoTools::makeDirectory(fullDirName);
161  }
162  m_genericImageFileName = imageFileName;
163  m_imageFileNameIsSet = true;
164  }
165 }
166 
171 template <class ImageType> void usSequenceWriter<ImageType>::setFirstFrameIndex(long firstIndex)
172 {
173  m_firstFrame = firstIndex;
174  m_firstFrameIsSet = true;
175 }
176 
181 template <class ImageType> void usSequenceWriter<ImageType>::open(const ImageType &image, uint64_t timestamp)
182 {
183  if (!m_headerFileNameIsSet || !m_imageFileNameIsSet)
184  throw(vpException(vpException::badValue, "file names not set"));
185 
186  // if not first index set, we begin at index 0
187  if (!m_firstFrameIsSet) {
188  m_firstFrame = 0;
189  m_frameCount = 0;
190  m_firstFrameIsSet = true;
191  }
192 
193  // saving the settings for all the sequence
194  m_frame = image;
195 
196  // Reading image
197  char buffer[FILENAME_MAX];
198  sprintf(buffer, m_genericImageFileName.c_str(), m_frameCount);
199 
200  // case of timestamp to add
201  if (timestamp != 0) {
202  std::vector<std::string> splitted = vpIoTools::splitChain(std::string(buffer), std::string("."));
203  std::string base = splitted.at(0);
204  base.append(std::string(".%lld."));
205  base.append(splitted.at(1));
206  sprintf(buffer, base.c_str(), timestamp);
207  std::vector<std::string> splittedGeneric =
208  vpIoTools::splitChain(std::string(m_genericImageFileName), std::string("."));
209  m_genericImageFileName = splittedGeneric.at(0) + std::string(".TIMESTAMP.") + splittedGeneric.at(1);
210  }
211 
212  std::string imageFileName = vpIoTools::getParent(m_sequenceFileName) + vpIoTools::path("/") + buffer;
213 
214  vpImageIo::write(image, imageFileName);
215 
216  m_frameCount = m_firstFrame + 1;
217  is_open = true;
218 }
219 
225 template <class ImageType> void usSequenceWriter<ImageType>::close()
226 {
227  throw(vpException(vpException::notImplementedError));
228 }
229 
230 template <> inline void usSequenceWriter<usImageRF2D<unsigned char> >::close()
231 {
232  if (!is_open)
233  return;
234 
235  // saving settings
236  usImageSettingsXmlParser xmlParser;
237  xmlParser.setImageSettings(m_frame.getTransducerRadius(), m_frame.getScanLinePitch(), m_frame.isTransducerConvex(),
238  m_frame.getAxialResolution(), us::RF_2D, m_frame.getSamplingFrequency(),
239  m_frame.getTransmitFrequency());
240  xmlParser.setSequenceFrameRate(m_frameRate);
241  xmlParser.setSequenceStartNumber(m_firstFrame);
242  xmlParser.setSequenceStopNumber(m_frameCount - 1);
243  xmlParser.setImageFileName(m_genericImageFileName);
244  xmlParser.save(m_sequenceFileName);
245  vpXmlParser::cleanup();
246 }
247 
248 template <> inline void usSequenceWriter<usImagePreScan2D<unsigned char> >::close()
249 {
250  if (!is_open)
251  return;
252 
253  // saving settings
254  usImageSettingsXmlParser xmlParser;
255  xmlParser.setImageSettings(m_frame.getTransducerRadius(), m_frame.getScanLinePitch(), m_frame.isTransducerConvex(),
256  m_frame.getAxialResolution(), us::PRESCAN_2D, m_frame.getSamplingFrequency(),
257  m_frame.getTransmitFrequency());
258  xmlParser.setImageType(us::PRESCAN_2D);
259  xmlParser.setSequenceFrameRate(m_frameRate);
260  xmlParser.setSequenceStartNumber(m_firstFrame);
261  xmlParser.setSequenceStopNumber(m_frameCount - 1);
262  xmlParser.setImageFileName(m_genericImageFileName);
263  xmlParser.save(m_sequenceFileName);
264  vpXmlParser::cleanup();
265 }
266 
267 template <> inline void usSequenceWriter<usImagePostScan2D<unsigned char> >::close()
268 {
269  if (!is_open)
270  return;
271 
272  // saving settings
273  usImageSettingsXmlParser xmlParser;
274  xmlParser.setImageSettings(m_frame.getTransducerRadius(), m_frame.getScanLinePitch(), m_frame.isTransducerConvex(),
275  m_frame.getScanLineNumber(), m_frame.getWidthResolution(), m_frame.getHeightResolution(),
276  m_frame.getSamplingFrequency(), m_frame.getTransmitFrequency());
277 
278  xmlParser.setImageType(us::POSTSCAN_2D);
279  xmlParser.setSequenceFrameRate(m_frameRate);
280  xmlParser.setSequenceStartNumber(m_firstFrame);
281  xmlParser.setSequenceStopNumber(m_frameCount - 1);
282  xmlParser.setImageFileName(m_genericImageFileName);
283  xmlParser.save(m_sequenceFileName);
284  vpXmlParser::cleanup();
285 }
286 
292 template <class ImageType> void usSequenceWriter<ImageType>::saveImage(const ImageType &image, uint64_t timestamp)
293 {
294  if (!is_open) {
295  open(image, timestamp);
296  return; // first image has been written by open();
297  }
298 
299  // Writing image
300  char buffer[FILENAME_MAX];
301  sprintf(buffer, m_genericImageFileName.c_str(), m_frameCount);
302 
303  // case of timestamp to add
304  if (timestamp != 0) {
305  std::vector<std::string> splitted = vpIoTools::splitChain(std::string(buffer), std::string("."));
306  std::string base = splitted.at(0);
307  base.append(std::string(".%lld."));
308  base.append(splitted.at(2));
309  sprintf(buffer, base.c_str(), timestamp);
310  }
311 
312  std::string imageFileName = vpIoTools::getParent(m_sequenceFileName) + vpIoTools::path("/") + buffer;
313 
314  vpImageIo::write(image, imageFileName);
315 
316  m_frameCount = m_frameCount + 1;
317 }
318 
319 #endif // __usSequenceWriter_h_
Input/output operations between ultrasound image settings and the assiciated xml files.
void setImageFileName(const std::string &imageFileName)
void setImageType(us::ImageType image_type)
void setImageSettings(double transducerRadius, double scanLinePitch, bool isTransducerConvex, double axialResolution, us::ImageType image_type, int samplingFrequency, int transmitFrequency)
void setSequenceStartNumber(int sequenceStartNumber)
void setSequenceStopNumber(int sequenceStopNumber)
void setSequenceFrameRate(double sequenceFrameRate)
Writing of sequences of ultrasound images.
void setFrameRate(double frameRate)
void setImageFileName(const std::string &imageFileName)
void setFirstFrameIndex(long firstIndex)
void saveImage(const ImageType &image, uint64_t timestamp=0)
double getFrameRate() const
virtual ~usSequenceWriter()
void setSequenceFileName(const std::string &sequenceFileName)
@ PRESCAN_2D
Definition: us.h:70
@ POSTSCAN_2D
Definition: us.h:72
@ RF_2D
Definition: us.h:68