Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
mariko_11
2 / 2 / 1
Регистрация: 11.03.2013
Сообщений: 64
#1

Открытие и запись файла bmp. Что здесь не так ? - C++

21.03.2014, 23:33. Просмотров 842. Ответов 5
Метки нет (Все метки)

Имеется программа, копирующая содержимое из указанного bmp в файл result. Проблема: файл stars копируется нормально, а вместо скопированного tank получается какая-то ерунда. Почему ?

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <iostream>
 
using namespace std;
 
typedef struct pixel {
    char red;
    char green;
    char blue;
 
} pixel_t;
 
typedef struct pixel_array {
    pixel_t **array_of_pixel;
    long height;
    long width;
 
} pixel_array_t;
 
typedef struct tagBITMAPFILEHEADER {
    unsigned short    bfType;
    unsigned long     bfSize;
    unsigned short    bfReserved1;
    unsigned short    bfReserved2;
    unsigned long     bfOffBits;
} BITMAPFILEHEADER;
 
typedef struct tagBITMAPINFOHEADER {
    unsigned long biSize;
    unsigned long biWidth;
    unsigned long biHeight;
    unsigned short  biPlanes;
    unsigned short  biBitCount;
    unsigned long biCompression;
    unsigned long biSizeImage;
    long  biXPelsPerMeter;
    long  biYPelsPerMeter;
    unsigned long biClrUsed;
    unsigned long biClrImportant;
} BITMAPINFOHEADER;
 
const int MAX_PATH_LEN = 260;
 
void parse_file(FILE *file, pixel_array_t *pix_arr, BITMAPFILEHEADER &header, BITMAPINFOHEADER &info_header) {
 
    unsigned long image_size = 0;
    long height = 0;
    long width = 0;
 
    // Читаем первую структуру (BITMAPFILEHEADER)
    fread(&header.bfType, 1, sizeof(header.bfType), file);
    fread(&header.bfSize, 1, sizeof(header.bfSize), file);
    fread(&header.bfReserved1, 1, sizeof(header.bfReserved1), file);
    fread(&header.bfReserved2, 1, sizeof(header.bfReserved2), file);
    fread(&header.bfOffBits, 1, sizeof(header.bfOffBits), file); // Нам нужно это поле
 
 
    cout << hex << "bfType = " << "0x" << header.bfType << endl;
    cout << hex << "bfSize = " << "0x" << header.bfSize << endl;
    cout << hex << "bfOffBits = " << "0x" << header.bfOffBits << endl;
 
    // Читаем вторую структуру (BITMAPINFOHEADER) чтобы узнать размер буфера пикселей
    fread(&info_header, 1, sizeof(info_header), file);
    cout << "biWidth = " << info_header.biWidth << endl;
    cout << "biHeight = " << info_header.biHeight << endl;
 
    if (info_header.biSizeImage == 0) { // Если это поле оказалось нулевым
        image_size = info_header.biWidth * 3 + info_header.biWidth % 4;
        image_size *= info_header.biHeight; // считаем вручную
    } else {
        image_size = info_header.biSizeImage; // иначе - берем как есть
    }
 
    cout << "size = " << image_size << endl;
 
    fseek(file, header.bfOffBits, SEEK_SET); // Смещаемся к буферу пикселей
    //fread(array_of_pixel, image_size, 1, file); // Читаем
 
    // Заводим двухмерный массив под структуры пикселя
    pix_arr->height = height = info_header.biHeight;
    pix_arr->width = width = info_header.biWidth;
    pix_arr->array_of_pixel = new pixel_t *[width];
    for (int i = 0; i < width; ++i) {
        pix_arr->array_of_pixel[i] = new pixel_t[height];
    }
 
    //задаем значения массиву
    for (int i = 0; i < width; ++i) {
        for (int j = 0; j < height ; ++j)
            fread(&pix_arr->array_of_pixel[i][j], sizeof(pixel_t), 1, file);
    }
 
}
 
