Farbe eines Pixels aus BMP monochrom abfragen

Hi!

Ich habe ein Bitmap (monochrom, enthält also nur schwarze und weiße Pixel). Nun würde ich dieses Bitmap gerne öffnen und dann mit einer Funktion das Pixel mit der Position x:10 y:5 lesen. Wenn das Pixel schwarz ist, soll die Funktion 0 zurückliefern, sonst soll sie 1 zurückliefern. Der Quellcode soll also etwa so aussehen:

#include

int getpixel(FILE *fp, int x, int y)
{
//Datei lesen und Pixel auslesen
if(pixel==schwarz) //Nur Pseudocode, ich weiß ja nicht, wie die Datei gelesen wird und was zurückgegeben wird
{
return 0;
}
else if(pixel==weiss) //Ebenfalls nur Pseudocode
{
return 1;
}
}

int main()
{
FILE *bild;
int pixelfarbe;
bild=fopen(„bild.bmp“,„r“); //Hier bin ich mir nicht sicher, ob der Lesemodus vielleicht binär sein muss, also ‚rb‘
pixelfarbe=getpixel(bild,10,5);
if(pixelfarbe==0)
{
printf(„Pixel ist schwarz!“);
}
else if(pixelfarbe==1)
{
printf(„Pixel ist weiss!“);
}
fclose(bild);
return 0;
}

Ich verwende TurboC von Borland. (Ja, dieses alte DOS-Programm :smiley:)

VG,
nano99

Hallo,

Ich bin nicht sicher in TurboC, da ich in letzter Zeit ausschliesslich in C#-Net gearbeitet habe.
Dort würde ich das Bild versteckt laden und dann direkt den Wert des Pixels abfragen.

Wenn Du jedoch mit TurboC unter Dos arbeitest müsstest Du wahrscheinlich im Dateiheader der Datei erst einmal das Bildformat auslesen (vermutlich feste Positionen im Dateiheader), dann die Datei schliessen,
dann aus Größe des Dateiheaders, Height und Width die Position Deines Pixels als soundsovieltes Byte in der Datei bestimmen, dieses Byte in einem zweiten Durchlauf aus der Datei lesen und ggf. noch mit AND den Wert des Pixels bestimmen wenn das Byte den Wert mehrerer Pixel codiert. Datentypbeschreibungen findet man z.B. unter wotsit.org .

Dein gesuchtes Pixel könnte dann möglicherweise im Byte Headerlänge + 5*BildBreite + 10 stecken.

Experimentell kannst Du auch weisse Bilder verschiedener Formate mit nur schwarzem Pixel an der Wunschposition mit einem Grafikprogramm erzeugen und die Byteposition mit einem Hexdump-Viewer vergleichen.

Ich hoffe diese Vorbemerkungen helfen Dir erst einmal weiter.

Hi,

sorry, da kann ich Dir leider nicht weiterhelfen, meine Kenntnisse in dieser Sprache sind zu schlecht.

Gruß

Hermann

Kann ich Dir so aus dem Stand nicht sagen.
Aber guggemaal hier ;

http://de.wikipedia.org/wiki/Windows_Bitmap

Viel Erfolg !

drs

Hi,

so einfach ist das nicht selbst zu programmieren. In Java koennte ich Dir jetzt genau sagen, wie es funktioniert, da das mehr oder weniger nativ unterstuetzt wird und es da APIs fuer Bitmaps gibt etc.

Ich kenne das BMP Format jetzt nicht so genau, und wenn ich jetzt einen Teil der Spezifikation kennen wuerde, heisst es nicht, dass es fuer Dein BMP so ist, da das Format variieren kann, es gibt zig Varianten, wie eine BMP gespeichert werden kann.
Weiterer Punkt: Die Schnittstelle „int getpixel(FILE *fp, int x, int y)“ ist m.E. suboptimal, da man bei jedem Zugriff die Breite der Bitmap erneut ermitteln muesste, da die Pixel wahrscheinlich einfach hintereinander weg in der Datei geschrieben stehen.

just my 2 cents, sorry, dass es nicht ausfuehrlicher sein kann.

