当前位置:

首页 > 编程开发 > 如何获知页面上的图象的实际尺寸?

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

页面图像的实际尺寸因格式而异:GIF尺寸存于文件头第6至9字节,小端序存储;JPEG需定位FFC0等SOF标记段读取;PNG从IHDR数据块前8字节获取,大端序。ASP代码通过文件系统对象解析二进制文件提取宽高。

在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]

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
作者最新文章
编程开发
上一篇: 图像图表
相关文章 更多
Claude Code入门:基础交互、上下文管理与功能扩展
Claude Code入门:基础交互、上下文管理与功能扩展

了解 Claude Code 的基础交互流程,包括文件生成确认、使用 /compact 管理对话上下文、通过 CLAUDE.md 设定项目规则以及调用技能复用输出格式,提升开发协作效率。

Visual Studio2022关闭编辑器滚动条代码缩略图设置
Visual Studio2022关闭编辑器滚动条代码缩略图设置

详细介绍在 Visual Studio 2022 中关闭编辑器垂直滚动条代码缩略图(地图模式)的具体操作方法,包含右键快捷路径与全局选项设置,帮助恢复紧凑清晰的传统滚动条。

Visual Studio2022生成项目安装包打包程序步骤
Visual Studio2022生成项目安装包打包程序步骤

详细介绍在 Visual Studio 2022 中使用官方 Microsoft Visual Studio Installer Projects 扩展生成 Windows 桌面应用程序安装包(.msi / setup.exe)的完整操作步骤与配置细节。

大地老师的Node.js怎么样
大地老师的Node.js怎么样

客观全面评析大地老师的Node.js教程:从技术栈覆盖、实战讲解风格到局限短板与进阶路径,帮助初学者和前端开发者客观评估是否适合自身学习需求。

MCP与CLI怎么选择?AI Agent工具接入方式比较
MCP与CLI怎么选择?AI Agent工具接入方式比较

在为大模型Agent接入外部工具时,是选择MCP的结构化参数定义,还是使用CLI的通用命令入口?本文通过图片筛选与上传的实际案例,分析两种方式在上下文开销、任务组合效率及安全风险上的差异,提供选型参考。

Codex从零开始怎么用?基础操作与工作流程
Codex从零开始怎么用?基础操作与工作流程

初次接触Codex不知从何下手?本文通过一个具体的HTML笔记应用案例,带你走完从建立项目、输入需求、批准执行到验收结果的完整流程,快速掌握Codex的基础使用方法。

junit怎么用才高效实用技巧与优化教程
junit怎么用才高效实用技巧与优化教程

学习如何通过结构化测试、精准断言和参数化设计提升JUnit测试效率,避免常见陷阱,实现高质量、可维护的单元测试代码。

klib是什么文件及其用途说明与打开方法
klib是什么文件及其用途说明与打开方法

遇到.klib文件打不开?它通常是Kotlin/Native的库文件而非普通文档。本文教你如何在Windows下确认文件来源、安全查看内部结构,以及开发者如何正确使用klib工具,避免误操作。

vue上传文件格式怎么设置及要求说明
vue上传文件格式怎么设置及要求说明

学习如何在Vue项目中设置文件上传格式限制。本文介绍使用HTML accept属性进行基础过滤,以及结合JavaScript进行严格后缀名校验的方法,确保只允许指定类型的文件被上传。

Visual Studio2017修改NuGet包缓存存放路径
Visual Studio2017修改NuGet包缓存存放路径

本文详细介绍在Visual Studio 2017中修改NuGet包全局缓存存放路径的实用方案,包括修改全局NuGet.Config文件、配置系统环境变量以及利用NTFS目录联接进行透明迁移,并提供验证与旧缓存清理步骤。

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

PDF教程
PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
Aperty macOS版
Aperty macOS版
macOS

Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

火山引擎 网页版
火山引擎 网页版
Windows/ macOS/ Linux

火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

立刻MV 网页版
立刻MV 网页版
Windows/ macOS/ Linux

立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

WINDOWS 更多
Maya(Autodesk Maya) Windows版
Maya(Autodesk Maya) Windows版
Windows

Autodesk Maya 是面向影视、电视、动画和游戏行业的专业三维制作软件,集多边形与 NURBS 建模、角色绑定、关键帧和动作捕捉动画、Bifrost 特效模拟、材质开发及 Arnold 渲染于一体,

Aperty Windows版
Aperty Windows版
Windows

Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

火山引擎 网页版
火山引擎 网页版
Windows/ macOS/ Linux

火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。