We have developed an application which compresses RGB data with JPEG
baseline, and store it back in a DICOM file. Until now, we have left the
Photometric Interpretation (0028, 0004) alone, "RGB".
Recently we have encountered a Fujitsu system (Dr. Able) that will not
display our images. They (Fujitsu) claim that the Photometric Interpretation
must be "YBR_FULL_422".
I searched a little in this news group with
http://groups.google.com/advanced_group_search
And it does indeed seem that *most* color JPEG images set the Photometric
Interpretation to "YBR_FLL_422", although the standard does not seem to
specify clearly one or the other.
To me, it seems that "RGB" makes more sense, because the JPEG compression
routine does the conversion from RGB to YUV (or YCbCr?). When the file is
decompressed on the other side, you end up with a buffer of RGB data to
display, *not* YUV. Why should we be concerned with the color space used
internally in JPEG? JPEG may convert RGB to ABC or XYZ. As long as it
converts back to RGB on the decompress side, who cares?
Of course we will probably just add switch in our software, allowing us to
set Photometric Interpretation to "YBR_FLL_422", but isn't this a hack?
Thanks!
--
Ken Sutherland
k...@j-mac.co.jp
http://www.j-mac.co.jp/
>
>To me, it seems that "RGB" makes more sense, because the JPEG compression
>routine does the conversion from RGB to YUV (or YCbCr?). When the file is
>decompressed on the other side, you end up with a buffer of RGB data to
>display, *not* YUV. Why should we be concerned with the color space used
>internally in JPEG? JPEG may convert RGB to ABC or XYZ. As long as it
>converts back to RGB on the decompress side, who cares?
The JPEG standard does not care at all about color spaces, it just
compresses image data with a certain number of channels. The JPEG stream
does not even contain information that identifies the types of color
components. It is your particular implementation of a JPEG library that
implicitly converts between RGB and YCbCr, but this is completely outside
the scope of JPEG. DICOM requires that the field "photometric
interpretation" must be consistent to whatever you find in the image pixel
data. If your compressed JPEG stream contains YCbCr data (as one would
expect), you MUST set the corresponding photometric interpretation in the
DICOM header, i.e. "YBR_FULL" or "YBR_FULL_422", depending on whether or not
the color components are subsampled. Note that there is no YBR_FULL_411 in
DICOM, i.e. you cannot do 4:1:1 subsampling in a conformant manner.
Regards,
Marco Eichelberg
OFFIS
Hi Ken,
If I might add some very practical consideration, the misunderstanding arises
from the fact that many books and texts on JPEG consider the color space
conversion
as part of the JPEG algorithm, and so do many commercial libraries.
Actually, converting RGB to YBR is just a convenient way to improve the
compression
performances (and therefore usual behaviour), but it is not part of the JPEG
process.
So it seems that you are making some wrong assumptions:
1) RGB is always converted to YBR before compressing -> wrong, you are not
forced to do so
2) the JPEG on the other side decompresses the data and then automatically
converts from YBR to RGB -> wrong,
theoretically you can implement JPEG but not perform any conversion from YBR
to RGB.
So if you write RGB in your Photometric Interpretation and transfer syntax is
JPEG, the other side
understands that you compressed JPEG without converting to YBR, and will
decompress without converting.
If you write YBR_FULL_422, the other side understands that you converted to YBR
and then compressed JPEG
and can correctly decompress and then apply the conversion YBR->RGB (if
desired).
So you see that setting Photometric Interpretation to the correct value is
important!
I hope this is correct, since I matured all this after many headaches ...
Andrea
--
Posted from [212.141.134.77]
via Mailgate.ORG Server - http://www.Mailgate.ORG
This is a very difficult and confusing area of the standard that has
received a lot of attention over the last few years.
Ken Sutherland wrote:
> We have developed an application which compresses RGB data with JPEG
> baseline, and store it back in a DICOM file. Until now, we have left the
> Photometric Interpretation (0028, 0004) alone, "RGB".
Unless you are actually sending compressed R, G and B components without
doing any color space transformation (very unusual), this is wrong.
> Recently we have encountered a Fujitsu system (Dr. Able) that will not
> display our images. They (Fujitsu) claim that the Photometric Interpretation
> must be "YBR_FULL_422".
If the "common" YCbCr color transformation with a down-sampling by 2
in the chrominance channels for each row is being performed, they
are correct.
> And it does indeed seem that *most* color JPEG images set the Photometric
> Interpretation to "YBR_FULL_422", although the standard does not seem to
> specify clearly one or the other.
The rules are specified in PS 3.5 and are somewhat generic in order
to accommodate all possibilities, and have been tweaked overtime with a
CP to try to make this clearer, especially since few people realize
that the JPEG bitstream itself specifies nothing about the "interpretation"
of the components (they could be infra-red and ultra-violet for all the
JPEG bitstream itself cares).
See also:
ftp://medical.nema.org/medical/dicom/final/cp156_ft.pdf
As well as:
PS 3.5 Section 8.2.1:
"The use of the DICOM Encapsulated Format to support JPEG Compressed
Pixel Data requires that the Data Elements which are related to the Pixel
Data encoding (e.g. Photometric Interpretation, Samples per
Pixel, Planar Configuration, Bits Allocated, Bits Stored, High Bit,
Pixel Representation, Rows, Columns, etc.) shall contain values which
are consistent with the characteristics of the compressed data stream .
The Pixel Data characteristics included in the JPEG Interchange Format
shall be used to decode the compressed data stream."
and
PS 3.5 Section 8.2.1 Note 2:
"Those characteristics not explicitly specified in the compressed
data stream (e.g. color space which is not specified in the JPEG Interchange
Format), or implied by the definition of the compression scheme
(e.g. always unsigned in JPEG), can therefore be determined from
the DICOM Data Element in the enclosing data set. For example a Photometric
Interpretation of "YBR FULL 422" would describe the color space that is
commonly used to lossy compress images using JPEG. It is unusual to use an RGB
color space for lossy compression, since no advantage is taken of correlation
between the red, green and blue components (e.g. of luminance), and poor
compression is achieved."
> To me, it seems that "RGB" makes more sense, because the JPEG compression
> routine does the conversion from RGB to YUV (or YCbCr?). When the file is
> decompressed on the other side, you end up with a buffer of RGB data to
> display, *not* YUV. Why should we be concerned with the color space used
> internally in JPEG? JPEG may convert RGB to ABC or XYZ. As long as it
> converts back to RGB on the decompress side, who cares?
As described above, the color space transformation is not a part of JPEG,
though it is very commonly implemented in software and hardware codecs.
Regardless, the only place the color space in use is signaled is in the
DICOM Photometric Interpretation field, therefore any "correct" DICOM
implementation will display your images incorrectly.
> Of course we will probably just add switch in our software, allowing us to
> set Photometric Interpretation to "YBR_FLL_422", but isn't this a hack?
No, it is the correct thing to do. All your "old" images are going to
be wrong however, and everyone else will need to put in a hack to
know that your "RGB" is not really RGB at all ... are there other
values in other attributes that you send that can be used to identify
your images (e.g. a manufacturer or software version field or a
particular private tag) ?
david
--
David A. Clunie mailto:dcl...@radpharm.com
Director, Technical Operations http://www.radpharm.com/
RadPharm Work 609-924-1067 Fax 609-924-2094
335 Wall Street Home 570-897-7123 Fax 425-930-0171
Princeton NJ 08540 http://www.dclunie.com/
Apparently what is happening is that our JPEG library is converting from RGB
to YCrCb, down-sampling, then compressing. Fujitsu is receiving this image,
decompress it, but their JPEG library does not automatically up-sample and
convert from YCrCb to RGB. It just gives them a buffer with down-sampled
YCrCb. Yuck!
I suppose that when you realize that the RGB <--> YCrCb conversion is NOT
part of the JPEG standard, then everything makes sense.
David wrote:
> > Of course we will probably just add switch in our software, allowing us
to
> > set Photometric Interpretation to "YBR_FLL_422", but isn't this a hack?
>
> No, it is the correct thing to do. All your "old" images are going to
> be wrong however, and everyone else will need to put in a hack to
> know that your "RGB" is not really RGB at all ... are there other
> values in other attributes that you send that can be used to identify
> your images (e.g. a manufacturer or software version field or a
> particular private tag) ?
There are quite a lot of DICOM images out there in the world that have the
Photometric tag mistakenly set incorrectly to "RGB". Not only ours. So
basically, we have taken the attitude, "If it ain't broke, don't fix it".
We will add a switch to our software to allow us to set the Photometric
Interpretation to "YBR_FLL_422". This should allow us to send our images to
Fujitsu OK. But we won't go back and change the (millions?) of files we have
already created unless we receive a specific request to do so.
We do not, to my knowledge, add any manufacturer or software version or
private tags.
Thanks guys! These news groups a great!
Ken Sutherland wrote:
> There are quite a lot of DICOM images out there in the world that have the
> Photometric tag mistakenly set incorrectly to "RGB". Not only ours. So
> basically, we have taken the attitude, "If it ain't broke, don't fix it".
>
> We will add a switch to our software to allow us to set the Photometric
> Interpretation to "YBR_FLL_422". This should allow us to send our images to
> Fujitsu OK. But we won't go back and change the (millions?) of files we have
> already created unless we receive a specific request to do so.
>
> We do not, to my knowledge, add any manufacturer or software version or
> private tags.
Regardless of the existing files, I still think that you should make the
default for the revised software YBR_FULL_422 since that is correct, and
make the ability to send RGB a switch, but its use deprecated, since its
use is incorrect and non-conformant. You should also document the problem
in the conformance statement and installation manual.
Also, you are certainly not the only implementor to have made this mistake.
To distinguish the images you created before from those you will create in
the future, perhaps you could add something in Derivation Description. It
is always very difficult for receivers and viewers of images to find some
sort of signal that the behavior of the sending software has changed unless
there is such a flag sent.
Yes, sorry. That's exactly what we are going to do. The default will be to
change the the tag to "YBR_FULL_422", but the swtich can be used to set it
to "RGB" or whatever.
>You should also document the problem
> in the conformance statement and installation manual.
Yes, I always forget about those dang conformance statements! 8^)
> Also, you are certainly not the only implementor to have made this
mistake.
In fact, the viewer that I tested with would only display JPEG files with
"RGB". It wouldn't display anything when the tag was "YBR_FULL_422"
> To distinguish the images you created before from those you will create in
> the future, perhaps you could add something in Derivation Description. It
> is always very difficult for receivers and viewers of images to find some
> sort of signal that the behavior of the sending software has changed
unless
> there is such a flag sent.
That's a good idea. I'll look into it.
Thanks!
Sorry to beat a dead horse like this, but I've gone over my source and have
tried to sum up the steps I take to modify the DICOM tags in order to write
out a new file with JPEG compressed image data.
-----------------
1. Free the original data (0x7fe0, 0x0010), and give it undefined (-1)
length
and VR = "OB"
2. Add the first item tag (0xfffe, 0xe000) with 0 length (empty) .
3. Add the second item tag (0xfffe, 0xe000), with the JPEG data!
4. Add the item delimitator tag (0xfffe, 0xe0dd) with length 0.
5. If the original file specified a Transfer Syntax (0x0002, 0x0010),
in the meta-header, change it to Lossy JPEG.
UID "1.2.840.10008.1.2.4.50" = JPEG Process 1 (8 Bit Gray or RGB Color)
UID "1.2.840.10008.1.2.4.51" = JPEG Process 1 (12 Bit Gray)
Don't don anything if the file has no meta-header.
6. Add a "Image Type" tag (0x0008, 0x0008) with the value
"DERIVED\\SECONDARY".
If the tag exists, change it.
NOTE: If the tag exists, should we append to it?
7. If there is no "SOP Class UID" (0x0008, 0x0016) tag, add one based on
the modality
"CT" "1.2.840.10008.5.1.4.1.1.2" CTImageStorage
"MR" "1.2.840.10008.5.1.4.1.1.4" MRImageStorage
"CR" "1.2.840.10008.5.1.4.1.1.1" ComputedRadiographyImageStorage
"NM" "1.2.840.10008.5.1.4.1.1.20" NuclearMedicineImageStorage
"US" "1.2.840.10008.5.1.4.1.1.6.1" UltrasoundImageStorage
"XA" "1.2.840.10008.5.1.4.1.1.12.1" XRayAngiographicImageStorage
"SC" "1.2.840.10008.5.1.4.1.1.7" SecondaryCaptureImageStorage
Default is "1.2.840.10008.5.1.4.1.1.7" SecondaryCaptureImageStorage
If an SOP Class UID exists, leave it alone.
8. If the user specified an SOP UID (0x0008, 0x0018) on the command line,
change it. Add the tag if it doesn't exist in the file. Don't do
anything if the user
didn't specify an SOP UID on the command line.
9. If there is no Conversion Type tag (0x0008, 0x0064),
add one with the value "WSD" (Workstation)
If a Conversion Type tag exists, leave it alone.
10 Add a "Derivation Description" tag (0x0008, 0x2111), e.g.
"lossy JPEG quality = 70; ratio = 16:1; JPEG 16 Bit DLL Version
1.0.2.19"
If the tag exists (unlikely), change it.
11. Add a Lossy Image Compression tag (0x0028, 0x2110) with the value "01".
If the tag exists (unlikely), change it to "01".
12. Add a "Lossy Image Compression Ratio" tag (0x0028, 0x2112).
Set it to the approximate compression ratio (e.g. "12" for 12:1)
If the tag exists (unlikely), change it.
13 If this is a color (RGB) image,
Change the Photometric Interpretation (0x0028, 0x0004) to "YBR_FULL_422"
If the user specified a Photometric Interpretation on the command line,
change it to that value, whatever that is.
14 JPEG encoded DICOM images are always written Explicit VR, Little Endian.
15. Recompute all group lengths, if present in the original file.
NOTE: Should I add group lengths if not present?
-----------------
Note that some steps, like 7, are there for older ACR-NEMA 2.0 files, which
we only support incompletely.
We do not attempt to handle multi-frame images, or other weird situations
like color palette images. We do handle overlay images, rather nicely, I
might say. 8^)
A "typical" file would look something like this:
(0002,0001) File Meta Information Version
OB 0
(0002,0002) Media Storage SOP Class UID
UI 26 1.2.840.10008.5.1.4.1.1.7
(0002,0003) Media Storage SOP Instance UID
UI 20 1.2.840.113664.00002
(0002,0010) Transfer Syntax UID
UI 22 1.2.840.10008.1.2.4.50
(0002,0012) Implementation Class UID
UI 0
(0008,0005) Specific CharacterSet
CS 30 ISO 2022 IR 13\ISO 2022 IR 87
(0008,0008) Image Type
CS 18 DERIVED\SECONDARY
(0008,0016) SOP Class UID
UI 26 1.2.840.10008.5.1.4.1.1.7
(0008,0018) SOP Instance UID
UI 40 1.2.392.200036.9132.3.1.6.1.1.897061504
(0008,0060) Modality
CS 2 OT
(0008,0064) Conversion Type
CS 4 WSD
(0008,0070) Manufacturer
LO 18 J-MAC SYSTEM, INC.
(0008,2111) Derivation Description
ST 74 lossy JPEG quality = 70; ratio = 20:1; JPEG 16 Bit DLL Version
1, 0, 2, 19
(0018,1012) Date SecondaryCapture
DA 8 19980522
(0018,1014) Time SecondaryCapture
TM 6 112242
(0028,0002) Samples per Pixel
US 2 3
(0028,0004) Photometric Interpret
CS 12 YBR_FULL_422
(0028,0006) Planar Configuration
US 2 0
(0028,0010) Rows
US 2 432
(0028,0011) Columns
US 2 456
(0028,0100) Bits Allocated
US 2 8
(0028,0101) Bits Stored
US 2 8
(0028,0102) High Bit
US 2 7
(0028,0103) Pixel Representation
US 2 0
(0028,2110) Lossy Image Compression
CS 2 01
(0028,2112) Lossy Image Compression Ratio
DS 2 20
(7FE0,0010) Pixel Data
OB -1
(FFFE,E000) Item
-- 0
(FFFE,E000) Item
-- 28856 FF D8 FF DB 00 43 00 0A-07 08 10 08 07 08 0B 0E
.....C..........
(FFFE,E0DD) Sequence Delimitation Item
-- 0
-----------------
If anyone sees any mistakes or omissions, please feel free to comment.
Thanks again!
>
>5. If the original file specified a Transfer Syntax (0x0002, 0x0010),
> in the meta-header, change it to Lossy JPEG.
> UID "1.2.840.10008.1.2.4.50" = JPEG Process 1 (8 Bit Gray or RGB Color)
> UID "1.2.840.10008.1.2.4.51" = JPEG Process 1 (12 Bit Gray)
> Don't don anything if the file has no meta-header.
If the file did not have a meta-header, create one. Never never ever write a
compressed file without meta-header. This would be a guarantee for
desaster. The file could not be read reliably because the type of
compression (JPEG process X lossy or lossless, JPEG LS, RLE, whatever you
want) would have to be *guessed* from the pixel data. Bad idea.
>6. Add a "Image Type" tag (0x0008, 0x0008) with the value
>"DERIVED\\SECONDARY".
> If the tag exists, change it.
> NOTE: If the tag exists, should we append to it?
DERIVED\SECONDARY must be the first two values of the multi-valued
attribute. Make sure other values (3-n) remain untouched if present in the
original image. Their meaning is SOP Class specific, and they might be
important.
>7. If there is no "SOP Class UID" (0x0008, 0x0016) tag, add one based on
>the modality
If there is no SOP Class UID, the file is not DICOM which means it is most
likely an ACR-NEMA image. Unless you can guarantee that the file fulfils
all integrity conditions for the given modality, make it a Secondary Capture
image and add all missing mandatory attributes for the Secondary Capture
IOD.
>8. If the user specified an SOP UID (0x0008, 0x0018) on the command line,
> change it. Add the tag if it doesn't exist in the file. Don't do
>anything if the user
> didn't specify an SOP UID on the command line.
If you create a lossy compressed image, you _must_ change the SOP Instance
UID, period.
>13 If this is a color (RGB) image,
> Change the Photometric Interpretation (0x0028, 0x0004) to
"YBR_FULL_422"
> If the user specified a Photometric Interpretation on the command line,
> change it to that value, whatever that is.
The photometric interpretation should match the contents of the JPEG stream.
If the JPEG data is sub-sampled 4:2:2, use YBR_FULL_422. Otherwise use
YBR_FULL.
Make sure the other attributes of the Image Pixel module also match the
compressed JPEG stream (e.g. Bits Stored, High Bit, Pixel Representation,
Samples Per Pixel etc.). Remove optional attributes such as "largest image
pixel value" which are likely to be wrong now.
>15. Recompute all group lengths, if present in the original file.
> NOTE: Should I add group lengths if not present?
I would re-compute but not create new group lengths (this is our toolkit's
default). I don't think anybody is really using group lengths, they are
mostly a left-over from ACR-NEMA. Exceptions are (0000,0000) and
(0002,0000) which are mandatory in certain places.
There's probably still a number of point's I've forgotten. For example, not
all photometric interpretations are allowed with all SOP classes. Maybe you
should just re-read the whole standard again until you're sure everything's
perfect. If you have too much time, that is :-))
Regards,
Marco Eichelberg
OFFIS
Marco Eichelberg wrote:
> If you create a lossy compressed image, you _must_ change the SOP Instance
> UID, period.
Absolutely ... this is one of the few times the standard is explicitly
clear about when one needs a new SOP Instance UID.
Remember that if there are cross-references (e.g. referenced image sequence
to scouts) these may need to be updated too, and if there are other objects
in the study (presentation states and SR) that reference the images, they
need to be updated as well.
> Make sure the other attributes of the Image Pixel module also match the
> compressed JPEG stream (e.g. Bits Stored, High Bit, Pixel Representation,
> Samples Per Pixel etc.). Remove optional attributes such as "largest image
> pixel value" which are likely to be wrong now.
Don't forget that to go into JPEG the data must be unsigned and less
than or equal to 12 bits in bit depth ... this may require rescaling
the data (e.g. 12 bit CT data, signed, rescale intercept of 0 should
typically be remapped to 12 bit, unsigned, rescale intercept -1024).
If the data claims to be 16 bits (e.g. typical MR data) but isn't really,
you will have to consider what to do ... right-shifting 4 bits will likely
ruin the image, so you may have to check all the pixel values and be sure
they are all less than 12 bits wide and then mask.
Also, don't forget to mask out any overlay bits in the (unused) high
bits, and when decompressing, if going back to 16 bits signed and
"un-rescaling" to sign extend.
(BTW. This is one of the things that the new JPEG 2000 transfer syntax
addresses - up to 16 bits signed and unsigned are supported).
> >15. Recompute all group lengths, if present in the original file.
> > NOTE: Should I add group lengths if not present?
>
> I would re-compute but not create new group lengths (this is our toolkit's
> default). I don't think anybody is really using group lengths, they are
> mostly a left-over from ACR-NEMA. Exceptions are (0000,0000) and
> (0002,0000) which are mandatory in certain places.
I would throw out all group lengths. Absolutely nobody should be depending
on their presence during parsing/reading, and may people get the calculations
wrong when writing (esp. with nested undefined length sequences and so on).
Apart from the meta-header group length of course, which is required.
> Remember that if there are cross-references (e.g. referenced image sequence
> to scouts) these may need to be updated too, and if there are other objects
> in the study (presentation states and SR) that reference the images, they
> need to be updated as well.
This could become nearly impossible unless you have total control over
the disposition of the images within the domain of these references. I
have been struggling with similar issues when reconciling patient record
changes with images. You are never certain when it is complete. It is a
....ing nightmare.
dee
;-D
Marco wrote:
>If the file did not have a meta-header, create one. Never never ever write
a
>compressed file without meta-header. This would be a guarantee for
>desaster. The file could not be read reliably because the type of
>compression (JPEG process X lossy or lossless, JPEG LS, RLE, whatever you
>want) would have to be *guessed* from the pixel data. Bad idea.
Yes, this is what I have been thinking. My only reservation is: Isn't a
Meta-Header intended for *transmission* of DICOM objects? And don't many
(most?) DICOM receive programs remove the meta-header before writing the
DICOM object to a file?
So I guess my question is, what is the purpose of the Meta Header in a DICOM
*file*? I know that the Transfer Syntax can help in determining big/little
endian, implicit/explcit and the compression method, if any. But if receive
programs throw this information away, we're back to guessing, aren't we?
I'm not opposed to creating a Meta-Header, I would just like to get this
clear for my own thinking. Files that I create will be immediately
transmitted somewhere, and my friends here are that creating a Meta-Header
may be futile.
Marco wrote:
>DERIVED\SECONDARY must be the first two values of the multi-valued
>attribute. Make sure other values (3-n) remain untouched if present in the
>original image. Their meaning is SOP Class specific, and they might be
>important
If the existing value of Image Type" tag (0x0008, 0x0008) is "ORIGINAL",
then it seems to make sense to throw away that value and replace it with
"DERIVED". Is that correct? Likewise with "PRIMARY" and SECONDARY".
So what you are saying is, replace "ORIGINAL/PRIMARY" with
"DERIVED/SECONDARY", but keep any other string values that may follow. OK, I
see!
Marco wrote:
>If there is no SOP Class UID, the file is not DICOM which means it is most
>likely an ACR-NEMA image. Unless you can guarantee that the file fulfils
>all integrity conditions for the given modality, make it a Secondary
Capture
>image and add all missing mandatory attributes for the Secondary Capture
>IOD.
We've decided to just barf an error when we detect ACR-NEMA 2.0.
Marco wrote:
>If you create a lossy compressed image, you _must_ change the SOP Instance
>UID, period.
David wrote:
>Remember that if there are cross-references (e.g. referenced image sequence
>to scouts) these may need to be updated too, and if there are other objects
>in the study (presentation states and SR) that reference the images, they
>need to be updated as well.
Dee wrote:
> This could become nearly impossible unless you have total control over
> the disposition of the images within the domain of these references. I
> have been struggling with similar issues when reconciling patient record
> changes with images. You are never certain when it is complete. It is a
> ....ing nightmare.
We've decided to let the application decide if (and how) to create an SOP
UID and to deal with the implications. I am making a library. So it's out of
my hands, as they say. But I agree with you that a new SOP Instance UID
should be created.
Marco wrote:
>The photometric interpretation should match the contents of the JPEG
stream.
>If the JPEG data is sub-sampled 4:2:2, use YBR_FULL_422. Otherwise use
>YBR_FULL.
It is not immediately clear what my JPEG library is doing. I am *assuming*
that it is sub-sampling, but I haven't found the parameter (or switch) that
will make me confident of this. I imagine that this must be in the JPEG
header tags somewhere. Time to break out that big pink book again! (JPEG
Still Image Data Compression Standard)
Marco wrote:
>Make sure the other attributes of the Image Pixel module also match the
>compressed JPEG stream (e.g. Bits Stored, High Bit, Pixel Representation,
>Samples Per Pixel etc.). Remove optional attributes such as "largest image
>pixel value" which are likely to be wrong now.
I hadn't thought about "largest image pixel value"... I wonder if there
might be other attributes like that, that will be rendered irrelevant.
Marco wrote:
>I would re-compute but not create new group lengths (this is our toolkit's
>default). I don't think anybody is really using group lengths, they are
>mostly a left-over from ACR-NEMA. Exceptions are (0000,0000) and
>(0002,0000) which are mandatory in certain places.
David wrote:
>I would throw out all group lengths. Absolutely nobody should be depending
>on their presence during parsing/reading, and may people get the
calculations
>wrong when writing (esp. with nested undefined length sequences and so on).
>Apart from the meta-header group length of course, which is required.
I'm extremely happy to hear this. I have been arguing for years now in favor
of throwing those dang group lengths out the window! Like David says, It can
be really tricky with private groups and "recursive sequences".
But a few weeks ago we got a complaint from somewhere (I won't name names!)
They're viewer (or something) couldn't read our JPEG files unless we
re-computed the group lengths. So now I am stuck computing them again. But
like Marco says, I don't create them if they don't exist.
David wrote:
>Don't forget that to go into JPEG the data must be unsigned and less
>than or equal to 12 bits in bit depth ... this may require rescaling
>the data (e.g. 12 bit CT data, signed, rescale intercept of 0 should
>typically be remapped to 12 bit, unsigned, rescale intercept -1024).
Yes, I'm doing all that. In fact, that is how I this all got started.
>If the data claims to be 16 bits (e.g. typical MR data) but isn't really,
>you will have to consider what to do ... right-shifting 4 bits will likely
>ruin the image, so you may have to check all the pixel values and be sure
>they are all less than 12 bits wide and then mask.
Regardless of the modality, I look at the actual (not reported) range of
values. If these can be shifted into the range 0..4095, then we don't have
to throw anything away. If the value range is larger than 4096, then I look
at the windowing values and try to fit the "JPEG Window" over that, throwing
away extreme values above and below.
If the Window Width is huge (over 4096), as is the case of some MR images,
then I divide all the values by the smallest denominator possible to get the
values within the necessary range.
If there is are no windowing values (ACR-NEMA only?) I have some default
values based on the modality. These default values are the same as those
used by our viewer.
And if all that fails, I just throw up my hands in frustration and leave!
David wrote:
>Also, don't forget to mask out any overlay bits in the (unused) high
>bits, and when decompressing, if going back to 16 bits signed and
>"un-rescaling" to sign extend.
If the overlay bits are embeded in the high-order bit(s) of the pixel data,
I move them to a new overlay data tag (0x6000, 0x3000) before compressing.
All unscaling is done by the viewer with the slope/intercept values.
Anyway, we have a long weekend here in Japan, so we'll give it a rest for a
few days!
>>compressed file without meta-header. This would be a guarantee for
>>desaster. The file could not be read reliably because the type of
>>compression (JPEG process X lossy or lossless, JPEG LS, RLE, whatever you
>>want) would have to be *guessed* from the pixel data. Bad idea.
>
>Yes, this is what I have been thinking. My only reservation is: Isn't a
>Meta-Header intended for *transmission* of DICOM objects? And don't many
>(most?) DICOM receive programs remove the meta-header before writing the
>DICOM object to a file?
No, actually it's exactly the other way round: You never transmit a
meta-header. It's stripped off when sending an image over network, and the
receiver is supposed to create a new one when writing the received object to
file in a DICOM conformant way. The meta-header roughly contains the same
information that is transported in the C-STORE request message which is used
to send images over a network.
>So I guess my question is, what is the purpose of the Meta Header in a
DICOM
>*file*? I know that the Transfer Syntax can help in determining big/little
>endian, implicit/explcit and the compression method, if any. But if receive
>programs throw this information away, we're back to guessing, aren't we?
The meta-header tells you that you have a DICOM object in the first place,
and it tells you the transfer syntax (i.e. encoding) of the rest of the
object, which is the most important information for decoding the object. If
the meta-header is missing, you indeed have to guess, and for each heuristic
one could create sample object where the guess goes wrong.
>So what you are saying is, replace "ORIGINAL/PRIMARY" with
>"DERIVED/SECONDARY", but keep any other string values that may follow. OK,
I
>see!
Exactly. The other string values will, for example, tell you that a CT
image is a scout and not a normal slice - but again, that's SOP class
specific.
>We've decided to let the application decide if (and how) to create an SOP
>UID and to deal with the implications. I am making a library. So it's out
of
>my hands, as they say. But I agree with you that a new SOP Instance UID
>should be created.
Maybe you should force the user to pass a certain flag (something like
KEEP_SOP_INSTANCE_UID_ALTHOUGH_THIS_IS_A_BAD_IDEA) to prevent your library
from creating a new SOP instance UID. I.e. make it difficult for the end
user to get things wrong.
>It is not immediately clear what my JPEG library is doing. I am *assuming*
>that it is sub-sampling, but I haven't found the parameter (or switch) that
>will make me confident of this. I imagine that this must be in the JPEG
>header tags somewhere. Time to break out that big pink book again! (JPEG
>Still Image Data Compression Standard)
It's in the frame header. For each color component you have one byte
indicating the horizontal and vertical sampling factor (table B.2 in ISO/IEC
10918-1).
>I hadn't thought about "largest image pixel value"... I wonder if there
>might be other attributes like that, that will be rendered irrelevant.
SmallestPixelValueInSeries
LargestPixelValueInSeries
PixelPaddingValue
and the palette color LUT stuff if your code handles conversion from PALETTE
COLOR.
Regards,
Marco Eichelberg
OFFIS
Ken Sutherland wrote:
> But a few weeks ago we got a complaint from somewhere (I won't name names!)
> They're viewer (or something) couldn't read our JPEG files unless we
> re-computed the group lengths. So now I am stuck computing them again. But
> like Marco says, I don't create them if they don't exist.
If they require group lengths they are non-compliant and will barf on
many people's images ... make them fix it - it shouldn't be your problem.
Of course, you do need to send fixed values for the "items" that are
the fragments in the sequence-like wrapper around the JPEG bitstream
in (7FE0,0010), but that is a different matter.
> If the Window Width is huge (over 4096), as is the case of some MR images,
> then I divide all the values by the smallest denominator possible to get the
> values within the necessary range.
NB. I would pay no attention whatsoever to the values in Window Center
and Window Width, if that is what you are referring to. Even if these
values are present and have any clinical significance whatsoever, that
doesn't mean that you should "discard" the pixel values outside the
window. If the actual range of pixel values is outside the 12-bit range
then you should scale by the actual range ... not by some essentially
arbitrary value in Window Width.
> If the overlay bits are embeded in the high-order bit(s) of the pixel data,
> I move them to a new overlay data tag (0x6000, 0x3000) before compressing.
Excellent.
I see! Thanks! I'll make a push for the meta-header.
David wrote:
>NB. I would pay no attention whatsoever to the values in Window Center
>and Window Width, if that is what you are referring to. Even if these
>values are present and have any clinical significance whatsoever, that
>doesn't mean that you should "discard" the pixel values outside the
>window. If the actual range of pixel values is outside the 12-bit range
>then you should scale by the actual range ... not by some essentially
>arbitrary value in Window Width.
I would agree with you in theory, however, CT images often have "noise"
around the perimeter, and they often select a very large (negative) number
for "air" outside the circle. (I'm sorry, I don't know the technical terms.)
So for these images it seems like it is a waist scale everything, discarding
pixel resolution, in an attempt to preserve these extraneous values.
Of course with lossy compression, there is no "correct" method. You have to
discard something. I realize that my method of using the windowing level and
width is not perfect. I will certainly pass along your advice to my
coworkers here.
Thanks again!
Ken Sutherland wrote:
> I would agree with you in theory, however, CT images often have "noise"
> around the perimeter, and they often select a very large (negative) number
> for "air" outside the circle. (I'm sorry, I don't know the technical terms.)
> So for these images it seems like it is a waist scale everything, discarding
> pixel resolution, in an attempt to preserve these extraneous values.
Oh, you want to look then at Pixel Padding Value which should describe
the out-of-Hounsfield-Unit-range value that is used for the perimeter,
and specifically exclude that (or clamp it to the value of air or -1024 HU
or whatever, considering Rescale Slope and Intercept of course).
For CT images, one way to do this (if the Rescale Slope is 1) is just
subtract the Rescale Intercept value (usually 0 or -1024) and then clamp
everything below zero to zero. The most +ve value is then the range, and
will hopefully fit in 12 bits.
I still argue that the values in Window Center and Width are useless
for this exercise, and if used will discard far more range than is
necessary.
Thank you for this suggestion. I will look into it.