This commit is contained in:
SunnyGor 2023-01-13 18:56:00 +08:00
parent cbbda43098
commit df85a8810b
10 changed files with 62 additions and 846 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 B

After

Width:  |  Height:  |  Size: 134 B

View File

@ -1,2 +0,0 @@
*height = info_h.biHeight;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 169 KiB

View File

@ -1,619 +0,0 @@
#include "image.h"
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cstring>
using namespace std;
//普通构造函数
Image::Image(int h, int w) :height(h), width(w)
{
this->height = h;
this->width = w;
// 动态分配二维数组存储像素数据,注意先申请一个存放指针的数组,
data = (unsigned char **)malloc(sizeof(unsigned char*) * this->height);
//其大小为sizeof(unsigned char*) * bitmapinfoheader.biHeight这点很容易错
//申请行指针
for (int i = 0; i < this->height; i++)
{
//注意3通道每个像素3个字节
data[i] = (unsigned char *)malloc(this->width * 3);
// 读取像素数据
for (int j = 0; j < this->width; j++)
{
data[i][j] = 0;
}
}
}
Image::Image(int h, int w, unsigned char val)//创建的图像像素值都为val;
{
this->height = h;
this->width = w;
// 动态分配二维数组存储像素数据,注意先申请一个存放指针的数组,
data = (unsigned char **)malloc(sizeof(unsigned char*) * this->height);
//其大小为sizeof(unsigned char*) * bitmapinfoheader.biHeight这点很容易错
//申请行指针
for (int i = 0; i < this->height; i++)
{
//注意3通道每个像素3个字节
data[i] = (unsigned char *)malloc(this->width * 3);
// 读取像素数据
for (int j = 0; j < this->width; j++)
{
data[i][j] = val;
}
}
}
Image::Image(const char* ImageName)//利用文件名从硬盘加载图像文件成为Image对象;
{
this->ReadBMP(ImageName);
}
Image::Image(unsigned char *m, int rows, int cols)//从一维静态数组创建Image对象图像的行数和列数由后面两个参数给出;
{
this->height = rows;
this->width = cols;
// 动态分配二维数组存储像素数据,注意先申请一个存放指针的数组,
data = (unsigned char **)malloc(sizeof(unsigned char*) * this->height);
//其大小为sizeof(unsigned char*) * bitmapinfoheader.biHeight这点很容易错
//申请行指针
for (int i = 0; i < this->height; i++)
{
//注意3通道每个像素3个字节
data[i] = (unsigned char *)malloc(this->width * 3);
// 读取像素数据
for (int j = 0; j < this->width; j++)
{
data[i][j] = *m;
m++;
}
}
}
Image::Image(unsigned char m[][100], int rows)//从静态二维数组创建Image对象图像的行数二维数组的第一个维度由第二个参数rows给出;
{
this->height = rows;
this->width = 100;
// 动态分配二维数组存储像素数据,注意先申请一个存放指针的数组,
data = (unsigned char **)malloc(sizeof(unsigned char*) * this->height);
//其大小为sizeof(unsigned char*) * bitmapinfoheader.biHeight这点很容易错
//申请行指针
for (int i = 0; i < this->height; i++)
{
//注意3通道每个像素3个字节
data[i] = (unsigned char *)malloc(this->width * 3);
// 读取像素数据
for (int j = 0; j < this->width; j++)
{
data[i][j] = m[i][j];
}
}
}
Image::Image(unsigned char **m, int h, int w)//从动态数组二级指针创建Image对象图像的行数和列数由后面两个参数给出;
{
this->height = h;
this->width = w;
// 动态分配二维数组存储像素数据,注意先申请一个存放指针的数组,
data = (unsigned char **)malloc(sizeof(unsigned char*) * this->height);
//其大小为sizeof(unsigned char*) * bitmapinfoheader.biHeight这点很容易错
//申请行指针
for (int i = 0; i < this->height; i++)
{
//注意3通道每个像素3个字节
data[i] = (unsigned char *)malloc(this->width * 3);
// 读取像素数据
for (int j = 0; j < this->width; j++)
{
data[i][j] = m[i][j];
}
}
}
//拷贝构造函数
Image::Image(Image &im)
{
if (this->data)
{
delete[] this->data;
this->data = NULL;
}
*this = im;
}
//释放堆区数据
void Image::myFree(unsigned char** data, int h)
{
for (int i = 0; i < h; i++)
{
free(data[i]);
data[i] = NULL;
}
free(data);
data = NULL;
puts("释放堆区数据");
}
//析构函数
Image::~Image()
{
this->myFree(this->data, this->height);
}
//从硬盘读入图像文件存储到image类中
void Image::ReadBMP(const char* filename)
{
FILE* fp = NULL; // C标准库的文件指针
fp = fopen(filename, "rb"); // 二进制读取方式打开文件
// 读取文件头
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++)
{
//注意3通道每个像素3个字节
data[i] = (unsigned char *)malloc(bitmapinfoheader.biWidth * 3);
// 读取像素数据
for (int j = 0; j < bitmapinfoheader.biWidth * 3; j++)
{
fread(&data[i][j], 1, 1, fp);
}
}
this->height = this->bitmapinfoheader.biHeight;
this->width = this->bitmapinfoheader.biWidth;
printf("height = %d width = %d\n",this->height,this->width);
// 关闭读取的文件
fclose(fp);
}
//保存bmp图像
void Image::WriteBMP(const char *filename)
{
FILE* fp = NULL; // 保存文件的文件指针
fp = fopen(filename, "wb"); // 二进制写入方式打开文件
// 写入文件头
fwrite(&bmpfileheader, sizeof(bmpfileheader), 1, fp);
// 写入信息头
fwrite(&bitmapinfoheader, sizeof(bitmapinfoheader), 1, fp);
// 写入数据
for (int i = 0; i < bitmapinfoheader.biHeight; i++)
{
fwrite(data[i], bitmapinfoheader.biWidth * 3, 1, fp);
}
// 关闭写入的文件
fclose(fp);
}
//保存bmp图像
void Image::WriteBMP(const char *filename, unsigned char** data)
{
FILE* fp = NULL; // 保存文件的文件指针
fp = fopen(filename, "wb"); // 二进制写入方式打开文件
// 写入文件头
fwrite(&bmpfileheader, sizeof(bmpfileheader), 1, fp);
// 写入信息头
fwrite(&bitmapinfoheader, sizeof(bitmapinfoheader), 1, fp);
// 写入数据
for (int i = 0; i < bitmapinfoheader.biHeight; i++)
{
fwrite(data[i], bitmapinfoheader.biWidth * 3, 1, fp);
}
// 关闭写入的文件
fclose(fp);
}
//保存bmp图像
void Image::WriteBMP(const char *filename, unsigned char** t_data,
BMPFILEHEADER bmpfileheader, BITMAPINFOHEADER t_bitmapinfoheader)
{
FILE* fp = NULL; // 保存文件的文件指针
fp = fopen(filename, "wb"); // 二进制写入方式打开文件
// 写入文件头
fwrite(&bmpfileheader, sizeof(bmpfileheader), 1, fp);
// 写入信息头
fwrite(&t_bitmapinfoheader, sizeof(t_bitmapinfoheader), 1, fp);
// 写入数据
for (int i = 0; i < t_bitmapinfoheader.biHeight; i++)
{
fwrite(t_data[i], t_bitmapinfoheader.biWidth * 3, 1, fp);
}
// 关闭写入的文件
fclose(fp);
}
//从文本文件读取
void Image::ReadText(const char* filename)
{
FILE* fp = NULL; // C标准库的文件指针
fp = fopen(filename, "rb"); // 二进制读取方式打开文件
fread(&bitmapinfoheader.biHeight, sizeof(bitmapinfoheader.biHeight), 1, fp);
fread(&bitmapinfoheader.biWidth, sizeof(bitmapinfoheader.biWidth), 1, fp);
// 动态分配二维数组存储像素数据,注意先申请一个存放指针的数组,
data = (unsigned char **)malloc(sizeof(unsigned char*) * bitmapinfoheader.biHeight);
//其大小为sizeof(unsigned char*) * bitmapinfoheader.biHeight这点很容易错
//申请行指针
for (int i = 0; i < bitmapinfoheader.biHeight; i++)
{
//注意3通道每个像素3个字节
data[i] = (unsigned char *)malloc(bitmapinfoheader.biWidth * 3);
// 读取像素数据
for (int j = 0; j < bitmapinfoheader.biWidth * 3; j++)
{
fread(&data[i][j], 1, 1, fp);
}
}
// 关闭读取的文件
fclose(fp);
}
//保存成文本文件
void Image::WriteText(const char *filename)
{
FILE* fp = NULL; // 保存文件的文件指针
fp = fopen(filename, "wb"); // 二进制写入方式打开文件
// 写入信息头
fwrite(&bitmapinfoheader.biHeight, sizeof(bitmapinfoheader.biHeight), 1, fp);
fwrite(&bitmapinfoheader.biWidth, sizeof(bitmapinfoheader.biWidth), 1, fp);
// 写入数据
for (int i = 0; i < bitmapinfoheader.biHeight; i++)
{
fwrite(data[i], bitmapinfoheader.biWidth * 3, 1, fp);
}
// 关闭写入的文件
fclose(fp);
}
//获取图像中指定点的值
unsigned char& Image::At(int row, int col)
{
return this->data[row * 3][col * 3];
}
//设置像素(row,col)为某值
void Image::Set(int row, int col, unsigned char value)
{
//重新读取数据
unsigned char** t_data = (unsigned char**)malloc(sizeof(unsigned char*) * bitmapinfoheader.biHeight);
for (int i = 0; i < bitmapinfoheader.biHeight; i++)
{
t_data[i] = (unsigned char*)malloc(bitmapinfoheader.biWidth * 3);
for (int j = 0; j < bitmapinfoheader.biWidth * 3; j++)
{
t_data[i][j] = data[i][j];
}
}
//修改像数值
for (int i = 0; i < 3; i++)
{
t_data[row * 3 + i][col * 3 + i] = value;
}
//保存图像
this->WriteBMP("setImg.bmp", t_data);
myFree(t_data, bitmapinfoheader.biHeight);
}
//设置图像所有像素为同一值
void Image::Set(unsigned char value)
{
//重新读取数据
unsigned char** t_data = (unsigned char**)malloc(sizeof(unsigned char*) * bitmapinfoheader.biHeight);
for (int i = 0; i < bitmapinfoheader.biHeight; i++)
{
t_data[i] = (unsigned char*)malloc(bitmapinfoheader.biWidth * 3);
for (int j = 0; j < bitmapinfoheader.biWidth * 3; j++)
{
t_data[i][j] = data[i][j];
}
}
//修改像数值
for (int i = 0; i < this->bitmapinfoheader.biHeight; i++)
{
for (int j = 0; j < this->bitmapinfoheader.biWidth * 3; j++)
{
t_data[i][j] = value;
}
}
//保存图像
this->WriteBMP("setAllImg.bmp", t_data);
myFree(t_data, bitmapinfoheader.biHeight);
}
//false 左右true 上下
void Image::Flip(int code)
{
//重新读取数据
unsigned char** t_data = (unsigned char**)malloc(sizeof(unsigned char*) * bitmapinfoheader.biHeight);
for (int i = 0; i < bitmapinfoheader.biHeight; i++)
{
t_data[i] = (unsigned char*)malloc(bitmapinfoheader.biWidth * 3);
for (int j = 0; j < bitmapinfoheader.biWidth * 3; j++)
{
t_data[i][j] = data[i][j];
}
}
if (code)
{
//上下翻转图片
for (int i = 0; i < bitmapinfoheader.biHeight / 2; i++)
{
unsigned char* temp = t_data[i];
t_data[i] = t_data[bitmapinfoheader.biHeight - 1 - i];
t_data[bitmapinfoheader.biHeight - 1 - i] = temp;
}
this->WriteBMP("flipImageUpDown.bmp",t_data);
}
else
{
//左右翻转图片
for (int i = 0; i < bitmapinfoheader.biHeight; i++)
{
for (int j = 0; j < bitmapinfoheader.biWidth * 3 / 2; j += 3)
{
unsigned char temp = t_data[i][j];
t_data[i][j] = t_data[i][bitmapinfoheader.biWidth * 3 - 1 - j - 2];
t_data[i][bitmapinfoheader.biWidth * 3 - 1 - j - 2] = temp;
unsigned char temp1 = t_data[i][j+1];
t_data[i][j + 1] = t_data[i][bitmapinfoheader.biWidth * 3 - 1 - j - 1];
t_data[i][bitmapinfoheader.biWidth * 3 - 1 - j - 1] = temp1;
unsigned char temp2 = t_data[i][j + 2];
t_data[i][j+2] = t_data[i][bitmapinfoheader.biWidth * 3 - 1 - j];
t_data[i][bitmapinfoheader.biWidth * 3 - 1 - j] = temp2;
}
}
this->WriteBMP("flipImageLeftRight.bmp",t_data);
}
this->myFree(t_data, this->bitmapinfoheader.biHeight);
}
//图像缩小,放大
//false缩小,true放大
void Image::Resize(int code)
{
if (code)//放大
{
/* *
*
*
*/
unsigned char** t_data = (unsigned char**)malloc(sizeof(unsigned char*) * bitmapinfoheader.biHeight * 2);
for (int i = 0; i < bitmapinfoheader.biHeight ; i++)
{
t_data[2 * i] = (unsigned char*)malloc(bitmapinfoheader.biWidth * 3 * 2);
for (int j = 0; j < bitmapinfoheader.biWidth; j++)
{
t_data[2 * i][6 * j] = data[i][3 * j];
t_data[2 * i][6 * j + 1] = data[i][3 * j + 1];
t_data[2 * i][6 * j + 2] = data[i][3 * j + 2];
t_data[2 * i][6 * j + 3] = data[i][3 * j];
t_data[2 * i][6 * j + 3 + 1] = data[i][3 * j + 1];
t_data[2 * i][6 * j + 3 + 2] = data[i][3 * j + 2];
}
t_data[2 * i + 1] = (unsigned char*)malloc(bitmapinfoheader.biWidth * 3 * 2);
for (int j = 0; j < bitmapinfoheader .biWidth * 6; j++)
{
t_data[2 * i + 1][j] = t_data[2 * i][j];
}
}
BMPFILEHEADER t_bmpfileheader = this->bmpfileheader;
BITMAPINFOHEADER t_bitmapinfoheader = this->bitmapinfoheader;
t_bitmapinfoheader.biHeight *= 2;
t_bitmapinfoheader.biWidth *= 2;
t_bitmapinfoheader.biSizeImage *= 4;
this->WriteBMP("magnifyImage.bmp", t_data, t_bmpfileheader, t_bitmapinfoheader);
this->myFree(t_data, t_bitmapinfoheader.biHeight);//释放内存
}
else//缩小
{
unsigned char** t_data = (unsigned char**)malloc(sizeof(unsigned char*) * bitmapinfoheader.biHeight / 2);
for (int i = 0; i < bitmapinfoheader.biHeight / 2; i++)
{
t_data[i] = (unsigned char*)malloc(bitmapinfoheader.biWidth * 3 / 2);
for (int j = 0, index = 0; j < bitmapinfoheader.biWidth / 2; j++)
{
t_data[i][index++] = data[2 * i][6 * j];
t_data[i][index++] = data[2 * i][6 * j + 1];
t_data[i][index++] = data[2 * i][6 * j + 2];
}
}
BMPFILEHEADER t_bmpfileheader = this->bmpfileheader;
BITMAPINFOHEADER t_bitmapinfoheader = this->bitmapinfoheader;
t_bitmapinfoheader.biHeight /= 2;
t_bitmapinfoheader.biWidth /= 2;
t_bitmapinfoheader.biSizeImage /= 4;
this->WriteBMP("shrinkImage.bmp", t_data, t_bmpfileheader, t_bitmapinfoheader);
this->myFree(t_data, t_bitmapinfoheader.biHeight);//释放内存
}
}
//图像裁剪的函数
void Image::Cut(int x1, int y1, int x2, int y2)
{//裁剪点(x1,y1)到点(x2,y2)的图像——(0,120) (512,360) h = y2 - y1 = 240, w = x2 - x1 = 512
if (x2 > x1 && y2 > y1)
{
int h = y2 - y1 + 1;
int w = x2 - x1 + 1;
while (w % 4)
{
w++;
}
//重新载入数据
unsigned char **t_data = (unsigned char**)malloc(h * sizeof(unsigned char*));
//m,n控制t_data的下标,i,j控制data下标
for (int i = y1,m = 0; i <= y2; i++, m++)
{
t_data[m] = (unsigned char*)malloc(w * 3);
memset(t_data[m],0, w * 3);
for (int j = x1*3, n = 0; j <= x2*3 + 2; j++, n++)
{
t_data[m][n] = data[i][j];
}
}
//重新载入头文件
BMPFILEHEADER t_bmpfileheader = this->bmpfileheader;
BITMAPINFOHEADER t_bitmapinfoheader = this->bitmapinfoheader;
t_bitmapinfoheader.biHeight = h;
t_bitmapinfoheader.biWidth = w;
//通过公式重新计算biSize
t_bitmapinfoheader.biSizeImage = (((w*t_bitmapinfoheader.biBitCount) + 31) / 32 * 4)*h;
//保存数据
WriteBMP("cutImage.bmp", t_data, t_bmpfileheader, t_bitmapinfoheader);
//释放数据
myFree(t_data, h);
}
else
{
puts("输入坐标有误");
}
}
//图像旋转的函数
void Image::Rotate(int degree)//图像旋转的函数简单起见旋转角度为90度的整数倍
{
BMPFILEHEADER t_bmpfileheader = this->bmpfileheader;
BITMAPINFOHEADER t_bitmapinfoheader = this->bitmapinfoheader;
if (degree == 90)
{
unsigned char** t_data = (unsigned char**)malloc(sizeof(unsigned char*) * bitmapinfoheader.biWidth);
for (int i = 0; i < bitmapinfoheader.biWidth; i++)
{
t_data[i] = (unsigned char*)malloc(bitmapinfoheader.biHeight * 3);
for (int j = 0; j < bitmapinfoheader.biHeight; j++)
{
t_data[i][j * 3] = data[bitmapinfoheader.biHeight - j - 1][3 * i];
t_data[i][j * 3 + 1] = data[bitmapinfoheader.biHeight - j - 1][3 * i + 1];
t_data[i][j * 3 + 2] = data[bitmapinfoheader.biHeight - j - 1][3 * i + 2];
}
}
//重写信息头
t_bitmapinfoheader.biHeight = this->bitmapinfoheader.biWidth;
t_bitmapinfoheader.biWidth = this->bitmapinfoheader.biHeight;
//保存图片
this->WriteBMP("rotate90.bmp", t_data, t_bmpfileheader, t_bitmapinfoheader);
this->myFree(t_data, t_bitmapinfoheader.biHeight);
}
else if (degree == 180)
{
unsigned char** t_data = (unsigned char**)malloc(sizeof(unsigned char*) * bitmapinfoheader.biHeight);
for (int i = 0; i < bitmapinfoheader.biHeight; i++)
{
t_data[i] = (unsigned char*)malloc(bitmapinfoheader.biWidth * 3);
for (int j = 0; j < bitmapinfoheader.biWidth; j++)
{
t_data[i][j * 3] = data[bitmapinfoheader.biHeight - i - 1][bitmapinfoheader.biWidth * 3 - j * 3 - 3];
t_data[i][j * 3 + 1] = data[bitmapinfoheader.biHeight - i - 1][bitmapinfoheader.biWidth * 3 - j * 3 - 3 + 1];
t_data[i][j * 3 + 2] = data[bitmapinfoheader.biHeight - i - 1][bitmapinfoheader.biWidth * 3 - j * 3 - 3 + 2];
}
}
//保存图片
this->WriteBMP("rotate180.bmp", t_data);
this->myFree(t_data, t_bitmapinfoheader.biHeight);
}
else if (degree == 270)
{
unsigned char** t_data = (unsigned char**)malloc(sizeof(unsigned char*) * bitmapinfoheader.biWidth);
for (int i = 0; i < bitmapinfoheader.biWidth; i++)
{
t_data[i] = (unsigned char*)malloc(bitmapinfoheader.biHeight * 3);
for (int j = 0; j < bitmapinfoheader.biHeight; j++)
{
t_data[i][j * 3] = data[j][bitmapinfoheader.biWidth * 3 - 3 -i * 3];
t_data[i][j * 3 + 1] = data[j][bitmapinfoheader.biWidth * 3 - 3 - i * 3 + 1];
t_data[i][j * 3 + 2] = data[j][bitmapinfoheader.biWidth * 3 - 3 - i * 3 + 2];
}
}
//重写信息头
t_bitmapinfoheader.biHeight = this->bitmapinfoheader.biWidth;
t_bitmapinfoheader.biWidth = this->bitmapinfoheader.biHeight;
//保存图片
this->WriteBMP("rotate270.bmp", t_data, t_bmpfileheader, t_bitmapinfoheader);
this->myFree(t_data, t_bitmapinfoheader.biHeight);
}
else
{
puts("输入的角度不符合要求");
}
}
//求均值方差
void Image::Mean_Variance(float &m, float &var)//求图像的均值和方差,利用参数输出
{
float sum = 0;
float ave = 0;
float vSum = 0;
float vAve = 0;
for (int i = 0; i < bitmapinfoheader.biHeight; i++)
{
for (int j = 0; j < bitmapinfoheader.biWidth * 3; j++)
{
sum += this->data[i][j];
}
}
ave = sum / (bitmapinfoheader.biHeight*bitmapinfoheader.biWidth * 3);
for (int i = 0; i < bitmapinfoheader.biHeight; i++)
{
for (int j = 0; j < bitmapinfoheader.biWidth * 3; j++)
{
vSum += (data[i][j] - ave)*(data[i][j] - ave);
}
}
vAve = vSum / (bitmapinfoheader.biHeight*bitmapinfoheader.biWidth * 3);
m = ave;
var = vAve;
}
Image& Image::operator=(Image& val)//重载操作符
{
this->bitmapinfoheader = val.bitmapinfoheader;
this->bmpfileheader = val.bmpfileheader;
this->height = val.height;
this->width = val.width;
// 动态分配二维数组存储像素数据,注意先申请一个存放指针的数组,
this->data = (unsigned char **)malloc(sizeof(unsigned char*) * bitmapinfoheader.biHeight);
//其大小为sizeof(unsigned char*) * bitmapinfoheader.biHeight这点很容易错
//申请行指针
for (int i = 0; i < bitmapinfoheader.biHeight; i++)
{
//注意3通道每个像素3个字节
this->data[i] = (unsigned char *)malloc(bitmapinfoheader.biWidth * 3);
// 读取像素数据
for (int j = 0; j < bitmapinfoheader.biWidth * 3; j++)
{
this->data[i][j] = val.data[i][j];
}
}
return *this;
}
//实现友元函数交换两个Image对象的数据
void Swap(Image &a, Image &b)
{
Image t(a);
a = b;
b = t;
}