void create_image(const char *name, pixel_t **pixels, int width, int height, BITMAPFILEHEADER &header, BITMAPINFOHEADER &info_header) {
    FILE *f;
 
    f = fopen(name, "wb");
    fwrite(&header.bfType, sizeof(header.bfType), 1, f);
    fwrite(&header.bfSize, sizeof(header.bfSize),1, f);
    fwrite(&header.bfReserved1, sizeof(header.bfReserved1),1, f);
    fwrite(&header.bfReserved2, sizeof(header.bfReserved2),1, f);
    fwrite(&header.bfOffBits, sizeof(header.bfOffBits),1, f);
 
    fwrite(&info_header, sizeof(info_header), 1, f);
 
    for(int i = 0; i < width; ++i) {
        for (int j = 0; j < height; ++j) {
            unsigned char pix [] = {pixels[i][j].red, pixels[i][j].green, pixels[i][j].blue};
            //unsigned char pix [] = {0, 0, (char)pixels[i][j]};
            fwrite(pix, 1, 3, f);
        }
    }
    fclose(f);
}
 
 
int main()
{
    char file_path[MAX_PATH_LEN] = "tank.bmp";
    pixel_array_t arr_info = {NULL, 0, 0}; // Массив структур пикселя.
 
    FILE *bmp_file;
 
    bmp_file = fopen(file_path, "r");
    if (bmp_file == NULL) {
        cout << "Error, file not found" << endl;
        return -1;
    }
 
    BITMAPFILEHEADER header; BITMAPINFOHEADER info_header;
 
    parse_file(bmp_file, &arr_info, header, info_header);
 
    cout << "w = " << arr_info.width << " h = " << arr_info.height << endl;
 
    create_image("result.bmp", arr_info.array_of_pixel, arr_info.width, arr_info.height, header, info_header);
 
    fclose(bmp_file);
 
 
    cout << "finished" << endl;
 
    return 0;
}
Вложения
Тип файла: zip bmp.zip (90.9 Кб, 13 просмотров)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.03.2014, 23:33     Открытие и запись файла bmp. Что здесь не так ?
Посмотрите здесь:

Открытие и запись bmp-файла - C++
Здравствуйте уважаемые участники форума. Прошу помощи, т.к. не могу найти ошибку в программе. Задача - прочитать побайтно файл bmp и...

Что здесь не так? - C++
// xc.cpp: определяет точку входа для консольного приложения. // #include &quot;stdafx.h&quot; // Таблица функции #include&lt;math.h&gt; ...

Что здесь не так - C++
Я хотел сделать программу для сложения двух чисел. после ввода второго слагаемого окно пропадает, я не могу найти свою ошибку Помогите...

Что здесь не так? - C++
Только начал изучать С++. Решил написать программу которая гласит что число больше или меньше ста и парное оно или непарное. За код строго...

Кто знает что здесь не так - C++
короче нада чтобы прожка спрашевала имя потом возраст а выводила имя и возрастнуб категорию человека в зависимости от введенного им...

что здесь не так? (из промежутка [n; m] вывести число, которое имеет наибольшее делителей) - C++
из промежутка вывести число, которое имеет наибольше делителей код: # include &lt;iostream&gt; # include &lt;conio.h&gt; using namespace std; ...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
mariko_11
2 / 2 / 1
Регистрация: 11.03.2013
Сообщений: 64
21.03.2014, 23:44  [ТС]     Открытие и запись файла bmp. Что здесь не так ? #2
А вот этот файл вообще копируется битым
Вложения
Тип файла: zip test_apache.zip (59.1 Кб, 6 просмотров)
alsav22
5416 / 4812 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
22.03.2014, 14:55     Открытие и запись файла bmp. Что здесь не так ? #3
Цитата Сообщение от mariko_11 Посмотреть сообщение
C++
1
2
FILE *bmp_file;
bmp_file = fopen(file_path, "r");
Открываете файл в текстовом режиме, а используете бинарные методы чтения. "rb" нужно.
mariko_11
2 / 2 / 1
Регистрация: 11.03.2013
Сообщений: 64
22.03.2014, 15:08  [ТС]     Открытие и запись файла bmp. Что здесь не так ? #4
Исправлено, но стало не сильно лучше. Последний рисунок всё равно получается битым. При открытии его в среде видна чёрная полоса наверху, а виндовая программа просмотра вообще его не открывает. В остальных битых рисунках та же история. Изображение почему-то полностью не влазит. Не могу понять, почему.
zss
Модератор
Эксперт С++
6321 / 5905 / 1913
Регистрация: 18.12.2011
Сообщений: 15,183
Завершенные тесты: 1
22.03.2014, 18:31     Открытие и запись файла bmp. Что здесь не так ? #5
Не забывайте, что строки изображения выровнены на границу двойного слова
(т.е. длина строки кратна 8).
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.03.2014, 21:59     Открытие и запись файла bmp. Что здесь не так ?
Еще ссылки по теме:

