tomaschku
Goto Top

Pixel Farbe in RGB

Hallo,

Ich möchte an der Stelle meiner Maus die Pixelfarbe in RGB herausfinden und dann mit anderen Werten abgleichen.
Da ich die Maus-Koordinaten schon für andere Zwecke benötige, wäre eine Funktion praktisch, die zwei POINT Werte als Argument hat.

Sowas wie:
Farbe pixel(POINT x, POINT y) {
	return GetFarbe("RGB", x, y);  
}

int main() {
	Farbe foo = pixel(cursor.x, cursor.y)
	if (foo == {0, 0, 0}) {/*...*/};
	/*...*/
	if (foo == {255, 255, 255}) {/*...*/};
}

Benutze: Windows 10; Visual Studio

LG,
tomaschku

Content-ID: 358946

Url: https://administrator.de/contentid/358946

Ausgedruckt am: 24.11.2024 um 17:11 Uhr

Tektronix
Tektronix 22.12.2017 um 08:25:55 Uhr
Goto Top
Hallo
Vielleicht nutzt Dir diese Batch irgendwas. Da wird auf den Bilschirm gezeichnet.
Es wird ein Powershell Modul Namens color.psm1 verwendet.
@echo off
setlocal disableDelayedExpansion
set q=^"  
echo(
echo(
call :c 0E "                ,      .-;" /n  
call :c 0E "             ,  |\    / /  __," /n  
call :c 0E "             |\ '.`-.|  |.'.-'" /n  
call :c 0E "              \`'-:  `; : /" /n  
call :c 0E "               `-._'.  \'|" /n  
call :c 0E "              ,_.-=` ` `  ~,_" /n  
call :c 0E "               '--,.    "&call :c 0c ".-. "&call :c 0E ",=!q!." /n  
call :c 0E "                 /     "&call :c 0c "{ "&call :c 0A "* "&call :c 0c ")"&call :c 0E "`"&call :c 06 ";-."&call :c 0E "}" /n  
call :c 0E "                 |      "&call :c 0c "'-' "&call :c 06 "/__ |" /n  
call :c 0E "                 /          "&call :c 06 "\_,\|" /n  
call :c 0E "                 |          (" /n  
call :c 0E "             "&call :c 0c "__ "&call :c 0E "/ '          \" /n  
call :c 02 "     /\_    "&call :c 0c "/,'`"&call :c 0E "|     '   "&call :c 0c ".-~!q!~~-." /n  
call :c 02 "     |`.\_ "&call :c 0c "|   "&call :c 0E "/  ' ,    "&call :c 0c "/        \" /n  
call :c 02 "   _/  `, \"&call :c 0c "|  "&call :c 0E "; ,     . "&call :c 0c "|  ,  '  . |" /n  
call :c 02 "   \   `,  "&call :c 0c "|  "&call :c 0E "|  ,  ,   "&call :c 0c "|  :  ;  : |" /n  
call :c 02 "   _\  `,  "&call :c 0c "\  "&call :c 0E "|.     ,  "&call :c 0c "|  |  |  | |" /n  
call :c 02 "   \`  `.   "&call :c 0c "\ "&call :c 0E "|   '     "&call :c 0A "|"&call :c 0c "\_|-'|_,'\|" /n  
call :c 02 "   _\   `,   "&call :c 0A "`"&call :c 0E "\  '  . ' "&call :c 0A "| |  | |  |           "&call :c 02 "__" /n  
call :c 02 "   \     `,   "&call :c 0E "| ,  '    "&call :c 0A "|_/'-|_\_/     "&call :c 02 "__ ,-;` /" /n  
call :c 02 "    \    `,    "&call :c 0E "\ .  , ' .| | | | |   "&call :c 02 "_/' ` _=`|" /n  
call :c 02 "     `\    `,   "&call :c 0E "\     ,  | | | | |"&call :c 02 "_/'   .=!q!  /" /n  
call :c 02 "     \`     `,   "&call :c 0E "`\      \/|,| ;"&call :c 02 "/'   .=!q!    |" /n  
call :c 02 "      \      `,    "&call :c 0E "`\' ,  | ; "&call :c 02 "/'    =!q!    _/" /n  
call :c 02 "       `\     `,  "&call :c 05 ".-!q!!q!-. "&call :c 0E "': "&call :c 02 "/'    =!q!     /" /n  
call :c 02 "    jgs _`\    ;"&call :c 05 "_{  '   ; "&call :c 02 "/'    =!q!      /" /n  
call :c 02 "       _\`-/__"&call :c 05 ".~  `."&call :c 07 "8"&call :c 05 ".'.!q!`~-. "&call :c 02 "=!q!     _,/" /n  
call :c 02 "    __\      "&call :c 05 "{   '-."&call :c 07 "|"&call :c 05 ".'.--~'`}"&call :c 02 "    _/" /n  
call :c 02 "    \    .=!q!` "&call :c 05 "}.-~!q!'"&call :c 0D "u"&call :c 05 "'-. '-..'  "&call :c 02 "__/" /n  
call :c 02 "   _/  .!q!    "&call :c 05 "{  -'.~('-._,.'"&call :c 02 "\_,/" /n  
call :c 02 "  /  .!q!    _/'"&call :c 05 "`--; ;  `.  ;" /n  
call :c 02 "   .=!q!  _/'      "&call :c 05 "`-..__,-'" /n  
call :c 02 "    __/'" /n  

if exist "%temp%\color.psm1" (  
    powershell -command "&{set-executionpolicy remotesigned; Import-Module '%temp%\color.psm1'}"  
    del "%temp%\color.psm1"  
)

echo(

exit /b

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:c <color pair> <string> </n>
setlocal enabledelayedexpansion
set "colors=0-black;1-darkblue;2-darkgreen;3-darkcyan;4-darkred;5-darkmagenta;6-darkyellow;7-gray;8-darkgray;9-blue;a-green;b-cyan;c-red;d-magenta;e-yellow;f-white"  
set "p=%~1"  
set "bg=!colors:*%p:~0,1%-=!"  
set bg=%bg:;=&rem.%
set "fg=!colors:*%p:~-1%-=!"  
set fg=%fg:;=&rem.%

if not "%~3"=="/n" set "br=-nonewline"  
set "str=%~2" & set "str=!str:'=''!"  

>>"%temp%\color.psm1" echo write-host '!str!' -foregroundcolor '%fg%' -backgroundcolor '%bg%' %br%  
endlocal
colinardo
Lösung colinardo 22.12.2017 aktualisiert um 10:09:57 Uhr
Goto Top
Servus tomaschku,
wäre eine Funktion praktisch, die zwei POINT Werte als Argument hat.
Du meinst sicherlich einen Point als Argument, denn ein Point beinhaltet ja bereits x und y Wert.
private Color GetColorFromPixel(Point position) {
    try {
        using (Bitmap b = new Bitmap(1, 1)) {
            using (Graphics g = Graphics.FromImage(b)) {
                g.CopyFromScreen(position.X, position.Y, 0, 0, new Size(1, 1));
                return b.GetPixel(0, 0);
            }
        }
    } catch (System.Exception ex) {
        return Color.Empty;
    }
}
Aufruf dann mit
Color c = GetColorFromPixel(Cursor.Position);
Das gibt dir dann ein Color(ARGB-Objekt) mit den Eigenschaften .A , .R , .G, und .B zurück.

Grüße Uwe
tomaschku
tomaschku 22.12.2017, aktualisiert am 23.12.2017 um 12:48:43 Uhr
Goto Top
einen Point als Argument
Stimmt. Ich habe Point mit Int verwechselt und angenommen, die könnten ja nur einen Wert haben.

Edit:
Irgendwie macht mir das 'private' Probleme. Wenn ich es entferne oder struct xyz{} hinzufüge, dann wird folgendes als undefiniert erkannt: 'Color, Point, System'

Falls es hilft: Ich benutze keine structs oder Klassen. Nur pure Funktionen.

Gruß tomaschku
tomaschku
tomaschku 22.12.2017 um 16:36:56 Uhr
Goto Top
Hi,
zwar nicht ganz der eigentliche Zweck, aber ich heb mir den Code auf! ;)

Gruß tomaschku
rubberman
Lösung rubberman 26.12.2017 aktualisiert um 21:40:15 Uhr
Goto Top
Nanu? Das ist doch weder C noch C++, Uwe.

Ich denke, hier muss die Windows API herhalten. Das wird wie immer nicht schön, da der Callback-Funktion eines Mouse-Hooks keine benutzerspezifischen Argumente übergeben werden können. Also globale Variablen (pfui!). Außerdem benötigt der Hook eine Message Schleife, was für Consoleanwendungen nicht vorgesehen ist. Also würde ich den ganzen Mist in eine andere Übersetzungseinheit auslagern, damit wenigstens im Hauptcode sauber gearbeitet werden kann.

clickpixel.h
#ifndef CLICKPIXEL_H_INCLUDED__
#define CLICKPIXEL_H_INCLUDED__

#ifdef __cplusplus
extern "C" {  
#endif

typedef struct tag_PIXEL
{
  long x, y;   /**< position of the pixel */
  int r, g, b; /**< color values (0...255) for red, green, and blue */
} PIXEL;

/** \brief  Get position and color of the pixel under the mouse pointer when the left mouse button was pressed down.
 *
 * \param p_pixel   Pointer to a PIXEL structure that retrieves the data of the clicked pixel.
 * \param minimize  Nonzero value if the current window shall be minimized. Zero otherwise.
 * \return Nonzero value if the function succeeded. Zero otherwise. */
int GetClickedPixel(PIXEL *const p_pixel, const int minimize);

#ifdef __cplusplus
}
#endif

#endif // CLICKPIXEL_H_INCLUDED__


clickpixel.c
#include <stddef.h>
#include "clickpixel.h" 
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0600
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

HHOOK             glob_mouse_hook = NULL;
HDC               glob_dc = NULL;
CRITICAL_SECTION  glob_mtx = {0};
POINT             glob_pt = {0};
COLORREF          glob_col = 0UL;
int               glob_stop = 0; // concurrently accessed

LRESULT CALLBACK MouseHookProc(int n_code, WPARAM w_param, LPMSLLHOOKSTRUCT hook_data)
{
  if (w_param == WM_LBUTTONDOWN)
  {
    EnterCriticalSection(&glob_mtx);
    if (glob_stop == 0)
    {
      glob_pt = hook_data->pt;
      glob_col = GetPixel(glob_dc, hook_data->pt.x, hook_data->pt.y);
      glob_stop = 1;
    }
    LeaveCriticalSection(&glob_mtx);
  }

  return CallNextHookEx(glob_mouse_hook, n_code, w_param, (LPARAM)hook_data);
}

int GetClickedPixel(PIXEL *const p_pixel, const int minimize)
{
  WINDOWPLACEMENT wpl = {sizeof(WINDOWPLACEMENT)};
  HWND h_wnd = GetConsoleWindow();
  glob_stop = 0;
  InitializeCriticalSection(&glob_mtx);
  if (p_pixel == NULL
      || GetWindowPlacement(h_wnd, &wpl) == FALSE
      || (glob_dc = GetDC(NULL)) == NULL
      || (glob_mouse_hook = SetWindowsHookExW(WH_MOUSE_LL, (HOOKPROC)MouseHookProc, (HINSTANCE)GetModuleHandleW(NULL), 0UL)) == NULL)
  {
    ReleaseDC(h_wnd, glob_dc);
    DeleteCriticalSection(&glob_mtx);
    return 0;
  }

  if (minimize != 0)
    ShowWindow(h_wnd, SW_SHOWMINNOACTIVE);

  MSG msg = {0};
  register int stop = 0;
  while (stop == 0)
  {
    Sleep(20UL);
    EnterCriticalSection(&glob_mtx);
    stop = glob_stop;
    LeaveCriticalSection(&glob_mtx);
    while (PeekMessageW(&msg, NULL, 0U, 0U, PM_REMOVE) != FALSE)
      DispatchMessageW(&msg);
  }

  UnhookWindowsHookEx(glob_mouse_hook);
  ReleaseDC(h_wnd, glob_dc);
  DeleteCriticalSection(&glob_mtx);
  if (minimize != 0)
    SetWindowPlacement(h_wnd, &wpl);

  if (glob_col == CLR_INVALID)
    return 0;

  p_pixel->x = glob_pt.x;
  p_pixel->y = glob_pt.y;
  p_pixel->r = GetRValue(glob_col);
  p_pixel->g = GetGValue(glob_col);
  p_pixel->b = GetBValue(glob_col);
  return 1;
}


Hauptcode (C)
#include <stdio.h>
#include "clickpixel.h" 

int main(int argc, char *argv)
{
  PIXEL pxl = {0};
  if (!GetClickedPixel(&pxl, 1))
    return 1;

  printf("x: %ld, y: %ld\nr: %d, g: %d, b: %d\n", pxl.x, pxl.y, pxl.r, pxl.g, pxl.b);  
  return 0;
}
oder Hauptcode (C++)
#include <iostream>
#include "clickpixel.h" 

int main(int argc, char *argv)
{
  PIXEL pxl{};
  if (!GetClickedPixel(&pxl, 1))
    return 1;

  std::cout << "x: " << pxl.x << ", y: " << pxl.y << "\nr: " << pxl.r << ", g: " << pxl.g << ", b: " << pxl.b << std::endl;  
  return 0;
}

Steffen
colinardo
colinardo 26.12.2017 aktualisiert um 16:03:39 Uhr
Goto Top
Servus Steffen,
Zitat von @rubberman:

Nanu? Das ist doch weder C noch C++, Uwe.
Nun, was er letztendlich wollte habe ich aus seinem Code schlussgefolgert, da er hier das Fragment cursor.X usw. benutzte erschien mir die Annahme das er c# benutzt, doch das naheliegendste zu sein und da es hier keine Kategorie c# gibt ...
Jetzt hat er ja die Wahl face-smile

Gut's Neues schonmal
Grüße Uwe
rubberman
rubberman 26.12.2017 um 15:41:15 Uhr
Goto Top
Hallo Uwe

Zitat von @colinardo:
habe ich aus seinem Code schlussgefolgert
Japp, ich auch. int main()etc. face-wink

da es hier keine Kategorie c# gibt ...
Ja, das ist ein Problem. @Frank sollte da nachbessern, denn C# hat mit C oder C++ überhaupt nichts zu tun, auch wenn Fragen bzgl. C# überwiegend hier landen. Eigentlich ist es schon ein no-go, C und C++ zusammen zu schmeißen, da nahezu niemand in seiner Frage schreibt um welche Sprache es eigentlich geht, aber C und C++ schon vom Paradigma unterschiedlicher gar nicht sein könnten...

Steffen
tomaschku
tomaschku 28.12.2017 um 14:47:32 Uhr
Goto Top
Hallo,
Gerade habe ich viel zu tun, aber ich werde nach Möglichkeit die Codes mal ausprobieren.
LG,
tomaschku