You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在.NET中叠加显示两张50%透明度的大尺寸地图图片?

.NET双地图叠加显示与对齐实现方案

问题说明

我有两张约7000×10000像素的图片(旧地图与现代地图),需要在屏幕上叠加显示,后续要通过旋转、拖拽边角完成对齐。尝试过两种方案均未达到预期:

  • 将可编辑图片放入Opacity为0.5的PictureBox,固定图片设为Form背景,结果仅能看到PictureBox的半透明图片
  • 使用两个尺寸、位置完全相同的PictureBox,各加载50%透明度的图片,结果仅能看到顶层的图片

参考Paint.Net的图层机制,寻求.NET下的可行实现方法,以下是我当前的代码:

当前代码

Dim imageData As New BldData 

Public Sub CreateImg(fnd As String, fnm As String)
    PiBxForgr.BringToFront()
    PiBxBackgr.SendToBack()
    Me.BackColor = Color.Red
    PiBxBackgr.SizeMode = PictureBoxSizeMode.Zoom
    Dim bckgrFileInfo = New FileInfo(fnm) ' 背景图
    If File.Exists(bckgrFileInfo.FullName) Then
        Dim bitMap = New Drawing.Bitmap(bckgrFileInfo.FullName)
        Dim shownRect = New Rectangle(0, 0, bitMap.Width, bitMap.Height)
        imageData.bitMapBackgr = bitMap.Clone(shownRect, bitMap.PixelFormat)
    End If
    Dim frgrFileInfo = New FileInfo(fnd) ' 前景图
    If File.Exists(frgrFileInfo.FullName) Then
        imageData.bitMap = New Drawing.Bitmap(frgrFileInfo.FullName)
        imageData.shownRect = New Rectangle(0, 0, imageData.bitMap.Width, imageData.bitMap.Height)
        rePaint()
    End If
    imageLoaded = True
End Sub
Private Sub rePaint()
    PiBxForgr.SizeMode = PictureBoxSizeMode.Zoom
    imageData.bitMapForgr = imageData.bitMap.Clone(imageData.shownRect, imageData.bitMap.PixelFormat)
    PiBxBackgr.Image = SetImageOpacity(imageData.bitMapBackgr, 0.5)
    PiBxForgr.Image = SetImageOpacity(imageData.bitMapForgr, 0.5)
End Sub
Private Function SetImageOpacity(image As Image, opacity As Double) As Image
    Dim bmp As New Bitmap(image.Width, image.Height)
    Using gfx As Graphics = Graphics.FromImage(bmp)
        Dim matrix As New ColorMatrix()
        matrix.Matrix33 = opacity ' 取值范围0.0到1.0
        Dim attributes As New ImageAttributes()
        attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap)
        gfx.DrawImage(image, New Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes)
    End Using
    Return bmp
End Function

Class BldData
    Friend bitMap As Bitmap ' 文件中的原始/旋转/变形图片
    Friend bitMapForgr As Bitmap ' 屏幕显示的前景图
    Friend bitMapBackgr As Bitmap ' 背景图
    Friend shownMap As Rectangle ' 显示的图片区域
    Friend scale As Integer ' 总尺寸/显示尺寸比例
    Friend shownmapOrgWidth As Integer
    ... 其他属性 ....
End Class

解决方案

核心思路:自定义绘制替代PictureBox叠加

放弃双PictureBox方案,改用在单个控件(或Form)的Paint事件中直接绘制两张半透明图片,既能确保两张图正确叠加显示,也方便后续添加旋转、拖拽边角的交互逻辑。

修改实现步骤

  1. 移除两个PictureBox,改用一个Panel(或直接在Form上)绘制,设置控件的DoubleBuffered = True避免绘制闪烁。
  2. 在控件的Paint事件中,先绘制半透明背景图,再绘制半透明前景图,实现叠加效果。
  3. 保留原有的SetImageOpacity函数,继续用ColorMatrix处理图片透明度。

修改后关键代码示例

Dim imageData As New BldData

' 假设使用名为MainPanel的Panel作为绘制容器
Private Sub MainPanel_Paint(sender As Object, e As PaintEventArgs) Handles MainPanel.Paint
    ' 绘制背景图
    If imageData.bitMapBackgr IsNot Nothing Then
        Dim transparentBackImg = SetImageOpacity(imageData.bitMapBackgr, 0.5)
        e.Graphics.DrawImage(transparentBackImg, GetScaledRect(imageData.bitMapBackgr, MainPanel.ClientRectangle))
    End If
    ' 绘制前景图
    If imageData.bitMapForgr IsNot Nothing Then
        Dim transparentFrontImg = SetImageOpacity(imageData.bitMapForgr, 0.5)
        e.Graphics.DrawImage(transparentFrontImg, GetScaledRect(imageData.bitMapForgr, MainPanel.ClientRectangle))
    End If
End Sub

' 计算图片按比例缩放后的显示区域
Private Function GetScaledRect(img As Image, containerRect As Rectangle) As Rectangle
    Dim scaleRatio = Math.Min(containerRect.Width / img.Width, containerRect.Height / img.Height)
    Dim displayWidth = img.Width * scaleRatio
    Dim displayHeight = img.Height * scaleRatio
    Dim offsetX = (containerRect.Width - displayWidth) / 2
    Dim offsetY = (containerRect.Height - displayHeight) / 2
    Return New Rectangle(offsetX, offsetY, displayWidth, displayHeight)
End Function

' 保留原有的透明度处理函数
Private Function SetImageOpacity(image As Image, opacity As Double) As Image
    Dim bmp As New Bitmap(image.Width, image.Height)
    Using gfx As Graphics = Graphics.FromImage(bmp)
        Dim matrix As New ColorMatrix()
        matrix.Matrix33 = opacity
        Dim attributes As New ImageAttributes()
        attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap)
        gfx.DrawImage(image, New Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes)
    End Using
    Return bmp
End Function

后续交互扩展方向

  • 旋转前景图:可通过Graphics.RotateTransform在绘制时应用旋转,或预先生成旋转后的Bitmap。
  • 拖拽边角调整:通过鼠标事件跟踪边角位置,计算缩放、扭曲的变换矩阵,在Paint事件中应用变换后绘制前景图。

内容的提问来源于stack exchange,提问作者Martin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 20:13:15