首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VB >

撇开GDI+完美实现角度渐变,散分

2012-12-28 
抛开GDI+完美实现角度渐变,散分。之前利用GDI+实现了线性渐变、对称渐变、圆形渐变、菱形渐变的基本效果,对于

抛开GDI+完美实现角度渐变,散分。
之前利用GDI+实现了线性渐变、对称渐变、圆形渐变、菱形渐变的基本效果,对于角度渐变一直没有思路。最近偶尔灵感一来,何必一定要求助GDI+呢,结果仔细分析下,其实这个的数学过程也不是很复杂,完全可以自己去实现啊。
兴起之余,干脆都不用GDI+,角度渐变都能实现,线性、对称和圆形从数学上讲还要简单些。只有这个菱形渐变涉及到的图形学知识稍微多谢,暂时还没有实现算法的自我编码。

其实一旦自己写算法,就能明白一些软件为什么有某些选项,比如渐变里PS就有反向、防色等,这个防色从代码角度来说就是误差扩散,和图像由高位变为低位时那个算法原理一致,这就叫一通百通啊。

[img=http://www.cnblogs.com/images/cnblogs_com/laviewpbt/193120/t_%e4%b8%ba%e9%a2%9d%e5%a4%96%e9%][/img]

[解决办法]
欢迎共享
[解决办法]





[解决办法]



[解决办法]
看看晚上有没有时间,有时间给大家整理一个原汁原味的版本,就是完全是按照原始算法写的版本,不做优化,然后有兴趣的可以自己优化,看你们的优化能力如何。

[解决办法]
谢谢分享........
[解决办法]
没有优化能力的再次路过
[解决办法]
很强大
[解决办法]
这就叫专业!
[解决办法]
感谢分享
[解决办法]
该回复于2010-12-16 12:58:58被版主删除
[解决办法]
仰慕中。。。
[解决办法]
观赏,NB
[解决办法]
有博客园帐号的可以到这里下载
http://files.cnblogs.com/laviewpbt/AngleGradient.rar
没有的我直接贴代码,就是新建一个窗体,直接贴代码就可以运行的。



Option Explicit


Private Type RGBQUAD                '只有bibitcount为1,2,4时才有调色板
   Blue As Byte                     '蓝色分量
   Green As Byte                    '绿色分量
   Red As Byte                      '红色分量
   Reserved As Byte                 '保留值
End Type

Private Type BITMAPINFOHEADER       '40 bytes
   biSize As Long                   'BITMAPINFOHEADER结构的大小
   biWidth As Long
   biHeight As Long
   biPlanes As Integer              '设备的为平面数,现在都是1
   biBitCount As Integer            '图像的颜色位图
   biCompression As Long            '压缩方式
   biSizeImage As Long              '实际的位图数据所占字节
   biXPelsPerMeter As Long          '目标设备的水平分辨率


   biYPelsPerMeter As Long          '目标设备的垂直分辨率
   biClrUsed As Long                '使用的颜色数
   biClrImportant As Long           '重要的颜色数。如果该项为0,表示所有颜色都是重要的
End Type


Private Declare Function SetDIBitsToDevice Lib "gdi32" (ByVal Hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal dx As Long, ByVal dy As Long, ByVal SrcX As Long, ByVal SrcY As Long, ByVal Scan As Long, ByVal NumScans As Long, Bits As Any, BitsInfo As BITMAPINFOHEADER, ByVal wUsage As Long) As Long
Private Declare Function GetTickCount Lib "kernel32" () As Long

Private Const DIB_RGB_COLORS = 0&
Private Const BI_RGB = 0&


Private LastX                   As Long
Private LastY                   As Long
Private StartX                  As Long
Private StartY                  As Long
Private MouseDown               As Boolean
Private BmpInfo                 As BITMAPINFOHEADER

Private m_Width                 As Long
Private m_Height                As Long
Private PixelData()             As Byte
Private Stride                  As Long


Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Button = vbLeftButton Then
        LastX = X
        LastY = Y
        StartX = X
        StartY = Y
        MouseDown = True
    End If
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If MouseDown = True Then
        Line (StartX, StartY)-(LastX, LastY)
        Line (StartX, StartY)-(X, Y)
        LastX = X
        LastY = Y
    End If
End Sub

Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)


    If MouseDown = True Then
        Dim ColorArray(3)       As RGBQUAD
        Dim PositonArrray(3)    As Single
        Dim t                   As Long
        ColorArray(0).Red = 0:
        ColorArray(0).Green = 0:
        ColorArray(0).Blue = 255:
        ColorArray(1).Red = 255:
        ColorArray(1).Green = 255:
        ColorArray(1).Blue = 255:
        ColorArray(2).Red = 0:
        ColorArray(2).Green = 255:
        ColorArray(2).Blue = 255:
        ColorArray(3).Red = 255:
        ColorArray(3).Green = 0:
        ColorArray(3).Blue = 0
        PositonArrray(0) = 0            '第一个最好为0
        PositonArrray(1) = 0.2
        PositonArrray(2) = 0.7
        PositonArrray(3) = 1           '最后一个最好为1,并且必须升序排列,且不能相等
        t = GetTickCount
        AngleGradient CLng(StartX), CLng(StartY), CLng(X), CLng(Y), ColorArray, PositonArrray()
        Me.Caption = GetTickCount - t
        MouseDown = False
    End If
    
