Считать bmp побайтно и пересохранить - C (СИ)
Формулировка задачи:
необходимо открыть bmp файл, считать заголовок(читаю оба в одну структуру)
считать растровый массив( с этим походу и есть беда)
произвести манипуляции с массивом(это пока опустим)
и сохранить результат в новый bmp (пока что просто перезаписать этот файл с другим именем)
пробую так
насколько я понял, беда с чтением растрового массива. как его правильно читать?
Листинг программы
- #include <stdio.h>
- int openBMP(char* path);
- int saveBMP(char* path);
- #pragma pack(push, 2)
- struct BmpHeader {
- unsigned char b1, b2; // Символы BM (2 байта)
- unsigned long size; // Размер файла (4 байта)
- unsigned short notUse1; // (2 байта)
- unsigned short notUse2; // (2 байта)
- unsigned long massPos; // Местанахождение данных растрового массива (4 байта)
- unsigned long headerLength; // Длинна этого заголовка (4 байта)
- unsigned long width; // Ширина изображения (4 байта)
- unsigned long height; // Высота изображения (4 байта)
- unsigned short colorPlaneNumber; // Число цветовых плоскостей (2 байта)
- unsigned short bitPixel; // Бит/пиксель (2 байта)
- unsigned long compressMethod; // Метод сжатия (4 байта)
- unsigned long massLength; // Длинна массива с мусоро (4 байта)
- unsigned long massWidth; // Ширина массива с мусором (4 байта)
- unsigned long massHeight; // Высота массива с мусором (4 байта)
- unsigned long colorNumber; // Число цветов изображения (4 байта)
- unsigned long generalColorNumber; // Число основных цветов (4 байта)
- } bmpHeader;
- #pragma pack(pop)
- unsigned char** img;
- int main(void)
- {
- if (readBMP("D:\\1.bmp") == 0) {
- printf("bad path");
- return 0;
- }
- if (saveBMP("D:\\_1.bmp") == 0) {
- printf("bad path");
- return 0;
- }
- return 0;
- }
- int readBMP(char* path) {
- FILE* file;
- int i, j;
- file = fopen(path,"rb");
- if(file == NULL) return 0;
- fread(&bmpHeader, sizeof(bmpHeader), 1, file);
- if (bmpHeader.b1 != 'B' || bmpHeader.b2 != 'M' || bmpHeader.bitPixel != 24) {
- printf("corrupted file");
- return 0;
- }
- img = (unsigned char**)calloc(bmpHeader.width, sizeof(*img));
- for(i = 0; i < bmpHeader.width; ++i)
- img[i] = (unsigned char*)calloc(bmpHeader.height, sizeof(*img[i]));
- for (i = 0; i < bmpHeader.width; i++) {
- for (j = 0; j < bmpHeader.height; j++) {
- fread(&img[i][j], sizeof(img[i][j]), 1, file);
- }
- }
- fclose(file);
- return 1;
- }
- int saveBMP(char* path) {
- FILE* file;
- int i, j;
- file = fopen(path,"wb");
- if(file == NULL) return 0;
- fwrite(&bmpHeader, sizeof(bmpHeader), 1, file);
- for (i = 0; i < bmpHeader.width; i++) {
- for (j = 0; j < bmpHeader.height; j++) {
- fwrite(&img[i][j], sizeof(img[i][j]), 1, file);
- }
- }
- fclose(file);
- return 1;
- }
Решение задачи: «Считать bmp побайтно и пересохранить»
textual
Листинг программы
- void rotate(const struct BmpHeader* head, unsigned char* img) {
- int i, j;
- int bytes = head->bitPixel / 8;
- int width = (bytes * head->width + bytes) & (-4);
- for (i = 0; i < head->height / 2; ++i) {
- for (j = 0; j < head->width; ++j) {
- swap(img + (width * i) + j * bytes,
- img + (width * (head->height - i - 1)) + j * bytes,
- bytes);
- }
- }
- }
Объяснение кода листинга программы
- Функция
rotate
принимает два аргумента: указатель на структуруBmpHeader
и указатель на массивimg
. - Внутри функции объявлены две переменные
i
иj
для использования в циклах. - Переменная
bytes
инициализируется значениемhead->bitPixel / 8
, гдеhead->bitPixel
— количество бит на пиксель, а/ 8
— деление на 8 для получения количества байт на пиксель. - Переменная
width
инициализируется значением(bytes * head->width + bytes) & (-4)
, гдеhead->width
— ширина изображения в пикселях, аbytes
— количество байт на пиксель. Значение& (-4)
используется для округления значения в меньшую сторону до ближайшего числа, кратного 4. - Переменная
i
инициализируется значением 0, а переменнаяj
инициализируется значением 0. - В цикле
for
перебираются все строки изображения от 0 доhead->height / 2 - 1
. - Внутри цикла
for
перебираются все столбцы изображения от 0 доhead->width - 1
. - Внутри вложенного цикла
for
происходит обмен значений двух указателей на массивimg
. Первый указатель указывает на текущую строку изображения, второй указатель указывает на строку изображения, которая будет перевернута. - Значение переменной
bytes
используется для определения количества байт, которые необходимо обменять. - Функция
swap
используется для обмена значений двух указателей на массивimg
. - Значение переменной
i
увеличивается на 1 после каждой итерации внешнего циклаfor
. - Значение переменной
j
увеличивается на 1 после каждой итерации внутреннего циклаfor
. - Значение переменной
width
используется для определения длины строки изображения в байтах. - Значение переменной
head->height
используется для определения высоты изображения в пикселях. - Значение переменной
head->width
используется для определения ширины изображения в пикселях. - Значение переменной
bytes
используется для определения количества байт на пиксель. - Значение переменной
i
используется для определения номера строки изображения. - Значение переменной
j
используется для определения номера столбца изображения. - Значение переменной
head->bitPixel
используется для определения количества бит на пиксель. - Значение переменной
img
используется для указания на массив, содержащий данные изображения.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д