c++ - 如何使用 C++ 创建 BMP 文件?
问题描述
我正在尝试创建一个在给定像素的情况下保存 BMP 图像的类。这是我的.h:
#ifndef _IMAGE_SAVER_
#define _IMAGE_SAVER_
#include <vector>
#include <fstream>
#include <sstream>
#include <string>
#include <bitset>
//#define _DEBUG_
#ifdef _DEBUG_
#include <iostream>
#endif
#include <stdint.h>
typedef struct BMFileHeader {
uint16_t _bfType = 19778;
uint32_t _bfSize;
uint16_t _bfReserved1 = 0;
uint16_t _bfReserved2 = 0;
uint32_t _bfOffBits = 54;
} BMFileHeader;
typedef struct BMInfoHeader {
uint32_t _biSize = 40;
uint32_t _biWidth;
uint32_t _biHeight;
uint16_t _biPlanes = 1;
uint16_t _biBitCount = 24;
uint32_t _biCompression = 0;
uint32_t _biSizeImage = 0;
uint32_t _biXPelsPerMeter = 3780;
uint32_t _biYPelsPerMeter = 3780;
uint32_t _biClrUser = 0;
uint32_t _biClrImportant = 0;
} BMInfoHeader;
typedef struct RGBQuad {
uint8_t _blue;
uint8_t _green;
uint8_t _red;
} RGBQuad;
class ImageSaver
{
public:
ImageSaver() = delete;
ImageSaver(const uint32_t& height, const uint32_t& width, const std::vector<RGBQuad>& pixels) : _RGBQuad_Vector(pixels) {
this->_Info_Header._biHeight = height;
this->_Info_Header._biWidth = width;
};
void saveImage(const std::string& fileName);
protected:
void setFileSize();
void createImageFile(const std::string& fileName);
private:
BMFileHeader _File_Header;
BMInfoHeader _Info_Header;
std::vector<RGBQuad> _RGBQuad_Vector;
};
#endif
这是我的.cpp:
#include "ImageSaver.h"
void ImageSaver::saveImage(const std::string& fileName)
{
this->setFileSize();
this->createImageFile(fileName);
}
void ImageSaver::setFileSize()
{
uint32_t height = this->_Info_Header._biHeight;
uint32_t width = this->_Info_Header._biWidth;
this->_File_Header._bfSize = 3 * (height * width) + 54;
}
void ImageSaver::createImageFile(const std::string& fileName)
{
std::ofstream imageFile(fileName + ".bmp", std::ios::binary);
imageFile.write((char*)&this->_File_Header, 14);
imageFile.write((char*)&this->_Info_Header, 40);
size_t numberOfPixels = this->_Info_Header._biHeight * this->_Info_Header._biWidth;
for (int i = 0; i < numberOfPixels; i++) {
imageFile.write((char*)&(this->_RGBQuad_Vector[i]), 3);
}
imageFile.close();
}
这是我的 main.cpp:
#include "ImageSaver.h"
#include <vector>
#include <iostream>
int main() {
std::vector<RGBQuad> pixels;
for (unsigned i = 0; i < 512 * 512; i++) {
RGBQuad pixel;
pixel._blue = 0;
pixel._green = 255;
pixel._red = 255;
pixels.push_back(pixel);
}
ImageSaver im(512, 512, pixels);
im.saveImage("scene1");
std::cout << "ESTOP0" << std::endl;
return 0;
}
每当我尝试创建图像文件时,它都会说该图像文件已损坏,即使在我看来我一直在正确遵循 BMP 格式。我分析了原始二进制数据,数据似乎(对我来说)是正确的。GIMP 可以打开图片,但它会给出一个黑色的 512x512 图片,这不是我想要的。
解决方案
你肯定想念#pragma pack
。#pragma pack(push,1)
用/包裹你的结构#pragma pack(pop)
当结构代表内存布局并且不应该有填充时,即使有未对齐的数据,也要打包结构。
static_assert
对于这种情况,具有预期sizeof
价值是非常有帮助的。
此外,当你打包它们时,它们RGBQuad
只会变成 3 个字节。如果您真的想要三倍,建议将其重命名为三倍。否则添加虚拟或 alpha 字节以完成它到四边形。
推荐阅读
- c++ - 在 Mac OS 上使用 C/C++ 获得鼠标跟踪速度
- sqlite - 为什么给出“参数计数不匹配”错误?
- java - 如何在架构级别监听 kafka 事件
- python - 我想为我的时间序列数据设置一个频率(我的数据以五分钟为单位)
- powershell - 当响应时间(不是名称解析)长于 x 时,有没有办法结束 Invoke-WebRequest?
- javascript - 通过中间件检查多权限
- java - REST 被错误(部分正确)类识别,如何防止这种情况发生?
- c# - 如何使用随机数生成器中的值显示嵌入程序中的图像?
- vue.js - 如何使用 bootstrap-vue 修复模态标题中的图像
- javascript - symfony 列表上的内联编辑元素问题