How to decode Hologic Breast Tomosynthesis Objects

4880 views
Skip to first unread message

Dave Harvey

unread,
Jan 16, 2014, 1:02:58 PM1/16/14
to
At the breast tomosynthesis forum at the SIIM meeting last June, there was a discussion comparing the very large official BTO objects (~ 500 Meg) with the very much smaller Hologic secondary capture objects (SCOs ~30 Meg), which contain the pixel data in private data elements. As a result, I had a look to see if I could determine the encoding of those objects by comparing them with the decompressed versions (see http://www.dclunie.com/pixelmedimagearchive/upmcdigitalmammotomocollection/index.html for examples).

I rapidly concluded:

1) There are no JPEG markers or other clues to the format
2) There are features of both Huffman and run-length encoding
3) Both the Huffman and run-length encoding show adaptive behaviour
4) The intervals between successive decoded pixel values were mostly multiple of 9 (with a few 8s and 10s, so not all final pixel values were multiple of 9)

This looked too complex to decipher, so I gave up :-(

However, last month I wrote my own JPEG-LS codec, and recognised the above pattern in images compressed using the lossy ("near lossless") mode, with a maximum permitted error (NEAR) of 4 (2 x NEAR + 1 = 9). I therefore revisited the Hologic examples, and it was immediately apparent that they are actually encoded using JPEG-LS, but without any of the expected JPEG markers. It was only a small amount of work to identify the other features required for full pixel data decoding, so I include below a recipe for re-writing such images into a form in which the pixel data for all frames may be accessed by any DICOM application which supports JPEG-LS without needing to expand to fully decompressed form. I have not attempted to re-create all the non-pixel data required to make valid BTO objects - I'll leave that to others!

Basic description of the private data

a) There are 2 versions of the set of frames - they appear to me to be essentially the same images, but with one of them at approximately half the resolution of the other.

b) The data is encoded using JPEG-LS in near-lossless mode, with a maximum error of 4. Due to the way that JPEG-LS works, this value must be correct, as any attempt to use a different value produces "garbage" from the decoder.

Decoding procedure:

1) Make a new SOP instance to hold the pixel data - and copy any attributes you wish to preserve from the original (not including the private data)

2) Decide whether you wish to access the full resolution or lower resolution version of the data, and (from the original SCO), select the appropriate private data sequence - 7E01,1010 for full resolution or 7E01, 1011 for lower resolution

3) Within the chosen sequence, there will be a collection of DICOM datasets, each of which will contain element 7E01,1012 - which is of type OB - these should be concatenated in order into an array of byte values (called hereafter, "data").

4) Locate the following values in the data, and set into appropriate DICOM attributes in the new image:

data[20-21] : Frame Count => 0028,0008
data[24-25] : Columns => 0028,0011
data[28-29] : Rows => 0028,0010
data[32] : Bits Stored => 0028,0101

Set corresponding values in 0028,0100 (16) and 0028,0102 (Bits Stored - 1), as well as 0028,0004 = MONOCHROME2

5) Construct a matching JPEG-LS header, using these and other values:

0xFF, 0xD8, // Start of image (SOI) marker
0xFF, 0xF7, // Start of JPEG-LS frame (SOF55) marker – marker segment follows
0x00, 0x0B, // Length of marker segment = 11 bytes including the length field
0x08, // P = Precision [Set from data[32] ]
0x00, 0x00, // Y = Number of lines [Set from data[28-29] - reversed to make big endian]
0x00, 0x00, // X = Number of columns [Set from data[24-25] - reversed to make big endian]
0x01, // Nf = Number of components in the frame = 1
0x01, // C1 = Component ID = 1 (first and only component)
0x11, // Sub-sampling: H1 = 1, V1 = 1
0x00, // Tq1 = 0 (this field is always 0)
0xFF, 0xDA, // Start of scan (SOS) marker
0x00, 0x08, // Length of marker segment = 8 bytes including the length field
0x01, // Ns = Number of components for this scan = 1
0x01, // Ci = Component ID = 1
0x00, // Tm1 = Mapping table index = 0 (no mapping table)
0x00, // NEAR [Set from data[36] ] -
0x00, // ILV = 0 (interleave mode = non-interleaved)
0x00 // Al = 0, Ah = 0 (no point transform)

