UsTK : Ultrasound ToolKit  version 2.0.1 under development (2024-12-17)
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 
121 template <class ImageType> usSequenceWriter<ImageType>::~usSequenceWriter() { close(); }
122 
127 template <class ImageType> void usSequenceWriter<ImageType>::setFrameRate(double frameRate) { m_frameRate = frameRate; }
128 
133 template <class ImageType> double usSequenceWriter<ImageType>::getFrameRate() const { return m_frameRate; }
134 
139 template <class ImageType> void usSequenceWriter<ImageType>::setSequenceFileName(const std::string &sequenceFileName)
140 {
141  m_sequenceFileName = sequenceFileName;
142  m_headerFileNameIsSet = true;
143 }
144 
152 template <class ImageType> void usSequenceWriter<ImageType>::setImageFileName(const std::string &imageFileName)
153 {
154  // create subdirectory if there is one
155  if (m_headerFileNameIsSet) {
156  std::string relativePathToHeader = vpIoTools::getParent(imageFileName);
157  if (!relativePathToHeader.empty()) {
158  std::string fullDirName = vpIoTools::getParent(m_sequenceFileName) + vpIoTools::path("/") + relativePathToHeader;
159  vpIoTools::makeDirectory(fullDirName);
160  }
161  m_genericImageFileName = imageFileName;
162  m_imageFileNameIsSet = true;
163  }
164 }
165 
170 template <class ImageType> void usSequenceWriter<ImageType>::setFirstFrameIndex(long firstIndex)
171 {
172  m_firstFrame = firstIndex;
173  m_firstFrameIsSet = true;
174 }
175 
180 template <class ImageType> void usSequenceWriter<ImageType>::open(const ImageType &image, uint64_t timestamp)
181 {
182  if (!m_headerFileNameIsSet || !m_imageFileNameIsSet)
183  throw(vpException(vpException::badValue, "file names not set"));
184 
185  // if not first index set, we begin at index 0
186  if (!m_firstFrameIsSet) {
187  m_firstFrame = 0;
188  m_frameCount = 0;
189  m_firstFrameIsSet = true;
190  }
191 
192  // saving the settings for all the sequence
193  m_frame = image;
194 
195  // Reading image
196  char buffer[FILENAME_MAX];
197  snprintf(buffer, FILENAME_MAX, m_genericImageFileName.c_str(), m_frameCount);
198 
199  // case of timestamp to add
200  if (timestamp != 0) {
201  std::vector<std::string> splitted = vpIoTools::splitChain(std::string(buffer), std::string("."));
202  std::string base = splitted.at(0);
203  base.append(std::string(".%lld."));
204  base.append(splitted.at(1));
205  snprintf(buffer, FILENAME_MAX, base.c_str(), timestamp);
206  std::vector<std::string> splittedGeneric =
207  vpIoTools::splitChain(std::string(m_genericImageFileName), std::string("."));
208  m_genericImageFileName = splittedGeneric.at(0) + std::string(".TIMESTAMP.") + splittedGeneric.at(1);
209  }
210 
211  std::string imageFileName = vpIoTools::getParent(m_sequenceFileName) + vpIoTools::path("/") + buffer;
212 
213  vpImageIo::write(image, imageFileName);
214 
215  m_frameCount = m_firstFrame + 1;
216  is_open = true;
217 }
218 
224 template <class ImageType> void usSequenceWriter<ImageType>::close()
225 {
226  throw(vpException(vpException::notImplementedError));
227 }
228 
229 template <> inline void usSequenceWriter<usImageRF2D<unsigned char> >::close()
230 {
231  if (!is_open)
232  return;
233 
234  // saving settings
235  usImageSettingsXmlParser xmlParser;
236  xmlParser.setImageSettings(m_frame.getTransducerRadius(), m_frame.getScanLinePitch(), m_frame.isTransducerConvex(),
237  m_frame.getAxialResolution(), us::RF_2D, m_frame.getSamplingFrequency(),
238  m_frame.getTransmitFrequency());
239  xmlParser.setSequenceFrameRate(m_frameRate);
240  xmlParser.setSequenceStartNumber(m_firstFrame);
241  xmlParser.setSequenceStopNumber(m_frameCount - 1);
242  xmlParser.setImageFileName(m_genericImageFileName);
243  xmlParser.save(m_sequenceFileName);
244  vpXmlParser::cleanup();
245 }
246 
247 template <> inline void usSequenceWriter<usImagePreScan2D<unsigned char> >::close()
248 {
249  if (!is_open)
250  return;
251 
252  // saving settings
253  usImageSettingsXmlParser xmlParser;
254  xmlParser.setImageSettings(m_frame.getTransducerRadius(), m_frame.getScanLinePitch(), m_frame.isTransducerConvex(),
255  m_frame.getAxialResolution(), us::PRESCAN_2D, m_frame.getSamplingFrequency(),
256  m_frame.getTransmitFrequency());
257  xmlParser.setImageType(us::PRESCAN_2D);
258  xmlParser.setSequenceFrameRate(m_frameRate);
259  xmlParser.setSequenceStartNumber(m_firstFrame);
260  xmlParser.setSequenceStopNumber(m_frameCount - 1);
261  xmlParser.setImageFileName(m_genericImageFileName);
262  xmlParser.save(m_sequenceFileName);
263  vpXmlParser::cleanup();
264 }
265 
266 template <> inline void usSequenceWriter<usImagePostScan2D<unsigned char> >::close()
267 {
268  if (!is_open)
269  return;
270 
271  // saving settings
272  usImageSettingsXmlParser xmlParser;
273  xmlParser.setImageSettings(m_frame.getTransducerRadius(), m_frame.getScanLinePitch(), m_frame.isTransducerConvex(),
274  m_frame.getScanLineNumber(), m_frame.getWidthResolution(), m_frame.getHeightResolution(),
275  m_frame.getSamplingFrequency(), m_frame.getTransmitFrequency());
276 
277  xmlParser.setImageType(us::POSTSCAN_2D);
278  xmlParser.setSequenceFrameRate(m_frameRate);
279  xmlParser.setSequenceStartNumber(m_firstFrame);
280  xmlParser.setSequenceStopNumber(m_frameCount - 1);
281  xmlParser.setImageFileName(m_genericImageFileName);
282  xmlParser.save(m_sequenceFileName);
283  vpXmlParser::cleanup();
284 }
285 
291 template <class ImageType> void usSequenceWriter<ImageType>::saveImage(const ImageType &image, uint64_t timestamp)
292 {
293  if (!is_open) {
294  open(image, timestamp);
295  return; // first image has been written by open();
296  }
297 
298  // Writing image
299  char buffer[FILENAME_MAX];
300  snprintf(buffer, FILENAME_MAX, m_genericImageFileName.c_str(), m_frameCount);
301 
302  // case of timestamp to add
303  if (timestamp != 0) {
304  std::vector<std::string> splitted = vpIoTools::splitChain(std::string(buffer), std::string("."));
305  std::string base = splitted.at(0);
306  base.append(std::string(".%lld."));
307  base.append(splitted.at(2));
308  snprintf(buffer, FILENAME_MAX, base.c_str(), timestamp);
309  }
310 
311  std::string imageFileName = vpIoTools::getParent(m_sequenceFileName) + vpIoTools::path("/") + buffer;
312 
313  vpImageIo::write(image, imageFileName);
314 
315  m_frameCount = m_frameCount + 1;
316 }
317 
318 #endif // __usSequenceWriter_h_
Input/output operations between ultrasound image settings and the associated 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