js-dicom
Version:
this is js-dicom
140 lines (117 loc) • 5.95 kB
JavaScript
import $ from 'jquery';
import getImageFrame from './getImageFrame';
import decodeImageFrame from './decodeImageFrame';
import isJPEGBaseline8BitColor from './isJPEGBaseline8BitColor';
import convertColorSpace from './convertColorSpace';
import metaData from './metaData';
import {default as isColorImageFn} from './isColorImage';
import getMinMax from './getMinMax';
import rendering from './rendering';
function isModalityLUTForDisplay (sopClassUid) {
// special case for XA and XRF
// https://groups.google.com/forum/#!searchin/comp.protocols.dicom/Modality$20LUT$20XA/comp.protocols.dicom/UBxhOZ2anJ0/D0R_QP8V2wIJ
return sopClassUid !== '1.2.840.10008.5.1.4.1.1.12.1' && // XA
sopClassUid !== '1.2.840.10008.5.1.4.1.1.12.2.1'; // XRF
}
function setPixelDataType (imageFrame) {
if (imageFrame.bitsAllocated === 16) {
if (imageFrame.pixelRepresentation === 0) {
imageFrame.pixelData = new Uint16Array(imageFrame.pixelData);
} else {
imageFrame.pixelData = new Int16Array(imageFrame.pixelData);
}
} else {
imageFrame.pixelData = new Uint8Array(imageFrame.pixelData);
}
}
function createImage (dataSet, pixelData, transferSyntax, options) {
const canvas = document.createElement('canvas');
const imageFrame = decodeImageFrame(getImageFrame(dataSet), transferSyntax, pixelData, canvas, options);
// var imagePixelModule = metaDataProvider('imagePixelModule', imageId);
const imagePlaneModule = metaData.metaDataProvider('imagePlaneModule', dataSet);
const voiLutModule = metaData.metaDataProvider('voiLutModule', dataSet);
const modalityLutModule = metaData.metaDataProvider('modalityLutModule', dataSet);
const sopCommonModule = metaData.metaDataProvider('sopCommonModule', dataSet);
const isColorImage = isColorImageFn(imageFrame.photometricInterpretation);
// JPEGBaseline (8 bits) is a lready returning the pixel data in the right format (rgba)
// because it's using a canvas to load and decode images.
if (!isJPEGBaseline8BitColor(imageFrame, transferSyntax)) {
setPixelDataType(imageFrame);
// convert color space
if (isColorImage) {
// setup the canvas context
canvas.height = imageFrame.rows;
canvas.width = imageFrame.columns;
const context = canvas.getContext('2d');
const imageData = context.createImageData(imageFrame.columns, imageFrame.rows);
convertColorSpace(imageFrame, imageData);
imageFrame.imageData = imageData;
imageFrame.pixelData = imageData.data;
}
}
const image = {
color: isColorImage,
columnPixelSpacing: imagePlaneModule.pixelSpacing ? imagePlaneModule.pixelSpacing[1] : undefined,
columns: imageFrame.columns,
height: imageFrame.rows,
intercept: modalityLutModule.rescaleIntercept ? modalityLutModule.rescaleIntercept : 0,
invert: imageFrame.photometricInterpretation === 'MONOCHROME1',
minPixelValue: imageFrame.smallestPixelValue,
maxPixelValue: imageFrame.largestPixelValue,
render: undefined, // set below
rowPixelSpacing: imagePlaneModule.pixelSpacing ? imagePlaneModule.pixelSpacing[0] : undefined,
rows: imageFrame.rows,
sizeInBytes: imageFrame.pixelData.length,
slope: modalityLutModule.rescaleSlope ? modalityLutModule.rescaleSlope : 1,
width: imageFrame.columns,
windowCenter: voiLutModule.windowCenter ? voiLutModule.windowCenter[0] : undefined,
windowWidth: voiLutModule.windowWidth ? voiLutModule.windowWidth[0] : undefined,
decodeTimeInMS: imageFrame.decodeTimeInMS
};
// add function to return pixel data
image.getPixelData = () => imageFrame.pixelData;
// Setup the renderer
if (image.color) {
image.render = rendering.renderColorImage;
image.getCanvas = function () {
canvas.height = image.rows;
canvas.width = image.columns;
const context = canvas.getContext('2d');
context.putImageData(imageFrame.imageData, 0, 0);
return canvas;
};
} else {
image.render = rendering.renderGrayscaleImage;
}
// calculate min/max if not supplied
if (image.minPixelValue === undefined || image.maxPixelValue === undefined) {
const minMax = getMinMax(imageFrame.pixelData);
image.minPixelValue = minMax.min;
image.maxPixelValue = minMax.max;
}
// Modality LUT
if (modalityLutModule.modalityLUTSequence &&
modalityLutModule.modalityLUTSequence.length > 0 &&
isModalityLUTForDisplay(sopCommonModule.sopClassUID)) {
image.modalityLUT = modalityLutModule.modalityLUTSequence[0];
}
// VOI LUT
if (voiLutModule.voiLUTSequence &&
voiLutModule.voiLUTSequence.length > 0) {
image.voiLUT = voiLutModule.voiLUTSequence[0];
}
// set the ww/wc to cover the dynamic range of the image if no values are supplied
if (image.windowCenter === undefined || image.windowWidth === undefined) {
if (image.color) {
image.windowWidth = 255;
image.windowCenter = 128;
} else {
const maxVoi = image.maxPixelValue * image.slope + image.intercept;
const minVoi = image.minPixelValue * image.slope + image.intercept;
image.windowWidth = maxVoi - minVoi;
image.windowCenter = (maxVoi + minVoi) / 2;
}
}
return image;
}
export default createImage;