Создание/открытие файлов, чтение из файла и запись в файл через наследование - C++
Имеется следующая иерархия классов: Файл, Типизированный файл, Текстовый файл Методы: Создать/Открыть файл, Чение из файла, Запись в...

Открытие .bmp - C++
Как открыть .bmp в VS 2012?

проверить моно ли в шестеричную запись числа вставить цифр 2 так,что она стала совершенной - C++
помогите пожалуйста проверить,можно ли в шестеричную запись числа х вставить цифру 2 так,что оно стало совершенным?на вход дается...

скажите пожалуйста, что означает здесь b. ,это какия-либо функция или что? - C++
скажите пожалуйста, что означает здесь b. ,это какия-либо функция или что? //анализируем все клетки доски for(int i = 0; i &lt; 8;...

Чтение чисел из файла.Что делаю не так? - C++
По заданию нужно чтоб читались значения в виде массива из файла и провести с массивом в дальнейшем различные операции(формулами,графиком) и...

Преобразовать код так, что бы ввод данных осуществлялся из файла - C++
Задание 2. Создал структуру: #include &quot;stdafx.h&quot; #include &quot;stdio.h&quot; #include &lt;iostream&gt; using namespace std; struct sity { ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
alsav22
5416 / 4812 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
23.03.2014, 21:59     Открытие и запись файла bmp. Что здесь не так ? #6
Цитата Сообщение от zss Посмотреть сообщение
(т.е. длина строки кратна 8).
А не четырём?

Добавлено через 1 час 56 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include <iostream>
using namespace std;
 
typedef struct pixel 
{
    char red;
    char green;
    char blue;
 
} pixel_t;
 
typedef struct pixel_array 
{
    pixel_t **array_of_pixel;
    long height;
    long width;
 
} pixel_array_t;
 
typedef struct tagBITMAPFILEHEADER {
    unsigned short    bfType;
    unsigned long     bfSize;
    unsigned short    bfReserved1;
    unsigned short    bfReserved2;
    unsigned long     bfOffBits;
} BITMAPFILEHEADER;
 
typedef struct tagBITMAPINFOHEADER {
    unsigned long biSize;
    unsigned long biWidth;
    unsigned long biHeight;
    unsigned short  biPlanes;
    unsigned short  biBitCount;
    unsigned long biCompression;
    unsigned long biSizeImage;
    long  biXPelsPerMeter;
    long  biYPelsPerMeter;
    unsigned long biClrUsed;
    unsigned long biClrImportant;
} BITMAPINFOHEADER;
 
const int MAX_PATH_LEN = 260;
 
void parse_file(FILE *file, pixel_array_t& pix_arr, BITMAPFILEHEADER &header, BITMAPINFOHEADER &info_header) {
 
    unsigned long image_size = 0;
    long height = 0;
    long width = 0;
 
    // Читаем первую структуру (BITMAPFILEHEADER)
    fread(&header.bfType, 1, sizeof(header.bfType), file);
    fread(&header.bfSize, 1, sizeof(header.bfSize), file);
    fread(&header.bfReserved1, 1, sizeof(header.bfReserved1), file);
    fread(&header.bfReserved2, 1, sizeof(header.bfReserved2), file);
    fread(&header.bfOffBits, 1, sizeof(header.bfOffBits), file); // Нам нужно это поле
 
 
    cout << hex << "bfType = " << "0x" << header.bfType << endl;
    cout << hex << "bfSize = " << "0x" << header.bfSize << endl;
    cout << hex << "bfOffBits = " << "0x" << header.bfOffBits << endl;
 
    // Читаем вторую структуру (BITMAPINFOHEADER) чтобы узнать размер буфера пикселей
    fread(&info_header, 1, sizeof(info_header), file);
    cout << "biWidth = " << info_header.biWidth << endl;
    cout << "biHeight = " << info_header.biHeight << endl;
 
    if (info_header.biSizeImage == 0) { // Если это поле оказалось нулевым
        image_size = info_header.biWidth * 3 + info_header.biWidth % 4;
        image_size *= info_header.biHeight; // считаем вручную
    } else {
        image_size = info_header.biSizeImage; // иначе - берем как есть
    }
 
    cout << "size = " << image_size << endl;
 
    fseek(file, header.bfOffBits, SEEK_SET); // Смещаемся к буферу пикселей
    //fread(array_of_pixel, image_size, 1, file); // Читаем
    
    // Заводим двухмерный массив под структуры пикселя
    pix_arr.height = height = info_header.biHeight;
    pix_arr.width = width = info_header.biWidth;
 
    pix_arr.array_of_pixel = new pixel_t* [height];
    for (int i = 0; i < height; ++i)
        pix_arr.array_of_pixel[i] = new pixel_t [width];
    
    int length_str = (3 * width + 3) & (-4); // длина строки в файле, включая округление вверх до кратного 4
    int n = length_str - width * 3; // количество байтов выравнивания в строке
    
    //задаем значения массиву
    for (int i = 0; i < height; ++i)
    {
        int j;
        for (j = 0; j < width; ++j)
            fread(&(pix_arr.array_of_pixel[i][j]), sizeof(pixel_t), 1, file);
        
        for (int k = 0; k < n; ++k) // пропуск байтов выравнивания
            fgetc(file);
    }
}
 
void create_image(const char *name, pixel_t** pixels, int width, int height, BITMAPFILEHEADER &header, BITMAPINFOHEADER &info_header) {
    FILE *f;
 
    f = fopen(name, "wb");
    fwrite(&header.bfType, sizeof(header.bfType), 1, f);
    fwrite(&header.bfSize, sizeof(header.bfSize),1, f);
    fwrite(&header.bfReserved1, sizeof(header.bfReserved1),1, f);
    fwrite(&header.bfReserved2, sizeof(header.bfReserved2),1, f);
    fwrite(&header.bfOffBits, sizeof(header.bfOffBits),1, f);
 
    fwrite(&info_header, sizeof(info_header), 1, f);
 
    int length_str = (3 * width + 3) & (-4); // длина строки в файле, включая округление вверх до кратного 4
    int n = length_str - width * 3; // количество байтов выравнивания в строке
    
    for (int i = 0; i < height; ++i)
    {
        for (int j = 0; j < width; ++j)
        {
            unsigned char pix [] = {pixels[i][j].red, pixels[i][j].green, pixels[i][j].blue};
            fwrite(pix, 1, 3, f);
        }
        for (int k = 0; k < n; ++k) // запись байтов выравнивания
        {
            fputc(0, f);
        }
    }
    
    for (int i = 0; i < info_header.biSizeImage - length_str * height; ++i)
        fputc(0, f);
    fclose(f);
}
 
 
int main()
{
    char file_path[MAX_PATH_LEN] = "test_apache.bmp";
    pixel_array_t arr_info = {NULL, 0, 0}; // Массив структур пикселя.
 
    FILE *bmp_file;
 
    bmp_file = fopen(file_path, "rb");
    if (bmp_file == NULL) {
        cout << "Error, file not found" << endl;
        return -1;
    }
 
    BITMAPFILEHEADER header; BITMAPINFOHEADER info_header;
 
    parse_file(bmp_file, arr_info, header, info_header);
 
    cout << "w = " << arr_info.width << " h = " << arr_info.height << endl;
 
    create_image("result.bmp", arr_info.array_of_pixel, arr_info.width, arr_info.height, header, info_header);
 
    fclose(bmp_file);
 
 
    cout << "finished" << endl;
 
    cin.get();
    return 0;
}
Добавлено через 20 часов 5 минут
mariko_11, что молчим? Проблема решена?
Yandex
Объявления
23.03.2014, 21:59     Открытие и запись файла bmp. Что здесь не так ?
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru