C ++将像素矢量写入BMP的通用方法

时间:2016-06-02 13:26:13

标签: c++ graphics bitmap

是否可以编写一个将采用像素矢量的类:

struct Pixel
{
    unsigned char Blue;
    unsigned char Green;
    unsigned char Red;
    unsigned char Alpha;
};

从矢量生成BMP。我试图从一个基本的例子开始,所以我只尝试4个像素,所以这就是为什么一些标题值是硬编码的。

这是我的标题:

uint16_t const BITMAP_FILE_TYPE = 0x4d42; //BM, little-endian 
static uint32_t const BITS_PER_BYTE = 8;
static uint32_t const BITS_PER_PIXEL = 24; 

#pragma pack(1) 
struct BITMAPFILEHEADER {
       //uint16_t   bfType;
       uint32_t   bfSize;
       uint16_t   bfReserved1;
       uint16_t   bfReserved2;
       uint32_t   bfOffBits;
}; BITMAPFILEHEADER;

struct BITMAPINFOHEADER {
       uint32_t      biSize;
       int32_t       biWidth;
       int32_t       biHeight;
       uint16_t      biPlanes;
       uint16_t      biBitCount;
       uint32_t      biCompression;
       uint32_t      biSizeImage;
       int32_t       biXPelsPerMeter;
       int32_t       biYPelsPerMeter;
       uint32_t      biClrUsed;
       uint32_t      biClrImportant;
}; BITMAPINFOHEADER;
#pragma pack()

inline uint64_t CalcBitmapFileSize(uint32_t widthBytes, uint32_t height) {
       uint64_t fileSize = widthBytes * height;

       uint32_t padSize = (widthBytes) % sizeof(uint32_t);
       if (padSize > 0) {
              padSize = sizeof(uint32_t) - padSize;
              padSize *= height;
       }
       fileSize += padSize;
       fileSize += sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);


       return fileSize;
}

class BitMapFileWriter
{
public:
    BitMapFileWriter();
    void WriteBMPFile(vector<Pixel> pixelVec, string fileName, uint32_t WIDTH, uint32_t HEIGHT);
};

这是我的意思:

void BitMapFileWriter::WriteBMPFile(vector<Pixel> pixelVec, string fileName, uint32_t WIDTH, uint32_t HEIGHT)
{
       FILE             *filePtr;          // file pointer
       BITMAPFILEHEADER bitmapFileHeader;  // bitmap file header
       BITMAPINFOHEADER bitmapInfoHeader;  // bitmap info header
       memset(&bitmapFileHeader, 0, sizeof(bitmapFileHeader));
       memset(&bitmapInfoHeader, 0, sizeof(bitmapInfoHeader));

                                                                     // open file for writing binary mode
       filePtr = fopen("C:\\BMP\\4PixelOutPut.bmp", "wb");

       // define the bitmap file header
       //bitmapFileHeader.bfType = BITMAP_FILE_TYPE;
       unsigned short bfType=0x4d42;  
       bitmapFileHeader.bfSize = static_cast<uint32_t>(CalcBitmapFileSize(WIDTH * (BITS_PER_PIXEL / BITS_PER_BYTE), HEIGHT));
       bitmapFileHeader.bfReserved1 = 0;
       bitmapFileHeader.bfReserved2 = 0;
       bitmapFileHeader.bfOffBits = sizeof(bitmapFileHeader) + sizeof(bitmapInfoHeader);

       // define the bitmap information header
       bitmapInfoHeader.biSize = sizeof(bitmapInfoHeader);
       bitmapInfoHeader.biWidth = WIDTH;                      // bitmap width
       bitmapInfoHeader.biHeight = HEIGHT;                    // bitmap height
       bitmapInfoHeader.biPlanes = 1;
       bitmapInfoHeader.biBitCount = BITS_PER_PIXEL;                        
       bitmapInfoHeader.biCompression = 0;               // no compression
       bitmapInfoHeader.biSizeImage = (WIDTH * HEIGHT) * 4;          // width * height
       bitmapInfoHeader.biXPelsPerMeter = 5000;
       bitmapInfoHeader.biYPelsPerMeter = 5000;
       bitmapInfoHeader.biClrUsed = 0;
       bitmapInfoHeader.biClrImportant = 0;

       fwrite(&bfType,1,sizeof(bfType),filePtr);
                                                                                                   // write the bitmap file header
       fwrite(&bitmapFileHeader, 1, sizeof(BITMAPFILEHEADER), filePtr);

       // write the bitmap info header
       fwrite(&bitmapInfoHeader, 1, sizeof(BITMAPINFOHEADER), filePtr);

       for(int i=0; i<4; i++)
       {
           Pixel pixel = pixelVec[i];
           fwrite(&pixel.Blue, 1, 1, filePtr);
           fwrite(&pixel.Green, 1, 1, filePtr);
           fwrite(&pixel.Red, 1, 1, filePtr);
       }


       // close our file
       fclose(filePtr);
}

并称之为:     BitMapFileWriter bmfw;     bmfw.WriteBMPFile(pixelVec,&#34; c:\ BMP \ 4PixelBMP.txt&#34;,2,2);

1 个答案:

答案 0 :(得分:1)

我发现这个课程可以作为参考使用。它是一个“表面”类,其成员包括宽度,高度和std::vector(32位)像素颜色。

Save成员函数将表面保存为.bmp文件。它可以很容易地转换成一个带有宽度,高度和矢量的独立函数。

Writer类包装ofstream对象并提供Save中使用的文件输出接口。

BIH结构应该看起来很熟悉,Surface的其余成员函数提供了一个非常小的绘图API。

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

struct Color {
    union {
        struct { unsigned char b,g,r,a; };
        unsigned char bytes[4];
        unsigned int ref;
    };
    Color(unsigned int ref=0) : ref(ref) {}
};

class Surface {
    int width, height;
    std::vector<Color> pixels;
public:
    void Fill(Color color) { std::fill(pixels.begin(), pixels.end(), color); }
    void HLine(int left, int y, int len, Color color) {
        if(y < 0 || y >= height || left >= width) { return; }
        if(left < 0) { len += left; left = 0; }
        if(left + len > width) { len = width - left; }
        int offset = y * width + left;
        std::fill(pixels.begin() + offset, pixels.begin() + offset + len, color); 
    }
    void RectFill(int x, int y, int w, int h, Color color) {
        for(int i=0; i<h; ++i) { HLine(x, y + i, w, color); }
    }
    Surface(int width, int height) : 
        width(width), 
        height(height),
        pixels(width*height, Color())
    {}
    template <typename I>       Color& operator () (const I& x, const I& y)       { return pixels[y*width+x]; }
    template <typename I> const Color& operator () (const I& x, const I& y) const { return pixels[y*width+x]; }

    class Writer {
        std::ofstream ofs;
    public:
        Writer(const char* filename) : ofs(filename, std::ios_base::out | std::ios_base::binary) {}
        void operator () (const void* pbuf, int size) { ofs.write(static_cast<const char*>(pbuf), size); }
        template <typename T> void operator () (const T& obj) { operator () (&obj, sizeof(obj)); }
    };

    struct BIH {
        unsigned int   sz;
        int            width, height;
        unsigned short planes;
        short          bits;
        unsigned int   compress, szimage;
        int            xppm, yppm;
        unsigned int   clrused, clrimp;
    };

    void Save(const char* filename) const {
        Writer w(filename);;
        w("BM", 2);
        BIH bih = {sizeof(bih)};
        bih.width = width;
        bih.height = -height;
        bih.planes = 1;
        bih.bits = 32;
        const unsigned int headersize = sizeof(bih) + 14;
        const int szbuf = int(sizeof(Color) * pixels.size());
        const unsigned int filesize = static_cast<unsigned int>(headersize + szbuf);
        w(filesize);
        const unsigned short z = 0;
        w(z);
        w(z);
        w(headersize);
        w(bih);
        w(pixels.data(), szbuf);
    }
};

int main() {
    Surface surf(600, 600);
    Color color;
    for(int j=0; j<12; ++j) {
        color.g = 0;
        for(int i=0; i<12; ++i) {
            color.b = 255 - (color.g + color.r) / 2;
            surf.RectFill(i*50, j*50, 50, 50, color);
            color.g += 21;
        }
        color.r += 21;
    }
    surf.Save("MyBmpFile.bmp");
}