Я настраиваю программу для графики, но для моего стартового тестового примера для создания растрового изображения. При попытке просмотра созданного образа я, кажется, получаю ошибку "файл не поддерживается". Сначала это было в bitmap.h
при unsigned char color[3] = {(char)floor(blue), (char)floor(green), (char)floor(red)};
думая, что бросок должен быть int, но это не сдвинулось с места.
color.h
#ifndef _COLOR_H
#define _COLOR_H
class Color {
public:
double r, g, b;
Color() {};
~Color() {};
Color(double _r, double _g, double _b) : r(_r/255), g(_g/255), b(_b/255) {}
// omitted operator overloads and print method not used in test case
};
#endif
bitmap.h
#ifndef _BITMAP_H
#define _BITMAP_H
void savebmp(const char* filename, int width, int height, int dpi, Color* data) {
FILE *f;
int k = width * height;
int s = 4 * k;
int filesize = 54 + s;
int m = static_cast<int>(39.375);
int ppm = dpi * m; // pixels per meter
unsigned char bmpfileheader[14] = {
'B', 'M', 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0
};
unsigned char bmpinfoheader[40] = {
40, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 24, 0
};
// Unsure about this implementation - read more about bitmap creading
bmpfileheader[2] = (unsigned char)(filesize);
bmpfileheader[3] = (unsigned char)(filesize >> 8);
bmpfileheader[4] = (unsigned char)(filesize >> 16);
bmpfileheader[5] = (unsigned char)(filesize >> 24);
bmpinfoheader[4] = (unsigned char)(width);
bmpinfoheader[5] = (unsigned char)(width >> 8);
bmpinfoheader[6] = (unsigned char)(width >> 16);
bmpinfoheader[7] = (unsigned char)(width >> 24);
bmpinfoheader[8] = (unsigned char)(height);
bmpinfoheader[9] = (unsigned char)(height >> 8);
bmpinfoheader[10] = (unsigned char)(height >> 16);
bmpinfoheader[11] = (unsigned char)(height >> 24);
bmpinfoheader[21] = (unsigned char)(s);
bmpinfoheader[22] = (unsigned char)(s >> 8);
bmpinfoheader[23] = (unsigned char)(s >> 16);
bmpinfoheader[24] = (unsigned char)(s >> 24);
bmpinfoheader[25] = (unsigned char)(ppm);
bmpinfoheader[26] = (unsigned char)(ppm >> 8);
bmpinfoheader[27] = (unsigned char)(ppm >> 16);
bmpinfoheader[28] = (unsigned char)(ppm >> 24);
bmpinfoheader[29] = (unsigned char)(ppm);
bmpinfoheader[30] = (unsigned char)(ppm >> 8);
bmpinfoheader[31] = (unsigned char)(ppm >> 16);
bmpinfoheader[32] = (unsigned char)(ppm >> 24);
fopen_s(&f, filename, "wb");
fwrite(bmpfileheader, 1, 14, f);
fwrite(bmpinfoheader, 1, 40, f);
for (int i = 0; i < k; i++) {
Color rgb = data[i];
double red = data[i].r * 255;
double green = data[i].g * 255;
double blue = data[i].b * 255;
unsigned char color[3] = {(char)floor(blue), (char)floor(green), (char)floor(red)};
fwrite(color, 1, 3, f);
}
fclose(f);
}
#endif
main.cpp
#include <iostream>
#include <fstream>
#include <cmath>
#include "color.h"
#include "bitmap.h"
int element;
int main(int argc, char **argv) {
int dpi = 72;
int width = 640;
int height = 480;
int n = width * height;
Color *pixels = new Color[n]; // look into smart pointers
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
// element position in pixels array
element = y * width + x;
pixels[element] = Color(23, 76, 210);
}
}
savebmp("practice.bmp", width, height, dpi, pixels);
// should generate solid blue image
std::getchar();
return 0;
}
Пара вещей:
memset
эти байтовые массивы до нулей, если вы оставляете дыры. Вы уверены, что идет в каждом байте? Вы должны быть.
Я могу только предположить, что вы BITMAPINFOHEADER
структуру BITMAPINFOHEADER
. Почему бы не использовать структуру? Даже если у вас нет заголовка, вы можете определить его самостоятельно и сэкономить путаницу с массивом байтов.
Далее, начиная с строки bmpinfoheader[21] = (unsigned char)(s);
у вас, кажется, есть один за другим. Поле biSizeImage
начинается с byte
с индексом 20, а не 21. Последующее действие продолжается в вашем коде.
Наконец, пиксели сохраняются по строкам, а затем дополняются к 4-байтовому выравниванию. Вы перечисляете pixels
по высоте во внутреннем цикле, поэтому вместо этого вы переходите от столбца к столбцу. И не забывайте прокладку! Вы можете рассчитать, сколько байтов вам нужно использовать с помощью:
4 - (sizeOfRowInBytes % 4)
Надеюсь, это поможет вам. Вы можете найти эту страницу в Википедии полезной.