Creating uncompressed image from JPEG 2000 stream

Questions regarding the DCMJP2K library, a DCMTK add-on that implements support for JPEG 2000 compression (lossy and lossless) in DCMTK

Moderator: Moderator Team

Post Reply
Message
Author
jdinca
Posts: 13
Joined: Thu, 2012-10-25, 07:18

Creating uncompressed image from JPEG 2000 stream

#1 Post by jdinca »

I have a JPEG 2000 byte stream, which, if I dump to disk with a 'jp2' extension, reads as a JPEG image. I'd like though to create an uncompressed (EXS_LittleEndianExplicit) DICOM file. So far, I can only create a compressed Dicom file, which reads in fine in Matlab, but gives the following error using dcmdjp2k (I have purchased the JPEG codecs):
I: reading input file test2.dcm
D: DcmItem::checkTransferSyntax() TransferSyntax="Little Endian Explicit"
I: decompressing file
cannot get marker segment
F: JPEG 2000 codec error: decompressing file: test2.dcm

Note that the transfer syntax of "Little Endian Explicit" might be a clue as to why dcmdjp2k cannot read the image, but Matlab can. I'm hoping in the forum to get some clues as to what might be wrong. Here are my steps (where tmpBuffer is the JPEG 2000 byte stream). Note, that the general method is taken from insertEncapsulatedPixelData.

1) Register codecs:
D2DecoderRegistration::registerCodecs(opt_uidcreation, opt_planarconfig);
and check dictionary is loaded.

2) Create DcmFileFormat
DcmFileFormat fileformat;
DcmDataset *pDataset = fileformat.getDataset();
// TODO: Prepare JPEG codec parameters (DJ_RPLossless or DJ_RPLossy) and call DcmDataset's chooseRepresentation method, just as in dcmcjpeg.
// DcmFileFormat dcmff(pDataset);
pDataset->chooseRepresentation( outputTS, NULL );

3) Create pixel sequence, add table offset, then store compressed data in the sequence (should DcmOffsetList dummyList; be more appropriately set?):
cond = pixelSequence->storeCompressedFrame(dummyList, tmpBuffer, numTmpBytes, 0);

4) insert pixel data attribute incorporating pixel sequence into dataset

5) Tell pixel data element that this is the original presentation of the pixel data and how it compressed:
pixelData->putOriginalRepresentation(EXS_JPEG2000, NULL, pixelSequence);
cond = pDataset->insert(pixelData);

6) Set all relevant tags, columns, rows, bits, samples, photometric interp etc.

7) Decompress (this fails):
cond = pDataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL);

8) Debug, dump dicom that is readable by Matlab:
fileformat.saveFile("test2.dcm", JPEG2000);

Any help or suggestions would be appreciated! Thank you.

Marco Eichelberg
OFFIS DICOM Team
OFFIS DICOM Team
Posts: 1435
Joined: Tue, 2004-11-02, 17:22
Location: Oldenburg, Germany
Contact:

Re: Creating uncompressed image from JPEG 2000 stream

#2 Post by Marco Eichelberg »

Thanks for sending us the sample file, and code. There are two problems with the compressed image file. This first one is quite simple: The offset table, i.e. the (normally empty) first item containing the jump offsets into the compressed image are missing. If I dump your file, the output looks like this

Code: Select all

(7fe0,0010) OB (PixelSequence #=1)                      # u/l, 1 PixelData
 (fffe,e000) pi 00\00\00\0c\6a\50\20\20\0d\0a\87\0a\00\00\00\14\66\74\79\70\6a\70... # 45422, 1 Item
(fffe,e0dd) na (SequenceDelimitationItem)               #   0, 0 SequenceDelimitationItem
while it should correctly look like this.

Code: Select all

(7fe0,0010) OB (PixelSequence #=2)                      # u/l, 1 PixelData
  (fffe,e000) pi (no value available)                     #   0, 1 Item
  (fffe,e000) pi 00\00\00\0c\6a\50\20\20\0d\0a\87\0a\00\00\00\14\66\74\79\70\6a\70... # 45422, 1 Item
(fffe,e0dd) na (SequenceDelimitationItem)               #   0, 0 SequenceDelimitationItem
Your source code contains some lines that should have created the offset table, but it obviously isn't there.

This article in the forum describes the second problem: in DICOM only the JPEG 2000 codestream, and not the full JP2 file must be embedded in the pixel sequence. A JPEG 2000 code stream always starts with the byte sequence FF 4F, and you can see that this is not the case with your byte stream, where this marker is at byte offset 0x55. So there is a JP2 header in front of that marker, which is not permitted in DICOM. Our 3.6.1 snapshot version of DCMJP2K has code that will skip such a header by looking for the FF 4F marker, and just print a warning, but earlier versions will report an error.

jdinca
Posts: 13
Joined: Thu, 2012-10-25, 07:18

Re: Creating uncompressed image from JPEG 2000 stream

#3 Post by jdinca »

Thank you for this solution. I now ensure the data I use begins at the JPEG 2000 codestream by searching for:

Code: Select all

const std::string jp2k_data("FF4F");
(And ends at FFD9.) I then insert the offset table to the pixel sequence:

Code: Select all

DcmPixelItem *offsetTable	= new DcmPixelItem(DcmTag(DCM_Item, EVR_OB));
if (offsetTable != NULL)
	cond	= pixelSequence->insert(offsetTable); // etc
And store the compressed frame. Choose representation allows me to decompress, and I access the uncompressed data with findAndGetUint8Array. Thank you for the help.

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest