在纯C ++中创建BMP

时间:2016-01-10 21:25:42

标签: c++ bmp

谢谢你的帮助。这是最终版本。 工作版

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();

问题 我需要在不使用非标准库的情况下在C ++中创建BMP,但我仍然有一些错误。我知道有一些类似的主题,但我仍然不清楚如何使这个东西发挥作用。

文件已创建,但当我尝试打开它时,照片浏览器会显示:

“Windows Image Viewer无法打开图片,因为文件太大或已损坏”。

我不确定问题是在标题还是像素写入中。

这就是代码:

#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;
}

由于所有这些都在上面的例子中起作用,在我的主项目中它没有。以下是主项目的功能和相同的结果: “Windows Image Viewer无法打开图片,因为文件太大或已损坏”。

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();
}

2 个答案:

答案 0 :(得分:2)

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

您需要添加 54 而不是40:

  • BITMAPFILEHEADER:14
  • BITMAPINFOHEADER:40

你们两个都在struct bmph合并。

因此:54 + (500*999)*4;,是结果文件的总大小。

bmpheader.biBitCount=4;

bmpheader.biBitCount应为32(RGB为24,RGBA为32)。

另外,如果你可以确保struct bmph的填充正常(即没有填充 - 不确定Linux的设置,例如Windows中的#pragma pack),那么你可以写整个结构一气呵成。

正如@fleebness已经建议的那样,请确保在结构中使用 fixed 类型,因此它们不会根据您编译的系统而改变。

答案 1 :(得分:0)

您是否尝试过此更正:

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

我相信std :: ofstream需要文本输出而不是二进制,所以你必须覆盖它。

另外,您可以参考:

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

而不是使用'unsigned short int'等,尝试使用std :: uint16_t作为2字节值,或者std :: uint32_t作为4字节值等等。