' Class implementing grayscale conversion of color image.
'
' Copyright (c) 2007 Miran Uhan
'
' This program is free software; you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation; either version 2 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
' GNU General Public License for more details.
'
' You should have received a copy of the GNU General Public License
' along with this program; if not, write to the
' Free Software Foundation, Inc.
' 51 Franklin Street, Fifth Floor
' Boston, MA 02110-1301 USA
'
' Sources:
' - http://www.codeproject.com/cs/library/yael_image_filters.asp
' - http://www.bobpowell.net/grayscale.htm
'
' For questions you can contact author at
' miran.uhan@gmail.com
' Sugestions and bug reports are also welcome.
'
Imports System.Drawing
Imports System.Drawing.Imaging
Public Class GrayScaleFilter
Inherits BasicFilter
Private _brightness As Brightness = Brightness.Normal
Private _useColorMatrix As Boolean = False
Private _factorRed As Integer = 30
Private _factorGreen As Integer = 59
Private _factorBlue As Integer = 11
''' <summary>
''' Get or set brightness.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property Brightness() As Brightness
Get
Return _brightness
End Get
Set(ByVal value As Brightness)
_brightness = value
Select Case _brightness
Case Brightness.Normal
_factorRed = 30
_factorGreen = 59
_factorBlue = 11
Case Brightness.Bright
_factorRed = 50
_factorGreen = 50
_factorBlue = 50
End Select
End Set
End Property
''' <summary>
''' Get or set factor for red component.
''' </summary>
''' <value>Integer in range [0..100].</value>
''' <returns></returns>
''' <remarks></remarks>
Public Property FactorRed() As Integer
Get
Return _factorRed
End Get
Set(ByVal value As Integer)
If ((value >= 0) And (value <= 100)) Then
_factorRed = value
End If
End Set
End Property
''' <summary>
''' Get or set factor for green component.
''' </summary>
''' <value>Integer in range [0..100].</value>
''' <returns></returns>
''' <remarks></remarks>
Public Property FactorGreen() As Integer
Get
Return _factorGreen
End Get
Set(ByVal value As Integer)
If ((value >= 0) And (value <= 100)) Then
_factorGreen = value
End If
End Set
End Property
''' <summary>
''' Get or set factor for blue component.
''' </summary>
''' <value>Integer in range [0..100].</value>
''' <returns></returns>
''' <remarks></remarks>
Public Property FactorBlue() As Integer
Get
Return _factorBlue
End Get
Set(ByVal value As Integer)
If ((value >= 0) And (value <= 100)) Then
_factorBlue = value
End If
End Set
End Property
''' <summary>
''' Get or set color matrix use flag.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property UseColorMatrix() As Boolean
Get
Return _useColorMatrix
End Get
Set(ByVal value As Boolean)
_useColorMatrix = value
End Set
End Property
''' <summary>
''' Execute filter and return filtered image.
''' </summary>
''' <param name="img"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Overrides Function ExecuteFilter( _
ByVal img As System.Drawing.Image) As System.Drawing.Image
Select Case img.PixelFormat
Case PixelFormat.Format16bppGrayScale
Return img
Case PixelFormat.Format24bppRgb, _
PixelFormat.Format32bppArgb, PixelFormat.Format32bppRgb
If _useColorMatrix Then
Return ExecuteRgb8Matrix(img)
Else
Return ExecuteRgb8(img)
End If
Case PixelFormat.Format48bppRgb
Return img
Case Else
Return img
End Select
End Function
''' <summary>
''' Execute filter on (A)RGB image with 8 bits per color.
''' </summary>
''' <param name="img"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function ExecuteRgb8( _
ByVal img As System.Drawing.Image) As System.Drawing.Image
Dim result As Bitmap = New Bitmap(img)
Dim bmpData As BitmapData = result.LockBits( _
New Rectangle(0, 0, result.Width, result.Height), _
ImageLockMode.ReadWrite, img.PixelFormat)
Dim pixelBytes As Integer = _
System.Drawing.Image.GetPixelFormatSize(img.PixelFormat) \ 8
'Get the address of the first line.
Dim ptr As IntPtr = bmpData.Scan0
Dim size As Integer = bmpData.Stride * result.Height
Dim pixels(size - 1) As Byte
Dim index As Integer
Dim Y As Integer
Dim mulR As Double = _factorRed / 100
Dim mulG As Double = _factorGreen / 100
Dim mulB As Double = _factorBlue / 100
'Copy the RGB values into the array.
System.Runtime.InteropServices.Marshal.Copy(ptr, pixels, 0, size)
'Main loop.
For row As Integer = 0 To result.Height - 1
For col As Integer = 0 To result.Width - 1
index = (row * bmpData.Stride) + (col * pixelBytes)
Y = CInt(System.Math.Round( _
mulR * pixels(index + 2) + _
mulG * pixels(index + 1) + _
mulB * pixels(index + 0)))
If (Y > 255) Then Y = 255
'Save new values.
pixels(index + 2) = CByte(Y)
pixels(index + 1) = CByte(Y)
pixels(index + 0) = CByte(Y)
Next
Next
'Copy the RGB values back to the bitmap
System.Runtime.InteropServices.Marshal.Copy(pixels, 0, ptr, size)
'Unlock the bits.
result.UnlockBits(bmpData)
Return result
End Function
''' <summary>
''' Execute filter on (A)RGB image with 8 bits per color.
''' </summary>
''' <param name="img"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function ExecuteRgb8Matrix( _
ByVal img As System.Drawing.Image) As System.Drawing.Image
'Reference from http://www.bobpowell.net/grayscale.htm
Dim result As Bitmap = New Bitmap(img)
result.SetResolution(img.HorizontalResolution, img.VerticalResolution)
Dim g As Graphics = Graphics.FromImage(result)
Dim colorMatrix As ColorMatrix
If (_brightness) Then
colorMatrix = New ColorMatrix(New Single()() _
{ _
New Single() {0.5, 0.5, 0.5, 0, 0}, _
New Single() {0.5, 0.5, 0.5, 0, 0}, _
New Single() {0.5, 0.5, 0.5, 0, 0}, _
New Single() {0, 0, 0, 1, 0}, _
New Single() {0, 0, 0, 0, 1} _
})
Else
colorMatrix = New ColorMatrix(New Single()() _
{ _
New Single() {0.3, 0.3, 0.3, 0, 0}, _
New Single() {0.59, 0.59, 0.59, 0, 0}, _
New Single() {0.11, 0.11, 0.11, 0, 0}, _
New Single() {0, 0, 0, 1, 0}, _
New Single() {0, 0, 0, 0, 1} _
})
End If
Dim imgAttributes As ImageAttributes = New ImageAttributes()
imgAttributes.SetColorMatrix(colorMatrix)
g.DrawImage(result, _
New Rectangle(0, 0, img.Width, img.Height), _
0, 0, img.Width, img.Height, _
GraphicsUnit.Pixel, imgAttributes)
g.Dispose()
Return result
End Function
End Class