View File

@ -1,60 +0,0 @@
#ifndef IMAGE_H
#define IMAGE_H
#include "struct.h"
class Image
{
public:
//构造函数及其重载
Image(){}//创建行列都为零的Image对象
Image(int h, int w);//创建h行w列的Image对象
Image(int h, int w, unsigned char val); //创建的图像像素值都为val;
Image(const char* ImageName); //利用文件名从硬盘加载图像文件成为Image对象;
Image(unsigned char *m, int rows, int cols); //从一维静态数组创建Image对象图像的行数和列数由后面两个参数给出;
Image(unsigned char m[][100], int rows); //从静态二维数组创建Image对象图像的行数二维数组的第一个维度由第二个参数rows给出;
Image(unsigned char **m, int h, int w); //从动态数组二级指针创建Image对象图像的行数和列数由后面两个参数给出;
Image(Image &im); //拷贝构造函数;
~Image(); //析构函数;
void ReadBMP(const char* filename); //从BMP文件中读入图像数据;
void WriteBMP(const char* filename); //将图像数据保存为BMP图像文件;
void WriteBMP(const char *filename, unsigned char** data);//翻转时写图片
void WriteBMP(const char *filename, unsigned char** data,//放缩时写图片
BMPFILEHEADER bmpfileheader, BITMAPINFOHEADER bitmapinfoheader);
void ReadText(const char* filename); //从文本文件中读入图像数据;
void WriteText(const char* filename); //将图像数据保存为文本文件;
unsigned char& At(int row, int col); //获取第row行第col列的像素点的值;
void Set(int row, int col, unsigned char value); //设置像素(row,col)为某值;
void Set(unsigned char value); //设置图像所有像素为同一值;
void Flip(int code); //图像的翻转; 根据code的值0:左右翻转1:上下翻转;
void Resize(int code); //图像的缩放;根据code的值0:缩小一倍1:放大一倍;
void Cut(int x1, int y1, int x2, int y2);//裁剪点(x1,y1)到点(x2,y2)的图像
void Rotate(int degree);//图像旋转的函数简单起见旋转角度为90度的整数倍
void Mean_Variance(float &m, float &var);//求图像的均值和方差,利用参数输出
friend void Swap(Image &a, Image &b);//使用友元函数交换两个Image对象的数据
void myFree(unsigned char** data, int h);
Image& operator=(Image& val);//重载操作符
private:
unsigned char **data;
int height;
int width;
BMPFILEHEADER bmpfileheader;
BITMAPINFOHEADER bitmapinfoheader;
};
#endif

