商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > 如何获知页面上的图象的实际尺寸?

如何获知页面上的图象的实际尺寸?

  发布于2026-07-22 阅读(0)

扫一扫,手机访问

在Web开发中,经常会遇到这样一个问题:页面上显示的图片,实际尺寸到底是多少?虽然浏览器渲染后我们可以通过开发者工具查看,但当需要在服务端动态处理图片显示时,直接获取原始尺寸就成了一个绕不开的技术点。表面上看,这是个很简单的需求,但真要自己动手写代码去解析,里面涉及的图像格式细节还是挺有意思的。

其实,不同图像格式的尺寸信息,存储位置和编码方式各不相同。比如GIF文件,它的宽高信息存放在文件头的第6到第9个字节,而且是以小端序(low-endian)的方式存储的。而JPEG则是另一种玩法,尺寸信息隐藏在标记段中,需要先找到FFC0或FFC1这样的SOF标记,才能准确读出宽高。PNG更直接,IHDR数据块的前八个字节就是宽高,存放方式是大端序(big-endian)。

下面这段ASP代码,就是针对这些常见图像格式,逐一解析获取尺寸的完整实现。核心思路是利用文件系统对象(FileSystemObject)以文本方式读取二进制文件,然后根据格式规则提取关键字节,再转换成十进制。

如何获知页面上的图像的实际尺寸?

先看主调用的逻辑:




千花飞舞之获知图像尺寸


<%
  graphic="images/intels.gif"
  HW = ReadImg(graphic)
  Response.Write graphic & " Dimensions: " & HW(0) & "x" & HW(1) & "
" response.write "" %>

这段代码首先通过ReadImg函数获取图像尺寸,然后动态生成一个img标签,并设置宽高属性。注意这里有个小bug:heightwidth都赋了HW(0)的值,应该一个是高度一个是宽度,但这是示例代码,实际使用时需要修正。

接下来是核心的graphicdetect.asp文件,它包含了所有格式的判断和读取函数:

<%
Dim HW

Function AscAt(s, n)
    AscAt = Asc(Mid(s, n, 1))
End Function

Function HexAt(s, n)
    HexAt = Hex(AscAt(s, n))
End Function

Function isJPG(fichero)
    If inStr(uCase(fichero), ".JPG") <> 0 Then
        isJPG = true
    Else
        isJPG = false
    End If
End Function

Function isPNG(fichero)
    If inStr(uCase(fichero), ".PNG") <> 0 Then
        isPNG = true
    Else
        isPNG = false
    End If
End Function

Function isGIF(fichero)
    If inStr(uCase(fichero), ".GIF") <> 0 Then
        isGIF = true
    Else
        isGIF = false
    End If
End Function

Function isBMP(fichero)
    If inStr(uCase(fichero), ".BMP") <> 0 Then
        isBMP = true
    Else
        isBMP = false
    End If
End Function

Function isWMF(fichero)
    If inStr(uCase(fichero), ".WMF") <> 0 Then
        isWMF = true
    Else
        isWMF = false
    End If
End Function

Function isWebImg(f)
    If isGIF(f) Or isJPG(f) Or isPNG(f) Or isBMP(f) Or isWMF(f) Then
        isWebImg = true
    Else
        isWebImg = true
    End If
End Function

这里有一个值得注意的地方:isWebImg函数中,Else分支也返回了true,这显然是个逻辑错误,应该是false。不过对于整体功能来说,这个函数只是在主流程中做一次过滤,不太影响核心的尺寸读取。

主分发函数ReadImg根据文件扩展名,调用对应的格式读取函数:

Function ReadImg(fichero)
    If isGIF(fichero) Then
        ReadImg = ReadGIF(fichero)
    Else
        If isJPG(fichero) Then
            ReadImg = ReadJPG(fichero)
        Else
            If isPNG(fichero) Then
                ReadImg = ReadPNG(fichero)
            Else
                If isBMP(fichero) Then
                    ReadImg = ReadPNG(fichero)
                Else
                    If isWMF(fichero) Then
                        ReadImg = ReadWMF(fichero)
                    Else
                        ReadImg = Array(0,0)
                    End If
                End If
            End If
        End If
    End If
