Wie kann man die Abmessungen von Bildern auslesen?

cymoril

Grünschnabel
Hi!

Ich suche mit nem C-Programm (Konsolenanwendung) in einem bestimmten Ordner nach Bildern: jpg, png und bmp.
Dateiname und -größe bekomm ich raus.

Mir fehlt noch die Abmessung (Höhe, Breite) von jedem Bild. Wie kann ich die auslesen?

Bitte auch Beispiele und die einzubindenden Bibliotheken angeben.


So sieht meine Prozedur zum finden der Dateien aus:

void suchen (char *PFAD)
{
int DATSIZ;
WIN32_FIND_DATA DATDLL;
DATDLL.cFileName[0]='\0';

//Suche und Ausgabe der ersten Datei

HANDLE SUCHEN = FindFirstFile(PFAD, &DATDLL);

cout<<"Filename:\t"<<DATDLL.cFileName<<"\nFormat:\t\tJPG\n";
DATSIZ = DATDLL.nFileSizeLow;
cout<<"Size:\t\t"<<DATSIZ<<" bytes\n\n";

//Suche und Ausgabe der übrigen Dateien

while(FindNextFile(SUCHEN, &DATDLL))
{
cout<<"Filename:\t"<<DATDLL.cFileName<<"\nFormat:\t\tJPG\n";
DATSIZ = DATDLL.nFileSizeLow;
cout<<"Size:\t\t"<<DATSIZ<<" bytes\n\n";
}
}


Ich arbeite übrigens mit Dev-C++.
 
Hi!

Zuerst mal soviel: Die Auflösung steht IN den Bilddateien selbst drin. Du mußt den Header des jeweiligen Formattyps kennen und auswerten (beispielsw. BMP, siehe dazu diesen Link bei Wikipedia).

Damit solltest Du jetzt weiterkommen.


CU!

-Mike
 
Will ja nicht sagen, dass Wikipedia Unrecht hat, aber es kommt nicht das richtige raus. Die ersten beiden Zeichen werden richtig ermittel, nämlich: "BM". Der Rest passt nicht.

Mein Code zur Ermittlung der Maße:
-----------------------------------------------------
Code:
#include <iostream>
#include <fstream>
using namespace std;

int main(void)
{
    char name[21]="d:/test/Spatz.bmp";
    int h=0, b=0;
    char header[26];
     ifstream lesen;
     lesen.open(name);

     //Auslesen des Headers
     
      for(int i=0;i<26;i++)
      {   lesen>>header[i];   }
      lesen.close();
      cout<<header[0]<<header[1]<<endl;
      
//Breite und Höhe zu Integer konvertieren

      for(int i=18;i<21;i++)
      {     
       b+=(int)header[i];
       b= b<<4;
      }

      for(int i=21;i<26;i++)
      {     
       h+=(int)header[i];
       h= b<<4;
      } 
       
       cout<<endl<<"Breite:\t"<<b<<endl<<"H\x94he:\t"<<h<<endl; 

//Ende main
cout<<endl;
system("Pause");
return 0;
}


Breite soll also ab dem 18. Byte beginngen, Höhe ab dem 22.; beide 4 Byte groß.
Die Werte die das Programm ausgibt sind:
Breite: -85248
Höhe: -1363968.
Die stimmten natürlich nicht (tatsächliche Werte etwa:
Breite:1001
Höhe: -678 ).

Hat jemand ne Idee, was ich falsch mache und wie es richtig geht?
 
Zuletzt bearbeitet:
Hallo,

die Stream-Operatoren << und >> sind nur sehr bedingt für binäre Ein-/Ausgabe geeignet. Verwende stattdessen die Methode read. Beispiel:
C++:
ifstream lesen;
lesen.open(name);
lesen.seekg(18);

unsigned int h, b;
lesen.read(reinterpret_cast<char *>(&b), 4);
lesen.read(reinterpret_cast<char *>(&h), 4);

Grüße, Matthias
 
Wikipedia hat schon recht. Hier mal was schnell gehacktes:

Code:
#include <iostream>  // I/O 
#include <fstream>   // file I/O
#include <iomanip>   // format manipulation

 
using namespace std;
 
int main()
{
  ifstream fp_in;                   // declare
  char     c;
  long     Width;
  long     Height;


  cout << ">>> ReadBMP Header (Width & Height) <<<" << endl;

  Width  = 0;
  Height = 0;

  fp_in.open("nice.bmp", ios::in);  // open the stream

  fp_in.seekg(18);  // Skip 18 Bytes

  for (int i=0; i<4; i++) {
    fp_in >> c;
    Width = Width + ((((int)c) & 0xff) << (i*8));
  }

  for (int i=0; i<4; i++) {
    fp_in >> c;
    Height = Height + ((((int)c) & 0xff) << (i*8));
  }

  cout << "Breite = " << Width << " | Höhe = " << Height << endl;

  fp_in.close();                    // close the stream

}

Und der Output:

Code:
>>> ReadBMP Header <<<
Breite = 400 | Höhe = 316

Was Du beachten mußt, ist daß (int) nicht immer (int) ist. Auf verschiedenen Platformen umfaßt z. B. (int) zwei oder evtl. auch vier Bytes. Achso, Variablen immer initialisieren.


CU!

-Mike
 
Zuletzt bearbeitet:
Code:
  char     c;
  long     Width;
[...]
  for (int i=0; i<4; i++) {
    fp_in >> c;
    Width = Width + ((((int)c) & 0xff) << (i*8));
  }
So bitte nicht. Das kann zufällig funktionieren, aber im Allgemeinen geht es schief. Schau dir einfach mal an, was folgendes Programm ausgibt:
C++:
#include <iostream>
#include <sstream>

int main(void) {
  char c = 42;
  std::stringstream ss("\x0A");
  ss >> c;
  std::cout << (int)c << std::endl; // => 42

  return 0;
}
Also nochmal: >> und << niemals für binäre Ein-/Ausgabe verwenden! Dafür gibt es read und write.

Grüße, Matthias
 
Kannst Du mal begründen, warum das schiefgeht? Interessehalber...
Der Operator >> führt eine formatierte Eingabe durch. Das bedeutet insbesondere, dass bestimmte Steuer- und Leerzeichen (wie eben \0x0A) beim Einlesen einfach übergangen werden. Bei textuellen Daten kann das durchaus erwünscht sein, bei binären ändert sich dadurch aber die Bedeutung. Wie sich diese Operatoren verhalten (sollten), kann man im C++-Standard (PDF, 12MB) nachlesen. Interessant in diesem Zusammenhang sind die Abschnitte 27.6.1.2 ff. Dort sind auch die Methoden für unformatierte Eingabe aufgeführt (es gibt beispielsweise auch noch get in mehreren Überladungen).

Grüße, Matthias
 
Erst mal Danke, danke, danke.

Werd dann ne Weile brauchen, um das alles durchzuprobieren.

cu,
Cym

------------------------------

Dazu bin ich nun leider nicht mehr gekommen. Meine Zeit die Lösung zu finden ist sozusagen abgelaufen.
Ich meiner Freizeit hab ich nun auch schon so viel zu tun, dass ich da erst mal nicht mehr weiter mache.

Trotzdem vielen vielen Dank!!
Damit schließ ich das Thema.

mfg,
Cym
 
Zuletzt bearbeitet:
Zurück