Skip to content

Commit

Permalink
Respect pixel padding value during interpolation
Browse files Browse the repository at this point in the history
  • Loading branch information
alund committed Jan 31, 2019
1 parent 13a8fba commit c3f450d
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 5 deletions.
14 changes: 14 additions & 0 deletions console/nii_dicom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -779,13 +779,17 @@ struct TDICOMdata clear_dicom_data() {
d.isRawDataStorage = false;
d.isStackableSeries = false; //combine DCE series https://github.com/rordenlab/dcm2niix/issues/252
d.isXA10A = false; //https://github.com/rordenlab/dcm2niix/issues/236
d.isHasPixelPaddingValue = false;
d.isHasFloatPixelPaddingValue = false;
d.triggerDelayTime = 0.0;
d.RWVScale = 0.0;
d.RWVIntercept = 0.0;
d.isScaleOrTEVaries = false;
d.bitsAllocated = 16;//bits
d.bitsStored = 0;
d.samplesPerPixel = 1;
d.pixelPaddingValue = -1;
d.floatPixelPaddingValue = -1.0;
d.isValid = false;
d.isXRay = false;
d.isMultiEcho = false;
Expand Down Expand Up @@ -3999,6 +4003,8 @@ const uint32_t kEffectiveTE = 0x0018+ (0x9082 << 16);
#define kBitsAllocated 0x0028+(0x0100 << 16 )
#define kBitsStored 0x0028+(0x0101 << 16 )//US 'BitsStored'
#define kIsSigned 0x0028+(0x0103 << 16 ) //PixelRepresentation
#define kPixelPaddingValue 0x0028+(0x0120 << 16 ) // https://github.com/rordenlab/dcm2niix/issues/262
#define kFloatPixelPaddingValue 0x0028+(0x0122 << 16 ) // https://github.com/rordenlab/dcm2niix/issues/262
#define kIntercept 0x0028+(0x1052 << 16 )
#define kSlope 0x0028+(0x1053 << 16 )
//#define kSpectroscopyDataPointColumns 0x0028+(0x9002 << 16 ) //IS
Expand Down Expand Up @@ -5028,6 +5034,14 @@ double TE = 0.0; //most recent echo time recorded
case kIsSigned : //http://dicomiseasy.blogspot.com/2012/08/chapter-12-pixel-data.html
d.isSigned = dcmInt(lLength,&buffer[lPos],d.isLittleEndian);
break;
case kPixelPaddingValue :
d.pixelPaddingValue = (short) dcmInt(lLength,&buffer[lPos],d.isLittleEndian);
d.isHasPixelPaddingValue = true;
break;
case kFloatPixelPaddingValue :
d.floatPixelPaddingValue = dcmStrFloat(lLength, &buffer[lPos]);
d.isHasFloatPixelPaddingValue = true;
break;
case kTR :
d.TR = dcmStrFloat(lLength, &buffer[lPos]);
break;
Expand Down
5 changes: 3 additions & 2 deletions console/nii_dicom.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,15 +158,16 @@ static const uint8_t MAX_NUMBER_OF_DIMENSIONS = 8;
uint32_t coilCrc, seriesUidCrc;
int numberOfImagesInGridUIH, numberOfDiffusionDirectionGE, phaseEncodingGE, protocolBlockStartGE, protocolBlockLengthGE, modality, dwellTime, effectiveEchoSpacingGE, phaseEncodingLines, phaseEncodingSteps, echoTrainLength, echoNum, sliceOrient, manufacturer, converted2NII, acquNum, imageNum, imageStart, imageBytes, bitsStored, bitsAllocated, samplesPerPixel,locationsInAcquisition, compressionScheme;
float numberOfAverages, imagingFrequency, patientWeight, zSpacing, zThick, pixelBandwidth, SAR, phaseFieldofView, accelFactPE, flipAngle, fieldStrength, TE, TI, TR, intenScale, intenIntercept, intenScalePhilips, gantryTilt, lastScanLoc, angulation[4];
float orient[7], patientPosition[4], patientPositionLast[4], xyzMM[4], stackOffcentre[4];
float orient[7], patientPosition[4], patientPositionLast[4], xyzMM[4], stackOffcentre[4], floatPixelPaddingValue;
float rtia_timerGE, radionuclidePositronFraction, radionuclideTotalDose, radionuclideHalfLife, doseCalibrationFactor; //PET ISOTOPE MODULE ATTRIBUTES (C.8-57)
float ecat_isotope_halflife, ecat_dosage;
double acquisitionDuration, triggerDelayTime, RWVScale, RWVIntercept, dateTime, acquisitionTime, acquisitionDate, bandwidthPerPixelPhaseEncode;
char coilElements[kDICOMStr], coilName[kDICOMStr], phaseEncodingDirectionDisplayedUIH[kDICOMStr], imageBaseName[kDICOMStr], scanOptions[kDICOMStr], stationName[kDICOMStr], softwareVersions[kDICOMStr], deviceSerialNumber[kDICOMStr], institutionAddress[kDICOMStr], institutionName[kDICOMStr], referringPhysicianName[kDICOMStr], seriesInstanceUID[kDICOMStr], studyInstanceUID[kDICOMStr], bodyPartExamined[kDICOMStr], procedureStepDescription[kDICOMStr], imageType[kDICOMStr], institutionalDepartmentName[kDICOMStr], manufacturersModelName[kDICOMStr], patientID[kDICOMStr], patientOrient[kDICOMStr], patientName[kDICOMStr],seriesDescription[kDICOMStr], studyID[kDICOMStr], sequenceName[kDICOMStr], protocolName[kDICOMStr],sequenceVariant[kDICOMStr],scanningSequence[kDICOMStr], patientBirthDate[kDICOMStr], patientAge[kDICOMStr], studyDate[kDICOMStr],studyTime[kDICOMStr];
char imageComments[kDICOMStrLarge];
uint32_t dimensionIndexValues[MAX_NUMBER_OF_DIMENSIONS];
struct TCSAdata CSA;
bool isRawDataStorage, isGrayscaleSoftcopyPresentationState, isStackableSeries, isCoilVaries, isNonParallelSlices, isSegamiOasis, isXA10A, isScaleOrTEVaries, isDerived, isXRay, isMultiEcho, isValid, is3DAcq, is2DAcq, isExplicitVR, isLittleEndian, isPlanarRGB, isSigned, isHasPhase, isHasImaginary, isHasReal, isHasMagnitude,isHasMixed, isFloat, isResampled, isLocalizer;
short pixelPaddingValue;
bool isRawDataStorage, isGrayscaleSoftcopyPresentationState, isStackableSeries, isCoilVaries, isNonParallelSlices, isSegamiOasis, isXA10A, isScaleOrTEVaries, isDerived, isXRay, isMultiEcho, isValid, is3DAcq, is2DAcq, isExplicitVR, isLittleEndian, isPlanarRGB, isSigned, isHasPhase, isHasImaginary, isHasReal, isHasMagnitude,isHasMixed, isFloat, isResampled, isLocalizer, isHasPixelPaddingValue, isHasFloatPixelPaddingValue;
char phaseEncodingRC, patientSex;
};

