// namespaces
var dwv = dwv || {};
dwv.dicom = dwv.dicom || {};
// List of pixel generators
dwv.dicom.pixelGenerators = dwv.dicom.pixelGenerators || {};
/**
* Get the DICOM element from a DICOM tags object.
*
* @param {object} tags The DICOM tags object.
* @returns {object} The DICOM elements and the end offset.
*/
dwv.dicom.getElementsFromJSONTags = function (tags) {
// transfer syntax
var isImplicit = dwv.dicom.isImplicitTransferSyntax(tags.TransferSyntaxUID);
// convert JSON to DICOM element object
var keys = Object.keys(tags);
var dicomElements = {};
var dicomElement;
var name;
var offset = 128 + 4; // preamble
var size;
for (var k = 0, len = keys.length; k < len; ++k) {
// get the DICOM element definition from its name
dicomElement = dwv.dicom.getDicomElement(keys[k]);
// set its value
size = dwv.dicom.setElementValue(dicomElement, tags[keys[k]], isImplicit);
// set offsets
offset += dwv.dicom.getDataElementPrefixByteSize(
dicomElement.vr, isImplicit);
dicomElement.startOffset = offset;
offset += size;
dicomElement.endOffset = offset;
// create the tag group/element key
name = new dwv.dicom.Tag(
dicomElement.tag.group, dicomElement.tag.element).getKey();
// store
dicomElements[name] = dicomElement;
}
// return
return {elements: dicomElements, offset: offset};
};
/**
* Get the DICOM pixel data from a DICOM tags object.
*
* @param {object} tags The DICOM tags object.
* @param {object} startOffset The start offset of the pixel data.
* @param {string} pixGeneratorName The name of a pixel generator.
* @param {number} sliceNumber The slice number.
* @param {Array} images The images to pass to the generator.
* @param {number} numberOfSlices The result number of slices.
* @returns {object} The DICOM pixel data element.
*/
dwv.dicom.generatePixelDataFromJSONTags = function (
tags, startOffset, pixGeneratorName, sliceNumber, images, numberOfSlices) {
// default
if (typeof pixGeneratorName === 'undefined') {
pixGeneratorName = 'gradSquare';
}
if (typeof sliceNumber === 'undefined') {
sliceNumber = 0;
}
if (typeof numberOfSlices === 'undefined') {
numberOfSlices = 1;
}
// check tags
if (typeof tags.TransferSyntaxUID === 'undefined') {
throw new Error('Missing transfer syntax for pixel generation.');
} else if (typeof tags.Rows === 'undefined') {
throw new Error('Missing number of rows for pixel generation.');
} else if (typeof tags.Columns === 'undefined') {
throw new Error('Missing number of columns for pixel generation.');
} else if (typeof tags.BitsAllocated === 'undefined') {
throw new Error('Missing BitsAllocated for pixel generation.');
} else if (typeof tags.PixelRepresentation === 'undefined') {
throw new Error('Missing PixelRepresentation for pixel generation.');
} else if (typeof tags.SamplesPerPixel === 'undefined') {
throw new Error('Missing SamplesPerPixel for pixel generation.');
} else if (typeof tags.PhotometricInterpretation === 'undefined') {
throw new Error('Missing PhotometricInterpretation for pixel generation.');
}
// extract info from tags
var numberOfRows = tags.Rows;
var numberOfColumns = tags.Columns;
var bitsAllocated = tags.BitsAllocated;
var pixelRepresentation = tags.PixelRepresentation;
var samplesPerPixel = tags.SamplesPerPixel;
// trim in case config contains padding
var photometricInterpretation = tags.PhotometricInterpretation.trim();
var sliceLength = numberOfRows * numberOfColumns;
var dataLength = sliceLength * samplesPerPixel;
// check values
if (samplesPerPixel !== 1 && samplesPerPixel !== 3) {
throw new Error(
'Unsupported SamplesPerPixel for pixel generation: ' +
samplesPerPixel);
}
if ((samplesPerPixel === 1 && !(photometricInterpretation === 'MONOCHROME1' ||
photometricInterpretation === 'MONOCHROME2')) ||
(samplesPerPixel === 3 && photometricInterpretation !== 'RGB')) {
throw new Error(
'Unsupported PhotometricInterpretation for pixel generation: ' +
photometricInterpretation + ' with SamplesPerPixel: ' + samplesPerPixel);
}
var numberOfSamples = 1;
var numberOfColourPlanes = 1;
if (samplesPerPixel === 3) {
if (typeof tags.PlanarConfiguration === 'undefined') {
throw new Error('Missing PlanarConfiguration for pixel generation.');
}
var planarConfiguration = tags.PlanarConfiguration;
if (planarConfiguration !== 0 && planarConfiguration !== 1) {
throw new Error(
'Unsupported PlanarConfiguration for pixel generation: ' +
planarConfiguration);
}
if (planarConfiguration === 0) {
numberOfSamples = 3;
} else {
numberOfColourPlanes = 3;
}
}
// create pixel array
var pixels = dwv.dicom.getTypedArray(
bitsAllocated, pixelRepresentation, dataLength);
// pixels generator
if (typeof dwv.dicom.pixelGenerators[pixGeneratorName] === 'undefined') {
throw new Error('Unknown PixelData generator: ' + pixGeneratorName);
}
var GeneratorClass = dwv.dicom.pixelGenerators[pixGeneratorName].generator;
var generator = new GeneratorClass({
numberOfColumns: numberOfColumns,
numberOfRows: numberOfRows,
numberOfSamples: numberOfSamples,
numberOfColourPlanes: numberOfColourPlanes,
photometricInterpretation: photometricInterpretation
});
if (typeof generator.setImages !== 'undefined') {
generator.setImages(images);
}
if (typeof generator.setNumberOfSlices !== 'undefined') {
generator.setNumberOfSlices(numberOfSlices);
}
generator.generate(pixels, sliceNumber);
// create and return the DICOM element
var vr = 'OW';
if (bitsAllocated === 8) {
vr = 'OB';
}
var pixVL = pixels.BYTES_PER_ELEMENT * dataLength;
return {
tag: {group: '0x7FE0', element: '0x0010'},
vr: vr,
vl: pixVL,
value: pixels,
startOffset: startOffset,
endOffset: startOffset + pixVL
};
};
/**
* Extract the image data from an image.
*
* @param {Image} image The image to get the data from.
* @returns {object} The image data buffer.
*/
dwv.dicom.getImageDataData = function (image) {
// draw the image in the canvas in order to get its data
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
// get the image data
var imageData = ctx.getImageData(0, 0, image.width, image.height);
// data.data
return imageData.data;
};