[vtkusers] Problem using vtkDicomWriter

Eddy Cappeau edcpwk at gmail.com
Fri Jan 27 08:31:09 EST 2017


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/
aa379886(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/d1eaac3d/attachment.html>


More information about the vtkusers mailing list