# Farbe eines Pixels auslesen



## import java.dev.org (16. Feb 2017)

Hallo,
ich such jetzt schon seit 5 Tagen nach der Lösung, aber ich bekomm es einfach nicht hin.

Ich benutze SDL2 und C++. Und ich will die Farbe eines bestimmten Pixels, z.B: an der Position x=300, y=250 auslesen in RGB Format.

Ich hab im Internet zwar viele Lösungen gefunden, aber bei allen stürzt mein Programm ab, vielleicht findet jemand den Fehler, oder kann mir sogar einen kleinen Code geben, der funktioniert (natürlich nicht zum sturren abschreiben, sondern dass ich versteh wie es richtig geht)
Naja... hier erstmal mein Code:



Spoiler





```
#include "Game.h"
#include "windows.h"


#include <SDL2\SDL.h>
#include <iostream>

// name: AmericaGame / Game.cpp
// author: Lukas Mrosek
// version: 1.0
// date: 09.02.2017
// developed for Augustinus-Gymnasium-Weiden

using namespace std;

#pragma once
bool Game::start() {
    // variables
    high = GetSystemMetrics(SM_CXSCREEN);
    width = GetSystemMetrics(SM_CYSCREEN);

    // init SDL with grafical driver
    if (SDL_Init(SDL_INIT_EVERYTHING) != 0)                                                    {

        std::cerr << "SDL ERROR! MSG:" << SDL_GetError() << std::endl;
        exit(-1);
    }


    // create window
    window = SDL_CreateWindow("AmericaGame", 0, 0, high, width, SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN);
    if (window == NULL){
        std::cerr << "SDL WINDOW ERROR! MSG:" << SDL_GetError() << std::endl;
        exit(-1);
    }


    // create renderer
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);          
    if (renderer == NULL)
    {
        std::cerr << "SDL RENDERER ERROR! MSG:" << SDL_GetError() << std::endl;
        exit(-1);
    }

    background = new Texture(renderer, "bg.bmp");
    background->Draw(0, 0, high, width);


    team1 = new Team("Republikaner");
    team2 = new Team("Demokraten");

    // init states
    initStates();

    SDL_RenderPresent(renderer);
}

void Game::run() {
    running = true;
    while (running) {

        SDL_Event event;
        while (SDL_PollEvent(&event)){
            switch (event.type){
            case SDL_QUIT:
                running = false;
                break;
            case SDL_KEYDOWN:
                switch (event.key.keysym.sym) {
                case SDLK_ESCAPE:
                    running = false;
                    break;
                }
                break;
            case SDL_MOUSEBUTTONDOWN:
                switch (event.button.button) {
                case SDL_BUTTON_LEFT:
                    int xm, ym;
                    SDL_GetMouseState(&xm, &ym);

                   ///////////////////////////////////////////////////////////////////////////////////////////
                   ///////////////////////////////////////////////////////////////////////////////////////////
                   //Dies ist die Auffällige Codemakierung, damit ihr wisst, welche Zeile ich meine //
                   ///////////////////////////////////////////////////////////////////////////////////////////
                   ///////////////////////////////////////////////////////////////////////////////////////////

                  
                   SDL_Surface* img = SDL_GetWindowSurface(window);
                  SDL_PixelFormat* fmt = img->format;
                  SDL_LockSurface(img);
                  Uint32 pixels;
                  Uint8 r, g, b;
                  pixels = getpixel32(img, xm, ym);
                  SDL_GetRGB(pixels, fmt, &r, &g, &b);
                  SDL_UnlockSurface(img);
                 std::cout << "\n\n Rot: " << (int)r << endl;*/
                }
            }
        }
    }

    // shutdown SDL
    SDL_Quit();
}
Uint32 Game::getpixel32(SDL_Surface *surface, int x, int y)
{
    int bpp = surface->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to retrieve */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

    switch (bpp) {
    case 1:
        return *p;
        break;

    case 2:
        return *(Uint16 *)p;
        break;

    case 3:
        if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
            return p[0] << 16 | p[1] << 8 | p[2];
        else
            return p[0] | p[1] << 8 | p[2] << 16;
        break;

    case 4:
        return *(Uint32 *)p;
        break;

    default:
        return 0;       /* shouldn't happen, but avoids warnings */
    }
}
```




So, bei der "auffälligen Codemakierung" geht die Stelle los, wo ich die Pixelfarbe auslesen will,
Seltsamerweise wird für Rot immer 0 ausgegeben, und ich hab keine Ahnung, wieso, selbst wenn ich auf reines Rot klicke....

Hoffentlich kann mir jmd helfen! Ich brauch das für die Schule ganz dringen und ich bin echt am verzweifeln :/


----------



## Thallius (16. Feb 2017)

Ich würde jetzt mal grob raten, dass getPixel Dir einen RGBA Wert zurück liefert und keinen RGB. Das Ganze dann wahrscheinlich noch in LittleIndian. Das sieht man aber natürlich nur, wenn man sich den Pixelwert mal als hexwert ausgeben läßt

Gruß

Claus


----------



## import java.dev.org (16. Feb 2017)

Thallius hat gesagt.:


> Ich würde jetzt mal grob raten, dass getPixel Dir einen RGBA Wert zurück liefert und keinen RGB. Das Ganze dann wahrscheinlich noch in LittleIndian. Das sieht man aber natürlich nur, wenn man sich den Pixelwert mal als hexwert ausgeben läßt
> 
> Gruß
> 
> Claus


