All files
[pithos-ms-client] / trunk / Libraries / ParallelExtensionsExtras / Drawing / FastBitmap.cs
1 //--------------------------------------------------------------------------
2 // 
3 //  Copyright (c) Microsoft Corporation.  All rights reserved. 
4 // 
5 //  File: FastBitmap.cs
6 //
7 //--------------------------------------------------------------------------
8
9 using System;
10 using System.Drawing;
11 using System.Drawing.Imaging;
12
13 namespace Microsoft.Drawing
14 {
15     public struct PixelData
16     {
17         public byte B;
18         public byte G;
19         public byte R;
20     }
21
22     public unsafe class FastBitmap : IDisposable
23     {
24         private Bitmap _bitmap;
25         private int _width;
26         private BitmapData _bitmapData = null;
27         private byte* _pBase = null;
28         private PixelData* _pInitPixel = null;
29         private Point _size;
30         private bool _locked = false;
31
32         public FastBitmap(Bitmap bmp)
33         {
34             if (bmp == null) throw new ArgumentNullException("bitmap");
35
36             _bitmap = bmp;
37             _size = new Point(bmp.Width, bmp.Height);
38
39             LockBitmap();
40         }
41
42         public PixelData* GetInitialPixelForRow(int rowNumber)
43         {
44             return (PixelData*)(_pBase + rowNumber * _width);
45         }
46
47         public PixelData* this[int x, int y]
48         {
49             get { return (PixelData*)(_pBase + y * _width + x * sizeof(PixelData)); }
50         }
51
52         public Color GetColor(int x, int y)
53         {
54             PixelData* data = this[x, y];
55             return Color.FromArgb(data->R, data->G, data->B);
56         }
57
58         public void SetColor(int x, int y, Color c)
59         {
60             PixelData* data = this[x, y];
61             data->R = c.R;
62             data->G = c.G;
63             data->B = c.B;
64         }
65
66         private void LockBitmap()
67         {
68             if (_locked) throw new InvalidOperationException("Already locked");
69
70             Rectangle bounds = new Rectangle(0, 0, _bitmap.Width, _bitmap.Height);
71
72             // Figure out the number of bytes in a row. This is rounded up to be a multiple 
73             // of 4 bytes, since a scan line in an image must always be a multiple of 4 bytes
74             // in length. 
75             _width = bounds.Width * sizeof(PixelData);
76             if (_width % 4 != 0) _width = 4 * (_width / 4 + 1);
77
78             _bitmapData = _bitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
79
80             _pBase = (byte*)_bitmapData.Scan0.ToPointer();
81             _locked = true;
82         }
83
84         private void InitCurrentPixel()
85         {
86             _pInitPixel = (PixelData*)_pBase;
87         }
88
89         private void UnlockBitmap()
90         {
91             if (!_locked) throw new InvalidOperationException("Not currently locked");
92
93             _bitmap.UnlockBits(_bitmapData);
94             _bitmapData = null;
95             _pBase = null;
96             _locked = false;
97         }
98
99         public void Dispose()
100         {
101             if (_locked) UnlockBitmap();
102         }
103     }
104 }