vb.net 教程 5-14 图像处理之内存处理基础5

前端之家收集整理的这篇文章主要介绍了vb.net 教程 5-14 图像处理之内存处理基础5前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

通过前期的教程,大家对于通过像素来处理图像有了一定认识,那么为什么还需要继续学习复杂的内存处理呢?

当然,一切都是为了效率。

这一篇我们就来谈谈图像处理的效率问题。

正如我之前在 图像处理之像素处理的系列教程开头所说的,vb相对于vc对于处理图像之类都处于劣势,vc可以使用指针来处理内存,vb不行。

到了.net框架下,c#也可以使用指针,vb.net我试了下,还是可以的,但是使用指针读写的效率却比用一维数组还要略低,更比不上c#,当然造成这个的原因我还不太清楚。

但是既然同是在vb.net下处理图像,那么我们还是需要尽可能地使用高效率的方法。下面我就几种处理图像的方法做个对比,当然这几种方法名称是我自己想出来的。

使用以下代码之前,需要引用

  1. Imports System.Drawing.Imaging
  2. Imports System.Runtime.InteropServices

一维数组处理代码(同 vb.net 教程 5-14 图像处理之内存处理基础4):

  1. '一维数组处理代码
  2. 'http://blog.csdn.net/uruseibest
  3. Private Sub Button4_Click(sender As Object,e As EventArgs) Handles Button4.Click
  4.  
  5. Dim timeStart,timeEnd As DateTime
  6. Dim timeDiff As TimeSpan
  7.  
  8. timeStart = Now()
  9.  
  10. '定义目标图片
  11. Dim destImg As New Bitmap(sourceImg.Width,sourceImg.Height)
  12. '定义源BitmapData,锁定区域是整个图片,只需要读取模式,采用24RGB
  13. Dim sourceData As BitmapData = sourceImg.LockBits(New Rectangle(0,sourceImg.Width,sourceImg.Height),ImageLockMode.ReadOnly,PixelFormat.Format24bppRgb)
  14. '定义目标BitmapData,锁定区域是整个图片,只需要写入模式,采用24位RGB
  15. Dim destData As BitmapData = destImg.LockBits(New Rectangle(0,ImageLockMode.WriteOnly,PixelFormat.Format24bppRgb)
  16. '获得源BitmapData的起始指针位置
  17. Dim pSource As IntPtr = sourceData.Scan0
  18. '获得源BitmapData占用内存空间的总的字节数
  19. Dim allBytes As Integer = sourceData.Stride * sourceData.Height
  20. '定义数组,用来放置源BitmapData的数据
  21. Dim rgbvalues() As Byte
  22. ReDim rgbvalues(allBytes - 1)
  23. '把指针位置开始allBytes个字节数据拷贝到rgbvalues()数组中
  24. Marshal.Copy(pSource,rgbvalues,allBytes)
  25.  
  26. '数组中第一个字节的序号
  27. Dim pos As Integer = 0
  28. Dim R,G,B As Integer
  29. Dim avgValue As Integer
  30.  
  31. '先高度,后宽度
  32. For j As Integer = 0 To sourceData.Height - 1
  33. For i As Integer = 0 To sourceData.Width - 1
  34. '图片上(i,j)像素对应的蓝色分量值
  35. B = rgbvalues(pos)
  36. '图片上(i,j)像素对应的蓝色分量值
  37. G = rgbvalues(pos + 1)
  38. '图片上(i,j)像素对应的蓝色分量值
  39. R = rgbvalues(pos + 2)
  40. '这里使用的是均值法
  41. avgValue = (B + G + R) / 3
  42. '把求出的数据写回去
  43. rgbvalues(pos) = avgValue
  44. rgbvalues(pos + 1) = avgValue
  45. rgbvalues(pos + 2) = avgValue
  46. '终归是在一维数组里面取数据,向前推进3个字节
  47. pos = pos + 3
  48. Next
  49. '一行数据取完了,继续推进到下一行
  50. pos = pos + sourceData.Stride - sourceData.Width * 3
  51. Next
  52.  
  53. '获得目标BitmapData的起始指针位置
  54. Dim pDest As IntPtr = destData.Scan0
  55. '将数组的内容拷到pDest指针开始的内存
  56. Marshal.Copy(rgbvalues,pDest,allBytes)
  57. '不要忘了解锁
  58. sourceImg.UnlockBits(sourceData)
  59. destImg.UnlockBits(destData)
  60.  
  61. picDest.Image = destImg
  62.  
  63. timeEnd = Now
  64. timeDiff = timeEnd - timeStart
  65. ListBox1.Items.Add("一维数组:" & timeDiff.TotalMilliseconds)
  66. End Sub

二维数组处理代码

  1. '二维数组处理代码
  2. 'http://blog.csdn.net/uruseibest
  3. Private Sub Button7_Click(sender As Object,e As EventArgs) Handles Button7.Click
  4. Dim timeStart,timeEnd As DateTime
  5. Dim timeDiff As TimeSpan
  6.  
  7. timeStart = Now()
  8. Dim destImg As New Bitmap(sourceImg.Width,sourceImg.Height)
  9. Dim sourceData As BitmapData = sourceImg.LockBits(New Rectangle(0,PixelFormat.Format24bppRgb)
  10. Dim destData As BitmapData = destImg.LockBits(New Rectangle(0,PixelFormat.Format24bppRgb)
  11.  
  12. Dim pSource As IntPtr = sourceData.Scan0
  13. Dim allBytes As Integer = sourceData.Stride * sourceData.Height
  14. Dim rgbvalues1() As Byte
  15. ReDim rgbvalues1(allBytes - 1)
  16.  
  17. Marshal.Copy(pSource,rgbvalues1,allBytes)
  18.  
  19. Dim rgbvalues2(,) As Byte
  20. ReDim rgbvalues2(destData.Height - 1,destData.Stride - 1)
  21.  
  22. Dim pDestArray2 As IntPtr
  23. pDestArray2 = Marshal.UnsafeAddrOfPinnedArrayElement(rgbvalues2,0)
  24. Marshal.Copy(rgbvalues1,pDestArray2,allBytes)
  25.  
  26. Dim pos As Integer = 0
  27. Dim R,B As Integer
  28. Dim avgValue As Integer
  29.  
  30. For j As Integer = 0 To sourceData.Height - 1
  31. For i As Integer = 0 To sourceData.Width - 1
  32. B = rgbvalues2(j,i * 3)
  33. G = rgbvalues2(j,i * 3 + 1)
  34. R = rgbvalues2(j,i * 3 + 2)
  35. avgValue = (B + G + R) / 3
  36. rgbvalues2(j,i * 3) = avgValue
  37. rgbvalues2(j,i * 3 + 1) = avgValue
  38. rgbvalues2(j,i * 3 + 2) = avgValue
  39. Next
  40. Next
  41.  
  42. Marshal.Copy(pDestArray2,allBytes)
  43.  
  44. Dim pDest As IntPtr = destData.Scan0
  45. Marshal.Copy(rgbvalues1,allBytes)
  46.  
  47. sourceImg.UnlockBits(sourceData)
  48. destImg.UnlockBits(destData)
  49. picDest.Image = destImg
  50.  
  51. timeEnd = Now
  52.  
  53. timeDiff = timeEnd - timeStart
  54. ListBox1.Items.Add("二维数组:" & timeDiff.TotalMilliseconds)
  55. End Sub

非常之遗憾,我没有在.net中找到一维数组直接拷贝到二维数组的方法,我也没有尝试使用copymemory,有兴趣的朋友可以自己试一下。

内存指针处理代码

需要说明的是,.net2.0下面没有提供指针加减方法,需要引用.net 4.0 以上版本目标框架,直接在项目属性中调整后自动重启动项目即可。

  1. '内存指针处理代码
  2. 'http://blog.csdn.net/uruseibest
  3. Private Sub Button5_Click(sender As Object,e As EventArgs) Handles Button5.Click
  4.  
  5. Dim timeStart,PixelFormat.Format24bppRgb)
  6.  
  7. Dim allBytes As Integer = sourceData.Stride * sourceData.Height
  8. Dim rgbvalues() As Byte
  9. ReDim rgbvalues(allBytes - 1)
  10.  
  11. Dim pSource As IntPtr = sourceData.Scan0
  12. Dim pDest As IntPtr = destData.Scan0
  13. Marshal.Copy(pSource,allBytes)
  14. Marshal.Copy(rgbvalues,allBytes)
  15.  
  16. Dim pos As IntPtr = pDest
  17. Dim R,B As Integer
  18. Dim avgValue As Byte
  19. For j As Integer = 0 To sourceData.Height - 1
  20. For i As Integer = 0 To sourceData.Width - 1
  21.  
  22. B = Marshal.ReadByte(pos)
  23. G = Marshal.ReadByte(pos + 1)
  24. R = Marshal.ReadByte(pos + 2)
  25.  
  26.  
  27. avgValue = (B + G + R) / 3
  28. Marshal.WriteByte(pos,avgValue)
  29. Marshal.WriteByte(pos + 1,avgValue)
  30. Marshal.WriteByte(pos + 2,avgValue)
  31.  
  32. pos = pos + 3
  33. Next
  34. pos = pos + sourceData.Stride - sourceData.Width * 3
  35. Next
  36. sourceImg.UnlockBits(sourceData)
  37. destImg.UnlockBits(destData)
  38.  
  39. picDest.Image = destImg
  40.  
  41. timeEnd = Now
  42. timeDiff = timeEnd - timeStart
  43. ListBox1.Items.Add("指针处理:" & timeDiff.TotalMilliseconds)
  44. End Sub

内存指针处理代码中,采用了Marshal.ReadByte()和Marshal.WriteByte()直接读写内存,不过效率似乎和数组差不多。

像素处理代码

  1. '像素处理代码
  2. 'http://blog.csdn.net/uruseibest
  3. Private Sub Button8_Click(sender As Object,e As EventArgs) Handles Button8.Click
  4. Dim pSourceColor As Color
  5. Dim pDestColor As Color
  6.  
  7. Dim timeStart,timeEnd As DateTime
  8. Dim timeDiff As TimeSpan
  9.  
  10. timeStart = Now
  11. Dim destImg As New Bitmap(sourceImg.Width,sourceImg.Height)
  12. Dim R,B As Integer
  13. Dim gray As Integer
  14. For i As Integer = 0 To sourceImg.Width - 1
  15. For j As Integer = 0 To sourceImg.Height - 1
  16. pSourceColor = sourceImg.GetPixel(i,j)
  17. R = pSourceColor.R
  18. G = pSourceColor.G
  19. B = pSourceColor.B
  20. gray = (R + G + B) / 3
  21. pDestColor = Color.FromArgb(gray,gray,gray)
  22. destImg.SetPixel(i,j,pDestColor)
  23. Next
  24. Next
  25. picDest.Image = destImg
  26. timeEnd = Now
  27.  
  28. timeDiff = timeEnd - timeStart
  29. ListBox1.Items.Add("像素处理:" & timeDiff.TotalMilliseconds)
  30. End Sub


由于.net平台下C#和vb.NET很相似,本文也可以为C#爱好者提供参考。

学习更多vb.net知识,请参看 vb.net 教程 目录

猜你在找的VB相关文章