ami-cjs.js
Version:
<p align="center"> <img src="https://cloud.githubusercontent.com/assets/214063/23213764/78ade038-f90c-11e6-8208-4fcade5f3832.png" width="60%"> </p>
967 lines (813 loc) • 36.1 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _parsers = require('./parsers.volume');
var _parsers2 = _interopRequireDefault(_parsers);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // ftp://medical.nema.org/MEDICAL/Dicom/2014c/output/chtml/part05/sect_6.2.html/
// Slicer way to handle images
// should follow it...
// 897 if ( (this->IndexSeriesInstanceUIDs[k] != idxSeriesInstanceUID && this->IndexSeriesInstanceUIDs[k] >= 0 && idxSeriesInstanceUID >= 0) ||
// 898 (this->IndexContentTime[k] != idxContentTime && this->IndexContentTime[k] >= 0 && idxContentTime >= 0) ||
// 899 (this->IndexTriggerTime[k] != idxTriggerTime && this->IndexTriggerTime[k] >= 0 && idxTriggerTime >= 0) ||
// 900 (this->IndexEchoNumbers[k] != idxEchoNumbers && this->IndexEchoNumbers[k] >= 0 && idxEchoNumbers >= 0) ||
// 901 (this->IndexDiffusionGradientOrientation[k] != idxDiffusionGradientOrientation && this->IndexDiffusionGradientOrientation[k] >= 0 && idxDiffusionGradientOrientation >= 0) ||
// 902 (this->IndexSliceLocation[k] != idxSliceLocation && this->IndexSliceLocation[k] >= 0 && idxSliceLocation >= 0) ||
// 903 (this->IndexImageOrientationPatient[k] != idxImageOrientationPatient && this->IndexImageOrientationPatient[k] >= 0 && idxImageOrientationPatient >= 0) )
// 904 {
// 905 continue;
// 906 }
/** * Imports ***/
var DicomParser = require('dicom-parser');
var Jpeg = require('jpeg-lossless-decoder-js');
var JpegBaseline = require('../../external/scripts/jpeg');
var Jpx = require('../../external/scripts/jpx');
/**
* Dicom parser is a combination of utilities to get a VJS image from dicom files.
*scripts
* Relies on dcmjs, jquery, HTML5 fetch API, HTML5 promise API.
*
* @module parsers/dicom
*
* @param arrayBuffer {arraybuffer} - List of files to be parsed. It is urls from which
* VJS.parsers.dicom can pull the data from.
*/
var ParsersDicom = function (_ParsersVolume) {
_inherits(ParsersDicom, _ParsersVolume);
function ParsersDicom(data, id) {
_classCallCheck(this, ParsersDicom);
var _this = _possibleConstructorReturn(this, (ParsersDicom.__proto__ || Object.getPrototypeOf(ParsersDicom)).call(this));
_this._id = id;
_this._arrayBuffer = data.buffer;
var byteArray = new Uint8Array(_this._arrayBuffer);
// catch error
// throw error if any!
_this._dataSet = null;
try {
_this._dataSet = DicomParser.parseDicom(byteArray);
} catch (e) {
window.console.log(e);
throw 'parsers.dicom could not parse the file';
}
return _this;
}
// image/frame specific
_createClass(ParsersDicom, [{
key: 'seriesInstanceUID',
value: function seriesInstanceUID() {
return this._dataSet.string('x0020000e');
}
}, {
key: 'studyInstanceUID',
value: function studyInstanceUID() {
return this._dataSet.string('x0020000d');
}
}, {
key: 'modality',
value: function modality() {
return this._dataSet.string('x00080060');
}
}, {
key: 'segmentationType',
value: function segmentationType() {
return this._dataSet.string('x00620001');
}
}, {
key: 'segmentationSegments',
value: function segmentationSegments() {
var segmentationSegments = [];
var segmentSequence = this._dataSet.elements.x00620002;
if (!segmentSequence) {
return segmentationSegments;
}
for (var i = 0; i < segmentSequence.items.length; i++) {
var recommendedDisplayCIELab = this._recommendedDisplayCIELab(segmentSequence.items[i]);
var segmentationCode = this._segmentationCode(segmentSequence.items[i]);
var segmentNumber = segmentSequence.items[i].dataSet.uint16('x00620004');
var segmentLabel = segmentSequence.items[i].dataSet.string('x00620005');
var segmentAlgorithmType = segmentSequence.items[i].dataSet.string('x00620008');
segmentationSegments.push({
recommendedDisplayCIELab: recommendedDisplayCIELab,
segmentationCodeDesignator: segmentationCode['segmentationCodeDesignator'],
segmentationCodeValue: segmentationCode['segmentationCodeValue'],
segmentationCodeMeaning: segmentationCode['segmentationCodeMeaning'],
segmentNumber: segmentNumber,
segmentLabel: segmentLabel,
segmentAlgorithmType: segmentAlgorithmType
});
}
return segmentationSegments;
}
}, {
key: '_segmentationCode',
value: function _segmentationCode(segment) {
var segmentationCodeDesignator = 'unknown';
var segmentationCodeValue = 'unknown';
var segmentationCodeMeaning = 'unknown';
var element = segment.dataSet.elements.x00082218;
if (element && element.items && element.items.length > 0) {
segmentationCodeDesignator = element.items[0].dataSet.string('x00080102');
segmentationCodeValue = element.items[0].dataSet.string('x00080100');
segmentationCodeMeaning = element.items[0].dataSet.string('x00080104');
}
return {
segmentationCodeDesignator: segmentationCodeDesignator,
segmentationCodeValue: segmentationCodeValue,
segmentationCodeMeaning: segmentationCodeMeaning
};
}
}, {
key: '_recommendedDisplayCIELab',
value: function _recommendedDisplayCIELab(segment) {
if (!segment.dataSet.elements.x0062000d) {
return null;
}
var offset = segment.dataSet.elements.x0062000d.dataOffset;
var length = segment.dataSet.elements.x0062000d.length;
var byteArray = segment.dataSet.byteArray.slice(offset, offset + length);
// https://www.dabsoft.ch/dicom/3/C.10.7.1.1/
var CIELabScaled = new Uint16Array(length / 2);
for (var i = 0; i < length / 2; i++) {
CIELabScaled[i] = (byteArray[2 * i + 1] << 8) + byteArray[2 * i];
}
var CIELabNormalized = [CIELabScaled[0] / 65535 * 100, CIELabScaled[1] / 65535 * 255 - 128, CIELabScaled[2] / 65535 * 255 - 128];
return CIELabNormalized;
}
}, {
key: 'sopInstanceUID',
value: function sopInstanceUID() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
// 2005140f only works for siemens
// which is the real one?
var sopInstanceUID = this._findStringEverywhere('x2005140f', 'x00080018', frameIndex);
return sopInstanceUID;
}
}, {
key: 'transferSyntaxUID',
value: function transferSyntaxUID() {
return this._dataSet.string('x00020010');
}
}, {
key: 'photometricInterpretation',
value: function photometricInterpretation() {
return this._dataSet.string('x00280004');
}
}, {
key: 'planarConfiguration',
value: function planarConfiguration() {
var planarConfiguration = this._dataSet.uint16('x00280006');
if (typeof planarConfiguration === 'undefined') {
planarConfiguration = null;
}
return planarConfiguration;
}
}, {
key: 'samplesPerPixel',
value: function samplesPerPixel() {
return this._dataSet.uint16('x00280002');
}
}, {
key: 'numberOfFrames',
value: function numberOfFrames() {
var numberOfFrames = this._dataSet.intString('x00280008');
// need something smarter!
if (typeof numberOfFrames === 'undefined') {
numberOfFrames = null;
}
return numberOfFrames;
}
}, {
key: 'numberOfChannels',
value: function numberOfChannels() {
var numberOfChannels = 1;
var photometricInterpretation = this.photometricInterpretation();
if (!(photometricInterpretation !== 'RGB' && photometricInterpretation !== 'PALETTE COLOR' && photometricInterpretation !== 'YBR_FULL' && photometricInterpretation !== 'YBR_FULL_422' && photometricInterpretation !== 'YBR_PARTIAL_422' && photometricInterpretation !== 'YBR_PARTIAL_420' && photometricInterpretation !== 'YBR_RCT')) {
numberOfChannels = 3;
}
// make sure we return a number! (not a string!)
return numberOfChannels;
}
}, {
key: 'invert',
value: function invert() {
var photometricInterpretation = this.photometricInterpretation();
return photometricInterpretation === 'MONOCHROME1' ? true : false;
}
}, {
key: 'imageOrientation',
value: function imageOrientation() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
// expect frame index to start at 0!
var imageOrientation = this._findStringEverywhere('x00209116', 'x00200037', frameIndex);
// format image orientation ('1\0\0\0\1\0') to array containing 6 numbers
if (imageOrientation) {
// make sure we return a number! (not a string!)
// might not need to split (floatString + index)
imageOrientation = imageOrientation.split('\\').map(Number);
}
return imageOrientation;
}
}, {
key: 'referencedSegmentNumber',
value: function referencedSegmentNumber() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var referencedSegmentNumber = -1;
var referencedSegmentNumberElement = this._findInGroupSequence('x52009230', 'x0062000a', frameIndex);
if (referencedSegmentNumberElement !== null) {
referencedSegmentNumber = referencedSegmentNumberElement.uint16('x0062000b');
}
return referencedSegmentNumber;
}
}, {
key: 'pixelAspectRatio',
value: function pixelAspectRatio() {
var pixelAspectRatio = [this._dataSet.intString('x00280034', 0), this._dataSet.intString('x00280034', 1)];
// need something smarter!
if (typeof pixelAspectRatio[0] === 'undefined') {
pixelAspectRatio = null;
}
// make sure we return a number! (not a string!)
return pixelAspectRatio;
}
}, {
key: 'imagePosition',
value: function imagePosition() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var imagePosition = this._findStringEverywhere('x00209113', 'x00200032', frameIndex);
// format image orientation ('1\0\0\0\1\0') to array containing 6 numbers
if (imagePosition) {
// make sure we return a number! (not a string!)
imagePosition = imagePosition.split('\\').map(Number);
}
return imagePosition;
}
}, {
key: 'instanceNumber',
value: function instanceNumber() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var instanceNumber = null;
// first look for frame!
// per frame functionnal group sequence
var perFrameFunctionnalGroupSequence = this._dataSet.elements.x52009230;
if (typeof perFrameFunctionnalGroupSequence !== 'undefined') {
if (perFrameFunctionnalGroupSequence.items[frameIndex].dataSet.elements.x2005140f) {
var planeOrientationSequence = perFrameFunctionnalGroupSequence.items[frameIndex].dataSet.elements.x2005140f.items[0].dataSet;
instanceNumber = planeOrientationSequence.intString('x00200013');
} else {
instanceNumber = this._dataSet.intString('x00200013');
if (typeof instanceNumber === 'undefined') {
instanceNumber = null;
}
}
} else {
// should we default to undefined??
// default orientation
instanceNumber = this._dataSet.intString('x00200013');
if (typeof instanceNumber === 'undefined') {
instanceNumber = null;
}
}
return instanceNumber;
}
}, {
key: 'pixelSpacing',
value: function pixelSpacing() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
// expect frame index to start at 0!
var pixelSpacing = this._findStringEverywhere('x00289110', 'x00280030', frameIndex);
// format image orientation ('1\0\0\0\1\0') to array containing 6 numbers
// should we default to undefined??
if (pixelSpacing) {
// make sure we return array of numbers! (not strings!)
pixelSpacing = pixelSpacing.split('\\').map(Number);
}
return pixelSpacing;
}
}, {
key: 'rows',
value: function rows() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var rows = this._dataSet.uint16('x00280010');
if (typeof rows === 'undefined') {
rows = null;
// print warning at least...
}
return rows;
}
}, {
key: 'columns',
value: function columns() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var columns = this._dataSet.uint16('x00280011');
if (typeof columns === 'undefined') {
columns = null;
// print warning at least...
}
return columns;
}
}, {
key: 'pixelType',
value: function pixelType() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
// 0 integer, 1 float
// dicom only support integers
return 0;
}
}, {
key: 'pixelRepresentation',
value: function pixelRepresentation() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var pixelRepresentation = this._dataSet.uint16('x00280103');
return pixelRepresentation;
}
}, {
key: 'bitsAllocated',
value: function bitsAllocated() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
// expect frame index to start at 0!
var bitsAllocated = this._dataSet.uint16('x00280100');
return bitsAllocated;
}
}, {
key: 'highBit',
value: function highBit() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
// expect frame index to start at 0!
var highBit = this._dataSet.uint16('x00280102');
return highBit;
}
}, {
key: 'rescaleIntercept',
value: function rescaleIntercept() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
return this._findFloatStringInFrameGroupSequence('x00289145', 'x00281052', frameIndex);
}
}, {
key: 'rescaleSlope',
value: function rescaleSlope() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
return this._findFloatStringInFrameGroupSequence('x00289145', 'x00281053', frameIndex);
}
}, {
key: 'windowCenter',
value: function windowCenter() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
return this._findFloatStringInFrameGroupSequence('x00289132', 'x00281050', frameIndex);
}
}, {
key: 'windowWidth',
value: function windowWidth() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
return this._findFloatStringInFrameGroupSequence('x00289132', 'x00281051', frameIndex);
}
}, {
key: 'sliceThickness',
value: function sliceThickness() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
return this._findFloatStringInFrameGroupSequence('x00289110', 'x00180050', frameIndex);
}
}, {
key: 'spacingBetweenSlices',
value: function spacingBetweenSlices() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var spacing = this._dataSet.intString('x00180088');
if (typeof spacing === 'undefined') {
spacing = null;
}
return spacing;
}
}, {
key: 'dimensionIndexValues',
value: function dimensionIndexValues() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var dimensionIndexValues = null;
// try to get it from enhanced MR images
// per-frame functionnal group sequence
var perFrameFunctionnalGroupSequence = this._dataSet.elements.x52009230;
if (typeof perFrameFunctionnalGroupSequence !== 'undefined') {
var frameContentSequence = perFrameFunctionnalGroupSequence.items[frameIndex].dataSet.elements.x00209111;
if (frameContentSequence !== undefined && frameContentSequence !== null) {
frameContentSequence = frameContentSequence.items[0].dataSet;
var dimensionIndexValuesElt = frameContentSequence.elements.x00209157;
if (dimensionIndexValuesElt !== undefined && dimensionIndexValuesElt !== null) {
// /4 because UL
var nbValues = dimensionIndexValuesElt.length / 4;
dimensionIndexValues = [];
for (var i = 0; i < nbValues; i++) {
dimensionIndexValues.push(frameContentSequence.uint32('x00209157', i));
}
}
}
}
return dimensionIndexValues;
}
}, {
key: 'inStackPositionNumber',
value: function inStackPositionNumber() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var inStackPositionNumber = null;
// try to get it from enhanced MR images
// per-frame functionnal group sequence
var perFrameFunctionnalGroupSequence = this._dataSet.elements.x52009230;
if (typeof perFrameFunctionnalGroupSequence !== 'undefined') {
// NOT A PHILIPS TRICK!
var philipsPrivateSequence = perFrameFunctionnalGroupSequence.items[frameIndex].dataSet.elements.x00209111.items[0].dataSet;
inStackPositionNumber = philipsPrivateSequence.uint32('x00209057');
} else {
inStackPositionNumber = null;
}
console.log('instack position ' + inStackPositionNumber);
return inStackPositionNumber;
}
}, {
key: 'stackID',
value: function stackID() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var stackID = null;
// try to get it from enhanced MR images
// per-frame functionnal group sequence
var perFrameFunctionnalGroupSequence = this._dataSet.elements.x52009230;
if (typeof perFrameFunctionnalGroupSequence !== 'undefined') {
// NOT A PHILIPS TRICK!
var philipsPrivateSequence = perFrameFunctionnalGroupSequence.items[frameIndex].dataSet.elements.x00209111.items[0].dataSet;
stackID = philipsPrivateSequence.intString('x00209056');
} else {
stackID = null;
}
return stackID;
}
}, {
key: 'extractPixelData',
value: function extractPixelData() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
// decompress
var decompressedData = this._decodePixelData(frameIndex);
var numberOfChannels = this.numberOfChannels();
if (numberOfChannels > 1) {
return this._convertColorSpace(decompressedData);
} else {
return decompressedData;
}
}
}, {
key: 'minMaxPixelData',
value: function minMaxPixelData() {
var pixelData = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var minMax = [65535, -32768];
var numPixels = pixelData.length;
for (var index = 0; index < numPixels; index++) {
var spv = pixelData[index];
minMax[0] = Math.min(minMax[0], spv);
minMax[1] = Math.max(minMax[1], spv);
}
return minMax;
}
//
// private methods
//
}, {
key: '_findInGroupSequence',
value: function _findInGroupSequence(sequence, subsequence, index) {
var functionalGroupSequence = this._dataSet.elements[sequence];
if (typeof functionalGroupSequence !== 'undefined') {
var inSequence = functionalGroupSequence.items[index].dataSet.elements[subsequence];
if (typeof inSequence !== 'undefined') {
return inSequence.items[0].dataSet;
}
}
return null;
}
}, {
key: '_findStringInGroupSequence',
value: function _findStringInGroupSequence(sequence, subsequence, tag, index) {
// index = 0 if shared!!!
var dataSet = this._findInGroupSequence(sequence, subsequence, index);
if (dataSet !== null) {
return dataSet.string(tag);
}
return null;
}
}, {
key: '_findStringInFrameGroupSequence',
value: function _findStringInFrameGroupSequence(subsequence, tag, index) {
return this._findStringInGroupSequence('x52009229', subsequence, tag, 0) || this._findStringInGroupSequence('x52009230', subsequence, tag, index);
}
}, {
key: '_findStringEverywhere',
value: function _findStringEverywhere(subsequence, tag, index) {
var targetString = this._findStringInFrameGroupSequence(subsequence, tag, index);
if (targetString === null) {
targetString = this._dataSet.string(tag);
}
if (typeof targetString === 'undefined') {
targetString = null;
}
return targetString;
}
}, {
key: '_findFloatStringInGroupSequence',
value: function _findFloatStringInGroupSequence(sequence, subsequence, tag, index) {
var dataInGroupSequence = this._dataSet.floatString(tag);
// try to get it from enhanced MR images
// per-frame functionnal group
if (typeof dataInGroupSequence === 'undefined') {
dataInGroupSequence = this._findInGroupSequence(sequence, subsequence, index);
if (dataInGroupSequence !== null) {
return dataInGroupSequence.floatString(tag);
} else {
return null;
}
}
return dataInGroupSequence;
}
}, {
key: '_findFloatStringInFrameGroupSequence',
value: function _findFloatStringInFrameGroupSequence(subsequence, tag, index) {
return this._findFloatStringInGroupSequence('x52009229', subsequence, tag, 0) || this._findFloatStringInGroupSequence('x52009230', subsequence, tag, index);
}
}, {
key: '_decodePixelData',
value: function _decodePixelData() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
// if compressed..?
var transferSyntaxUID = this.transferSyntaxUID();
// find compression scheme
if (transferSyntaxUID === '1.2.840.10008.1.2.4.90' || // JPEG 2000 Lossless
transferSyntaxUID === '1.2.840.10008.1.2.4.91') {
// JPEG 2000 Lossy
// JPEG 2000
return this._decodeJ2K(frameIndex);
} else if (transferSyntaxUID === '1.2.840.10008.1.2.4.57' || // JPEG Lossless, Nonhierarchical (Processes 14)
transferSyntaxUID === '1.2.840.10008.1.2.4.70') {
// JPEG Lossless, Nonhierarchical (Processes 14 [Selection 1])
// JPEG LOSSLESS
return this._decodeJPEGLossless(frameIndex);
} else if (transferSyntaxUID === '1.2.840.10008.1.2.4.50' || // JPEG Baseline lossy process 1 (8 bit)
transferSyntaxUID === '1.2.840.10008.1.2.4.51') {
// JPEG Baseline lossy process 2 & 4 (12 bit)
// JPEG Baseline
return this._decodeJPEGBaseline(frameIndex);
} else if (transferSyntaxUID === '1.2.840.10008.1.2' || // Implicit VR Little Endian
transferSyntaxUID === '1.2.840.10008.1.2.1') {
// Explicit VR Little Endian
// get data
return this._decodeUncompressed(frameIndex);
} else if (transferSyntaxUID === '1.2.840.10008.1.2.2') {
// Explicit VR Big Endian
// get data
var frame = this._decodeUncompressed(frameIndex);
// and sawp it!
return this._swapFrame(frame);
} else {
throw 'no decoder for transfer syntax ' + transferSyntaxUID;
}
}
}, {
key: '_decodeJ2K',
value: function _decodeJ2K() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var encodedPixelData = DicomParser.readEncapsulatedPixelData(this._dataSet, this._dataSet.elements.x7fe00010, frameIndex);
// let pixelDataElement = this._dataSet.elements.x7fe00010;
// let pixelData = new Uint8Array(this._dataSet.byteArray.buffer, pixelDataElement.dataOffset, pixelDataElement.length);
var jpxImage = new Jpx();
// https://github.com/OHIF/image-JPEG2000/issues/6
// It currently returns either Int16 or Uint16 based on whether the codestream is signed or not.
jpxImage.parse(encodedPixelData);
// let j2kWidth = jpxImage.width;
// let j2kHeight = jpxImage.height;
var componentsCount = jpxImage.componentsCount;
if (componentsCount !== 1) {
throw 'JPEG2000 decoder returned a componentCount of ${componentsCount}, when 1 is expected';
}
var tileCount = jpxImage.tiles.length;
if (tileCount !== 1) {
throw 'JPEG2000 decoder returned a tileCount of ${tileCount}, when 1 is expected';
}
var tileComponents = jpxImage.tiles[0];
var pixelData = tileComponents.items;
// window.console.log(j2kWidth, j2kHeight);
return pixelData;
}
// from cornerstone
}, {
key: '_decodeJPEGLossless',
value: function _decodeJPEGLossless() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var encodedPixelData = DicomParser.readEncapsulatedPixelData(this._dataSet, this._dataSet.elements.x7fe00010, frameIndex);
var pixelRepresentation = this.pixelRepresentation(frameIndex);
var bitsAllocated = this.bitsAllocated(frameIndex);
var byteOutput = bitsAllocated <= 8 ? 1 : 2;
var decoder = new Jpeg.lossless.Decoder();
var decompressedData = decoder.decode(encodedPixelData.buffer, encodedPixelData.byteOffset, encodedPixelData.length, byteOutput);
if (pixelRepresentation === 0) {
if (byteOutput === 2) {
return new Uint16Array(decompressedData.buffer);
} else {
// untested!
return new Uint8Array(decompressedData.buffer);
}
} else {
return new Int16Array(decompressedData.buffer);
}
}
}, {
key: '_decodeJPEGBaseline',
value: function _decodeJPEGBaseline() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var encodedPixelData = DicomParser.readEncapsulatedPixelData(this._dataSet, this._dataSet.elements.x7fe00010, frameIndex);
var rows = this.rows(frameIndex);
var columns = this.columns(frameIndex);
var bitsAllocated = this.bitsAllocated(frameIndex);
var jpegBaseline = new JpegBaseline();
jpegBaseline.parse(encodedPixelData);
if (bitsAllocated === 8) {
return jpegBaseline.getData(columns, rows);
} else if (bitsAllocated === 16) {
return jpegBaseline.getData16(columns, rows);
}
}
}, {
key: '_decodeUncompressed',
value: function _decodeUncompressed() {
var frameIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var pixelRepresentation = this.pixelRepresentation(frameIndex);
var bitsAllocated = this.bitsAllocated(frameIndex);
var pixelDataElement = this._dataSet.elements.x7fe00010;
var pixelDataOffset = pixelDataElement.dataOffset;
var numberOfChannels = this.numberOfChannels();
var numPixels = this.rows(frameIndex) * this.columns(frameIndex) * numberOfChannels;
var frameOffset = 0;
var buffer = this._dataSet.byteArray.buffer;
if (pixelRepresentation === 0 && bitsAllocated === 8) {
// unsigned 8 bit
frameOffset = pixelDataOffset + frameIndex * numPixels;
return new Uint8Array(buffer, frameOffset, numPixels);
} else if (pixelRepresentation === 0 && bitsAllocated === 16) {
// unsigned 16 bit
frameOffset = pixelDataOffset + frameIndex * numPixels * 2;
return new Uint16Array(buffer, frameOffset, numPixels);
} else if (pixelRepresentation === 1 && bitsAllocated === 16) {
// signed 16 bit
frameOffset = pixelDataOffset + frameIndex * numPixels * 2;
return new Int16Array(buffer, frameOffset, numPixels);
} else if (pixelRepresentation === 0 && bitsAllocated === 32) {
// unsigned 32 bit
frameOffset = pixelDataOffset + frameIndex * numPixels * 4;
return new Uint32Array(buffer, frameOffset, numPixels);
} else if (pixelRepresentation === 0 && bitsAllocated === 1) {
var newBuffer = new ArrayBuffer(numPixels);
var newArray = new Uint8Array(newBuffer);
frameOffset = pixelDataOffset + frameIndex * numPixels;
var index = 0;
var bitStart = frameIndex * numPixels;
var bitEnd = frameIndex * numPixels + numPixels;
var byteStart = Math.floor(bitStart / 8);
var bitStartOffset = bitStart - byteStart * 8;
var byteEnd = Math.ceil(bitEnd / 8);
var targetBuffer = new Uint8Array(buffer, pixelDataOffset);
for (var i = byteStart; i <= byteEnd; i++) {
while (bitStartOffset < 8) {
switch (bitStartOffset) {
case 0:
newArray[index] = targetBuffer[i] & 0x0001;
break;
case 1:
newArray[index] = targetBuffer[i] >>> 1 & 0x0001;
break;
case 2:
newArray[index] = targetBuffer[i] >>> 2 & 0x0001;
break;
case 3:
newArray[index] = targetBuffer[i] >>> 3 & 0x0001;
break;
case 4:
newArray[index] = targetBuffer[i] >>> 4 & 0x0001;
break;
case 5:
newArray[index] = targetBuffer[i] >>> 5 & 0x0001;
break;
case 6:
newArray[index] = targetBuffer[i] >>> 6 & 0x0001;
break;
case 7:
newArray[index] = targetBuffer[i] >>> 7 & 0x0001;
break;
default:
break;
}
bitStartOffset++;
index++;
// if return..
if (index >= numPixels) {
return newArray;
}
}
bitStartOffset = 0;
}
}
}
}, {
key: '_convertColorSpace',
value: function _convertColorSpace(uncompressedData) {
var rgbData = null;
var photometricInterpretation = this.photometricInterpretation();
var planarConfiguration = this.planarConfiguration();
if (photometricInterpretation === 'RGB' && planarConfiguration === 0) {
// ALL GOOD, ALREADY ORDERED
// planar or non planar planarConfiguration
rgbData = uncompressedData;
} else if (photometricInterpretation === 'RGB' && planarConfiguration === 1) {
if (uncompressedData instanceof Int8Array) {
rgbData = new Int8Array(uncompressedData.length);
} else if (uncompressedData instanceof Uint8Array) {
rgbData = new Uint8Array(uncompressedData.length);
} else if (uncompressedData instanceof Int16Array) {
rgbData = new Int16Array(uncompressedData.length);
} else if (uncompressedData instanceof Uint16Array) {
rgbData = new Uint16Array(uncompressedData.length);
} else {
throw 'unsuported typed array: ${uncompressedData}';
}
var numPixels = uncompressedData.length / 3;
var rgbaIndex = 0;
var rIndex = 0;
var gIndex = numPixels;
var bIndex = numPixels * 2;
for (var i = 0; i < numPixels; i++) {
rgbData[rgbaIndex++] = uncompressedData[rIndex++]; // red
rgbData[rgbaIndex++] = uncompressedData[gIndex++]; // green
rgbData[rgbaIndex++] = uncompressedData[bIndex++]; // blue
}
} else if (photometricInterpretation === 'YBR_FULL') {
if (uncompressedData instanceof Int8Array) {
rgbData = new Int8Array(uncompressedData.length);
} else if (uncompressedData instanceof Uint8Array) {
rgbData = new Uint8Array(uncompressedData.length);
} else if (uncompressedData instanceof Int16Array) {
rgbData = new Int16Array(uncompressedData.length);
} else if (uncompressedData instanceof Uint16Array) {
rgbData = new Uint16Array(uncompressedData.length);
} else {
throw 'unsuported typed array: ${uncompressedData}';
}
// https://github.com/chafey/cornerstoneWADOImageLoader/blob/master/src/decodeYBRFull.js
var nPixels = uncompressedData.length / 3;
var ybrIndex = 0;
var _rgbaIndex = 0;
for (var _i = 0; _i < nPixels; _i++) {
var y = uncompressedData[ybrIndex++];
var cb = uncompressedData[ybrIndex++];
var cr = uncompressedData[ybrIndex++];
rgbData[_rgbaIndex++] = y + 1.40200 * (cr - 128); // red
rgbData[_rgbaIndex++] = y - 0.34414 * (cb - 128) - 0.71414 * (cr - 128); // green
rgbData[_rgbaIndex++] = y + 1.77200 * (cb - 128); // blue
// rgbData[rgbaIndex++] = 255; //alpha
}
} else {
throw 'photometric interpolation not supported: ${photometricInterpretation}';
}
return rgbData;
}
/**
* Swap bytes in frame.
*/
}, {
key: '_swapFrame',
value: function _swapFrame(frame) {
// swap bytes ( if 8bits (1byte), nothing to swap)
var bitsAllocated = this.bitsAllocated();
if (bitsAllocated === 16) {
for (var i = 0; i < frame.length; i++) {
frame[i] = this._swap16(frame[i]);
}
} else if (bitsAllocated === 32) {
for (var _i2 = 0; _i2 < frame.length; _i2++) {
frame[_i2] = this._swap32(frame[_i2]);
}
}
return frame;
}
}]);
return ParsersDicom;
}(_parsers2.default);
// VJS.parsers.dicom.prototype.frameOfReferenceUID = function(imageJqueryDom) {
// // try to access frame of reference UID through its DICOM tag
// let seriesNumber = imageJqueryDom.find('[tag="00200052"] Value').text();
// // if not available, assume we only have 1 frame
// if (seriesNumber === '') {
// seriesNumber = 1;
// }
// return seriesNumber;
// };
//
// ENDIAN NESS NOT TAKEN CARE OF
// http://stackoverflow.com/questions/5320439/how-do-i-swap-endian-ness-byte-order-of-a-letiable-in-javascript
// http://www.barre.nom.fr/medical/samples/
//
//
exports.default = ParsersDicom;
module.exports = exports['default'];