Problem beim Ermitteln von Pixeldaten einer Bitmap
-
Hallo,
möchte eine etwas größere Bitmap verarbeiten. Im ersten Schritt geht es darum die Pixel des Bitmaps in eine Textdatei zu schreiben. Prinzipiell funktioniert dies auch, allerdings ist meine Verarbeitung fehlerhaft.
#include <stdio.h> #include <stdlib.h> #include <math.h> typedef unsigned short WORD; typedef unsigned long DWORD; typedef long LONG; #pragma pack(2) typedef struct bmpFileHeader { WORD typ; /* Magic Numbers ('BM' => 0x4D42) Offset = 0; */ DWORD groesse; /* Dateigröße Offset = 2; */ WORD res1; /* Reseviert Offset = 6; */ WORD res2; /* Reseviert Offset = 10; */ DWORD startPixeldaten; /* Beginn der Pixeldaten Offset = 14; */ } bmpfh; #pragma pack() typedef struct bmpInfoHeader { DWORD groesse; /* Größe bmpInfoHeader */ LONG breite; /* Breite der Bitmap (Pixel) */ LONG hoehe; /* Höhe der Bitmap (Pixel) */ WORD farbebenen; /* Immer = 1 */ WORD farbtiefe; /* Bitmap-Farbtiefe in bpp */ DWORD kompression; /* Angabe über eventuell verwendete Kompression */ DWORD bildGroesseByte; /* Größe der Bilddatei in Byte */ LONG pixelProMeterX; /* Pixel pro Meter (X) auf Ausgabegerät */ LONG pixelProMeterY; /* Pixel pro Meter (Y) auf Ausgabegerät */ DWORD farbtabelle; /* Anzahl der Einträge in Farbtabelle */ DWORD verwendeteFarben; /* Anzahl der im Bild verwendeten Farben */ } bmpih; int main() { FILE *eingabedatei = NULL; FILE *ausgabedatei = NULL; bmpFileHeader bmpfh; bmpInfoHeader bmpih; unsigned char R, G, B; int zeilen; int spalten; int i; int j; eingabedatei = fopen("TEST.bmp", "rb"); if (eingabedatei == NULL) return printf("Eingabedatei konnte nicht geoeffnet werden\n"); ausgabedatei = fopen("daten.txt", "w"); if (ausgabedatei == NULL) return printf("Ausgabedatei konnte nicht geoeffnet werden\n"); fseek(eingabedatei, 0, SEEK_SET); fread(&bmpfh, sizeof(bmpFileHeader), 1, eingabedatei); if (bmpfh.typ != 0x4D42) return printf("Es handelt sich um keine Bitmap\n"); fseek(eingabedatei, 0, SEEK_CUR); fread(&bmpih, sizeof(bmpInfoHeader), 1, eingabedatei); printf("Dateigroesse (Bytes) : %ld\n", bmpfh.groesse); printf("Beginn der Pixeldaten: %ld\n", bmpfh.startPixeldaten); printf("Bildgroesse (Pixel) : %ld x %ld\n", bmpih.breite, bmpih.hoehe); printf("Farbpalette (Bit) : %ld\n", bmpih.farbtiefe); printf("Farbanzahl : %2.0f\n", pow(2.0, (double)bmpih.farbtiefe)); fseek(eingabedatei, 54, SEEK_SET); zeilen = bmpih.hoehe; spalten = bmpih.breite; for (i = 0; i < zeilen ; i++) { for (j = 0; j < spalten ; j++) { fread(&B, sizeof(unsigned char), 1, eingabedatei); fread(&G, sizeof(unsigned char), 1, eingabedatei); fread(&R, sizeof(unsigned char), 1, eingabedatei); fprintf(ausgabedatei, "R = %3d | G = %3d | B = %3d\n", R, G, B); } } fclose(eingabedatei); fclose(ausgabedatei); return 0; }
Hier die Ausgabe:
R = 255 | G = 0 | B = 0 R = 255 | G = 255 | B = 255 R = 255 | G = 0 | B = 0 R = 0 | G = 0 | B = 0
Verwendet habe ich folgendes (hier stark vergrößertes) Bild:
http://upload.wikimedia.org/wikipedia/en/0/0d/Bmp_format.png
Nach dem BMP-Format müsste die Reihenfolge eigentlich so aussehen:
R = 255 | G = 0 | B = 0 R = 255 | G = 255 | B = 255 R = 0 | G = 0 | B = 255 R = 0 | G = 255 | B = 0
Danke im Voraus!
-
Nachtrag: Mit "eine etwas größere Bitmap" ist natürlich eine andere Bitmap als die hier (beispielhaft) verwendete Bitmap gemeint.
-
hi,
da ich genau das gebraucht habe was du da geschrieben hast, warst du mir erst einmal eine große Hilfe
aber du hast Recht, du hast einen kleinen Fehler eingebaut... hast du mal bei Wikipedia geschaut? nach jeder Pixelzeile sind 2 zusätzliche Bytes gespeichert mit irgendwelchen infos über die row... diese musst du natürlich nach jeder Zeile überspringen... ich habe das elegant mit einer Variable gelöst schau:
erstmal die Variable deklarierenint offset;
dann schreibst du for deine doppelforschleife
seeker = 54; fseek(eingabedatei, seeker, SEEK_SET);
nach der ersten for-schleife dann die 2 bytes überspringen:
seeker += j*3 + 2; fseek(eingabedatei, seeker, SEEK_SET);
und schon klappts prima
-
sry hatte murks geschrieben da ich kurzfristig den namen der variablen geändert hatte : hier nochmal alles komplett:
erst offset deklarierenint offset;
dann
// offset auf Beginn der Pixel einstellen offset = 54; fseek(eingabedatei, offset, SEEK_SET); zeilen = bmpih.hoehe; spalten = bmpih.breite; printf("%d Zeile(n), %d Spalte(n)\n", zeilen, spalten); for (i = 0; i < zeilen ; i++) { for (j = 0; j < spalten ; j++) { fread(&B, sizeof(unsigned char), 1, eingabedatei); fread(&G, sizeof(unsigned char), 1, eingabedatei); fread(&R, sizeof(unsigned char), 1, eingabedatei); fprintf(ausgabedatei, "R = %3d | G = %3d | B = %3d\n", R, G, B); } // nach jeder row 2 bytes vorspulen offset += j*3 + 2; fseek(eingabedatei, offset, SEEK_SET); }