Уроки, алгоритмы, программы, примеры

Вход на сайт

Материалы по разделам

Построения
на плоскости (2D)
Графика
в пространстве (3D)
Вычислительная
геометрия
Физическое
моделирование
Фрактальная
графика

Новые комментарии

dobryj den, popytalas otkryt prikreplionnyj fail ctoby posmotret kak rabotaet, no mne ego ne pokazyvaet vydajet osibku. Pochemu?
Очень интересно! ии сайт крутой жалко что умирает(
У Вас число превысит максимальное число int. Можно использовать в Вашем случае uint, но лучше все переписать на double.
Добавление к программе строки glutReshapeFunc(changeSize); приводит к тому, что треугольник перестаёт совсем отрисовываться.
Выдаёт ошибку glut32.dll не найден! При том, что он лежит в System32! Всё решил) Нужно отправить не в System32, а в System.

Счетчики и рейтинг

Рейтинг@Mail.ru Яндекс.Метрика
Среда программирования: 
Code Blocks + MinGW

Чтобы сохранить картинку в формате BMP необходимо соблюдение особых правил, а именно соблюдения спецификаций заголовков файла BMP, в данном уроке мы рассматриваем наиболее часто встречаемую спецификацию с заголовками BMP и DIB (14 и 40 байт соответственно).
Прежде чем рассказать о том как строить заголовки BMP и DIB вооружимся необходимой функцией:

void int_to_bytes(char * arr, int n)
{
    for (int i = 0; i < 4; i++)
        arr[i] = (char)((n >> 8 * i) & 0xFF);
}

Она побайтово записывает значение целого числа в массив arr в ПЕРЕВЕРНУТОМ виде.

Для начала открываем файл:

ofstream os(filename, ofstream::binary);

Далее следует идентификатор того, что это файл BMP, а именно байты { 'B', 'M' }.
Идентификатор занимает 2 байта.
Запишем его в файл:

w[0] = 'B'; w[1] = 'M'; os.write(w, 2);

Далее идет размер файла в байтах, подсчитаем его так: (4*width*height + 14 + 40), т.к. на каждый пиксел мы будем тратить по 32 бита (4 байта) и 14 + 40 байтов на заголовки.
Идентификатор занимает 4 байта.
Запишем его в файл:

int_to_bytes(w, width*height*4 + 14 + 40); os.write(w, 4);

Далее следуют байты, специфические вашему приложению, мы в них не заинтересованы, пусть будет 0.
Идентификатор занимает 4 байта.
Запишем его в файл:

int_to_bytes(w, 0); os.write(w, 4);

Далее следует положение массива пикселов самой картинки. Т.к. на заголовки у нас уходит 14+40 байт, значит массив будет находится со смещением 54.
Идентификатор занимает 4 байта.
Запишем его в файл:

int_to_bytes(w, 54); os.write(w, 4);

Теперь начинается заголовок DIB
Указывается размер DIB заголовка, у нас он равен 40 байт.
Идентификатор занимает 4 байта.
Запишем его в файл:

int_to_bytes(w, 40); os.write(w, 4);

Далее следуют размеры изображения, по 4 байта соответственно:

int_to_bytes(w, width); os.write(w, 4);
int_to_bytes(w, height); os.write(w, 4);

Количество цветовых плоскостей. У нас одна, 2 байта:

int_to_bytes(w, 1); os.write(w, 2);

Количество бит на пиксел, у нас 32. 2 байта:

int_to_bytes(w, 32); os.write(w, 2);

Метод сжатия. У нас 0 т.е. BI_RGB - никакого сжатия нету, 4 байта:

int_to_bytes(w, 0); os.write(w, 4);

Размер сырого изображения, без заголовков. Может быть указан 0 для изображений BI_RGB - что и есть наш случай. 4 байта:

int_to_bytes(w, 0); os.write(w, 4);

Размер печати - у нас 2834 пиксел на метр по вертикали и горизонтали. По 4 байта:

int_to_bytes(w, 2834); os.write(w, 4);
int_to_bytes(w, 2834); os.write(w, 4);

Количество цветов. 0 приравнивается к 2n, где n - битность (32 бита у нас), 4 байта:

int_to_bytes(w, 0); os.write(w, 4);

Количество "важных" цветов, чаще всего игнорируется большинством приложений, может быть 0. 4 байта:

int_to_bytes(w, 0); os.write(w, 4);

А далее сама запись картинки. Необходимо заметить, что для стандарта BMP строки идут с конца изображения:

int last = height - 1;
for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
        os.write(bytes + (4*width*(last - i) + 4*j), 4);
    }
}

Полный код, который создает файл "file.bmp" с нарисований функцией
cos(3*x^3+5*x^2-6*x-8)

#include <fstream>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
#define WIDTH 640
#define HEIGHT 360
 
void exit_with_msg(const char * msg)
{
    printf(msg);
    printf("\n");
    exit(1);
}
 
void int_to_bytes(char * arr, int n)
{
    for (int i = 0; i < 4; i++)
        arr[i] = (char)((n >> 8 * i) & 0xFF);
}
 
void write_bmp(const char * filename, const char * bytes, 
               int width, int height)
{
    if (width % 4 != 0) exit_with_msg("bad width");
 
    ofstream os(filename, ofstream::binary);
    char w[4]; // working array
 
    /* BMP header start */
    // BMP identifier
    w[0] = 'B'; w[1] = 'M'; os.write(w, 2);
    // file size bytes
    int_to_bytes(w, width*height*4 + 14 + 40); os.write(w, 4);
    // application dependent bytes
    int_to_bytes(w, 0); os.write(w, 4);
    //array offset
    int_to_bytes(w, 54); os.write(w, 4);
    /* BMP header end */
 
    /* DIB header start */
    // DIB size
    int_to_bytes(w, 40); os.write(w, 4);
    // width and height
    int_to_bytes(w, width); os.write(w, 4);
    int_to_bytes(w, height); os.write(w, 4);
    // color planes
    int_to_bytes(w, 1); os.write(w, 2);
    // bits per pixel
    int_to_bytes(w, 32); os.write(w, 2);
    // compression method BI_RGB (none)
    int_to_bytes(w, 0); os.write(w, 4);
    // raw image size (can be 0 for BI_RGB bitmaps)
    int_to_bytes(w, 0); os.write(w, 4);
    // image print resolution
    int_to_bytes(w, 2834); os.write(w, 4);
    int_to_bytes(w, 2834); os.write(w, 4);
    // number of colors (0 defaults to 2^n)
    int_to_bytes(w, 0); os.write(w, 4);
    // number of important colors used
    int_to_bytes(w, 0); os.write(w, 4);
    /* DIB header end */
 
    /* image start */
    int last = height - 1;
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            os.write(bytes + (4*width*(last - i) + 4*j), 4);
        }
    }
    /* image end */
 
    os.close();
}
 
float f(float x)
{ return cos(3*x*x*x+5*x*x-6*x-8); }
 
int main()
{
    // allocate bytes for picutre
    char * bytes = new char[WIDTH * HEIGHT * 4];
    if (bytes == NULL) exit_with_msg("no memory");
 
    // draw picture in memory
    memset(bytes, 0, WIDTH*HEIGHT*4);
    for (float x = -5.0f; x < 5.0f; x += 0.0005f)
    {
        float y = f(x);
        int X = (int)(64*(x+5));
        int Y = (int)(90*(y+2));
        bytes[4*(WIDTH*(HEIGHT-Y) + X)] = 255;
    }
 
    // write picture to file
    write_bmp("file.bmp", bytes, WIDTH, HEIGHT);
 
    return 0;
}