home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / OldSrc / CH4 / SRC / FILTER.CLS < prev    next >
Encoding:
Text File  |  1997-01-03  |  37.1 KB  |  1,290 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "Filter"
  6. Attribute VB_Creatable = False
  7. Attribute VB_Exposed = False
  8. Option Explicit
  9.  
  10. Private Bound As Integer
  11. Private Kernel() As Single
  12. Private Wgt As Single
  13. Private Kind As Integer
  14.  
  15. ' Filter types.
  16. Const FILTER_NONE = 0
  17. Const FILTER_LOWPASS = 1
  18. Const FILTER_HIGHPASS = 2
  19. Const FILTER_PREWITT = 3
  20. Const FILTER_LAPLACIAN = 4
  21. Const FILTER_RANK_MIN = 5
  22. Const FILTER_RANK_MEDIAN = 6
  23. Const FILTER_RANK_MAX = 7
  24. Const FILTER_VOTING = 8
  25. Const FILTER_EMBOSS = 9
  26. Const FILTER_MORPHO = 10
  27. Const FILTER_ERODE_OUTLINE = 11
  28. Const FILTER_DILATE_OUTLINE = 12
  29.  
  30. ' Prewitt and embossing filter types.
  31. Const FILTER_UP = 0
  32. Const FILTER_UP_RIGHT = 1
  33. Const FILTER_RIGHT = 2
  34. Const FILTER_DOWN_RIGHT = 3
  35. Const FILTER_DOWN = 4
  36. Const FILTER_DOWN_LEFT = 5
  37. Const FILTER_LEFT = 6
  38. Const FILTER_UP_LEFT = 7
  39.  
  40. ' Morphological filter types.
  41. Const FILTER_EROSION = 10
  42. Const FILTER_DILATION = 11
  43.  
  44. ' ************************************************
  45. ' Apply a voting filter.
  46. ' ************************************************
  47. Private Sub ApplyVoting(from_pict As Object, to_pict As Object, show_progress As Boolean)
  48. Dim bm As BITMAP
  49. Dim hbm As Integer
  50. Dim status As Long
  51. Dim bytesin() As Byte
  52. Dim bytesout() As Byte
  53. Dim wid As Long
  54. Dim hgt As Long
  55. Dim i As Integer
  56. Dim j As Integer
  57. Dim k As Integer
  58.  
  59. Dim hPal As Integer
  60. Dim palentry(0 To 255) As PALETTEENTRY
  61. Dim x As Integer
  62. Dim y As Integer
  63. Dim arr_size As Integer
  64. Dim brightness() As Integer
  65. Dim index() As Integer
  66. Dim count() As Integer
  67. Dim value As Integer
  68. Dim idx As Integer
  69. Dim best_i As Integer
  70.  
  71.     ' *****************************
  72.     ' * Get the input bitmap data *
  73.     ' *****************************
  74.     ' Get a handle to the input bitmap.
  75.     hbm = from_pict.Image
  76.     
  77.     ' See how big it is.
  78.     status = GetObject(hbm, BITMAP_SIZE, bm)
  79.     wid = bm.bmWidthBytes
  80.     hgt = bm.bmHeight
  81.     
  82.     ' Get the bits.
  83.     ReDim bytesin(0 To wid - 1, 0 To hgt - 1)
  84.     status = GetBitmapBits(hbm, wid * hgt, bytesin(0, 0))
  85.     ReDim bytesout(0 To wid - 1, 0 To hgt - 1)
  86.     
  87.     ' ********************
  88.     ' * Apply the filter *
  89.     ' ********************
  90.     ' Get the current color values.
  91.     hPal = from_pict.Picture.hPal
  92.     i = GetPaletteEntries(hPal, 0, 255, palentry(0))
  93.  
  94.     ' Compute the new color values.
  95.     arr_size = 2 * Bound + 1
  96.     arr_size = arr_size * arr_size
  97.     ReDim brightness(1 To arr_size)
  98.     ReDim index(1 To arr_size)
  99.     ReDim count(1 To arr_size)
  100.     
  101.     For x = Bound To wid - 1 - Bound
  102.         ' If the operation has been canceled, stop.
  103.         DoEvents
  104.         If Not OperationRunning Then Exit For
  105.         
  106.         ' If we should show progress, do so.
  107.         If show_progress Then
  108.             status = SetBitmapBits(to_pict.Image, wid * hgt, bytesout(0, 0))
  109.             to_pict.Refresh
  110.         End If
  111.         
  112.         For y = Bound To hgt - 1 - Bound
  113.             ' Load values into the brightness and
  114.             ' index arrays.
  115.             idx = 0
  116.             For i = -Bound To Bound
  117.                 For j = -Bound To Bound
  118.                     With palentry(bytesin(x + i, y + j))
  119.                         value = CInt(.peRed) + .peGreen + .peBlue
  120.                     End With
  121.                     For k = 1 To idx
  122.                         If brightness(k) = value Then
  123.                             count(k) = count(k) + 1
  124.                             Exit For
  125.                         End If
  126.                     Next k
  127.                     If k > idx Then
  128.                         idx = idx + 1
  129.                         count(idx) = 1
  130.                         brightness(idx) = value
  131.                         index(idx) = bytesin(x + i, y + j)
  132.                     End If
  133.                 Next j
  134.             Next i
  135.             ' See which value got the most votes.
  136.             value = count(1)
  137.             best_i = 1
  138.             For i = 2 To idx
  139.                 If value < count(i) Then
  140.                     value = count(i)
  141.                     best_i = i
  142.                 End If
  143.             Next i
  144.             
  145.             ' Set the new pixel value.
  146.             bytesout(x, y) = index(best_i)
  147.         Next y
  148.     Next x
  149.     
  150.     ' **********************
  151.     ' * Display the output *
  152.     ' **********************
  153.     status = SetBitmapBits(to_pict.Image, wid * hgt, bytesout(0, 0))
  154.     to_pict.Refresh
  155. End Sub
  156.  
  157. ' ************************************************
  158. ' Apply a median filter.
  159. ' ************************************************
  160. Private Sub ApplyRank(from_pict As Object, to_pict As Object, show_progress As Boolean)
  161. Dim bm As BITMAP
  162. Dim hbm As Integer
  163. Dim status As Long
  164. Dim bytesin() As Byte
  165. Dim bytesout() As Byte
  166. Dim wid As Long
  167. Dim hgt As Long
  168. Dim i As Integer
  169. Dim j As Integer
  170.  
  171. Dim hPal As Integer
  172. Dim palentry(0 To 255) As PALETTEENTRY
  173. Dim x As Integer
  174. Dim y As Integer
  175. Dim arr_size As Integer
  176. Dim brightness() As Integer
  177. Dim index() As Integer
  178. Dim idx As Integer
  179. Dim tmp As Integer
  180. Dim best_brightness As Long
  181. Dim best_j As Integer
  182.  
  183.     ' *****************************
  184.     ' * Get the input bitmap data *
  185.     ' *****************************
  186.     ' Get a handle to the input bitmap.
  187.     hbm = from_pict.Image
  188.     
  189.     ' See how big it is.
  190.     status = GetObject(hbm, BITMAP_SIZE, bm)
  191.     wid = bm.bmWidthBytes
  192.     hgt = bm.bmHeight
  193.     
  194.     ' Get the bits.
  195.     ReDim bytesin(0 To wid - 1, 0 To hgt - 1)
  196.     status = GetBitmapBits(hbm, wid * hgt, bytesin(0, 0))
  197.     ReDim bytesout(0 To wid - 1, 0 To hgt - 1)
  198.     
  199.     ' ********************
  200.     ' * Apply the filter *
  201.     ' ********************
  202.     ' Get the current color values.
  203.     hPal = from_pict.Picture.hPal
  204.     i = GetPaletteEntries(hPal, 0, 255, palentry(0))
  205.  
  206.     ' Compute the new color values.
  207.     arr_size = 2 * Bound + 1
  208.     arr_size = arr_size * arr_size
  209.     ReDim brightness(1 To arr_size)
  210.     ReDim index(1 To arr_size)
  211.     
  212.     For x = Bound To wid - 1 - Bound
  213.         ' If the operation has been canceled, stop.
  214.         DoEvents
  215.         If Not OperationRunning Then Exit For
  216.         
  217.         ' If we should show progress, do so.
  218.         If show_progress Then
  219.             status = SetBitmapBits(to_pict.Image, wid * hgt, bytesout(0, 0))
  220.             to_pict.Refresh
  221.         End If
  222.         
  223.         For y = Bound To hgt - 1 - Bound
  224.             ' Load values into the brightness and
  225.             ' index arrays.
  226.             idx = 1
  227.             For i = -Bound To Bound
  228.                 For j = -Bound To Bound
  229.                     With palentry(bytesin(x + i, y + j))
  230.                         brightness(idx) = CInt(.peRed) + .peGreen + .peBlue
  231.                     End With
  232.                     index(idx) = bytesin(x + i, y + j)
  233.                     idx = idx + 1
  234.                 Next j
  235.             Next i
  236.             ' Sort the pixels by brightness.
  237.             For i = 1 To arr_size - 1
  238.                 best_brightness = brightness(i)
  239.                 best_j = i
  240.                 For j = i + 1 To arr_size
  241.                     If brightness(j) > brightness(i) Then
  242.                         best_brightness = brightness(j)
  243.                         best_j = j
  244.                     End If
  245.                 Next j
  246.                 ' Swap the i and best_j positions.
  247.                 brightness(best_j) = brightness(i)
  248.                 brightness(i) = best_brightness
  249.                 tmp = index(best_j)
  250.                 index(best_j) = index(i)
  251.                 index(i) = tmp
  252.             Next i
  253.             
  254.             ' Set output value based on rank.
  255.             Select Case Kind
  256.                 Case FILTER_RANK_MIN
  257.                     bytesout(x, y) = index(1)
  258.                 Case FILTER_RANK_MEDIAN
  259.                     bytesout(x, y) = index(5)
  260.                 Case FILTER_RANK_MAX
  261.                     bytesout(x, y) = index(9)
  262.             End Select
  263.         Next y
  264.     Next x
  265.     
  266.     ' **********************
  267.     ' * Display the output *
  268.     ' **********************
  269.     status = SetBitmapBits(to_pict.Image, wid * hgt, bytesout(0, 0))
  270.     to_pict.Refresh
  271. End Sub
  272.  
  273.  
  274. ' ************************************************
  275. ' Create an outline by subtracting an eroded image
  276. ' from the original.
  277. ' ************************************************
  278. Private Sub ApplyErodeOutline(from_pict As Object, to_pict As Object, show_progress As Boolean)
  279. Dim bm As BITMAP
  280. Dim hbm As Integer
  281. Dim status As Long
  282. Dim bytesin() As Byte
  283. Dim bytesout() As Byte
  284. Dim wid As Long
  285. Dim hgt As Long
  286. Dim i As Integer
  287. Dim j As Integer
  288. Dim c As Integer
  289.  
  290. Dim hPal As Integer
  291. Dim palentry(0 To 255) As PALETTEENTRY
  292. Dim x As Integer
  293. Dim y As Integer
  294.  
  295.     ' *****************************
  296.     ' * Get the input bitmap data *
  297.     ' *****************************
  298.     ' Get a handle to the input bitmap.
  299.     hbm = from_pict.Image
  300.     
  301.     ' See how big it is.
  302.     status = GetObject(hbm, BITMAP_SIZE, bm)
  303.     wid = bm.bmWidthBytes
  304.     hgt = bm.bmHeight
  305.     
  306.     ' Get the bits.
  307.     ReDim bytesin(0 To wid - 1, 0 To hgt - 1)
  308.     status = GetBitmapBits(hbm, wid * hgt, bytesin(0, 0))
  309.     ReDim bytesout(0 To wid - 1, 0 To hgt - 1)
  310.     
  311.     ' ********************
  312.     ' * Apply the filter *
  313.     ' ********************
  314.     ' Get the current color values.
  315.     hPal = from_pict.Picture.hPal
  316.     i = GetPaletteEntries(hPal, 0, 255, palentry(0))
  317.  
  318.     ' Do the erosion.
  319.     For x = Bound To wid - 1 - Bound
  320.         ' If the operation has been canceled, stop.
  321.         DoEvents
  322.         If Not OperationRunning Then Exit For
  323.         
  324.         ' If we should show progress, do so.
  325.         If show_progress Then
  326.             status = SetBitmapBits(to_pict.Image, wid * hgt, bytesout(0, 0))
  327.             to_pict.Refresh
  328.         End If
  329.         
  330.         For y = Bound To hgt - 1 - Bound
  331.             For i = -Bound To Bound
  332.                 For j = -Bound To Bound
  333.                     If palentry(bytesin(x + i, y + j)).peRed <> Kernel(i, j) Then Exit For
  334.                 Next j
  335.                 If j <= Bound Then Exit For
  336.             Next i
  337.             If j <= Bound Then
  338.                 c = bytesin(x, y) - (255 - Wgt)
  339.             Else
  340.                 c = bytesin(x, y) - Wgt
  341.             End If
  342.             If c < 0 Then c = 0
  343.             bytesout(x, y) = GetNearestPaletteIndex( _
  344.                 hPal, RGB(c, c, c) + &H2000000)
  345.         Next y
  346.     Next x
  347.         
  348.     ' **********************
  349.     ' * Display the output *
  350.     ' **********************
  351.     status = SetBitmapBits(to_pict.Image, wid * hgt, bytesout(0, 0))
  352.     to_pict.Refresh
  353. End Sub
  354.  
  355. ' ************************************************
  356. ' Display a message box describing dilated
  357. ' outlines.
  358. ' ************************************************
  359. Sub ShowDilateOutline()
  360.     MsgBox "This filter creates an outline by subtracting" & _
  361.         "the original image from a dilated version.", _
  362.         vbInformation, "Filter Values"
  363. End Sub
  364.  
  365. ' ************************************************
  366. ' Display a message box describing edoded
  367. ' outlines.
  368. ' ************************************************
  369. Sub ShowErodeOutline()
  370.     MsgBox "This filter creates an outline by " & _
  371.         "subtracting an eroded image from the original.", _
  372.         vbInformation, "Filter Values"
  373. End Sub
  374.  
  375.  
  376. ' ************************************************
  377. ' Create an outline by subtracting the original
  378. ' image from a dilated image.
  379. ' ************************************************
  380. Private Sub ApplyDilateOutline(from_pict As Object, to_pict As Object, show_progress As Boolean)
  381. Dim bm As BITMAP
  382. Dim hbm As Integer
  383. Dim status As Long
  384. Dim bytesin() As Byte
  385. Dim bytesout() As Byte
  386. Dim wid As Long
  387. Dim hgt As Long
  388. Dim i As Integer
  389. Dim j As Integer
  390. Dim c As Integer
  391.  
  392. Dim hPal As Integer
  393. Dim palentry(0 To 255) As PALETTEENTRY
  394. Dim x As Integer
  395. Dim y As Integer
  396.  
  397.     ' *****************************
  398.     ' * Get the input bitmap data *
  399.     ' *****************************
  400.     ' Get a handle to the input bitmap.
  401.     hbm = from_pict.Image
  402.     
  403.     ' See how big it is.
  404.     status = GetObject(hbm, BITMAP_SIZE, bm)
  405.     wid = bm.bmWidthBytes
  406.     hgt = bm.bmHeight
  407.     
  408.     ' Get the bits.
  409.     ReDim bytesin(0 To wid - 1, 0 To hgt - 1)
  410.     status = GetBitmapBits(hbm, wid * hgt, bytesin(0, 0))
  411.     ReDim bytesout(0 To wid - 1, 0 To hgt - 1)
  412.     
  413.     ' ********************
  414.     ' * Apply the filter *
  415.     ' ********************
  416.     ' Get the current color values.
  417.     hPal = from_pict.Picture.hPal
  418.     i = GetPaletteEntries(hPal, 0, 255, palentry(0))
  419.  
  420.     ' Do the erosion.
  421.     For x = Bound To wid - 1 - Bound
  422.         ' If the operation has been canceled, stop.
  423.         DoEvents
  424.         If Not OperationRunning Then Exit For
  425.         
  426.         ' If we should show progress, do so.
  427.         If show_progress Then
  428.             status = SetBitmapBits(to_pict.Image, wid * hgt, bytesout(0, 0))
  429.             to_pict.Refresh
  430.         End If
  431.         
  432.         For y = Bound To hgt - 1 - Bound
  433.             For i = -Bound To Bound
  434.                 For j = -Bound To Bound
  435.                     If palentry(bytesin(x + i, y + j)).peRed <> Kernel(i, j) Then Exit For
  436.                 Next j
  437.                 If j <= Bound Then Exit For
  438.             Next i
  439.             If j <= Bound Then
  440.                 c = (255 - Wgt) - bytesin(x, y)
  441.             Else
  442.                 c = Wgt - bytesin(x, y)
  443.             End If
  444.             If c < 0 Then c = 0
  445.             bytesout(x, y) = GetNearestPaletteIndex( _
  446.                 hPal, RGB(c, c, c) + &H2000000)
  447.         Next y
  448.     Next x
  449.         
  450.     ' **********************
  451.     ' * Display the output *
  452.     ' **********************
  453.     status = SetBitmapBits(to_pict.Image, wid * hgt, bytesout(0, 0))
  454.     to_pict.Refresh
  455. End Sub
  456.  
  457. ' ************************************************
  458. ' Apply a morphological filter.
  459. '
  460. ' Give the output pixel the value Wgt if the
  461. ' area's pixels match the kernel. Otherwise give
  462. ' it value 255 - Wgt.
  463. ' ************************************************
  464. Private Sub ApplyMorpho(from_pict As Object, to_pict As Object, show_progress As Boolean)
  465. Dim bm As BITMAP
  466. Dim hbm As Integer
  467. Dim status As Long
  468. Dim bytesin() As Byte
  469. Dim bytesout() As Byte
  470. Dim wid As Long
  471. Dim hgt As Long
  472. Dim i As Integer
  473. Dim j As Integer
  474. Dim c As Integer
  475.  
  476. Dim hPal As Integer
  477. Dim palentry(0 To 255) As PALETTEENTRY
  478. Dim x As Integer
  479. Dim y As Integer
  480.  
  481.     ' *****************************
  482.     ' * Get the input bitmap data *
  483.     ' *****************************
  484.     ' Get a handle to the input bitmap.
  485.     hbm = from_pict.Image
  486.     
  487.     ' See how big it is.
  488.     status = GetObject(hbm, BITMAP_SIZE, bm)
  489.     wid = bm.bmWidthBytes
  490.     hgt = bm.bmHeight
  491.     
  492.     ' Get the bits.
  493.     ReDim bytesin(0 To wid - 1, 0 To hgt - 1)
  494.     status = GetBitmapBits(hbm, wid * hgt, bytesin(0, 0))
  495.     ReDim bytesout(0 To wid - 1, 0 To hgt - 1)
  496.     
  497.     ' ********************
  498.     ' * Apply the filter *
  499.     ' ********************
  500.     ' Get the current color values.
  501.     hPal = from_pict.Picture.hPal
  502.     i = GetPaletteEntries(hPal, 0, 255, palentry(0))
  503.  
  504.     ' Compute the new color values.
  505.     For x = Bound To wid - 1 - Bound
  506.         ' If the operation has been canceled, stop.
  507.         DoEvents
  508.         If Not OperationRunning Then Exit For
  509.         
  510.         ' If we should show progress, do so.
  511.         If show_progress Then
  512.             status = SetBitmapBits(to_pict.Image, wid * hgt, bytesout(0, 0))
  513.             to_pict.Refresh
  514.         End If
  515.         
  516.         For y = Bound To hgt - 1 - Bound
  517.             For i = -Bound To Bound
  518.                 For j = -Bound To Bound
  519.                     If palentry(bytesin(x + i, y + j)).peRed <> Kernel(i, j) Then Exit For
  520.                 Next j
  521.                 If j <= Bound Then Exit For
  522.             Next i
  523.             If j <= Bound Then
  524.                 c = 255 - Wgt
  525.             Else
  526.                 c = Wgt
  527.             End If
  528.             bytesout(x, y) = GetNearestPaletteIndex( _
  529.                 hPal, RGB(c, c, c) + &H2000000)
  530.         Next y
  531.     Next x
  532.     
  533.     ' **********************
  534.     ' * Display the output *
  535.     ' **********************
  536.     status = SetBitmapBits(to_pict.Image, wid * hgt, bytesout(0, 0))
  537.     to_pict.Refresh
  538. End Sub
  539.  
  540.  
  541.  
  542.  
  543. ' ************************************************
  544. ' Apply an embossing filter. This is just like a
  545. ' normal filter except we add 127 to each new
  546. ' pixel value to give the image a gray background.
  547. ' ************************************************
  548. Private Sub ApplyEmboss(from_pict As Object, to_pict As Object, show_progress As Boolean)
  549. Dim bm As BITMAP
  550. Dim hbm As Integer
  551. Dim status As Long
  552. Dim bytesin() As Byte
  553. Dim bytesout() As Byte
  554. Dim wid As Long
  555. Dim hgt As Long
  556. Dim i As Integer
  557. Dim j As Integer
  558.  
  559. Dim hPal As Integer
  560. Dim palentry(0 To 255) As PALETTEENTRY
  561. Dim x As Integer
  562. Dim y As Integer
  563. Dim r As Long
  564. Dim g As Long
  565. Dim b As Long
  566.  
  567.     ' *****************************
  568.     ' * Get the input bitmap data *
  569.     ' *****************************
  570.     ' Get a handle to the input bitmap.
  571.     hbm = from_pict.Image
  572.     
  573.     ' See how big it is.
  574.     status = GetObject(hbm, BITMAP_SIZE, bm)
  575.     wid = bm.bmWidthBytes
  576.     hgt = bm.bmHeight
  577.     
  578.     ' Get the bits.
  579.     ReDim bytesin(0 To wid - 1, 0 To hgt - 1)
  580.     status = GetBitmapBits(hbm, wid * hgt, bytesin(0, 0))
  581.     ReDim bytesout(0 To wid - 1, 0 To hgt - 1)
  582.     
  583.     ' ********************
  584.     ' * Apply the filter *
  585.     ' ********************
  586.     ' Get the current color values.
  587.     hPal = from_pict.Picture.hPal
  588.     i = GetPaletteEntries(hPal, 0, 255, palentry(0))
  589.  
  590.     ' Compute the new color values.
  591.     For x = Bound To wid - 1 - Bound
  592.         ' If the operation has been canceled, stop.
  593.         DoEvents
  594.         If Not OperationRunning Then Exit For
  595.         
  596.         ' If we should show progress, do so.
  597.         If show_progress Then
  598.             status = SetBitmapBits(to_pict.Image, wid * hgt, bytesout(0, 0))
  599.             to_pict.Refresh
  600.         End If
  601.         
  602.         For y = Bound To hgt - 1 - Bound
  603.             r = 0
  604.             g = 0
  605.             b = 0
  606.             For i = -Bound To Bound
  607.                 For j = -Bound To Bound
  608.                     With palentry(bytesin(x + i, y + j))
  609.                         r = r + Kernel(i, j) * .peRed
  610.                         g = g + Kernel(i, j) * .peGreen
  611.                         b = b + Kernel(i, j) * .peBlue
  612.                     End With
  613.                 Next j
  614.             Next i
  615.             r = r / Wgt + 127
  616.             g = g / Wgt + 127
  617.             b = b / Wgt + 127
  618.             If r < 0 Then r = 0
  619.             If g < 0 Then g = 0
  620.             If b < 0 Then b = 0
  621.             bytesout(x, y) = GetNearestPaletteIndex( _
  622.                 hPal, RGB(r, g, b) + &H2000000)
  623.         Next y
  624.     Next x
  625.     
  626.     ' **********************
  627.     ' * Display the output *
  628.     ' **********************
  629.     status = SetBitmapBits(to_pict.Image, wid * hgt, bytesout(0, 0))
  630.     to_pict.Refresh
  631. End Sub
  632.  
  633.  
  634.  
  635. ' ************************************************
  636. ' Apply a normal filter.
  637. ' ************************************************
  638. Private Sub ApplyNormal(from_pict As Object, to_pict As Object, show_progress As Boolean)
  639. Dim bm As BITMAP
  640. Dim hbm As Integer
  641. Dim status As Long
  642. Dim bytesin() As Byte
  643. Dim bytesout() As Byte
  644. Dim wid As Long
  645. Dim hgt As Long
  646. Dim i As Integer
  647. Dim j As Integer
  648.  
  649. Dim hPal As Integer
  650. Dim palentry(0 To 255) As PALETTEENTRY
  651. Dim x As Integer
  652. Dim y As Integer
  653. Dim r As Long
  654. Dim g As Long
  655. Dim b As Long
  656.  
  657.     ' *****************************
  658.     ' * Get the input bitmap data *
  659.     ' *****************************
  660.     ' Get a handle to the input bitmap.
  661.     hbm = from_pict.Image
  662.     
  663.     ' See how big it is.
  664.     status = GetObject(hbm, BITMAP_SIZE, bm)
  665.     wid = bm.bmWidthBytes
  666.     hgt = bm.bmHeight
  667.     
  668.     ' Get the bits.
  669.     ReDim bytesin(0 To wid - 1, 0 To hgt - 1)
  670.     status = GetBitmapBits(hbm, wid * hgt, bytesin(0, 0))
  671.     ReDim bytesout(0 To wid - 1, 0 To hgt - 1)
  672.     
  673.     ' ********************
  674.     ' * Apply the filter *
  675.     ' ********************
  676.     ' Get the current color values.
  677.     hPal = from_pict.Picture.hPal
  678.     i = GetPaletteEntries(hPal, 0, 255, palentry(0))
  679.  
  680.     ' Compute the new color values.
  681.     For x = Bound To wid - 1 - Bound
  682.         ' If the operation has been canceled, stop.
  683.         DoEvents
  684.         If Not OperationRunning Then Exit For
  685.         
  686.         ' If we should show progress, do so.
  687.         If show_progress Then
  688.             status = SetBitmapBits(to_pict.Image, wid * hgt, bytesout(0, 0))
  689.             to_pict.Refresh
  690.         End If
  691.         
  692.         For y = Bound To hgt - 1 - Bound
  693.             r = 0
  694.             g = 0
  695.             b = 0
  696.             For i = -Bound To Bound
  697.                 For j = -Bound To Bound
  698.                     With palentry(bytesin(x + i, y + j))
  699.                         r = r + Kernel(i, j) * .peRed
  700.                         g = g + Kernel(i, j) * .peGreen
  701.                         b = b + Kernel(i, j) * .peBlue
  702.                     End With
  703.                 Next j
  704.             Next i
  705.             r = r / Wgt
  706.             g = g / Wgt
  707.             b = b / Wgt
  708.             If r < 0 Then r = 0
  709.             If g < 0 Then g = 0
  710.             If b < 0 Then b = 0
  711.             bytesout(x, y) = GetNearestPaletteIndex( _
  712.                 hPal, RGB(r, g, b) + &H2000000)
  713.         Next y
  714.     Next x
  715.     
  716.     ' **********************
  717.     ' * Display the output *
  718.     ' **********************
  719.     status = SetBitmapBits(to_pict.Image, wid * hgt, bytesout(0, 0))
  720.     to_pict.Refresh
  721. End Sub
  722.  
  723.  
  724.  
  725. ' ************************************************
  726. ' Display a message box giving the filter's
  727. ' dimensions.
  728. ' ************************************************
  729. Public Sub ShowVoting()
  730. Dim numstr As String
  731. Dim txt As String
  732.  
  733.     numstr = Format$(2 * Bound + 1)
  734.     txt = "This is a " & numstr & "x" & numstr & _
  735.         " voting filter."
  736.     MsgBox txt, vbInformation, "Filter Values"
  737. End Sub
  738. ' ************************************************
  739. ' Display a message box describing a morphological
  740. ' filter.
  741. ' ************************************************
  742. Public Sub ShowMorpho()
  743. Dim txt As String
  744. Dim numstr As String
  745. Dim maxlen As Integer
  746. Dim x As Integer
  747. Dim y As Integer
  748.  
  749.     ' See how long the biggest number is.
  750.     maxlen = 0
  751.     For y = -Bound To Bound
  752.         For x = -Bound To Bound
  753.             numstr = Format$(Kernel(x, y))
  754.             If maxlen < Len(numstr) Then maxlen = Len(numstr)
  755.         Next x
  756.     Next y
  757.  
  758.     ' Build the message to display.
  759.     For y = -Bound To Bound
  760.         For x = -Bound To Bound
  761.             numstr = Format$(Kernel(x, y))
  762.             txt = txt & _
  763.                 Space$(maxlen - Len(numstr)) & _
  764.                 numstr & " "
  765.         Next x
  766.         txt = txt & vbCrLf
  767.     Next y
  768.     
  769.     txt = txt & vbCrLf & _
  770.         "If all value match:" & Str$(Wgt)
  771.     txt = txt & vbCrLf & _
  772.         "Otherwise:         " & Str$(255 - Wgt)
  773.  
  774.     MsgBox txt, vbInformation, "Filter Values"
  775. End Sub
  776.  
  777. ' ************************************************
  778. ' Display a message box giving the filter's
  779. ' dimensions.
  780. ' ************************************************
  781. Public Sub ShowRank(rank_type As Integer)
  782. Dim numstr As String
  783. Dim typestr As String
  784. Dim txt As String
  785.  
  786.     numstr = Format$(2 * Bound + 1)
  787.     Select Case rank_type
  788.         Case 0
  789.             typestr = " minimum "
  790.         Case 1
  791.             typestr = " median "
  792.         Case 2
  793.             typestr = " maximum "
  794.     End Select
  795.     
  796.     txt = "This is a " & numstr & "x" & _
  797.         numstr & typestr & "filter."
  798.     MsgBox txt, vbInformation, "Filter Values"
  799. End Sub
  800.  
  801.  
  802. ' ************************************************
  803. ' Display a message box showing the filter's
  804. ' components and weight.
  805. ' ************************************************
  806. Public Sub ShowNormal()
  807. Dim txt As String
  808. Dim numstr As String
  809. Dim maxlen As Integer
  810. Dim x As Integer
  811. Dim y As Integer
  812.  
  813.     ' See how long the biggest number is.
  814.     maxlen = 0
  815.     For y = -Bound To Bound
  816.         For x = -Bound To Bound
  817.             numstr = Format$(Kernel(x, y), "0.00")
  818.             If maxlen < Len(numstr) Then maxlen = Len(numstr)
  819.         Next x
  820.     Next y
  821.  
  822.     ' Build the message to display.
  823.     For y = -Bound To Bound
  824.         For x = -Bound To Bound
  825.             numstr = Format$(Kernel(x, y), "0.00")
  826.             txt = txt & _
  827.                 Space$(maxlen - Len(numstr)) & _
  828.                 numstr & " "
  829.         Next x
  830.         txt = txt & vbCrLf
  831.     Next y
  832.     txt = txt & vbCrLf & "Weight:" & Str$(Wgt)
  833.  
  834.     MsgBox txt, vbInformation, "Filter Values"
  835. End Sub
  836.  
  837.  
  838.  
  839. ' ************************************************
  840. ' Display a message box describing the filter.
  841. ' ************************************************
  842. Public Sub ShowFilter()
  843.     Select Case Kind
  844.         Case FILTER_LOWPASS, FILTER_HIGHPASS, _
  845.              FILTER_PREWITT, FILTER_LAPLACIAN, _
  846.              FILTER_EMBOSS
  847.             ShowNormal
  848.     
  849.         Case FILTER_RANK_MIN
  850.             ShowRank 0
  851.         
  852.         Case FILTER_RANK_MEDIAN
  853.             ShowRank 1
  854.         
  855.         Case FILTER_RANK_MAX
  856.             ShowRank 2
  857.         
  858.         Case FILTER_VOTING
  859.             ShowVoting
  860.     
  861.         Case FILTER_MORPHO
  862.             ShowMorpho
  863.     
  864.         Case FILTER_ERODE_OUTLINE
  865.             ShowErodeOutline
  866.     
  867.         Case FILTER_DILATE_OUTLINE
  868.             ShowDilateOutline
  869.     End Select
  870. End Sub
  871.  
  872.  
  873.  
  874. ' ************************************************
  875. ' Initialize the filter based on its name.
  876. ' ************************************************
  877. Sub InitializeFilter(filtername As String)
  878.     Select Case filtername
  879.         Case "Average 3x3"
  880.             InitializeAverage 3
  881.         
  882.         Case "Low Pass 3x3"
  883.             InitializeLowPass 3
  884.         Case "Low Pass 5x5"
  885.             InitializeLowPass 5
  886.         Case "Low Pass 7x7"
  887.             InitializeLowPass 7
  888.             
  889.         Case "High Pass 1"
  890.             InitializeHighPass 1
  891.         Case "High Pass 2"
  892.             InitializeHighPass 2
  893.         Case "High Pass 3"
  894.             InitializeHighPass 3
  895.         Case "High Pass 4"
  896.             InitializeHighPass 4
  897.     
  898.         Case "Prewitt Up"
  899.             InitializePrewitt FILTER_UP
  900.         Case "Prewitt Up-Right"
  901.             InitializePrewitt FILTER_UP_RIGHT
  902.         Case "Prewitt Right"
  903.             InitializePrewitt FILTER_RIGHT
  904.         Case "Prewitt Down-Right"
  905.             InitializePrewitt FILTER_DOWN_RIGHT
  906.         Case "Prewitt Down"
  907.             InitializePrewitt FILTER_DOWN
  908.         Case "Prewitt Down-Left"
  909.             InitializePrewitt FILTER_DOWN_LEFT
  910.         Case "Prewitt Left"
  911.             InitializePrewitt FILTER_LEFT
  912.         Case "Prewitt Up-Left"
  913.             InitializePrewitt FILTER_UP_LEFT
  914.         
  915.         Case "Laplacian 1"
  916.             InitializeLaplacian 1
  917.         Case "Laplacian 2"
  918.             InitializeLaplacian 2
  919.     
  920.         Case "Minimum 3x3"
  921.             Kind = FILTER_RANK_MIN
  922.             Bound = 1
  923.         Case "Median 3x3"
  924.             Kind = FILTER_RANK_MEDIAN
  925.             Bound = 1
  926.         Case "Maximum 3x3"
  927.             Kind = FILTER_RANK_MAX
  928.             Bound = 1
  929.             
  930.         Case "Voting 3x3"
  931.             InitializeVoting 3
  932.         
  933.         Case "Emboss Up"
  934.             InitializeEmboss FILTER_UP
  935.         Case "Emboss Up-Right"
  936.             InitializeEmboss FILTER_UP_RIGHT
  937.         Case "Emboss Right"
  938.             InitializeEmboss FILTER_RIGHT
  939.         Case "Emboss Down-Right"
  940.             InitializeEmboss FILTER_DOWN_RIGHT
  941.         Case "Emboss Down"
  942.             InitializeEmboss FILTER_DOWN
  943.         Case "Emboss Down-Left"
  944.             InitializeEmboss FILTER_DOWN_LEFT
  945.         Case "Emboss Left"
  946.             InitializeEmboss FILTER_LEFT
  947.         Case "Emboss Up-Left"
  948.             InitializeEmboss FILTER_UP_LEFT
  949.     
  950.         ' Morphological filters.
  951.         Case "Erosion"
  952.             InitializeMorpho FILTER_EROSION
  953.         Case "Dilation"
  954.             InitializeMorpho FILTER_DILATION
  955.             
  956.         ' Outlines.
  957.         Case "Erosion Outline"
  958.             InitializeErodeOutline
  959.         Case "Dilation Outline"
  960.             InitializeDilateOutline
  961.     End Select
  962. End Sub
  963.  
  964.  
  965. ' ************************************************
  966. ' Apply the filter to an array of bits.
  967. ' ************************************************
  968. Public Sub ApplyFilter(from_pict As Object, to_pict As Object, show_progress As Boolean)
  969.     Select Case Kind
  970.         Case FILTER_NONE
  971.             Beep
  972.             MsgBox "This filter is undefined.", vbExclamation
  973.     
  974.         Case FILTER_LOWPASS, FILTER_HIGHPASS, _
  975.              FILTER_PREWITT, FILTER_LAPLACIAN
  976.             ApplyNormal from_pict, to_pict, show_progress
  977.         
  978.         Case FILTER_EMBOSS
  979.             ApplyEmboss from_pict, to_pict, show_progress
  980.     
  981.         Case FILTER_RANK_MEDIAN, FILTER_RANK_MIN, _
  982.              FILTER_RANK_MAX
  983.             ApplyRank from_pict, to_pict, show_progress
  984.     
  985.         Case FILTER_VOTING
  986.             ApplyVoting from_pict, to_pict, show_progress
  987.     
  988.         Case FILTER_MORPHO
  989.             ApplyMorpho from_pict, to_pict, show_progress
  990.     
  991.         Case FILTER_ERODE_OUTLINE
  992.             ApplyErodeOutline from_pict, to_pict, show_progress
  993.         
  994.         Case FILTER_DILATE_OUTLINE
  995.             ApplyDilateOutline from_pict, to_pict, show_progress
  996.     
  997.     End Select
  998. End Sub
  999. ' ************************************************
  1000. ' Initialize a high pass (sharpening) filter.
  1001. ' ************************************************
  1002. Public Sub InitializeHighPass(high_kind As Integer)
  1003. Dim r As Integer
  1004. Dim c As Integer
  1005.  
  1006.     Kind = FILTER_HIGHPASS
  1007.     Bound = 1
  1008.     ReDim Kernel(-Bound To Bound, -Bound To Bound)
  1009.     
  1010.     Select Case high_kind
  1011.         Case 1
  1012.             For r = -Bound To Bound
  1013.                 For c = -Bound To Bound
  1014.                     Kernel(r, c) = -1
  1015.                 Next c
  1016.             Next r
  1017.             Kernel(0, 0) = 9
  1018.             Wgt = 1
  1019.             
  1020.         Case 2
  1021.             Kernel(-1, -1) = 0
  1022.             Kernel(-1, 0) = -1
  1023.             Kernel(-1, 1) = 0
  1024.             Kernel(0, -1) = -1
  1025.             Kernel(0, 0) = 5
  1026.             Kernel(0, 1) = -1
  1027.             Kernel(1, -1) = 0
  1028.             Kernel(1, 0) = -1
  1029.             Kernel(1, 1) = 0
  1030.             Wgt = 1
  1031.         
  1032.         Case 3
  1033.             Kernel(-1, -1) = 1
  1034.             Kernel(-1, 0) = -2
  1035.             Kernel(-1, 1) = 1
  1036.             Kernel(0, -1) = -2
  1037.             Kernel(0, 0) = 5
  1038.             Kernel(0, 1) = -2
  1039.             Kernel(1, -1) = 1
  1040.             Kernel(1, 0) = -2
  1041.             Kernel(1, 1) = 1
  1042.             Wgt = 1
  1043.     
  1044.         Case 4
  1045.             For r = -Bound To Bound
  1046.                 For c = -Bound To Bound
  1047.                     Kernel(r, c) = -1
  1048.                 Next c
  1049.             Next r
  1050.             Kernel(0, 0) = 15
  1051.             Wgt = Kernel(0, 0) - 8
  1052.         
  1053.         Case Else
  1054.             ' Flag the filter as uninitialized.
  1055.             Kind = FILTER_NONE
  1056.             Wgt = 1
  1057.     
  1058.     End Select
  1059. End Sub
  1060.  
  1061. ' ************************************************
  1062. ' Initialize a voting filter.
  1063. ' ************************************************
  1064. Public Sub InitializeVoting(size As Integer)
  1065.     Kind = FILTER_VOTING
  1066.     Bound = size \ 2
  1067. End Sub
  1068.  
  1069. ' ************************************************
  1070. ' Initialize an averaging (blurring) filter.
  1071. ' ************************************************
  1072. Public Sub InitializeAverage(size As Integer)
  1073. Dim r As Integer
  1074. Dim c As Integer
  1075.  
  1076.     Kind = FILTER_LOWPASS
  1077.     Bound = size \ 2
  1078.     ReDim Kernel(-Bound To Bound, -Bound To Bound)
  1079.     
  1080.     For r = -Bound To Bound
  1081.         For c = -Bound To Bound
  1082.             Kernel(r, c) = 1
  1083.         Next c
  1084.     Next r
  1085.     Wgt = (2 * Bound + 1) * (2 * Bound + 1)
  1086. End Sub
  1087.  
  1088.  
  1089.  
  1090. ' ************************************************
  1091. ' Initialize a 3x3 Laplacian filter.
  1092. ' ************************************************
  1093. Public Sub InitializeLaplacian(laplacian_type As Integer)
  1094. Dim r As Integer
  1095. Dim c As Integer
  1096.  
  1097.     Kind = FILTER_LAPLACIAN
  1098.     Bound = 1
  1099.     ReDim Kernel(-Bound To Bound, -Bound To Bound)
  1100.     
  1101.     Select Case laplacian_type
  1102.         Case 1
  1103.             For r = -Bound To Bound
  1104.                 For c = -Bound To Bound
  1105.                     Kernel(r, c) = -1
  1106.                 Next c
  1107.             Next r
  1108.             Kernel(0, 0) = 8
  1109.         
  1110.         Case 2
  1111.             Kernel(-1, -1) = 0
  1112.             Kernel(0, -1) = -1
  1113.             Kernel(1, -1) = 0
  1114.             Kernel(-1, 0) = -1
  1115.             Kernel(0, 0) = 4
  1116.             Kernel(1, 0) = -1
  1117.             Kernel(-1, 1) = 0
  1118.             Kernel(0, 1) = -1
  1119.             Kernel(1, 1) = 0
  1120.         
  1121.     End Select
  1122.     Wgt = 1
  1123. End Sub
  1124.  
  1125. ' ************************************************
  1126. ' Initialize a 3x3 dilation filter for use when
  1127. ' creating an outline using dilation.
  1128. ' ************************************************
  1129. Public Sub InitializeDilateOutline()
  1130.     InitializeMorpho FILTER_DILATION
  1131.     Kind = FILTER_DILATE_OUTLINE
  1132. End Sub
  1133. ' ************************************************
  1134. ' Initialize a 3x3 erosion filter for use when
  1135. ' creating an outline using erosion.
  1136. ' ************************************************
  1137. Public Sub InitializeErodeOutline()
  1138.     InitializeMorpho FILTER_EROSION
  1139.     Kind = FILTER_ERODE_OUTLINE
  1140. End Sub
  1141.  
  1142.  
  1143.  
  1144.  
  1145. ' ************************************************
  1146. ' Initialize a 3x3 morphological filter.
  1147. ' ************************************************
  1148. Public Sub InitializeMorpho(morpho_type As Integer)
  1149. Dim r As Integer
  1150. Dim c As Integer
  1151.  
  1152.     Kind = FILTER_MORPHO
  1153.     Bound = 1
  1154.     ReDim Kernel(-Bound To Bound, -Bound To Bound)
  1155.     
  1156.     Select Case morpho_type
  1157.         Case FILTER_EROSION
  1158.             For r = -Bound To Bound
  1159.                 For c = -Bound To Bound
  1160.                     Kernel(r, c) = 255
  1161.                 Next c
  1162.             Next r
  1163.             Wgt = 255
  1164.             
  1165.         Case FILTER_DILATION
  1166.             For r = -Bound To Bound
  1167.                 For c = -Bound To Bound
  1168.                     Kernel(r, c) = 0
  1169.                 Next c
  1170.             Next r
  1171.             Wgt = 0
  1172.     End Select
  1173. End Sub
  1174.  
  1175.  
  1176.  
  1177. ' ************************************************
  1178. ' Initialize a 3x3 embossing filter.
  1179. ' ************************************************
  1180. Public Sub InitializeEmboss(emboss_type As Integer)
  1181. Dim r As Integer
  1182. Dim c As Integer
  1183.  
  1184.     Kind = FILTER_EMBOSS
  1185.     Bound = 1
  1186.     ReDim Kernel(-Bound To Bound, -Bound To Bound)
  1187.     
  1188.     For r = -Bound To Bound
  1189.         For c = -Bound To Bound
  1190.             Kernel(r, c) = 0
  1191.         Next c
  1192.     Next r
  1193.     
  1194.     Select Case emboss_type
  1195.         Case FILTER_UP
  1196.             Kernel(0, -1) = 1: Kernel(0, 1) = -1
  1197.         Case FILTER_UP_RIGHT
  1198.             Kernel(-1, 1) = -1: Kernel(1, -1) = 1
  1199.         Case FILTER_RIGHT
  1200.             Kernel(1, 0) = 1: Kernel(-1, 0) = -1
  1201.         Case FILTER_DOWN_RIGHT
  1202.             Kernel(-1, -1) = -1: Kernel(1, 1) = 1
  1203.         Case FILTER_DOWN
  1204.             Kernel(0, -1) = -1: Kernel(0, 1) = 1
  1205.         Case FILTER_DOWN_LEFT
  1206.             Kernel(-1, 1) = 1: Kernel(1, -1) = -1
  1207.         Case FILTER_LEFT
  1208.             Kernel(1, 0) = -1: Kernel(-1, 0) = 1
  1209.         Case FILTER_UP_LEFT
  1210.             Kernel(-1, -1) = 1: Kernel(1, 1) = -1
  1211.     End Select
  1212.     Wgt = 1
  1213. End Sub
  1214.  
  1215.  
  1216.  
  1217. ' ************************************************
  1218. ' Initialize a 3x3 Prewitt filter.
  1219. ' ************************************************
  1220. Public Sub InitializePrewitt(prewitt_type As Integer)
  1221. Dim r As Integer
  1222. Dim c As Integer
  1223.  
  1224.     Kind = FILTER_PREWITT
  1225.     Bound = 1
  1226.     ReDim Kernel(-Bound To Bound, -Bound To Bound)
  1227.     
  1228.     For r = -Bound To Bound
  1229.         For c = -Bound To Bound
  1230.             Kernel(r, c) = 1
  1231.         Next c
  1232.     Next r
  1233.     Kernel(0, 0) = -2
  1234.     
  1235.     Select Case prewitt_type
  1236.         Case FILTER_UP
  1237.             Kernel(-1, 1) = -1: Kernel(0, 1) = -1: Kernel(1, 1) = -1
  1238.         Case FILTER_UP_RIGHT
  1239.             Kernel(-1, 0) = -1: Kernel(-1, 1) = -1: Kernel(0, 1) = -1
  1240.         Case FILTER_RIGHT
  1241.             Kernel(-1, -1) = -1: Kernel(-1, 0) = -1: Kernel(-1, 1) = -1
  1242.         Case FILTER_DOWN_RIGHT
  1243.             Kernel(-1, -1) = -1: Kernel(-1, 0) = -1: Kernel(0, -1) = -1
  1244.         Case FILTER_DOWN
  1245.             Kernel(-1, -1) = -1: Kernel(0, -1) = -1: Kernel(1, -1) = -1
  1246.         Case FILTER_DOWN_LEFT
  1247.             Kernel(0, -1) = -1: Kernel(1, -1) = -1: Kernel(1, 0) = -1
  1248.         Case FILTER_LEFT
  1249.             Kernel(1, -1) = -1: Kernel(1, 0) = -1: Kernel(1, 1) = -1
  1250.         Case FILTER_UP_LEFT
  1251.             Kernel(0, 1) = -1: Kernel(1, 0) = -1: Kernel(1, 1) = -1
  1252.     End Select
  1253.     Wgt = 1
  1254. End Sub
  1255.  
  1256.  
  1257.  
  1258. ' ************************************************
  1259. ' Initialize a low pass (blurring) filter.
  1260. ' ************************************************
  1261. Public Sub InitializeLowPass(size As Integer)
  1262. Dim r As Integer
  1263. Dim c As Integer
  1264. Dim vr As Integer
  1265.  
  1266.     Kind = FILTER_LOWPASS
  1267.     Bound = size \ 2
  1268.     ReDim Kernel(-Bound To Bound, -Bound To Bound)
  1269.     
  1270.     For r = -Bound To Bound
  1271.         vr = Bound + 1 - Abs(r)
  1272.         For c = -Bound To Bound
  1273.             Kernel(r, c) = vr * (Bound + 1 - Abs(c))
  1274.             Wgt = Wgt + Kernel(r, c)
  1275.         Next c
  1276.     Next r
  1277. End Sub
  1278.  
  1279.  
  1280.  
  1281.  
  1282. ' ************************************************
  1283. ' Flag the filter as uninitialized.
  1284. ' ************************************************
  1285. Private Sub Class_Initialize()
  1286.     Kind = FILTER_NONE
  1287. End Sub
  1288.  
  1289.  
  1290.