как создать данные заголовка растрового изображения, а затем записать в файл с помощью C ++ - PullRequest
2 голосов
/ 21 мая 2019

Я хочу создать заголовок растрового файла без какой-либо библиотеки.это данные моего изображения:

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;
}

Ответы [ 2 ]

0 голосов
/ 22 мая 2019

Я написал версию функции для вас. Я проверял это, он успешно работает.

Функция 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 - это typedef, равный std::vector<std::vector<Color24>>.
Color24 - это структура, которую я создал для обработки цветов RGB.

Типы, которые я использовал (uint8_t, uint16_t, uint32_t, ...), должны сделать его более читабельным. Когда в спецификации растрового изображения указано, что для поля заголовка необходимы 1, 2 или 4 байта, я использовал соответствующий явный тип. Но если эти типы не определены в вашей платформе, вы можете заменить их на unsigned char, unsigned short и unsigned int (просто проверьте с помощью sizeof(), если размеры совпадают с 1, 2 и 4). Но если вы можете включить cstdint, все будет хорошо.

Конечно, вы можете адаптировать функцию к вашим потребностям.

Надеюсь, это вам поможет.

0 голосов
/ 21 мая 2019

Используйте эту структуру: 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...