我想创建一个没有任何库的位图文件头。这是我图像的数据:
width = 3px;
height = 10px;
bits_per_pixle = 24;
我如何为其头生成54 bytes
数据然后写入文件?我对此有很多问题。我不知道如何将数据以十六进制形式写入文件。我不知道如何在4个字节等中写入文件大小。有人可以帮助我吗?谢谢。
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
int main()
{
int w = 3;
int h = 10;
int bits_per_pixle = 24;
ofstream des("file.bmp", ios::binary);
return 0;
}
答案 0 :(得分:0)
使用以下结构: BITMAPINFOHEADER
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
答案 1 :(得分:0)
我为您编写了该功能的一个版本。我测试了它,成功了。
函数createRawBitmap24()
创建不压缩的位图图像,每个像素24位:
struct Color24
{
uint8_t red;
uint8_t green;
uint8_t blue;
};
typedef std::vector<std::vector<Color24>> Image24;
bool check(const Image24 & img)
{
// check the shape
bool valid(!img.empty());
if(valid)
{
size_t line_size(img[0].size());
for(size_t i = 1; valid && (i < img.size()); ++i)
{
if(img.at(i).size() != line_size)
valid = false;
}
}
else
valid = false;
return valid;
}
bool createRawBitmap24(const std::string & file_path, const Image24 & img)
{
bool success(false);
if(check(img))
{
// ----- create the image in bmp format -----
// find the padding size
uint8_t padding_size(0);
size_t n = img[0].size()*3;
while(((n+padding_size) % 4) != 0)
++padding_size;
// build the raw content
const uint32_t ris = static_cast<uint32_t>(img.size()*(img[0].size()*3 + padding_size)); // raw image size
uint8_t * raw_content = new uint8_t[ris];
size_t cursor(0);
for(int i = static_cast<int>(img.size()-1); i >= 0; --i) // read lines in reverse order
{
for(const Color24 & pixel : img.at(static_cast<size_t>(i)))
{
raw_content[cursor++] = pixel.blue;
raw_content[cursor++] = pixel.green;
raw_content[cursor++] = pixel.red;
}
for(size_t j = 0; j < padding_size; ++j)
{
raw_content[cursor++] = 0xFF;
}
}
// build the header
const uint32_t hs(54); // header size
const uint32_t fs = (hs + ris); // file size
const uint32_t width = static_cast<uint32_t>(img[0].size()); // image width (without padding)
const uint32_t height = static_cast<uint32_t>(img.size()); // image height (without padding)
const uint32_t reso(2835); // resolution, ~72 DPI
const uint8_t header[hs] = {
'B', 'M',
static_cast<uint8_t>(fs & 0xFF), static_cast<uint8_t>((fs >> 8) & 0xFF), static_cast<uint8_t>((fs >> 16) & 0xFF), static_cast<uint8_t>((fs >> 24) & 0xFF),
0, 0,
0, 0,
static_cast<uint8_t>(hs & 0xFF), static_cast<uint8_t>((hs >> 8) & 0xFF), static_cast<uint8_t>((hs >> 16) & 0xFF), static_cast<uint8_t>((hs >> 24) & 0xFF),
40, 0, 0, 0,
static_cast<uint8_t>(width & 0xFF), static_cast<uint8_t>((width >> 8) & 0xFF), static_cast<uint8_t>((width >> 16) & 0xFF), static_cast<uint8_t>((width >> 24) & 0xFF),
static_cast<uint8_t>(height & 0xFF), static_cast<uint8_t>((height >> 8) & 0xFF), static_cast<uint8_t>((height >> 16) & 0xFF), static_cast<uint8_t>((height >> 24) & 0xFF),
1, 0,
24, 0,
0, 0, 0, 0,
static_cast<uint8_t>(ris & 0xFF), static_cast<uint8_t>((ris >> 8) & 0xFF), static_cast<uint8_t>((ris >> 16) & 0xFF), static_cast<uint8_t>((ris >> 24) & 0xFF),
static_cast<uint8_t>(reso & 0xFF), static_cast<uint8_t>((reso >> 8) & 0xFF), static_cast<uint8_t>((reso >> 16) & 0xFF), static_cast<uint8_t>((reso >> 24) & 0xFF),
static_cast<uint8_t>(reso & 0xFF), static_cast<uint8_t>((reso >> 8) & 0xFF), static_cast<uint8_t>((reso >> 16) & 0xFF), static_cast<uint8_t>((reso >> 24) & 0xFF),
0, 0, 0, 0,
0, 0, 0, 0
};
// ----- Write the content in the file -----
std::ofstream out_s(file_path, std::ofstream::binary);
if(out_s)
{
for(size_t i = 0; i < hs; ++i)
out_s << header[i];
for(size_t i = 0; i < ris; ++i)
out_s << raw_content[i];
out_s.close();
success = true;
}
delete [] raw_content;
}
return success;
}
要使用它,只需调用函数createRawBitmap24()
并提供文件路径和要创建的Image24
作为参数。
如您所见,Image24
是std::vector<std::vector<Color24>>
的typedef。
Color24
是我创建的用于处理RGB颜色的结构。
我使用的类型(uint8_t
,uint16_t
,uint32_t
,...)是为了使其更具可读性。当一个头字段需要1、2或4个字节的位图规范时,我使用了相应的显式类型。但是,如果您的平台中未定义这些类型,则可以将它们替换为unsigned char
,unsigned short
和unsigned int
(如果大小与1相同,只需使用sizeof()
进行检查) ,2和4)。但是,如果可以包含cstdint,就可以了。
当然,您可以根据需要调整功能。
希望它能对您有所帮助。