3
votes

I'm struggling with the DCMTK 3.6.1 library and now I'm blocked in a common situation: accessing compress data pixel of a DICOM image.

As the authors of the library suggest here http://support.dcmtk.org/redmine/projects/dcmtk/wiki/Howto_AccessingCompressedData, this is the correct way to get the compress data.

This code work, but they start from a file to create the dataset. In my code I have my dataset filled in this way

status = data->putAndInsertUint8Array(DCM_PixelData, pSource, sizeBuffer);

where pSource contains my UNcompressed pixel data. After this I add the Image DICOM tags (Group 28) and make the compression with

status = data->chooseRepresentation(EXS_JPEGProcess14SV1, &param);

and starting from this dataset I want to acces to compressed data

status = data->findAndGetElement(DCM_PixelData, element);
    DcmPixelData *dpix = NULL;
    dpix = OFstatic_cast(DcmPixelData*, element);
    /* Since we have compressed data, we must utilize DcmPixelSequence
    in order to access it in raw format, e. g. for decompressing it
    with an external library.
    */
    DcmPixelSequence *dseq = NULL;
    E_TransferSyntax xferSyntax = EXS_Unknown;
    const DcmRepresentationParameter *rep = NULL;
    // Find the key that is needed to access the right representation of the data within DCMTK
    dpix->getOriginalRepresentationKey(xferSyntax, rep);

    // Access original data representation and get result within pixel sequence
    status = dpix->getEncapsulatedRepresentation(xferSyntax, rep, dseq);
    Uint32 length;
    if (status.good())
    {
        DcmPixelItem* pixitem = NULL;
        // Access first frame (skipping offset table)
        dseq->getItem(pixitem, 1);
        if (pixitem == NULL)
            return 1;
        Uint8* pixData = NULL;
        // Get the length of this pixel item (i.e. fragment, i.e. most of the time, the lenght of the frame)
        length = pixitem->getLength();
        if (length == 0)
            return 1;
        // Finally, get the compressed data for this pixel item
        status = pixitem->getUint8Array(pixData);
        // Metto i Pixel Data compressi su pSorgCompr
        pSorgCompr = (LPBYTE)pixData;
    }
    ////////////////////////////

    DJEncoderRegistration::cleanup();
    DJDecoderRegistration::cleanup();

but the row status = dpix->getEncapsulatedRepresentation(xferSyntax, rep, dseq); retun a FAIL with error "Pixel Representation not found" and I don't understand why.

The strage thing is that if before accesing the compressed data, I save the compressed file with fileformat.saveFile("compressedPixelData.dcm", EXS_JPEGProcess14SV1); and next I load the file with result = fileformat.loadFile("compressedPixelData.dcm");, all works perfectly

It's like the loadfile function solve the problem, I do not know how, maybe filling some tags?

The tags that I fill before calling the chooseRepresentation function are:

  • DCM_Rows
  • DCM_Columns
  • DCM_BitsStored
  • DCM_SamplesPerPixel
  • DCM_PlanarConfiguration
  • DCM_HighBit
  • DCM_BitsAllocated
  • DCM_PixelRepresentation
  • DCM_RescaleIntercept
  • DCM_RescaleSlope
  • DCM_PhotometricInterpretation
  • DCM_PixelAspectRatio
  • DCM_ImagerPixelSpacing
  • DCM_PixelSpacing
2

2 Answers

1
votes

In DICOM, the compressed frame(s) are stored differently from the uncompressed (Native) frame(s) under the Pixel data Element (7FE0, 0010). Here is the basic concept of compressed image encoding in DICOM.

The encapsulated pixel stream (compressed image data) is segmented into one or more Fragments (Items) under Pixel Data Element (7FE0, 0010) of the top-level Data Set. In encapsulated encoding, Pixel Data Element is a sequence and it holds two or more Item Elements (Fragments), each Fragment (Item Element) have its own explicit length. Also, encapsulated Format supports both Single-Frame and Multi-Frame image encoding. A frame may be entirely contained within a single fragment (Item), or may span multiple fragments. The sequence of Fragments of the encapsulated pixel stream is terminated by a delimiter.
The first Item (FFFE, E000) in the Sequence of Items before the encoded Pixel Data Stream is normally empty or may contain a Basic Offset Table item which holds the byte offsets to the first byte of the Item Tag of the first fragment for each frame in the Sequence of Items.

So, when you want to extract the compressed pixel stream from DICOM Data Set, you need to skip the first Item element under the Pixel Data sequence. I hope this helps in understanding the documentation you referenced. Please, refer to DICOM standard PS 3.5 Annex A for more information.

0
votes

Well, maybe I have solved the problem. I have added the istructions

dataset->removeAllButCurrentRepresentations(); 

before accessing to compressed pixel data.

I can also do PixelData->removeAllButCurrentRepresentations(); instead of the instruction before and works in the same way....

But I really don't understand why it work.... can you please try to explain? Thanks