Hallo nano99,

Mit dem GDI+ steht hier was:
http://msdn.microsoft.com/en-us/library/windows/desk…

ohne Objektorientierten Wrapper ist es etwas komplizierter:

//File Laden
hBitmap = (HBITMAP) ::LoadImage (0, „bild.bmp“,IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

//memory DC beschaffen, hDC eines Fensters (GetWindowDC) oder von PeginPaint
HDC hMemDC = ::CreateCompatibleDC(hDC);

//bitmat reinladen

SelectObject(hMemDC, hBitmap );

//zielfunktion
COLORREF cr = GetPixel(hMemDC,XPOS,YPOS);

Bei dieser Methode hängt das Ergebnis u.U. von
dem mit dem hDC verknüpften Device ab; ich weiß
nicht ob sich dies Abhängigkeit irgenwie beseitigen
lässt. Wenn die Grafik sowieso irgenwo gezeichnet
wir ist das ja egal.
Ach ja un die Headerdateien nicht vergessen:
‚Windows.h‘ oder ‚Gdiplus.h‘ für das erste Bsp…

Schönen Gruß
andreas

Hallo

also grundsätzlich würde ich dir empfehlen einfach einen library zu verwenden die Bilder einliest. Ich würde OpenCV verwenden gibt aber viele alternativen.

Wenn du’s ohne Bibliothek machen willst kann ich dir momentan auch nicht wirklich weiter helfen. Da ich die Bitmap Spezifikation nicht kenne. (Auch wenn es vermutlich sehr einfach ist).

Mit der Library könntest natürlich mit deinem Compiler Probleme haben wenn. Aber ohne gute gründe, würde ich ohne hin zu einen moderneren raten (VisualStudio(Express)/Gcc/clang) gibt es alle gratis.

Hallo nano99,

ich bin mir jetzt gerade nicht ganz sicher, was du von mir erwartest. Einen Hinweis oder das fertige Programm?

Fangen wir einfach mit den Hinweisen an. Vom Prinzip her funktioniert das Ganze so:

  • Die Datei muss geöffnet werden.
  • Anschließend liest man die Header-Informationen aus.
  • Anhand der Header-Informationen erfährt man, um was für einen Typ von BMP-Datei es sich handelt.
  • Mit diesen Informationen kann man nun auf den Bildinhalt zugreifen. In deinem Fall auf genau dieses eine Pixel. Zum Schluss kommt noch deine Abfrage ob es sich um ein schwarzes oder weißes Pixel handelt – fertig!

Nun gibt es verschiedene Möglichkeiten. Gesetzten Falles, dass du genau weißt, um was für einen Typ von BMP-Datei es sich handelt, sich dieser nicht ändert und du immer gleich große Bilder hast, dann kannst du einmal herausfinden/ausrechnen an welcher Position in der Datei dieses Pixel steht und von da an kannst du immer nur die dazugehörigen Werte auslesen und dann deine Fallunterscheidung (schwarz/weiß) treffen. Dies wäre der einfachste Fall.

Sollte es einen Grund geben, warum dass Pixel x:10 y:5 nicht immer an der selben Stelle in der Datei zu finden ist – Dateien von verschiedenem Typ (Farbtiefe, Komprimierung, etc.) oder verschiedener Größe (wichtig bei einem gebräuchlichem bottom-up-Bitmap) – dann bleiben dir zwei Möglichkeiten:

Entweder du probierst mit den ganzen Unwägbarkeiten klarzukommen und rechnest unter Einbeziehung der oben genannten Dinge die Position des Pixels in der Datei aus und liest die entsprechenden Werte.

Oder du liest das komplette Bild mit Hilfe einer eigenen oder vorgefertigten Bitmap-Bibliothek ein und greifst dann auf das spezielle Pixel zu (hierfür bieten die Bibliotheken eine Möglichkeiten oder zumindest bekommst du ein Array mit den Daten, aus dem du dir das Pixel heraussuchen kannst).

Der zuallererst genannte, einfachste Fall ist wohl der schnellste, jedoch müssen die Bedingungen erfüllt sein. Falls diese es nicht sind, würde ich dazu tendieren eine Bibliothek zu verwenden.

Auf jeden Fall dürfte es gut sein, zu wissen, wie so eine BMP-Datei aufgebaut ist. Hierzu bietet sich die Wikipedia an (https://de.wikipedia.org/wiki/Windows_Bitmap), die alles schön auflistet. Ebenfalls dort verlinkt findet sich eine C+±Klasse (http://www.kalytta.com/bitmap.h), die BMP-Dateien einlesen kann. Diese könntest du auf deine Bedürfnisse anpassen oder du suchst nach einer speziellen (Turbo)C-Bibliothek.

Ich hoffe, ich konnte dir damit weiterhelfen.

Viele Grüße

Benjamin Radke

Hallo,

erstmal vielen Dank für die Antwort.
Da ich zwar in C schon etwas fortgeschritten bin, im Arbeiten mit Dateien und BMPs aber noch ein Anfänger bin, würde ich gerne einen kompletten Quellcode haben. :wink: Aber alle Dateizugriffe und ähnliches im Code sollten erklärt sein.
Über eine Antwort wäre ich sehr dankbar! :smile:

Viele Grüße,
nano99

P.S.: Falls es damit irgendwie einfacher ist, habe ich auch Microsoft Visual C++ 2010 Express, um C oder C++ Programme zu kompilieren.

Hallo nano99,
leider habe ich von Graphikbearbeitung keine Ahnung.
Aber warum muss es eigentlich TurboC sein? In den Modernen Sprachen wie C# ist es bestimmt leichter die gewünschte Funktion zu finden.

Hallo nano99,

leider bin ich nicht ganz so firm in C und es ist auch schon ein Weilchen her, dass ich damit gearbeitet habe. Außerdem reicht bei mir die Zeit nicht, mich dort wieder richtig einzuarbeiten.

Ich habe es dennoch probiert und folgende Ergebnisse. Als Bibliothek kommt nach kurzer Google-Suche FreeImage in Betracht (http://freeimage.sourceforge.net/). Als Grundlage habe ich ein Beispielprojekt, welches beim Download mitgeliefert wird genommen. Den Quelltext habe ich etwas angepasst und folgendes daraus gemacht:

#include
#include „FreeImage.h“

int main(void)
{
FIBITMAP *dib,*ptr;
RGBQUAD *value;

// initialize the FreeImage library
FreeImage_Initialise(FALSE);

dib = FreeImage_Load(FIF_BMP, „test.bmp“, BMP_DEFAULT);

if(FreeImage_GetPixelColor(dib, 10, 5, value))
{
printf(„Farbwert Rot: %d“, value.rgbRed);
}

FreeImage_Unload(dib);

// release the FreeImage library
FreeImage_DeInitialise();

return 0;
}

Leider kompiliert die Datei nicht – es gibt Probleme mit der Struktur RGBQUAD bzw. dem Zugriff auf rgbRed. Nach (sehr) kurzer Recherche musste ich wegen der Zeit abbrechen.

Später habe ich mich noch einmal kurz dran gesetzt. Dieses Mal habe ich aber zu VisualStudio 2012 und C# gegriffen. Hier sieht der Quelltext folgendermaßen aus:

using System;
using System.Drawing;

namespace BMP
{
class Program
{
static void Main(string[] args)
{
Bitmap bmp = new Bitmap(„test.bmp“);
Color c = bmp.GetPixel(10, 5);

if (c.R == 0 && c.G == 0 && c.B == 0)
{
Console.WriteLine(„Pixel ist schwarz“);
}
else if (c.R == 255 && c.G == 255 && c.B == 255)
{
Console.WriteLine(„Pixel ist weiß“);
}
else
{
Console.WriteLine(„Pixel ist weder schwarz noch weiß“);
}
}
}
}

Wie du siehst kommt man hier ohne eine fremde Bibliothek aus; es reichen die Bordmittel von .Net. Außerdem funktioniert das Programm!

Ich hoffe mal, du kannst mit zumindest einem der beiden Quelltexte etwas anfangen.

Viele Grüße und noch einen schönen Abend

Benjamin