2015-12-11 1 views
1

J'ai un petit fichier bmp et je veux obtenir les valeurs RVB de chaque pixel et afficher ces valeurs dans un fichier txt si R, G et B ne sont pas tous zéro. J'ai écrit le programme suivant; il lit correctement les données d'en-tête, mais les valeurs RVB ne viennent pas. Je suppose que j'ai fait quelque chose de mal dans la boucle for.Lecture de pixels RVB à partir du fichier bmp

#include <iostream> 
#include <fstream> 
#include <cstdlib> 

using namespace std; 

int main() 
{ 
ifstream ifs; 
ofstream ofs; 
char input[80]; 
char output[80]; 

cout<<"Input file name"<<endl; 
cin>>input; 
ifs.open(input, ios::binary); 

if(!ifs) 
{ 
    cout<<"Error in opening file"<<endl; 
    system("pause"); 
    return 0; 
} 

cout<<"Output file name"<<endl; 
cin>>output; 
ofs.open(output, ios::binary); 

ifs.seekg(2); 

int file_size; 
ifs.read((char*)&file_size, sizeof(int)); 

ofs<<"Bitmap size: "<<file_size<<"\r\n"; 

ifs.seekg(10); 
int beg; 
ifs.read((char*)&beg, sizeof(int)); 

ofs<<"Beggining of image: "<<beg<<"\r\n"; 

ifs.seekg(18); 
int columns; 
ifs.read((char*)&columns, sizeof(int)); 

ofs<<"Column number: "<<columns<<"\r\n"; 

ifs.seekg(22); 
int rows; 
ifs.read((char*)&rows, sizeof(int)); 

ofs<<"Row number: "<<rows<<"\r\n"; 

int image_size=0; 
columns+=(3*columns)%4; 
image_size=3*columns*rows; 

ofs<<"Size of image"<<image_size<<"\r\n"; 

ifs.seekg(beg); 

unsigned char R,G,B; 
for(int i=0; i<image_size; i+=3) 
{ 
    ifs.read((char*)&B, sizeof(unsigned char)); 
    ifs.read((char*)&G, sizeof(unsigned char)); 
    ifs.read((char*)&R, sizeof(unsigned char)); 

    if(R!=0 || G!=0 || B!=0) 
    ofs<<"R: "<<R<<" G: "<<G<<" B: "<<B<<" position in file: "<<ifs.tellg()<<"\r\n"; 
} 


system("pause"); 
    return 0; 


} 
+2

Le format de fichier BMP est un peu plus impliqué que vous ne le pensez. Utilisez une bibliothèque au lieu de lancer votre propre importateur BMP. – IInspectable

Répondre

1

Je courais le code et il fonctionne très bien, je suppose que vous entendez par « valeurs RVB ne sont pas à venir » vous ne voyez pas les valeurs entières, auquel cas ce fixerai:

ofs<<"R: "<<int(R)<<" G: "<<int(G)<<" B: "<<int(B)<<" position in file: "<<ifs.tellg()<<"\r\n"; 

Mise à jour: J'ai posté plus tôt que vous pourriez remplacer ifs.read() avec ifs >> R >> G >> B; Comme le souligne @Benjamin Lindley, cela est incorrect car l'opérateur >> est pour du texte formaté, pas binaire. Cela signifie que si le fichier contient par exemple un caractère espace/newline/etc, l'opérateur l'ignorera et prendra le caractère suivant. Mieux vaut utiliser ifs.get (char) dans ce cas simple.

+0

À moins bien sûr que @IInspectable le signale, le fichier n'est pas aussi simple que celui que j'ai utilisé pour tester, dans ce cas, obtenir une bibliothèque et l'utiliser pour inspecter les images internes –

+0

Merci beaucoup! :) C'est exactement ce que je voulais. –

+0

J'ai raté ce casting plusieurs fois! Content que cela ait aidé. Pouvez-vous marquer mon message comme réponse? –

0

Vous faites plusieurs suppositions sur le codage de l'image que vous devez vérifier.

Si vous regardez le BMP header, vous verrez:

  • à l'offset 28 que le fichier ne doit pas nécessairement 3 * 8 bits par pixel que vous assumez. Il peut avoir 1, 4, 8 ou 24 bits par pixel;

  • au décalage 30, le type de compression est spécifié. Il peut être 0 pour aucun (votre hypothèse) mais aussi être Running Length Encoding: 1 = RLE-8 ou 2 = RLE-4. À l'offset 34, vous pouvez directement lire la taille des données d'image en octets, de sorte que vous n'avez pas besoin de le calculer vous-même.

Attention également que sizeof(int) pourrait être en théorie différente de 4. Ce n'est pas le problème, mais ce qui explique la pratique de l'utilisation DWORD Microsoft (pour int) et WORD (pour faire court) comme documented here.

Je suppose que RLE est utilisé dans votre fichier: Dans ce cas, en raison de la compression, vous ne pouvez plus regarder les octets de pixels à une position fixe: vous devez d'abord décompresser les données.

+0

Dans mon cas, c'est aussi simple que ça, c'est une mission pour la classe que je dois faire :) mais merci pour les commentaires, j'apprécie vraiment :) Et merci pour l'info sur la taille de l'image! :) –