DICOMAppHelper.h 18.7 KB
Newer Older
Matt Turek's avatar
Matt Turek committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*=========================================================================

  Program:   DICOMParser
  Module:    DICOMAppHelper.h
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2003 Matt Turek
  All rights reserved.
  See Copyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
18
19
20
21

#ifndef __DICOM_APP_HELPER_H_
#define __DICOM_APP_HELPER_H_

Matt Turek's avatar
Matt Turek committed
22
23
24
#ifdef _MSC_VER
#pragma warning ( disable : 4514 )
#pragma warning ( push, 3 )
Matt Turek's avatar
Matt Turek committed
25
#endif 
26
27
28
29

#include <vector>
#include <string>

30
#include "DICOMConfig.h"
Matt Turek's avatar
Matt Turek committed
31
32
33
#include "DICOMTypes.h"
#include "DICOMCallback.h"

34
class DICOMParser;
35

Matt Turek's avatar
Matt Turek committed
36
// Function object for sorting strings
37
38
struct ltstdstr
{
39
  bool operator()(const dicom_stl::string s1, const dicom_stl::string s2) const
40
41
42
43
44
  {
    return s1 < s2;
  }
};

Matt Turek's avatar
Matt Turek committed
45
// Helper structure for DICOM elements
46
47
48
49
50
struct DICOMTagInfo
{
  doublebyte group;
  doublebyte element;
  DICOMParser::VRTypes datatype;
51
  const char* description;
52
53
};

Matt Turek's avatar
Matt Turek committed
54
55
56

// Helper class use for ordering DICOM images based on different
// (group, element) tags.
57
class DICOM_EXPORT DICOMOrderingElements
Matt Turek's avatar
Matt Turek committed
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
{
public:
  DICOMOrderingElements()
    {
      // Default values to something "valid"
      SliceNumber = -1;
      SliceLocation = 0.0;
      ImagePositionPatient[0] = 0.0;
      ImagePositionPatient[1] = 0.0;
      ImagePositionPatient[2] = 0.0;
      ImageOrientationPatient[0] = 1.0;
      ImageOrientationPatient[1] = 0.0;
      ImageOrientationPatient[2] = 0.0;
      ImageOrientationPatient[3] = 0.0;
      ImageOrientationPatient[4] = 1.0;
      ImageOrientationPatient[5] = 0.0;
    }
      
  int SliceNumber;
  float SliceLocation;
  float ImagePositionPatient[3];
  float ImageOrientationPatient[6];
};

82
class DICOMAppHelperImplementation;
Matt Turek's avatar
Matt Turek committed
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

/**
 * \class DICOMAppHelper
 * \brief Class to interface an application to a DICOMParser
 *
 * DICOMAppHelper assists an application in communicating with a
 * DICOMParser. DICOMAppHelper registers a series of callbacks to the
 * DICOMParser which allows it to cache the information from a DICOM
 * file in a format that is appropriate for an application to
 * use. Once a DICOM file is read, an application can query the
 * DICOMAppHelper for the resolution, pixel size, and pixel data.
 *
 * If a DICOMParser scans more than one file, the DICOMAppHelper will
 * group filesnames by SeriesUID.  This allows an application to pass
 * a series of DICOM files to the DICOMParser (which via the callback
 * mechanism allows the DICOMAppHelper to cache information) and then
 * query the DICOMAppHelper for the files that are from the same
 * series.  The application can request the filenames for a particular
 * series to be sorted based on image number, slice location, or
 * patient position. This allows the DICOMAppHelper to assist an
 * application is collecting all the images from one series into a
 * volume.
 */