6) Locate the index to the frame positions in the encoded data. This starts 1024 bytes before the end of "data" and consists of a series of 4 byte little-endian values, giving the start of each frame relative to the start of data. It includes an extra value at the end to allow the calculation of the length of the last frame.

7) Restruct each frame as JPEG-LS data, by extracting the encoded data from data[index[frame]] to data[index[frame+1]-1], then prepending the JPEG-LS data from step 5, and appending an EOI marker (FF, D9). If the frame length is odd, append an additional 00 byte. Each frame can now be packed as a new fragment into the new SOP instance (remembering to include a basic offset table as the first fragment).

8) Add an 0002 group meta-header, indicating that the transfer syntax is 1.2.840.10008.1.2.4.81 (JPEG-LS in near-lossless mode)

The positions of the important values in data are empirical, but the numbers of frames, width and height are well-established, as they vary between images, and are consistent. The values for precision (10) and NEAR (4), are less certain, as all images I have seen contain the same values, but their positions seem logical, so they are probably correct.

Interestingly, the images generated this way are even smaller than the Hologic originals, as they only contain one of the 2 resolution versions - the high resolution one works out at about 75% of the original size, and the lower one at 25% of the original.

The above recipe has worked for all Hologic SCO objects I have tried it on so far, and gives pixel values identical to the decopmressed versions available on the site from which they were obtained, but being entirely empirical, it is quite possible that there may be subtleties which have escaped me, so if you find any images for which it does not work (or if you need any guidance on how to use the above notes), please do get in touch.

Dave Harvey

David Clunie

unread,
Jan 19, 2014, 11:45:13 AM1/19/14
to
Excellent detective work Dave !

David

Dave Harvey

unread,
Feb 5, 2014, 5:43:27 AM2/5/14
to
After some questions and further examples from other people, I have a few small additions and clarifications to make to my original observations:

1) Even once decoded into standard JPEG-LS, very few "standard" systems will be able to view these images as they stand, as JPEG-LS is implemented in very few viewers and toolkits (we only added it ourselves this week!) The reason is that JPEG-LS is an utterly different compression technique to the other "JPEG" formats (each of which is similarly unrelated to the others!)

2) Whilst my original test images had 2 different resolution versions, it seems that other Hologic SCO objects might only have a single version (in the "high" resolution sequence - 7FE1,1010)

3) A raw projection image that I was sent for checking varied slightly from the above (and from other images from the same source), in that it used JPEG-LS in lossless mode (NEAR = 0). This did have 0 in data[36], validating the supposition that this location is indeed the value of NEAR. The algorithm above still worked, but ideally, when transcoding such images, the transfer syntax should be set as 1.2.840.10008.1.2.4.80 (not .81) to indicate lossless mode.

4) When using the offsets from step 7 of my recipe, it is important to note that the offsets are from the very start of the binary data, NOT from the start of the 2nd block (yes, that's where the frames actually are, but the OFFSET is measured from the beginning, so the offset of the first frame will be the same as the length of the 1st block)

Dave Harvey

Yassin Jdaoudi

unread,
Feb 17, 2014, 8:44:17 AM2/17/14
to
Dear Dave,

Interesting investigation. Thank you for sharing.

However, I have a small doubt concerning the second point in the decoding procedure: "Decide whether you wish to access the full resolution or lower resolution version of the data..."

There is a scalability principle, findable in lossless codecs, so called (resolution) progressive algorithms, the basic (Laplacian) idea is to first encode a lower image resolution and then encode differences to higher resolutions. For example, see
Burt, P.J.; Adelson, E.H., "The Laplacian Pyramid as a Compact Image Code," Communications, IEEE Transactions on , vol.31, no.4, pp.532,540, Apr 1983
-or-
http://www.prip.tuwien.ac.at/twist/docs/irregularLaplacian.pdf

When you choose to access only one version of the dataset, you might loose a part of the information resulting in an object having a lower quality. The latter is readable though.

I might be wrong but is it possible the double version of the dataset is used in that purpose?

Let me know if I misunderstood something.

Thank you.

Regards,
Yassin Jdaoudi.

Dave Harvey

unread,
Feb 17, 2014, 11:22:06 AM2/17/14
to
Yassin,

This idea did occur to me, but I discounted it for 3 reasons:

1) There would be nowhere near enough entropy/information in the low resolution image to make up for the missing data. As the "full" version seems only to be coded to the nearest multiple of 9 for each pixel, then that is just over 3 bits of data "lost" per pixel, so for each group of 4 pixels (corresponding to each low resolution pixel), that would need more than 12 bits per pixel in the low resolution image, and there is nothing like that amount there.

