WIP
DirectOutput framework for virtual pinball cabinets WIP
Go to:
Overview 
FastBitmap.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Drawing;
6 
7 namespace DirectOutput.General.BitmapHandling
8 {
9  public class FastBitmap
10  {
11  private PixelData[,] _Pixels = new PixelData[0, 0];
20  public PixelData[,] Pixels
21  {
22  get
23  {
24  return _Pixels;
25  }
26  private set
27  {
28  _Pixels = value;
29  }
30  }
31 
32 
40  public PixelData GetPixel(int X, int Y)
41  {
42  if (X < Width && Y < Height)
43  {
44  return Pixels[X, Y];
45  }
46  else
47  {
48  return new PixelData();
49  }
50 
51 
52  //try
53  //{
54  // return Pixels[X, Y];
55  //}
56  //catch { }
57  //return new PixelData();
58  }
59 
60 
61 
73  public FastBitmap GetClip(int ResultWidth, int ResultHeight, int SourceLeft = 0, int SourceTop = 0, int SourceWidth = -1, int SourceHeight = -1, FastBitmapDataExtractModeEnum DataExtractMode = FastBitmapDataExtractModeEnum.SinglePixelCenter)
74  {
75 
76  SourceLeft = SourceLeft.Limit(0, Width - 1);
77  SourceTop = SourceTop.Limit(0, Height - 1);
78  SourceWidth = (SourceWidth < 0 ? Width - SourceLeft : SourceWidth);
79  SourceHeight = (SourceHeight < 0 ? Height - SourceTop : SourceHeight);
80  ResultWidth = ResultWidth.Limit(0, int.MaxValue);
81  ResultHeight = ResultHeight.Limit(0, int.MaxValue);
82 
83  FastBitmap F = new FastBitmap();
84  F.SetFrameSize(ResultWidth, ResultHeight);
85  PixelData[,] D = F.Pixels;
86 
87  switch (DataExtractMode)
88  {
89  case FastBitmapDataExtractModeEnum.BlendPixels:
90 
91  float Red = 0;
92  float Green = 0;
93  float Blue = 0;
94  float Alpha = 0;
95  float Weight = 0;
96 
97  float PixelSourceWidth = (float)SourceWidth / ResultWidth;
98  float PixelSourceHeight = (float)SourceHeight / ResultHeight;
99  float PixelSourceCount = PixelSourceWidth * PixelSourceHeight;
100 
101 
102  for (int y = 0; y < ResultHeight; y++)
103  {
104  float PixelSourceTop = SourceTop+ y * PixelSourceHeight;
105  float PixelSourceBottom = PixelSourceTop + PixelSourceHeight;
106 
107 
108  for (int x = 0; x < ResultWidth; x++)
109  {
110  int PSR = 0;
111  int PSB = 0;
112  float PixelSourceLeft = SourceLeft+x * PixelSourceWidth;
113  float PixelSourceRight = PixelSourceLeft + PixelSourceWidth;
114  Red = 0;
115  Green = 0;
116  Blue = 0;
117  Alpha = 0;
118 
119  if (!PixelSourceTop.IsIntegral())
120  {
121  //Upper left corner
122  if (!PixelSourceLeft.IsIntegral())
123  {
124  PixelData PD = GetPixel((int)PixelSourceLeft.Floor(), (int)PixelSourceTop.Floor());
125  Weight = (PixelSourceTop.Ceiling() - PixelSourceTop) * (PixelSourceLeft.Ceiling() - PixelSourceLeft);
126  Red += PD.Red * Weight;
127  Green += PD.Green * Weight;
128  Blue += PD.Blue * Weight;
129  Alpha += PD.Alpha * Weight;
130  }
131 
132  //Upper edge
133  PSR = (int)PixelSourceRight.Floor();
134  Weight = (PixelSourceTop.Ceiling() - PixelSourceTop);
135  for (int xs = (int)PixelSourceLeft.Ceiling(); xs < PSR; xs++)
136  {
137  PixelData PD = GetPixel(xs, (int)PixelSourceTop.Floor());
138  Red += PD.Red * Weight;
139  Green += PD.Green * Weight;
140  Blue += PD.Blue * Weight;
141  Alpha += PD.Alpha * Weight;
142  }
143 
144  //Upper right corner
145  if (!PixelSourceRight.IsIntegral())
146  {
147  Weight = (PixelSourceTop.Ceiling() - PixelSourceTop) * (PixelSourceRight - PixelSourceRight.Floor());
148  PixelData PD = GetPixel((int)PixelSourceRight.Floor(), (int)PixelSourceTop.Floor());
149  Red += PD.Red * Weight;
150  Green += PD.Green * Weight;
151  Blue += PD.Blue * Weight;
152  Alpha += PD.Alpha * Weight;
153  }
154  }
155 
156  PSB = (int)PixelSourceBottom.Floor();
157  PSR = (int)PixelSourceRight.Floor();
158  for (int ys = (int)PixelSourceTop.Ceiling(); ys < PSB; ys++)
159  {
160  //Left edge
161  if (!PixelSourceLeft.IsIntegral())
162  {
163  PixelData PD = GetPixel((int)PixelSourceLeft.Floor(), ys);
164  Weight = (PixelSourceLeft.Ceiling() - PixelSourceLeft);
165  Red += PD.Red * Weight;
166  Green += PD.Green * Weight;
167  Blue += PD.Blue * Weight;
168  Alpha += PD.Alpha * Weight;
169  }
170 
171  //full pixels
172  for (int xs = (int)PixelSourceLeft.Ceiling(); xs < PSR; xs++)
173  {
174  PixelData PD = GetPixel(xs, ys);
175  Red += PD.Red;
176  Green += PD.Green;
177  Blue += PD.Blue;
178  Alpha += PD.Alpha;
179  }
180 
181  //Right edge
182  if (!PixelSourceRight.IsIntegral())
183  {
184  Weight = (PixelSourceRight - PSR);
185  PixelData PD = GetPixel(PSR, ys);
186  Red += PD.Red * Weight;
187  Green += PD.Green * Weight;
188  Blue += PD.Blue * Weight;
189  Alpha += PD.Alpha * Weight;
190  }
191  }
192 
193 
194  if (!PixelSourceBottom.IsIntegral())
195  {
196  PSB = (int)PixelSourceBottom.Floor();
197  PSR = (int)PixelSourceRight.Floor();
198 
199  //Lower left corner
200  if (!PixelSourceLeft.IsIntegral())
201  {
202  PixelData PD = GetPixel((int)PixelSourceLeft.Floor(), PSB);
203  Weight = (PixelSourceBottom - PSB) * (PixelSourceLeft.Ceiling() - PixelSourceLeft);
204  Red += PD.Red * Weight;
205  Green += PD.Green * Weight;
206  Blue += PD.Blue * Weight;
207  Alpha += PD.Alpha * Weight;
208  }
209 
210  //Lower edge
211 
212 
213  Weight = (PixelSourceBottom - PSB);
214  for (int xs = (int)PixelSourceLeft.Ceiling(); xs < PSR; xs++)
215  {
216  PixelData PD = GetPixel(xs, PSB);
217  Red += PD.Red * Weight;
218  Green += PD.Green * Weight;
219  Blue += PD.Blue * Weight;
220  Alpha += PD.Alpha * Weight;
221  }
222 
223  //Lower right corner
224  if (!PixelSourceRight.IsIntegral())
225  {
226  Weight = (PixelSourceBottom - PSB) * (PixelSourceRight - PSR);
227  PixelData PD = GetPixel(PSR, PSB);
228  Red += PD.Red * Weight;
229  Green += PD.Green * Weight;
230  Blue += PD.Blue * Weight;
231  Alpha += PD.Alpha * Weight;
232  }
233  }
234  D[x, y] = new PixelData((byte)(Red / PixelSourceCount).Limit(0, 255), (byte)(Green / PixelSourceCount).Limit(0, 255), (byte)(Blue / PixelSourceCount).Limit(0, 255), (byte)(Alpha / PixelSourceCount).Limit(0, 255));
235  }
236 
237  }
238  break;
239  case FastBitmapDataExtractModeEnum.SinglePixelTopLeft:
240  case FastBitmapDataExtractModeEnum.SinglePixelCenter:
241  default:
242  float XSource = 0;
243 
244  float XSourceBase = 0;
245  float YSource = 0;
246  float XStep = (float)SourceWidth / ResultWidth;
247  float YStep = (float)SourceHeight / ResultHeight;
248 
249  if (DataExtractMode == FastBitmapDataExtractModeEnum.SinglePixelCenter)
250  {
251  XSourceBase = XStep / 2;
252  YSource = YStep / 2;
253  }
254 
255  for (int y = 0; y < ResultHeight; y++)
256  {
257  XSource = XSourceBase;
258  for (int x = 0; x < ResultWidth; x++)
259  {
260  D[x, y] = GetPixel(XSource.RoundToInt(), YSource.RoundToInt());
261  XSource += XStep;
262  }
263  YSource += YStep;
264  }
265 
266  break;
267  }
268 
269 
270  return F;
271  }
272 
273 
280  public void SetFrameSize(int Width, int Height)
281  {
282  Pixels = new PixelData[Width.Limit(0, int.MaxValue), Height.Limit(0, int.MaxValue)];
283  _Width = Width;
284  _Height = Height;
285  }
286 
287 
288 
289  private int _Width = 0;
290 
297  public int Width
298  {
299  get
300  {
301  return _Width;
302  }
303  }
304 
305 
306  private int _Height = 0;
313  public int Height
314  {
315  get
316  {
317  return Pixels.GetLength(1);
318  }
319  }
320 
321 
326  public void Load(Image Image)
327  {
328  Load(new Bitmap(Image));
329  }
330 
335  public void Load(Bitmap Bitmap)
336  {
337 
338  UnsafeBitmap UImg = new UnsafeBitmap(Bitmap);
339  UImg.LockBitmap();
340 
341  SetFrameSize(Bitmap.Width, Bitmap.Height);
342 
343  PixelData[,] P = Pixels;
344 
345  int h = Bitmap.Height;
346  int w = Bitmap.Width;
347 
348  for (int y = 0; y < h; y++)
349  {
350  for (int x = 0; x < w; x++)
351  {
352  P[x, y] = UImg.GetPixel(x, y);
353  }
354  }
355  UImg.UnlockBitmap();
356  UImg = null;
357 
358  GC.Collect();
359  }
360 
361 
362 
366  public FastBitmap() { }
367 
372  public FastBitmap(Bitmap Bitmap)
373  {
374  Load(Bitmap);
375  }
376 
381  public FastBitmap(Image Image)
382  {
383  Load(Image);
384  }
385  }
386 }
void SetFrameSize(int Width, int Height)
Sets the size (width/height) of the frame. Setting the framesize will discard all existing pixel dat...
Definition: FastBitmap.cs:280
Struct holding the data for a single pixel in a bitmap.
Definition: PixelData.cs:12
PixelData[,] Pixels
The pixel data array of the frame. Dimension 0 if the array is the x/horizontal direction...
Definition: FastBitmap.cs:21
This class allows fast access to the pixels of a bitmap. The code was inspired/stolen from this threa...
Definition: UnsafeBitmap.cs:14
void Load(Bitmap Bitmap)
Loads the currently active frame of the specified bitmap into the FastBitmap object.
Definition: FastBitmap.cs:335
FastBitmap(Bitmap Bitmap)
Initializes a new instance of the FastBitmap class and loads the currently active frame of the specif...
Definition: FastBitmap.cs:372
FastBitmap()
Initializes a new instance of the FastBitmap class.
Definition: FastBitmap.cs:366
FastBitmap(Image Image)
Initializes a new instance of the FastBitmap class and loads the currently active frame of the specif...
Definition: FastBitmap.cs:381
FastBitmapDataExtractModeEnum
The enum defines how the pixels are extracted from the source image.
FastBitmap GetClip(int ResultWidth, int ResultHeight, int SourceLeft=0, int SourceTop=0, int SourceWidth=-1, int SourceHeight=-1, FastBitmapDataExtractModeEnum DataExtractMode=FastBitmapDataExtractModeEnum.SinglePixelCenter)
Gets a FastBitmap with a specified size representing a defineable section of the current object...
Definition: FastBitmap.cs:73
void Load(Image Image)
Loads the currently active frame of the specified Image into the FastBitmap object.
Definition: FastBitmap.cs:326
PixelData GetPixel(int X, int Y)
Gets the PixelData for the specified pixel of the frame. For positions outside the frame...
Definition: FastBitmap.cs:40