106
class DICOM_EXPORT DICOMAppHelper
107
{
Matt Turek's avatar
Matt Turek committed
108
109
public:
  /** Standard constructor */
110
111
  DICOMAppHelper();

Matt Turek's avatar
Matt Turek committed
112
113
  /** Standard destructor */
  virtual ~DICOMAppHelper();
114

Matt Turek's avatar
Matt Turek committed
115
116
117
118
119
120
121
122
123
  /** Callbacks that are registered with the DICOMParser.  The
   * DICOMParser will call one of these callbacks whenever it
   * encounters a (group, element) that has an associated callback */
  virtual void RescaleSlopeCallback(DICOMParser *parser,
                                     doublebyte group,
                                    doublebyte element,
                                    DICOMParser::VRTypes type,
                                    unsigned char* val,
                                    quadbyte len);
124

Matt Turek's avatar
Matt Turek committed
125
126
  virtual void ArrayCallback(DICOMParser *parser,
                             doublebyte group,
127
128
129
                             doublebyte element,
                             DICOMParser::VRTypes type,
                             unsigned char* val,
Matt Turek's avatar
Matt Turek committed
130
                             quadbyte len);
131
  
Matt Turek's avatar
Matt Turek committed
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
  virtual void SliceNumberCallback(DICOMParser *parser,
                                   doublebyte group,
                                   doublebyte element,
                                   DICOMParser::VRTypes type,
                                   unsigned char* val,
                                   quadbyte len) ;

  virtual void SliceLocationCallback(DICOMParser *parser,
                                     doublebyte group,
                                     doublebyte element,
                                     DICOMParser::VRTypes type,
                                     unsigned char* val,
                                     quadbyte len) ;

  virtual void ImagePositionPatientCallback(DICOMParser *parser,
                                            doublebyte group,
                                            doublebyte element,
                                            DICOMParser::VRTypes type,
                                            unsigned char* val,
                                            quadbyte len) ;
  
  virtual void ImageOrientationPatientCallback(DICOMParser *parser,
                                               doublebyte group,
                                               doublebyte element,
                                               DICOMParser::VRTypes type,
                                               unsigned char* val,
                                               quadbyte len) ;
  
  virtual void SeriesUIDCallback(DICOMParser *parser,
                                 doublebyte group,
                                 doublebyte element,
                                 DICOMParser::VRTypes type,
                                 unsigned char* val,
                                 quadbyte len) ;
Jim Miller's avatar
Jim Miller committed
166

Matt Turek's avatar
Matt Turek committed
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  virtual void TransferSyntaxCallback(DICOMParser *parser,
                                      doublebyte group,
                                      doublebyte element,
                                      DICOMParser::VRTypes type,
                                      unsigned char* val,
                                      quadbyte len) ;
  
  virtual void BitsAllocatedCallback(DICOMParser *parser,
                                     doublebyte group,
                                     doublebyte element,
                                     DICOMParser::VRTypes type,
                                     unsigned char* val,
                                     quadbyte len) ;
  
  virtual void ToggleSwapBytesCallback(DICOMParser *parser,
                                       doublebyte,
                                       doublebyte,
                                       DICOMParser::VRTypes,
                                       unsigned char*,
                                       quadbyte);
  
  virtual void PixelSpacingCallback(DICOMParser *parser,
                                    doublebyte group,
190
191
192
193
194
                                    doublebyte element,
                                    DICOMParser::VRTypes type,
                                    unsigned char* val,
                                    quadbyte len) ;

Matt Turek's avatar
Matt Turek committed
195
196
  virtual void HeightCallback(DICOMParser *parser,
                              doublebyte group,
197
198
199
200
201
                              doublebyte element,
                              DICOMParser::VRTypes type,
                              unsigned char* val,
                              quadbyte len);

Matt Turek's avatar
Matt Turek committed
202
203
  virtual void WidthCallback( DICOMParser *parser,
                              doublebyte group,
204
205
206
207
208
                              doublebyte element,
                              DICOMParser::VRTypes type,
                              unsigned char* val,
                              quadbyte len);

Matt Turek's avatar
Matt Turek committed
209
210
  virtual void PixelRepresentationCallback(DICOMParser *parser,
                                           doublebyte group,
211
212
213
214
215
                                           doublebyte element,
                                           DICOMParser::VRTypes type,
                                           unsigned char* val,
                                           quadbyte len);

Matt Turek's avatar
Matt Turek committed
216
217
  virtual void PhotometricInterpretationCallback(DICOMParser *parser,
                                                 doublebyte,
218
219
220
221
222
                                                 doublebyte,
                                                 DICOMParser::VRTypes,
                                                 unsigned char* val,
                                                 quadbyte len);

Matt Turek's avatar
Matt Turek committed
223
224
  virtual void PixelDataCallback(DICOMParser *parser,
                                 doublebyte,
225
226
227
228
229
                                 doublebyte,
                                 DICOMParser::VRTypes,
                                 unsigned char* val,
                                 quadbyte len);

Matt Turek's avatar
Matt Turek committed
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
  virtual void RescaleOffsetCallback( DICOMParser *parser,
                                      doublebyte,
                                      doublebyte,
                                      DICOMParser::VRTypes,
                                      unsigned char* val,
                                      quadbyte);

  /** Register all the standard callbacks with the DICOM Parser.  This
   * associates a callback with each (group, element) tag pair in the
   * header of the file whose data needs to be cached. */
  virtual void RegisterCallbacks(DICOMParser* parser);

  /** Register a callback for retrieving the pixel data from a DICOM
   *  file */
  virtual void RegisterPixelDataCallback(DICOMParser* parser);

246

Matt Turek's avatar
Matt Turek committed
247
248
249
250
251
252
253
254
255
256
257
  /** Output information associated with a DICOM series */
  void OutputSeries();


  /** The next set of methods are for accessing information which is
   * cached when a DICOM file is processed.  This allows access to
   * information from the header as well as the pixel data. */
  
  
  /** Get the pixel spacing of the last image processed by the
   *  DICOMParser */
258
259
260
261
262
  float* GetPixelSpacing()
    {
    return this->PixelSpacing;
    }

Matt Turek's avatar
Matt Turek committed
263
264
  /** Get the image width of the last image processed by the
   *  DICOMParser */
265
266
267
268
269
  int GetWidth()
    {
    return this->Width;
    }

Matt Turek's avatar
Matt Turek committed
270
271
  /** Get the image height of the last image processed by the
   *  DICOMParser */
272
273
274
275
276
  int GetHeight()
    {
    return this->Height;
    }

Matt Turek's avatar
Matt Turek committed
277
278
  /** Get the dimensions (width, height) of the last image processed
   *  by the DICOMParser */
279
280
281
282
283
  int* GetDimensions()
    {
    return this->Dimensions;
    }

Matt Turek's avatar
Matt Turek committed
284
285
286
287
288
289
290
  /** Get the (DICOM) x,y,z coordinates of the first pixel in the
   * image (upper left hand corner) of the last image processed by the
   * DICOMParser */
  float *GetImagePositionPatient()
    {
      return this->ImagePositionPatient;
    }
291
292
293
294
295
296
297
298

  /** Get the (DICOM) directions cosines. It consist of the components
   * of the first two vectors. The third vector needs to be computed
   * to form an orthonormal basis. */
 float *GetImageOrientationPatient()
    {
      return this->ImageOrientationPatient;
    }
Matt Turek's avatar
Matt Turek committed
299
300
301
  
  /** Get the number of bits allocated per pixel of the last image
   *  processed by the DICOMParser */
302
303
304
305
306
  int GetBitsAllocated()
    {
    return this->BitsAllocated;
    }

Matt Turek's avatar
Matt Turek committed
307
308
309
  /** Get the pixel representation of the last image processed by the
   * DICOMParser. A zero is a unsigned quantity.  A one indicates a
   * signed quantity. */
310
311
312
313
314
  int GetPixelRepresentation()
    {
    return this->PixelRepresentation;
    }

Matt Turek's avatar
Matt Turek committed
315
316
  /** Get the number of components of the last image processed by the
   *  DICOMParser. */
317
318
319
320
321
322
323
324
325
326
327
328
  int GetNumberOfComponents()
    {
    if (!this->PhotometricInterpretation)
      {
      return 1;
      }

    //
    // DICOM standard says that spaces (0x20) are to
    // be ignored for CS types.  We don't handle this
    // well yet.
    //
329
330
    dicom_stl::string str1(*this->PhotometricInterpretation);
    dicom_stl::string rgb("RGB ");
331
332
333
334
335
336
337
338
339
340
341

    if (str1 == rgb)
      {
      return 3;
      }
    else
      {
      return 1;
      }
    }

Matt Turek's avatar
Matt Turek committed
342
343
  /** Get the transfer syntax UID for the last image processed by the
   *  DICOMParser. */
344
  dicom_stl::string GetTransferSyntaxUID()
345
346
347
348
    {
    return *(this->TransferSyntaxUID);
    }

Matt Turek's avatar
Matt Turek committed
349
350
  /** Get a textual description of the transfer syntax of the last
   *  image processed by the DICOMParser. */
351
352
  const char* TransferSyntaxUIDDescription(const char* uid);

Matt Turek's avatar
Matt Turek committed
353
354
355
356
357
  /** Get the image data from the last image processed by the
   * DICOMParser.  The data is only valid if the PixelDataCallback was
   * registered.
   * \sa RegisterPixelDataCallback()
  */
358
359
  void GetImageData(void* & data, DICOMParser::VRTypes& dataType, unsigned long& len);

Matt Turek's avatar
Matt Turek committed
360
361
  /** Determine whether the image data was rescaled (by the
   *  RescaleSlope tag) to be floating point. */
362
363
  bool RescaledImageDataIsFloat();

Matt Turek's avatar
Matt Turek committed
364
365
  /** Determine whether the image data was rescaled (by the
   * RescaleSlope tag) to be a signed data type. */
366
367
  bool RescaledImageDataIsSigned();

Matt Turek's avatar
Matt Turek committed
368
369
  /** Get the slice number of the last image processed by the
      DICOMParser. */
370
371
372
373
374
  int GetSliceNumber()
    {
    return this->SliceNumber;
    }

Matt Turek's avatar
Matt Turek committed
375
376
377
378
  /** Clear the internal databases. This will reset the internal
   * databases that are grouping filenames based on SeriesUID's and
   * ordering filenames based on image locations. */
  void Clear();
379

Matt Turek's avatar
Matt Turek committed
380
381
  /** Get the series UIDs for the files processed since the last
   * clearing of the cache. */
382
  void GetSeriesUIDs(dicom_stl::vector<dicom_stl::string> &v); 
Matt Turek's avatar
Matt Turek committed
383
384
  
  /** Get the filenames for a series ordered by slice number. */
385
  void GetSliceNumberFilenamePairs(const dicom_stl::string &seriesUID,
386
                              dicom_stl::vector<dicom_stl::pair<int, dicom_stl::string> > &v, bool ascending = true);
387

Matt Turek's avatar
Matt Turek committed
388
389
  /** Get the filenames for a series order by slice number.  Use the
      first series by default. */
390
  void GetSliceNumberFilenamePairs(dicom_stl::vector<dicom_stl::pair<int, dicom_stl::string> > &v, bool ascending = true);
391

Matt Turek's avatar
Matt Turek committed
392
  /* Get the filenames for a series ordered by slice location. */
393
  void GetSliceLocationFilenamePairs(const dicom_stl::string &seriesUID,
394
                              dicom_stl::vector<dicom_stl::pair<float, dicom_stl::string> > &v, bool ascending = true);
Matt Turek's avatar
Matt Turek committed
395
396
397

  /* Get the filenames for a series ordered by slice location. Use the
   * first series by default. */
398
  void GetSliceLocationFilenamePairs(dicom_stl::vector<dicom_stl::pair<float, dicom_stl::string> > &v, bool ascending = true);
Matt Turek's avatar
Matt Turek committed
399
400
401
402

  /* Get the filenames for a series ordered by image position
     patient. This is the most reliable way to order the images in a
     series. */
403
  void GetImagePositionPatientFilenamePairs(const dicom_stl::string &seriesUID,
404
                            dicom_stl::vector<dicom_stl::pair<float, dicom_stl::string> > &v, bool ascending = true);
Matt Turek's avatar
Matt Turek committed
405
406
407
408

  /* Get the filenames for a series ordered by image position
     patient. This is the most reliable way to order the images in a
     series. Use the first series by default. */
409
  void GetImagePositionPatientFilenamePairs(dicom_stl::vector<dicom_stl::pair<float, dicom_stl::string> > &v, bool ascending = true);
410

411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
  float GetRescaleSlope()
    {
    return this->RescaleSlope;
    }

  float GetRescaleOffset()
    {
    return this->RescaleOffset;
    }

  dicom_stl::string GetPatientName()
    {
    return *(this->PatientName);
    }

  dicom_stl::string GetStudyUID()
    {
    return *(this->StudyUID);
    }

Jim Miller's avatar
Jim Miller committed
431
432
433
434
435
  dicom_stl::string GetStudyID()
    {
    return *(this->StudyID);
    }
  
436
437
438
439
440
441
442
443
444
445
446
447
448
449
  void PatientNameCallback(DICOMParser *,
                           doublebyte,
                           doublebyte,
                           DICOMParser::VRTypes,
                           unsigned char* val,
                           quadbyte);

  void StudyUIDCallback(DICOMParser *,
                           doublebyte,
                           doublebyte,
                           DICOMParser::VRTypes,
                           unsigned char* val,
                           quadbyte);

Jim Miller's avatar
Jim Miller committed
450
451
452
453
454
455
456
  void StudyIDCallback(DICOMParser *,
                           doublebyte,
                           doublebyte,
                           DICOMParser::VRTypes,
                           unsigned char* val,
                           quadbyte);

457
458
459
460
461
462
463
464
465
466
467
468
  void GantryAngleCallback(DICOMParser *,
                           doublebyte,
                           doublebyte,
                           DICOMParser::VRTypes,
                           unsigned char* val,
                           quadbyte);

  float GetGantryAngle()
    {
    return this->GantryAngle;
    }

Jim Miller's avatar
Jim Miller committed
469
470
  

471
472
473
474
475
476
477
478
 protected:
  int BitsAllocated;
  bool ByteSwapData;
  float PixelSpacing[3];
  int Width;
  int Height;
  int SliceNumber; 
  int Dimensions[2];
Matt Turek's avatar
Matt Turek committed
479
  float ImagePositionPatient[3];
480
  float ImageOrientationPatient[6];
481
482

  // map from series UID to vector of files in the series 
483
  // dicom_stl::map<dicom_stl::string, dicom_stl::vector<dicom_stl::string>, ltstdstr> SeriesUIDMap;
Matt Turek's avatar
Matt Turek committed
484
485

  // map from filename to intraseries sortable tags
486
  // dicom_stl::map<dicom_stl::string, DICOMOrderingElements, ltstdstr> SliceOrderingMap;
487

488
489
  typedef dicom_stl::map<dicom_stl::pair<doublebyte, doublebyte>, DICOMTagInfo> TagMapType;
  // TagMapType TagMap;
490

491
  dicom_stream::ofstream HeaderFile;
492
493
494
495
  
  // 0 unsigned
  // 1 2s complement (signed)
  int PixelRepresentation;
496
497
  dicom_stl::string* PhotometricInterpretation;
  dicom_stl::string* TransferSyntaxUID;
498
499
500
501
502
503
  float RescaleOffset;
  float RescaleSlope;
  void* ImageData;
  DICOMParser::VRTypes ImageDataType;
  unsigned long ImageDataLengthInBytes;

504
505
  dicom_stl::string* PatientName;
  dicom_stl::string* StudyUID;
Jim Miller's avatar
Jim Miller committed
506
  dicom_stl::string* StudyID;
507
508
  float GantryAngle;

509
510
  DICOMMemberCallback<DICOMAppHelper>* SeriesUIDCB;
  DICOMMemberCallback<DICOMAppHelper>* SliceNumberCB;
Matt Turek's avatar
Matt Turek committed
511
512
513
  DICOMMemberCallback<DICOMAppHelper>* SliceLocationCB;
  DICOMMemberCallback<DICOMAppHelper>* ImagePositionPatientCB;
  DICOMMemberCallback<DICOMAppHelper>* ImageOrientationPatientCB;
514
  DICOMMemberCallback<DICOMAppHelper>* TransferSyntaxCB;
515
  DICOMMemberCallback<DICOMAppHelper>* ToggleSwapBytesCB;
516
517
518
519
520
521
522
523
524
  DICOMMemberCallback<DICOMAppHelper>* BitsAllocatedCB;
  DICOMMemberCallback<DICOMAppHelper>* PixelSpacingCB;
  DICOMMemberCallback<DICOMAppHelper>* HeightCB;
  DICOMMemberCallback<DICOMAppHelper>* WidthCB;
  DICOMMemberCallback<DICOMAppHelper>* PixelRepresentationCB;
  DICOMMemberCallback<DICOMAppHelper>* PhotometricInterpretationCB;
  DICOMMemberCallback<DICOMAppHelper>* RescaleOffsetCB;
  DICOMMemberCallback<DICOMAppHelper>* RescaleSlopeCB;
  DICOMMemberCallback<DICOMAppHelper>* PixelDataCB;
525
526
  DICOMMemberCallback<DICOMAppHelper>* PatientNameCB;
  DICOMMemberCallback<DICOMAppHelper>* StudyUIDCB;
Jim Miller's avatar
Jim Miller committed
527
  DICOMMemberCallback<DICOMAppHelper>* StudyIDCB;
528
529

  DICOMMemberCallback<DICOMAppHelper>* GantryAngleCB;
530

531
532
533
534
535
536
537
538
  //
  // Implementation contains stl templated classes that 
  // can't be exported from a DLL in Windows. We hide
  // them in the implementation to get rid of annoying
  // compile warnings.
  //
  DICOMAppHelperImplementation* Implementation;

539
540
541
 private:
  DICOMAppHelper(const DICOMAppHelper&);  
  void operator=(const DICOMAppHelper&); 
542
    
543
544
};

Matt Turek's avatar
Matt Turek committed
545
546
547
548
#ifdef _MSC_VER
#pragma warning ( pop )
#endif

549
#endif