fw4spl
ImageRGBLookupLazyStream.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 "fwDcmtkIO/reader/rgblookup/ImageRGBLookupLazyStream.hpp"
8 
9 #include "fwDcmtkIO/reader/rgblookup/ImageRGBLookupLazyReader.hpp"
10 
11 #include <boost/filesystem/operations.hpp>
12 #include <boost/filesystem/path.hpp>
13 #include <boost/foreach.hpp>
14 #include <boost/make_shared.hpp>
15 
16 #include <dcmtk/dcmdata/dcistrmb.h>
17 
18 namespace fwDcmtkIO
19 {
20 namespace reader
21 {
22 namespace rgblookup
23 {
24 
25 //------------------------------------------------------------------------------
26 
27 ImageRGBLookupLazySource::ImageRGBLookupLazySource( ImageRGBLookupLazyInformation::sptr dcmInfo ) :
28  m_dcmInfo( dcmInfo )
29 {
30  SLM_ASSERT( "ImageRGBLookupLazySource needs at least one dicom item to read an image.",
31  !dcmInfo->m_dicomSeries->getDicomContainer().empty());
32 
33  m_frameSize = m_dcmInfo->m_rows * m_dcmInfo->m_columns * m_dcmInfo->m_imageType.sizeOf() * 3;
34  m_currentFrame = 0;
35  m_currentPosition = 0;
36  m_currentDicom = m_dcmInfo->m_dicomSeries->getDicomContainer().begin();
37 
38  // Read instance
39  DcmFileFormat fileFormat;
40  OFCondition status;
41  DcmDataset* dataset;
42 
43  // Open first instance
44  const auto firstItem = m_dcmInfo->m_dicomSeries->getDicomContainer().begin();
45  const ::fwMemory::BufferObject::sptr bufferObj = firstItem->second;
46  const size_t buffSize = bufferObj->getSize();
47  const std::string dicomPath = bufferObj->getStreamInfo().fsFile.string();
48  ::fwMemory::BufferObject::Lock lock(bufferObj);
49  char* buffer = static_cast< char* >( lock.getBuffer() );
50 
51  DcmInputBufferStream is;
52  is.setBuffer(buffer, offile_off_t(buffSize));
53  is.setEos();
54 
55  fileFormat.transferInit();
56  if (!fileFormat.read(is).good())
57  {
58  FW_RAISE("Unable to read Dicom file '"<< dicomPath <<"' "<<
59  "(slice: '" << firstItem->first << "')");
60  }
61 
62  fileFormat.loadAllDataIntoMemory();
63  fileFormat.transferEnd();
64 
65  dataset = fileFormat.getDataset();
66 
67  if(m_dcmInfo->m_bitsAllocated == 16)
68  {
69  const Uint16* redLookup;
70  const Uint16* greenLookup;
71  const Uint16* blueLookup;
72  // Those values are freed by the dataset destructor
73  dataset->findAndGetUint16Array(DCM_RedPaletteColorLookupTableData, redLookup);
74  dataset->findAndGetUint16Array(DCM_GreenPaletteColorLookupTableData, greenLookup);
75  dataset->findAndGetUint16Array(DCM_BluePaletteColorLookupTableData, blueLookup);
76  m_redLookup = (void*) redLookup;
77  m_greenLookup = (void*) greenLookup;
78  m_blueLookup = (void*) blueLookup;
79  }
80  else
81  {
82  const Uint8* redLookup;
83  const Uint8* greenLookup;
84  const Uint8* blueLookup;
85  // Those values are freed by the dataset destructor
86  dataset->findAndGetUint8Array(DCM_RedPaletteColorLookupTableData, redLookup);
87  dataset->findAndGetUint8Array(DCM_GreenPaletteColorLookupTableData, greenLookup);
88  dataset->findAndGetUint8Array(DCM_BluePaletteColorLookupTableData, blueLookup);
89  m_redLookup = (void*) redLookup;
90  m_greenLookup = (void*) greenLookup;
91  m_blueLookup = (void*) blueLookup;
92  }
93 
94  if(m_dcmInfo->m_bitsAllocated == 16)
95  {
97  m_dcmInfo->m_rows, m_dcmInfo->m_columns,
98  m_currentDicom->second,
99  (Uint16*)m_redLookup,
100  (Uint16*)m_greenLookup, (Uint16*)m_blueLookup,
101  m_dcmInfo->m_pixelValueBitsAllocated));
102  }
103  else
104  {
106  m_dcmInfo->m_rows, m_dcmInfo->m_columns,
107  m_currentDicom->second,
108  (Uint8*)m_redLookup,
109  (Uint8*)m_greenLookup, (Uint8*)m_blueLookup,
110  m_dcmInfo->m_pixelValueBitsAllocated));
111  }
112 }
113 
114 //------------------------------------------------------------------------------
115 
116 std::streamsize ImageRGBLookupLazySource::read(char* stream, std::streamsize size)
117 {
118  std::streamsize result = -1;
119 
120  // Load new frame
121  if(m_currentPosition + size > m_frameSize)
122  {
123  // Copy remaining bytes
124  const size_t remainingBytes = m_frameSize - m_currentPosition;
125  const size_t extraBytes = size - remainingBytes;
126 
127  if(remainingBytes > 0)
128  {
129  memcpy(stream, m_frame + m_currentPosition, remainingBytes);
130  result = remainingBytes;
131  }
132 
133  // Change frame
134  delete m_frame;
135  ++m_currentFrame;
136  ++m_currentDicom;
137  m_currentPosition = 0;
138 
139  // If there is more frame
140  if(m_currentDicom != m_dcmInfo->m_dicomSeries->getDicomContainer().end())
141  {
142  // Copy extra bytes from the new frame
143  if(extraBytes > 0)
144  {
145  if(m_dcmInfo->m_bitsAllocated == 16)
146  {
147  m_frame =
150  m_dcmInfo->m_rows, m_dcmInfo->m_columns,
151  m_currentDicom->second,
152  (Uint16*)m_redLookup,
153  (Uint16*)m_greenLookup,
154  (Uint16*)m_blueLookup,
155  m_dcmInfo->m_pixelValueBitsAllocated));
156  }
157  else
158  {
159  m_frame =
162  m_dcmInfo->m_rows, m_dcmInfo->m_columns,
163  m_currentDicom->second,
164  (Uint8*)m_redLookup,
165  (Uint8*)m_greenLookup,
166  (Uint8*)m_blueLookup,
167  m_dcmInfo->m_pixelValueBitsAllocated));
168  }
169 
170  memcpy(stream, m_frame + m_currentPosition, extraBytes);
171  m_currentPosition += extraBytes;
172  result = remainingBytes + extraBytes;
173  }
174  }
175  else
176  {
177  SLM_TRACE("Reading process over.");
178  }
179  }
180  // Copy bytes from the loaded frame
181  else
182  {
183  memcpy(stream, m_frame + m_currentPosition, size);
184  m_currentPosition += size;
185  result = size;
186 
187  if(m_currentDicom->second == m_dcmInfo->m_dicomSeries->getDicomContainer().rbegin()->second &&
188  m_currentPosition == m_frameSize)
189  {
190  SLM_TRACE("Reading process over.");
191  delete m_frame;
192  }
193  }
194  return result;
195 }
196 
197 //------------------------------------------------------------------------------
198 
199 ImageRGBLookupLazyStream::ImageRGBLookupLazyStream( ImageRGBLookupLazyInformation::sptr dcmInfo ) :
200  m_dcmInfo( dcmInfo )
201 {
202 }
203 
204 //------------------------------------------------------------------------------
205 
207 {
208  SPTR(::boost::iostreams::stream<ImageRGBLookupLazySource>) is
209  = std::make_shared< ::boost::iostreams::stream<ImageRGBLookupLazySource> >( m_dcmInfo );
210  return is;
211 }
212 
213 //------------------------------------------------------------------------------
214 
215 } //rgblookup
216 } //reader
217 } //fwDcmtkIO
#define SPTR(_cls_)
ImageRGBLookupLazyStream(ImageRGBLookupLazyInformation::sptr dcmInfo)
Constructor. Builds the fwMemory::stream::in::IFactory with few dicom information.
std::shared_ptr< std::istream > get()
Returns the istream on dicom image buffer.
base class for BufferObject Lock
LockBase< T >::BufferType getBuffer() const
Returns BufferObject&#39;s buffer pointer.
std::streamsize read(char *stream, std::streamsize size)
Method to read n bytes in dicom buffer and write it in s.
Class used to perform a lazy reading of dicom images with fw4spl system.
#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
fwDcmtkIO contains classes used to pull Dicom images from a pacs using dcmtk library.
Definition: Codec.hpp:12
static void * createInstanceBuffer(unsigned int rows, unsigned int columns, const ::fwMemory::BufferObject::sptr &instance, const T *redLookup, const T *greenLookup, const T *blueLookup, unsigned short pixelValueBitsAllocated)
Create an instance buffer according to the image type. The template T is used to determine color form...
#define SLM_TRACE(message)
Definition: spyLog.hpp:228
ImageRGBLookupLazyInformation::sptr m_dcmInfo
To conserve dicom information.
ImageRGBLookupLazySource(ImageRGBLookupLazyInformation::sptr dcmInfo)
Constructor.