简体   繁体   中英

JPEG compressed pixel data to Raw Pixel data

For people who don't know what a DICOM file is, it is a file that holds medical imaging data about patients. It holds the patient data and some pixel data. All you need to know is that the pixel data is in the same file but separated from the rest of the patient's data.

I made a program that can read RAW pixel data in DICOM files. However, the pixel data is frequently compressed using JPEG compression. Here's the dictionary that I use in order to know the method of pixel compression:

using System.Collections.Generic;

namespace DICOMViewer.Parsing
{
    public static class TransferSyntaxDictionary
    {
        // DICOM Transfer Syntax Dictionary
        // Reference: DCIOM Standard 2009, Part 5: Data Structures and Encoding

        static private readonly Dictionary<string, string> d = new Dictionary<string, string>
        {
            { "1.2.840.10008.1.2", "Implicit VR Little Endian: Default Transfer Syntax for DICOM" },
            { "1.2.840.10008.1.2.1", "Explicit VR Little Endian" },
            { "1.2.840.10008.1.2.1.99", "Deflated Explicit VR Little Endian" },
            { "1.2.840.10008.1.2.2", "Explicit VR Big Endian" },
            { "1.2.840.10008.1.2.4.50", "JPEG Baseline (Process 1): Default Transfer Syntax for Lossy JPEG 8 Bit Image Compression" },
            { "1.2.840.10008.1.2.4.51", "JPEG Extended (Process 2 & 4): Default Transfer Syntax for Lossy JPEG 12 Bit Image Compression (Process 4 only)" },
            { "1.2.840.10008.1.2.4.52", "JPEG Extended (Process 3 & 5)" },
            { "1.2.840.10008.1.2.4.53", "JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8)" }, 
            { "1.2.840.10008.1.2.4.54", "JPEG Spectral Selection, Non-Hierarchical (Process 7 & 9)" },
            { "1.2.840.10008.1.2.4.55", "JPEG Full Progression, Non-Hierarchical (Process 10 & 12)" },
            { "1.2.840.10008.1.2.4.56", "JPEG Full Progression, Non-Hierarchical (Process 11 & 13)" },
            { "1.2.840.10008.1.2.4.57", "JPEG Lossless, Non-Hierarchical (Process 14)" }, 
            { "1.2.840.10008.1.2.4.58", "JPEG Lossless, Non-Hierarchical (Process 15)" },
            { "1.2.840.10008.1.2.4.59", "JPEG Extended, Hierarchical (Process 16 & 18)" },
            { "1.2.840.10008.1.2.4.60", "JPEG Extended, Hierarchical (Process 17 & 19)" },
            { "1.2.840.10008.1.2.4.61", "JPEG Spectral Selection, Hierarchical (Process 20 & 22)" },
            { "1.2.840.10008.1.2.4.62", "JPEG Spectral Selection, Hierarchical (Process 21 & 23)" },
            { "1.2.840.10008.1.2.4.63", "JPEG Full Progression, Hierarchical (Process 24 & 26)" }, 
            { "1.2.840.10008.1.2.4.64", "JPEG Full Progression, Hierarchical (Process 25 & 27)" },
            { "1.2.840.10008.1.2.4.65", "JPEG Lossless, Hierarchical (Process 28)" },
            { "1.2.840.10008.1.2.4.66", "JPEG Lossless, Hierarchical (Process 29)" },
            { "1.2.840.10008.1.2.4.70", "JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1]): Default Transfer Syntax for Lossless JPEG Image Compression" }, 
            { "1.2.840.10008.1.2.4.80", "JPEG-LS Lossless Image Compression" },
            { "1.2.840.10008.1.2.4.81", "JPEG-LS Lossy (Near-Lossless) Image Compression" },
            { "1.2.840.10008.1.2.4.90", "JPEG 2000 Image Compression (Lossless Only)" },
            { "1.2.840.10008.1.2.4.91", "JPEG 2000 Image Compression" },
            { "1.2.840.10008.1.2.4.92", "JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only)" },
            { "1.2.840.10008.1.2.4.93", "JPEG 2000 Part 2 Multi-component Image Compression" },
            { "1.2.840.10008.1.2.4.94", "JPIP Referenced" },
            { "1.2.840.10008.1.2.4.95", "JPIP Referenced Deflate" },
            { "1.2.840.10008.1.2.4.100", "MPEG2 Main Profile @ Main Level" },
            { "1.2.840.10008.1.2.5", "RLE Lossless" },
            { "1.2.840.10008.1.2.6.1", "RFC 2557 MIME encapsulation" }
        };

