Access Color of Bitmap
-
Hi,
ich versuche verzweifelt die Farben aus einer Bitmap auszulesen. Hier mein Versuch:[code="cpp"]
this->hBitmap = (HBITMAP)LoadImage(GetModuleHandle(NULL), FileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); // TestBitmap laden (5 * 5 Pixel groß)HDC hDC = GetDC(NULL);
HDC hDC_Mem = CreateCompatibleDC(hDC);
HDC hDC_Target = CreateCompatibleDC(hDC_Mem);BITMAP bitmap;
GetObject(hBitmap, sizeof(BITMAP), &bitmap);SelectObject(hDC_Mem, hBitmap);
HBITMAP CompatibleBitmap = CreateCompatibleBitmap(hDC_Mem,
bitmap.bmWidth, bitmap.bmHeight);SelectObject(hDC_Target, CompatibleBitmap);
BitBlt(hDC_Target, 0, 0, bitmap.bmWidth, bitmap.bmHeight,
hDC_Mem, 0, 0, SRCCOPY);FILE *fptr;
fopen_s(&fptr, PfadZurBitmap, "rb+");
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
fread(&bmfHeader, sizeof(BITMAPFILEHEADER), 1, fptr);
fread(&bi, sizeof(BITMAPINFOHEADER), 1, fptr);
fclose(fptr);
DWORD BmpSize = bmfHeader.bfSize - sizeof(BITMAPFILEHEADER) - sizeof(BITMAPINFOHEADER);
HANDLE hDIB = GlobalAlloc(GHND, BmpSize);
color *arr = (color*)GlobalLock(hDIB);GetDIBits(hDC_Mem, CompatibleBitmap, 0, (UINT)bitmap.bmHeight,
arr, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
[code]Wenn ich mir nun die Farben ausgeben lasse sind diese durchaus realistisch, ganze Zahlen wie sie auch in der Bitmap vorkommen (z.B. (50, 50, 50) (250, 250, 0) ).
Dennoch sind diese wild durcheinander gewürfelt und auch nicht immer in der richtigen reihenfolge ... statt (0, 0, 50) z.B. (50, 0, 0)
Leider weiß ich nicht, warum das Array was ich zurückgeliefert bekomme derart durcheinander ist und wie ich nun gezielt auf die Pixelfarben zugreifen kann
Ich hoffe ihr könnt ihr mir weiterhelfen
Grüße Mark
-
Erstmal wäre es nett wenn du die Codetags so verwendest das sie funktionieren.
In deinem Code wird die Datei zweimal gelesen. Warum ?
Wenn man es lowlevel versucht muss man sich mit diversen Problemen beschäftigen,
die das Dateiformat betreffen.Ich habe zum Test mal eine kleine BMP-Datei angelegt. Offensichtlich wird bei kleinen Bitmaps nicht ein
BITMAPINFOHEADER sondern nur ein BITMAPCOREHEADER verwendet. Man muss das feststellen und darauf reagieren.Hier mein Vorschlag:
FILE *fptr; errno_t err = _wfopen_s( &fptr, FileName, TEXT("rb+")); BITMAPFILEHEADER bmfHeader; BITMAPCOREHEADER bicore; BITMAPINFOHEADER biinfo; LONG Width, Height; size_t fheadlen = fread(&bmfHeader, 1, sizeof(BITMAPFILEHEADER), fptr); size_t infolen = fread(&bicore, 1, sizeof(BITMAPCOREHEADER), fptr); printf("Groesse Header: %ld, INFOSTRUCT:%ld\n", (long)bmfHeader.bfSize, (long)bicore.bcSize); switch( bicore.bcSize) { case sizeof(BITMAPCOREHEADER): Width = bicore.bcWidth; Height = bicore.bcHeight; break; case sizeof(BITMAPINFOHEADER): // Zeiger zurueck, neu lesen fseek(fptr, sizeof(BITMAPFILEHEADER), SEEK_SET); infolen = fread(&biinfo, 1, sizeof(BITMAPINFOHEADER), fptr); Width = biinfo.biWidth; Height = biinfo.biHeight; break; default: printf("Achtung: BitmapInfoHeader unbekannt! \n"); return -1; } // Zeiger auf Daten int fpos = fseek(fptr, bmfHeader.bfOffBits, SEEK_SET); // Datengroesse berechnen DWORD BmpSizeFile = bmfHeader.bfSize - bmfHeader.bfOffBits; BYTE *bmdata = (BYTE *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, BmpSizeFile); size_t datalen = fread(&bmdata, 1, BmpSizeFile, fptr); fclose(fptr);
Die Daten sollten dann als BGR (Tripple-Byte) im Speicher liegen. Angefangen wird immer mit der letzten Zeile
und diese wird so aufgefüllt, das die Anzahl der Bytes pro Zeile durch 4 teilbar ist.Habs sicherheitshalber gerade nochmal geprüft.
-
Wenn du schon das Bitmap in einem DC hast kannst du GetPixel und SetPixel benutzen. Hast du mal das Bitmap angezeigt, ob es richtig geladen wurde?
Du kannst auch DevIl mit ilutConvertToHBitmap benutzen und dir den ganzen Aufwand sparen.