【发布时间】:2014-07-20 23:44:14
【问题描述】:
我一直在尝试解决 .NET(所有版本)本身不支持 TRUE 透明度的古老问题,在阅读了数千篇文章、问题/答案、论坛、msdn 文章等之后,却一无所获除了能够通过使用整个表单来做到这一点,其中没有可见的控件(参见http://www.codeproject.com/Articles/1822/Per-Pixel-Alpha-Blend-in-C)
我已经部分放弃了这种搜索,而是决定通过使用每个图形/文本直接绘制到表单上的 MDIParent/Client 情况来满足。
我遇到的问题是,当我保存透明度时,我最终会在任何阴影周围出现一个斑点,我认为(但不确定)是 PNG 正在以较低的分辨率保存或丢失Alpha 通道或其他东西,MakeTransparent(在此处插入颜色),只是不满意。如果你能说明这个过程哪里出了这么严重的错误……请告诉我。
输入图片
输出图像
我使用的代码如下:
Imports Graphics
Public Class PictureForm
Private Declare Auto Function BitBlt Lib "gdi32.dll" (ByVal _
hdcDest As IntPtr, ByVal nXDest As Integer, ByVal _
nYDest As Integer, ByVal nWidth As Integer, ByVal _
nHeight As Integer, ByVal hdcSrc As IntPtr, ByVal nXSrc _
As Integer, ByVal nYSrc As Integer, ByVal dwRop As _
System.Int32) As Boolean
Private Const SRCCOPY As Integer = &HCC0020
Public Graphic As Drawing.Graphics
Private Sub PictureForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Show()
Graphic = Me.CreateGraphics
Graphic.CompositingQuality = Drawing2D.CompositingQuality.HighQuality
Graphic.DrawImage(Image.FromFile("C:\Users\Daniel\Downloads\PNG-icon.png"), 35, 22)
Dim bmp As Bitmap = GetFormImage()
bmp.MakeTransparent(Color.White)
bmp.Save("test.png", System.Drawing.Imaging.ImageFormat.Png)
bmp.Dispose()
End Sub
Public Function GetFormImage() As Bitmap
' Get this form's Graphics object.
Dim me_gr As Drawing.Graphics = Me.CreateGraphics
' Make a Bitmap to hold the image.
Dim bm As New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height, me_gr)
Dim bm_gr As Drawing.Graphics = Drawing.Graphics.FromImage(bm)
Dim bm_hdc As IntPtr = bm_gr.GetHdc
' Get the form's hDC. We must do this after
' creating the new Bitmap, which uses me_gr.
Dim me_hdc As IntPtr = me_gr.GetHdc
' BitBlt the form's image onto the Bitmap.
BitBlt(bm_hdc, 0, 0, Me.ClientSize.Width, _
Me.ClientSize.Height, _
me_hdc, 0, 0, SRCCOPY)
me_gr.ReleaseHdc(me_hdc)
bm_gr.ReleaseHdc(bm_hdc)
' Return the result.
Return bm
End Function
End Class
此外,您会注意到第一张图像中的字母在输出中没有被渲染为透明。
【问题讨论】:
-
当您绘制到表单时,您将具有表单背景色(我猜是白色)的源图像合并到 PNG 的透明部分中,从而生成一个新图像。阴影结果不是白色或灰色,而是混合(RGB(234...239, 239, 239)),所以
MakeTransparent(White)不起作用。它确实适用于白色的字母。将 PNG 图像放入图片框并从那里编辑/保存(不需要 NativeMetods),它工作正常。保存的图像大小不同,但没有您显示的任何工件。 -
这个想法是能够有多个层,我可以四处移动。由于无法消除的人造背景,PictureBox 不允许这样做。我确实看到了一个很好的 bitblt 工作示例,它消除了所有透明区域并使用了表单的图像区域,它显示了相反的证据,即实际上可以清除所有透明区域。此外,即使我将背景设置为蓝色,我仍然会得到那个白色的斑点。清除字母表明我没有使用通常存储在 png 中的颜色索引。我不知道怎么做。
-
您没有使用图层 - 您将 PNG 与表单合并。 PNG 的透明度允许表单 BG 颜色成为 PNG 的一部分。 BitBlt 无法从表格中分辨出原件,因为您制作了它们。
-
是的,最终保存的是表单内容的 BitBlt,但是这似乎是使用透明度分层多个图像的唯一方法 --- 在设计模式下,每个层都是可移动的/等(如 Photoshop)。上面的代码被缩短以演示问题。我很想问如何对无限数量的图片框进行分层,但是每个人的问题一直被标记为“已解决”,声称解决方案在这里>>stackoverflow.com/questions/395256/…
-
让我发疯的是,我可以在 VB6 中做到这一点,但是 VS2012 仍然在伪造它 --- 人们声称使用 WPF 是多么容易,但 WPF 甚至没有一个PictureBox ...更不用说,您不能简单地双击该项目以转到它的代码...并且没有Form_Load事件等等等等。太可怕了。我正在考虑改用 Delphi。
标签: vb.net transparency gdi+ alphablending bitblt