开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 3522|回复: 9
打印 上一主题 下一主题
收起左侧

[图文教程] 懒惰算法实现高速图像模糊(源代码)

[复制链接]

结帖率:67% (16/24)
跳转到指定楼层
楼主
发表于 2012-6-21 16:48:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式   广东省广州市
高速模糊.rar (7.88 KB, 下载次数: 68)
这个速度绝对一流,比这个论坛里的任何其他相关代码都块。

转载请保留作者信息。


'*****************************************************************************************
'**    函 数 名 :  FastBlur
'**    输    入 :  Radius   -   模糊的半径
'**    输    出 :  是否成功
'**    功能描述 :  普通的均值模糊
'**    开发日期 :  2008-1-17
'**    作    者 :  laviewpbt
'**    联系方式:   33184777
'**    修改日期 :  2008-5-22
'**    版    本 :  Version 1.3.1
'**    转载请不要删除以上信息
'****************************************************************************************

Public Function FastBlur(Optional ByVal Radius As Long = 3) As Boolean

    Dim x                   As Long, y                      As Long
    Dim Rad                 As Long, Circumference          As Long
    Dim SumRowRed           As Long, SumRowGreen            As Long
    Dim SumRowBlue          As Long, mPtrC                  As Long
    Dim Width               As Long, Height                 As Long
    Dim DataArr(0 To 2)     As Byte, pDataArr(0 To 0)       As Long
    Dim OldArrPtr           As Long, OldpArrPtr             As Long
    Dim DataArrC(0 To 2)    As Byte, pDataArrC(0 To 0)      As Long
    Dim OldArrPtrC          As Long, OldpArrPtrC            As Long
    Dim Left                As Long, Right                  As Long
    Dim Top                 As Long, Bottom                 As Long
    Dim TempT               As Long, TempB                  As Long
     
    If mHdc  <> 0 Or mBmpInfo.biBitCount = 32 Then
        If Radius  < 1 Then Radius = 1
        If Radius > 500 Then Radius = 500                   '修正参数范围
        Width = Me.Width: Height = Me.Height
        Rad = Radius
        Circumference = Rad * 2 + 1
         
        MakePoint VarPtrArray(DataArr), VarPtrArray(pDataArr), OldArrPtr, OldpArrPtr   '绑定模拟指针
        MakePoint VarPtrArray(DataArrC), VarPtrArray(pDataArrC), OldArrPtrC, OldpArrPtrC
        mPtrC = GlobalAlloc(GPTR, mBmpInfo.biSizeImage)                                 '因为模糊会破坏原来的像素,所以要是用一个备份
        CopyMemory ByVal mPtrC, ByVal mPtr, mBmpInfo.biSizeImage                        '复制图像数据
         
        ReDim SumRed(Width - 1) As Long
        ReDim SumGreen(Width - 1) As Long
        ReDim SumBlue(Width - 1) As Long
        ReDim SumNum(Width - 1) As Long         '有多少个像素参加了累加
         
        For x = 0 To Rad                '循环无需从-Rad to Rad ,因为我们明确知道在-Rad到0处图像无数据
            For y = 0 To Rad            '计算左上角第一个像素的模糊化值,记录下各颜色分量和有效像素数
                pDataArrC(0) = mPtrC + mWidthBytes * y + x * 4      '指向我们需要的数句在备份数据中的地址(首地址+高度*扫描行宽度+宽度*每像素字节数)
                SumRed(0) = SumRed(0) + DataArrC(2)                 '累加值
                SumGreen(0) = SumGreen(0) + DataArrC(1)
                SumBlue(0) = SumBlue(0) + DataArrC(0)
                SumNum(0) = SumNum(0) + 1                           '计数器加一
            Next
        Next
        pDataArr(0) = mPtr + 4                                      '指向原始数据待要修改点的地址
        DataArr(2) = SumRed(0) \ SumNum(0)                          '修改原始数据
        DataArr(1) = SumGreen(0) \ SumNum(0)
        DataArr(0) = SumBlue(0) \ SumNum(0)