View File

@ -1,75 +0,0 @@
#include "image.h"
#include <cstdio>
#include <cstdlib>
int main(int argc, char* argv[])
{
Image img; //创建对象
//读写BMP文件
img.ReadBMP("hello.bmp");
img.WriteBMP("FruitsCopy.bmp");
img.WriteText("FruitsCopy.text");
//读写text文件
Image readtxtImage;
readtxtImage.ReadText("FruitsCopy.text");
readtxtImage.WriteText("writeFruits.text");
//图像的上下翻转,并保存结果图像文件
img.Flip(true);
//图像的左右翻转,如img.Flip(true);并保存结果图像文件
img.Flip(false);
//左右翻转需要注意每个像数占3个字节翻转时不能简单直接翻转
//而需要每个字节对应地翻转
//图像的缩放,并保存结果图像文件
img.Resize(false);//图像缩小
img.Resize(true);//图像放大
//缩小时也需要注意每个像数占3个字节不能简单通过删除字节而缩小
//而需要每个字节对应地删除
//放大也是一样的道理
//获取图像的某点的像素值,并修改, 并保存结果图像文件
int row = 100;
int col = 100;
img.At(row, col);
img.Set(row, col, 10);
img.Set(100);
//使用拷贝构造函数创建新的对象
Image new_img(img);
new_img.WriteBMP("new_img.bmp");
//截取指定区域内的图像,并保存结果图像文件(x1,y1) (x2,y2)
new_img.Cut(120,120,360,360);
//需要保证 x2 > x1 && y2 > y1
//顺时针旋转图像并保存结果图像文件简单起见旋转角度为90度的整数倍
img.Rotate(90);
img.Rotate(180);
img.Rotate(270);
//求图像的均值和方差,并在命令行输出
float ave = 0;
float vAve = 0;
img.Mean_Variance(ave, vAve);
printf("平均值为:%f\n方差为:%f\n", ave, vAve);
//交换两个图像的数据
Image img1("Baboon.bmp");
Image img2("Lena.bmp");
Swap(img1, img2);
//保存交换完的结果图像文件
img1.WriteBMP("S_img1_baboon.bmp");
img2.WriteBMP("S_img2_lena.bmp");
return 0;
}

