How to read the Color of other Monitor Pixel
So the problem is different scales in each monitor
First, I detect index of which monitor the input point
is in with this answer :
private int ConvertMousePointToScreenIndex(Point mousePoint)
{
//first get all the screens
System.Drawing.Rectangle ret;
for (int i = 1; i <= Screen.AllScreens.Count(); i++)
{
ret = Screen.AllScreens[i - 1].Bounds;
if (ret.Contains(mousePoint))
return i - 1;
}
return 0;
}
Second, I just need to get real width / virtual width
of that indexed monitor based on this answer
const int ENUM_CURRENT_SETTINGS = -1;
public double GetScale(Point point)
{
Screen screen = Screen.AllScreens[ConvertMousePointToScreenIndex(point)];
DEVMODE dm = new DEVMODE();
dm.dmSize = (short)Marshal.SizeOf(typeof(DEVMODE));
EnumDisplaySettings(screen.DeviceName, ENUM_CURRENT_SETTINGS, ref dm);
double RealWidth = dm.dmPelsWidth;
double VirtualWidth = screen.Bounds.Width;
return RealWidth / VirtualWidth;
}
[DllImport("user32.dll")]
public static extern bool EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref DEVMODE lpDevMode);
[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE
{
private const int CCHDEVICENAME = 0x20;
private const int CCHFORMNAME = 0x20;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public int dmPositionX;
public int dmPositionY;
public ScreenOrientation dmDisplayOrientation;
public int dmDisplayFixedOutput;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
public string dmFormName;
public short dmLogPixels;
public int dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
public int dmICMMethod;
public int dmICMIntent;
public int dmMediaType;
public int dmDitherType;
public int dmReserved1;
public int dmReserved2;
public int dmPanningWidth;
public int dmPanningHeight;
}
And finally, apply it to GetColorAt :
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern int BitBlt(IntPtr hDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);
Bitmap screenPixel = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
public Color GetColorAt(Point location)
{
double scale = GetScale(location);
using (Graphics gdest = Graphics.FromImage(screenPixel))
{
using (Graphics gsrc = Graphics.FromHwnd(IntPtr.Zero))
{
IntPtr hSrcDC = gsrc.GetHdc();
IntPtr hDC = gdest.GetHdc();
int retval = BitBlt(hDC, 0, 0, 1, 1, hSrcDC, (int)Math.Round(point.X * scale), (int)Math.Round(point.Y * scale), (int)CopyPixelOperation.SourceCopy);
gdest.ReleaseHdc();
gsrc.ReleaseHdc();
}
}
return screenPixel.GetPixel(0, 0);
}
Quickly getting the color of some pixels on the screen in Python on Windows 7
I had this same exact problem, and solved it (in Java, in C#). The main idea behind the solution is GetPixel from screen is slow, and you can't fix that. But as you need some pixels, you can get a bunch of them all at once.
The time that it took to get 64 pixels was 98 times faster.
glReadPixels with screen pixels
As mentioned in the other answer and comments You can use glReadPixels
only for pixels inside your OpenGL context window that are actually rendered at that time ... As you mentioned you have used GetPixel
it hints you are using GDI. In that case you are trying to read GDI Canvas pixel from OpenGL which is not possible (the other way around is possible however but slow). So I advice to read this:
- How can I access a graphics card's output directly?
Where you can find example of both methods. If you are trying to obtain pixel from your own app then you can use different api then GetPixel
.
If you're in VCL environment use Graphics::TBitmap::ScanLine property which can be used for direct pixel access without restrictions or performance hits if used properly.
On MSVC++ of GCC environment use WinAPI BitBlt
but that is a bit slower and not as elegant (at least from my point of view).
How to get the colour of a pixel at X,Y using c#?
To get a pixel color from the Screen here's code from Pinvoke.net:
using System;
using System.Drawing;
using System.Runtime.InteropServices;
sealed class Win32
{
[DllImport("user32.dll")]
static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("user32.dll")]
static extern Int32 ReleaseDC(IntPtr hwnd, IntPtr hdc);
[DllImport("gdi32.dll")]
static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos);
static public System.Drawing.Color GetPixelColor(int x, int y)
{
IntPtr hdc = GetDC(IntPtr.Zero);
uint pixel = GetPixel(hdc, x, y);
ReleaseDC(IntPtr.Zero, hdc);
Color color = Color.FromArgb((int)(pixel & 0x000000FF),
(int)(pixel & 0x0000FF00) >> 8,
(int)(pixel & 0x00FF0000) >> 16);
return color;
}
}
C# How to get pixel color/data from the screen?
To capture specific rectangle form the screen use the following code
public Bitmap CaptureFromScreen(Rectangle rect)
{
Bitmap bmpScreenCapture = null;
if (rect == Rectangle.Empty)//capture the whole screen
{
rect = Screen.PrimaryScreen.Bounds;
}
bmpScreenCapture = new Bitmap(rect.Width,rect.Height);
Graphics p = Graphics.FromImage(bmpScreenCapture);
p.CopyFromScreen(rect.X,
rect.Y,
0, 0,
rect.Size,
CopyPixelOperation.SourceCopy);
p.Dispose();
return bmpScreenCapture;
}
To Get The color form a specific location use the function
public Color GetColorFromScreen(Point p)
{
Rectangle rect = new Rectangle(p, new Size(2, 2));
Bitmap map = CaptureFromScreen(rect);
Color c = map.GetPixel(0, 0);
map.Dispose();
return c;
}
How can I get the color of a screen pixel THROUGH ADB
I will post an answer to my own question. The answer maybe device-specified (nexus7 2013), and you can adjust it to your own devices.
1.Firstly, I find out that the command screencap screen.png
is quite slow because it take most of its time converting to png file type. So, to save time, the first step is dump screen to a raw data file.
adb shell
screencap screen.dump
2.Check the file size. My screen resolution is 1920*1200, and the file size is 9216012 byte. Noticing that 9216012=1920*1200*4+12, I guess the data file use 4 byte to store every pixel information, and use another 12 byte to do some mystery staff. Just do some more screencaps and I find the 12 byte at the head of each file are the same. So, the additional 12 byte is at the head of the data file.
3.Now, things are simple by using dd
and hd
. Assuming that I want to get the color at (x,y):
let offset=1200*$y+$x+3
dd if='screen.dump' bs=4 count=1 skip=$offset 2>/dev/null | hd
I get output like
00000000: 4b 73 61 ff s 21e
sum 21e
The 4b 73 61 ff
is my answer.
Related Topics
Serializing and Deserializing Expression Trees in C#
Why Would I Ever Need to Use C# Nested Classes
Does the Use of Async/Await Create a New Thread
Using Linq to Concatenate Strings
How to Convert This Foreach Code to Parallel.Foreach
Dependency Injection Unity - Conditional Resolving
Correct Use of Multimapping in Dapper
Is It Better to Create a Singleton to Access Unity Container or Pass It Through the Application
Static VS Non-Static Class Members
How to Get Memory Available or Used in C#
Performance Surprise with "As" and Nullable Types
How to Check for Permissions to Write to a Directory or File
How to Drag and Drop Files into an Application
Omitting All Xsi and Xsd Namespaces When Serializing an Object in .Net
If Statements Matching Multiple Values
Can Console.Clear Be Used to Only Clear a Line Instead of Whole Console