Get_RGB liefert einen RGB Wert, get_RGBA einen RGBA wert 
Das mt dem Hexwert klingt vernünftig, sry dass ich jetzt so blöd frag, aber wie geht das


----------



## Thallius (16. Feb 2017)

import java.dev.org hat gesagt.:


> Get_RGB liefert einen RGB Wert, get_RGBA einen RGBA wert



ein RGB Wert hat aber nunmal nur 24bit und keine 32. Also muss auch bei Get_RGB irgendwas in den restlichen 8 bit stehen. Wenn das dann Nullen sind, würde das z.B. bei LittleEndian erklären warum dein Rot immer 0 ist, denn bei RGB0 steht der 0 wert bei LittleEndian in den ersten 8 Bits.



> Das mt dem Hexwert klingt vernünftig, sry dass ich jetzt so blöd frag, aber wie geht das



printf("%08lx", wert)


----------



## import java.dev.org (16. Feb 2017)

Hab jetzt SDL_getRGBA benutzt und printf("%08lx", wert), jetzt wird nichtmehr 0, sondern 00000000 ausgegeben...


----------



## VfL_Freak (16. Feb 2017)

Moin,


import java.dev.org hat gesagt.:


> Hab jetzt SDL_getRGBA benutzt und printf("%08lx", wert), jetzt wird nichtmehr 0, sondern 00000000 ausgegeben...


hmm, eine dezimale Null ist auch hexadecimal Null ??? 

Zeig doch mal den genauen Code, mit dem Du das gemacht hast ... 

Gruß Klaus


----------



## import java.dev.org (16. Feb 2017)

Der steht doch in meiner Frage ^^



Spoiler





```
#include "Game.h"
#include "windows.h"


#include <SDL2\SDL.h>
#include <iostream>

// name: AmericaGame / Game.cpp
// author: Lukas Mrosek
// version: 1.0
// date: 09.02.2017
// developed for Augustinus-Gymnasium-Weiden

using namespace std;

#pragma once
bool Game::start() {
    // variables
    high = GetSystemMetrics(SM_CXSCREEN);
    width = GetSystemMetrics(SM_CYSCREEN);

    // init SDL with grafical driver
    if (SDL_Init(SDL_INIT_EVERYTHING) != 0)                                                    {

        std::cerr << "SDL ERROR! MSG:" << SDL_GetError() << std::endl;
        exit(-1);
    }


    // create window
    window = SDL_CreateWindow("AmericaGame", 0, 0, high, width, SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN);
    if (window == NULL){
        std::cerr << "SDL WINDOW ERROR! MSG:" << SDL_GetError() << std::endl;
        exit(-1);
    }


    // create renderer
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);        
    if (renderer == NULL)
    {
        std::cerr << "SDL RENDERER ERROR! MSG:" << SDL_GetError() << std::endl;
        exit(-1);
    }

    background = new Texture(renderer, "bg.bmp");
    background->Draw(0, 0, high, width);


    team1 = new Team("Republikaner");
    team2 = new Team("Demokraten");

    // init states
    initStates();

    SDL_RenderPresent(renderer);
}

void Game::run() {
    running = true;
    while (running) {

        SDL_Event event;
        while (SDL_PollEvent(&event)){
            switch (event.type){
            case SDL_QUIT:
                running = false;
                break;
            case SDL_KEYDOWN:
                switch (event.key.keysym.sym) {
                case SDLK_ESCAPE:
                    running = false;
                    break;
                }
                break;
            case SDL_MOUSEBUTTONDOWN:
                switch (event.button.button) {
                case SDL_BUTTON_LEFT:
                    int xm, ym;
                    SDL_GetMouseState(&xm, &ym);

                   ///////////////////////////////////////////////////////////////////////////////////////////
                   ///////////////////////////////////////////////////////////////////////////////////////////
                   //Dies ist die Auffällige Codemakierung, damit ihr wisst, welche Zeile ich meine //
                   ///////////////////////////////////////////////////////////////////////////////////////////
                   ///////////////////////////////////////////////////////////////////////////////////////////

                
                   SDL_Surface* img = SDL_GetWindowSurface(window);
                  SDL_PixelFormat* fmt = img->format;
                  SDL_LockSurface(img);
                  Uint32 pixels;
                  Uint8 r, g, b;
                  pixels = getpixel32(img, xm, ym);
                  SDL_GetRGB(pixels, fmt, &r, &g, &b);
                  SDL_UnlockSurface(img);
                 std::cout << "\n\n Rot: " << (int)r << endl;*/
                }
            }
        }
    }

    // shutdown SDL
    SDL_Quit();
}
Uint32 Game::getpixel32(SDL_Surface *surface, int x, int y)
{
    int bpp = surface->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to retrieve */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

    switch (bpp) {
    case 1:
        return *p;
        break;

    case 2:
        return *(Uint16 *)p;
        break;

    case 3:
        if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
            return p[0] << 16 | p[1] << 8 | p[2];
        else
            return p[0] | p[1] << 8 | p[2] << 16;
        break;

    case 4:
        return *(Uint32 *)p;
        break;

    default:
        return 0;       /* shouldn't happen, but avoids warnings */
    }
}
```


----------



## import java.dev.org (17. Feb 2017)

Egal, hab das Problem selbst gelöst, das Fenster war vorher Fullscreen, jetzt nichtmehr und es geht 
Danke an alle die mir geholfen haben


----------

