【问题标题】:How to identify contents of a byte[] is a JPEG?如何识别 byte[] 的内容是 JPEG?
【发布时间】:2011-05-31 19:41:57
【问题描述】:

我有一个小字节数组(小于 25K),我将其作为较大消息信封的一部分进行接收和解码。有时这是一个图像,而且它是一个 JPG。除了字节数组之外,我没有上下文信息,并且需要识别它是否是图像,以及图像是否为 JPG 类型。

在开头、结尾或某个偏移处是否存在一些幻数或幻字节,我可以通过查看来识别它?

我的代码示例如下所示(来自内存,而不是 c/p):

byte[] messageBytesAfterDecode = retrieveBytesFromEnvelope();
if(null != messageBytesAfterDecode && messageBytesAfterDecode > 0){
    if(areTheseBytesAJpeg(messageBytesAfterDecode)){
        doSomethingWithAJpeg(messageBytesAfterDecode)
    }else{
        flagEnvelopeAsHavingBadContentInTheField();
    }
}

我真的需要什么进入

areTheseBytesAJpeg(byte[] mBytes){}

方法,甚至是指向详细说明它的规范的指针。我希望有一种非常快速的方法来做出这个决定,因为我真的不想将它们读入图像等。

【问题讨论】:

    标签: java image jpeg


    【解决方案1】:

    来自维基百科:

    JPEG 图像文件以 FF D8 开头,以 FF D9 结尾。

    http://en.wikipedia.org/wiki/Magic_number_(programming)

    【讨论】:

    • 所有谷歌 - 它甚至把它放在结果中:google.com/search?&q=jpg+magic+number
    • 不错。让我运行我的测试,我会回来的!
    • 真是太好了!我的一半是维基百科,一半是火狐。一定是让我慢下来的原因。
    • 工作就像一个魅力,正是我所要求的。
    【解决方案2】:

    关于其他 jpeg 文件格式的一些额外信息:文件的开头包含这些字节

    BMP : 42 4D
    JPG : FF D8 FF EO ( Starting 2 Byte will always be same)
    PNG : 89 50 4E 47
    GIF : 47 49 46 38
    

    当 JPG 文件使用 JFIF 或 EXIF 时,签名不同:

    Raw  : FF D8 FF DB  
    JFIF : FF D8 FF E0  
    EXIF : FF D8 FF E1
    

    一些代码:

    private static Boolean isJPEG(File filename) throws Exception {
        DataInputStream ins = new DataInputStream(new BufferedInputStream(new FileInputStream(filename)));
        try {
            if (ins.readInt() == 0xffd8ffe0) {
                return true;
            } else {
                return false;
    
            }
        } finally {
            ins.close();
        }
    }
    

    【讨论】:

    • 当JPG文件使用JFIF或EXIF时,签名不同: Raw: FF D8 FF DB ; JFIF: FF D8 FF E0 ; EXIF: FF D8 FF E1
    • @GabrielHautclocq 谢谢!我已经更新了完整信息的答案。
    【解决方案3】:

    关于幻数(包括 JPEG 文件)的另一个“知识”来源是 GNU/Linux file 命令使用的 magic 文件。

    如果您安装了file 命令,那么file --version 会告诉您magic 文件所在的位置,您可以使用文本编辑器阅读它...并仔细阅读man 5 magic

    (和magic文件内容确认其他答案的细节。)

    【讨论】:

      【解决方案4】:

      引用this wikipedia article:

      JPEG 图像文件以 FF D8 和 以FF D9结束。 JPEG/JFIF 文件 包含“JFIF”的 ASCII 码(4A 46 49 46) 作为空终止字符串。 JPEG/Exif 文件包含 ASCII 码 对于“Exif”(45 78 69 66)也可以作为 以空结尾的字符串,后跟 有关文件的更多元数据。

      【讨论】:

      • 请注意,一些 JPEG 在该位置既没有 4A 46 49 46 也没有 45 78 69 66(尽管我见过的大多数都是这样)。不是这方面的专家,但我正在查看一个在该位置有 50 68 6F 74 的 JPEG;对应于“Photoshop”中的 ASCII“Phot”,尽管我已经从 Photoshop 以多种方式保存了 JPEG,但无法复制它。 (然而,Photoshop 将此文件识别为 JPEG,Windows 和 OS X 也是如此。)此文件在任何地方都不包含 JFIF 或 Exif 标记。最后,文件确实以 FF D8 开头并以 FF D9 结尾(因为它是 JPEG,所以应该如此)。
      【解决方案5】:

      许多格式都由所谓的幻数识别。这些是通常在文件前面的字节序列,用于识别以下二进制数据是否真的是您认为的那样。谷歌快速搜索返回:http://www.linfo.org/magic_number.html,特别是引用:

      “同样,JPEG(联合图像专家组)图像文件常用的幻数是 0x4A464946,它是 JFIF(JPEG 文件交换格式)的 ASCII 等价物。但是,JPEG 幻数不是文件;相反,它们从第七个字节开始。其他示例包括 MIDI(乐器数字接口)文件的 0x4D546864 和 bzip2 压缩文件的 0x425a6831415925。"

      【讨论】:

      • Jfif 不一定与 jpeg 相同。虽然,大多数人说 jpeg 时的意思实际上是 jfif,因为他们认为它使用 YUV 作为颜色格式。
      • 请注意@onemasse 的评论,但是,很多 JPEG 是 Exif,而不是 JFIF,例如许多用数码相机拍摄的 JPEG,许多从 Photoshop 保存的 JPEG(这意味着很多 JPEG在网上找到)等。这是基于我的个人经验,但这里还有更多:en.wikipedia.org/wiki/JPEG_File_Interchange_Format.
      【解决方案6】:

      JPG 文件确实有一个特定的标题,您可以使用它来确定它是 JPG 文件的可能性很大。但是,尚不清楚您是否会将整个文件放在字节数组中。

      无论如何,这是标题的详细信息:http://www.fastgraph.com/help/jpeg_header_format.html

      【讨论】:

      • 有趣的是,您的链接以“严格来说,JPEG 文件没有正式标题”开头。XD
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-03
      • 2017-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-29
      相关资源
      最近更新 更多