C++ DICOM Library (Linux, Windows, macOS, iOS, visionOS, Android): DICOMHERO (original) (raw)
Build with confidence

- Full source code (C++ and Objective-C included, Python & Java auto-generated by SWIG, Swift auto-generated by XCode bridge headers)
- Modern CMake solution
- Extensive documentation
- One year of support & upgrades
- SDK requirements and risk analysis
- Standard Operating Procedures used for the development of the SDK
- Test units with code coverage report
- Binary compatibility between minor releases
Send and receive DICOM messages
Communicate via DICOM messages (DIMSE) over network associations (ACSE).
DICOMHERO SDK can act as SCU, SCP, or both and recognizes all the composite and normalized DIMSE commands.
AssociationSCU scu("SCU", scpName, 1, 1,
presentationContexts, readSCU, writeSCU, 0);
DimseService dimse(scu);
CEchoCommand echoCommand(
"1.2.840.10008.1.1",
dimse.getNextCommandID(),
dimseCommandPriority_t::medium,
"1.1.1.1.1");
dimse.sendCommandOrResponse(echoCommand);
CEchoResponse response =
dimse.getCEchoResponse(echoCommand);DICOM & DICOMDIR files
Read and write DICOM and Jpeg files and have both high-level and raw access to the data.
Lazy loading allows the processing of large DICOM files.
DicomDir newDicomDir;
DicomDirEntry rootRecord =
newDicomDir.getNewEntry("PATIENT");
DataSet dataSet(rootRecord.getEntryDataSet());
dataSet.setUnicodeString(TagId(tagId_t::PatientName_0010_0010), L"Surname");
newDicomDir.setFirstRootEntry(rootRecord);Supports compressed (lossy/lossless) and raw images
Decompress the embedded images or convert them to other color formats or bit depth. Supports raw, RLE, jpeg baseline, and jpeg lossless.
Transform transformToYBR =
colorTransformsFactory::getTransform(
"RGB",
"YBR_FULL");
Image ybrImage =
transformToYBR.allocateOutputImage(
baselineImage,
width,
height);
transformToYBR.runTransform(
baselineImage,
0, 0,
width, height,
ybrImage,
0, 0);DICOMHERO Objects: the whole standard at your fingertips
DICOMHERO Objects brings the DICOM Standard CIODs, NIODs, modules & macros in C++ form.
Check how the DICOMHERO Objects library is used in the worklist example to query a modality worklist server.
// Create the C-FIND payload using the negotiated transfer syntax
DataSet dataSet(negotiatedTransferSyntaxes.front());
modules::PatientIdentification patient(dataSet);
patient.setPatientNameValue(dicomhero::PatientName("*", "",""));
patient.setPatientIDValue(patientID);
modules::ScheduledProcedureStep procedureStep(dataSet);
auto procedureSequenceItem = procedureStep.addScheduledProcedureStepSequenceItem();
// Create empty tags to signal that we want to receive the value back from the server
procedureSequenceItem.getScheduledStationAETitleTagCreate();
procedureSequenceItem.getScheduledProcedureStepStartDateTagCreate();
procedureSequenceItem.getScheduledProcedureStepIDTagCreate();
procedureSequenceItem.getModalityTagCreate();<br>procedureSequenceItem.getScheduledPerformingPhysicianNameTagCreate();
procedureSequenceItem.getScheduledProcedureStepDescriptionTagCreate();
// Build the C-FIND command using the payload we just created
CFindCommand cfind(
dicom2018e::uidModalityWorklistInformationModelFIND,
1,
dimseCommandPriority_t::medium,
dicom2018e::uidModalityWorklistInformationModelFIND,
dataSet);
// Send the C-FIND command
dimse.sendCommandOrResponse(cfind);Works with Python
Install DICOMHERO with pip3, build or parse DICOM Datasets with raw, RLE or Jpeg compressed images, and communicate with other DICOM modalities via ACSE & DIMSE.
from dicomhero6 import dicomhero6<br><br>dataset = dicomhero6.DataSet()
# Create an RGB image (16 bit per channel)
image = dicomhero6.Image(300, 100, dicomhero6.bitDepth_t_depthU16, "RGB", 15)
# Generate test gradients
handler = image.getWritingDataHandler()
write_int_array = array.array('H', [0] * handler.getSize())
for y in range(0, 100):
for x in range(0, 300):
write_int_array[(y * 300 + x) * 3] = y
write_int_array[(y * 300 + x) * 3 + 1] = x
write_int_array[(y * 300 + x) * 3 + 2] = x + 1
memory = handler.getMemory()
memory.assign(write_int_array)
handler = None # Force the handler to write into the image
dataset.setImage(0, image, dicomhero6.imageQuality_t_high)
dicomhero6.CodecFactory.save(dataset, "test.dcm", dicomhero6.codecType_t_dicom)Works with Java
DICOMHERO can be compiled into an AAR library using AndroidStudio and the NDK.
Using the DICOMHERO Bitmap you can generate pixel buffers ready to be displayed on Android devices.
// The CodecFactory will read from the Pipe which is feed by the thread launched
// before. We could just pass a file name to it but this would limit what we
// can read to only local files
DataSet loadDataSet = CodecFactory.load(new StreamReader(dicomheroPipe.getStreamInput()));
// Get the first frame from the dataset (after the proper modality transforms<br>// have been applied).
Image dicomImage = loadDataSet.getImageApplyModalityTransform(0);
// Use a DrawBitmap to build a stream of bytes that can be handled by the
// Android Bitmap class.
TransformsChain chain = new TransformsChain();
if(ColorTransformsFactory.isMonochrome(dicomImage.getColorSpace()))
{
VOILUT voilut = new VOILUT(VOILUT.getOptimalVOI(dicomImage, 0, 0, dicomImage.getWidth(), dicomImage.getHeight()));
chain.addTransform(voilut);
}
DrawBitmap drawBitmap = new DrawBitmap(chain);
Memory memory = drawBitmap.getBitmap(dicomImage, drawBitmapType_t.drawBitmapRGBA, 4);
// Build the Android Bitmap from the raw bytes returned by DrawBitmap.
Bitmap renderBitmap = Bitmap.createBitmap((int)dicomImage.getWidth(), (int)dicomImage.getHeight(), Bitmap.Config.ARGB_8888);
byte[] memoryByte = new byte[(int)memory.size()];
memory.data(memoryByte);
ByteBuffer byteBuffer = ByteBuffer.wrap(memoryByte);
renderBitmap.copyPixelsFromBuffer(byteBuffer);
// Update the image
mImageView.setImageBitmap(renderBitmap);
mImageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
// Update the text with the patient name
mTextView.setText(loadDataSet.getPatientName(new TagId(0x10,0x10), 0, new PersonName("Undefined", "", "")).getAlphabeticRepresentation());Unicode support
DICOMHERO translates Unicode strings to/from multiple DICOM charsets.
structuredReport.addPatientModule()
.setPatientNameUnicodeValue(
UnicodePersonName(L"Test^Patient",
L"",
L""))
.setPatientBirthDateValue(
Date(2020, 1, 1, 10, 0, 0, 0, 0, 0));Source available
DICOMHERO comes with full source code.
Commercial royalty-free licenses and support are available.
Self-contained
DICOMHERO depends only on the default OS libraries.
Multi-platform
DICOMHERO runs on:
- Linux
- Windows
- iOS
- macOS
- visionOS
- Android
Multi-language
Written in C++, wrappers for:
- Python
- Java
- Objective-C
- Swift