2016-01-10 1 views
0

Nous vous remercions de votre aide. C'est la version finale. version de travailCréation de BMP en C++ pur

BMPHead.znak1='B'; 
BMPHead.znak2='M'; 
BMPHead.bfSize=40; 
BMPHead.bfReserved1 = 0; 
BMPHead.bfReserved1 = 0; 
BMPHead.bfOffBits=54; 
BMPHead.biSize=40; 
BMPHead.biWidth=CSVHead.depth_pxsize ; 
BMPHead.biHeight=CSVHead.lateral_pxsize; 
BMPHead.biPlanes=1; 
BMPHead.biBitCount=32; 
BMPHead.biCompression = 0; 
BMPHead.biSizeImage = ((CSVHead.lateral_pxsize * CSVHead.depth_pxsize)*4); 
BMPHead.biXPelsPerMeter = 0; 
BMPHead.biYPelsPerMeter = 0; 
BMPHead.biClrUsed = 0; 
BMPHead.biClrImportant =0; 



void zamiana_danych(int &EndOfHead, float line[], csvh &CSVHead, bmph BMPHead, float &max, float &min) 
{ unsigned char bit_empty=0; 
    float tmp[500]; 
    ifstream obraz; 
    fstream bitmapa("POP_OCT.bmp"); 
    obraz.open("POP_OCT.csv", ios::binary); 
    obraz.seekg(EndOfHead, ios_base::beg); 
    bitmapa.seekg(BMPHead.bfOffBits, ios_base::beg); // this part was missing 
    for(int numb=0; numb < CSVHead.depth_pxsize; numb++) 
     { 
     //wczytanie jednego wiersza dancyh 
     for(int i=0; i<CSVHead.lateral_pxsize; i++) 
      { //wczytanie komorki danych 
       obraz>>line[i]; 
       obraz.seekg(+1, ios_base::cur); 
       tmp[i]=((max-min)/255) * line[i] - min; 
       unsigned char pixel[4]={tmp[i],tmp[i],tmp[i],0}; 
       bitmapa.write((char*)&pixel, sizeof(pixel)); 
      } 
     } 
     bitmapa.close(); 
     obraz.close(); 

Question Je dois créer BMP en C++ sans utiliser les bibliothèques non standard, mais j'ai encore quelques erreurs. Je sais qu'il y a des sujets similaires, mais je ne sais toujours pas comment faire fonctionner cette chose.

fichier est créé, mais lorsque je tente de l'ouvrir, photo navigateur dit:

« Windows Image Viewer ne peut pas ouvrir l'image, car le fichier est trop grand ou cassé ».

Je ne suis pas sûr si le problème est en entête ou en écriture de pixels.

C'est le code:

#include<iostream> 
#include<fstream> 
#include<cstring> 
#include <stdlib.h> 
using namespace std; 


struct bmph{ 
unsigned short int bfType; // instead of this I use znak1 and znak2 
unsigned long int bfSize; 
unsigned short int bfReserved1; 
unsigned short int bfReserved2; 
unsigned long int bfOffBits; 
unsigned long int biSize; 
unsigned long int biWidth; 
unsigned long int biHeight; 
unsigned short int biPlanes; 
unsigned short int biBitCount; 
unsigned long int biCompression; 
unsigned long int biSizeImage; 
unsigned long int biXPelsPerMeter; 
unsigned long int biYPelsPerMeter; 
unsigned long int biClrUsed; 
unsigned long int biClrImportant; 
}; 


int main() 
{ 
unsigned char pixel[4]={255,255,255,0}; 
char znak1='B'; 
char znak2='M'; 
bmph bmpheader; 

ofstream moje_bmp("tworzBMP.bmp"); 

bmpheader.bfSize=40 + (500*999)*4; 
bmpheader.bfReserved1 = 0; 
bmpheader.bfReserved1 = 0; 
bmpheader.bfOffBits=54; 
bmpheader.biSize=40; 
bmpheader.biWidth=500; 
bmpheader.biHeight=999; 
bmpheader.biPlanes=1; 
bmpheader.biBitCount=4; 
bmpheader.biCompression = 0; 
bmpheader.biSizeImage = (500*999)*4; 
bmpheader.biXPelsPerMeter = 0; 
bmpheader.biYPelsPerMeter = 0; 
bmpheader.biClrUsed = 0; 
bmpheader.biClrImportant =0; 


moje_bmp << znak1 <<znak2; 
moje_bmp.write((char*)&bmpheader.bfSize, sizeof(bmpheader.bfSize)); 
moje_bmp.write((char*)&bmpheader.bfReserved1, sizeof(bmpheader.bfReserved1)); 
moje_bmp.write((char*)&bmpheader.bfReserved1, sizeof(bmpheader.bfReserved1)); 
moje_bmp.write((char*)&bmpheader.bfOffBits, sizeof(bmpheader.bfOffBits)); 
moje_bmp.write((char*)&bmpheader.bfSize, sizeof(bmpheader.bfSize)); 
moje_bmp.write((char*)&bmpheader.biWidth, sizeof(bmpheader.biWidth)); 
moje_bmp.write((char*)&bmpheader.biHeight, sizeof(bmpheader.biHeight)); 
moje_bmp.write((char*)&bmpheader.biPlanes, sizeof(bmpheader.biPlanes)); 
moje_bmp.write((char*)&bmpheader.biBitCount, sizeof(bmpheader.biBitCount)); 
moje_bmp.write((char*)&bmpheader.biCompression, sizeof(bmpheader.biCompression)); 
moje_bmp.write((char*)&bmpheader.biSizeImage, sizeof(bmpheader.biSizeImage)); 
moje_bmp.write((char*)&bmpheader.biXPelsPerMeter, sizeof(bmpheader.biXPelsPerMeter)); 
moje_bmp.write((char*)&bmpheader.biYPelsPerMeter, sizeof(bmpheader.biYPelsPerMeter)); 
moje_bmp.write((char*)&bmpheader.biClrUsed, sizeof(bmpheader.biClrUsed)); 
moje_bmp.write((char*)&bmpheader.biClrImportant, sizeof(bmpheader.biClrImportant)); 

    for(int tx=0; tx<500;tx++) 
     { 
       for(int ty=0; ty<999;ty++) 
       { 
        moje_bmp.write((char*)&pixel, sizeof(pixel)); 
       } 
     } 
moje_bmp.close(); 
return 0; 
} 

Comme tout cela a travaillé dans l'exemple ci-dessus, dans mon projet principal, il ne fonctionne pas. Voici les fonctions du projet principal et le même résultat: "Windows Image Viewer ne peut pas ouvrir l'image, car le fichier est trop gros ou cassé".

void glowa_bmp(bmph &BMPHead, csvh &CSVHead) 
{ 
ofstream bitmapa("bitmapa.bmp", ios::binary); 

//przypisanie wartosci naglowka 
BMPHead.znak1='B'; 
BMPHead.znak2='M'; 
BMPHead.bfSize=54; 
BMPHead.bfReserved1 = 0; 
BMPHead.bfReserved1 = 0; 
BMPHead.bfOffBits=54; 
BMPHead.biSize=40; 
BMPHead.biWidth=CSVHead.depth_pxsize ; 
BMPHead.biHeight=CSVHead.lateral_pxsize; 
BMPHead.biPlanes=1; 
BMPHead.biBitCount=32; 
BMPHead.biCompression = 0; 
BMPHead.biSizeImage = ((CSVHead.lateral_pxsize * CSVHead.depth_pxsize)*4); 
BMPHead.biXPelsPerMeter = 0; 
BMPHead.biYPelsPerMeter = 0; 
BMPHead.biClrUsed = 0; 
BMPHead.biClrImportant =0; 

//zapisanie naglowka w pliku 
bitmapa << BMPHead.znak1 << BMPHead.znak2; 
bitmapa.write((char*)&BMPHead.bfSize, sizeof(BMPHead.bfSize)); 
bitmapa.write((char*)&BMPHead.bfReserved1, sizeof(BMPHead.bfReserved1)); 
bitmapa.write((char*)&BMPHead.bfReserved1, sizeof(BMPHead.bfReserved1)); 
bitmapa.write((char*)&BMPHead.bfOffBits, sizeof(BMPHead.bfOffBits)); 
bitmapa.write((char*)&BMPHead.bfSize, sizeof(BMPHead.bfSize)); 
bitmapa.write((char*)&BMPHead.biWidth, sizeof(BMPHead.biWidth)); 
bitmapa.write((char*)&BMPHead.biHeight, sizeof(BMPHead.biHeight)); 
bitmapa.write((char*)&BMPHead.biPlanes, sizeof(BMPHead.biPlanes)); 
bitmapa.write((char*)&BMPHead.biBitCount, sizeof(BMPHead.biBitCount)); 
bitmapa.write((char*)&BMPHead.biCompression, sizeof(BMPHead.biCompression)); 
bitmapa.write((char*)&BMPHead.biSizeImage, sizeof(BMPHead.biSizeImage)); 
bitmapa.write((char*)&BMPHead.biXPelsPerMeter,  sizeof(BMPHead.biXPelsPerMeter)); 
bitmapa.write((char*)&BMPHead.biYPelsPerMeter, sizeof(BMPHead.biYPelsPerMeter)); 
bitmapa.write((char*)&BMPHead.biClrUsed, sizeof(BMPHead.biClrUsed)); 
bitmapa.write((char*)&BMPHead.biClrImportant, sizeof(BMPHead.biClrImportant)); 

bitmapa.close(); 
} 




void zamiana_danych(int &EndOfHead, float line[], csvh &CSVHead, float &max, float &min) 
{ unsigned char bit_empty=0; 
    float tmp[500]; 
    ifstream obraz; 
    ofstream bitmapa("bitmapa.bmp", ios::binary); 
    obraz.open("POP_OCT.csv", ios::binary); 
    obraz.seekg(EndOfHead, ios_base::beg); 
    for(int numb=0; numb < CSVHead.depth_pxsize; numb++) 
     { 
     //wczytanie jednego wiersza dancyh 
     for(int i=0; i<CSVHead.lateral_pxsize; i++) 
      { //wczytanie komorki danych 
       obraz>>line[i]; 
       obraz.seekg(+1, ios_base::cur); 
       tmp[i]=((max-min)/255) * line[i] - min; 
       unsigned char pixel[4]={tmp[i],tmp[i],tmp[i],0}; 
       bitmapa.write((char*)&pixel, sizeof(pixel)); 
      } 
     } 
     bitmapa.close(); 
     obraz.close(); 
} 
+0

Vous ne définissez pas ou n'écrivez pas 'bfReserved2'. Ce n'est probablement pas un problème, car vous écrivez 'bfReserved1' deux fois. Mais c'est faux". Qu'est-ce que 'sizeof (long)' dans votre compilateur? –

+0

'BMPHead.bfSize = 54;' est toujours faux. Voir ma réponse + commentaires :) - Il doit être la taille totale de votre fichier. –

