2017-09-01 57 views
-1

嗯,我正在使用restAPI從python中獲取2d numpy rgb數組,並且我想使用C++創建它並從中創建圖像。您是否有任何想法如何做到這一點?或者你知道一個類似numpy的C++庫嗎?如何使用2d rgb數組在C++中創建圖像?

+0

什麼樣的圖像?你想把它保存到磁盤,顯示它,還有其他的東西嗎? –

+0

PNG或BMP,我想顯示它 –

回答

0

創建位圖(.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; 
}