1: /*
2: Copyright (c) 2010 <a href="http://www.gutgames.com">James Craig</a>
3:
4: Permission is hereby granted, free of charge, to any person obtaining a copy
5: of this software and associated documentation files (the "Software"), to deal
6: in the Software without restriction, including without limitation the rights
7: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8: copies of the Software, and to permit persons to whom the Software is
9: furnished to do so, subject to the following conditions:
10:
11: The above copyright notice and this permission notice shall be included in
12: all copies or substantial portions of the Software.
13:
14: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20: THE SOFTWARE.*/
21:
22: #region Usings
23: using System.Drawing;
24: using System.Drawing.Imaging;
25: using Utilities.Math;
26:
27: #endregion
28:
29: namespace Utilities.Media.Image
30: {
31: /// <summary>
32: /// Used when applying convolution filters to an image
33: /// </summary>
34: public class Filter
35: {
36: #region Constructor
37:
38: /// <summary>
39: /// Constructor
40: /// </summary>
41: public Filter()
42: {
43: MyFilter = new int[3, 3];
44: Width = 3;
45: Height = 3;
46: Offset = 0;
47: Absolute = false;
48: }
49:
50: /// <summary>
51: /// Constructor
52: /// </summary>
53: /// <param name="Width">Width</param>
54: /// <param name="Height">Height</param>
55: public Filter(int Width, int Height)
56: {
57: MyFilter = new int[Width, Height];
58: this.Width = Width;
59: this.Height = Height;
60: Offset = 0;
61: Absolute = false;
62: }
63:
64: #endregion
65:
66: #region Public Properties
67:
68: /// <summary>
69: /// The actual filter array
70: /// </summary>
71: public int[,] MyFilter { get; set; }
72:
73: /// <summary>
74: /// Width of the filter box
75: /// </summary>
76: public int Width { get; set; }
77:
78: /// <summary>
79: /// Height of the filter box
80: /// </summary>
81: public int Height { get; set; }
82:
83: /// <summary>
84: /// Amount to add to the red, blue, and green values
85: /// </summary>
86: public int Offset { get; set; }
87:
88: /// <summary>
89: /// Determines if we should take the absolute value prior to clamping
90: /// </summary>
91: public bool Absolute { get; set; }
92:
93: #endregion
94:
95: #region Public Functions
96:
97: /// <summary>
98: /// Applies the filter to the input image
99: /// </summary>
100: /// <param name="Input">input image</param>
101: /// <returns>Returns a separate image with the filter applied</returns>
102: public Bitmap ApplyFilter(Bitmap Input)
103: {
104: Bitmap NewBitmap = new Bitmap(Input.Width, Input.Height);
105: BitmapData NewData = Image.LockImage(NewBitmap);
106: BitmapData OldData = Image.LockImage(Input);
107: int NewPixelSize = Image.GetPixelSize(NewData);
108: int OldPixelSize = Image.GetPixelSize(OldData);
109: for (int x = 0; x < Input.Width; ++x)
110: {
111: for (int y = 0; y < Input.Height; ++y)
112: {
113: int RValue = 0;
114: int GValue = 0;
115: int BValue = 0;
116: int Weight = 0;
117: int XCurrent = -Width / 2;
118: for (int x2 = 0; x2 < Width; ++x2)
119: {
120: if (XCurrent + x < Input.Width && XCurrent + x >= 0)
121: {
122: int YCurrent = -Height / 2;
123: for (int y2 = 0; y2 < Height; ++y2)
124: {
125: if (YCurrent + y < Input.Height && YCurrent + y >= 0)
126: {
127: Color Pixel = Image.GetPixel(OldData, XCurrent + x, YCurrent + y, OldPixelSize);
128: RValue += MyFilter[x2, y2] * Pixel.R;
129: GValue += MyFilter[x2, y2] * Pixel.G;
130: BValue += MyFilter[x2, y2] * Pixel.B;
131: Weight += MyFilter[x2, y2];
132: }
133: ++YCurrent;
134: }
135: }
136: ++XCurrent;
137: }
138: Color MeanPixel = Image.GetPixel(OldData, x, y, OldPixelSize);
139: if (Weight == 0)
140: Weight = 1;
141: if (Weight > 0)
142: {
143: if (Absolute)
144: {
145: RValue = System.Math.Abs(RValue);
146: GValue = System.Math.Abs(GValue);
147: BValue = System.Math.Abs(BValue);
148: }
149: RValue = (RValue / Weight) + Offset;
150: RValue = MathHelper.Clamp(RValue, 255, 0);
151: GValue = (GValue / Weight) + Offset;
152: GValue = MathHelper.Clamp(GValue, 255, 0);
153: BValue = (BValue / Weight) + Offset;
154: BValue = MathHelper.Clamp(BValue, 255, 0);
155: MeanPixel = Color.FromArgb(RValue, GValue, BValue);
156: }
157: Image.SetPixel(NewData, x, y, MeanPixel, NewPixelSize);
158: }
159: }
160: Image.UnlockImage(NewBitmap, NewData);
161: Image.UnlockImage(Input, OldData);
162: return NewBitmap;
163: }
164:
165: #endregion
166: }
167: }