forked from BRAINSia/BRAINSTools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDebugImageViewerClient.h
309 lines (285 loc) · 9.46 KB
/
DebugImageViewerClient.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/*=========================================================================
*
* Copyright SINAPSE: Scalable Informatics for Neuroscience, Processing and Software Engineering
* The University of Iowa
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*=========================================================================*/
#if !defined( DebugImageViewerClient_h )
#define DebugImageViewerClient_h
#include "BRAINSCommonLib.h"
#ifdef USE_DebugImageViewer
#include <string>
#include <itksys/SystemTools.hxx>
#include <vtkClientSocket.h>
#include <itkImage.h>
#include <itkRescaleIntensityImageFilter.h>
#include <itkSpatialOrientation.h>
#include <itkSpatialOrientationAdapter.h>
#include <itkOrientImageFilter.h>
#include <cstdio>
// #include <itkIO.h>
// #include <itkIO2.h>
namespace DebugImageViewerUtil
{
typedef itk::SpatialOrientationAdapter SOAdapterType;
typedef SOAdapterType::DirectionType DirectionType;
template <class InputImageType, class OutputImageType>
typename OutputImageType::Pointer
ScaleAndCast(const typename InputImageType::Pointer & image,
const typename OutputImageType::PixelType OutputMin,
const typename OutputImageType::PixelType OutputMax)
{
typedef itk::RescaleIntensityImageFilter<InputImageType,
OutputImageType> R2CRescaleFilterType;
typename R2CRescaleFilterType::Pointer RealToProbMapCast
= R2CRescaleFilterType::New();
RealToProbMapCast->SetOutputMinimum(OutputMin);
RealToProbMapCast->SetOutputMaximum(OutputMax);
RealToProbMapCast->SetInput(image);
try
{
RealToProbMapCast->Update();
}
catch( itk::ExceptionObject & e )
{
throw;
}
typename OutputImageType::Pointer returnScaled = RealToProbMapCast->GetOutput();
return returnScaled;
}
/** AllocateImageFromExample creates and allocates an image of the type OutputImageType,
* using TemplateImageType as the source of size and spacing...
*
*/
template <class TemplateImageType, class OutputImageType>
typename OutputImageType::Pointer
AllocateImageFromExample(
const typename TemplateImageType::Pointer & TemplateImage)
{
typename OutputImageType::Pointer rval = OutputImageType::New();
rval->CopyInformation(TemplateImage);
rval->SetRegions( TemplateImage->GetLargestPossibleRegion() );
rval->Allocate();
return rval;
}
template <class ImageType>
typename ImageType::Pointer
OrientImage(typename ImageType::Pointer & inputImage,
itk::SpatialOrientation::ValidCoordinateOrientationFlags orient)
{
typename itk::OrientImageFilter<ImageType, ImageType>::Pointer orienter
= itk::OrientImageFilter<ImageType, ImageType>::New();
orienter->SetDesiredCoordinateOrientation(orient);
orienter->UseImageDirectionOn();
orienter->SetInput(inputImage);
orienter->Update();
typename ImageType::Pointer returnval
= orienter->GetOutput();
returnval->DisconnectPipeline();
orienter->ReleaseDataFlagOn();
return returnval;
}
template <class ImageType>
typename ImageType::Pointer
OrientImage(typename ImageType::Pointer & inputImage,
const typename ImageType::DirectionType & dirCosines)
{
return OrientImage<ImageType>
( inputImage,
SOAdapterType().FromDirectionCosines(
dirCosines) );
}
}
class DebugImageViewerClient
{
public:
DebugImageViewerClient() : m_Sock(0), m_Enabled(false), m_PromptUser(false)
{
}
~DebugImageViewerClient()
{
if( m_Sock )
{
this->m_Sock->CloseSocket();
this->m_Sock->Delete();
}
}
void SetPromptUser(bool x)
{
m_PromptUser = x;
}
/** Send an image to the viewer */
template <class ImageType>
void SendImage(const typename ImageType::Pointer & image,
unsigned viewIndex = 0)
{
this->Send<ImageType>(image, viewIndex);
if( this->m_PromptUser )
{
//
// make sure we connect to interactive input
FILE *in = fopen("/dev/tty", "r");
std::cerr << ">>>>>>>>>Hit enter to continue " << std::flush;
char buf[256];
fgets(buf, 255, in);
fclose(in);
}
}
/** Send one component of a vector image to the viewer */
template <class ImageType>
void SendImage(const typename ImageType::Pointer & image,
unsigned viewIndex,
unsigned vectorIndex)
{
this->Send<ImageType>(image, viewIndex, vectorIndex);
if( this->m_PromptUser )
{
//
// make sure we connect to interactive input
FILE *in = fopen("/dev/tty", "r");
std::cerr << ">>>>>>>>>Hit enter to continue " << std::flush;
char buf[256];
fgets(buf, 255, in);
fclose(in);
}
}
/** enable sending of images to the viewer */
void SetEnabled(bool enabled)
{
this->m_Enabled = enabled;
if( enabled )
{
this->_Init();
}
else if( this->m_Sock != 0 )
{
this->m_Sock->CloseSocket();
this->m_Sock->Delete();
this->m_Sock = 0;
}
}
bool Enabled()
{
return m_Enabled;
}
private:
void _Init()
{
this->m_Sock = vtkClientSocket::New();
this->m_Sock->ConnectToServer("localhost", 19345);
}
template <class ImageType>
void Send(const typename ImageType::Pointer & image, unsigned int viewIndex);
template <class ImageType>
void Send(const typename ImageType::Pointer & image, unsigned int viewIndex, unsigned int vectorIndex);
private:
vtkClientSocket *m_Sock;
bool m_Enabled;
bool m_PromptUser;
};
template <class ImageType>
void
DebugImageViewerClient::Send(const typename ImageType::Pointer & image, unsigned int viewIndex)
{
if( !this->Enabled() )
{
return;
}
typedef itk::Image<unsigned char, 3> TransferImageType;
typedef TransferImageType::SizeType SizeType;
typedef TransferImageType::SpacingType SpacingType;
typedef TransferImageType::PointType PointType;
//
// make sure image is in a known image type
TransferImageType::Pointer xferImage
= DebugImageViewerUtil::ScaleAndCast<ImageType, TransferImageType>(image, 0, 255);
typename TransferImageType::DirectionType DesiredDirectionCos;
DesiredDirectionCos[0][0] = 1; DesiredDirectionCos[0][1] = 0;
DesiredDirectionCos[0][2] = 0;
DesiredDirectionCos[1][0] = 0; DesiredDirectionCos[1][1] = 1;
DesiredDirectionCos[1][2] = 0;
DesiredDirectionCos[2][0] = 0; DesiredDirectionCos[2][1] = 0;
DesiredDirectionCos[2][2] = 1;
xferImage = DebugImageViewerUtil::OrientImage<TransferImageType>(xferImage,
DesiredDirectionCos);
//
// get size
SizeType size = xferImage->GetLargestPossibleRegion().GetSize();
unsigned int bufferSize = size[0] * size[1] * size[2]
* sizeof( typename TransferImageType::PixelType );
// get spacing
SpacingType spacing = xferImage->GetSpacing();
// get orientation
itk::SpatialOrientation::ValidCoordinateOrientationFlags orientation
= itk::SpatialOrientationAdapter().FromDirectionCosines
( xferImage->GetDirection() );
// get origin
PointType origin = xferImage->GetOrigin();
for( unsigned int i = 0; i < 3; i++ )
{
this->m_Sock->Send( &size[i], sizeof( SizeType::SizeValueType ) );
}
for( unsigned int i = 0; i < 3; i++ )
{
this->m_Sock->Send( &spacing[i], sizeof( SpacingType::ValueType ) );
}
this->m_Sock->Send( &orientation, sizeof( orientation ) );
// send origin
for( unsigned int i = 0; i < 3; i++ )
{
double x = origin[i];
this->m_Sock->Send( &x, sizeof( double ) );
}
this->m_Sock->Send( &viewIndex, sizeof( viewIndex ) );
// transfer image pixels
this->m_Sock->Send(xferImage->GetBufferPointer(),
bufferSize);
// std::cerr << "DebugImageViewer: size = " << size
// << " spacing = " << spacing << std::endl
// << "orientation = " << orientation
// << " viewIndex = " << " bufferSize " << bufferSize
// << std::endl;
// std::cerr.flush();
}
template <class ImageType>
void
DebugImageViewerClient::Send(const typename ImageType::Pointer & image,
unsigned int viewIndex,
unsigned int vectorIndex)
{
if( !this->Enabled() )
{
return;
}
//
// assume ImageType is a vector type.
typedef typename ImageType::PixelType::ComponentType ScalarPixelType;
typedef typename itk::Image<ScalarPixelType, ImageType::ImageDimension>
ScalarImageType;
typename ScalarImageType::Pointer scalarImage
= DebugImageViewerUtil::AllocateImageFromExample<ImageType, ScalarImageType>
(image);
typename itk::ImageRegionConstIterator<ImageType>
sourceIt( image, image->GetLargestPossibleRegion() );
typename itk::ImageRegionIterator<ScalarImageType>
destIt( scalarImage, scalarImage->GetLargestPossibleRegion() );
for( ; !sourceIt.IsAtEnd(); ++sourceIt, ++destIt )
{
destIt.Set(sourceIt.Get()[vectorIndex]);
}
this->Send<ScalarImageType>(scalarImage, viewIndex);
}
#endif // USE_DebugImageViewer
#endif // DebugImageViewerClient_h