'*********************************************第一阶段结束*******************************************
         
        For x = 1 To Width - 1                                      '计算第一行像素除(0,0)点外其他像素的模糊值
            Left = x - Rad - 1                                      '水平方向循环起始处
            Right = x + Rad                                         '水平方向循环终止处
            SumRed(x) = SumRed(x - 1)                               '先复制前一个像素点相关信息
            SumGreen(x) = SumGreen(x - 1)   '
            SumBlue(x) = SumBlue(x - 1)
            SumNum(x) = SumNum(x - 1)
            For y = 0 To Rad                                        '我们可以明确知道第一行像素在垂直方向上的领域只需从0开始
                If y  < Height Then                                  '防止在rad>Height的时候出错
                    If Left >= 0 Then                               '是有效的像素
                        pDataArrC(0) = mPtrC + mWidthBytes * y + Left * 4   '寻址
                        SumRed(x) = SumRed(x) - DataArrC(2)         '对第一行的其他像素,模糊值等于前一个像素的模糊值减去模糊区域最左侧还要左一个单位的总和然后加上最右侧区域的那列的模糊值
                        SumGreen(x) = SumGreen(x) - DataArrC(1)
                        SumBlue(x) = SumBlue(x) - DataArrC(0)
                        SumNum(x) = SumNum(x) - 1                   '计数器也要加1
                    End If
                    If Right  < Width Then
                        pDataArrC(0) = mPtrC + mWidthBytes * y + Right * 4  '加上最右侧那一列的像素(如果存在的话)
                        SumRed(x) = SumRed(x) + DataArrC(2)
                        SumGreen(x) = SumGreen(x) + DataArrC(1)
                        SumBlue(x) = SumBlue(x) + DataArrC(0)
                        SumNum(x) = SumNum(x) + 1                           '计数器也要加1
                    End If
                End If
            Next
            pDataArr(0) = mPtr + x * 4                              '计算要修改处的地址
            DataArr(2) = SumRed(x) \ SumNum(x)
            DataArr(1) = SumGreen(x) \ SumNum(x)
            DataArr(0) = SumBlue(x) \ SumNum(x)
        Next                                                        '至此,第一行像素的模糊值计算完毕
         
  '*********************************************第二阶段结束*******************************************
