【问题标题】:Reading image data from a JFIF?从 JFIF 读取图像数据?
【发布时间】:2014-10-09 14:58:55
【问题描述】:

所以我正在从文件中读取 JFIF (JPEG) 数据,作为练习(我知道那里已经有库已经这样做了,我不是在寻找那些)。我已经得到了图像文件的大小、颜色深度和尺寸。但是,我不太确定如何获取实际的图像数据。我在十六进制编辑器中查看了数据,并将其与实际图像进行比较让我无处可去。如果有人有一个很好的资源来开始这件事(我知道这可能是一个艰巨而有启发性的过程,但这就是我这样做的原因),那就太棒了。

到目前为止我的代码,仅用于上下文:

// check header data, assign header data to important fields

        // Start Of Image (SOI) must be FFD8 and the next marker must be FF
        if(!(this.data[0] == (byte) 0xFF && this.data[1] == (byte) 0xD8
                && this.data[2] == (byte) 0xFF))
            this.isValid = false;

        // check if file is not valid
        if(!isValid) 
            log.log(Level.SEVERE, 
                    String.format("ERROR: File %s is not registered as a JFIF!\n", this.filename), 
                    new IllegalArgumentException());

        // If the next values are correct, then the data stream starts at SOI
        // If not, the data stream is raw
        this.isRawDataStream = !(this.data[3] == (byte) 0xE0
                && this.data[6]  == (byte) 0x4A
                && this.data[7]  == (byte) 0x46
                && this.data[8]  == (byte) 0x49
                && this.data[9]  == (byte) 0x46
                && this.data[10] == (byte) 0x00);

        // Read until SOF0 marker (0xC0)
        int i = 11;
        while(this.data[i] != (byte) 0xC0) {
            i++;
        }
        System.out.println("SOF0 marker at offset " + i);

        // Skip two bytes, next byte is the color depth
        this.colorDepth = this.data[i+3];

        // Next two bytes are the image height
        String h = String.format("%02X", this.data[i+4]) + String.format("%02X", this.data[i+5]);
        this.height = hexStringToInt(h);
        System.out.println("Height: " + this.height);

        // Next two bytes are the image width
        String w = String.format("%02X", this.data[i+6]) + String.format("%02X", this.data[i+7]); 
        this.width = hexStringToInt(w);
        System.out.println("Width: " + this.width);

        System.out.println("Color depth: " + this.colorDepth);
        // load pixels into an image
        this.image = new BufferedImage(this.width,
                                       this.height, 
                                       BufferedImage.TYPE_INT_RGB);

然后,我需要获取每个像素并将其发送到图像。如何获取每个像素及其各自的 RGB 数据?

【问题讨论】:

  • 您可以阅读规范以查看 jfif 所需的所有数据:jpeg.org/public/jfif.pdf
  • 啊,所以,根据阅读,我必须像这样获取RGB数据? Y = 0.299 R + 0.587 G + 0.114 B Cb = - 0.1687 R - 0.3313 G + 0.5 B + 128 Cr = 0.5 R - 0.4187 G - 0.0813 B + 128 @Obicere
  • 遵循规范。我还没有读过它,但它可能不止于此。但它将包含解析图像所需的所有信息。

标签: java image jpeg jfif


【解决方案1】:

你要做的不是一个简单的下午项目。这本书解释了这个过程:JPEG压缩数据和像素值之间有很多代码。

http://www.amazon.com/Compressed-Image-File-Formats-JPEG/dp/0201604434/ref=pd_bxgy_b_img_y

首先,您必须处理两种独立但相关的压缩方法:顺序和渐进式。

当你读取位数据时,你必须

  1. 霍夫曼解码
  2. 运行长度解码
  3. 逆量化
  4. 列表项
  5. 反离散余弦变换
  6. 上样
  7. YCbCr 到 RGB 转换

这是在简单的顺序情况下。

你不会在这个论坛上得到所有这些步骤的解释。

我也推荐

http://www.amazon.com/dp/1558514341/ref=rdr_ext_tmb

【讨论】:

  • 这并不是要劝阻您,而是要设定您对项目范围的期望。当我多年前做你想做的事时,人们很难过甚至没有尝试。只需使用图书馆。然后你什么都学不到,JPEG 仍然是一门黑艺术。
  • 没错!我很高兴有人得到它!另外,我可能会广泛阅读以下内容:w3.org/Graphics/JPEG/itu-t81.pdf 因为它可能会指导我完成整个事情。
  • 完整解码需要 DHT 和 DQT 块。 DHT 是霍夫曼表。附件 C 解释了如何获取 DHT 块中的数据并从中构建一个霍夫曼表。上面的书籍展示了如何进行霍夫曼解码。
  • 您现在应该只使用顺序 jpeg 图像。首先计算每个组件所需的 MCU 数量。这来自组件的图像大小和采样因子。接下来,您将需要进行霍夫曼解码。您需要能够读取 DHT 标记并能够构建表格。如果您有计数,标准会告诉您如何从中构建表格。 Counts 给出一个值的霍夫曼码的长度。该表将包含每个值的位序列。您将需要代码来读取以位为单位的压缩数据流。
  • Mincode 和 Maxcode 是你用来解码的。 MinCode [I] 是长度为 I 的最小霍夫曼码。 MaxCode [i] 是长度为 I 的最大霍夫曼码。
猜你喜欢
  • 1970-01-01
  • 2017-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-06
  • 2012-07-16
  • 1970-01-01
相关资源
最近更新 更多