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
|
#include "vtkDICOMMetaData.h"
#include "vtkDICOMFileSorter.h"
#include "vtkDICOMReader.h"
#include "vtkDICOMTagPath.h"
#include "vtkDICOMSequence.h"
#include "vtkDICOMItem.h"
#include "vtkSmartPointer.h"
#include "vtkStringArray.h"
#include <sstream>
#include <string.h>
#include <stdlib.h>
#include <math.h>
// macro for performing tests
#define TestAssert(t) \
if (!(t)) \
{ \
cout << exename << ": Assertion Failed: " << #t << "\n"; \
cout << __FILE__ << ":" << __LINE__ << "\n"; \
cout.flush(); \
rval |= 1; \
}
int main(int argc, char *argv[])
{
int rval = 0;
const char *exename = argv[0];
// remove path portion of exename
const char *cp = exename + strlen(exename);
while (cp != exename && cp[-1] != '\\' && cp[-1] != '/') { --cp; }
exename = cp;
vtkSmartPointer<vtkDICOMFileSorter> sorter =
vtkSmartPointer<vtkDICOMFileSorter>::New();
vtkSmartPointer<vtkStringArray> files =
vtkSmartPointer<vtkStringArray>::New();
for (int i = 1; i < argc; i++)
{
files->InsertNextValue(argv[i]);
}
sorter->SetInputFileNames(files);
sorter->Update();
vtkSmartPointer<vtkDICOMMetaData> meta =
vtkSmartPointer<vtkDICOMMetaData>::New();
if (sorter->GetNumberOfSeries() > 0)
{
// read the meta data from the supplied image
vtkStringArray *a = sorter->GetFileNamesForSeries(0);
vtkSmartPointer<vtkDICOMReader> reader =
vtkSmartPointer<vtkDICOMReader>::New();
reader->SetFileNames(a);
reader->UpdateInformation();
meta = reader->GetMetaData();
}
else if (argc == 1)
{
// create a real world value mapping sequence by hand
// 1) use Unified Code for Units of Measure (UCUM), version 1.9
// 2) the CodeMeaning should be a copy of CodeValue unless:
// 2a) CodeValue=1, in which case use CodeMeaning=unity
vtkDICOMItem unitsItem;
unitsItem.Set(DC::CodeValue, "m2/s");
unitsItem.Set(DC::CodingSchemeDesignator, "UCUM");
unitsItem.Set(DC::CodingSchemeVersion, "1.9");
unitsItem.Set(DC::CodeMeaning, "m2/s");
vtkDICOMItem mappingItem;
mappingItem.Set(DC::LUTExplanation, "Hot Metal");
mappingItem.Set(DC::MeasurementUnitsCodeSequence,
vtkDICOMValue(vtkDICOMVR::SQ, unitsItem));
mappingItem.Set(DC::LUTLabel, "HOT_METAL");
// need to explicitly define the VR for these, because it depends
// on whether the PixelRepresentation is signed or unsigned
mappingItem.Set(DC::RealWorldValueFirstValueMapped,
vtkDICOMValue(vtkDICOMVR::US, 0));
mappingItem.Set(DC::RealWorldValueLastValueMapped,
vtkDICOMValue(vtkDICOMVR::US, 4095));
mappingItem.Set(DC::RealWorldValueIntercept, 0.234);
mappingItem.Set(DC::RealWorldValueSlope, 0.438);
meta->Set(DC::RealWorldValueMappingSequence,
vtkDICOMValue(vtkDICOMVR::SQ, mappingItem));
}
else
{
cout << "The provided file is not DICOM!" << endl;
}
if (meta->Has(DC::RealWorldValueMappingSequence))
{
const vtkDICOMItem& mappingItem =
meta->Get(DC::RealWorldValueMappingSequence).GetItem(0);
std::string lutName = mappingItem.Get(DC::LUTLabel).AsString();
std::string units = mappingItem.Get(vtkDICOMTagPath(
DC::MeasurementUnitsCodeSequence, 0, DC::CodeValue)).AsString();
double range[2];
range[0] = mappingItem.Get(DC::RealWorldValueFirstValueMapped).AsDouble();
range[1] = mappingItem.Get(DC::RealWorldValueLastValueMapped).AsDouble();
double slope = mappingItem.Get(DC::RealWorldValueSlope).AsDouble();
double inter = mappingItem.Get(DC::RealWorldValueIntercept).AsDouble();
cout << "Map pixel values in the range " << range[0] << ", " << range[1] << endl;
cout << "through the equation y = " << slope << " * x + " << inter << endl;
cout << "to real values with units of " << units << endl;
cout << "and display the result with color table " << lutName << endl;
if (argc == 1)
{
TestAssert(range[0] == 0);
TestAssert(range[1] == 4095);
TestAssert(fabs(slope - 0.438) < 1e-16);
TestAssert(fabs(inter - 0.234) < 1e-16);
TestAssert(units == "m2/s");
TestAssert(lutName == "HOT_METAL");
}
}
else
{
cout << "Image has no real world value mapping!" << endl;
}
return rval;
}
|