For y = 1 To Height - 1                 '从第二行开始算起了
            Top = y - Rad - 1
            Bottom = y + Rad
            SumRowRed = 0
            SumRowGreen = 0
            SumRowBlue = 0
            TempT = mPtrC + mWidthBytes * Top           '为了加快计算速度
            TempB = mPtrC + mWidthBytes * Bottom
            For x = 0 To Rad                            '计算每行的第一个像素的模糊值
                If x  < Width Then                       '在合理的范围内
                    If Top >= 0 Then                    '减去不在该像素领域的一行像素累加和
                        pDataArrC(0) = TempT + x * 4
                        SumRowRed = SumRowRed - DataArrC(2)     '等于上一行的像素模糊值减去最上行还上一行的像素值加上最下部的像素和
                        SumRowGreen = SumRowGreen - DataArrC(1)
                        SumRowBlue = SumRowBlue - DataArrC(0)
                        SumNum(0) = SumNum(0) - 1
                    End If
                    If Bottom  < Height Then             '加上新增像素的一行像素累加和
                        pDataArrC(0) = TempB + x * 4
                        SumRowRed = SumRowRed + DataArrC(2)
                        SumRowGreen = SumRowGreen + DataArrC(1)
                        SumRowBlue = SumRowBlue + DataArrC(0)
                        SumNum(0) = SumNum(0) + 1
                    End If
                End If
            Next
            SumRed(0) = SumRed(0) + SumRowRed
            SumGreen(0) = SumGreen(0) + SumRowGreen
            SumBlue(0) = SumBlue(0) + SumRowBlue
            pDataArr(0) = mPtr + mWidthBytes * y            '更新该点
            DataArr(2) = SumRed(0) \ SumNum(0)
            DataArr(1) = SumGreen(0) \ SumNum(0)
            DataArr(0) = SumBlue(0) \ SumNum(0)
            
            For x = 1 To Width - 1        '计算一行的其他像素
                Left = x - Rad - 1
                If Left >= 0 Then
                    If Top >= 0 Then
                        pDataArrC(0) = TempT + Left * 4         '加上新增领域的一列像素累加和
                        SumRowRed = SumRowRed + DataArrC(2)
                        SumRowGreen = SumRowGreen + DataArrC(1)
                        SumRowBlue = SumRowBlue + DataArrC(0)
                    End If
                    If Bottom  < Height Then
                        pDataArrC(0) = TempB + Left * 4         '减去不在该像素领域一列像素累加和
                        SumRowRed = SumRowRed - DataArrC(2)
                        SumRowGreen = SumRowGreen - DataArrC(1)
                        SumRowBlue = SumRowBlue - DataArrC(0)
                    End If
                End If
                          
                If Top  < 0 Then
                    If x >= Radius And x  < Width - Radius Then
                        SumNum(x) = SumNum(x) + Circumference   '移入一行像素数
                    ElseIf x  < Radius Then
                        SumNum(x) = SumNum(x) + Radius + x + 1
                    Else
                        SumNum(x) = SumNum(x) + Radius + (Width - x)
                    End If
                End If
                If Bottom >= Height Then
                    If x >= Radius And x  < Width - Radius Then
                        SumNum(x) = SumNum(x) - Circumference
                    ElseIf x  < Radius Then
                        SumNum(x) = SumNum(x) - (Radius + x + 1)    '移出一行像素
                    Else
                        SumNum(x) = SumNum(x) - (Radius + (Width - x))
                    End If
                End If
                 
                Right = x + Rad
                If Right  < Width Then
                    If Top >= 0 Then
                        pDataArrC(0) = TempT + Right * 4            '同样的道理
                        SumRowRed = SumRowRed - DataArrC(2)
                        SumRowGreen = SumRowGreen - DataArrC(1)
                        SumRowBlue = SumRowBlue - DataArrC(0)
                    End If
                    If Bottom  < Height Then
                        pDataArrC(0) = TempB + Right * 4
                        SumRowRed = SumRowRed + DataArrC(2)
                        SumRowGreen = SumRowGreen + DataArrC(1)
                        SumRowBlue = SumRowBlue + DataArrC(0)
                    End If
                End If
               
                SumRed(x) = SumRed(x) + SumRowRed
                SumGreen(x) = SumGreen(x) + SumRowGreen
                SumBlue(x) = SumBlue(x) + SumRowBlue
                  
                pDataArr(0) = pDataArr(0) + 4               '更新数据
                DataArr(2) = SumRed(x) \ SumNum(x)          '对于图像数据用右除足够了
                DataArr(1) = SumGreen(x) \ SumNum(x)
                DataArr(0) = SumBlue(x) \ SumNum(x)
            Next
        Next
        GlobalFree mPtrC                                    '释放内存
        FreePoint VarPtrArray(DataArr), VarPtrArray(pDataArr), OldArrPtr, OldpArrPtr        '释放模拟指针
        FreePoint VarPtrArray(DataArrC), VarPtrArray(pDataArrC), OldArrPtrC, OldpArrPtrC
        FastBlur = True
    End If
End Function




结帖率:0% (0/1)
沙发
发表于 2012-8-25 16:55:45 | 只看该作者   湖北省咸宁市
看看…………
回复 支持 反对

使用道具 举报

结帖率:40% (2/5)
板凳
发表于 2012-11-28 20:31:53 | 只看该作者   广东省深圳市
额,遇到高人了。。。

但是,最蛋疼还是。。。我不懂函数
回复 支持 反对

使用道具 举报

结帖率:40% (2/5)
地板
发表于 2012-11-28 20:33:02 | 只看该作者   广东省深圳市
更不懂VB。。无语了
回复 支持 反对

使用道具 举报

地下
发表于 2012-12-17 16:12:54 | 只看该作者   黑龙江省齐齐哈尔市
下下来研究下
回复 支持 反对

使用道具 举报

结帖率:94% (15/16)

签到天数: 3 天

6
发表于 2013-2-26 14:26:39 | 只看该作者   广东省深圳市
看不懂啊!~
回复 支持 反对

使用道具 举报

结帖率:100% (30/30)
7
发表于 2016-4-23 17:57:09 | 只看该作者   河南省安阳市
看到了一个转字
回复 支持 反对

使用道具 举报

8
发表于 2016-9-24 19:27:30 | 只看该作者   陕西省西安市
不错学习了。。。
回复 支持 反对

使用道具 举报

结帖率:75% (3/4)

签到天数: 8 天

9
发表于 2018-5-7 15:04:14 | 只看该作者   河北省石家庄市
还要这样的啊
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:[email protected]
网站简介:精易论坛成立于2009年,是一个程序设计学习交流技术论坛,隶属于揭阳市揭东区精易科技有限公司所有。
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表