I've been finding some odd behaviour with gdcmImage
and gdcmImageChangeTransferSyntax
when using Python 3.6 to 3.10 on Ubuntu 20.04 64-bit, Windows 10 64-bit and MacOS 64-bit Intel. I've tried with my own compilation and using wheels installed from pip install python-gdcm
.
The script below demonstrates using this dataset, but it happens with everything I've tested.
import gdcm from pydicom import dcmread def convert(pixel_data): image = gdcm.Image() image.SetNumberOfDimensions(2) image.SetDimensions((800, 600, 1)) pi = gdcm.PhotometricInterpretation.GetPIType( "PALETTE COLOR" ) image.SetPhotometricInterpretation( gdcm.PhotometricInterpretation(pi) ) image.SetTransferSyntax( gdcm.TransferSyntax( gdcm.TransferSyntax.ExplicitVRLittleEndian ) ) pixel_format = gdcm.PixelFormat(1, 8, 8, 7, 0) image.SetPixelFormat(pixel_format) elem = gdcm.DataElement( gdcm.Tag(0x7FE0, 0x0010), gdcm.VL(len(pixel_data)), gdcm.VR(gdcm.VR.OB), ) elem.SetByteStringValue(pixel_data) image.SetDataElement(elem) # Convert to RLE converter = gdcm.ImageChangeTransferSyntax() converter.SetTransferSyntax( gdcm.TransferSyntax( gdcm.TransferSyntax.GetTSType("1.2.840.10008.1.2.5") ) ) converter.SetInput(image) result = converter.Change() if not result: raise RuntimeError( "An error occurred: ImageChangeTransferSyntax.Change() " "returned a failure result" ) # Re-using image as the variable causes crash on Ubuntu # and weirdness on Windows # image = converter.GetOutput() output = converter.GetOutput() elem = output.GetDataElement() seq = elem.GetSequenceOfFragments() fragment = seq.GetFragment(0) value = fragment.GetByteValue() buffer = value.GetBuffer() print("Re-encoding to bytes") as_bytes = buffer.encode("utf-8", "surrogateescape") print("Cleaning bad objects") # Freeing up the objects here causes crash on Windows image = None converter = None print("Returning bytes") # If image and converter aren't freed then crash # here on Windows instead return as_bytes if __name__ == "__main__": # 1.2.840.10008.1.2.1 (Explicit VR Little Endian) ds = dcmread("OBXXXX1A.dcm") pixel_data = ds.PixelData # bytes print("Converting to RLE") convert(pixel_data) print("Conversion complete")
The above works on Ubuntu, however on macOS and Windows it will crash during the "Cleaning bad objects" step.
Also, on Ubuntu I can reliably get a segfault when re-using image as the variable name (at the position indicated by "Re-using image as the variable causes crash"), and on Windows it gives a weird gdcmImage
instance.
Windows will sometimes give "Windows fatal exception: code 0xc0000374" or a Python heap error as well.
Thanks
Dean, the above code is anti-pattern. While I agree, the python wrapping mechanism is clearly brain-dead, you cannot allocate a gdcm.Image directly in python code. You need to have a holder for it (ref mechanism). Use the Input/Ouput of a gdcm.ImageReader/gdcm.ImageWriter. See gdcm/Examples/Python section.
in your code
that should work
OK, thanks, I'll give that a try
Yep, that worked, thanks Mathieu!