End Sub

Private Sub Form_Load()
    Dim X   As Long
    m_Width = Me.ScaleWidth
    m_Height = Me.ScaleHeight
    Stride = m_Width * 4
    LastX = -1: LastY = -1
    ReDim PixelData(m_Width * m_Height * 4 - 1) As Byte
    With BmpInfo
        .biSize = Len(BmpInfo)
        .biWidth = m_Width
        .biHeight = -m_Height
        .biPlanes = 1
        .biBitCount = 32
        .biCompression = BI_RGB
    End With
    Me.ScaleMode = 3
    Me.DrawMode = 6         '反色笔
End Sub
  

Private Function AngleGradient(X1 As Long, Y1 As Long, X2 As Long, Y2 As Long, _


                            ColorArray() As RGBQUAD, PositionArray() As Single) As Boolean
    
    Dim Dx1             As Long, Dx2                As Long
    Dim Dy1             As Long, Dy2                As Long
    Dim Speed           As Long
    Dim StartAngle      As Double, EndAngle         As Double
    Dim Angle           As Double
    Dim DiffPosition    As Double
    Dim X               As Long, Y                  As Long
    Dim Z               As Long
    Dim Count           As Long

    Const Pi            As Double = 3.1415926
    Const HalfPi        As Double = Pi / 2
    Const TripplePi     As Double = 1.5 * Pi
    
    Count = UBound(ColorArray) - LBound(ColorArray)
    Dx2 = X2 - X1: Dy2 = Y1 - Y2                    '得到起始角度(以X1,Y1点位原点)
    If Dx2 > 0 Then                                 '
        StartAngle = Atn(Dy2 / Dx2)                 '位于第一第四象限(Atn函数范围的值为-PI/2到PI/2)
    ElseIf Dx2 < 0 Then
        StartAngle = Atn(Dy2 / Dx2) + Pi            '位于第二第三象限
    Else
        If Dy2 > 0 Then                             '特殊处理
            StartAngle = HalfPi
        Else
            StartAngle = TripplePi
        End If
    End If



   For Y = 0 To m_Height - 1
        Speed = Y * Stride '
        For X = 0 To m_Width - 1
            Dy1 = Y1 - Y
            Dx1 = X - X1
            If Dx1 < 0 Then                 '这里的计算公式是Index=(当前角度-StartAngle)/2/pi*4096,稍微做了优化
                EndAngle = Atn(Dy1 / Dx1) + Pi
            ElseIf Dx1 > 0 Then
                EndAngle = Atn(Dy1 / Dx1)
            Else
                If Dy1 > 0 Then
                    EndAngle = HalfPi
                Else
                    EndAngle = TripplePi
                End If
            End If
            Angle = EndAngle - StartAngle                   '计算和其实线条的角度差
            If Angle < 0 Then Angle = Angle + 2 * Pi        '修正下
            Angle = Angle / 2 / Pi                          '归一化
            If Angle >= PositionArray(Count) Then
                PixelData(Speed + 2) = ColorArray(Count).Red
                PixelData(Speed + 1) = ColorArray(Count).Green
                PixelData(Speed) = ColorArray(Count).Blue
            Else
                For Z = 0 To Count - 1
                    If Angle >= PositionArray(Z) And Angle < PositionArray(Z + 1) Then          '根据角度差来插值
                        DiffPosition = (Angle - PositionArray(Z)) / (PositionArray(Z + 1) - PositionArray(Z))


                        PixelData(Speed + 2) = (DiffPosition * (ColorArray(Z + 1).Red * 1& - ColorArray(Z).Red) + ColorArray(Z).Red)
                        PixelData(Speed + 1) = (DiffPosition * (ColorArray(Z + 1).Green * 1& - ColorArray(Z).Green) + ColorArray(Z).Green)
                        PixelData(Speed) = (DiffPosition * (ColorArray(Z + 1).Blue * 1& - ColorArray(Z).Blue) + ColorArray(Z).Blue)
                        Exit For
                    End If
                Next
            End If
            Speed = Speed + 4
        Next
    Next
    SetDIBitsToDevice Me.Hdc, 0, 0, m_Width, m_Height, 0, 0, 0, m_Height, PixelData(0), BmpInfo, DIB_RGB_COLORS