2) If that sort of encoding were being used, then one of the 2 images would only consist of the "differences" between the other image and the uncompressed image, but in fact, both are complete images in their own right. Put another way, the low resolution information is duplicated in each image.

3) The decompressed versions of the high-resolution images are identical to the decompressed versions of the same images provided by Hologic, confirming that no "other" information is used in the decompression of the pixel data.

Thanks for your comments, it is great to see others adding their opinions to this topic, but in this case, I am sure that the low resolution image could not make any meaningful "correction" to the high resolution one.

Dave

shouj...@gmail.com

unread,
Jul 31, 2014, 12:44:18 PM7/31/14
to
Hi Dave,

Thank you very much for sharing the way of decoding JPEG-LS tomo data.
I wonder if you could share with me the way of locating the index to the frame positions in the encoded data of regular breast tomosynthesis (with SOPClassUID of 1.2.840.10008.5.1.4.1.1.13.1.3
I need to randomly load any frame of the tomo data, instead of allocating memory for the decompressed entire volume data and then move the pointer to the frame that is of interest.

Thanks.

Shoujie

On Thursday, January 16, 2014 12:02:58 PM UTC-6, Dave Harvey wrote:
> At the breast tomosynthesis forum at the SIIM meeting last June, there was a discussion comparing the very large official BTO objects (~ 500 Meg) with the very much smaller Hologic secondary capture objects (SCOs ~30 Meg), which contain the pixel data in private data elements. As a result, I had a look to see if I could determine the encoding of those objects by comparing them with the decompressed versions (see http://www.dclunie.com/pixelmedimagearchive/upmcdigitalmammotomocollection/index.html for examples).
>
>
>
> I rapidly concluded:
>
>
>
> 1) There are no JPEG markers or other clues to the format
>
> 2) There are features of both Huffman and run-length encoding
>
> 3) Both the Huffman and run-length encoding show adaptive behaviour
>
> 4) The intervals between successive decoded pixel values were mostly multiple of 9 (with a few 8s and 10s, so not all final pixel values were multiple of 9)
>
>
>
> This looked too complex to decipher, so I gave up :-(
>
>
>
> However, last month I wrote my own JPEG-LS codec, and recognised the above pattern in images compressed using the lossy ("near lossless") mode, with a maximum permitted error (NEAR) of 4 (2 x NEAR + 1 = 9). I therefore revisited the Hologic examples, and it was immediately apparent that they are actually encoded using JPEG-LS, but without any of the expected JPEG markers. It was only a small amount of work to identify the other features required for full pixel data decoding, so I include below a recipe for re-writing such images into a form in which the pixel data for all frames may be accessed by any DICOM application which supports JPEG-LS without needing to expand to fully decompressed form. I have not attempted to re-create all the non-pixel data required to make valid BTO objects - I'll leave that to others!
>
>
>
> Basic description of the private data
>
>
>
> a) There are 2 versions of the set of frames - they appear to me to be essentially the same images, but with one of them at approximately half the resolution of the other.
>
>
>
> b) The data is encoded using JPEG-LS in near-lossless mode, with a maximum error of 4. Due to the way that JPEG-LS works, this value must be correct, as any attempt to use a different value produces "garbage" from the decoder.
>
>
>
> Decoding procedure:
>
>
>
> 1) Make a new SOP instance to hold the pixel data - and copy any attributes you wish to preserve from the original (not including the private data)
>
>
>
> 2) Decide whether you wish to access the full resolution or lower resolution version of the data, and (from the original SCO), select the appropriate private data sequence - 7E01,1010 for full resolution or 7E01, 1011 for lower resolution
>
>
>
> 3) Within the chosen sequence, there will be a collection of DICOM datasets, each of which will contain element 7E01,1012 - which is of type OB - these should be concatenated in order into an array of byte values (called hereafter, "data").
>
>
>
> 4) Locate the following values in the data, and set into appropriate DICOM attributes in the new image:
>
>
>
> data[20-21] : Frame Count => 0028,0008
>
> data[24-25] : Columns => 0028,0011
>
> data[28-29] : Rows => 0028,0010
>
> data[32] : Bits Stored => 0028,0101
>
>
>
> Set corresponding values in 0028,0100 (16) and 0028,0102 (Bits Stored - 1), as well as 0028,0004 = MONOCHROME2
>
>
>
> 5) Construct a matching JPEG-LS header, using these and other values:
>
>
>
> 0xFF, 0xD8, // Start of image (SOI) marker
>
> 0xFF, 0xF7, // Start of JPEG-LS frame (SOF55) marker - marker segment follows

