Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Kolejność kolorów w pikselach, GDI32

Ostatnio zmodyfikowano 2016-09-04 00:49
Autor Wiadomość
AnusIsRael
Temat założony przez niniejszego użytkownika
Kolejność kolorów w pikselach, GDI32
» 2016-09-01 21:58:54
Witam, otóż ostatnio postanowiłem napisać program, który miałby kopiować obszar pikseli z ekranu do bufora a następnie go przetwarzać. Wygląda on następująco:

C/C++
#include "windows.h"
#include "stdio.h"
#include "cstdint"

//Rozmiar obszaru
#define X 138
#define Y 138
#define Size X*Y

//Lewy górny róg kwadratu - miejsce początku kopiowania
#define StartX 892
#define StartY 530

uint8_t * pPixel;

uint8_t * GetSquare() //Funkcja wczytująca matryce pikseli
{
    HDC CurrentWindow = GetDC( NULL );
    HDC Temp = CreateCompatibleDC( CurrentWindow ); //Bufor...
   
    BITMAPINFO iBitmap;
   
    //138 na 138 pikseli 24b bez kanału alfa
    //całkowity rozmiar obrazu 138*138*3B
   
    iBitmap.bmiHeader.biSize = sizeof( iBitmap.bmiHeader );
    iBitmap.bmiHeader.biWidth = X;
    iBitmap.bmiHeader.biHeight = Y;
    iBitmap.bmiHeader.biPlanes = 1;
    iBitmap.bmiHeader.biBitCount = 24;
    iBitmap.bmiHeader.biCompression = BI_RGB;
    iBitmap.bmiHeader.biSizeImage = X * 3 * Y;
    iBitmap.bmiHeader.biClrUsed = 0;
    iBitmap.bmiHeader.biClrImportant = 0;
   
    //Uzyskuje znacznik do bitmapy na nowej matrycy
   
    HBITMAP hBitmap = CreateDIBSection( Temp, & iBitmap, DIB_RGB_COLORS,( void ** )( & pPixel ), NULL, 0 );
   
    SelectObject( Temp, hBitmap );
   
    //Kopiuję piksele z "wyświetlacza" do nowego bufora Temp
   
    BitBlt( Temp, 0, 0, X, Y, CurrentWindow, StartX, StartY, SRCCOPY );
   
    return pPixel; //Zwracam znacznik
}

int main( int argc, char ** argv )
{
    system( "PAUSE" );
    uint8_t * temp = GetSquare();
   
    //Kolejność kolorów ulega zmianie co 138 pikseli, dlaczego?
    //Zaczyna od BGR
    for( int i = 0; i <( Size * 3 ); i += 3 ) {
        printf( "RED %u\n", temp[ i ] );
        printf( "GREEN %u\n", temp[ i + 1 ] );
        printf( "BLUE %u\n", temp[ i + 2 ] );
        printf( "%u\n", i );
    }
    system( "PAUSE" );
}

Cały problem polega na tym, że kolejność reprezentacji kolorów ulega zmianie co szerokość ramki (138 pikseli), czyli co 138*3 i. Reprezentacja zaczyna się od BGR (przesunięcie o 2 bajty), po czym przechodzi chyba przez każdą możliwą kombinacje (RGB, GBR, RBG, etc...) Wychodzi na to, że gubie gdzieś jeden bajt co wiersz, dlaczego?
Używam GCC w wersji 5.1.0 (g++ -O3 -std=c++14 -o file.exe file.cpp -lgdi32) pod windowsem 10 pro x64
Log kompilacji jest czysty, tzn: żadnych błędów, uwag.
Będę wdzięczny za każdą sugestie :)
~AIR
P-151305
pekfos
» 2016-09-01 23:21:30
Linie są wyrównane do wielokrotności rozmiaru DWORD.
P-151307
AnusIsRael
Temat założony przez niniejszego użytkownika
» 2016-09-01 23:51:11
Zmieniłem BitCount na 32 więc jest wielokrotnością DWORD, tymczasem problem pozostaje.
C/C++
iBitmap.bmiHeader.biSize = sizeof( iBitmap.bmiHeader )
iBitmap.bmiHeader.biWidth = X;
iBitmap.bmiHeader.biHeight = Y;
iBitmap.bmiHeader.biPlanes = 1;
iBitmap.bmiHeader.biBitCount = 32;
iBitmap.bmiHeader.biCompression = BI_RGB;
iBitmap.bmiHeader.biSizeImage = X * 4 * Y;
iBitmap.bmiHeader.biClrUsed = 0;
iBitmap.bmiHeader.biClrImportant = 0;

EDIT: Problem rozwiązany, okazuje się, że wartości podawane są domyślnie w BGR. Dzięki za pomoc :)!
P-151309
pekfos
» 2016-09-02 00:08:18
Czy to zmienisz, czy nie, musisz zmodyfikować swoją pętlę w main().
P-151311
AnusIsRael
Temat założony przez niniejszego użytkownika
» 2016-09-02 00:38:31
Tak zrobiłem :v
P-151313
Rashmistrz
» 2016-09-02 18:16:54
Linie są wyrównane do wielokrotności rozmiaru DWORD.
Zmieniłem BitCount na 32 więc jest wielokrotnością DWORD, tymczasem problem pozostaje.

Emmmm... ale to linie mają być wyrównane, a nie piksele... Tak powiedział Pekfos.
// (do adresu który jest wielokrotnością DWORD)

// twój kod:
C/C++
for( int i = 0; i <( Size * 3 ); i += 3 ) {
    printf( "RED %u\n", temp[ i ] );
    printf( "GREEN %u\n", temp[ i + 1 ] );
    printf( "BLUE %u\n", temp[ i + 2 ] );
    printf( "%u\n", i );
}


Jak dobrze zrozumiałem to powinno być tak:
Wypisujesz jedną linijkę, wyrównujesz zmienną indeksową
do wielokrotności 4-rech i wypisujesz kolejną linijkę.
Czynność powtarzaj do wypisania wszystkiego...
czy jak tam wolisz.
P-151338
AnusIsRael
Temat założony przez niniejszego użytkownika
» 2016-09-04 00:49:46
Przecież napisałem, że zmieniłem pętle razem z headerem :v
C/C++
for( int i = 0; i <( Size * 4 ); i += 4 ) {
    printf( "RED %u\n", temp[ i ] );
    printf( "GREEN %u\n", temp[ i + 1 ] );
    printf( "BLUE %u\n", temp[ i + 2 ] );
    printf( "%u\n", i );
}

Myślałem, że błąd występuje nadal, gdyż nie wiedziałem, że kolory zapisane są w BGRA a nie RGBA.
P-151410
« 1 »
  Strona 1 z 1