0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

为什么IE中的图像会变成x?

Posted at

在网上我们经常看见以.jpg为扩展名的文件,却有着gif图片的特征,绘声绘色的在浏览器里帧帧重绘。当然这是在理想的情况下,如果我们使用IE浏览器,就会发现图片只能显示成一个小红x,任凭怎样刷新都无法显示。

ddd.png

ddddd.png

造成这样的结果并不是一种原因,当我们将文件的后缀名修改时,实际上文件内容并没有发生改变,比如用笔记本打开修改扩展名为JPG的GIF文件,会发现它们都拥有相同的文件头,GIF87a,而这是GIF文件通用的文件头。

wfeeeee.png

不过有幸我们能够通过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中均有存在,当然国内使用IE8内核的360安全浏览器里也有这样的情况了。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?