64 : DATABUFFSIZE(8192), LINEBUFFSIZE(5020), FILENAMESIZE(512),
65 fCompression(0), fNFiles(0), fRows(0), fColumns(0),
66 fBitAllocated(0), fMaxPixelValue(0), fMinPixelValue(0),
67 fPixelSpacingX(0.), fPixelSpacingY(0.),
68 fSliceThickness(0.), fSliceLocation(0.),
69 fRescaleIntercept(0), fRescaleSlope(0),
70 fLittleEndian(true), fImplicitEndian(false),
71 fPixelRepresentation(0) {
84 G4int returnvalue = 0;
size_t rflag = 0;
85 char *
buffer =
new char[LINEBUFFSIZE];
87 fImplicitEndian =
false;
90 rflag = std::fread( buffer, 1, 128, dicom );
93 rflag = std::fread( buffer, 1, 4, dicom );
95 if(std::strncmp(
"DICM", buffer, 4) != 0) {
97 fImplicitEndian =
true;
102 short elementLength2;
104 unsigned long elementLength4;
106 char *
data =
new char[DATABUFFSIZE];
116 rflag = std::fread(buffer, 2, 1, dicom);
117 GetValue(buffer, readGroupId);
119 rflag = std::fread(buffer, 2, 1, dicom);
120 GetValue(buffer, readElementId);
123 G4int tagDictionary = readGroupId*0x10000 + readElementId;
126 if(tagDictionary == 0x7FE00010)
break;
129 rflag = std::fread(buffer,2,1,dicom);
130 GetValue(buffer, elementLength2);
134 if((elementLength2 == 0x424f ||
135 elementLength2 == 0x574f ||
136 elementLength2 == 0x464f ||
137 elementLength2 == 0x5455 ||
138 elementLength2 == 0x5153 ||
139 elementLength2 == 0x4e55) &&
142 rflag = std::fread(buffer, 2, 1, dicom);
145 rflag = std::fread(buffer, 4, 1, dicom);
146 GetValue(buffer, elementLength4);
148 if(elementLength2 == 0x5153)
150 if(elementLength4 == 0xFFFFFFFF)
152 read_undefined_nested( dicom );
155 if(read_defined_nested( dicom, elementLength4 )==0){
156 G4cerr <<
"Function read_defined_nested() failed!" <<
G4endl;
161 rflag = std::fread(data, elementLength4,1,dicom);
167 if(!fImplicitEndian || readGroupId == 2) {
171 rflag = std::fread(buffer, 2, 1, dicom);
172 GetValue(buffer, elementLength2);
173 elementLength4 = elementLength2;
175 rflag = std::fread(data, elementLength4, 1, dicom);
182 if(std::fseek(dicom, -2,
SEEK_CUR) != 0) {
186 rflag = std::fread(buffer, 4, 1, dicom);
187 GetValue(buffer, elementLength4);
191 if(elementLength4 == 0xFFFFFFFF)
193 read_undefined_nested(dicom);
196 rflag = std::fread(data, elementLength4, 1, dicom);
203 data[elementLength4] =
'\0';
206 GetInformation(tagDictionary, data);
210 std::ofstream foutG4DCM;
212 foutG4DCM.open(fnameG4DCM);
213 G4cout <<
"### Writing of " << fnameG4DCM <<
" ### " <<
G4endl;
215 foutG4DCM << fMaterialIndices.size() <<
G4endl;
218 std::map<G4float,G4String>::const_iterator ite;
219 for( ite = fMaterialIndices.begin(); ite != fMaterialIndices.end(); ite++, ii++ ){
220 foutG4DCM << ii <<
" " << (*ite).second <<
G4endl;
223 foutG4DCM << fColumns/fCompression <<
" " << fRows/fCompression <<
" 1 " <<
G4endl;
225 foutG4DCM << -fPixelSpacingX*fColumns/2. <<
" " << fPixelSpacingX*fColumns/2. <<
G4endl;
226 foutG4DCM << -fPixelSpacingY*fRows/2. <<
" " << fPixelSpacingY*fRows/2. <<
228 foutG4DCM << fSliceLocation-fSliceThickness/2. <<
" " << fSliceLocation+fSliceThickness/2. <<
G4endl;
233 StoreData( foutG4DCM );
241 if (rflag)
return returnvalue;
246 void DicomHandler::GetInformation(
G4int & tagDictionary,
char *
data) {
247 if(tagDictionary == 0x00280010 ) {
248 GetValue(data, fRows);
251 }
else if(tagDictionary == 0x00280011 ) {
252 GetValue(data, fColumns);
253 std::printf(
"[0x00280011] Columns -> %i\n",fColumns);
255 }
else if(tagDictionary == 0x00280102 ) {
257 GetValue(data, highBits);
258 std::printf(
"[0x00280102] High bits -> %i\n",highBits);
260 }
else if(tagDictionary == 0x00280100 ) {
261 GetValue(data, fBitAllocated);
262 std::printf(
"[0x00280100] Bits allocated -> %i\n", fBitAllocated);
264 }
else if(tagDictionary == 0x00280101 ) {
266 GetValue(data, bitStored);
267 std::printf(
"[0x00280101] Bits stored -> %i\n",bitStored);
269 }
else if(tagDictionary == 0x00280106 ) {
270 GetValue(data, fMinPixelValue);
271 std::printf(
"[0x00280106] Min. pixel value -> %i\n", fMinPixelValue);
273 }
else if(tagDictionary == 0x00280107 ) {
274 GetValue(data, fMaxPixelValue);
275 std::printf(
"[0x00280107] Max. pixel value -> %i\n", fMaxPixelValue);
277 }
else if(tagDictionary == 0x00281053) {
278 fRescaleSlope = atoi(data);
279 std::printf(
"[0x00281053] Rescale Slope -> %d\n", fRescaleSlope);
281 }
else if(tagDictionary == 0x00281052 ) {
282 fRescaleIntercept = atoi(data);
283 std::printf(
"[0x00281052] Rescale Intercept -> %d\n", fRescaleIntercept );
285 }
else if(tagDictionary == 0x00280103 ) {
287 fPixelRepresentation = atoi(data);
288 std::printf(
"[0x00280103] Pixel Representation -> %i\n", fPixelRepresentation);
289 if(fPixelRepresentation == 1 ) {
290 std::printf(
"### PIXEL REPRESENTATION = 1, BITS ARE SIGNED, ");
291 std::printf(
"DICOM READING SCAN FOR UNSIGNED VALUE, POSSIBLE ");
295 }
else if(tagDictionary == 0x00080006 ) {
296 std::printf(
"[0x00080006] Modality -> %s\n", data);
298 }
else if(tagDictionary == 0x00080070 ) {
299 std::printf(
"[0x00080070] Manufacturer -> %s\n", data);
301 }
else if(tagDictionary == 0x00080080 ) {
302 std::printf(
"[0x00080080] Institution Name -> %s\n", data);
304 }
else if(tagDictionary == 0x00080081 ) {
305 std::printf(
"[0x00080081] Institution Address -> %s\n", data);
307 }
else if(tagDictionary == 0x00081040 ) {
308 std::printf(
"[0x00081040] Institution Department Name -> %s\n", data);
310 }
else if(tagDictionary == 0x00081090 ) {
311 std::printf(
"[0x00081090] Manufacturer's Model Name -> %s\n", data);
313 }
else if(tagDictionary == 0x00181000 ) {
314 std::printf(
"[0x00181000] Device Serial Number -> %s\n", data);
316 }
else if(tagDictionary == 0x00080008 ) {
317 std::printf(
"[0x00080008] Image Types -> %s\n", data);
319 }
else if(tagDictionary == 0x00283000 ) {
320 std::printf(
"[0x00283000] Modality LUT Sequence SQ 1 -> %s\n", data);
322 }
else if(tagDictionary == 0x00283002 ) {
323 std::printf(
"[0x00283002] LUT Descriptor US or SS 3 -> %s\n", data);
325 }
else if(tagDictionary == 0x00283003 ) {
326 std::printf(
"[0x00283003] LUT Explanation LO 1 -> %s\n", data);
328 }
else if(tagDictionary == 0x00283004 ) {
329 std::printf(
"[0x00283004] Modality LUT Type LO 1 -> %s\n", data);
331 }
else if(tagDictionary == 0x00283006 ) {
332 std::printf(
"[0x00283006] LUT Data US or SS -> %s\n", data);
334 }
else if(tagDictionary == 0x00283010 ) {
335 std::printf(
"[0x00283010] VOI LUT Sequence SQ 1 -> %s\n", data);
337 }
else if(tagDictionary == 0x00280120 ) {
338 std::printf(
"[0x00280120] Pixel Padding Value US or SS 1 -> %s\n", data);
340 }
else if(tagDictionary == 0x00280030 ) {
342 int iss = datas.find(
'\\');
343 fPixelSpacingX = atof( datas.substr(0,iss).c_str() );
344 fPixelSpacingY = atof( datas.substr(iss+2,datas.length()).c_str() );
346 }
else if(tagDictionary == 0x00200037 ) {
347 std::printf(
"[0x00200037] Image Orientation (Phantom) -> %s\n", data);
349 }
else if(tagDictionary == 0x00200032 ) {
350 std::printf(
"[0x00200032] Image Position (Phantom,mm) -> %s\n", data);
352 }
else if(tagDictionary == 0x00180050 ) {
353 fSliceThickness = atof(data);
354 std::printf(
"[0x00180050] Slice Thickness (mm) -> %f\n", fSliceThickness);
356 }
else if(tagDictionary == 0x00201041 ) {
357 fSliceLocation = atof(data);
358 std::printf(
"[0x00201041] Slice Location -> %f\n", fSliceLocation);
360 }
else if(tagDictionary == 0x00280004 ) {
361 std::printf(
"[0x00280004] Photometric Interpretation -> %s\n", data);
363 }
else if(tagDictionary == 0x00020010) {
364 if(strcmp(data,
"1.2.840.10008.1.2") == 0)
365 fImplicitEndian =
true;
366 else if(strncmp(data,
"1.2.840.10008.1.2.2", 19) == 0)
367 fLittleEndian =
false;
382 void DicomHandler::StoreData(std::ofstream& foutG4DCM)
389 if(fCompression == 1) {
390 for(
G4int ww = 0; ww < fRows; ww++) {
393 density = Pixel2density(mean);
394 foutG4DCM << GetMaterialIndex( density ) <<
" ";
402 for(
G4int ww = 0; ww < fRows ;ww += fCompression ) {
403 for(
G4int xx = 0;
xx < fColumns ;
xx +=fCompression ) {
406 for(
int sumx = 0; sumx < fCompression; sumx++) {
407 for(
int sumy = 0; sumy < fCompression; sumy++) {
408 if(ww+sumy >= fRows ||
xx+sumx >= fColumns) overflow =
true;
409 mean += fTab[ww+sumy][
xx+sumx];
413 mean /= fCompression*fCompression;
416 density = Pixel2density(mean);
417 foutG4DCM << GetMaterialIndex( density ) <<
" ";
426 if(fCompression == 1) {
427 for(
G4int ww = 0; ww < fRows; ww++) {
430 density = Pixel2density(mean);
431 foutG4DCM << density <<
" ";
432 if(
xx%8 == 3 ) foutG4DCM <<
G4endl;
439 for(
G4int ww = 0; ww < fRows ;ww += fCompression ) {
440 for(
G4int xx = 0;
xx < fColumns ;
xx +=fCompression ) {
443 for(
int sumx = 0; sumx < fCompression; sumx++) {
444 for(
int sumy = 0; sumy < fCompression; sumy++) {
445 if(ww+sumy >= fRows ||
xx+sumx >= fColumns) overflow =
true;
446 mean += fTab[ww+sumy][
xx+sumx];
450 mean /= fCompression*fCompression;
453 density = Pixel2density(mean);
454 foutG4DCM << density <<
" ";
455 if(
xx/fCompression%8 == 3 ) foutG4DCM <<
G4endl;
465 void DicomHandler::ReadMaterialIndices( std::ifstream& finData)
471 if( finData.eof() )
return;
474 for(
unsigned int ii = 0; ii < nMate; ii++ ){
475 finData >> mateName >> densityMax;
476 fMaterialIndices[densityMax] = mateName;
477 G4cout << ii <<
" ReadMaterialIndices " << mateName <<
" " << densityMax <<
G4endl;
483 unsigned int DicomHandler::GetMaterialIndex(
G4float density )
485 std::map<G4float,G4String>::reverse_iterator ite;
486 G4int ii = fMaterialIndices.size();
487 for( ite = fMaterialIndices.rbegin(); ite != fMaterialIndices.rend(); ite++, ii-- ) {
488 if( density >= (*ite).first ) {
500 G4int returnvalue = 0;
size_t rflag = 0;
505 fTab =
new G4int*[fRows];
506 for (
G4int i = 0; i < fRows; i ++ ) {
507 fTab[i] =
new G4int[fColumns];
510 if(fBitAllocated == 8) {
516 unsigned char ch = 0;
518 for(
G4int j = 0; j < fRows; j++) {
519 for(
G4int i = 0; i < fColumns; i++) {
521 rflag = std::fread( &ch, 1, 1, dicom);
522 fTab[j][i] = ch*fRescaleSlope + fRescaleIntercept;
530 for(
G4int j = 0; j < fRows; j++) {
531 for(
G4int i = 0; i < fColumns; i++) {
533 rflag = std::fread(sbuff, 2, 1, dicom);
534 GetValue(sbuff, pixel);
535 fTab[j][i] = pixel*fRescaleSlope + fRescaleIntercept;
541 char * nameProcessed =
new char[FILENAMESIZE];
544 std::sprintf(nameProcessed,
"%s.g4dcmb",filename2);
545 fileOut = std::fopen(nameProcessed,
"w+b");
546 std::printf(
"### Writing of %s ###\n",nameProcessed);
548 unsigned int nMate = fMaterialIndices.size();
549 rflag = std::fwrite(&nMate,
sizeof(
unsigned int), 1, fileOut);
551 std::map<G4float,G4String>::const_iterator ite;
552 for( ite = fMaterialIndices.begin(); ite != fMaterialIndices.end(); ite++ ){
554 for(
G4int ii = (*ite).second.length(); ii < 40; ii++ ) {
558 const char* mateNameC = mateName.c_str();
559 rflag = std::fwrite(mateNameC,
sizeof(
char),40, fileOut);
562 unsigned int fRowsC = fRows/fCompression;
563 unsigned int fColumnsC = fColumns/fCompression;
564 unsigned int planesC = 1;
565 G4float pixelLocationXM = -fPixelSpacingX*fColumns/2.;
566 G4float pixelLocationXP = fPixelSpacingX*fColumns/2.;
567 G4float pixelLocationYM = -fPixelSpacingY*fRows/2.;
568 G4float pixelLocationYP = fPixelSpacingY*fRows/2.;
569 G4float fSliceLocationZM = fSliceLocation-fSliceThickness/2.;
570 G4float fSliceLocationZP = fSliceLocation+fSliceThickness/2.;
572 rflag = std::fwrite(&fRowsC,
sizeof(
unsigned int), 1, fileOut);
573 rflag = std::fwrite(&fColumnsC,
sizeof(
unsigned int), 1, fileOut);
574 rflag = std::fwrite(&planesC,
sizeof(
unsigned int), 1, fileOut);
576 rflag = std::fwrite(&pixelLocationXM,
sizeof(
G4float), 1, fileOut);
577 rflag = std::fwrite(&pixelLocationXP,
sizeof(
G4float), 1, fileOut);
578 rflag = std::fwrite(&pixelLocationYM,
sizeof(
G4float), 1, fileOut);
579 rflag = std::fwrite(&pixelLocationYP,
sizeof(
G4float), 1, fileOut);
580 rflag = std::fwrite(&fSliceLocationZM,
sizeof(
G4float), 1, fileOut);
581 rflag = std::fwrite(&fSliceLocationZP,
sizeof(
G4float), 1, fileOut);
585 std::printf(
"%8f %8f\n",fPixelSpacingX,fPixelSpacingY);
590 G4int compSize = fCompression;
597 for(
G4int ww = 0; ww < fRows; ww++) {
600 density = Pixel2density(mean);
601 unsigned int mateID = GetMaterialIndex( density );
602 rflag = std::fwrite(&mateID,
sizeof(
unsigned int), 1, fileOut);
609 for(
G4int ww = 0; ww < fRows ;ww += compSize ) {
613 for(
int sumx = 0; sumx < compSize; sumx++) {
614 for(
int sumy = 0; sumy < compSize; sumy++) {
615 if(ww+sumy >= fRows ||
xx+sumx >= fColumns) overflow =
true;
616 mean += fTab[ww+sumy][
xx+sumx];
620 mean /= compSize*compSize;
623 density = Pixel2density(mean);
624 unsigned int mateID = GetMaterialIndex( density );
625 rflag = std::fwrite(&mateID,
sizeof(
unsigned int), 1, fileOut);
634 for(
G4int ww = 0; ww < fRows; ww++) {
637 density = Pixel2density(mean);
638 rflag = std::fwrite(&density,
sizeof(
G4float), 1, fileOut);
645 for(
G4int ww = 0; ww < fRows ;ww += compSize ) {
649 for(
int sumx = 0; sumx < compSize; sumx++) {
650 for(
int sumy = 0; sumy < compSize; sumy++) {
651 if(ww+sumy >= fRows ||
xx+sumx >= fColumns) overflow =
true;
652 mean += fTab[ww+sumy][
xx+sumx];
656 mean /= compSize*compSize;
659 density = Pixel2density(mean);
660 rflag = std::fwrite(&density,
sizeof(
G4float), 1, fileOut);
669 delete [] nameProcessed;
677 if (rflag)
return returnvalue;
703 std::ifstream calibration(
"CT2Density.dat");
704 calibration >> nbrequali;
710 G4cerr <<
"@@@ No value to transform pixels in density!" <<
G4endl;
714 for(
G4int i = 0; i < nbrequali; i++) {
715 calibration >> valueCT[i] >> valuedensity[i];
720 for(
G4int j = 1; j < nbrequali; j++) {
721 if( pixel >= valueCT[j-1] && pixel < valueCT[j]) {
723 deltaCT = valueCT[j] - valueCT[j-1];
724 deltaDensity = valuedensity[j] - valuedensity[j-1];
727 density = valuedensity[j] - ((valueCT[j] - pixel)*deltaDensity/deltaCT );
733 std::printf(
"@@@ Error density = %f && Pixel = %i (0x%x) && deltaDensity/deltaCT = %f\n",density,pixel,pixel, deltaDensity/deltaCT);
736 delete [] valuedensity;
745 std::ifstream checkData(
"Data.dat");
746 char * oneLine =
new char[128];
748 if(!(checkData.is_open())) {
750 G4cout <<
"\nDicomG4 needs Data.dat :\n\tFirst line: number of image pixel for a "
751 <<
"voxel (G4Box)\n\tSecond line: number of images (CT slices) to "
752 <<
"read\n\tEach following line contains the name of a Dicom image except "
753 <<
"for the .dcm extension\n";
757 checkData >> fCompression;
758 checkData >> fNFiles;
760 checkData.getline(oneLine,100);
761 std::ifstream testExistence;
762 G4bool existAlready =
true;
763 for(
G4int rep = 0; rep < fNFiles; rep++) {
764 checkData.getline(oneLine,100);
767 G4cout << fNFiles <<
" test file " << oneName <<
G4endl;
768 testExistence.open(oneName.
data());
769 if(!(testExistence.is_open())) {
770 existAlready =
false;
771 testExistence.clear();
772 testExistence.close();
774 testExistence.clear();
775 testExistence.close();
778 ReadMaterialIndices( checkData );
783 if( existAlready ==
false ) {
785 G4cout <<
"\nAll the necessary images were not found in processed form, starting "
786 <<
"with .dcm images\n";
790 char * fCompressionc =
new char[LINEBUFFSIZE];
791 char * maxc =
new char[LINEBUFFSIZE];
793 char *
name =
new char[FILENAMESIZE];
794 char * inputFile =
new char[FILENAMESIZE];
797 lecturePref = std::fopen(
"Data.dat",
"r");
798 rflag = std::fscanf(lecturePref,
"%s",fCompressionc);
799 fCompression = atoi(fCompressionc);
800 rflag = std::fscanf(lecturePref,
"%s",maxc);
801 fNFiles = atoi(maxc);
804 for(
G4int i = 1; i <= fNFiles; i++ ) {
806 rflag = std::fscanf(lecturePref,
"%s",inputFile);
807 std::sprintf(name,
"%s.dcm",inputFile);
808 std::cout <<
"check 1: " << name << std::endl;
810 std::printf(
"### Opening %s and reading :\n",name);
811 dicom = std::fopen(name,
"rb");
824 delete [] fCompressionc;
833 template <
class Type>
834 void DicomHandler::GetValue(
char * _val, Type & _rval) {
836 #if BYTE_ORDER == BIG_ENDIAN
838 #else // BYTE_ORDER == LITTLE_ENDIAN
841 const int SIZE =
sizeof(_rval);
843 for(
int i = 0; i < SIZE/2; i++) {
845 _val[i] = _val[SIZE - 1 - i];
846 _val[SIZE - 1 - i] = ctemp;
849 _rval = *(Type *)_val;
853 G4int DicomHandler::read_defined_nested(FILE * nested,
G4int SQ_Length)
856 unsigned short item_GroupNumber;
857 unsigned short item_ElementNumber;
859 G4int items_array_length=0;
860 char *
buffer=
new char[LINEBUFFSIZE];
863 while(items_array_length < SQ_Length)
865 rflag = std::fread(buffer, 2, 1, nested);
866 GetValue(buffer, item_GroupNumber);
868 rflag = std::fread(buffer, 2, 1, nested);
869 GetValue(buffer, item_ElementNumber);
871 rflag = std::fread(buffer, 4, 1, nested);
872 GetValue(buffer, item_Length);
874 rflag = std::fread(buffer, item_Length, 1, nested);
876 items_array_length= items_array_length+8+item_Length;
881 if( SQ_Length>items_array_length )
889 void DicomHandler::read_undefined_nested(FILE * nested)
892 unsigned short item_GroupNumber;
893 unsigned short item_ElementNumber;
894 unsigned int item_Length;
895 char * buffer=
new char[LINEBUFFSIZE];
900 rflag = std::fread(buffer, 2, 1, nested);
901 GetValue(buffer, item_GroupNumber);
903 rflag = std::fread(buffer, 2, 1, nested);
904 GetValue(buffer, item_ElementNumber);
906 rflag = std::fread(buffer, 4, 1, nested);
907 GetValue(buffer, item_Length);
909 if(item_Length!=0xffffffff)
910 rflag = std::fread(buffer, item_Length, 1, nested);
912 read_undefined_item(nested);
915 }
while(item_GroupNumber!=0xFFFE || item_ElementNumber!=0xE0DD || item_Length!=0);
922 void DicomHandler::read_undefined_item(FILE * nested)
925 unsigned short item_GroupNumber;
926 unsigned short item_ElementNumber;
927 G4int item_Length;
size_t rflag = 0;
928 char *buffer=
new char[LINEBUFFSIZE];
932 rflag = std::fread(buffer, 2, 1, nested);
933 GetValue(buffer, item_GroupNumber);
935 rflag = std::fread(buffer, 2, 1, nested);
936 GetValue(buffer, item_ElementNumber);
938 rflag = std::fread(buffer, 4, 1, nested);
939 GetValue(buffer, item_Length);
943 rflag = std::fread(buffer,item_Length,1,nested);
946 while(item_GroupNumber!=0xFFFE || item_ElementNumber!=0xE00D || item_Length!=0);