动态分配数组实现bmp图片读取、翻转、缩小、灰白处理、保存
读取图片,图片翻转
实验要求:
1.动态分配二维数组a,将图像数据“降维”后读入a中。
这里的“降维”指的是把3通道的彩色图像读取到单通道的二维数组中。
2.将数组a的元素上下翻转。即第一行变为最后一行。即实现函数FlipImageUpDown。
3.将数组a的元素左右翻转。即第一列变为最后一列。即实现函数FlipImageLeftRight。
4.将图像缩小为原来尺寸的一半,存入动态分配内存的二维数组b。
一个简单的做法是将a中的属于奇数行和奇数列的元素读取写入到b中。
操作完成后,将b写回硬盘一个新的BMP文件中。
具体实验题目
https://wws.lanzous.com/b01i760yh
密码:8s16
图片:
自己随便找一张,放到相应目录下,注意把源码里读取的图片的名字改一下。
出现的问题
//读取数据的函数一使用就报错,一直解决不了
void readData(unsigned char ** data,
BMPFILEHEADER& bmpfileheader, BITMAPINFOHEADER& bitmapinfoheader)
/* *
*主要是,参数列表的 unsigned char ** data 有问题,这里最好是用一个三级指针接收,
*可以自己类比感觉一下,普通变量用一级指针接收,才能直接操作
*/
解决:
unsigned char** readData(BMPFILEHEADER& bmpfileheader, BITMAPINFOHEADER& bitmapinfoheader)
直接函数返回一个开辟在堆区数据的地址。
源码
1.main.cpp
#include "结构体.h"
#include "函数.h"
int main()
{
BMPFILEHEADER bmpfileheader;
BITMAPINFOHEADER bitmapinfoheader;
unsigned char** data = NULL;
data = readData(bmpfileheader, bitmapinfoheader);
//1.打印单行字节数
printf("每行的字节数为:%d\n", (bitmapinfoheader.biSizeImage / bitmapinfoheader.biHeight));
//2.把真彩图简单地变为灰度图并保存
removeColors(data, bitmapinfoheader);
saveData(data, bmpfileheader, bitmapinfoheader, "noColor.bmp");
//3.上下翻转图片
flipImageUpDown(data, bmpfileheader, bitmapinfoheader);
//4.左右翻转图片
flipImageLeftRight(data, bmpfileheader, bitmapinfoheader);
//5.缩小图片
shrinkImage(data, bmpfileheader, bitmapinfoheader);
// 释放动态分配的内存
myFree(data,bitmapinfoheader);
return 0;
}
2.function.cpp
#pragma once
#include "函数.h"
//读取数据的函数
unsigned char** readData(BMPFILEHEADER& bmpfileheader, BITMAPINFOHEADER& bitmapinfoheader)
{
FILE* fp = NULL; // C标准库的文件指针
fopen_s(&fp, FILENAME, "rb"); // 二进制读取方式打开文件
unsigned char** data = NULL;
// 读取文件头
fread(&bmpfileheader, sizeof(bmpfileheader), 1, fp);
// 读取信息头
fread(&bitmapinfoheader, sizeof(bitmapinfoheader), 1, fp);
// 动态分配二维数组存储像素数据,注意先申请一个存放指针的数组,
data = (unsigned char **)malloc(sizeof(unsigned char*) * bitmapinfoheader.biHeight);
//其大小为sizeof(unsigned char*) * bitmapinfoheader.biHeight,这点很容易错
//申请行指针
for (int i = 0; i < bitmapinfoheader.biHeight; i++