如何识别一个byte[]中的内容是否为JPEG格式?

35

我有一个小的字节数组(小于25K),作为一个较大消息包的一部分接收并解码。有时候这是一张图片,而且它是JPG格式的。我没有其他上下文信息,只有这个字节数组,并且需要确定它是否是一张图片以及图片类型是否为JPG。

有没有某些神奇的数字或字节存在于开头、结尾或某个偏移量处,我可以查看以识别它呢?

我的代码示例类似于以下内容(从记忆中而非复制粘贴):

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

我非常需要填写在

areTheseBytesAJpeg(byte[] mBytes){}

我需要一个方法,或者一个指向详细说明的规范的指针。我希望有一种非常快速的方法来确定这一点,因为我不想将它们读入到图像中等等。

6个回答

62

1
所有谷歌 - 它甚至将其放在结果中:http://www.google.com/search?&q=jpg+magic+number - zsalzbank
好的。让我运行我的测试,然后我回来! - Kylar
那真是太好了!我的电脑一半是维基百科,一半是火狐浏览器。这可能是导致我的电脑变慢的原因。 - user257111
运行得非常好,完全符合我的要求。 - Kylar

22

关于与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();
    }
}

6
当JPG文件使用JFIF或EXIF格式时,它们的标识符不同: 原始格式:FF D8 FF DB; JFIF格式:FF D8 FF E0; EXIF格式:FF D8 FF E1。 - Gabriel Hautclocq
@GabrielHautclocq 谢谢!我已经更新了答案,提供了完整的信息。 - RATHI

9
另一个关于魔术数字(包括JPEG文件)的“知识”来源是GNU/Linux中使用的“file”命令的“magic”文件。如果您已安装“file”命令,则“file --version”将告诉您“magic”文件的位置,并且您可以使用文本编辑器阅读它...并仔细阅读“man 5 magic”。(“magic”文件的内容确认了其他答案的细节。)

6
引用维基百科文章的说法:
JPEG图像文件以FF D8开头,以FF D9结尾。JPEG / JFIF文件包含“JFIF”(4A 46 49 46)的ASCII代码作为空字符终止的字符串。JPEG / Exif文件包含“Exif”(45 78 69 66)的ASCII代码,也作为空字符终止的字符串,后跟有关文件的更多元数据。

2
请注意,有些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文件)。 - James Corcoran

4
许多格式都是通过所谓的魔数进行识别的。这些字节序列通常在文件前部,用于确定接下来的二进制数据是否确实是您想要的。一个快速的谷歌搜索返回了以下链接:http://www.linfo.org/magic_number.html,其中特别引用到:“同样,JPEG(Joint Photographic Experts Group)图像文件的常用魔数是0x4A464946,它是JFIF(JPEG文件交换格式)的ASCII等效形式。 然而,JPEG魔数不是文件中的第一个字节;而是从第七个字节开始。更多例子包括MIDI(音乐设备数字接口)文件的0x4D546864和bzip2压缩文件的0x425a6831415925。”

Jfif不一定与jpeg相同。尽管大多数人在说jpeg时实际上指的是jfif,因为他们认为它使用YUV作为颜色格式。 - onemasse
1
请注意@onemasse的评论,很多JPEG格式的照片是Exif而不是JFIF,例如许多数码相机拍摄的JPEG照片,从Photoshop保存的许多JPEG照片(这意味着在网上可以找到许多JPEG照片),等等。这基于我的个人经验,但在这里还有更多信息:http://en.wikipedia.org/wiki/JPEG_File_Interchange_Format。 - James Corcoran

0

JPG文件确实有一个特定的头部,您可以使用它来确定它是JPG文件的非常高的可能性。但是,如果您将整个文件存储在字节数组中并不清楚。

无论如何,以下是头部的具体信息:http://www.fastgraph.com/help/jpeg_header_format.html


很有趣,你的链接开头是“严格来说,JPEG文件没有正式的头部”XD。 - user1156544

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接