[vtkusers] Problem using vtkDicomWriter
David Gobbi
david.gobbi at gmail.com
Fri Jan 27 11:02:02 EST 2017
Hi Eddy,
Thanks for tracking this down, I'm adding this change to vtk-dicom.
- David
On Fri, Jan 27, 2017 at 6:31 AM, Eddy Cappeau <edcpwk at gmail.com> wrote:
> Hi David,
>
> I've patched my vtk 7.1 source and recompile and that's working. I can
> load my dicom directory in Slicer without problems now.
>
> I've surely faced a corner case, but after reading the documentation (
> https://msdn.microsoft.com/en-us/library/windows/desktop/aa
> 379886(v=vs.85).aspx), I think it's maybe safer to use the
> CRYPT_VERIFYCONTEXT flag.
>
> Thanks for your help.
>
> Eddy
>
>
> 2017-01-27 11:27 GMT+01:00 Eddy Cappeau <edcpwk at gmail.com>:
>
>> Hi David,
>>
>> For the vtk-dicom I'm using, I've just compile VTK 7.1 with the vtkdicom
>> module activated.
>> I'm on Windows 7 and compile with visual studio 2013 in 64 bits.
>>
>> I've tried this :
>>
>> auto uidg = generator->GetUIDGenerator();
>>
>> assert(uidg != nullptr);
>>
>> auto uid_1 = uidg->GenerateUID(DC::SeriesInstanceUID);
>> auto uid_2 = uidg->GenerateUID(DC::SOPInstanceUID);
>> auto uid_3 = uidg->GenerateUID(DC::FrameOfReferenceUID);
>>
>> auto uid_4 = vtkDICOMUtilities::GenerateUID(DC::SeriesInstanceUID);
>> auto uid_5 = vtkDICOMUtilities::GenerateUID(DC::SOPInstanceUID);
>> auto uid_6 = vtkDICOMUtilities::GenerateUID(DC::FrameOfReferenceUID);
>>
>> The value returned is always : "2.25.302240678275694148452352"
>>
>> After some investiations, I found a problem with the
>> vtkGenerateRandomBytes function in vtkDICOMUIDGenerator.cxx.
>> The error returned by CryptAcquireContext in my case is NTE_BAD_KEY_STATE.
>> So the CryptGenRandom function is never called a the buffer is filled
>> with zeros.
>>
>> I copied the function for debug purpose and used the fix proposed at the
>> end of this thread :
>>
>> http://stackoverflow.com/questions/29996467/cryptacquirecont
>> ext-fails-with-return-code-0x8009000b-nte-bad-key-state-but
>>
>> And that did the trick it seems.
>>
>> For testing the solution, how can I patch my vtk-dicom sources ?
>> is it enough to edit de source directly in VTK-7.1.0\Remote\vtkDICOM\Source
>> and rebuild VTK ?
>>
>> Thanks,
>>
>> Eddy
>>
>> 2017-01-26 17:23 GMT+01:00 David Gobbi <david.gobbi at gmail.com>:
>>
>>> Hi Eddy,
>>>
>>> The SOPInstanceUID must be different for each image (and the other two
>>> UIDs shouldn't be the same as the SeriesInstanceUID, either).
>>>
>>> What version of vtk-dicom are you using, and what operating system? I
>>> can check on my end to make sure that the random numbers for the UUIDs are
>>> being properly generated. I use CryptGenRandom() on Windows and
>>> /dev/urandom on UNIX/Linux.
>>>
>>> - David
>>>
>>> On Thu, Jan 26, 2017 at 9:05 AM, Eddy Cappeau <edcpwk at gmail.com> wrote:
>>>
>>>> Hi David,
>>>>
>>>> When I load the DICOM directory, Slicer tells me that there's only one
>>>> serie.
>>>> Each image have the same SeriesInstanceUID.
>>>>
>>>> I don't know if it's normal but the SeriesInstanceUID is also used for
>>>> the SOPInstanceUID, the StudyInstanceUID and the FrameOfReferenceUID.
>>>>
>>>> I've made a screenshot of the Slicer metadata browser here :
>>>>
>>>> https://framapic.org/t3tTt1RHhlWP/XhHP9dQ2Nz8s.png
>>>>
>>>>
>>>> Eddy
>>>>
>>>>
>>>> 2017-01-26 15:43 GMT+01:00 David Gobbi <david.gobbi at gmail.com>:
>>>>
>>>>> Hi Eddy,
>>>>>
>>>>> In Slicer's DICOM browser, does it show all of the images as belonging
>>>>> to the same series? I'm wondering if, perhaps, each image has a different
>>>>> SeriesInstanceUID. That would definitely cause problems with loading into
>>>>> a "dicom aware" program like Slicer, but ParaView probably wouldn't care.
>>>>>
>>>>> - David
>>>>>
>>>>> On Thu, Jan 26, 2017 at 7:30 AM, Eddy Cappeau <edcpwk at gmail.com>
>>>>> wrote:
>>>>>
>>>>>> Hi Andras,
>>>>>>
>>>>>> I didn't manage to load un single image before.
>>>>>>
>>>>>> Thank you for the tip.
>>>>>>
>>>>>> Eddy
>>>>>>
>>>>>> 2017-01-26 15:28 GMT+01:00 Eddy Cappeau <edcpwk at gmail.com>:
>>>>>>
>>>>>>> Hello David,
>>>>>>>
>>>>>>> I used the vtkDICOMMRGenerator filter, unsigned short instead of
>>>>>>> unsigned char and add this line :
>>>>>>>
>>>>>>> meta->SetAttributeValue(DC::SpacingBetweenSlices, "1");
>>>>>>>
>>>>>>> The BitsAllocated has now a value of 16 but I've got the same result.
>>>>>>>
>>>>>>> Thanks to the tips given by Andras, I've opened each slice
>>>>>>> individually and they seems correct.
>>>>>>>
>>>>>>> There's definitly something wrong in my files, but I don't see why.
>>>>>>>
>>>>>>> Thanks.
>>>>>>>
>>>>>>> Eddy
>>>>>>>
>>>>>>> 2017-01-25 14:35 GMT+01:00 David Gobbi <david.gobbi at gmail.com>:
>>>>>>>
>>>>>>>> Hi Eddy,
>>>>>>>>
>>>>>>>> The code is using a vtkDICOMCTGenerator to write an MR image, which
>>>>>>>> is definitely wrong. Use the vtkDICOMMRGenerator, and make sure the meta
>>>>>>>> data matches the IOD: http://dicom.nema.org/med
>>>>>>>> ical/dicom/current/output/chtml/part03/sect_C.8.3.html
>>>>>>>>
>>>>>>>> The standard says that BitsAllocated must be 16 for MR images,
>>>>>>>> therefore an 8-bit MR image is non-standard and DICOM software may to
>>>>>>>> refuse to display it. You should convert your data to 16-bit (In fact, it
>>>>>>>> seems fishy that you are working with unsigned char, since if you are
>>>>>>>> writing a reformat of an MR image, then wasn't the original MR image a
>>>>>>>> 16-bit image?)
>>>>>>>>
>>>>>>>> I can't answer about why Slicer is only showing one slice, as I
>>>>>>>> don't currently have Slicer installed.
>>>>>>>>
>>>>>>>> - David
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On Wed, Jan 25, 2017 at 1:57 AM, Eddy Cappeau <edcpwk at gmail.com>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>>> Hi David,
>>>>>>>>>
>>>>>>>>> Here's the code below. This is almost the example of the api doc :
>>>>>>>>>
>>>>>>>>> auto generator = vtkSmartPointer <vtkDICOMCTGenerator>::New();
>>>>>>>>> vtkSmartPointer <vtkDICOMMetaData> meta = vtkSmartPointer
>>>>>>>>> <vtkDICOMMetaData>::New();
>>>>>>>>>
>>>>>>>>> meta->SetAttributeValue(DC::PatientName, "Test");
>>>>>>>>> meta->SetAttributeValue(DC::PatientID, "0000001");
>>>>>>>>> meta->SetAttributeValue(DC::ScanOptions, "");
>>>>>>>>> meta->SetAttributeValue(DC::ScanningSequence, "GR");
>>>>>>>>> meta->SetAttributeValue(DC::SequenceVariant, "SP");
>>>>>>>>> meta->SetAttributeValue(DC::ScanOptions, "");
>>>>>>>>> meta->SetAttributeValue(DC::MRAcquisitionType, "2D");
>>>>>>>>>
>>>>>>>>> vtkSmartPointer <vtkDICOMWriter> dicom_writer =
>>>>>>>>> vtkSmartPointer <vtkDICOMWriter>::New();
>>>>>>>>> dicom_writer->SetInputData(img);
>>>>>>>>> dicom_writer->SetMetaData(meta);
>>>>>>>>> dicom_writer->SetGenerator(generator);
>>>>>>>>> dicom_writer->SetSeriesDescription("Sagittal Multi-planar
>>>>>>>>> Reformat");
>>>>>>>>>
>>>>>>>>> // Set the output filename format as a printf-style string.
>>>>>>>>> dicom_writer->SetFilePattern("%s/IM-0001-%04.4d.dcm");
>>>>>>>>> // Set the directory to write the files into.
>>>>>>>>> dicom_writer->SetFilePrefix(path.toStdString().c_str());
>>>>>>>>> // Write the file.
>>>>>>>>> dicom_writer->Write();
>>>>>>>>>
>>>>>>>>> Sorry, the use of an unsigned short type was a carreless mistake.
>>>>>>>>> The result is better with unsigned char,
>>>>>>>>> but I still see just one image of the serie on 3D Slicer. Is there
>>>>>>>>> something missing to have a complete serie ?
>>>>>>>>>
>>>>>>>>> I didn't know the vtkImageImport and I'll give it a try.
>>>>>>>>>
>>>>>>>>> Thanks,
>>>>>>>>>
>>>>>>>>> Eddy
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> 2017-01-24 15:41 GMT+01:00 David Gobbi <david.gobbi at gmail.com>:
>>>>>>>>>
>>>>>>>>>> Hi Eddy,
>>>>>>>>>>
>>>>>>>>>> Can you provide the code that you used to write the image with
>>>>>>>>>> vtkDICOMWriter? Here is an example:
>>>>>>>>>> http://dgobbi.github.io/vtk-dicom/doc/api/image_writer.html
>>>>>>>>>>
>>>>>>>>>> Creating an image with a loop that calls GetScalarPointer() for
>>>>>>>>>> every pixel is not very efficient, and casting to a "char *" when the data
>>>>>>>>>> is "unsigned short" is wrong: you are setting only 8 bits of each 16-bit
>>>>>>>>>> pixel, while leaving the other 8 bits uninitialized. The vtkImageImport
>>>>>>>>>> filter is a better way of generating image data:
>>>>>>>>>> http://www.vtk.org/Wiki/VTK/Examples/Cxx/Images/ImageImport
>>>>>>>>>>
>>>>>>>>>> - David
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Tue, Jan 24, 2017 at 2:51 AM, Eddy Cappeau <edcpwk at gmail.com>
>>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>>> Hi,
>>>>>>>>>>>
>>>>>>>>>>> I'd like to use the vtkDICOMWriter class to convert a vtkImage
>>>>>>>>>>> to a set of DICOM images.
>>>>>>>>>>>
>>>>>>>>>>> I've compile VTK with the vtkDICOM module enabled and followed
>>>>>>>>>>> the example from the pdf found on the github repository (
>>>>>>>>>>> http://dgobbi.github.io/vtk-dicom/doc/vtk-dicom.pdf).
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> The image data is created like this :
>>>>>>>>>>>
>>>>>>>>>>> auto img = vtkSmartPointer < vtkImageData >::New();
>>>>>>>>>>> img->SetOrigin(0, 0, 0);
>>>>>>>>>>> img->SetDimensions(1024, 1024, numlayer);
>>>>>>>>>>> img->SetSpacing(1, 1, 1);
>>>>>>>>>>> img->AllocateScalars(VTK_UNSIGNED_SHORT, 1);
>>>>>>>>>>>
>>>>>>>>>>> and the data filled like this :
>>>>>>>>>>>
>>>>>>>>>>> for (int n = 0; x < numlayer; n++) {
>>>>>>>>>>> for (int x = 0; x < 1024; x++) {
>>>>>>>>>>> for (int y = 0; y < 1024; y++) {
>>>>>>>>>>> char* pixel =
>>>>>>>>>>> static_cast<char*>(img->GetScalarPointer(x, y, n));
>>>>>>>>>>> pixel[0] = values[x][y];
>>>>>>>>>>> }
>>>>>>>>>>>
>>>>>>>>>>> I can load the converted result with paraview without problems.
>>>>>>>>>>> But with 3D Slicer, I can just load the first file of the serie
>>>>>>>>>>> and it display a blank image.
>>>>>>>>>>>
>>>>>>>>>>> What do I have to do to be able to load the images with both
>>>>>>>>>>> application ?
>>>>>>>>>>>
>>>>>>>>>>> Thanks,
>>>>>>>>>>>
>>>>>>>>>>> Eddy
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20170127/a62c3f80/attachment.html>
More information about the vtkusers
mailing list