发布于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:height和width都赋了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]
上一篇:图像图表
下一篇:如何使图象随机显示?
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8