在网上我们经常看见以.jpg为扩展名的文件,却有着gif图片的特征,绘声绘色的在浏览器里帧帧重绘。当然这是在理想的情况下,如果我们使用IE浏览器,就会发现图片只能显示成一个小红x,任凭怎样刷新都无法显示。
造成这样的结果并不是一种原因,当我们将文件的后缀名修改时,实际上文件内容并没有发生改变,比如用笔记本打开修改扩展名为JPG的GIF文件,会发现它们都拥有相同的文件头,GIF87a,而这是GIF文件通用的文件头。

不过有幸我们能够通过webkit-like浏览器打开这张修改扩展名的gif图片,查看webkit源码我们就能发现,在webkit的
ImageDecoder模块,使用的正是写死文件头的方法进行判断图片解码:
bool matchesGIFSignature(char* contents) { return !memcmp(contents, "GIF87a", 6) || !memcmp(contents, "GIF89a", 6); } bool matchesPNGSignature(char* contents) { return !memcmp(contents, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8); } bool matchesJPEGSignature(char* contents) { return !memcmp(contents, "\xFF\xD8\xFF", 3); } if (matchesGIFSignature(contents)) return new GIFImageDecoder(alphaOption, gammaAndColorProfileOption);
而对比之下,firefox采用的Gecko引擎的判定方式就变得更加“web”了,它首先通过imgLoader.cpp通过比对文件头方式确定文件类型,然后再赋予他们一个MIMEType常量:
if (aLength >= 6 && (!nsCRT::strncmp(aContents, "GIF87a", 6) || !nsCRT::strncmp(aContents, "GIF89a", 6))) { aContentType.AssignLiteral("image/gif"); } /* or a PNG? */ else if (aLength >= 8 && ((unsigned char)aContents[0]==0x89 && (unsigned char)aContents[1]==0x50 && (unsigned char)aContents[2]==0x4E && (unsigned char)aContents[3]==0x47 && (unsigned char)aContents[4]==0x0D && (unsigned char)aContents[5]==0x0A && (unsigned char)aContents[6]==0x1A && (unsigned char)aContents[7]==0x0A)) { aContentType.AssignLiteral("image/png"); }
最后再通过Image.cpp判断MIMETYPE常量判断应该使用哪种解码器去解析,虽然使用MIMETYPE是非常“web”的方式,firefox也曾经声称自己的存在对web更有必要,但这显然是一个脱裤子放屁式的举动,尤其是当你看到Image目录结构和webkit条理清晰的Decoder/Encoder安排之后:
Image::GetDecoderType(const char *aMimeType) { // By default we don't know eDecoderType rv = eDecoderType_unknown; // PNG if (!strcmp(aMimeType, "image/png")) rv = eDecoderType_png; else if (!strcmp(aMimeType, "image/x-png")) rv = eDecoderType_png; // GIF else if (!strcmp(aMimeType, "image/gif")) rv = eDecoderType_gif; // JPEG else if (!strcmp(aMimeType, "image/jpeg")) rv = eDecoderType_jpeg; else if (!strcmp(aMimeType, "image/pjpeg")) rv = eDecoderType_jpeg; else if (!strcmp(aMimeType, "image/jpg")) rv = eDecoderType_jpeg; // BMP else if (!strcmp(aMimeType, "image/bmp")) rv = eDecoderType_bmp; else if (!strcmp(aMimeType, "image/x-ms-bmp")) rv = eDecoderType_bmp; // ICO else if (!strcmp(aMimeType, "image/x-icon")) rv = eDecoderType_ico; else if (!strcmp(aMimeType, "image/vnd.microsoft.icon")) rv = eDecoderType_ico; // Icon else if (!strcmp(aMimeType, "image/icon")) rv = eDecoderType_icon; return rv; }
了解了其他两种方式之后,我们再来看IE。虽然是黑盒我们看不到答案的来龙去脉,但获取头文件确定解码方式是现行的两种浏览器的主流方式,显然IE并没有这么做。通过右键图片属性的,很可能是通过文件协议直接读取扩展名,导致了原本是GIF的文件却通过JPG的编码方式读取,得到的结果必然是一张小红叉。
以上情况在
IE6 -
IE10中均有存在,当然其他使用IE内核的浏览器里也有这样的情况了。
via:lerous
标签:图片IE Web