Форум программистов, компьютерный форум, киберфорум
Константин_2012
Войти
Регистрация
Восстановить пароль
Оценить эту запись

Получить цвет пикселя монитора

Запись от Константин_2012 размещена 18.03.2015 в 12:29

Цитата:
Сообщение от EvilFromHell Посмотреть сообщение
Решил я проверить на деле известные мне способы, дабы прекратить споры и сомнения.
Для этого написал вот такой класс:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
        public class FastGetPixel
        {
            [DllImport("user32.dll", EntryPoint = "ReleaseDC")]
            public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
            [DllImport("gdi32.dll")]
            private static extern int BitBlt(
              IntPtr hdcDest, // handle to destination DC
              int nXDest,  // x-coord of destination upper-left corner
              int nYDest,  // y-coord of destination upper-left corner
              int nWidth,  // width of destination rectangle
              int nHeight, // height of destination rectangle
              IntPtr hdcSrc,  // handle to source DC
              int nXSrc,   // x-coordinate of source upper-left corner
              int nYSrc,   // y-coordinate of source upper-left corner
              UInt32 dwRop    // raster operation code
            );
            [DllImport("gdi32.dll")]
            public static extern uint GetPixel(IntPtr hDC, int x, int y);
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);
            [StructLayout(LayoutKind.Sequential)]
            private struct RECT
            {
                public int Left;        // x position of upper-left corner
                public int Top;         // y position of upper-left corner
                public int Right;       // x position of lower-right corner
                public int Bottom;      // y position of lower-right corner
            }
            [DllImport("user32.dll")]
            public static extern IntPtr GetDesktopWindow();
            [DllImport("user32.dll")]
            public static extern IntPtr GetWindowDC(IntPtr hWnd);
            private const Int32 SRCCOPY = 13369376;
            private IntPtr hWnd;
            private Bitmap innerbitmap;
            private bool screenmade = false;
            private BitmapData bmpData;
            private int byteLen = 4;
            private byte[] bitmapBuffer;
            private Color col = Color.Empty;
            public FastGetPixel()
            {
                hWnd = GetDesktopWindow();
            }
 
            public FastGetPixel(IntPtr hWndsource)
            {
                hWnd = hWndsource;
            }
 
            public IntPtr Handle{
                get{ return hWnd;}
                set { try { innerbitmap.UnlockBits(bmpData); } catch { } try { innerbitmap.Dispose(); } catch { } bitmapBuffer = null; screenmade = false;  hWnd = value; }
            }
 
            public Color GetLockedPixel(int Xpos, int Ypos)
            { 
                try
                {
                int index = bmpData.Stride * Ypos + Xpos * byteLen;
                col = Color.FromArgb(bitmapBuffer[index + 2], bitmapBuffer[index + 1], bitmapBuffer[index + 0]);
                }
                catch { col = Color.Empty; }
                return col;
            }
 
            public bool LockWindowImage(PixelFormat PF)
            {
                try
                {
                    if (!screenmade)
                    {
                        RECT rectal = new RECT();
                        GetWindowRect(new HandleRef(null, hWnd), out rectal);
                        innerbitmap = new Bitmap(rectal.Right, rectal.Bottom);
                        Graphics loGraphics = Graphics.FromImage(innerbitmap);
                        IntPtr lnDst = loGraphics.GetHdc();
                        IntPtr hDC = GetWindowDC(hWnd); 
                        BitBlt(lnDst, 0, 0, rectal.Right - rectal.Left, rectal.Bottom - rectal.Top, hDC, 0, 0, SRCCOPY);
                        loGraphics.ReleaseHdc(lnDst);
                        loGraphics.Flush();
                        loGraphics.Dispose();
                        ReleaseDC(hWnd, hDC);
                        bmpData = innerbitmap.LockBits(new Rectangle(0, 0, innerbitmap.Width, innerbitmap.Height), ImageLockMode.ReadOnly, PF);
                        bitmapBuffer = new byte[bmpData.Stride * bmpData.Height];
                        Marshal.Copy(bmpData.Scan0, bitmapBuffer, 0, bitmapBuffer.Length);
                        byteLen = bmpData.Stride / bmpData.Width;
                        screenmade = true;
                    }
                    else { return false; }
                }
                
                catch { return false; }
                return true;
            }
 
            public bool LockWindowImage()
            {
                try
                {
                    if (!screenmade)
                    {
                    RECT rectal = new RECT();
                    GetWindowRect(new HandleRef(null, hWnd), out rectal);
                    innerbitmap = new Bitmap(rectal.Right, rectal.Bottom);
                    Graphics loGraphics = Graphics.FromImage(innerbitmap);
                    IntPtr lnDst = loGraphics.GetHdc();
                    IntPtr hDC = GetWindowDC(hWnd); 
                    BitBlt(lnDst, 0, 0, rectal.Right - rectal.Left, rectal.Bottom - rectal.Top, hDC, 0, 0, SRCCOPY);
                    loGraphics.ReleaseHdc(lnDst);
                    loGraphics.Flush();
                    loGraphics.Dispose();
                    ReleaseDC(hWnd, hDC);
                    bmpData = innerbitmap.LockBits(new Rectangle(0, 0, innerbitmap.Width, innerbitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
                    bitmapBuffer = new byte[bmpData.Stride * bmpData.Height];
                    Marshal.Copy(bmpData.Scan0, bitmapBuffer, 0, bitmapBuffer.Length);
                    byteLen = 4;
                    screenmade = true;
                    }
                else { return false; }
                }
                catch { return false; }
                return true;
            }
 
            public bool LockWindowImage(int Left, int Top, int Width, int Height, PixelFormat PF)
            {
                try
                {
                    if (!screenmade)
                    {
                    innerbitmap = new Bitmap(Width, Height);
                    Graphics loGraphics = Graphics.FromImage(innerbitmap);
                    IntPtr lnDst = loGraphics.GetHdc();
                    IntPtr hDC = GetWindowDC(hWnd); 
                    BitBlt(lnDst, 0, 0, Width, Height, hDC, Left, Top, SRCCOPY);
                    loGraphics.ReleaseHdc(lnDst);
                    loGraphics.Flush();
                    loGraphics.Dispose();
                    ReleaseDC(hWnd, hDC);
                    bmpData = innerbitmap.LockBits(new Rectangle(0, 0, innerbitmap.Width, innerbitmap.Height), ImageLockMode.ReadOnly, PF);
                    bitmapBuffer = new byte[bmpData.Stride * bmpData.Height];
                    Marshal.Copy(bmpData.Scan0, bitmapBuffer, 0, bitmapBuffer.Length);
                    byteLen = bmpData.Stride / bmpData.Width;
                    screenmade = true;
                    }
                else { return false; }
                }
                catch { return false; }
                return true;
            }
            public void Clear() { try { innerbitmap.UnlockBits(bmpData); } catch { } try { innerbitmap.Dispose(); } catch { }bitmapBuffer = null; screenmade = false; }
        }
    }
