新闻详情

新闻详情

首页 / 资讯中心 / 详情

VB.NET 基于 GDI+ 生成高清缩略图:插值算法与 JPEG 压缩全解析

发布时间:2026/9/14 1:43:26来源:尧图网络
VB.NET 基于 GDI+ 生成高清缩略图:插值算法与 JPEG 压缩全解析
简介基于VB开发的图片缩略图生成与压缩程序源码目标明确主要面向对VB图像处理感兴趣的新手以及希望快速实现图片压缩与缩略图功能的开发人员。程序完整演示了从本地读取图片、按比例生成缩略图、设定压缩参数、保存输出结果的全过程可应用于批量生成缩略图、网站上传前图片压缩等实际场景。资源包共32个文件压缩后约286KB以vb源文件、resx资源文件、exe可执行程序、config配置和vbproj工程文件为主要构成相关注释清晰工程结构紧凑便于按模块研读和二次开发。已有351人学习浏览说明该案例在VB图像处理入门与借鉴方面具有一定热度。用户可获得一套可直接运行的VB工程覆盖界面交互设计、图片编码保存、异常处理与调试运行等关键环节结合源代码注释能较快掌握缩略图生成和图片压缩的核心写法也为后续自主开发图片处理工具提供现成的实现参考适合VB课程设计或日常工具开发时直接参考。1. 为什么 VB 生成缩略图还在被需要维护老一套 WinForms 图库系统时最烦的不是数据库慢而是用户直接上传 5MB 原图导致列表页卡死。给图片生成缩略图是对读图体验成本最低的优化。这份基于 VB 写的“图片生成缩略图”程序源码核心是用 GDI 把原图按比例绘制到新位图并保存附带完整注释适合刚从 VB6 转 VB.NET 的新手也适合需要快速做一个图片压缩工具的维护型开发人员。缩略图不等于简单把 PictureBox 拉小这里涉及插值算法、JPEG 质量参数和文件释放值得逐行看。程序老媛出品的一贯特点是亲测校正、质量保证拿它能省去不少排查时间。2. 缩略图生成的基础GDI 的 Graphics.DrawImage 与插值算法2.1 PictureBox 缩放不等于生成缩略图很多新手会把PictureBox.SizeMode StretchImage当成缩略图方案但这样只是改变了控件显示尺寸并没有生成新的图片文件。真要产生缩略图必须创建一个独立的目标位图用Graphics.DrawImage将原图画进去再Save到磁盘。PictureBox的 StretchImage 走的是控件绘制路径缩放质量受控件默认参数限制缩到 160×120 之后文字边缘会明显发虚而且你无法直接拿到压缩后的字节流。正确的做法是绕开控件直接操作System.Drawing。整个过程包括读取原图、计算目标尺寸、创建画布、设置插值模式、绘制、编码保存。下面先讲清楚画质相关的三个关键参数否则代码写得再多输出也是“能看但没法用”的图。2.2 决定缩放质量的三个 GDI 参数在System.Drawing.Drawing2D命名空间里与缩放画质直接相关的是InterpolationMode、SmoothingMode和PixelOffsetMode。这三者解决的问题完全不同插值模式决定缩放时像素怎么补齐平滑模式影响线条和边缘抗锯齿像素偏移模式决定绘制位置是否落在像素中心。参数常用枚举值作用建议InterpolationModeHighQualityBicubic / HighQualityBilinear / NearestNeighbor决定像素补齐方式影响缩放清晰度照片用 HighQualityBicubic像素图标用 NearestNeighborSmoothingModeHighQuality / AntiAlias / None控制线条抗锯齿对位图缩放影响较小生成透明 PNG 时设 HighQualityPixelOffsetModeHighQuality / Half / Default修正像素中心偏移避免出现半透明边缘透明图片建议 HighQualityHighQualityBicubic会参考周围 4×4 像素做加权在缩小场景下能保留更多细节但计算量也最大HighQualityBilinear只参考 2×2 像素速度更快但更容易出现锯齿和摩尔纹。对这个图片压缩工具来说选择HighQualityBicubic是通用性最好的方案。如果缩略图来源是二维码、验证码这种二值图反而应该用NearestNeighbor否则边缘会出现一圈灰边。注意这三个枚举都在System.Drawing.Drawing2D命名空间下使用前需要Imports System.Drawing.Drawing2D否则 VB.NET 编辑器会报未定义类型。2.3 先算比例再画图防止变形最常见的错误是拿到maxW和maxH后直接g.DrawImage(src, 0, 0, maxW, maxH)这样会把竖图压扁横图拉高。正确做法是先计算原宽高与目标上限的缩放比例取较小值并限制不允许放大Private Function CalcThumbSize(srcW As Integer, srcH As Integer, maxW As Integer, maxH As Integer) As Size 取两个比例中较小的保证缩略图完整落在最大矩形内 Dim ratio As Double Math.Min(maxW / srcW, maxH / srcH) If ratio 1.0 Then ratio 1.0 原图比目标小时不放大 Return New Size( Math.Max(1, CInt(Math.Round(srcW * ratio))), Math.Max(1, CInt(Math.Round(srcH * ratio))) ) End Function这段代码的关键在Math.Min(maxW / srcW, maxH / srcH)。横向缩放比例和纵向缩放比例取较小者能保证两个方向都不超出目标矩形。ratio 1.0时说明原图本身比目标还小缩略图场景下放大没有意义只会增加文件体积所以直接限制为1.0。Math.Max(1, ...)防止极端情况下计算结果是 0导致New Bitmap(0, 0)抛异常。需要注意 VB 的/是浮点除法\才是整数除法。这里必须用/否则maxW / srcW在整数除法下会得到截断值宽高比稍小于 1 时直接变成 0。调试时看到尺寸翻倍或全黑先检查是不是这里写成了反斜杠。2.4 最小可运行绘制流程拿到目标尺寸后最小绘制流程可以写成下面这个样子。这个结构会贯穿整个源码创建画布、设置质量参数、绘制、保存每一步都不能省。Using src As New Bitmap(sourcePath) Dim thumbSize As Size CalcThumbSize(src.Width, src.Height, 160, 120) Using thumb As New Bitmap(thumbSize.Width, thumbSize.Height) Using g As Graphics Graphics.FromImage(thumb) g.InterpolationMode Drawing2D.InterpolationMode.HighQualityBicubic g.Clear(Color.White) g.DrawImage(src, 0, 0, thumbSize.Width, thumbSize.Height) End Using thumb.Save(targetPath, Imaging.ImageFormat.Jpeg) End Using End UsingUsing是 .NET 的资源释放保证。Bitmap从文件加载时会锁定源文件只有Dispose后其他进程才能改写或删除Graphics是 GDI 句柄的封装不释放会造成句柄泄漏。DrawImage的重载参数是(Image, x, y, width, height)由于宽高比已经算过不会变形。g.Clear(Color.White)必须放在DrawImage之前它会把画布刷成白色同时解决透明 PNG 转 JPEG 时黑底的问题。2.5 透明通道和背景色的处理策略2.4 使用白色背景只是其中一种策略。生成 PNG 缩略图时可以不调用Clear让透明区域保留但保存成 JPEG 时必须先刷一层底色因为 JPEG 不支持 Alpha 通道。如果原图是带透明通道的 PNGDrawImage绘制时会与画布底色做 alpha 混合所以最终呈现的背景就是你设置的颜色而不是原图里的透明区域。这里有个容易忽略的细节PixelOffsetMode设为HighQuality后缩小透明图标偶尔会在边缘出现半透明像素导出成 JPG 后会变成一圈灰边。解决办法是先把画布底色设成与页面背景接近的颜色或者用PixelOffsetMode.Half让像素中心对齐。对图标类资源压缩这个参数比SmoothingMode影响更明显调试时可以先只改它对比输出文件。3. 源码拆解Form1.vb 里的图片加载、缩放与保存实现3.1 从 .sln 和 .vbproj 看这套源码的形态拿到源码包第一眼看到WindowsApp4.sln和WindowsApp4.vbproj可以确定这是 Visual Studio 的 VB.NET Windows Forms 应用不是 VB6 的.vbp工程。WindowsApp4是新建项目时的默认命名空间作者没有重命名但不影响编译运行。.vs文件夹是 VS 缓存obj和bin是编译输出这三个目录删除后重新生成即可不影响源码可用性。文件/目录作用能否删除WindowsApp4.sln / WindowsApp4.vbproj解决方案和项目入口否Form1.vb / Form1.Designer.vb主窗体逻辑与设计器生成代码否My Project程序集信息、设置、资源管理按需ResourceHome.png内置资源图片可能是示例图或按钮背景可替换bin / obj编译中间文件与输出程序集可删Form1.vb和Form1.Designer.vb的分离是有意设计Designer.vb由 IDE 维护保存按钮、PictureBox 等控件的属性设置手写逻辑应放在Form1.vb。新手经常直接改Designer.vb重新生成解决方案时被 IDE 覆盖找半天原因。真正的生成逻辑应该放在Form1.vb的按钮事件或独立函数里。3.2 核心逻辑加载原图并生成缩略图这类源码最核心的部分是一个可复用的生成函数。签名大致是GenerateThumbnail(srcPath, dstPath, maxW, maxH)传入源图片路径、目标路径和尺寸上限返回布尔值表示是否成功。完整实现如下Public Function GenerateThumbnail(srcPath As String, dstPath As String, maxW As Integer, maxH As Integer) As Boolean Try Using src As New Bitmap(srcPath) 读取原图 Dim ratio As Double Math.Min( maxW / src.Width, maxH / src.Height) If ratio 1.0 Then ratio 1.0 Dim tw As Integer Math.Max(1, CInt(Math.Round(src.Width * ratio))) Dim th As Integer Math.Max(1, CInt(Math.Round(src.Height * ratio))) Using thumb As New Bitmap(tw, th) 创建目标画布 Using g As Graphics Graphics.FromImage(thumb) g.InterpolationMode Drawing2D.InterpolationMode.HighQualityBicubic g.SmoothingMode Drawing2D.SmoothingMode.HighQuality g.PixelOffsetMode Drawing2D.PixelOffsetMode.HighQuality g.Clear(Color.White) g.DrawImage(src, 0, 0, tw, th) End Using If Not SaveJpeg(thumb, dstPath, 85L) Then Return False End Using End Using Return True Catch ex As Exception Debug.WriteLine(GenerateThumbnail: ex.Message) Return False End Try End FunctionNew Bitmap(srcPath)只接受 GDI 能解码的图片格式遇到损坏文件或 CMYK 的 TIFF 可能抛异常所以整段放在Try/Catch中并返回False。g.Clear(Color.White)必须在DrawImage之前否则刷色会覆盖绘制结果。三个质量参数与第二章参数表对应SaveJpeg是下一步要讲的质量控制函数。3.3 用 EncoderParameters 控制 JPEG 压缩比直接调thumb.Save(path, ImageFormat.Jpeg)虽然能保存但压缩质量走的是 GDI 默认值不可调生成的缩略图往往体积偏大。要控制图片压缩程度必须先找到 JPEG 编码器再传入EncoderParametersPrivate Function SaveJpeg(img As Bitmap, path As String, quality As Long) As Boolean Dim codec As ImageCodecInfo Nothing For Each c As ImageCodecInfo In ImageCodecInfo.GetImageEncoders() If c.FormatID.Equals(Imaging.ImageFormat.Jpeg.Guid) Then codec c Exit For End If Next If codec Is Nothing Then Return False Using eps As New Imaging.EncoderParameters(1) eps.Param(0) New Imaging.EncoderParameter( Imaging.Encoder.Quality, quality) img.Save(path, codec, eps) End Using Return True End FunctionGetImageEncoders()返回系统已注册的所有图片编码器包括 BMP、JPEG、PNG、TIFF 等。通过FormatID匹配比按MimeType字符串匹配稳定不会因为系统语言环境不同而失效。EncoderParameter(Encoder.Quality, quality)的第二个参数是Long类型范围 0 到 100。85L 是通用平衡点网页预览场景体积和画质都比较合适如果想更小可以降到 70L但会出现明显的压缩色块。3.4 从源码注释里最容易踩的坑我在检查这类源码时通常先看三个位置文件释放、透明背景、控件引用。首先Bitmap和Graphics必须用Using管理。漏掉文件释放时批量处理同一个目录会报“文件正由另一进程使用”必须重启程序才能解锁源图。其次透明 PNG 转 JPEG 前必须Clear画布。如果不调用默认底色是黑色透明区域会变成黑块。Clear(Color.White)是大多数预览场景的正确选择。第三不要直接把PictureBox.Image指向一个即将释放的Bitmap。控件只是持有引用底层图像被Dispose后下一次重绘会出现空白或异常。常见做法是在下一次加载前让控件继续保持旧引用或者对图像调用Clone后交给控件管理。3.5 把最大宽高与压缩质量暴露到窗体上固定 160×120 的源码只能算 demo实际使用时需要把参数暴露到界面上。常见做法是在窗体上加NumericUpDown控件控制最大宽高加TrackBar控制压缩质量。按钮事件里这样取值Dim ok As Boolean GenerateThumbnail( txtSource.Text, txtTarget.Text, CInt(nudMaxW.Value), CInt(nudMaxH.Value) )NumericUpDown.Value类型是Decimal传给 Integer 参数前必须CInt。TrackBar.Value本身就是 32 位整数可以直接传给SaveJpeg的质量参数替换掉写死的85L。把参数开放出来之后同一个工具既能生成 160×120 的列表缩略图也能生成 800×600 的详情页预览图不再需要为每种尺寸重新编译一次。4. 批量生成与缩略图验证的进阶技巧4.1 批量处理整个目录的循环写法单张处理后下一步自然是批量。遍历文件夹并调用GenerateThumbnail时建议先快速检查分辨率跳过原本就很小的小图Dim folder As String C:\Pictures For Each file As String In Directory.GetFiles(folder, *.jpg) Try Using probe As New Bitmap(file) If probe.Width 800 AndAlso probe.Height 800 Then Continue For End Using GenerateThumbnail(file, Path.Combine(folder, thumbs, Path.GetFileNameWithoutExtension(file) _thumb.jpg), 160, 120) Catch ex As Exception Debug.WriteLine(file : ex.Message) End Try NextGetFiles(folder, *.jpg)只匹配小写.jpg扩展名不匹配.jpeg。要支持多种格式可以把*.jpg、*.jpeg、*.png三个结果拼接再去重。文件数量上十万张时建议改用Directory.EnumerateFiles它边遍历边处理不会一次性把所有路径载入内存。Continue For会先跳出当前迭代同时Using块正确释放探针位图。4.2 修正手机相片的 EXIF 方向手机上传的图片经常出现“缩略图旋转 90 度”的问题。原因不在缩放而在于原图的 EXIF0x0112属性记录了拍摄方向Bitmap绘制时默认忽略它。处理方式是在绘制前把方向修正到像素上Private Sub FixOrientation(ByVal img As Bitmap) If Array.IndexOf(img.PropertyIdList, H112) 0 Then Exit Sub Dim v As Integer BitConverter.ToUInt16( img.GetPropertyItem(H112).Value, 0) Select Case v Case 3 : img.RotateFlip(RotateFlipType.Rotate180FlipNone) Case 6 : img.RotateFlip(RotateFlipType.Rotate90FlipNone) Case 8 : img.RotateFlip(RotateFlipType.Rotate270FlipNone) End Select End SubPropertyIdList是一个整型数组H112是 274 的十六进制写法表示方向属性。GetPropertyItem返回的Value前两个字节是小端序短整数1 表示无旋转3 表示 180 度6 表示需要顺时针旋转 90 度8 表示逆时针旋转 90 度。RotateFlip会修改原图像素必须在生成缩略图之前调用。这个函数对没有 EXIF 信息的截图不会产生副作用因为PropertyIdList不包含H112时直接退出。4.3 用代码验证生成结果而不是靠肉眼批量生成后用代码自检比一张张看快得多Using chk As New Bitmap(targetPath) Debug.Assert(chk.Width 160 AndAlso chk.Height 120) End Using If (New FileInfo(targetPath)).Length 1024 Then Debug.WriteLine(缩略图过小请检查原图是否有效) End If重新打开文件读取宽高能立刻发现尺寸计算是否被改坏文件小于 1KB 通常说明原图本身是纯色或读取失败。至于 Windows 资源管理器里不显示缩略图优先确认targetPath这张图能否用图片查看器打开能打开就是系统缩略图缓存问题和生成程序无关。outlook 不显示缩略图、pdf 缩略图补丁、solidworks 重新注册缩略图组件都属于另一个排查分支不要混在编码逻辑里。把缩略图目录加入资源管理器“大图标”视图后再对比原图与_thumb.jpg的字节数如果尺寸落在 160×120 以内且体积明显下降就说明生成环节没有问题。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Python字符串处理与编码优化实战指南 2026/9/14 2:28:30

