dicomParser
dicomParser copied to clipboard
Getting: Error parsing byte stream RangeError: Invalid typed array length: ####
I'm trying to use the simple example to read in a dicom file and display it on the page using cornerstone and the cornerstoneWADOImageLoader libraries. I have this working fine using regular files and the wado fileuri loader, but I'm trying to get it working with byte arrays so I can do work with it with server-processed data. The simple example is throwing an error based on an incorrect Uint16Array length, I believe. Does anyone see anything wrong with this code?
const reader = new FileReader();
reader.addEventListener('load', (e) => {
let pixelData = self.loadP10Data(reader.result);
dicomImageData['example://1'] = pixelData;
self.loadAndViewP10Image('example://1');
}, false);
reader.readAsArrayBuffer(file);
loadP10Data(readerResult) {
const self = this;
try
{
let byteArray = new Uint8Array(readerResult);
// Parse the byte array to get a DataSet object that has the parsed contents
var dataSet = dicomParser.parseDicom(byteArray/*, options */);
// get the pixel data element (contains the offset and length of the data)
var pixelDataElement = dataSet.elements.x7fe00010;
// create a typed array on the pixel data (this example assumes 16 bit unsigned data)
// FAILS HERE:
var pixelData = new Uint16Array(dataSet.byteArray.buffer, pixelDataElement.dataOffset, pixelDataElement.length);
return pixelData;
}
catch(ex)
{
console.log('Error parsing byte stream', ex);
}
return '';
}
Error:
Got pixel data {tag: "x7fe00010", vr: "OW", length: 89456, dataOffset: 2098, hadUndefinedLength: true, …} app.js:56571 LENGTH 89456 app.js:56577 Error parsing byte stream RangeError: Invalid typed array length: 89456 at typedArrayConstructByArrayBuffer (
) at new Uint16Array (native) at StringBase64DicomFile.loadP10Data (http://localhost:3000/app.js:56573:29) at FileReader.reader.addEventListener (http://localhost:3000/app.js:56539:26)
I'm getting the same error.Pls help.
Iam getting the same error. Any updates on this ???
Is there a possible way to catch the error thrown while calling loadandcacheimage ?
We were able to work around it through a sort of hack. We could only get the cornerstone library to work only with explicit file handles (as opposed to loading or downloading the binary or base64 data of a file, and then putting that into cornerstone directly through a different loader). So as a workaround, we used the Chrome File API to put the binary data into a "file", and then load that into cornerstone with its handler.
Here is some example code that expects base64 data of the dicom file (from a React component), makes a 'file' out of it, and passes that to cornerstone as any other normal file:
(navigator as any).webkitPersistentStorage.requestQuota (
5000000, function(grantedBytes) {
self.writeFile(nextProps.value);
//self.registerCornerstoneImageLoader();
}, function(e) { console.log('Error', e); }
);
writeFile(fileData) {
const self = this;
(window as any).webkitRequestFileSystem((window as any).PERSISTENT, 5000000, (fs) => {
fs.root.getFile('dicomData.dcm', {create: true}, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
fileWriter.onwriteend = function(e) {
self.readFile();
};
fileWriter.onerror = function(e) {
};
// convert base64 string to binary
var buf = new Buffer(fileData, 'base64');
var blob = new Blob([buf], {type: 'application/dicom'});
fileWriter.write(blob);
}, self.onFileError);
}, self.onFileError);
}, self.onFileError);
}
readFile() {
const self = this;
(window as any).webkitRequestFileSystem((window as any).PERSISTENT, 5000000, (fs) => {
fs.root.getFile('dicomData.dcm', {}, function(fileEntry) {
fileEntry.file(function(file) {
self.loadAndViewDicomFile(file);
}, self.onFileError);
}, self.onFileError);
}, self.onFileError);
}
loadAndViewDicomFile(file: any) {
var self = this;
let cs = (window as any).cornerstone,
csLoader = (window as any).cornerstoneWADOImageLoader,
csImageEl = self._dicomPreviewElement;
// Disable old images from previous submission:
if (cs && csLoader && csImageEl) {
var imageId = csLoader.wadouri.fileManager.add(file);
var enabledEl = cs.getEnabledElement(csImageEl);
if (enabledEl)
cs.disable(csImageEl);
enabledEl = cs.enable(csImageEl);
window.setTimeout(() => {
cs.loadImage(imageId).then(function(image: any) {
self.setState({
dicomFile: file,
cornerstoneImage: image
});
var viewport = cs.getDefaultViewportForImage(csImageEl, image);
cs.displayImage(csImageEl, image, viewport);
}, function(err: any) {
let errorMessage = "An error occurred trying to parse the dicom file. The dicom file may be in an incompatible format. Please try another file.";
self.setState({
dicomError: errorMessage
})
});
});
}
}
Hope it helps.
Thanks a lot ! But it dint work out ! This is what I have and I am not able to add a function to capture the error for the same. cornerstone.loadAndCacheImage(imageId).then(function(image) { function code to display image });
Thanks for posting your solution, @rw3iss!
@swederik is this within your realm of expertise? This doesn't sound like supported functionality, but I've seen similar requests floating around. It might be worth marking it as an enhancement? How hard would it be to create a custom loader that takes a "key" that corresponds to a local store, and grabs the value (byte array) and successfully creates a new image object w/ it?
Has the problem been solved?Iam getting the same error……
RangeError: Invalid typed array length: 524288
I can't speak to the cornerstone side, but the RangeError is most likely coming from using the length in the UInt16Array constructor. It should be the number of elements, whereas the length field from the data element is the number of bytes. So this should be more accurate, assuming each pixel is 2 bytes:
var pixelData = new Uint16Array(dataSet.byteArray.buffer, pixelDataElement.dataOffset, pixelDataElement.length / 2);
Also remember to take the BitsStored field into account: if it's 8, you'll need to put the pixels in a UInt8Array; if it's 16, UInt16Array works.