И устроил вот такие замеры(в каждом цикле сбрасываются цвета пикселей с экрана в массив):
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
           Stopwatch SW0 = new Stopwatch();
            SW0.Start();
            List<Color> listing = new List<Color>();
            Bitmap some = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            Graphics er = Graphics.FromImage(some);
            er.CopyFromScreen(new Point(0,0), new Point(0,0),new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height));
            er.Flush();
            er.Dispose();
            for (int i = 0; i < Screen.PrimaryScreen.Bounds.Height; i++)
            {
                for (int j = 0; j < Screen.PrimaryScreen.Bounds.Width; j++)
                {
                    listing.Add(some.GetPixel(j, i));
                }
            }
            SW0.Stop();
 
            Stopwatch SW1 = new Stopwatch();
            SW1.Start();
            List<Color> listing2 = new List<Color>();
            FastGetPixel pi = new FastGetPixel();
            pi.LockWindowImage();
            for (int i = 0; i < Screen.PrimaryScreen.Bounds.Height; i++)
            {
                for (int j = 0; j < Screen.PrimaryScreen.Bounds.Width; j++)
                {
                    listing2.Add(pi.GetLockedPixel(j, i));
                }
            }
            pi.Clear();
            SW1.Stop();
 
            Stopwatch SW2 = new Stopwatch();
            SW2.Start();
            List<int> listing3 = new List<int>();
            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    listing3.Add(autoit.PixelGetColor(j, i));
                }
            }
            SW2.Stop();
 
            Stopwatch SW3 = new Stopwatch();
            SW3.Start();
            List<Color> listing4 = new List<Color>();
            IntPtr hWnd = GetDesktopWindow();
            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    IntPtr hDC = GetWindowDC(hWnd);
                    uint pixel = GetPixel(hDC, j, i);
                    ReleaseDC(hWnd, hDC);
                    listing4.Add(Color.FromArgb((byte)(pixel & 0x000000FF), (byte)((pixel & 0x0000FF00) >> 8), (byte)((pixel & 0x00FF0000) >> 16)));
                }
            }
            SW3.Stop();
 
 
             Stopwatch SW4 = new Stopwatch();
             SW4.Start();
             List<Color> listing5 = new List<Color>();
             IntPtr hWnd2 = GetDesktopWindow();
             for (int i = 0; i < 10; i++)
             {
                 for (int j = 0; j < 10; j++)
                 {
                     IntPtr lnSrc = GetWindowDC(hWnd2);
                     Bitmap bitmp = new Bitmap(1, 1);
                     Graphics loGraphics = Graphics.FromImage(bitmp);
                     IntPtr lnDst = loGraphics.GetHdc();
                     BitBlt(lnDst, 0, 0, 1, 1, lnSrc, j, i, SRCCOPY);
                     loGraphics.ReleaseHdc(lnDst);
                     loGraphics.Flush();
                     loGraphics.Dispose();
                     ReleaseDC(hWnd2, lnSrc);
                     listing5.Add(bitmp.GetPixel(0, 0));
                     bitmp.Dispose();
                 }
             }
             SW4.Stop();
 
 
             Stopwatch SW5 = new Stopwatch();
             SW5.Start();
             List<Color> listing6 = new List<Color>();
             FastGetPixel pi2 = new FastGetPixel();
             for (int i = 0; i < 10; i++)
             {
                 for (int j = 0; j < 10; j++)
                 {
                     pi2.LockWindowImage(j,i,1,1,PixelFormat.Format32bppPArgb);
                     listing6.Add(pi2.GetLockedPixel(0, 0));
                     pi2.Clear();
                 }
             }
             SW5.Stop();
 
 
 
             MessageBox.Show(SW0.ElapsedMilliseconds.ToString() + " " + SW1.ElapsedMilliseconds.ToString() + " " + SW2.ElapsedMilliseconds.ToString() + " " + SW3.ElapsedMilliseconds.ToString() + " " + SW4.ElapsedMilliseconds.ToString() + " " + SW5.ElapsedMilliseconds.ToString());
Результат получился вот такой(в миллисекундах):

Шарповские CopyFromScreen+GetPixel по экрану 1920x1080 (SW0) - 1594
Класс FastGetPixel(тот, что выше) по экрану 1920x1080 (SW1)- 253

Остальные методы непомерно долгие, но позволяют взять 1 единственный пиксель с разных окон:
Autoit - квадрат 10x10 (SW2) - 2062
Метод, указанный в посте Goal - квадрат 10x10 (SW3) - 2102
BitBlt в битмап 1x1 и шарповский GetPixel с него - квадрат 10x10 (SW4) - 2119
Класс FastGetPixel для пикселей по отдельности(как будто с разных окон) - квадрат 10x10 (SW5) - 2069

Из этого следует, что из представленных методов самый быстрый тот, что в классе выше. Если вы знаете другие, более быстрые, или найдете ошибки, возможности для ускорения или еще что полезное представленных-очень прошу отписаться. Результаты чуть варьируют, но соотношение примерно то же. Оптимизацию пробовал включать и выключать, особо не меняются соотношения.
Здравствуйте, а у вас, случайно, исходника нет?
Размещено в Без категории
Показов 1256 Комментарии 0
Всего комментариев 0
Комментарии
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru