如何使用2d rgb数组在c ++中创建图像?

时间:2017-09-01 01:50:37

标签: c++

我是否正在使用restAPI从python中获取2d numpy rgb-array并且我想使用c ++从它创建和映像。你知道怎么做吗?或者你知道类似的numpy库来自c ++吗?

1 个答案:

答案 0 :(得分:1)

创建位图非常简单(.bmp扩展名)。

你可以使用一个像这样的库: https://github.com/ArashPartow/bitmap。具有狭窄用例的库通常具有可读性。在这种情况下,逻辑全部包含在单个hpp文件中。看一下它,它有点复杂,因为它处理了大量不同的情况。

或者你可以自己做。查找如何编写二进制位图头并使用fstream将其写入文件。打开文件以编写ios::out | ios::binary时,您将需要使用二进制选项。您可以在此处找到位图标题和文件格式的详细信息:https://en.wikipedia.org/wiki/BMP_file_format

顺便说一下,维基百科在逐位表的二进制文件格式上有许多不错的参考资料。

对于一个非常天真的实现,它不处理一堆不同的格式,我过去就已经这样做了。

BitmapFileHeader.h

#pragma once
#include <cstdint>

#pragma pack(push, 2)
struct BitmapFileHeader
{
    char header[2]{'B', 'M'};
    uint32_t fileSize;
    uint32_t reserved{};
    uint32_t dataOffset;
};
#pragma pack(pop)

BitmapInfoHeader.h

#pragma once

#include <cstdint>

#pragma pack(push, 2)
struct BitmapInfoHeader
{
    uint32_t headerSize{ 40 };
    uint32_t width{ 0 };
    uint32_t height{ 0 };
    uint16_t planes{ 1 };
    uint16_t bitsPerPixel{ 24 };
    uint32_t compression{ 0 };
    uint32_t dataSize{ 0 };
    uint32_t horizontalResolution{ 2400 };
    uint32_t verticalResolution{ 2400 };
    uint32_t colors{ 0 };
    uint32_t importantColors{ 0 };
};
#pragma pack(pop)

Bitmap.h

#include <string>
#include <iostream>
#include <cstdint>
#include <memory>
#include <fstream>
#include "BitmapFileHeader.h"
#include "BitmapInfoHeader.h"


using namespace std;

class Bitmap
{
private:
    int m_width{ 0 };
    int m_height{ 0 };
    unique_ptr<uint8_t[]> m_pixels{ nullptr };

public:
    struct RBG {
        uint8_t r;
        uint8_t b;
        uint8_t g;
    };

    Bitmap(int width, int height) : m_width(width), 
        m_height(height), m_pixels(new uint8_t[width * height * sizeof(RBG)]{}) {};

    void setPixel(int, int, RBG);
    void setDimensions(int, int);
    int getSize();
    bool write(string);

    ~Bitmap();
};

Bitmap.cpp

#include "stdafx.h"
#include "Bitmap.h"

using namespace std;

void Bitmap::setPixel(int x, int y, RBG color)
{
    uint8_t *pixel = m_pixels.get();

    pixel = pixel + ((y * sizeof(RBG)) * m_width) + (x * sizeof(RBG));

    // little endian
    pixel[0] = color.b;
    pixel[1] = color.g;
    pixel[2] = color.r;
}

void Bitmap::setDimensions(int w, int h)
{
    m_width = w;
    m_height = h;
}

int Bitmap::getSize()
{
    return m_width * m_height * sizeof(RBG);
}

bool Bitmap::write(string filename)
{   
    BitmapFileHeader fileHeader; 
    BitmapInfoHeader infoHeader;

    fileHeader.fileSize = sizeof(BitmapFileHeader) + sizeof(BitmapInfoHeader) + getSize();
    fileHeader.dataOffset = sizeof(BitmapFileHeader) + sizeof(BitmapInfoHeader);

    infoHeader.width = m_width;
    infoHeader.height = m_height;

    ofstream file; 
    file.open(filename, ios::out | ios::binary);

    if (!file)
    {
        return false;
    }

    file.write(reinterpret_cast<char *>(&fileHeader), sizeof(fileHeader));
    file.write(reinterpret_cast<char *>(&infoHeader), sizeof(infoHeader));
    file.write(reinterpret_cast<char *>(m_pixels.get()), getSize());

    file.close();

    return true;
}

Bitmap::~Bitmap()
{
    cout << "bitmap destroyed" << endl;
}