+0

@Danny_ds il devrait être, mais il fonctionne de cette façon ... Ne sait pas comment – Artur

Répondre

2
bmpheader.bfSize=40 + (500*999)*4; 

Vous devez ajouter au lieu de 40:

  • BITMAPFILEHEADER: 14
  • BITMAPINFOHEADER: 40

qui vous les deux combinés dans struct bmph. Par exemple: 54 + (500*999)*4;, soit la taille totale du fichier résultant.

bmpheader.biBitCount=4; 

bmpheader.biBitCount devrait être 32 (24 pour RGB et 32 ​​pour RVBA).


En outre, si vous pouvez vous assurer que le rembourrage de struct bmph est ok (pas de rembourrage - pas sûr du réglage pour Linux, il est #pragma pack dans Windows par exemple), vous pouvez alors écrire struct tout en un aller.

Et comme @fleebness l'a déjà suggéré, assurez-vous d'utiliser les types corrigés dans votre structure, afin qu'ils ne changent pas selon le système pour lequel vous compilez.

+0

'biBitCount = 32' dans ce cas, car il a quatre octets par pixel. '4 'signifie quatre bits par pixel, et le lecteur découvre évidemment la différence entre la taille et le nombre de pixels, et les objets. –

+0

@MatsPetersson - Oui, si bien sûr - regardait les mauvaises données ici. 4 ne fera pas bien. –

+0

J'ai mis 'bmpheader.bfSize = 40;' et 'bmpheader.biBitCount = 32;' L'image est correcte maintenant, merci beaucoup! – Artur

0

Avez-vous essayé cette correction:

ofstream moje_bmp("tworzBMP.bmp", std::ios::binary | std::ios::out); 

Je crois std :: ofstream attend la sortie de texte au lieu de binaire, donc vous devez remplacer.

En outre, vous pouvez consulter à ceci:

https://web.archive.org/web/20080912171714/http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html

et au lieu d'utiliser 'court unsigned int' et tel, essayer des choses comme std :: uint16_t pour 2 valeurs d'octets, ou std :: uint32_t pour quatre valeurs d'octets, etc.

+0

Bon point ..... –

+0

@fleebness J'ai essayé et cela ne fonctionne pas. – Artur

+0

Oui, je l'ai juste essayé moi-même et j'ai trouvé que ça ne fonctionnait pas, ce qui veut dire qu'il y a peut-être quelque chose avec la taille réelle des membres de votre structure. – fleebness