You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
417 lines
15 KiB
C++
417 lines
15 KiB
C++
/*=========================================================================
|
|
|
|
Program: DICOMParser
|
|
Module: DICOMAppHelper.h
|
|
Language: C++
|
|
|
|
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.
|
|
|
|
=========================================================================*/
|
|
|
|
#ifndef __DICOM_APP_HELPER_H_
|
|
#define __DICOM_APP_HELPER_H_
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning(disable : 4514)
|
|
#pragma warning(disable : 4018)
|
|
#pragma warning(push, 3)
|
|
#endif
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "DICOMCallback.h"
|
|
#include "DICOMConfig.h"
|
|
#include "DICOMTypes.h"
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning(default : 4018)
|
|
#endif
|
|
|
|
class DICOMParser;
|
|
|
|
// Function object for sorting strings
|
|
struct ltstdstr
|
|
{
|
|
bool operator()(const dicom_stl::string& s1, const dicom_stl::string& s2) const
|
|
{
|
|
return s1 < s2;
|
|
}
|
|
};
|
|
|
|
// Helper structure for DICOM elements
|
|
struct DICOMTagInfo
|
|
{
|
|
doublebyte group;
|
|
doublebyte element;
|
|
DICOMParser::VRTypes datatype;
|
|
const char* description;
|
|
};
|
|
|
|
// Helper class use for ordering DICOM images based on different
|
|
// (group, element) tags.
|
|
class DICOM_EXPORT DICOMOrderingElements
|
|
{
|
|
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];
|
|
};
|
|
|
|
class DICOMAppHelperImplementation;
|
|
|
|
/**
|
|
* \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.
|
|
*/
|
|
class DICOM_EXPORT DICOMAppHelper
|
|
{
|
|
public:
|
|
/** Standard constructor */
|
|
DICOMAppHelper();
|
|
|
|
/** Standard destructor */
|
|
virtual ~DICOMAppHelper();
|
|
|
|
/** 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);
|
|
|
|
virtual void ArrayCallback(DICOMParser* parser, doublebyte group, doublebyte element,
|
|
DICOMParser::VRTypes type, unsigned char* val, quadbyte len);
|
|
|
|
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);
|
|
|
|
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, doublebyte element,
|
|
DICOMParser::VRTypes type, unsigned char* val, quadbyte len);
|
|
|
|
virtual void HeightCallback(DICOMParser* parser, doublebyte group, doublebyte element,
|
|
DICOMParser::VRTypes type, unsigned char* val, quadbyte len);
|
|
|
|
virtual void WidthCallback(DICOMParser* parser, doublebyte group, doublebyte element,
|
|
DICOMParser::VRTypes type, unsigned char* val, quadbyte len);
|
|
|
|
virtual void PixelRepresentationCallback(DICOMParser* parser, doublebyte group,
|
|
doublebyte element, DICOMParser::VRTypes type, unsigned char* val, quadbyte len);
|
|
|
|
virtual void PhotometricInterpretationCallback(DICOMParser* parser, doublebyte, doublebyte,
|
|
DICOMParser::VRTypes, unsigned char* val, quadbyte len);
|
|
|
|
virtual void PixelDataCallback(DICOMParser* parser, doublebyte, doublebyte, DICOMParser::VRTypes,
|
|
unsigned char* val, quadbyte len);
|
|
|
|
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);
|
|
|
|
/** 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 */
|
|
float* GetPixelSpacing() { return this->PixelSpacing; }
|
|
|
|
/** Get the image width of the last image processed by the
|
|
* DICOMParser */
|
|
int GetWidth() { return this->Width; }
|
|
|
|
/** Get the image height of the last image processed by the
|
|
* DICOMParser */
|
|
int GetHeight() { return this->Height; }
|
|
|
|
/** Get the dimensions (width, height) of the last image processed
|
|
* by the DICOMParser */
|
|
int* GetDimensions() { return this->Dimensions; }
|
|
|
|
/** 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; }
|
|
|
|
/** 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; }
|
|
|
|
/** Get the number of bits allocated per pixel of the last image
|
|
* processed by the DICOMParser */
|
|
int GetBitsAllocated() { return this->BitsAllocated; }
|
|
|
|
/** Get the pixel representation of the last image processed by the
|
|
* DICOMParser. A zero is a unsigned quantity. A one indicates a
|
|
* signed quantity. */
|
|
int GetPixelRepresentation() { return this->PixelRepresentation; }
|
|
|
|
/** Get the number of components of the last image processed by the
|
|
* DICOMParser. */
|
|
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.
|
|
//
|
|
dicom_stl::string str1(*this->PhotometricInterpretation);
|
|
dicom_stl::string rgb("RGB ");
|
|
|
|
if (str1 == rgb)
|
|
{
|
|
return 3;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/** Get the transfer syntax UID for the last image processed by the
|
|
* DICOMParser. */
|
|
dicom_stl::string GetTransferSyntaxUID() { return *(this->TransferSyntaxUID); }
|
|
|
|
/** Get a textual description of the transfer syntax of the last
|
|
* image processed by the DICOMParser. */
|
|
const char* TransferSyntaxUIDDescription(const char* uid);
|
|
|
|
/** Get the image data from the last image processed by the
|
|
* DICOMParser. The data is only valid if the PixelDataCallback was
|
|
* registered.
|
|
* \sa RegisterPixelDataCallback()
|
|
*/
|
|
void GetImageData(void*& data, DICOMParser::VRTypes& dataType, unsigned long& len);
|
|
|
|
/** Determine whether the image data was rescaled (by the
|
|
* RescaleSlope tag) to be floating point. */
|
|
bool RescaledImageDataIsFloat();
|
|
|
|
/** Determine whether the image data was rescaled (by the
|
|
* RescaleSlope tag) to be a signed data type. */
|
|
bool RescaledImageDataIsSigned();
|
|
|
|
/** Get the slice number of the last image processed by the
|
|
DICOMParser. */
|
|
int GetSliceNumber() { return this->SliceNumber; }
|
|
|
|
/** 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();
|
|
|
|
/** Get the series UIDs for the files processed since the last
|
|
* clearing of the cache. */
|
|
void GetSeriesUIDs(dicom_stl::vector<dicom_stl::string>& v);
|
|
|
|
/** Get the filenames for a series ordered by slice number. */
|
|
void GetSliceNumberFilenamePairs(const dicom_stl::string& seriesUID,
|
|
dicom_stl::vector<dicom_stl::pair<int, dicom_stl::string> >& v, bool ascending = true);
|
|
|
|
/** Get the filenames for a series order by slice number. Use the
|
|
first series by default. */
|
|
void GetSliceNumberFilenamePairs(
|
|
dicom_stl::vector<dicom_stl::pair<int, dicom_stl::string> >& v, bool ascending = true);
|
|
|
|
/* Get the filenames for a series ordered by slice location. */
|
|
void GetSliceLocationFilenamePairs(const dicom_stl::string& seriesUID,
|
|
dicom_stl::vector<dicom_stl::pair<float, dicom_stl::string> >& v, bool ascending = true);
|
|
|
|
/* Get the filenames for a series ordered by slice location. Use the
|
|
* first series by default. */
|
|
void GetSliceLocationFilenamePairs(
|
|
dicom_stl::vector<dicom_stl::pair<float, dicom_stl::string> >& v, bool ascending = true);
|
|
|
|
/* Get the filenames for a series ordered by image position
|
|
patient. This is the most reliable way to order the images in a
|
|
series. */
|
|
void GetImagePositionPatientFilenamePairs(const dicom_stl::string& seriesUID,
|
|
dicom_stl::vector<dicom_stl::pair<float, dicom_stl::string> >& v, bool ascending = true);
|
|
|
|
/* 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. */
|
|
void GetImagePositionPatientFilenamePairs(
|
|
dicom_stl::vector<dicom_stl::pair<float, dicom_stl::string> >& v, bool ascending = true);
|
|
|
|
float GetRescaleSlope() { return this->RescaleSlope; }
|
|
|
|
float GetRescaleOffset() { return this->RescaleOffset; }
|
|
|
|
dicom_stl::string GetPatientName() { return *(this->PatientName); }
|
|
|
|
dicom_stl::string GetStudyUID() { return *(this->StudyUID); }
|
|
|
|
dicom_stl::string GetStudyID() { return *(this->StudyID); }
|
|
|
|
void PatientNameCallback(
|
|
DICOMParser*, doublebyte, doublebyte, DICOMParser::VRTypes, unsigned char* val, quadbyte);
|
|
|
|
void StudyUIDCallback(
|
|
DICOMParser*, doublebyte, doublebyte, DICOMParser::VRTypes, unsigned char* val, quadbyte);
|
|
|
|
void StudyIDCallback(
|
|
DICOMParser*, doublebyte, doublebyte, DICOMParser::VRTypes, unsigned char* val, quadbyte);
|
|
|
|
void GantryAngleCallback(
|
|
DICOMParser*, doublebyte, doublebyte, DICOMParser::VRTypes, unsigned char* val, quadbyte);
|
|
|
|
float GetGantryAngle() { return this->GantryAngle; }
|
|
|
|
protected:
|
|
int BitsAllocated;
|
|
bool ByteSwapData;
|
|
float PixelSpacing[3];
|
|
int Width;
|
|
int Height;
|
|
int SliceNumber;
|
|
int Dimensions[2];
|
|
float ImagePositionPatient[3];
|
|
float ImageOrientationPatient[6];
|
|
|
|
// map from series UID to vector of files in the series
|
|
// dicom_stl::map<dicom_stl::string, dicom_stl::vector<dicom_stl::string>, ltstdstr> SeriesUIDMap;
|
|
|
|
// map from filename to intraseries sortable tags
|
|
// dicom_stl::map<dicom_stl::string, DICOMOrderingElements, ltstdstr> SliceOrderingMap;
|
|
|
|
typedef dicom_stl::map<dicom_stl::pair<doublebyte, doublebyte>, DICOMTagInfo> TagMapType;
|
|
// TagMapType TagMap;
|
|
|
|
dicom_stream::ofstream* HeaderFile;
|
|
|
|
// 0 unsigned
|
|
// 1 2s complement (signed)
|
|
int PixelRepresentation;
|
|
dicom_stl::string* PhotometricInterpretation;
|
|
dicom_stl::string* TransferSyntaxUID;
|
|
float RescaleOffset;
|
|
float RescaleSlope;
|
|
void* ImageData;
|
|
DICOMParser::VRTypes ImageDataType;
|
|
unsigned long ImageDataLengthInBytes;
|
|
|
|
dicom_stl::string* PatientName;
|
|
dicom_stl::string* StudyUID;
|
|
dicom_stl::string* StudyID;
|
|
float GantryAngle;
|
|
|
|
DICOMMemberCallback<DICOMAppHelper>* SeriesUIDCB;
|
|
DICOMMemberCallback<DICOMAppHelper>* SliceNumberCB;
|
|
DICOMMemberCallback<DICOMAppHelper>* SliceLocationCB;
|
|
DICOMMemberCallback<DICOMAppHelper>* ImagePositionPatientCB;
|
|
DICOMMemberCallback<DICOMAppHelper>* ImageOrientationPatientCB;
|
|
DICOMMemberCallback<DICOMAppHelper>* TransferSyntaxCB;
|
|
DICOMMemberCallback<DICOMAppHelper>* ToggleSwapBytesCB;
|
|
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;
|
|
DICOMMemberCallback<DICOMAppHelper>* PatientNameCB;
|
|
DICOMMemberCallback<DICOMAppHelper>* StudyUIDCB;
|
|
DICOMMemberCallback<DICOMAppHelper>* StudyIDCB;
|
|
|
|
DICOMMemberCallback<DICOMAppHelper>* GantryAngleCB;
|
|
|
|
//
|
|
// 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;
|
|
|
|
private:
|
|
DICOMAppHelper(const DICOMAppHelper&);
|
|
void operator=(const DICOMAppHelper&);
|
|
};
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
#endif
|