View File

@ -1,35 +0,0 @@
#ifndef STRUCT_H
#define STRUCT_H
// 针对该结构体的字节对齐问题调整对齐策略
#pragma pack(push,1)
struct BMPFILEHEADER
{
unsigned short bfType;
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
};
#pragma pack(pop)
struct BITMAPINFOHEADER
{
unsigned long biSize; //本结构所占用字节数 40字节
long biWidth; //位图的宽度,以像素为单位
long biHeight; //位图的高度,以像素为单位
unsigned short biPlanes; //目标设备的级别必须为1
unsigned short biBitCount; //每个像素所需的位数必须是1双色
//416色、8256色或24真彩色之一
unsigned long biCompression; //位图压缩类型,必须是 0BI_RGB不压缩
//1BI_RLE8压缩类型
//2BI_RLE压缩类型之一
unsigned long biSizeImage; //位图的大小,以字节为单位
long biXPelsPerMeter; //位图水平分辨率,每米像素数
long biYPelsPerMeter; //位图垂直分辨率,每米像素数
unsigned long biClrUsed; //位图实际使用的颜色表中的颜色数
unsigned long biClrImportant; //位图显示过程中重要的颜色数
};
#endif

Binary file not shown.

117
try.c
View File

@ -5,7 +5,7 @@
typedef unsigned char uch;
// 檔案結構
// 妾旀绲愭
#pragma pack(2)
struct BmpFileHeader {
uint16_t bfTybe;
@ -29,17 +29,17 @@ struct BmpInfoHeader {
};
#pragma pack()
//辅助计算函数
//杈呭姪璁$畻鍑芥暟
float linear_single(float x, float x1, float x2, float f1, float f2){
return floor(f1 * (x2 - x) / (x2 - x1) + f2 * (x - x1) / (x2 - x1));
}
// 双线性插值函数
// 参考 https://zh.wikipedia.org/wiki/%E5%8F%8C%E7%BA%BF%E6%80%A7%E6%8F%92%E5%80%BC
// 鍙岀嚎鎬ф彃鍊煎嚱鏁<EFBFBD>
// 鍙傝€<EFBFBD> https://zh.wikipedia.org/wiki/%E5%8F%8C%E7%BA%BF%E6%80%A7%E6%8F%92%E5%80%BC
char** linear_insert(uch** old_pixels, uint32_t row, uint32_t col, uint32_t old_width, uint32_t old_height, float radio_w, float radio_h){
float x = row / radio_h;
float y = col / radio_w;
// 如果整数格点就直接返回
// 濡傛灉鏁存暟鏍肩偣灏辩洿鎺ヨ繑鍥<EFBFBD>
int x1 = floor(x);
int x2 = ceil(x);
int y1 = floor(y);
@ -49,7 +49,7 @@ char** linear_insert(uch** old_pixels, uint32_t row, uint32_t col, uint32_t old_
if (y2 >= old_width){y2 = y1;}
if (x1 == x2 && y1 == y2){
uint32_t idx = x1*old_width+y1;
return old_pixels[x1][idx + 0], old_pixels[x1][idx + 1], old_pixels[x1][idx + 2];}
return old_pixels[idx + 0], old_pixels[idx + 1], old_pixels[idx + 2];}
if (x1 == x2){
int x = x1;
uint32_t idx1 = x*old_width+y;
@ -86,7 +86,7 @@ void bmpWrite(const char* name, const uch* raw_img, uint32_t width, uint32_t hei
perror("Error bmpWrite.");
return;
}
// 檔案資訊
// 妾旀璩囪▕
struct BmpFileHeader file_h = {
.bfTybe=0x4d42,
.bfReserved1=0,
@ -100,7 +100,7 @@ void bmpWrite(const char* name, const uch* raw_img, uint32_t width, uint32_t hei
if(bits==8) {file_h.bfSize+= 1024, file_h.bfOffBits+= 1024;}
// 圖片資訊
// 鍦栫墖璩囪▕
struct BmpInfoHeader info_h = {
.biSize=40,
.biPlanes=1,
@ -112,10 +112,10 @@ void bmpWrite(const char* name, const uch* raw_img, uint32_t width, uint32_t hei
};
info_h.biWidth = new_width;
info_h.biHeight = new_height;
info_h.biBitCount = bits;// 多少位的圖
info_h.biBitCount = bits;// 澶氬皯浣嶇殑鍦<EFBFBD>
info_h.biSizeImage = new_width*new_height * bits/8;
if(bits == 8) {info_h.biClrUsed=256;}
// 寫入檔頭
// 瀵叆妾旈牠
FILE *pFile = NULL;
// pFile = fopen(name,"wb+");
fopen_s(&pFile, name,"wb+");
@ -125,7 +125,7 @@ void bmpWrite(const char* name, const uch* raw_img, uint32_t width, uint32_t hei
}
fwrite((char*)&file_h, sizeof(char), sizeof(file_h), pFile);
fwrite((char*)&info_h, sizeof(char), sizeof(info_h), pFile);
// 寫調色盤
// 瀵鑹茬洡
if(bits == 8) {
for(unsigned i = 0; i < 256; ++i) {
uch c = i;
@ -137,44 +137,50 @@ void bmpWrite(const char* name, const uch* raw_img, uint32_t width, uint32_t hei
}
// char newpixels[new_width*new_height];
unsigned char **newpixels=(unsigned char**)malloc(new_width*new_height*3);// 沒用到
unsigned char **newpixels=(unsigned char**)malloc(new_width*new_height*3);// 娌掔敤鍒<EFBFBD>
// 寫入圖片資訊
// 瀵叆鍦栫墖璩囪▕
size_t alig = ((new_width*bits/8)*3) % 4;
// for(int j = new_height-1; j >= 0; --j) {
// for(unsigned i = 0; i < new_width; ++i) {
// uint32_t idx = j*new_width +i;
// if(bits == 24) { // RGB圖片
// fwrite((char*)&raw_img[idx*3 +2], sizeof(char), sizeof(uch), pFile);
// fwrite((char*)&raw_img[idx*3 +1], sizeof(char), sizeof(uch), pFile);
// fwrite((char*)&raw_img[idx*3 +0], sizeof(char), sizeof(uch), pFile);
// } else if(bits == 8) { // 灰階圖
// fwrite((char*)&raw_img[idx], sizeof(char), sizeof(uch), pFile);
// }
// }
for(int j = new_height-1; j >= 0; --j) {
for(unsigned i = 0; i < new_width; ++i) {
uint32_t idx = j*new_width +i;
if(bits == 24) { // RGB圖片
char** r, g, b = linear_insert(&(raw_img), j, i, width, height, radio_w, radio_h);
fwrite(b, sizeof(char), sizeof(uch), pFile);
fwrite(g, sizeof(char), sizeof(uch), pFile);
fwrite(r, sizeof(char), sizeof(uch), pFile);
} else if(bits == 8) { // 灰階圖
if(bits == 24) { // RGB鍦栫墖
fwrite((char*)&raw_img[idx*3 +2], sizeof(char), sizeof(uch), pFile);
fwrite((char*)&raw_img[idx*3 +1], sizeof(char), sizeof(uch), pFile);
fwrite((char*)&raw_img[idx*3 +0], sizeof(char), sizeof(uch), pFile);
// printf("%x",(raw_img)[idx*3 +2]);
// printf("%x",(raw_img)[idx*3 +1]);
// printf("%x",(raw_img)[idx*3 +0]);
// printf(" ");
}
else if(bits == 8) { // 鐏伴殠鍦<E6AEA0>
fwrite((char*)&raw_img[idx], sizeof(char), sizeof(uch), pFile);
}
// printf("\n");
}
//# 计算新像素
// 對齊4byte
// for(int j = new_height-1; j >= 0; --j) {
// for(unsigned i = 0; i < new_width; ++i) {
// uint32_t idx = j*new_width +i;
// if(bits == 24) { // RGB鍦栫墖
// char** r, g, b = linear_insert(&(raw_img), j, i, width, height, radio_w, radio_h);
// fwrite(b, sizeof(char), sizeof(uch), pFile);
// fwrite(g, sizeof(char), sizeof(uch), pFile);
// fwrite(r, sizeof(char), sizeof(uch), pFile);
// } else if(bits == 8) { // 鐏伴殠鍦<E6AEA0>
// fwrite((char*)&raw_img[idx], sizeof(char), sizeof(uch), pFile);
// }
// }
//# 璁畻鏂板儚绱<E5849A>
// 灏嶉綂4byte
for(size_t i = 0; i < alig; ++i) {
fwrite("", sizeof(char), sizeof(uch), pFile);
}
}
fclose(pFile);
free(newpixels); //記得釋放空間
free(newpixels); //瑷樺緱閲嬫斁绌洪枔
}
void bmpRead(const char* name, uch** oldpixels, uint32_t* width, uint32_t* height, uint16_t* bits)
{
@ -182,11 +188,11 @@ void bmpRead(const char* name, uch** oldpixels, uint32_t* width, uint32_t* heigh
perror("Error bmpRead.");
return;
}
// 檔案資訊
// 妾旀璩囪▕
struct BmpFileHeader file_h;
// 圖片資訊
// 鍦栫墖璩囪▕
struct BmpInfoHeader info_h;
// 讀取檔頭
// 璁€鍙栨獢闋<EFBFBD>
FILE *pFile = NULL;
// pFile = fopen(name, "rb+");
fopen_s(&pFile, name, "rb+");
@ -196,25 +202,25 @@ void bmpRead(const char* name, uch** oldpixels, uint32_t* width, uint32_t* heigh
}
fread((char*)&file_h, sizeof(char), sizeof(file_h), pFile);
fread((char*)&info_h, sizeof(char), sizeof(info_h), pFile);
// 讀取長寬
// 璁€鍙栭暦瀵<EFBFBD>
*width = info_h.biWidth;
*height = info_h.biHeight;
*bits = info_h.biBitCount;
**oldpixels=(unsigned char**)malloc((*width)*(*height)*3);
// **oldpixels=(unsigned char**)malloc((*width)*(*height)*3);
// size_t ImgSize = ((size_t)*width) * ((size_t)*height) * 3;
// *raw_img = (uch*)calloc(ImgSize, sizeof(uch));
// 讀取讀片資訊轉RAW檔資訊
size_t ImgSize = ((size_t)*width) * ((size_t)*height) * 3;
*oldpixels = (uch*)calloc(ImgSize, sizeof(uch));
// 璁€鍙栬畝鐗囪硣瑷婅綁RAW妾旇硣瑷<EFBFBD>
fseek(pFile, file_h.bfOffBits, SEEK_SET);
size_t alig = ((info_h.biWidth*info_h.biBitCount/8)*3) % 4;
for(int j = *height-1; j >= 0; --j) {
for(unsigned i = 0; i < *width; ++i) {
uint32_t idx = j*(*width)+i;
if(*bits == 24) { // RGB圖片
if(*bits == 24) { // RGB鍦栫墖
fread((char*)&(*oldpixels)[idx*3 +2], sizeof(char), sizeof(uch), pFile);
fread((char*)&(*oldpixels)[idx*3 +1], sizeof(char), sizeof(uch), pFile);
fread((char*)&(*oldpixels)[idx*3 +0], sizeof(char), sizeof(uch), pFile);
} else if(*bits == 8) { // 灰階圖
} else if(*bits == 8) { // 鐏伴殠鍦<EFBFBD>
fread((char*)&(*oldpixels)[idx], sizeof(char), sizeof(uch), pFile);
}
}
@ -226,17 +232,17 @@ void bmpRead(const char* name, uch** oldpixels, uint32_t* width, uint32_t* heigh
//---------------------------------------------------------------------------
// size_t ImgSize = ((size_t)*width) * ((size_t)*height) * 3;
// *raw_img = (uch*)calloc(ImgSize, sizeof(uch));
// // 讀取讀片資訊轉RAW檔資訊
// // 璁€鍙栬畝鐗囪硣瑷婅綁RAW妾旇硣瑷<EFBFBD>
// fseek(pFile, file_h.bfOffBits, SEEK_SET);
// size_t alig = ((info_h.biWidth*info_h.biBitCount/8)*3) % 4;
// for(int j = *height-1; j >= 0; --j) {
// for(unsigned i = 0; i < *width; ++i) {
// uint32_t idx = j*(*width)+i;
// if(*bits == 24) { // RGB圖片
// if(*bits == 24) { // RGB鍦栫墖
// fread((char*)&(*raw_img)[idx*3 +2], sizeof(char), sizeof(uch), pFile);
// fread((char*)&(*raw_img)[idx*3 +1], sizeof(char), sizeof(uch), pFile);
// fread((char*)&(*raw_img)[idx*3 +0], sizeof(char), sizeof(uch), pFile);
// } else if(*bits == 8) { // 灰階圖
// } else if(*bits == 8) { // 鐏伴殠鍦<EFBFBD>
// fread((char*)&(*raw_img)[idx], sizeof(char), sizeof(uch), pFile);
// }
// }
@ -249,16 +255,17 @@ void bmpRead(const char* name, uch** oldpixels, uint32_t* width, uint32_t* heigh
for(unsigned i = 0; i < *width; ++i) {
uint32_t idx = j*(*width)+i;
for(int k = 0; k < 3; k++){
printf((char*)&(*oldpixels)[idx*3 + k]);
printf("\t");
printf("%x",(*oldpixels)[idx*3 +k]);
printf(" ");
}
printf("\t done \t");
printf("\t");
}
printf("\n");
}
printf("done \n");
}
// 圖像結構
// 鍦栧儚绲愭
typedef struct Imgraw {
uint32_t width, height;
uint16_t bits;
@ -281,11 +288,11 @@ int main(int argc, char const *argv[]) {
printf("Enter a radio of height :") ;
scanf("%f", &radio_h);
printf("\n");
// 建構
// 寤烘
Imgraw img = {0, 0, 0, NULL};
// 讀圖
// 璁€鍦<EFBFBD>
Imgraw_Read(&img, "./input/bw2x1.bmp");
// 寫圖
// 瀵湒
Imgraw_Writ(&img, "./output/bw2x1(output).bmp", radio_w, radio_h);
return 0;
}

BIN
try.exe

Binary file not shown.