首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >确定JPEG (JFIF)图像的大小

确定JPEG (JFIF)图像的大小
EN

Stack Overflow用户
提问于 2009-10-12 21:35:41
回答 4查看 21.1K关注 0票数 35

我需要找到JPEG (JFIF)图像的大小。图像不是作为独立文件保存的,所以我不能使用GetFileSize或其他类似的API (图像被放置在流中,除了通常的JPEG/JFIF头外,没有其他标头)。

我做了一些研究,发现JPEG图像是由不同的部分组成的,每个部分从一个框架标记(0xFF 0xXX)开始,以及这个帧的大小。使用这些信息,我能够解析文件中的许多信息。

问题是,我找不到压缩数据的大小,因为似乎没有压缩数据的帧标记。此外,压缩后的数据似乎遵循SOS (FFDA)标记,图像以图像的末尾(FFD9)结束。

实现这一目标的一种方法是从字节到字节搜索EOI标记,但是我认为压缩的数据可能包含这种字节组合,对吗?

是否有一种简单而正确的方法来找到图像的总大小?(我更喜欢没有任何外部库的代码/想法)

基本上,我需要图像开始(SOI-FFE0)和图像结束(EOI-FFD9)之间的距离(以字节为单位)。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-10-21 17:47:20

压缩的数据将不包括SOI或EOI字节,因此您在那里是安全的。但是注释、应用程序数据或其他标头可能。幸运的是,您可以在给定长度时识别和跳过这些部分。

JPEG规范告诉您需要什么:

http://www.w3.org/Graphics/JPEG/itu-t81.pdf

见表B.1,第32页。有*的符号后面没有长度场(RST,SOI,EOI,TEM)。其他人也是。

您需要跳过不同的字段,但这并不是太糟糕。

如何通过:

  1. 开始阅读SOI (FFD8)。这是个开始。这应该是溪流里的第一件事。
代码语言:javascript
复制
- Then, progress through the file, finding more markers and skipping over the headers:
- SOI marker (`FFD8`): Corrupted image. You should have found an EOI already!
- TEM (`FF01`): standalone marker, keep going.
- RST (`FFD0` through `FFD7`): standalone marker, keep going. You could validate that the restart markers count up from `FFD0` through `FFD7` and repeat, but that is not necessary for measuring the length.
- EOI marker (`FFD9`): You're done!
- Any marker that is not RST, SOI, EOI, TEM (`FF01` through `FFFE`, minus the exceptions above): After the marker, read the next 2 bytes, this is the 16-bit big-endian length of that frame header (not including the 2-byte marker, but including the length field). Skip the given amount (typically length minus 2, since you already got those bytes).
- If you get an end-of-file before EOI, then you've got a corrupted image.
- Once you've got an EOI, you've gotten through the JPEG and should have the length. You can start again by reading another SOI if you expect more than one JPEG in your stream.

票数 41
EN

Stack Overflow用户

发布于 2010-01-05 10:20:08

也许是这样的

代码语言:javascript
复制
int GetJpgSize(unsigned char *pData, DWORD FileSizeLow, unsigned short *pWidth, unsigned short *pHeight)
{
  unsigned int i = 0;


  if ((pData[i] == 0xFF) && (pData[i + 1] == 0xD8) && (pData[i + 2] == 0xFF) && (pData[i + 3] == 0xE0)) {
    i += 4;

    // Check for valid JPEG header (null terminated JFIF)
    if ((pData[i + 2] == 'J') && (pData[i + 3] == 'F') && (pData[i + 4] == 'I') && (pData[i + 5] == 'F')
        && (pData[i + 6] == 0x00)) {

      //Retrieve the block length of the first block since the first block will not contain the size of file
      unsigned short block_length = pData[i] * 256 + pData[i + 1];

      while (i < FileSizeLow) {
        //Increase the file index to get to the next block
        i += block_length; 

        if (i >= FileSizeLow) {
          //Check to protect against segmentation faults
          return -1;
        }

        if (pData[i] != 0xFF) {
          return -2;
        } 

        if (pData[i + 1] == 0xC0) {
          //0xFFC0 is the "Start of frame" marker which contains the file size
          //The structure of the 0xFFC0 block is quite simple [0xFFC0][ushort length][uchar precision][ushort x][ushort y]
          *pHeight = pData[i + 5] * 256 + pData[i + 6];
          *pWidth = pData[i + 7] * 256 + pData[i + 8];

          return 0;
        }
        else {
          i += 2; //Skip the block marker

          //Go to the next block
          block_length = pData[i] * 256 + pData[i + 1];
        }
      }

      //If this point is reached then no size was found
      return -3;
    }
    else {
      return -4;
    } //Not a valid JFIF string
  }
  else {
    return -5;
  } //Not a valid SOI header

  return -6;
}  // GetJpgSize
票数 3
EN

Stack Overflow用户

发布于 2009-10-12 21:38:14

由于您没有发布任何语言,所以我不确定这是否有效,但是:

你能Stream.Seek(0, StreamOffset.End);,然后采取溪流的位置吗?

请具体说明您正在使用的框架。

实际情况是,如果文件头没有指定预期大小,则必须查找(或读取)到图像的末尾。

编辑

由于您试图流多个文件,您将希望使用流友好的容器格式。

奥格应该是一个很好的适合这一点。

JPEG实际上已经是流友好的,但是您必须保证每个文件在将其发送到流之前都有一个有效的终止符,否则您就会冒着意外输入导致应用程序崩溃的风险。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1557071

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档