Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > [С++] Запись bmp в массив


Автор: b26041986 28.3.2016, 01:30
Помогите, пожалуйста! Как на С++ можно считать монохромный bmp файл в массив? (Нужно получить матрицу яркости. Т.е. должен получится двумерный int массив из элементов 0...255).

Автор: math64 28.3.2016, 10:49
В какой среде программируешь? Если нужна универсальная программа - разбирайся с форматом бмп.
Иначе - используй функции среды для загрузки изображения (обычно она универсальная, и подходит под любой формат) и получения отдельных пикселей (обычно получаешь 32 разрядное число, байты которого прозрачность, красный, зеленый и синий комоненты - для монохромного изображения цветовые компоненты будут одинаковыми).

Автор: rudolfninja 28.3.2016, 11:14
Я когда-то писал диссертацию на тему стеганографии, и был у меня там кусок кода, который, насколько я понял, делал то, что вам требуется.
Вот код, правда, это один из чернвых вариантов, но вроде работает:
Bmp.h (вам отсюда нужны структуры и метод readFromFile)
Код

#ifndef BMP_H
#define BMP_H

typedef unsigned char uchar;
typedef unsigned int  uint;

typedef struct RGBApixel {
    uchar Blue;
    uchar Green;
    uchar Red;
    uchar Alpha;
} RGBApixel;

#pragma pack(push,1)

typedef struct BMPH {
    short bfType;
    uint  bfSize;
    short bfReserved1;
    short bfReserved2;
    uint  bfOffBits;

    uint  biSize;
    uint  biWidth;
    uint  biHeight;
    short biPlanes;
    short biBitCount;
    uint  biCompression;
    uint  biSizeImage;
    uint  biXPelsPerMeter;
    uint  biYPelsPerMeter;
    uint  biClrUsed;
    uint  biClrImportant;
} BMPH;

#pragma pack(pop)

class BMP
{
public:
    RGBApixel** pixels;
    BMPH header;

    BMP();
    ~BMP();
    bool readFromFile(char* filename);
    bool writeToFile(char* filename);
    RGBApixel getPixel(int x, int y);
    void setPixel(int x, int y, RGBApixel pixel);
    BMP operator=(BMP copy);
};

#endif // BMP_H

Реализация readFromFile
Код

bool BMP::readFromFile(char *filename)
{
    using namespace std;

    short bitCount;
    int width;
    int height;
    int colSize;

    char* buffer;

    ifstream input(filename, ios::in | ios::binary);
    input.read((char*) &(this->header), 54);
    input.seekg(this->header.bfOffBits, ios_base::beg);

    bitCount = this->header.biBitCount;
    width = this->header.biWidth;
    height = this->header.biHeight;

    colSize = (int)((width*bitCount)/8.0);

    while (8*colSize < width*bitCount) {
        colSize++;
    }

    while (colSize % 4) {
        colSize++;
    }

    this->pixels = new RGBApixel*[width];
    buffer = new char[colSize];
    for (int i = 0; i < width; i++)
        this->pixels[i] = new RGBApixel[height];

    for (int i = height-1; i >= 0; i--) {
        input.read(buffer, colSize);
        for (int j = 0; j < width; j++) {
            if (bitCount == 24) {
                memcpy((char*) &(pixels[j][i]), buffer + 3*j, 3);
            } else if (bitCount == 32) {
                memcpy((char*) &(pixels[j][i]), buffer + 4*j, 4);
            } else {
                return false;
            }
        }
    }
    return true;
}

Код несложный, попробуйте разобраться.

Автор: math64 28.3.2016, 11:48
Пример не учитывает возможности что пиксель может заниметь 1 байт (что логично для монохромного бмп)

Автор: b26041986 28.3.2016, 20:03
Использую Dev-Cpp.

появляется ошибка в строке  


ifstream input(filename, ios::in | ios::binary);


Сообщение:
`std::ifstream input' has initializer but incomplete type 

пока еще буду разбираться ...

.....
м.б. для такого задания лучше использовать среду по-крупнее?

Автор: math64 29.3.2016, 08:15
Имелось в в виду WinAPI. MFC, Qt и т. д. - у них у всех есть свои методы для работы с изображениями (хотя для Windows всё в итоге сводится к WinAPI).
Вместо ifstream можно использовать <strdio.h>: FILE* input = fopen(filename, "rb"); если тебе это привычнее. Но тогда далее тоже следует использовать stdio.
Учти:
в 16-разрядной ОС: short - 16, int - 16, long - 32 бит
в 32-разрядной ОС: short - 16, int - 32, long - 32 бит
в 64-разрядной ОС: short - 16, int - 32, long - 64 бит
Для какой разрядности код  rudolfninja и правильно ли там определено uint ?

Автор: rudolfninja 29.3.2016, 08:28
В 32-разрядной и в 64-разрядной ОС, насколько я понимаю, размер uint будет одинаковый.

Цитата(math64 @  29.3.2016,  08:15 Найти цитируемый пост)
правильно ли там определено uint

А почему нет?

Автор: math64 29.3.2016, 08:45
rudolfninja, если бы ты написал typedef unsigned int  uint32; - было бы понятно, какую ты хочешь разрядность.

http://ru.cppreference.com/w/cpp/language/types
т.е. при переходе WIN32->WIN64 поменяется только разрядность указателей.
но в 64-разрядном Линуксе long будет 64 разрядный.

Автор: Hate42 30.3.2016, 10:35
Спасибо

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)