End Function

注意BMP格式的读取函数,这里误写成了ReadPNG,实际应该是ReadBMP。这种嵌套的If-Else结构虽然可读性差一些,但在早期ASP开发中很常见,毕竟当时没有Switch语句。

各格式的读取函数高度相似,核心都是通过FileSystemObject打开文件,读取特定字节数,然后提取宽高数据。以GIF格式为例:

Function ReadGIF(fichero)
    Dim fso, ts, s, HW, nbytes
    HW = Array("","")
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set ts = fso.OpenTextFile(Server.MapPath("/" & fichero), 1)
    s = Right(ts.Read(10), 4)
    HW(0) = HexToDec(HexAt(s,2) & HexAt(s,1))
    HW(1) = HexToDec(HexAt(s,4) & HexAt(s,3))
    ts.Close
    ReadGIF = HW
End Function

GIF的尺寸信息位于文件头偏移6和8处,各占2个字节,小端序存储。代码中先读取文件前10个字节,然后取后4个字节,再把每两个字节合并后通过HexToDec转换成十进制。注意这里的字节顺序:HexAt(s,2) & HexAt(s,1)是对宽度的高低位做了交换,这就是小端序的处理方式。

JPEG的读取方式略有不同,需要读取167个字节,然后取最后4个字节:

Function ReadJPG(fichero)
    Dim fso, ts, s, HW, nbytes
    HW = Array("","")
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set ts = fso.OpenTextFile(Server.MapPath("/" & fichero), 1)
    s = Right(ts.Read(167), 4)
    HW(0) = HexToDec(HexAt(s,3) & HexAt(s,4))
    HW(1) = HexToDec(HexAt(s,1) & HexAt(s,2))
    ts.Close
    ReadJPG = HW
End Function

这个读取方式比较取巧,直接假设了文件前167个字节中包含了SOF标记。对于标准的JPEG文件来说,这个假设通常是成立的,但如果文件包含大量缩略图或EXIF数据,可能会偏移。更稳健的做法应该是搜索FFC0标记,不过对于大多数场景,这个简化版本已经够用了。

PNG和BMP的读取方式类似,都是读取前24个字节,取后8个字节。不过PNG是大端序,而BMP是小端序,代码中已经通过不同的字节组合方式处理了这一点:

Function ReadPNG(fichero)
    Dim fso, ts, s, HW, nbytes
    HW = Array("","")
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set ts = fso.OpenTextFile(Server.MapPath("/" & fichero), 1)
    s = Right(ts.Read(24), 8)
    HW(0) = HexToDec(HexAt(s,3) & HexAt(s,4))
    HW(1) = HexToDec(HexAt(s,7) & HexAt(s,8))
    ts.Close
    ReadPNG = HW
End Function

最后是辅助函数HexToDec,用于将十六进制字符串转换为十进制数。它逐字符遍历,判断每个字符是否是合法的十六进制数字,然后累加计算:

Function HexToDec(cadhex)
    Dim n, i, ch, decimal
    decimal = 0
    n = Len(cadhex)
    For i=1 To n
        ch = Mid(cadhex, i, 1)
        If isHex(ch) Then
            decimal = decimal * 16
            If isDigit(c) Then
                decimal = decimal + ch
            Else
                decimal = decimal + Asc(uCase(ch)) - Asc("A")
            End If
        Else
            HexToDec = -1
        End If
    Next
    HexToDec = decimal
End Function

这里有一个小问题:If isDigit(c) Then中的c应该是ch,估计是笔误,但不影响理解。整体来看,这段代码虽然有些瑕疵,但核心思路清晰——通过文件系统直接解析二进制结构,获取图像尺寸。这在没有现代图像处理库的ASP时代,确实是一种非常实用的技术方案。

[1]

本文转载于:https://www.jb51.net/article/4772.htm 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注