rosset...@bluewin.ch

unread,
Aug 24, 2014, 4:05:47 PM8/24/14
to
Thanks for these informations !

I also found, that starting at data[40], you have a repetitive structure of 24 bytes (one for each frame). This structure contains:

- pixel spacing (square pixel) (0028,0030) at the first 4 bytes of the structure, encoded as little-endian 32 bit float
- slice location (0020,1041) at position 9 to 12 of the structure, encoded as little-endian 32 bit float

shouj...@gmail.com

unread,
Oct 10, 2014, 2:47:20 PM10/10/14
to
Never mind, I got this problem resolved.
If anyone is having the similar problem, I could offer help :)

Shoujie

abedalma...@gmail.com

unread,
Nov 19, 2014, 5:17:42 PM11/19/14
to
hello i have a small imaging clinic and in need of a pacs server software i have less then 5 modalities and i need ur help iv been using conquest dicom server everything was fine until we go the new hologic memo machine which sends bto files(breast tomosynthesis object) the software doesn't understand this kind of file so it rejects it any help from you would be great and yes im willing to pay so thxs in advanced have a nice day

David Clunie

unread,
Nov 20, 2014, 9:20:41 AM11/20/14
to
Hi

If it is simply a matter of adding the Breast Tomosynthesis Image Storage
SOP Class ("1.2.840.10008.5.1.4.1.1.13.1.3") to the list of Storage SOP
Classes that Conquest will store and regurgitate, then someone from the
Conquest forum should be able to explain how to do that. See:

http://forum.image-systems.biz/viewforum.php?f=33

I believe the file is "dgatesop.lst".

David

knya...@gmail.com

unread,
Nov 25, 2015, 3:13:20 AM11/25/15
to
Great job! Thank you very much, Dave!
Message has been deleted

feldma...@yahoo.com

unread,
Apr 22, 2016, 5:11:25 PM4/22/16
to
hello,

i read your dicom post and i am trying to convert hologic tomo sco to bto. i can get imagery but i want to also find (0020,0032) image position (patient) that is found in (0018,9504) x-ray 3d frame type sequence. do you know how to find this or do you have a mapping of the hologic tomo sco structure that you can share? have you written a converter that you can share?

thank you for your time,

joel

raj.s...@gmail.com

unread,
Jun 28, 2016, 10:41:49 PM6/28/16
to
Dear All

Has anyone made their converter code (hologic -> DICOM) open source for others to use and contribute or build other analysis on top of it. If so, please do let us know.

thanks

short...@gmail.com

unread,
Apr 13, 2017, 1:49:48 PM4/13/17
to
On Tuesday, June 28, 2016 at 10:41:49 PM UTC-4, raj.s...@gmail.com wrote:
> Dear All
>
> Has anyone made their converter code (hologic -> DICOM) open source for others to use and contribute or build other analysis on top of it. If so, please do let us know.

This is an interesting question. We're moving away from Hologic for Dx, and will be storing new studies as BTOs to be read on our new PACS (Sectra). It would be useful if, instead of converting all SCO priors in situ to BTO, we could convert them on the fly when we prefetch the night before. What are the chances anyone is using this converter for production purposes?

Dan

nicek...@gmail.com

unread,
Dec 13, 2017, 10:24:49 AM12/13/17
to
How can I contact you?

nicek...@gmail.com

unread,
Dec 13, 2017, 10:30:47 AM12/13/17
to
On Thursday, January 16, 2014 at 12:02:58 PM UTC-6, Dave Harvey wrote:
How can I contact you? I want more details

Pantelis Georgiadis

unread,
Apr 19, 2022, 11:44:03 AMApr 19
to
DicomScoToBto is an open-source utility to decode Hologic Breast Tomosynthesis Objects, that was created based on Dave Harvey's investigation results!
https://github.com/PantelisGeorgiadis/DicomScoToBto
Reply all
Reply to author
Forward
0 new messages