JPEG压缩像素数据到原始像素数据

时间:2016-11-08 19:54:48

标签: c# compression jpeg dicom libjpeg

对于不知道DICOM文件是什么的人来说,它是一个包含患者医疗影像数据的文件。它保存患者数据和一些像素数据。您需要知道的是,像素数据位于同一文件中,但与患者数据的其余部分分开。

我制作的程序可以读取DICOM文件中的RAW像素数据。但是,像素数据经常使用JPEG压缩进行压缩。这是我用来了解像素压缩方法的字典:

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] : "???";
        }
    }
}

如您所见,我想解压缩有26种不同类型的JPEG压缩方法(所有这些方法的密钥均为1.2.840.10008.1.2.4.xx)。总而言之,我有一些像素数据(作为MemoryStream)使用JPEG压缩算法压缩,我想解压缩为RAW像素数据。我甚至不知道从哪里开始!这有点令人沮丧。

有些人想知道我尝试了什么: 我尝试使用LibJpeg.NET,但是当我调用jpeg_decompress_struct.jpeg_read_header(bool require_image)函数时,我得到一个异常:Not a JPEG file: starts with 0xFE 0xFF

3 个答案:

答案 0 :(得分:1)

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.

答案 1 :(得分:0)

列出的大多数传输语法都已停用,因此DICOM标准并不知道这种压缩是否有效。

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

所以你不需要支持它。也许您想要支持旧图像,但要记住,其中许多图像过去并未真正使用过,并且从2006年开始退役!

此外,每个DICOM设备都必须与DICOM一致性声明相关联,声明其中包括传输sysntax支持。您不需要支持所有DICOM传输语法,只需支持您在一致性声明中声明的语法。例如,并非所有DICOM设备都支持Jpeg2000或Jpeg LS

答案 2 :(得分:0)

DICOM 压缩图像像素数据没有像 JPEG 文件那样的标准图像标题。 列、行、bitsperpixel等像素信息仅在DICOM Data-Set Attribute值中直接编码,Data-Set PixelData Attribute值包含经过特殊编码的压缩字节流。 查看DICOM Standard PS 3.5 Annex A - Transfer Syntax,特别注意A.4 http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_A.4.html

话虽如此,我在定位能够解码和编码 JPEG Lossless Non-Hierarchical Level 14 和预测器选定值 1(原生 JPEG 无损压缩的 DICOM)的库时遇到了同样的问题。事实证明,可以从 ITU-T.81 标准轻松实现(可以从 1998 年之类的许多地方下载)。仅使用 DICOM 标准指定的标准,我就在一周内设法编写了(不是一个而是两个)编码器/解码器编解码器。我只使用查找表,它的工作速度非常快。想想一旦构建下一个就容易得多,因为您拥有 JPEG 读/写基础设施,唯一的问题是为 JPEG 扩展(如 JPEG-LS)实现 MCU 编码/解码逻辑。

如果您决定不走那条路,第二种解决方案是重建丢失的标题。我决定不这样做,因为大多数库实际上不支持这种压缩(至少我的经验),而实际上支持它的库非常庞大(支持大量我们实际上不需要的其他东西)。 但无论如何,这两条路都通向学习 JPEG 编码过程的内部。

最后的第三个解决方案是找到一些能够这样做的开源项目,我想现在网上应该有更多可用的。

希望这能帮助其他寻找类似答案的人。