Construyendo una aplicación DICOM sencilla con C++ y DCMTK, en Visual Studio 2019

Brandon Lara
5 min readJul 29, 2021

--

Photo by National Cancer Institute on Unsplash

Esta guía da por sentado que ya se ha configurado el entorno de desarrollo, por lo tanto, antes de seguir es necesario configurarlo siguiendo esta otra guía Configurar DCMTK con CMake, para el desarrollo en C++ y Visual Studio 2019

Sin esta configuración, no se puede realizar nada de lo que se explica a continuación. Además, en esta guía voy a utilizar el proyecto TestDCMTK creado en la guía de configuración.

El objetivo de esta guía es construir una pequeña aplicación de ejemplo que servirá como introducción a la programación mediante la librería DCMTK. Este ejemplo consistirá en una aplicación de consola, que al ejecutarla creará un archivo DICOM con ciertos datos y una imagen de prueba. La información necesaria para llevar a cabo esta aplicación se puede encontrar en la documentación de DCMTK y en el código del comando img2dcm.

Al final de esta guía se encuentra todo el código de la aplicación que se va a construir.

En Visual Studio los proyectos de tipo “Console App” se crean con un archivo .cpp donde se escribe el código que se va a ejecutar. Por lo tanto el proyecto TestDCMTK creado anteriormente como una “Console App”, tiene un archivo TestDCMTK.cpp donde se programara la aplicación utilizando la librería DCMTK.

Para las funcionalidades que se han especificado anteriormente es necesario incluir lo siguiente:

#include <iostream>
#include "dcmtk/config/osconfig.h"
#include "dcmtk/dcmdata/dcfilefo.h"
#include "dcmtk/dcmdata/libi2d/i2d.h"
#include "dcmtk/dcmdata/libi2d/i2djpgs.h"
#include "dcmtk/dcmdata/libi2d/i2dplsc.h"
#include "dcmtk/dcmdata/dctk.h"
using namespace std;

DCMTK tiene muchas funcionalidades que se especifican en la documentación. Sin embargo, para poder utilizarlas, se tienen que incluir/importar tal y como se ha hecho anteriormente para hacer uso de las clases y funcionalidades para la gestión de las estructuras de datos DICOM, y para la conversión de imagen a DICOM.

Después de esto, dentro de la función vamos a crear e inicializar las variables que se van a utilizar:

char uid[100];
I2DImgSource* inputPlug = new I2DJpegSource();
I2DOutputPlug* outPlug = new I2DOutputPlugSC();
Image2Dcm i2d;
E_TransferSyntax writeXfer;
DcmDataset* resultDset = NULL;

Se les puede poner cualquier nombre, siempre y cuando se utilicen adecuadamente.

  • uid servirá para generar un uid para la instancia SOP.
  • inputPlug es de tipo I2DJpegSource, que se trata de una implementación I2DImgSource para analizar imágenes JPEG y convertirlas en ficheros DICOM.
  • outPlug es de tipo I2DOutputPlugSC, el cual implementa la conversión de imagen a fichero DICOM.
  • i2d es una variable de tipo Image2Dcm, en el cual se implementan las utilidades para convertir de imagen a fichero DICOM.
  • writeXfer es una variable de tipo E_TransferSyntax, el cual consiste en un enumerador de todas las sintaxis de transferencia DICOM conocidas por el conjunto de herramientas.
  • resultDset es una variable de tipo DcmDataset, que se trata de una clase que maneja el formato de conjunto de datos DICOM.

Una vez realizado esto vamos a establecer la imagen de entrada que se va a leer mediante inputPlug y después se realiza la conversión de imagen a DICOM mediante la función convert de i2d, a la cual por los parámetros de entrada se le pasa lo siguiente:

  • inputPlug con la imagen a convertir.
  • outPlug para realizar la conversión.

Mientras que por los parámetros de salida se le pasa lo siguiente:

  • resultDset para almacenar el objeto DICOM resultante.
  • writeXfer para guardar la sintaxis de transferencia.

Entonces, para este ejemplo el código resultante seria:

inputPlug->setImageFile("test.jpg");
i2d.convert(inputPlug, outPlug, resultDset, writeXfer);

Después de esto, el objeto resultDset consistiría en un objeto DICOM sin pero con una imagen. Este objeto de tipo DcmDataset proporciona ciertas funciones para establecer los datos del mismo. Haciendo uso de estas mismas funciones, se va a establecer con datos de prueba, el nombre del paciente, el identificador de la clase SOP, y el identificador de la instancia SOP:

resultDset->putAndInsertString(DCM_PatientName, "Brandon Lara");
resultDset->putAndInsertString(DCM_SOPClassUID, UID_SecondaryCaptureImageStorage);
resultDset->putAndInsertString(DCM_SOPInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT));

En el primer parámetro se especifica que dato se va a editar, se puede especificar directamente o utilizar los tags de DCMTK. En mi opinión creo que es mas legible utilizar los tags.

En el segundo parámetro se introduce el nuevo valor que va a tener el dato que se pasa por el primer parámetro.

Por ultimo, se va a guardar resultDset como un archivo DICOM (.dcm) en la carpeta del proyecto. Para ello es necesario crear un DcmFileFormat con este resultDset para poder guardarlo usando la función save de DcmFileFormat.

De esta manera, el código quedaría así:

DcmFileFormat dcmff(resultDset);
dcmff.saveFile("test.dcm", writeXfer, EET_ExplicitLength, EGL_recalcGL, EPD_noChange, OFstatic_cast(Uint32, 0), OFstatic_cast(Uint32, 0), EWM_fileformat);

Como se puede ver en el primer parámetro, los datos se guardan en el archivo “test.dcm”, mientras que en el resto de parámetros se han establecido de la misma manera que se ha hecho en el código del comando img2dcm

Antes de ejecutar todo este código, en la carpeta del proyecto que contiene el archivo .cpp, hay que poner la imagen de prueba que se va a convertir en archivo DICOM(En mi caso test.jpg):

Después ejecutamos el proyecto TestDCMTK mediante Visual Studio:

Si todo ha ido bien, debería haber creado el archivo test.dcm carpeta del proyecto que contiene el archivo .cpp y donde se ha puesto la imagen de prueba.

Los datos de este archivo se pueden mostrar con las utilidades de consola de DCMTK, programando código en C++ mediante las librerías DCMTK , o utilizando un DICOM Viewer.

  • Usando MicroDicom se puede ver que todo se ha establecido correctamente:
  • Usando las librerías DCMTK podemos escribir el siguiente código para mostrar el nombre del paciente en la consola:

En mi caso, el resultado de ejecutar este código es:

Como dije al principio de esta guía, aquí os dejo todo el código de la aplicación que se ha construido para esta guía:

Espero que esta guía haya servido para facilitar la introducción a la programación mediante esta librería, cualquier duda o sugerencia me la podéis comentar sin problemas, intentare responder siempre :)

--

--