        static public string GetTransferSyntaxName(string theTransferSyntaxUID)
        {
            return d.ContainsKey(theTransferSyntaxUID) ? d[theTransferSyntaxUID] : "???";
        }
    }
}

As you see there are 26 different types of JPEG compression methods that I wanna decompress(All those having a key of 1.2.840.10008.1.2.4.xx). To summarize, I have some pixel data(as a MemoryStream ) compressed using a JPEG compression algorithm that I wanna decompress to RAW pixel data. I don't even know where to start! That's kinda frustrating.

Some people would like to know what I have tried: I tried to use LibJpeg.NET, but when I call the jpeg_decompress_struct.jpeg_read_header(bool require_image) function I get an exception: Not a JPEG file: starts with 0xFE 0xFF

DICOM supports almost all of the ITU 81 standard , while the famous libjpeg (in its common binary distribution[*]) only support 8bits huffman & sequential.

You need to use another JPEG library which at least support:

  • 8/12 bits huffman & sequential
  • 16bits lossless

For reference:

[*] If you download the source code, you'll be able to compile the 12bits huffman/sequential binaries.


EDIT: In fact re-reading your question, I discover you are not dealing with Fragments at all, hence the famous 0xFE 0xFF error message. You should be reading the DICOM standard, since it comes with trivial examples .

Most of the transfer syntax, which are listed, are retired, so the DICOM Standard doesn't know that kind of compression as a valid one.

  • 1.2.840.10008.1.2.4.52 Retired
  • 1.2.840.10008.1.2.4.53 Retired
  • 1.2.840.10008.1.2.4.54 Retired
  • 1.2.840.10008.1.2.4.55 Retired
  • 1.2.840.10008.1.2.4.56 Retired
  • 1.2.840.10008.1.2.4.57 Retired
  • 1.2.840.10008.1.2.4.58 Retired
  • 1.2.840.10008.1.2.4.59 Retired
  • 1.2.840.10008.1.2.4.60 Retired
  • 1.2.840.10008.1.2.4.61 Retired
  • 1.2.840.10008.1.2.4.62 Retired
  • 1.2.840.10008.1.2.4.63 Retired
  • 1.2.840.10008.1.2.4.64 Retired
  • 1.2.840.10008.1.2.4.65 Retired
  • 1.2.840.10008.1.2.4.66 Retired

So you don't need to support it. Maybe you want to to support for old images but keep in mind that many of them are not really used in the past and are retired from 2006!

Moreover every DICOM device have to be associated with a DICOM Conformance Statement where it is declared, among other things, the transfer sysntax support. You don't need to support all DICOM Transfer Syntax but just ones you have declared in your conformance statement. For example not all DICOM device supports Jpeg2000, or Jpeg LS

DICOM Compressed images pixeldata does not have standard image headers like JPEG files. Pixel information like columns, rows, bitsperpixel and others, are directly encoded only in DICOM Data-Set Attribute values, and the Data-Set PixelData Attribute value contains compressed byte stream which is specially encoded. Check the DICOM Standard PS 3.5 Annex A - Transfer Syntax, especially pay attention to A.4 http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_A.4.html

That being said, I had same issue locating library capable of decoding and encoding JPEG Lossless Non-Hierarchical Level 14 and predictor Selected Value 1 (DICOM of Native JPEG Lossless Compression). Which turns out can be easily implemented from ITU-T.81 Standard (can be download from many places it dates from 1998 or something like that). Only using standards specified by DICOM standard I have managed to write, not one but two, encoder/decoder codecs under a week. Am using only Look Up Tables and it works very fast. Think once you build one next one is much easier, since you have JPEG read/write infrastructure only catch is implementing MCU encoding/decoding logic for JPEG extension's like JPEG-LS.

If you decide not to go that road, second solution would be to rebuild missing headers. Which I decided not to do since most libraries actually do not support such compression's (at least my experience), and libraries that actually support it are extremely huge (support tons of other things which we actually don't need). But never the less both road leads to learning internal of JPEG encoding process.

Third last solution would be to find some open-source project capable of doing so, and I imagine by now there should more then several available on net.

Hope this helps others looking for similar answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM