dcmjs-org / dcmjs

Javascript implementation of DICOM manipulation
https://dcmjs.netlify.com/
MIT License
291 stars 110 forks source link

Changing instance UID corrupts file, Invalid DICOM file, expected header is missing #315

Open esmadau opened 1 year ago

esmadau commented 1 year ago

A lot of this was taken from this example: https://github.com/dcmjs-org/dcmjs/blob/add-commander/examples/nodejs/readwrite.js

I just need to be able to set the UID and generate new binary data. Code below is making sure data held in memory has changed.

To reproduce:

// read DicomDict from an arrayBuffer
let DicomDict = data.DicomMessage.readFile(arrayBuffer);
let dataset = data.DicomMetaDictionary.naturalizeDataset(DicomDict.dict);
console.log("StudyInstanceUID name is :", dataset.StudyInstanceUID);

// Generate new UID and set on dataset
dataset.StudyInstanceUID = DICOMUID.create();
console.log("New StudyInstanceUID name is :", dataset.StudyInstanceUID);

// write arraybuffer
DicomDict.dict = data.DicomMetaDictionary.denaturalizeDataset(dataset);
let new_file_WriterBuffer = DicomDict.write();

// REREAD buffer to see if id did change
const newArrayBuffer = new ArrayBuffer(new_file_WriterBuffer);
let NewDicomDict = data.DicomMessage.readFile(newArrayBuffer);
let dataset_new = data.DicomMetaDictionary.naturalizeDataset(NewDicomDict.dict);
console.log("dataset_new.StudyInstanceUID name in dataset_new is :", dataset_new.StudyInstanceUID);

What I would expect:

INFO[0000] StudyInstanceUID name is : 2.25.127629050410002609075320091401000010001  source=console
INFO[0000] New StudyInstanceUID name is : 2.25.39439685288125461796754857035753291132  source=console
INFO[0000] dataset_new.StudyInstanceUID name in dataset_new is  2.25.39439685288125461796754857035753291132  source=console

What I see:

INFO[0000] StudyInstanceUID name is : 2.25.127629050410002609075320091401000010001  source=console
INFO[0000] New StudyInstanceUID name is : 2.25.39439685288125461796754857035753291132  source=console
ERRO[0000] Error: Invalid DICOM file, expected header is missing
        at value (file:///home/x/dist/stowTest.bundle.js:2:912306(57))
        at file:///home/x/dist/stowTest.bundle.js:2:1020469(95402)
        at file:///home/x/dist/stowTest.bundle.js:2:1020917(39)
        at file:///home/x/dist/stowTest.bundle.js:2:1021023(3)
        at native  hint="script exception"
pieper commented 1 year ago

Thanks for reporting this. That's definitely a use case we want to make sure works.

From what I can see the DICM marker is missing (maybe the whole preamble is missing).

https://github.com/dcmjs-org/dcmjs/blob/914b3dccd1a9e9fd19f2ac94be6e02a82a6316ec/src/DicomMessage.js#L201

But it should have been written out by DicomDict.write() so something must be going on.

https://github.com/dcmjs-org/dcmjs/blob/914b3dccd1a9e9fd19f2ac94be6e02a82a6316ec/src/DicomDict.js#L20-L24

Could you look at, for example, this test and see what's different from your case? If needed could you make a PR for this use case in the form of a test that could be used to document this use case and confirm that it's (ultimately) fixed.

esmadau commented 1 year ago

Thanks for the quick reply. I'll work on a test. Also, I noticed that when overriding the UID given the example provided, PixelData is lost. Is there a way for me to change the UID and retain PixelData?

pieper commented 1 year ago

PixelData should not be lost. Did you make a simple test case to illustrate what you are doing?

EastLight0 commented 1 year ago

hi friends! I have a similar problem...

I'm trying to insert a dicom tag. A tag is inserted in the final dicom file. but, an error occurs when opening the saved dicom file. So I thought about my problem. After checking that the Pixeldata is changed after saving, I looked for the problem.

let arrayBuffer = fs.readFileSync(filePath).buffer;    
let DicomDict = dcmjs.data.DicomMessage.readFile(arrayBuffer);    
console.log(DicomDict.dict['7FE00010']);    
DicomDict.upsertTag('00080005', 'CS', 'ISO_IR 192');    
console.log(DicomDict.dict['7FE00010']);   
let new_file_WriterBuffer = DicomDict.write();   
fs.writeFileSync(filePath, new Buffer.from(new_file_WriterBuffer));

If you print the log before and after modifying the dicom file, you can get the following result.

image

Since the file is a 512*512 image, byteLength 524288 should appear, but you can see that it is loaded as byteLength 519511.

Some another files are loaded so perfect image

I think that when loading the dicom file, the PixelArray cannot be loaded correctly.... The "dcmjs.data.DicomMessage.readFile" function doesn't seem to load the file correctly.

Please... help me...

pieper commented 1 year ago

@EastLight0 Thanks for reporting. Please make a test that demonstrates the issue following the example of the other tests in the repo.