Считать 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
используется для указания на массив, содержащий данные изображения.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д