Expand Down
24 changes: 21 additions & 3 deletions console/nii_dicom_batch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2986,8 +2986,17 @@ unsigned char * nii_saveNII3DtiltFloat32(char * niiFilename, struct nifti_1_head
rLo = (rLo * hdrIn.dim[1]) + (s * nVox2DIn); //offset to start of row below
rHi = (rHi * hdrIn.dim[1]) + (s * nVox2DIn); //offset to start of row above
int rOut = (r * hdrIn.dim[1]) + (s * nVox2D); //offset to output row
for (int c = 0; c < hdrIn.dim[1]; c++) { //for each row
imOut32[rOut+c] = round( ( ((float)imIn32[rLo+c])*fracLo) + ((float)imIn32[rHi+c])*fracHi);
for (int c = 0; c < hdrIn.dim[1]; c++) { //for each column
float valLo = (float) imIn32[rLo+c];
float valHi = (float) imIn32[rHi+c];
if (d.isHasFloatPixelPaddingValue && (valLo == d.floatPixelPaddingValue || valHi == d.floatPixelPaddingValue)) {
// https://github.com/rordenlab/dcm2niix/issues/262 - Use nearest neighbor interpolation
// when at least one of the values is padding.
imOut32[rOut+c] = fracHi >= 0.5 ? valHi : valLo;
}
else {
imOut32[rOut+c] = round(valLo*fracLo + valHi*fracHi);
}
} //for c (each column)
} //rI (input row) in range
} //for r (each row)
Expand Down Expand Up @@ -3075,7 +3084,16 @@ unsigned char * nii_saveNII3Dtilt(char * niiFilename, struct nifti_1_header * hd
rHi = (rHi * hdrIn.dim[1]) + (s * nVox2DIn); //offset to start of row above
int rOut = (r * hdrIn.dim[1]) + (s * nVox2D); //offset to output row
for (int c = 0; c < hdrIn.dim[1]; c++) { //for each row
imOut16[rOut+c] = round( ( ((float)imIn16[rLo+c])*fracLo) + ((float)imIn16[rHi+c])*fracHi);
int valLo = imIn16[rLo+c];
int valHi = imIn16[rHi+c];
if (d.isHasPixelPaddingValue && (valLo == d.pixelPaddingValue || valHi == d.pixelPaddingValue)) {
// https://github.com/rordenlab/dcm2niix/issues/262 - Use nearest neighbor interpolation
// when at least one of the values is padding.
imOut16[rOut+c] = fracHi >= 0.5 ? valHi : valLo;
}
else {
imOut16[rOut+c] = round((((float) valLo)*fracLo) + ((float) valHi)*fracHi);
}
} //for c (each column)
} //rI (input row) in range
} //for r (each row)
Expand Down

0 comments on commit c3f450d

Please sign in to comment.