in src/engine/loaders/LoaderDicom.js [1261:1893]
readFromBuffer(indexFile, fileName, ratioLoaded, arrBuf, callbackProgress, callbackComplete) {
if (typeof indexFile !== 'number') {
console.log('LoaderDicom.readFromBuffer: bad indexFile argument');
}
if (typeof fileName !== 'string') {
console.log('LoaderDicom.readFromBuffer: bad fileName argument');
}
if (typeof arrBuf !== 'object') {
console.log('LoaderDicom.readFromBuffer: bad arrBuf argument');
}
// const bufBytes = new Uint8Array(arrBuf);
// const isUint8Arr = bufBytes instanceof Uint8Array;
// if (!isUint8Arr) {
// console.log('LoaderDicom. readFromBuffer. Error read buffer');
// return false;
// }
// console.log(`LoaderDicom. readFromBuffer. file = ${fileName}, ratio = ${ratioLoaded}`);
// add info
const dicomInfo = this.m_dicomInfo;
const sliceInfo = new DicomSliceInfo();
const strSlice = 'Slice ' + indexFile.toString();
sliceInfo.m_sliceName = strSlice;
sliceInfo.m_fileName = fileName;
sliceInfo.m_tags = [];
dicomInfo.m_sliceInfo.push(sliceInfo);
const dataView = new DataView(arrBuf);
if (dataView === null) {
console.log('No memory');
return LoadResult.ERROR_NO_MEMORY;
}
const fileSize = dataView.byteLength;
// check dicom header
const SIZE_HEAD = 144;
if (fileSize < SIZE_HEAD) {
// this.m_errors[indexFile] = DICOM_ERROR_TOO_SMALL_FILE;
this.m_error = LoadResult.ERROR_TOO_SMALL_DATA_SIZE;
if (callbackComplete !== undefined) {
callbackComplete(LoadResult.ERROR_TOO_SMALL_DATA_SIZE);
}
return LoadResult.ERROR_TOO_SMALL_DATA_SIZE;
}
const OFF_MAGIC = 128;
const SIZE_DWORD = 4;
const SIZE_SHORT = 2;
for (let i = 0; i < SIZE_DWORD; i++) {
const v = dataView.getUint8(OFF_MAGIC + i);
if (v !== MAGIC_DICM[i]) {
this.m_errors[indexFile] = DICOM_ERROR_WRONG_HEADER;
console.log(`Dicom readFromBuffer. Wrong header in file: ${fileName}`);
if (callbackComplete !== undefined) {
callbackComplete(LoadResult.WRONG_HEADER_MAGIC);
}
return LoadResult.WRONG_HEADER_MAGIC;
}
}
let offset = OFF_MAGIC;
offset += SIZE_DWORD;
//
this.m_littleEndian = true;
this.m_explicit = true;
this.m_metaFound = false;
this.m_metaFinished = false;
this.m_metaFinishedOffset = -1;
this.m_needsDeflate = false;
this.m_imageNumber = -1;
this.m_xDim = -1;
this.m_yDim = -1;
this.m_bitsPerPixel = -1;
this.m_windowCenter = -1;
this.m_windowWidth = -1;
let pixelBitMask = 0;
let pixelPaddingValue = 0;
let pixelsTagReaded = false;
let pixelMinValue = -1;
let pixelMaxValue = -1;
// read tag by tag, until image tag
let tag;
for (tag = this.getNextTag(dataView, offset); tag !== null; ) {
if (tag.isPixelData()) {
pixelsTagReaded = true;
break;
}
offset = tag.m_offsetEnd;
tag = this.getNextTag(dataView, offset);
if (tag === null) {
break;
}
// add to tag info
const dicomInfo = this.m_dicomInfo;
const numlices = dicomInfo.m_sliceInfo.length;
const sliceInfo = dicomInfo.m_sliceInfo[numlices - 1];
const tagInfo = new DicomTagInfo();
tagInfo.m_tag = '(' + LoaderDicom.numberToHexString(tag.m_group) + ',' + LoaderDicom.numberToHexString(tag.m_element) + ')';
const strTagName = this.m_dictionary.getTextDesc(tag.m_group, tag.m_element);
tagInfo.m_attrName = strTagName.length > 1 ? strTagName : '';
let strVal = LoaderDicom.getAttrValueAsString(tag);
strVal = strVal !== null ? strVal : '';
tagInfo.m_attrValue = strVal;
sliceInfo.m_tags.push(tagInfo);
// console.log(`Add tag info. tag = ${tagInfo.m_tag} atNa = ${tagInfo.m_attrName} atVal = ${tagInfo.m_attrValue} `);
// get important info from tag: image number
if (tag.m_group === TAG_IMAGE_INSTANCE_NUMBER[0] && tag.m_element === TAG_IMAGE_INSTANCE_NUMBER[1]) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const strNum = LoaderDicom.getStringAt(dv, 0, dataLen);
this.m_imageNumber = parseInt(strNum, 10) - 1;
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`Str = ${strNum}, ImageNumber = ${this.m_imageNumber}`);
}
}
// get important tag: image rows
if (tag.m_group === TAG_IMAGE_ROWS[0] && tag.m_element === TAG_IMAGE_ROWS[1]) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const yDim = dataLen === SIZE_SHORT ? dv.getUint16(0, this.m_littleEndian) : dv.getUint32(0, this.m_littleEndian);
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`yDim = ${yDim}`);
}
if (this.m_yDim < 0) {
this.m_yDim = yDim;
} else if (this.m_yDim !== yDim) {
console.log('Bad image size y');
if (callbackComplete !== undefined) {
callbackComplete(LoadResult.WRONG_IMAGE_DIM_Y);
}
return LoadResult.WRONG_IMAGE_DIM_Y;
}
}
// get important tag: image cols
if (tag.m_group === TAG_IMAGE_COLS[0] && tag.m_element === TAG_IMAGE_COLS[1]) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const xDim = dataLen === SIZE_SHORT ? dv.getUint16(0, this.m_littleEndian) : dv.getUint32(0, this.m_littleEndian);
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`xDim = ${xDim}`);
}
if (this.m_xDim < 0) {
this.m_xDim = xDim;
} else if (this.m_xDim !== xDim) {
console.log('Bad image size x');
if (callbackComplete !== undefined) {
callbackComplete(LoadResult.WRONG_IMAGE_DIM_X);
}
return LoadResult.WRONG_IMAGE_DIM_X;
}
}
// get important tag: bits allocated
if (tag.m_group === TAG_BITS_ALLOCATED[0] && tag.m_element === TAG_BITS_ALLOCATED[1]) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
this.m_bitsPerPixel = dataLen === SIZE_SHORT ? dv.getUint16(0, this.m_littleEndian) : dv.getUint32(0, this.m_littleEndian);
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`bitsPerPixel = ${this.m_bitsPerPixel}`);
}
}
// window center
if (tag.m_group === TAG_WINDOW_CENTER[0] && tag.m_element === TAG_WINDOW_CENTER[1]) {
if (tag.m_value != null && tag.m_value.byteLength > 0) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const strNum = LoaderDicom.getStringAt(dv, 0, dataLen);
this.m_windowCenter = parseInt(strNum, 10);
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`Str = ${strNum}, WindowCenter = ${this.m_windowCenter}`);
}
} // if non zero data
} // window center
// window width
if (tag.m_group === TAG_WINDOW_WIDTH[0] && tag.m_element === TAG_WINDOW_WIDTH[1]) {
if (tag.m_value != null && tag.m_value.byteLength > 0) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const strNum = LoaderDicom.getStringAt(dv, 0, dataLen);
this.m_windowWidth = parseInt(strNum, 10);
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`Str = ${strNum}, WindowWidth = ${this.m_windowWidth}`);
}
} // if non zero data
} // window width
// rescale intercept
if (tag.m_group === TAG_RESCALE_INTERCEPT[0] && tag.m_element === TAG_RESCALE_INTERCEPT[1]) {
if (tag.m_value != null && tag.m_value.byteLength > 0) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const strNum = LoaderDicom.getStringAt(dv, 0, dataLen);
this.m_rescaleIntercept = parseInt(strNum, 10);
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`Str = ${strNum}, RescaleIntercept = ${this.m_rescaleIntercept}`);
}
} // if non zero data
} // rescale intercept
// rescale slope
if (tag.m_group === TAG_RESCALE_SLOPE[0] && tag.m_element === TAG_RESCALE_SLOPE[1]) {
if (tag.m_value != null && tag.m_value.byteLength > 0) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const strNum = LoaderDicom.getStringAt(dv, 0, dataLen);
this.m_rescaleSlope = parseInt(strNum, 10);
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`Str = ${strNum}, RescaleSlope = ${this.m_rescaleSlope}`);
}
} // if non zero data
} // rescale slope
// rescale type
if (tag.m_group === TAG_RESCALE_TYPE[0] && tag.m_element === TAG_RESCALE_TYPE[1]) {
if (tag.m_value != null && tag.m_value.byteLength > 0) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const strVal = LoaderDicom.getStringAt(dv, 0, dataLen);
if (strVal === 'HU') {
this.m_rescaleHounsfield = true;
}
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`Str = ${strNum}, RescaleType = ${this.m_rescaleHounsfield}`);
}
} // if non zero data
} // rescale type
// pixel representation
if (tag.m_group === TAG_PIXEL_REPRESENTATION[0] && tag.m_element === TAG_PIXEL_REPRESENTATION[1]) {
if (tag.m_value != null && tag.m_value.byteLength > 0) {
const dataLenPixRep = tag.m_value.byteLength;
const dvPixRep = new DataView(tag.m_value);
const pixRep =
dataLenPixRep === SIZE_SHORT ? dvPixRep.getUint16(0, this.m_littleEndian) : dvPixRep.getUint32(0, this.m_littleEndian);
if (pixRep === 1) {
this.m_pixelRepresentaionSigned = true;
}
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`Str = ${strNum}, Pixel representation is signed = ${this.m_pixelRepresentaionSigned}`);
}
} // if non zero data
} // rescale slope
// get series number
if (tag.m_group === TAG_SERIES_NUMBER[0] && tag.m_element === TAG_SERIES_NUMBER[1]) {
if (tag.m_value != null && tag.m_value.byteLength > 0) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const strNum = LoaderDicom.getStringAt(dv, 0, dataLen);
this.m_seriesNumber = parseInt(strNum, 10);
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`Str = ${strNum}, SeriesNumber = ${this.m_seriesNumber}`);
}
} // if non zero data
} // series number
// get important tag: series description
if (tag.m_group === TAG_SERIES_DESCRIPTION[0] && tag.m_element === TAG_SERIES_DESCRIPTION[1] && tag.m_value !== null) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
this.m_seriesDescr = LoaderDicom.getStringAt(dv, 0, dataLen);
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`Series description = ${this.m_seriesDescr}`);
}
}
// get important tag: hight bit
if (tag.m_group === TAG_IMAGE_HIGH_BIT[0] && tag.m_element === TAG_IMAGE_HIGH_BIT[1]) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const highBit = dataLen === SIZE_SHORT ? dv.getUint16(0, this.m_littleEndian) : dv.getUint32(0, this.m_littleEndian);
pixelBitMask = (1 << (highBit + 1)) - 1;
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`highBit = ${highBit}`);
}
}
// get important tag: min pixel value
if (tag.m_group === TAG_IMAGE_SMALL_PIX_VAL[0] && tag.m_element === TAG_IMAGE_SMALL_PIX_VAL[1]) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
pixelMinValue = dataLen === SIZE_SHORT ? dv.getInt16(0, this.m_littleEndian) : dv.getInt32(0, this.m_littleEndian);
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`pixelMinValue = ${pixelMinValue}`);
}
}
// get important tag: max pixel value
if (tag.m_group === TAG_IMAGE_LARGE_PIX_VAL[0] && tag.m_element === TAG_IMAGE_LARGE_PIX_VAL[1]) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
pixelMaxValue = dataLen === SIZE_SHORT ? dv.getInt16(0, this.m_littleEndian) : dv.getInt32(0, this.m_littleEndian);
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`pixelMaxValue = ${pixelMaxValue}`);
}
}
// get important tag: pixel padding value
if (tag.m_group === TAG_PIXEL_PADDING_VALUE[0] && tag.m_element === TAG_PIXEL_PADDING_VALUE[1]) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
pixelPaddingValue = dataLen === SIZE_SHORT ? dv.getUint16(0, this.m_littleEndian) : dv.getUint32(0, this.m_littleEndian);
this.m_padValue = pixelPaddingValue;
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`pixelPaddingValue = ${pixelPaddingValue}`);
}
}
// get important tag: pixel spacing in 2d (xy)
if (tag.m_group === TAG_PIXEL_SPACING[0] && tag.m_element === TAG_PIXEL_SPACING[1]) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const strPixelSpacing = LoaderDicom.getStringAt(dv, 0, dataLen);
const strArr = strPixelSpacing.split('\\');
if (strArr.length === SIZE_SHORT) {
this.m_pixelSpacing.x = parseFloat(strArr[0]);
this.m_pixelSpacing.y = parseFloat(strArr[1]);
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`TAG. pixel spacing xy = ${this.m_pixelSpacing.x} * ${this.m_pixelSpacing.y}`);
}
}
}
// get important tag: image position (x,y,z)
if (tag.m_group === TAG_IMAGE_POSITION[0] && tag.m_element === TAG_IMAGE_POSITION[1]) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const strImagePosition = LoaderDicom.getStringAt(dv, 0, dataLen);
const strArr = strImagePosition.split('\\');
const NUM_COMPONENTS_3 = 3;
if (strArr.length === NUM_COMPONENTS_3) {
// eslint-disable-next-line
const xPos = parseFloat(strArr[0]);
// eslint-disable-next-line
const yPos = parseFloat(strArr[1]);
// eslint-disable-next-line
const zPos = parseFloat(strArr[2]);
this.m_imagePosMin.x = xPos < this.m_imagePosMin.x ? xPos : this.m_imagePosMin.x;
this.m_imagePosMin.y = yPos < this.m_imagePosMin.y ? yPos : this.m_imagePosMin.y;
this.m_imagePosMin.z = zPos < this.m_imagePosMin.z ? zPos : this.m_imagePosMin.z;
this.m_imagePosMax.x = xPos > this.m_imagePosMax.x ? xPos : this.m_imagePosMax.x;
this.m_imagePosMax.y = yPos > this.m_imagePosMax.y ? yPos : this.m_imagePosMax.y;
this.m_imagePosMax.z = zPos > this.m_imagePosMax.z ? zPos : this.m_imagePosMax.z;
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`TAG. image position x,y,z = ${xPos}, ${yPos}, ${zPos}`);
}
}
}
// slice thickness
if (tag.m_group === TAG_SLICE_THICKNESS[0] && tag.m_element === TAG_SLICE_THICKNESS[1]) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const strSliceThickness = LoaderDicom.getStringAt(dv, 0, dataLen);
this.m_pixelSpacing.z = parseFloat(strSliceThickness);
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`TAG. slice thickness = ${this.m_pixelSpacing.z}`);
}
}
// get important tag: slice location (x,y,z)
if (tag.m_group === TAG_SLICE_LOCATION[0] && tag.m_element === TAG_SLICE_LOCATION[1]) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const strSliceLocation = LoaderDicom.getStringAt(dv, 0, dataLen);
const sliceLoc = parseFloat(strSliceLocation);
this.m_sliceLocation = sliceLoc;
this.m_sliceLocMin = sliceLoc < this.m_sliceLocMin ? sliceLoc : this.m_sliceLocMin;
this.m_sliceLocMax = sliceLoc > this.m_sliceLocMax ? sliceLoc : this.m_sliceLocMax;
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`TAG. Slice location = ${this.m_sliceLocation}`);
}
}
// get important tag: samples per pixel
if (tag.m_group === TAG_SAMPLES_PER_PIXEL[0] && tag.m_element === TAG_SAMPLES_PER_PIXEL[1]) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
this.m_samplesPerPixel = dataLen === SIZE_SHORT ? dv.getUint16(0, this.m_littleEndian) : dv.getUint32(0, this.m_littleEndian);
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`samplesPerPixel = ${this.m_samplesPerPixel}`);
}
}
// dicom info
if (tag.m_group === TAG_SERIES_DESCRIPTION[0] && tag.m_element === TAG_SERIES_DESCRIPTION[1] && tag.m_value !== null) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const strDescr = LoaderDicom.getStringAt(dv, 0, dataLen);
// console.log(`DicomLoader. Series descr read = ${strDescr}`);
this.m_dicomInfo.m_seriesDescr = strDescr;
}
if (tag.m_group === TAG_SERIES_TIME[0] && tag.m_element === TAG_SERIES_TIME[1] && tag.m_value !== null) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const strTimeMerged = LoaderDicom.getStringAt(dv, 0, dataLen);
// eslint-disable-next-line
const strHour = strTimeMerged.substring(0, 2);
// eslint-disable-next-line
const strMinute = strTimeMerged.substring(2, 4);
// eslint-disable-next-line
const strSec = strTimeMerged.substring(4, strTimeMerged.length);
const strTimeBuild = `${strHour}:${strMinute}:${strSec}`;
// console.log(`Series time read = ${strTimeBuild}`);
this.m_dicomInfo.m_seriesTime = strTimeBuild;
if (DEBUG_PRINT_TAGS_INFO) {
console.log(`Series time = ${this.m_dicomInfo.m_seriesTime}`);
}
}
if (tag.m_group === TAG_PATIENT_NAME[0] && tag.m_element === TAG_PATIENT_NAME[1] && tag.m_value !== null) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
this.m_dicomInfo.m_patientName = LoaderDicom.getUtf8StringAt(dv, 0, dataLen);
this.m_dicomInfo.m_patientName = this.m_dicomInfo.m_patientName.trim();
//console.log(`m_patientName = ${this.m_dicomInfo.m_patientName}`);
}
if (tag.m_group === TAG_PATIENT_ID[0] && tag.m_element === TAG_PATIENT_ID[1] && tag.m_value !== null) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
this.m_dicomInfo.m_patientId = LoaderDicom.getStringAt(dv, 0, dataLen);
// console.log(`m_patientId = ${this.m_dicomInfo.m_patientId}`);
}
if (tag.m_group === TAG_PATIENT_GENDER[0] && tag.m_element === TAG_PATIENT_GENDER[1] && tag.m_value !== null) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
this.m_dicomInfo.m_patientGender = LoaderDicom.getStringAt(dv, 0, dataLen);
// console.log(`m_patientGender = ${this.m_dicomInfo.m_patientGender}`);
}
if (tag.m_group === TAG_PATIENT_BIRTH_DATE[0] && tag.m_element === TAG_PATIENT_BIRTH_DATE[1] && tag.m_value !== null) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const strDateMerged = LoaderDicom.getStringAt(dv, 0, dataLen);
// eslint-disable-next-line
const strY = strDateMerged.substring(0, 4);
// eslint-disable-next-line
const strM = strDateMerged.substring(4, 6);
// eslint-disable-next-line
const strD = strDateMerged.substring(6);
this.m_dicomInfo.m_patientDateOfBirth = `${strD}/${strM}/${strY}`;
// console.log(`m_patientDateOfBirth = ${this.m_dicomInfo.m_patientDateOfBirth}`);
}
if (tag.m_group === TAG_STUDY_DATE[0] && tag.m_element === TAG_STUDY_DATE[1] && tag.m_value !== null) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const strDateMerged = LoaderDicom.getStringAt(dv, 0, dataLen);
// eslint-disable-next-line
const strY = strDateMerged.substring(0, 4);
// eslint-disable-next-line
const strM = strDateMerged.substring(4, 6);
// eslint-disable-next-line
const strD = strDateMerged.substring(6);
this.m_dicomInfo.m_studyDate = `${strD}/${strM}/${strY}`;
// console.log(`m_studyDate = ${this.m_dicomInfo.m_studyDate}`);
}
if (tag.m_group === TAG_STUDY_DESCR[0] && tag.m_element === TAG_STUDY_DESCR[1] && tag.m_value !== null) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
const strDescr = LoaderDicom.getStringAt(dv, 0, dataLen);
this.m_dicomInfo.m_studyDescr = strDescr;
this.m_dicomInfo.m_studyDescr = this.m_dicomInfo.m_studyDescr.trim();
// console.log(`m_studyDescr = ${this.m_dicomInfo.m_studyDescr}`);
}
if (tag.m_group === TAG_BODY_PART_EXAMINED[0] && tag.m_element === TAG_BODY_PART_EXAMINED[1] && tag.m_value !== null) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
this.m_dicomInfo.m_bodyPartExamined = LoaderDicom.getStringAt(dv, 0, dataLen);
// console.log(`m_patientName = ${this.m_dicomInfo.m_patientName}`);
}
if (tag.m_group === TAG_ACQUISION_TIME[0] && tag.m_element === TAG_ACQUISION_TIME[1] && tag.m_value !== null) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
this.m_dicomInfo.m_acquisionTime = LoaderDicom.getStringAt(dv, 0, dataLen);
// console.log(`m_acquisionTime = ${this.m_dicomInfo.m_acquisionTime}`);
}
if (tag.m_group === TAG_INSTITUTION_NAME[0] && tag.m_element === TAG_INSTITUTION_NAME[1] && tag.m_value !== null) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
this.m_dicomInfo.m_institutionName = LoaderDicom.getUtf8StringAt(dv, 0, dataLen);
this.m_dicomInfo.m_institutionName = this.m_dicomInfo.m_institutionName.trim();
// console.log(`m_institutionName = ${this.m_dicomInfo.m_institutionName}`);
}
if (tag.m_group === TAG_OPERATORS_NAME[0] && tag.m_element === TAG_OPERATORS_NAME[1] && tag.m_value !== null) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
this.m_dicomInfo.m_operatorsName = LoaderDicom.getUtf8StringAt(dv, 0, dataLen);
this.m_dicomInfo.m_operatorsName = this.m_dicomInfo.m_operatorsName.trim();
// console.log(`m_operatorsName = ${this.m_dicomInfo.m_operatorsName}`);
}
if (tag.m_group === TAG_PHYSICANS_NAME[0] && tag.m_element === TAG_PHYSICANS_NAME[1] && tag.m_value !== null) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
this.m_dicomInfo.m_physicansName = LoaderDicom.getUtf8StringAt(dv, 0, dataLen);
this.m_dicomInfo.m_physicansName = this.m_dicomInfo.m_physicansName.trim();
// console.log(`m_physicansName = ${this.m_dicomInfo.m_physicansName}`);
}
if (tag.m_group === TAG_MANUFACTURER_NAME[0] && tag.m_element === TAG_MANUFACTURER_NAME[1] && tag.m_value !== null) {
const dataLen = tag.m_value.byteLength;
const dv = new DataView(tag.m_value);
this.m_dicomInfo.m_manufacturerName = LoaderDicom.getStringAt(dv, 0, dataLen);
this.m_dicomInfo.m_manufacturerName = this.m_dicomInfo.m_manufacturerName.trim();
// console.log(`m_manufacturerName = ${this.m_dicomInfo.m_manufacturerName}`);
}
} // for all tags readed
if (!pixelsTagReaded) {
if (callbackComplete !== undefined) {
callbackComplete(LoadResult.ERROR_PIXELS_TAG_NOT_FOUND);
}
return LoadResult.ERROR_PIXELS_TAG_NOT_FOUND;
}
// check transform syntax
if (this.m_transformSyntax.length > 1) {
// const decoder = new jpeg.lossless.Decoder();
// const outBuffer = decoder.decompress(tag.m_value);
if (callbackComplete !== undefined) {
callbackComplete(LoadResult.ERROR_COMPRESSED_IMAGE_NOT_SUPPORTED);
}
return LoadResult.ERROR_COMPRESSED_IMAGE_NOT_SUPPORTED;
}
// check correct data from tags
const BITS_IN_BYTE = 8;
const imageSizeBytes = Math.floor(this.m_xDim * this.m_yDim * (this.m_bitsPerPixel / BITS_IN_BYTE) * this.m_samplesPerPixel);
if (imageSizeBytes !== tag.m_value.byteLength || pixelBitMask === 0) {
console.log(`Wrong image pixels size. Readed ${tag.m_value.byteLength}, but expected ${imageSizeBytes}`);
if (callbackComplete !== undefined) {
callbackComplete(LoadResult.ERROR_COMPRESSED_IMAGE_NOT_SUPPORTED);
}
return LoadResult.WRONG_HEADER_DATA_SIZE;
}
const numPixels = this.m_xDim * this.m_yDim;
// const volSlice = this.m_slicesVolume.getNewSlice();
const volSlice = new DicomSlice();
if (volSlice === null) {
console.log('No memory');
return LoadResult.ERROR_NO_MEMORY;
}
if (this.m_pixelRepresentaionSigned) {
volSlice.m_image = new Int16Array(numPixels);
} else {
volSlice.m_image = new Uint16Array(numPixels);
}
if (volSlice.m_image === null) {
console.log('No memory');
return LoadResult.ERROR_NO_MEMORY;
}
volSlice.m_sliceNumber = this.m_imageNumber;
volSlice.m_sliceLocation = this.m_sliceLocation;
volSlice.m_patientName = this.m_dicomInfo.m_patientName;
volSlice.m_studyDescr = this.m_dicomInfo.m_studyDescr;
volSlice.m_studyDate = this.m_dicomInfo.m_studyDate;
volSlice.m_seriesTime = this.m_dicomInfo.m_seriesTime;
volSlice.m_seriesDescr = this.m_dicomInfo.m_seriesDescr;
volSlice.m_bodyPartExamined = this.m_dicomInfo.m_bodyPartExamined;
volSlice.m_institutionName = this.m_dicomInfo.m_institutionName;
volSlice.m_operatorsName = this.m_dicomInfo.m_operatorsName;
volSlice.m_physicansName = this.m_dicomInfo.m_physicansName;
volSlice.buildHash();
volSlice.m_xDim = this.m_xDim;
volSlice.m_yDim = this.m_yDim;
// console.log(`patName = ${volSlice.m_patientName}`);
// console.log(`studyDescr = ${volSlice.m_studyDescr}`);
// console.log(`studyDate = ${volSlice.m_studyDate}`);
// console.log(`seriesTime = ${volSlice.m_seriesTime}`);
// console.log(`seriesDescr = ${volSlice.m_seriesDescr}`);
// console.log(`bodyPartExamined = ${volSlice.m_bodyPartExamined}`);
// Fill slice image
// const imageDst = this.m_slices[this.m_imageNumber];
const imageDst = volSlice.m_image;
const imageSrc = new DataView(tag.m_value);
if (imageSrc === null) {
console.log('No memory');
return LoadResult.ERROR_NO_MEMORY;
}
const BITS_8 = 8;
const BITS_16 = 16;
const NUM_1 = 1;
const NUM_3 = 3;
let i;
if (this.m_bitsPerPixel === BITS_8) {
if (this.m_samplesPerPixel === NUM_1) {
for (i = 0; i < numPixels; i++) {
const val = imageSrc.getUint8(i);
imageDst[i] = val;
}
// if 1 sample per pixel
} else if (this.m_samplesPerPixel === NUM_3) {
// if 3 samples per pixel
let j = 0;
for (i = 0; i < numPixels; i++, j += 3) {
const b0 = imageSrc.getUint8(j + 0);
const b1 = imageSrc.getUint8(j + 1);
const b2 = imageSrc.getUint8(j + 2);
// assert(b0 < 256);
// assert(b1 < 256);
// assert(b2 < 256);
imageDst[i] = Math.floor((b0 + b1 + b2) / 3);
}
}
} else if (this.m_bitsPerPixel === BITS_16) {
let i2 = 0;
for (i = 0; i < numPixels; i++) {
let val = imageSrc.getUint16(i2, this.m_littleEndian);
i2 += SIZE_SHORT;
imageDst[i] = val;
} // end for i pixels
} else {
// if 16 bpp
console.log('TODO: need to implement reading non-8 and non-16 bit dicom images');
}
this.m_error = DICOM_ERROR_OK;
// add volume slice to slices volume (and manage series)
this.m_slicesVolume.addSlice(volSlice);
// console.log(`Dicom read OK. Volume pixels = ${this.m_xDim} * ${this.m_yDim} * ${this.m_zDim}`);
if (callbackComplete !== undefined) {
callbackComplete(LoadResult.SUCCESS);
}
return LoadResult.SUCCESS;
} // end readFromBuffer