DICOM 压缩格式读取

Howto: Accessing Compressed Data

If compressed DICOM images are loaded, DCMTK most of the time does the job of decompressing the image data itself, e.g. when the user feeds it into the DicomImage class for visualization or directly calls chooseRepresentation() to change the transfer syntax. However, sometimes it may be useful to access the original, compressed pixel data of a single- or multi-frame image. This may be the case if the compressed data should be decompressed by an external library (e.g. because DCMTK does not support this kind of compression codec like for MPEG2) or if the data should be decompressed at all since it should be inserted directly into to another file.

For uncompressed pixel data usually this is done very easily by just finding the Pixel Data element in the DICOM dataset by calling DcmItem's findAndGetElement() routine and then call getUint8Array() (for example) on the resulting element to access the uncompressed raw pixel data vaules. For compressed data, however, there are some intermediate steps necessary in order to parse the underlying DICOM structures.

The reason is that for compressed data, there is a pseudo-sequence embedded into the Pixel Data element that has to be parsed before actually accessing the compressed data (and individual frames if applicable). The first pseudo-item in that sequence is always the offset table indicating at which byte position each frame actually starts within the following raw data of the Pixel Data element. However, you cannot rely on that table since it may be empty (always empty for MPEG2, for example). Within the next items so-called fragments stored. Usually, one fragment refers to exactly one frame of the image, but that is not a requirement at all. For the rest of the example, at least, this is assumed since this covers 90% of all cases.

In order to access the pixel sequence and the items it is containing, you have to deal with the Pixel Sequence within the Pixel Data element, and that is done using the DcmPixelSequence class in DCMTK. Here is a full (compiling) example how to accomplish that:

#include "dcmtk/config/osconfig.h"    /* make sure OS specific configuration is included first */
#include "dcmtk/dcmdata/dctk.h" 
#include "dcmtk/dcmdata/dcpxitem.h" 

int main(int argc, char *argv[])
{
  OFCondition result = EC_Normal;
  /* Load file and get pixel data element */
  DcmFileFormat dfile;
  result = dfile.loadFile("example.dcm");
  if (result.bad())
    return 1;
  DcmDataset *data = dfile.getDataset();
  if (data == NULL)
    return 1;
  DcmElement* element = NULL;
  result = data->findAndGetElement(DCM_PixelData, element);
  if (result.bad() || element == NULL)
    return 1;
  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
  result = dpix->getEncapsulatedRepresentation(xferSyntax, rep, dseq);
  if ( result == EC_Normal )
  {
    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)
    Uint32 length = pixitem->getLength();
    if (length == 0)
      return 1;
    // Finally, get the compressed data for this pixel item
    result = pixitem->getUint8Array(pixData);
    // Do something useful with pixData...
  }
  if (result.bad())
    return 1;
  else
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值