VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > vb >
  • vb.net 教程 5-14 图像处理之内存处理基础5

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。
通过前期的教程,大家对于通过像素来处理图像有了一定认识,那么为什么还需要继续学习复杂的内存处理呢?
 
当然,一切都是为了效率。
 
这一篇我们就来谈谈图像处理的效率问题。
 
正如我之前在 图像处理之像素处理 的系列教程开头所说的,vb相对于vc对于处理图像之类都处于劣势,vc可以使用指针来处理内存,vb不行。
 
到了.net框架下,c#也可以使用指针,vb.net我试了下,还是可以的,但是使用指针读写的效率却比用一维数组还要略低,更比不上c#,当然造成这个的原因我还不太清楚。
 
但是既然同是在vb.net下处理图像,那么我们还是需要尽可能地使用高效率的方法。下面我就几种处理图像的方法做个对比,当然这几种方法的名称是我自己想出来的。
 
使用以下代码之前,需要引用
 
 
 
Imports System.Drawing.Imaging  
Imports System.Runtime.InteropServices  
 
 
 
 
 
 
 
 
 
 
 
 
一维数组处理代码(同 vb.net 教程 5-14 图像处理之内存处理基础4):
 
    '一维数组处理代码
    'http://blog.csdn.net/uruseibest
    Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
 
        Dim timeStart, timeEnd As DateTime
        Dim timeDiff As TimeSpan
 
        timeStart = Now()
 
        '定义目标图片
        Dim destImg As New Bitmap(sourceImg.Width, sourceImg.Height)
        '定义源BitmapData,锁定区域是整个图片,只需要读取模式,采用24位RGB
        Dim sourceData As BitmapData = sourceImg.LockBits(New Rectangle(0, 0, sourceImg.Width, sourceImg.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb)
        '定义目标BitmapData,锁定区域是整个图片,只需要写入模式,采用24位RGB
        Dim destData As BitmapData = destImg.LockBits(New Rectangle(0, 0, sourceImg.Width, sourceImg.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb)
        '获得源BitmapData的起始指针位置
        Dim pSource As IntPtr = sourceData.Scan0
        '获得源BitmapData占用内存空间的总的字节数
        Dim allBytes As Integer = sourceData.Stride * sourceData.Height
        '定义数组,用来放置源BitmapData的数据
        Dim rgbvalues() As Byte
        ReDim rgbvalues(allBytes - 1)
        '把指针位置开始allBytes个字节数据拷贝到rgbvalues()数组中
        Marshal.Copy(pSource, rgbvalues, 0, allBytes)
 
        '数组中第一个字节的序号
        Dim pos As Integer = 0
        Dim R, G, B As Integer
        Dim avgValue As Integer
 
        '先高度,后宽度
        For j As Integer = 0 To sourceData.Height - 1
            For i As Integer = 0 To sourceData.Width - 1
                '图片上(i,j)像素对应的蓝色分量值
                B = rgbvalues(pos)
                '图片上(i,j)像素对应的蓝色分量值
                G = rgbvalues(pos + 1)
                '图片上(i,j)像素对应的蓝色分量值
                R = rgbvalues(pos + 2)
                '这里使用的是均值法
                avgValue = (B + G + R) / 3
                '把求出的数据写回去
                rgbvalues(pos) = avgValue
                rgbvalues(pos + 1) = avgValue
                rgbvalues(pos + 2) = avgValue
                '终归是在一维数组里面取数据,向前推进3个字节
                pos = pos + 3
            Next
            '一行数据取完了,继续推进到下一行
            pos = pos + sourceData.Stride - sourceData.Width * 3
        Next
 
        '获得目标BitmapData的起始指针位置
        Dim pDest As IntPtr = destData.Scan0
        '将数组的内容拷到pDest指针开始的内存
        Marshal.Copy(rgbvalues, 0, pDest, allBytes)
        '不要忘了解锁
        sourceImg.UnlockBits(sourceData)
        destImg.UnlockBits(destData)
 
        picDest.Image = destImg
 
        timeEnd = Now
        timeDiff = timeEnd - timeStart
        ListBox1.Items.Add("一维数组:" & timeDiff.TotalMilliseconds)
    End Sub
二维数组处理代码:
 
    '二维数组处理代码
    'http://blog.csdn.net/uruseibest
    Private Sub Button7_Click(sender As Object, e As EventArgs) Handles Button7.Click
        Dim timeStart, timeEnd As DateTime
        Dim timeDiff As TimeSpan
 
        timeStart = Now()
        Dim destImg As New Bitmap(sourceImg.Width, sourceImg.Height)
        Dim sourceData As BitmapData = sourceImg.LockBits(New Rectangle(0, 0, sourceImg.Width, sourceImg.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb)
        Dim destData As BitmapData = destImg.LockBits(New Rectangle(0, 0, sourceImg.Width, sourceImg.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb)
 
        Dim pSource As IntPtr = sourceData.Scan0
        Dim allBytes As Integer = sourceData.Stride * sourceData.Height
        Dim rgbvalues1() As Byte
        ReDim rgbvalues1(allBytes - 1)
 
        Marshal.Copy(pSource, rgbvalues1, 0, allBytes)
 
        Dim rgbvalues2(,) As Byte
        ReDim rgbvalues2(destData.Height - 1, destData.Stride - 1)
 
        Dim pDestArray2 As IntPtr
        pDestArray2 = Marshal.UnsafeAddrOfPinnedArrayElement(rgbvalues2, 0)
        Marshal.Copy(rgbvalues1, 0, pDestArray2, allBytes)
 
        Dim pos As Integer = 0
        Dim R, G, B As Integer
        Dim avgValue As Integer
 
        For j As Integer = 0 To sourceData.Height - 1
            For i As Integer = 0 To sourceData.Width - 1
                B = rgbvalues2(j, i * 3)
                G = rgbvalues2(j, i * 3 + 1)
                R = rgbvalues2(j, i * 3 + 2)
                avgValue = (B + G + R) / 3
                rgbvalues2(j, i * 3) = avgValue
                rgbvalues2(j, i * 3 + 1) = avgValue
                rgbvalues2(j, i * 3 + 2) = avgValue
            Next
        Next
 
        Marshal.Copy(pDestArray2, rgbvalues1, 0, allBytes)
 
        Dim pDest As IntPtr = destData.Scan0
        Marshal.Copy(rgbvalues1, 0, pDest, allBytes)
 
        sourceImg.UnlockBits(sourceData)
        destImg.UnlockBits(destData)
        picDest.Image = destImg
 
        timeEnd = Now
 
        timeDiff = timeEnd - timeStart
        ListBox1.Items.Add("二维数组:" & timeDiff.TotalMilliseconds)
    End Sub
非常之遗憾,我没有在.net中找到一维数组直接拷贝到二维数组的方法,我也没有尝试使用copymemory,有兴趣的朋友可以自己试一下。
 
内存指针处理代码:
 
需要说明的是,.net2.0下面没有提供指针加减方法,需要引用.net 4.0 以上版本目标框架,直接在项目属性中调整后自动重启动项目即可。
 
    '内存指针处理代码
    'http://blog.csdn.net/uruseibest
    Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
 
        Dim timeStart, timeEnd As DateTime
        Dim timeDiff As TimeSpan
 
        timeStart = Now()
        Dim destImg As New Bitmap(sourceImg.Width, sourceImg.Height)
        Dim sourceData As BitmapData = sourceImg.LockBits(New Rectangle(0, 0, sourceImg.Width, sourceImg.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb)
        Dim destData As BitmapData = destImg.LockBits(New Rectangle(0, 0, sourceImg.Width, sourceImg.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb)
 
        Dim allBytes As Integer = sourceData.Stride * sourceData.Height
        Dim rgbvalues() As Byte
        ReDim rgbvalues(allBytes - 1)
 
        Dim pSource As IntPtr = sourceData.Scan0
        Dim pDest As IntPtr = destData.Scan0
        Marshal.Copy(pSource, rgbvalues, 0, allBytes)
        Marshal.Copy(rgbvalues, 0, pDest, allBytes)
 
        Dim pos As IntPtr = pDest
        Dim R, G, B As Integer
        Dim avgValue As Byte
        For j As Integer = 0 To sourceData.Height - 1
            For i As Integer = 0 To sourceData.Width - 1
 
                B = Marshal.ReadByte(pos)
                G = Marshal.ReadByte(pos + 1)
                R = Marshal.ReadByte(pos + 2)
 
 
                avgValue = (B + G + R) / 3
                Marshal.WriteByte(pos, avgValue)
                Marshal.WriteByte(pos + 1, avgValue)
                Marshal.WriteByte(pos + 2, avgValue)
 
                pos = pos + 3
            Next
            pos = pos + sourceData.Stride - sourceData.Width * 3
        Next
        sourceImg.UnlockBits(sourceData)
        destImg.UnlockBits(destData)
 
        picDest.Image = destImg
 
        timeEnd = Now
        timeDiff = timeEnd - timeStart
        ListBox1.Items.Add("指针处理:" & timeDiff.TotalMilliseconds)
    End Sub
内存指针处理代码中,采用了Marshal.ReadByte()和Marshal.WriteByte()直接读写内存,不过效率似乎和数组差不多。
 
像素处理代码:
 
 
 
    '像素处理代码
    'http://blog.csdn.net/uruseibest
    Private Sub Button8_Click(sender As Object, e As EventArgs) Handles Button8.Click
        Dim pSourceColor As Color
        Dim pDestColor As Color
 
        Dim timeStart, timeEnd As DateTime
        Dim timeDiff As TimeSpan
 
        timeStart = Now
        Dim destImg As New Bitmap(sourceImg.Width, sourceImg.Height)
        Dim R, G, B As Integer
        Dim gray As Integer
        For i As Integer = 0 To sourceImg.Width - 1
            For j As Integer = 0 To sourceImg.Height - 1
                pSourceColor = sourceImg.GetPixel(i, j)
                R = pSourceColor.R
                G = pSourceColor.G
                B = pSourceColor.B
                gray = (R + G + B) / 3
                pDestColor = Color.FromArgb(gray, gray, gray)
                destImg.SetPixel(i, j, pDestColor)
            Next
        Next
        picDest.Image = destImg
        timeEnd = Now
 
        timeDiff = timeEnd - timeStart
        ListBox1.Items.Add("像素处理:" & timeDiff.TotalMilliseconds)
    End Sub
 
 
 
 
 
 
 
 
 
 
 
 
 
 
由于.net平台下C#和vb.NET很相似,本文也可以为C#爱好者提供参考。
 
学习更多vb.net知识,请参看 vb.net 教程 目录
 
 
 
 
 
 
————————————————
版权声明:本文为CSDN博主「VB.Net」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/uruseibest/article/details/70185603

相关教程