Python字符串处理与编码优化实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
AI论文降重技术解析:千笔AI如何实现高效查重 2026/9/14 2:28:30

AI论文降重技术解析:千笔AI如何实现高效查重

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
大语言模型技术架构与商业化应用解析 2026/9/14 2:28:30

大语言模型技术架构与商业化应用解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
数学建模竞赛数据分析:从预处理到模型构建实战 2026/9/14 2:28:30

数学建模竞赛数据分析:从预处理到模型构建实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
纯JS实现植物大战僵尸:DOM游戏开发实战指南 2026/9/14 2:28:30

纯JS实现植物大战僵尸:DOM游戏开发实战指南

简介:这是一份面向前端初学者与JavaScript进阶学习者的趣味实践项目源码,聚焦游戏逻辑实现与DOM交互开发,帮助开发者在真实场景中掌握ES6语法、面向对象编程、事件驱动机制及基础动画控制。资源包含364个文件,主体为22个核心JS脚本…

阅读更多 →
HI6421 PMIC Linux驱动移植:从手册到设备树的完整实践 2026/9/14 2:25:29

HI6421 PMIC Linux驱动移植:从手册到设备树的完整实践

简介:面向嵌入式驱动开发者的Hi6421 PMIC驱动核心源码文件,适合需要理解电源管理集成电路软件控制、I2C/SPI通信及低功耗策略的研发场景。资源以RAR压缩包形式提供,压缩包内仅含1个C源文件,整体大小约1KB,属轻量级驱动…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