Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-23 09:21:45

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 //
0027 /// \file medical/DICOM/src/DicomHandler.cc
0028 /// \brief Implementation of the DicomHandler class
0029 //
0030 // The code was written by :
0031 //      *Louis Archambault louis.archambault@phy.ulaval.ca,
0032 //      *Luc Beaulieu beaulieu@phy.ulaval.ca
0033 //      +Vincent Hubert-Tremblay at tigre.2@sympatico.ca
0034 //
0035 //
0036 // *Centre Hospitalier Universitaire de Quebec (CHUQ),
0037 // Hotel-Dieu de Quebec, departement de Radio-oncologie
0038 // 11 cote du palais. Quebec, QC, Canada, G1R 2J6
0039 // tel (418) 525-4444 #6720
0040 // fax (418) 691 5268
0041 //
0042 // + University Laval, Quebec (QC) Canada
0043 //*******************************************************
0044 //
0045 //*******************************************************
0046 //
0047 /// DicomHandler.cc :
0048 ///        - Handling of DICM images
0049 ///         - Reading headers and pixels
0050 ///        - Transforming pixel to density and creating *.g4dcm
0051 ///          files
0052 //*******************************************************
0053 
0054 #include "DicomHandler.hh"
0055 
0056 #include "DicomPhantomZSliceHeader.hh"
0057 #include "DicomPhantomZSliceMerged.hh"
0058 
0059 #include "G4ios.hh"
0060 #include "globals.hh"
0061 
0062 #include <cctype>
0063 #include <cstring>
0064 #include <fstream>
0065 
0066 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0067 
0068 DicomHandler* DicomHandler::fInstance = 0;
0069 
0070 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0071 
0072 DicomHandler* DicomHandler::Instance()
0073 {
0074   if (fInstance == 0) {
0075     static DicomHandler dicomhandler;
0076     fInstance = &dicomhandler;
0077   }
0078   return fInstance;
0079 }
0080 
0081 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0082 
0083 G4String DicomHandler::GetDicomDataPath()
0084 {
0085   // default is current directory
0086   G4String driverPath = ".";
0087   // check environment
0088   const char* path = std::getenv("DICOM_PATH");
0089 
0090   if (path) {
0091     // if is set in environment
0092     return G4String(path);
0093   }
0094   else {
0095     // if DICOM_USE_HEAD, look for data installation
0096 #ifdef DICOM_USE_HEAD
0097     G4cerr << "Warning! DICOM was compiled with DICOM_USE_HEAD option but "
0098            << "the DICOM_PATH was not set!" << G4endl;
0099     G4String datadir = G4GetEnv<G4String>("G4ENSDFSTATEDATA", "");
0100     if (datadir.length() > 0) {
0101       auto _last = datadir.rfind("/");
0102       if (_last != std::string::npos) datadir.erase(_last);
0103       driverPath = datadir + "/DICOM1.1/DICOM_HEAD_TEST";
0104       G4int rc = setenv("DICOM_PATH", driverPath.c_str(), 0);
0105       G4cerr << "\t --> Using '" << driverPath << "'..." << G4endl;
0106       G4ConsumeParameters(rc);
0107     }
0108 #endif
0109   }
0110   return driverPath;
0111 }
0112 
0113 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0114 
0115 G4String DicomHandler::GetDicomDataFile()
0116 {
0117 #if defined(DICOM_USE_HEAD) && defined(G4_DCMTK)
0118   return GetDicomDataPath() + "/Data.dat.new";
0119 #else
0120   return GetDicomDataPath() + "/Data.dat";
0121 #endif
0122 }
0123 
0124 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0125 
0126 #ifdef DICOM_USE_HEAD
0127 DicomHandler::DicomHandler()
0128   : DATABUFFSIZE(8192),
0129     LINEBUFFSIZE(5020),
0130     FILENAMESIZE(512),
0131     fCompression(0),
0132     fNFiles(0),
0133     fRows(0),
0134     fColumns(0),
0135     fBitAllocated(0),
0136     fMaxPixelValue(0),
0137     fMinPixelValue(0),
0138     fPixelSpacingX(0.),
0139     fPixelSpacingY(0.),
0140     fSliceThickness(0.),
0141     fSliceLocation(0.),
0142     fRescaleIntercept(0),
0143     fRescaleSlope(0),
0144     fLittleEndian(true),
0145     fImplicitEndian(false),
0146     fPixelRepresentation(0),
0147     fNbrequali(0),
0148     fValueDensity(NULL),
0149     fValueCT(NULL),
0150     fReadCalibration(false),
0151     fMergedSlices(NULL),
0152     fCt2DensityFile("null.dat")
0153 {
0154   fMergedSlices = new DicomPhantomZSliceMerged;
0155   fDriverFile = GetDicomDataFile();
0156   G4cout << "Reading the DICOM_HEAD project " << fDriverFile << G4endl;
0157 }
0158 #else
0159 DicomHandler::DicomHandler()
0160   : DATABUFFSIZE(8192),
0161     LINEBUFFSIZE(5020),
0162     FILENAMESIZE(512),
0163     fCompression(0),
0164     fNFiles(0),
0165     fRows(0),
0166     fColumns(0),
0167     fBitAllocated(0),
0168     fMaxPixelValue(0),
0169     fMinPixelValue(0),
0170     fPixelSpacingX(0.),
0171     fPixelSpacingY(0.),
0172     fSliceThickness(0.),
0173     fSliceLocation(0.),
0174     fRescaleIntercept(0),
0175     fRescaleSlope(0),
0176     fLittleEndian(true),
0177     fImplicitEndian(false),
0178     fPixelRepresentation(0),
0179     fNbrequali(0),
0180     fValueDensity(NULL),
0181     fValueCT(NULL),
0182     fReadCalibration(false),
0183     fMergedSlices(NULL),
0184     fDriverFile("Data.dat"),
0185     fCt2DensityFile("CT2Density.dat")
0186 {
0187   fMergedSlices = new DicomPhantomZSliceMerged;
0188 }
0189 #endif
0190 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0191 
0192 DicomHandler::~DicomHandler() {}
0193 
0194 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0195 
0196 G4int DicomHandler::ReadFile(FILE* dicom, char* filename2)
0197 {
0198   G4cout << " ReadFile " << filename2 << G4endl;
0199 
0200   G4int returnvalue = 0;
0201   size_t rflag = 0;
0202   char* buffer = new char[LINEBUFFSIZE];
0203 
0204   fImplicitEndian = false;
0205   fLittleEndian = true;
0206 
0207   rflag = std::fread(buffer, 1, 128, dicom);  // The first 128 bytes
0208                                               // are not important
0209                                               // Reads the "DICOM" letters
0210   rflag = std::fread(buffer, 1, 4, dicom);
0211   // if there is no preamble, the FILE pointer is rewinded.
0212   if (std::strncmp("DICM", buffer, 4) != 0) {
0213     std::fseek(dicom, 0, SEEK_SET);
0214     fImplicitEndian = true;
0215   }
0216 
0217   short readGroupId;  // identify the kind of input data
0218   short readElementId;  // identify a particular type information
0219   short elementLength2;  // deal with element length in 2 bytes
0220                          // unsigned int elementLength4;
0221   // deal with element length in 4 bytes
0222   unsigned long elementLength4;  // deal with element length in 4 bytes
0223 
0224   char* data = new char[DATABUFFSIZE];
0225 
0226   // Read information up to the pixel data
0227   while (true) {
0228     // Reading groups and elements :
0229     readGroupId = 0;
0230     readElementId = 0;
0231     // group ID
0232     rflag = std::fread(buffer, 2, 1, dicom);
0233     GetValue(buffer, readGroupId);
0234     // element ID
0235     rflag = std::fread(buffer, 2, 1, dicom);
0236     GetValue(buffer, readElementId);
0237 
0238     // Creating a tag to be identified afterward
0239     G4int tagDictionary = readGroupId * 0x10000 + readElementId;
0240 
0241     // beginning of the pixels
0242     if (tagDictionary == 0x7FE00010) {
0243       // Following 2 fread's are modifications to original DICOM example
0244       // (Jonathan Madsen)
0245       if (!fImplicitEndian) rflag = std::fread(buffer, 2, 1, dicom);  // Reserved 2 bytes
0246       // (not used for pixels)
0247       rflag = std::fread(buffer, 4, 1, dicom);  // Element Length
0248       // (not used for pixels)
0249       break;  // Exit to ReadImageData()
0250     }
0251 
0252     // VR or element length
0253     rflag = std::fread(buffer, 2, 1, dicom);
0254     GetValue(buffer, elementLength2);
0255 
0256     // If value representation (VR) is OB, OW, SQ, UN, added OF and UT
0257     // the next length is 32 bits
0258     if ((elementLength2 == 0x424f ||  // "OB"
0259          elementLength2 == 0x574f ||  // "OW"
0260          elementLength2 == 0x464f ||  // "OF"
0261          elementLength2 == 0x5455 ||  // "UT"
0262          elementLength2 == 0x5153 ||  // "SQ"
0263          elementLength2 == 0x4e55)
0264         &&  // "UN"
0265         !fImplicitEndian)
0266     {  // explicit VR
0267 
0268       rflag = std::fread(buffer, 2, 1, dicom);  // Skip 2 reserved bytes
0269 
0270       // element length
0271       rflag = std::fread(buffer, 4, 1, dicom);
0272       GetValue(buffer, elementLength4);
0273 
0274       if (elementLength2 == 0x5153) {
0275         if (elementLength4 == 0xFFFFFFFF) {
0276           read_undefined_nested(dicom);
0277           elementLength4 = 0;
0278         }
0279         else {
0280           if (read_defined_nested(dicom, elementLength4) == 0) {
0281             G4Exception("DicomHandler::ReadFile", "DICOM001", FatalException,
0282                         "Function read_defined_nested() failed!");
0283           }
0284         }
0285       }
0286       else {
0287         // Reading the information with data
0288         rflag = std::fread(data, elementLength4, 1, dicom);
0289       }
0290     }
0291     else {
0292       //  explicit with VR different than previous ones
0293       if (!fImplicitEndian || readGroupId == 2) {
0294         // G4cout << "Reading  DICOM files with Explicit VR"<< G4endl;
0295         //  element length (2 bytes)
0296         rflag = std::fread(buffer, 2, 1, dicom);
0297         GetValue(buffer, elementLength2);
0298         elementLength4 = elementLength2;
0299 
0300         rflag = std::fread(data, elementLength4, 1, dicom);
0301       }
0302       else {  // Implicit VR
0303 
0304         // G4cout << "Reading  DICOM files with Implicit VR"<< G4endl;
0305 
0306         // element length (4 bytes)
0307         if (std::fseek(dicom, -2, SEEK_CUR) != 0) {
0308           G4Exception("DicomHandler::ReadFile", "DICOM001", FatalException, "fseek failed");
0309         }
0310 
0311         rflag = std::fread(buffer, 4, 1, dicom);
0312         GetValue(buffer, elementLength4);
0313 
0314         // G4cout <<  std::hex<< elementLength4 << G4endl;
0315 
0316         if (elementLength4 == 0xFFFFFFFF) {
0317           read_undefined_nested(dicom);
0318           elementLength4 = 0;
0319         }
0320         else {
0321           rflag = std::fread(data, elementLength4, 1, dicom);
0322         }
0323       }
0324     }
0325 
0326     // NULL termination
0327     data[elementLength4] = '\0';
0328 
0329     // analyzing information
0330     GetInformation(tagDictionary, data);
0331   }
0332 
0333   G4String fnameG4DCM = G4String(filename2) + ".g4dcm";
0334 
0335   // Perform functions originally written straight to file
0336   DicomPhantomZSliceHeader* zslice = new DicomPhantomZSliceHeader(fnameG4DCM);
0337   for (auto ite = fMaterialIndices.cbegin(); ite != fMaterialIndices.cend(); ++ite) {
0338     zslice->AddMaterial(ite->second);
0339   }
0340 
0341   zslice->SetNoVoxelsX(fColumns / fCompression);
0342   zslice->SetNoVoxelsY(fRows / fCompression);
0343   zslice->SetNoVoxelsZ(1);
0344 
0345   zslice->SetMinX(-fPixelSpacingX * fColumns / 2.);
0346   zslice->SetMaxX(fPixelSpacingX * fColumns / 2.);
0347 
0348   zslice->SetMinY(-fPixelSpacingY * fRows / 2.);
0349   zslice->SetMaxY(fPixelSpacingY * fRows / 2.);
0350 
0351   zslice->SetMinZ(fSliceLocation - fSliceThickness / 2.);
0352   zslice->SetMaxZ(fSliceLocation + fSliceThickness / 2.);
0353 
0354   //===
0355 
0356   ReadData(dicom, filename2);
0357 
0358   // DEPRECIATED
0359   // StoreData( foutG4DCM );
0360   // foutG4DCM.close();
0361 
0362   StoreData(zslice);
0363 
0364   // Dumped 2 file after DicomPhantomZSliceMerged has checked for consistency
0365   // zslice->DumpToFile();
0366 
0367   fMergedSlices->AddZSlice(zslice);
0368 
0369   //
0370   delete[] buffer;
0371   delete[] data;
0372 
0373   if (rflag) return returnvalue;
0374   return returnvalue;
0375 }
0376 
0377 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0378 
0379 void DicomHandler::GetInformation(G4int& tagDictionary, char* data)
0380 {
0381   if (tagDictionary == 0x00280010) {  // Number of Rows
0382     GetValue(data, fRows);
0383     std::printf("[0x00280010] Rows -> %i\n", fRows);
0384   }
0385   else if (tagDictionary == 0x00280011) {  // Number of fColumns
0386     GetValue(data, fColumns);
0387     std::printf("[0x00280011] Columns -> %i\n", fColumns);
0388   }
0389   else if (tagDictionary == 0x00280102) {  // High bits  ( not used )
0390     short highBits;
0391     GetValue(data, highBits);
0392     std::printf("[0x00280102] High bits -> %i\n", highBits);
0393   }
0394   else if (tagDictionary == 0x00280100) {  // Bits allocated
0395     GetValue(data, fBitAllocated);
0396     std::printf("[0x00280100] Bits allocated -> %i\n", fBitAllocated);
0397   }
0398   else if (tagDictionary == 0x00280101) {  //  Bits stored ( not used )
0399     short bitStored;
0400     GetValue(data, bitStored);
0401     std::printf("[0x00280101] Bits stored -> %i\n", bitStored);
0402   }
0403   else if (tagDictionary == 0x00280106) {  //  Min. pixel value
0404     GetValue(data, fMinPixelValue);
0405     std::printf("[0x00280106] Min. pixel value -> %i\n", fMinPixelValue);
0406   }
0407   else if (tagDictionary == 0x00280107) {  //  Max. pixel value
0408     GetValue(data, fMaxPixelValue);
0409     std::printf("[0x00280107] Max. pixel value -> %i\n", fMaxPixelValue);
0410   }
0411   else if (tagDictionary == 0x00281053) {  //  Rescale slope
0412     fRescaleSlope = atoi(data);
0413     std::printf("[0x00281053] Rescale Slope -> %d\n", fRescaleSlope);
0414   }
0415   else if (tagDictionary == 0x00281052) {  // Rescalse intercept
0416     fRescaleIntercept = atoi(data);
0417     std::printf("[0x00281052] Rescale Intercept -> %d\n", fRescaleIntercept);
0418   }
0419   else if (tagDictionary == 0x00280103) {
0420     //  Pixel representation ( functions not design to read signed bits )
0421     fPixelRepresentation = atoi(data);  // 0: unsigned  1: signed
0422     std::printf("[0x00280103] Pixel Representation -> %i\n", fPixelRepresentation);
0423     if (fPixelRepresentation == 1) {
0424       std::printf("### PIXEL REPRESENTATION = 1, BITS ARE SIGNED, ");
0425       std::printf("DICOM READING SCAN FOR UNSIGNED VALUE, POSSIBLE ");
0426       std::printf("ERROR !!!!!! -> \n");
0427     }
0428   }
0429   else if (tagDictionary == 0x00080006) {  //  Modality
0430     std::printf("[0x00080006] Modality -> %s\n", data);
0431   }
0432   else if (tagDictionary == 0x00080070) {  //  Manufacturer
0433     std::printf("[0x00080070] Manufacturer -> %s\n", data);
0434   }
0435   else if (tagDictionary == 0x00080080) {  //  Institution Name
0436     std::printf("[0x00080080] Institution Name -> %s\n", data);
0437   }
0438   else if (tagDictionary == 0x00080081) {  //  Institution Address
0439     std::printf("[0x00080081] Institution Address -> %s\n", data);
0440   }
0441   else if (tagDictionary == 0x00081040) {  //  Institution Department Name
0442     std::printf("[0x00081040] Institution Department Name -> %s\n", data);
0443   }
0444   else if (tagDictionary == 0x00081090) {  //  Manufacturer's Model Name
0445     std::printf("[0x00081090] Manufacturer's Model Name -> %s\n", data);
0446   }
0447   else if (tagDictionary == 0x00181000) {  //  Device Serial Number
0448     std::printf("[0x00181000] Device Serial Number -> %s\n", data);
0449   }
0450   else if (tagDictionary == 0x00080008) {  //  Image type ( not used )
0451     std::printf("[0x00080008] Image Types -> %s\n", data);
0452   }
0453   else if (tagDictionary == 0x00283000) {  // Modality LUT Sequence(not used)
0454     std::printf("[0x00283000] Modality LUT Sequence SQ 1 -> %s\n", data);
0455   }
0456   else if (tagDictionary == 0x00283002) {  // LUT Descriptor ( not used )
0457     std::printf("[0x00283002] LUT Descriptor US or SS 3 -> %s\n", data);
0458   }
0459   else if (tagDictionary == 0x00283003) {  // LUT Explanation ( not used )
0460     std::printf("[0x00283003] LUT Explanation LO 1 -> %s\n", data);
0461   }
0462   else if (tagDictionary == 0x00283004) {  // Modality LUT ( not used )
0463     std::printf("[0x00283004] Modality LUT Type LO 1 -> %s\n", data);
0464   }
0465   else if (tagDictionary == 0x00283006) {  // LUT Data ( not used )
0466     std::printf("[0x00283006] LUT Data US or SS -> %s\n", data);
0467   }
0468   else if (tagDictionary == 0x00283010) {  // VOI LUT ( not used )
0469     std::printf("[0x00283010] VOI LUT Sequence SQ 1 -> %s\n", data);
0470   }
0471   else if (tagDictionary == 0x00280120) {  // Pixel Padding Value (not used)
0472     std::printf("[0x00280120] Pixel Padding Value US or SS 1 -> %s\n", data);
0473   }
0474   else if (tagDictionary == 0x00280030) {  // Pixel Spacing
0475     G4String datas(data);
0476     G4int iss = G4int(datas.find('\\'));
0477     fPixelSpacingX = atof(datas.substr(0, iss).c_str());
0478     fPixelSpacingY = atof(datas.substr(iss + 1, datas.length()).c_str());
0479   }
0480   else if (tagDictionary == 0x00200037) {  // Image Orientation ( not used )
0481     std::printf("[0x00200037] Image Orientation (Phantom) -> %s\n", data);
0482   }
0483   else if (tagDictionary == 0x00200032) {  // Image Position ( not used )
0484     std::printf("[0x00200032] Image Position (Phantom,mm) -> %s\n", data);
0485   }
0486   else if (tagDictionary == 0x00180050) {  // Slice Thickness
0487     fSliceThickness = atof(data);
0488     std::printf("[0x00180050] Slice Thickness (mm) -> %f\n", fSliceThickness);
0489   }
0490   else if (tagDictionary == 0x00201041) {  // Slice Location
0491     fSliceLocation = atof(data);
0492     std::printf("[0x00201041] Slice Location -> %f\n", fSliceLocation);
0493   }
0494   else if (tagDictionary == 0x00280004) {  // Photometric Interpretation
0495     // ( not used )
0496     std::printf("[0x00280004] Photometric Interpretation -> %s\n", data);
0497   }
0498   else if (tagDictionary == 0x00020010) {  // Endian
0499     if (strcmp(data, "1.2.840.10008.1.2") == 0)
0500       fImplicitEndian = true;
0501     else if (strncmp(data, "1.2.840.10008.1.2.2", 19) == 0)
0502       fLittleEndian = false;
0503     // else 1.2.840..10008.1.2.1 (explicit little endian)
0504 
0505     std::printf("[0x00020010] Endian -> %s\n", data);
0506   }
0507 
0508   // others
0509   else {
0510     // std::printf("[0x%x] -> %s\n", tagDictionary, data);
0511     ;
0512   }
0513 }
0514 
0515 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0516 
0517 void DicomHandler::StoreData(DicomPhantomZSliceHeader* dcmPZSH)
0518 {
0519   G4int mean;
0520   G4double density;
0521   G4bool overflow = false;
0522 
0523   if (!dcmPZSH) {
0524     return;
0525   }
0526 
0527   dcmPZSH->SetSliceLocation(fSliceLocation);
0528 
0529   //----- Print indices of material
0530   if (fCompression == 1) {  // no fCompression: each pixel has a density value)
0531     for (G4int ww = 0; ww < fRows; ++ww) {
0532       dcmPZSH->AddRow();
0533       for (G4int xx = 0; xx < fColumns; ++xx) {
0534         mean = fTab[ww][xx];
0535         density = Pixel2density(mean);
0536         dcmPZSH->AddValue(density);
0537         dcmPZSH->AddMateID(GetMaterialIndex(G4float(density)));
0538       }
0539     }
0540   }
0541   else {
0542     // density value is the average of a square region of
0543     // fCompression*fCompression pixels
0544     for (G4int ww = 0; ww < fRows; ww += fCompression) {
0545       dcmPZSH->AddRow();
0546       for (G4int xx = 0; xx < fColumns; xx += fCompression) {
0547         overflow = false;
0548         mean = 0;
0549         for (G4int sumx = 0; sumx < fCompression; ++sumx) {
0550           for (G4int sumy = 0; sumy < fCompression; ++sumy) {
0551             if (ww + sumy >= fRows || xx + sumx >= fColumns) overflow = true;
0552             mean += fTab[ww + sumy][xx + sumx];
0553           }
0554           if (overflow) break;
0555         }
0556         mean /= fCompression * fCompression;
0557 
0558         if (!overflow) {
0559           density = Pixel2density(mean);
0560           dcmPZSH->AddValue(density);
0561           dcmPZSH->AddMateID(GetMaterialIndex(G4float(density)));
0562         }
0563       }
0564     }
0565   }
0566 
0567   dcmPZSH->FlipData();
0568 }
0569 
0570 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0571 // This function is depreciated as it is handled by
0572 // DicomPhantomZSliceHeader::DumpToFile
0573 void DicomHandler::StoreData(std::ofstream& foutG4DCM)
0574 {
0575   G4int mean;
0576   G4double density;
0577   G4bool overflow = false;
0578 
0579   //----- Print indices of material
0580   if (fCompression == 1) {  // no fCompression: each pixel has a density value)
0581     for (G4int ww = 0; ww < fRows; ++ww) {
0582       for (G4int xx = 0; xx < fColumns; ++xx) {
0583         mean = fTab[ww][xx];
0584         density = Pixel2density(mean);
0585         foutG4DCM << GetMaterialIndex(G4float(density)) << " ";
0586       }
0587       foutG4DCM << G4endl;
0588     }
0589   }
0590   else {
0591     // density value is the average of a square region of
0592     // fCompression*fCompression pixels
0593     for (G4int ww = 0; ww < fRows; ww += fCompression) {
0594       for (G4int xx = 0; xx < fColumns; xx += fCompression) {
0595         overflow = false;
0596         mean = 0;
0597         for (G4int sumx = 0; sumx < fCompression; ++sumx) {
0598           for (G4int sumy = 0; sumy < fCompression; ++sumy) {
0599             if (ww + sumy >= fRows || xx + sumx >= fColumns) overflow = true;
0600             mean += fTab[ww + sumy][xx + sumx];
0601           }
0602           if (overflow) break;
0603         }
0604         mean /= fCompression * fCompression;
0605 
0606         if (!overflow) {
0607           density = Pixel2density(mean);
0608           foutG4DCM << GetMaterialIndex(G4float(density)) << " ";
0609         }
0610       }
0611       foutG4DCM << G4endl;
0612     }
0613   }
0614 
0615   //----- Print densities
0616   if (fCompression == 1) {  // no fCompression: each pixel has a density value)
0617     for (G4int ww = 0; ww < fRows; ww++) {
0618       for (G4int xx = 0; xx < fColumns; xx++) {
0619         mean = fTab[ww][xx];
0620         density = Pixel2density(mean);
0621         foutG4DCM << density << " ";
0622         if (xx % 8 == 3) foutG4DCM << G4endl;  // just for nicer reading
0623       }
0624     }
0625   }
0626   else {
0627     // density value is the average of a square region of
0628     // fCompression*fCompression pixels
0629     for (G4int ww = 0; ww < fRows; ww += fCompression) {
0630       for (G4int xx = 0; xx < fColumns; xx += fCompression) {
0631         overflow = false;
0632         mean = 0;
0633         for (G4int sumx = 0; sumx < fCompression; ++sumx) {
0634           for (G4int sumy = 0; sumy < fCompression; ++sumy) {
0635             if (ww + sumy >= fRows || xx + sumx >= fColumns) overflow = true;
0636             mean += fTab[ww + sumy][xx + sumx];
0637           }
0638           if (overflow) break;
0639         }
0640         mean /= fCompression * fCompression;
0641 
0642         if (!overflow) {
0643           density = Pixel2density(mean);
0644           foutG4DCM << density << " ";
0645           if (xx / fCompression % 8 == 3) foutG4DCM << G4endl;  // just for nicer
0646           // reading
0647         }
0648       }
0649     }
0650   }
0651 }
0652 
0653 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..
0654 void DicomHandler::ReadMaterialIndices(std::ifstream& finData)
0655 {
0656   unsigned int nMate;
0657   G4String mateName;
0658   G4float densityMax;
0659   finData >> nMate;
0660   if (finData.eof()) return;
0661 
0662   G4cout << " ReadMaterialIndices " << nMate << G4endl;
0663   for (unsigned int ii = 0; ii < nMate; ++ii) {
0664     finData >> mateName >> densityMax;
0665     fMaterialIndices[densityMax] = mateName;
0666     //    G4cout << ii << " ReadMaterialIndices " << mateName << " "
0667     //     << densityMax << G4endl;
0668   }
0669 }
0670 
0671 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0672 
0673 unsigned int DicomHandler::GetMaterialIndex(G4float density)
0674 {
0675   std::map<G4float, G4String>::const_reverse_iterator ite;
0676   std::size_t ii = fMaterialIndices.size();
0677 
0678   for (ite = fMaterialIndices.crbegin(); ite != fMaterialIndices.crend(); ++ite, ii--) {
0679     if (density >= (*ite).first) {
0680       break;
0681     }
0682   }
0683 
0684   if (ii == fMaterialIndices.size()) {
0685     ii = fMaterialIndices.size() - 1;
0686   }
0687 
0688   return unsigned(ii);
0689 }
0690 
0691 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0692 
0693 G4int DicomHandler::ReadData(FILE* dicom, char* filename2)
0694 {
0695   G4int returnvalue = 0;
0696   size_t rflag = 0;
0697 
0698   //  READING THE PIXELS
0699 
0700   fTab = new G4int*[fRows];
0701   for (G4int i = 0; i < fRows; ++i) {
0702     fTab[i] = new G4int[fColumns];
0703   }
0704 
0705   if (fBitAllocated == 8) {  // Case 8 bits :
0706 
0707     std::printf("@@@ Error! Picture != 16 bits...\n");
0708     std::printf("@@@ Error! Picture != 16 bits...\n");
0709     std::printf("@@@ Error! Picture != 16 bits...\n");
0710 
0711     unsigned char ch = 0;
0712 
0713     for (G4int j = 0; j < fRows; ++j) {
0714       for (G4int i = 0; i < fColumns; ++i) {
0715         rflag = std::fread(&ch, 1, 1, dicom);
0716         fTab[j][i] = ch * fRescaleSlope + fRescaleIntercept;
0717       }
0718     }
0719     returnvalue = 1;
0720   }
0721   else {  //  from 12 to 16 bits :
0722     char sbuff[2];
0723     short pixel;
0724     for (G4int j = 0; j < fRows; ++j) {
0725       for (G4int i = 0; i < fColumns; ++i) {
0726         rflag = std::fread(sbuff, 2, 1, dicom);
0727         GetValue(sbuff, pixel);
0728         fTab[j][i] = pixel * fRescaleSlope + fRescaleIntercept;
0729       }
0730     }
0731   }
0732 
0733   // Creation of .g4 files wich contains averaged density data
0734   G4String nameProcessed = filename2 + G4String(".g4dcmb");
0735   FILE* fileOut = std::fopen(nameProcessed.c_str(), "w+b");
0736 
0737   G4cout << "### Writing of " << nameProcessed << " ###\n";
0738 
0739   unsigned int nMate = fMaterialIndices.size();
0740   rflag = std::fwrite(&nMate, sizeof(unsigned int), 1, fileOut);
0741   //--- Write materials
0742   for (auto ite = fMaterialIndices.cbegin(); ite != fMaterialIndices.cend(); ++ite) {
0743     G4String mateName = (*ite).second;
0744     for (std::size_t ii = (*ite).second.length(); ii < 40; ++ii) {
0745       mateName += " ";
0746     }  // mateName = const_cast<char*>(((*ite).second).c_str());
0747 
0748     const char* mateNameC = mateName.c_str();
0749     rflag = std::fwrite(mateNameC, sizeof(char), 40, fileOut);
0750   }
0751 
0752   unsigned int fRowsC = fRows / fCompression;
0753   unsigned int fColumnsC = fColumns / fCompression;
0754   unsigned int planesC = 1;
0755   G4float pixelLocationXM = -G4float(fPixelSpacingX * fColumns / 2.);
0756   G4float pixelLocationXP = G4float(fPixelSpacingX * fColumns / 2.);
0757   G4float pixelLocationYM = -G4float(fPixelSpacingY * fRows / 2.);
0758   G4float pixelLocationYP = G4float(fPixelSpacingY * fRows / 2.);
0759   G4float fSliceLocationZM = G4float(fSliceLocation - fSliceThickness / 2.);
0760   G4float fSliceLocationZP = G4float(fSliceLocation + fSliceThickness / 2.);
0761   //--- Write number of voxels (assume only one voxel in Z)
0762   rflag = std::fwrite(&fRowsC, sizeof(unsigned int), 1, fileOut);
0763   rflag = std::fwrite(&fColumnsC, sizeof(unsigned int), 1, fileOut);
0764   rflag = std::fwrite(&planesC, sizeof(unsigned int), 1, fileOut);
0765   //--- Write minimum and maximum extensions
0766   rflag = std::fwrite(&pixelLocationXM, sizeof(G4float), 1, fileOut);
0767   rflag = std::fwrite(&pixelLocationXP, sizeof(G4float), 1, fileOut);
0768   rflag = std::fwrite(&pixelLocationYM, sizeof(G4float), 1, fileOut);
0769   rflag = std::fwrite(&pixelLocationYP, sizeof(G4float), 1, fileOut);
0770   rflag = std::fwrite(&fSliceLocationZM, sizeof(G4float), 1, fileOut);
0771   rflag = std::fwrite(&fSliceLocationZP, sizeof(G4float), 1, fileOut);
0772   // rflag = std::fwrite(&fCompression, sizeof(unsigned int), 1, fileOut);
0773 
0774   std::printf("%8i   %8i\n", fRows, fColumns);
0775   std::printf("%8f   %8f\n", fPixelSpacingX, fPixelSpacingY);
0776   std::printf("%8f\n", fSliceThickness);
0777   std::printf("%8f\n", fSliceLocation);
0778   std::printf("%8i\n", fCompression);
0779 
0780   G4int compSize = fCompression;
0781   G4int mean;
0782   G4float density;
0783   G4bool overflow = false;
0784 
0785   //----- Write index of material for each pixel
0786   if (compSize == 1) {  // no fCompression: each pixel has a density value)
0787     for (G4int ww = 0; ww < fRows; ++ww) {
0788       for (G4int xx = 0; xx < fColumns; ++xx) {
0789         mean = fTab[ww][xx];
0790         density = Pixel2density(mean);
0791         unsigned int mateID = GetMaterialIndex(density);
0792         rflag = std::fwrite(&mateID, sizeof(unsigned int), 1, fileOut);
0793       }
0794     }
0795   }
0796   else {
0797     // density value is the average of a square region of
0798     // fCompression*fCompression pixels
0799     for (G4int ww = 0; ww < fRows; ww += compSize) {
0800       for (G4int xx = 0; xx < fColumns; xx += compSize) {
0801         overflow = false;
0802         mean = 0;
0803         for (G4int sumx = 0; sumx < compSize; ++sumx) {
0804           for (G4int sumy = 0; sumy < compSize; ++sumy) {
0805             if (ww + sumy >= fRows || xx + sumx >= fColumns) overflow = true;
0806             mean += fTab[ww + sumy][xx + sumx];
0807           }
0808           if (overflow) break;
0809         }
0810         mean /= compSize * compSize;
0811 
0812         if (!overflow) {
0813           density = Pixel2density(mean);
0814           unsigned int mateID = GetMaterialIndex(density);
0815           rflag = std::fwrite(&mateID, sizeof(unsigned int), 1, fileOut);
0816         }
0817       }
0818     }
0819   }
0820 
0821   //----- Write density for each pixel
0822   if (compSize == 1) {  // no fCompression: each pixel has a density value)
0823     for (G4int ww = 0; ww < fRows; ++ww) {
0824       for (G4int xx = 0; xx < fColumns; ++xx) {
0825         mean = fTab[ww][xx];
0826         density = Pixel2density(mean);
0827         rflag = std::fwrite(&density, sizeof(G4float), 1, fileOut);
0828       }
0829     }
0830   }
0831   else {
0832     // density value is the average of a square region of
0833     // fCompression*fCompression pixels
0834     for (G4int ww = 0; ww < fRows; ww += compSize) {
0835       for (G4int xx = 0; xx < fColumns; xx += compSize) {
0836         overflow = false;
0837         mean = 0;
0838         for (G4int sumx = 0; sumx < compSize; ++sumx) {
0839           for (G4int sumy = 0; sumy < compSize; ++sumy) {
0840             if (ww + sumy >= fRows || xx + sumx >= fColumns) overflow = true;
0841             mean += fTab[ww + sumy][xx + sumx];
0842           }
0843           if (overflow) break;
0844         }
0845         mean /= compSize * compSize;
0846 
0847         if (!overflow) {
0848           density = Pixel2density(mean);
0849           rflag = std::fwrite(&density, sizeof(G4float), 1, fileOut);
0850         }
0851       }
0852     }
0853   }
0854 
0855   rflag = std::fclose(fileOut);
0856 
0857   delete[] nameProcessed;
0858 
0859   /*    for ( G4int i = 0; i < fRows; i ++ ) {
0860         delete [] fTab[i];
0861         }
0862      delete [] fTab;
0863   */
0864 
0865   if (rflag) return returnvalue;
0866   return returnvalue;
0867 }
0868 
0869 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.......
0870 
0871 // DICOM HEAD does not use the calibration curve
0872 
0873 #ifdef DICOM_USE_HEAD
0874 void DicomHandler::ReadCalibration()
0875 {
0876   fNbrequali = 0;
0877   fReadCalibration = false;
0878   G4cout << "No calibration curve for the DICOM HEAD needed!" << G4endl;
0879 }
0880 #else
0881 // Separated out of Pixel2density
0882 // No need to read in same calibration EVERY time
0883 // Increases the speed of reading file by several orders of magnitude
0884 
0885 void DicomHandler::ReadCalibration()
0886 {
0887   fNbrequali = 0;
0888   // CT2Density.dat contains the calibration curve to convert CT (Hounsfield)
0889   // number to physical density
0890   std::ifstream calibration(fCt2DensityFile.c_str());
0891   calibration >> fNbrequali;
0892   fValueDensity = new G4double[fNbrequali];
0893   fValueCT = new G4double[fNbrequali];
0894 
0895   if (!calibration) {
0896     G4Exception("DicomHandler::ReadFile", "DICOM001", FatalException,
0897                 "@@@ No value to transform pixels in density!");
0898   }
0899   else {  // calibration was successfully opened
0900     for (G4int i = 0; i < fNbrequali; ++i) {  // Loop to store all the pts in CT2Density.dat
0901       calibration >> fValueCT[i] >> fValueDensity[i];
0902     }
0903   }
0904   calibration.close();
0905   fReadCalibration = true;
0906 }
0907 #endif
0908 
0909 #ifdef DICOM_USE_HEAD
0910 G4float DicomHandler::Pixel2density(G4int pixel)
0911 {
0912   G4float density = -1;
0913 
0914   // Air
0915   if (pixel == -998.) density = 0.001290;
0916   // Soft Tissue
0917   else if (pixel == 24.)
0918     density = 1.00;
0919   // Brain
0920   else if (pixel == 52.)
0921     density = 1.03;
0922   // Spinal disc
0923   else if (pixel == 92.)
0924     density = 1.10;
0925   // Trabecular bone
0926   else if (pixel == 197.)
0927     density = 1.18;
0928   // Cortical Bone
0929   else if (pixel == 923.)
0930     density = 1.85;
0931   // Tooth dentine
0932   else if (pixel == 1280.)
0933     density = 2.14;
0934   // Tooth enamel
0935   else if (pixel == 2310.)
0936     density = 2.89;
0937 
0938   return density;
0939 }
0940 
0941 #else
0942 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
0943 
0944 G4float DicomHandler::Pixel2density(G4int pixel)
0945 {
0946   if (!fReadCalibration) {
0947     ReadCalibration();
0948   }
0949 
0950   G4float density = -1.;
0951   G4double deltaCT = 0;
0952   G4double deltaDensity = 0;
0953 
0954   for (G4int j = 1; j < fNbrequali; ++j) {
0955     if (pixel >= fValueCT[j - 1] && pixel < fValueCT[j]) {
0956       deltaCT = fValueCT[j] - fValueCT[j - 1];
0957       deltaDensity = fValueDensity[j] - fValueDensity[j - 1];
0958 
0959       // interpolating linearly
0960       density = G4float(fValueDensity[j] - ((fValueCT[j] - pixel) * deltaDensity / deltaCT));
0961       break;
0962     }
0963   }
0964 
0965   if (density < 0.) {
0966     std::printf(
0967       "@@@ Error density = %f && Pixel = %i \
0968       (0x%x) && deltaDensity/deltaCT = %f\n",
0969       density, pixel, pixel, deltaDensity / deltaCT);
0970   }
0971 
0972   return density;
0973 }
0974 #endif
0975 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0976 
0977 void DicomHandler::CheckFileFormat()
0978 {
0979   std::ifstream checkData(fDriverFile.c_str());
0980   char* oneLine = new char[128];
0981 
0982   if (!(checkData.is_open())) {  // Check existance of Data.dat
0983 
0984     G4String message = "\nDicomG4 needs Data.dat (or another driver file specified";
0985     message += " in command line):\n";
0986     message += "\tFirst line: number of image pixel for a voxel (G4Box)\n";
0987     message += "\tSecond line: number of images (CT slices) to read\n";
0988     message += "\tEach following line contains the name of a Dicom image";
0989     message += " except for the .dcm extension";
0990     G4Exception("DicomHandler::ReadFile", "DICOM001", FatalException, message.c_str());
0991   }
0992 
0993   checkData >> fCompression;
0994   checkData >> fNFiles;
0995   G4String oneName;
0996   checkData.getline(oneLine, 100);
0997   std::ifstream testExistence;
0998   G4bool existAlready = true;
0999   for (G4int rep = 0; rep < fNFiles; ++rep) {
1000     checkData.getline(oneLine, 100);
1001     oneName = oneLine;
1002     oneName += ".g4dcm";  // create dicomFile.g4dcm
1003     G4cout << fNFiles << " test file " << oneName << G4endl;
1004     testExistence.open(oneName.data());
1005     if (!(testExistence.is_open())) {
1006       existAlready = false;
1007       testExistence.clear();
1008       testExistence.close();
1009     }
1010     testExistence.clear();
1011     testExistence.close();
1012   }
1013 
1014   ReadMaterialIndices(checkData);
1015 
1016   checkData.close();
1017   delete[] oneLine;
1018 
1019   if (existAlready == false) {  // The files *.g4dcm have to be created
1020 
1021     G4cout << "\nAll the necessary images were not found in processed form "
1022            << ", starting with .dcm images\n";
1023 
1024     FILE* dicom;
1025     FILE* lecturePref;
1026     char* fCompressionc = new char[LINEBUFFSIZE];
1027     char* maxc = new char[LINEBUFFSIZE];
1028     // char name[300], inputFile[300];
1029     char* inputFile = new char[FILENAMESIZE];
1030     G4int rflag;
1031     lecturePref = std::fopen(fDriverFile.c_str(), "r");
1032 
1033     rflag = std::fscanf(lecturePref, "%s", fCompressionc);
1034     fCompression = atoi(fCompressionc);
1035     rflag = std::fscanf(lecturePref, "%s", maxc);
1036     fNFiles = atoi(maxc);
1037     G4cout << " fNFiles " << fNFiles << G4endl;
1038 
1039     /////////////////////
1040 
1041 #ifdef DICOM_USE_HEAD
1042     for (G4int i = 1; i <= fNFiles; ++i) {  // Begin loop on filenames
1043       rflag = std::fscanf(lecturePref, "%s", inputFile);
1044       G4String path = GetDicomDataPath() + "/";
1045 
1046       G4String name = inputFile + G4String(".dcm");
1047       // Writes the results to a character string buffer.
1048 
1049       G4String name2 = path + name;
1050       //  Open input file and give it to gestion_dicom :
1051       G4cout << "### Opening " << name2 << " and reading :\n";
1052       dicom = std::fopen(name2.c_str(), "rb");
1053       // Reading the .dcm in two steps:
1054       //      1.  reading the header
1055       //      2. reading the pixel data and store the density in Moyenne.dat
1056       if (dicom != 0) {
1057         ReadFile(dicom, inputFile);
1058       }
1059       else {
1060         G4cout << "\nError opening file : " << name2 << G4endl;
1061       }
1062       rflag = std::fclose(dicom);
1063     }
1064 #else
1065 
1066     for (G4int i = 1; i <= fNFiles; ++i) {  // Begin loop on filenames
1067       rflag = std::fscanf(lecturePref, "%s", inputFile);
1068 
1069       G4String name = inputFile + G4String(".dcm");
1070       // Writes the results to a character string buffer.
1071 
1072       // G4cout << "check: " << name << G4endl;
1073       //  Open input file and give it to gestion_dicom :
1074       G4cout << "### Opening " << name << " and reading :\n";
1075       dicom = std::fopen(name.c_str(), "rb");
1076       // Reading the .dcm in two steps:
1077       //      1.  reading the header
1078       //      2. reading the pixel data and store the density in Moyenne.dat
1079       if (dicom != 0) {
1080         ReadFile(dicom, inputFile);
1081       }
1082       else {
1083         G4cout << "\nError opening file : " << name << G4endl;
1084       }
1085       rflag = std::fclose(dicom);
1086     }
1087 #endif
1088 
1089     rflag = std::fclose(lecturePref);
1090 
1091     // Checks the spacing is correct. Dumps to files
1092     fMergedSlices->CheckSlices();
1093 
1094     delete[] fCompressionc;
1095     delete[] maxc;
1096     delete[] inputFile;
1097     if (rflag) return;
1098   }
1099 
1100   if (fValueDensity) {
1101     delete[] fValueDensity;
1102   }
1103   if (fValueCT) {
1104     delete[] fValueCT;
1105   }
1106   if (fMergedSlices) {
1107     delete fMergedSlices;
1108   }
1109 }
1110 
1111 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1112 
1113 G4int DicomHandler::read_defined_nested(FILE* nested, G4int SQ_Length)
1114 {
1115   //      VARIABLES
1116   unsigned short item_GroupNumber;
1117   unsigned short item_ElementNumber;
1118   G4int item_Length;
1119   G4int items_array_length = 0;
1120   char* buffer = new char[LINEBUFFSIZE];
1121   size_t rflag = 0;
1122 
1123   while (items_array_length < SQ_Length) {
1124     rflag = std::fread(buffer, 2, 1, nested);
1125     GetValue(buffer, item_GroupNumber);
1126 
1127     rflag = std::fread(buffer, 2, 1, nested);
1128     GetValue(buffer, item_ElementNumber);
1129 
1130     rflag = std::fread(buffer, 4, 1, nested);
1131     GetValue(buffer, item_Length);
1132 
1133     rflag = std::fread(buffer, item_Length, 1, nested);
1134 
1135     items_array_length = items_array_length + 8 + item_Length;
1136   }
1137 
1138   delete[] buffer;
1139 
1140   if (SQ_Length > items_array_length)
1141     return 0;
1142   else
1143     return 1;
1144   if (rflag) return 1;
1145 }
1146 
1147 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
1148 
1149 void DicomHandler::read_undefined_nested(FILE* nested)
1150 {
1151   //      VARIABLES
1152   unsigned short item_GroupNumber;
1153   unsigned short item_ElementNumber;
1154   unsigned int item_Length;
1155   char* buffer = new char[LINEBUFFSIZE];
1156   size_t rflag = 0;
1157 
1158   do {
1159     rflag = std::fread(buffer, 2, 1, nested);
1160     GetValue(buffer, item_GroupNumber);
1161 
1162     rflag = std::fread(buffer, 2, 1, nested);
1163     GetValue(buffer, item_ElementNumber);
1164 
1165     rflag = std::fread(buffer, 4, 1, nested);
1166     GetValue(buffer, item_Length);
1167 
1168     if (item_Length != 0xffffffff)
1169       rflag = std::fread(buffer, item_Length, 1, nested);
1170     else
1171       read_undefined_item(nested);
1172 
1173   } while (item_GroupNumber != 0xFFFE || item_ElementNumber != 0xE0DD || item_Length != 0);
1174 
1175   delete[] buffer;
1176   if (rflag) return;
1177 }
1178 
1179 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
1180 
1181 void DicomHandler::read_undefined_item(FILE* nested)
1182 {
1183   //      VARIABLES
1184   unsigned short item_GroupNumber;
1185   unsigned short item_ElementNumber;
1186   G4int item_Length;
1187   size_t rflag = 0;
1188   char* buffer = new char[LINEBUFFSIZE];
1189 
1190   do {
1191     rflag = std::fread(buffer, 2, 1, nested);
1192     GetValue(buffer, item_GroupNumber);
1193 
1194     rflag = std::fread(buffer, 2, 1, nested);
1195     GetValue(buffer, item_ElementNumber);
1196 
1197     rflag = std::fread(buffer, 4, 1, nested);
1198     GetValue(buffer, item_Length);
1199 
1200     if (item_Length != 0) rflag = std::fread(buffer, item_Length, 1, nested);
1201 
1202   } while (item_GroupNumber != 0xFFFE || item_ElementNumber != 0xE00D || item_Length != 0);
1203 
1204   delete[] buffer;
1205   if (rflag) return;
1206 }
1207 
1208 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
1209 
1210 template<class Type>
1211 void DicomHandler::GetValue(char* _val, Type& _rval)
1212 {
1213 #if BYTE_ORDER == BIG_ENDIAN
1214   if (fLittleEndian) {  // little endian
1215 #else  // BYTE_ORDER == LITTLE_ENDIAN
1216   if (!fLittleEndian) {  // big endian
1217 #endif
1218     const G4int SIZE = sizeof(_rval);
1219     char ctemp;
1220     for (G4int i = 0; i < SIZE / 2; ++i) {
1221       ctemp = _val[i];
1222       _val[i] = _val[SIZE - 1 - i];
1223       _val[SIZE - 1 - i] = ctemp;
1224     }
1225   }
1226   _rval = *(Type*)_val;
1227 }
1228 
1229 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....