cornerstone-wado-image-loader
Version:
Cornerstone Image Loader for DICOM WADO-URI and WADO-RS
184 lines (135 loc) • 8.25 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8">
<title>imageLoader/wadouri/dataset-from-partial-content.js - Documentation</title>
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
<script src="scripts/nav.js" defer></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger" class="navicon-button x">
<div class="navicon"></div>
</label>
<label for="nav-trigger" class="overlay"></label>
<nav >
<h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#addTask">addTask</a></li><li><a href="global.html#arrayBufferToString">arrayBufferToString</a></li><li><a href="global.html#cacheSizeInBytes">cacheSizeInBytes</a></li><li><a href="global.html#cancelTask">cancelTask</a></li><li><a href="global.html#decodeAsync">decodeAsync</a></li><li><a href="global.html#decodeImageFrame">decodeImageFrame</a></li><li><a href="global.html#extractOrientationFromDataset">extractOrientationFromDataset</a></li><li><a href="global.html#extractOrientationFromMetadata">extractOrientationFromMetadata</a></li><li><a href="global.html#extractOrientationFromNMMultiframeDataset">extractOrientationFromNMMultiframeDataset</a></li><li><a href="global.html#extractOrientationFromNMMultiframeMetadata">extractOrientationFromNMMultiframeMetadata</a></li><li><a href="global.html#extractPositionFromDataset">extractPositionFromDataset</a></li><li><a href="global.html#extractPositionFromMetadata">extractPositionFromMetadata</a></li><li><a href="global.html#extractPositionFromNMMultiframeDataset">extractPositionFromNMMultiframeDataset</a></li><li><a href="global.html#extractPositionFromNMMultiframeMetadata">extractPositionFromNMMultiframeMetadata</a></li><li><a href="global.html#extractSliceThicknessFromDataset">extractSliceThicknessFromDataset</a></li><li><a href="global.html#extractSpacingFromDataset">extractSpacingFromDataset</a></li><li><a href="global.html#framesAreFragmented">framesAreFragmented</a></li><li><a href="global.html#getImageTypeSubItemFromDataset">getImageTypeSubItemFromDataset</a></li><li><a href="global.html#getImageTypeSubItemFromMetadata">getImageTypeSubItemFromMetadata</a></li><li><a href="global.html#getMinMax">getMinMax</a></li><li><a href="global.html#getNumberString">getNumberString</a></li><li><a href="global.html#getNumberValues">getNumberValues</a></li><li><a href="global.html#getStatistics">getStatistics</a></li><li><a href="global.html#getTransferSyntaxForContentType">getTransferSyntaxForContentType</a></li><li><a href="global.html#getUncompressedImageFrame">getUncompressedImageFrame</a></li><li><a href="global.html#getValue">getValue</a></li><li><a href="global.html#handleMessageFromWorker">handleMessageFromWorker</a></li><li><a href="global.html#handler">handler</a></li><li><a href="global.html#initialize">initialize</a></li><li><a href="global.html#loadCodecs">loadCodecs</a></li><li><a href="global.html#loadWebWorkerTask">loadWebWorkerTask</a></li><li><a href="global.html#registerLoaders">registerLoaders</a></li><li><a href="global.html#registerTaskHandler">registerTaskHandler</a></li><li><a href="global.html#removeAFromRGBA">removeAFromRGBA</a></li><li><a href="global.html#setPixelDataType">setPixelDataType</a></li><li><a href="global.html#setTaskPriority">setTaskPriority</a></li><li><a href="global.html#spawnWebWorker">spawnWebWorker</a></li><li><a href="global.html#startTaskOnWebWorker">startTaskOnWebWorker</a></li><li><a href="global.html#terminate">terminate</a></li><li><a href="global.html#unpackBinaryFrame">unpackBinaryFrame</a></li></ul>
</nav>
<div id="main">
<h1 class="page-title">imageLoader/wadouri/dataset-from-partial-content.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>// @ts-check
import external from '../../externalModules.js';
function fixFragments(dataSet) {
// The partially parsed pixelData element has incorrect fragment
// lengths because the byte array is truncated, so we manually set
// it to the actual length.
const fragments = dataSet.elements.x7fe00010.fragments;
const totalLength = dataSet.byteArray.length;
for (const fragment of fragments) {
const { position, length } = fragment;
if (length > totalLength - position) {
console.log(
`Truncated fragment, changing fragment length from ${
fragment.length
} to ${totalLength - position}`
);
fragment.length = totalLength - position;
}
}
return dataSet;
}
function parsePartialByteArray(byteArray) {
const { dicomParser } = external;
/**
* First parse just up to pixelData. This will make sure the
* metadata header is correctly parsed (assuming no other error is
* thrown during parsing). Then, parse again using the whole partial
* arraybuffer. This will error, but still kick out the parsed
* partial pixel data in the error object.
*/
let dataSet = dicomParser.parseDicom(byteArray, {
untilTag: 'x7fe00010',
});
if (!dataSet.elements.x7fe00010) {
console.warn('Pixel data not found!');
// Re-fetch more of the file
}
let pixelDataSet;
try {
// This is expected to fail, since the file is incomplete, but
// dicomParser helpfully spits out the parsed partial dataset in
// the error object. The problem is, the dataset here is
// incomplete, because dicomParser throws *before* combining the
// metadata header and regular datasets, so transfer syntax and
// other metadata headers aren't included.
pixelDataSet = dicomParser.parseDicom(byteArray);
} catch (err) {
console.error(err);
console.log('pixel data dataset:', err.dataSet);
pixelDataSet = err.dataSet;
}
// Add the parsed partial pixel data element to the dataset
// including the metadata headers.
dataSet.elements.x7fe00010 = pixelDataSet.elements.x7fe00010;
dataSet = fixFragments(dataSet);
return dataSet;
}
export default async function dataSetFromPartialContent(
byteArray,
loadRequest,
metadata
) {
const dataSet = parsePartialByteArray(byteArray);
const { uri, imageId, fileTotalLength } = metadata;
// Allow re-fetching of more of the file
dataSet.fetchMore = async function (fetchOptions) {
// Default to fetching the rest of the file if no lengthToFetch is set. Also
// default to fetching the same URI/imageId
const _options = Object.assign(
{
uri,
imageId,
fetchedLength: byteArray.length, // Not sure if this would ever need to be configurable tbh
lengthToFetch: fileTotalLength - byteArray.length,
},
fetchOptions
);
const { fetchedLength, lengthToFetch } = _options;
// Use passed xhr loader to re-fetch new byte range
const { arrayBuffer } = await loadRequest(uri, imageId, {
byteRange: `${fetchedLength}-${fetchedLength + lengthToFetch}`,
});
// Combine byte ranges
const byteArrayToAppend = new Uint8Array(arrayBuffer);
const combinedByteArray = new Uint8Array(
dataSet.byteArray.length + byteArrayToAppend.length
);
combinedByteArray.set(dataSet.byteArray);
combinedByteArray.set(byteArrayToAppend, dataSet.byteArray.length);
// Re-parse potentially partial byte range and return
return dataSetFromPartialContent(combinedByteArray, loadRequest, metadata);
};
return dataSet;
}
</code></pre>
</article>
</section>
</div>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.7</a> using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
</footer>
<script>prettyPrint();</script>
<script src="scripts/polyfill.js"></script>
<script src="scripts/linenumber.js"></script>
</body>
</html>