End Function



大家可以自己优化速度。
[解决办法]



[解决办法]
顶,效果不错。
[解决办法]
这里最关键的是渲染的算法 实际上知道算法以后 代码并不难 就是简单的数学运算用VB表现出来而已
[解决办法]
好东西哦
[解决办法]
感谢分享
[解决办法]
该回复于2010-12-16 17:33:24被版主删除
[解决办法]
  
  强人啊!


[解决办法]
好漂亮 可惜vb的 回来看着自己改吧。。。
[解决办法]
收藏~~
[解决办法]
这就叫专业
[解决办法]
哇塞,难得的洗礼啊~~
[解决办法]
该回复于2010-12-17 09:00:35被版主删除
[解决办法]
古得
[解决办法]
好强大
[解决办法]
该回复于2010-12-17 09:30:50被版主删除
[解决办法]
该回复于2010-12-17 09:03:49被版主删除
[解决办法]
之前利用GDI+实现了线性渐变、对称渐变、圆形渐变、菱形渐变的基本效果,对于角度渐变一直没有思路。最近偶尔灵感一来,何必一定要求助GDI+呢,结果仔细分析下,其实这个的数学过程也不是很复杂,完全可以自己去实现啊。


兴起之余,干脆都不用GDI+,角度渐变都能实现,线性、对称和圆形从数学上讲还要简单些。只有这个菱形渐变涉及到的图形学知识稍微多谢,暂时还没有实现算法的自我编码。
[解决办法]
该回复于2010-12-17 09:05:11被版主删除
[解决办法]
该回复于2010-12-17 09:05:11被版主删除
[解决办法]
感谢分享,不错,不错,真不错
[解决办法]
该回复于2010-12-17 09:05:10被版主删除
[解决办法]
用途是什么?
[解决办法]
感谢分享!
[解决办法]
呵呵,楼主挺牛的
[解决办法]
围观专家
[解决办法]
复用性问题,自己理解跟好。
[解决办法]
感谢分享
[解决办法]
该回复于2010-12-17 09:08:35被版主删除
[解决办法]
该回复于2010-12-17 09:10:41被版主删除
[解决办法]
该回复于2010-12-17 09:08:37被版主删除
[解决办法]
该回复于2010-12-17 09:08:36被版主删除
[解决办法]
昨天顶过了,居然又找不到了,再顶!
[解决办法]
牛人啊
[解决办法]
角度渐变是以当前点和两个取样点之间的夹角(0-360度之间)为依据进行插值的,而径向渐变则是以当前点于起点的距离和两个取样点距离之间的比值为依据进行插值的。对称渐变则是以当前点到垂直于两取样点,且经过起点的直线的距离和两取样点距离的比值为依据,且这个距离取的是正值。而线性渐变其实要比堆成渐变复杂些,还要判断距离的正负,也就是说要判断当前点和终点是否在直线的同一侧。

不过呢,这些都一些基本的集合知识,比如点到直线的距离,点在直线的那一侧啊等等,都不是很困难。
[解决办法]
该回复于2010-12-17 10:08:26被版主删除
[解决办法]
很好,谢谢楼主
[解决办法]
收藏一个
[解决办法]
这渐变,有啥用啊?谁需要这样的渐变啊?
[解决办法]
都是精品啊
[解决办法]

[解决办法]
该回复于2010-12-17 13:20:30被版主删除
[解决办法]
帮顶顶!

我在IDE里花了22秒.....
[解决办法]
很好很好
[解决办法]
都是牛人啊。。。
[解决办法]
顶啊~记得学OPENGL的时候,就学了下颜色渐变就是对颜色进行插值
[解决办法]

引用:
昨天顶过了,居然又找不到了,再顶
被顶飞了
[解决办法]
昨天顶过了,居然又找不到了,再顶
[解决办法]
感谢分享
------解决方案--------------------


戳 狠人
[解决办法]
我在(?墙)丶刻下你的名。
[解决办法]
我开始学win32,不知道什么时候能达到楼主的水平啊。
只能是仰止了!
[解决办法]
null
[解决办法]
null
[解决办法]
null
[解决办法]
null

热点排行