利用C的BMP图像的读取、保存及旋转的实现
分类:
文章
•
2023-03-22 23:38:42
- <img src="https://img-blog.****.net/20150919152225406?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />// "bmp.h"
- #ifndef BMP_H_
- #define BMP_H_
-
- typedef unsigned char BYTE; //1个字节
- typedef unsigned short WORD; //2个字节
- typedef unsigned int DWORD; //4个字节(无符号)
- typedef long LONG; //4个字节
-
- #pragma pack(2) //设定为2字节对齐方式
- typedef struct
- {
- WORD bfType;
- DWORD bfSize;
- WORD bfReserved1;
- WORD bfReserved2;
- DWORD bfOffBits;
- }BITMAPFILEHEADER; //文件头
- #pragma pack(pop)
-
- typedef struct
- {
- DWORD biSize;
- LONG biWidth;
- LONG biHeight;
- WORD biPlanes;
- WORD biBitCount;
- DWORD biCompression;
- DWORD biSizeImage;
- LONG biXPelsPerMeter;
- LONG biYPelsPerMeter;
- DWORD biClrUsed;
- DWORD biClrImportant;
- }BITMAPINFOHEADER; //文件信息头
-
- typedef struct
- {
- BYTE rgbBlue;
- BYTE rgbGreen;
- BYTE rgbRed;
- BYTE rgbReserved;
- }RGBQUAD; //调色板结构
-
- typedef struct
- {
- unsigned char* buf;
- int width_x;
- int height_y;
- RGBQUAD* palette;
- int deepth;
- }Bmpbase;
-
- bool saveBmp(char*, unsigned char*, int, int, int, RGBQUAD*);
- Bmpbase readbmp(char*);
- Bmpbase imrotate(unsigned char*, int, int, int, RGBQUAD*,double);
-
- #endif
- </pre><pre name="code" class="cpp">
- // "readbmp.cpp"
- #include"bmp.h"
- #include<iostream>
- using namespace std;
-
- //unsigned char* pBmpBuf; //读入图像数据的指针
- //int bmpWidth; //图像的宽
- //int bmpHeight; //图像的高
- //RGBQUAD* pColorTable;
- //int biBitCount; //图像类型,每个像素的位数
-
- Bmpbase readbmp(char* bmpName)
- {
- Bmpbase bmp;
- //二进制读方式打开指定的图像文件
- FILE* fp = fopen(bmpName, "rb");
- if (fp == 0)
- exit;
-
- //跳过位图文件头结构BITMAPFILEHEADER
- fseek(fp,sizeof(BITMAPFILEHEADER), 0); //
- //定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中
- BITMAPINFOHEADER head;
- fread(&head, sizeof(BITMAPINFOHEADER), 1, fp);
-
- //获取图向宽、高、每个像素所占位数等信息
- bmp.width_x = head.biWidth;
- bmp.height_y = head.biHeight;
- bmp.deepth= head.biBitCount;
-
- //定义变量,计算图像每行像素所占字节数
- int lineByte = (bmp.width_x*bmp.deepth / 8 + 3) / 4 * 4;
- //灰度图有颜色表,且颜色表表项为256
- if (bmp.deepth == 8)
- {
- bmp.palette = new RGBQUAD[256];
- fread(bmp.palette, sizeof(RGBQUAD), 256, fp);
- }
- //申请位图数据所需的空间,读入位图数据进入内存
- bmp.buf = new unsigned char[lineByte*bmp.height_y];
-
- fread(bmp.buf, 1, lineByte*bmp.height_y, fp);
-
- fclose(fp);
- return bmp;
- }
- // "imrotate.cpp"
- #include"bmp.h"
- #include<cmath>
- #include<iostream>
- using namespace std;
-
-
- Bmpbase imrotate(unsigned char* imgbuf, int width, int height, int deep, RGBQUAD* CTable,double theta)
- {
- Bmpbase bmp1;
- theta = (theta / 180)*3.1415; //角度转化为弧度
-
-
- //定义四个顶点坐标
- int x1 = -width / 2, y1 = height / 2;
-
-
- int x2 = width / 2, y2 = height / 2;
-
-
- int x3= width / 2, y3 =-height / 2;
-
-
- int x4 = -width / 2, y4 = -height / 2;
-
- //旋转这四个顶点的坐标
- double new_x1 = cos(theta)*x1 + sin(theta)*y1;
- double new_y1 = -sin(theta)*x1 + cos(theta)*y1;
-
-
- double new_x2 = cos(theta)*x2+ sin(theta)*y2;
- double new_y2 =-sin(theta)*x2 + cos(theta)*y2;
-
-
- double new_x3 = cos(theta)*x3 + sin(theta)*y3;
- double new_y3 =-sin (theta)*x3+ cos(theta)*y3;
-
-
- double new_x4 = cos(theta)*x4 + sin(theta)*y4;
- double new_y4 = -sin(theta)*x4 +cos (theta)*y4;
-
-
- int new_width = fmax(abs(new_x1-new_x3)+0.5,abs(new_x2-new_x4)+0.5);
- bmp1.width_x = new_width; //新图像的宽度
- int new_height = fmax(abs(new_y1 - new_y3) + 0.5, abs(new_y2 - new_y4) + 0.5);
- bmp1.height_y = new_height; //新图像的高度
- int old_lineByte = (width*deep / 8 + 3) / 4 * 4;
- int lineByte = int((new_width*deep / 8 + 3) / 4) * 4;
- unsigned char* buf = new unsigned char[lineByte*new_height];
- for (int i = 0; i < lineByte*new_height; i++)
- *(buf + i) =0;
- int newX, newY,oldX,oldY,old_i,old_j;
- for (int i = 0; i < new_width; i++)
- {
- for (int j = 0; j < new_height;j++)
- {
- newX= i - new_width / 2;
- newY = j - new_height / 2;
- oldX = cos(theta)*newX - sin(theta)*newY;
- oldY = sin(theta)*newX + cos(theta)*newY;
- if (abs(oldX) <= width / 2 && abs(oldY) <= height / 2)
- {
- old_i = oldX + width / 2>0 ? (oldX + width / 2):0;
- old_j = oldY + height / 2>0 ? (oldY + height / 2):0;
- *(buf + j*lineByte + i) = *(imgbuf + old_j*old_lineByte + old_i);
- }
- }
- }
-
-
- bmp1.buf = buf;
- bmp1.deepth = deep;
- bmp1.palette = CTable;
- return bmp1;
- }
- // "saveBmp.cpp"
- #include"bmp.h"
- #include<iostream>
- using namespace std;
- /*
- char* bmpName 文件名字及路径
- unsigned char* imgBuf 待存盘的位图数据
- int width 以像素为单位待存盘位图的宽
- int height 以像素为单位待存盘位图的高
- int biBitCount 每个像素所占位数
- RGBQUAD* pColorTable 颜色表指针
- */
-
- bool saveBmp(char* bmpName, unsigned char* imgBuf, int width, int height, int biBitCount, RGBQUAD* pColorTable)
- {
- if (!imgBuf)
- return 0;
-
- //颜色表大小
- int colorTablesize = 0;
- if (biBitCount == 8)
- colorTablesize = 1024;
-
- //带存储图像每行字节数
- int lineByte = (width*biBitCount / 8 + 3) / 4 * 4;
-
- //以二进制写的方式打开文件
- FILE* fp = fopen(bmpName, "wb");
- if (fp == 0)
- return 0;
- //申请位图文件头结构变量,填写文件头信息
- BITMAPFILEHEADER fileHead;
- fileHead.bfType = 0x4D42; //bmp类型
- //bfSize是图像文件4个组成部分之和
- fileHead.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTablesize + lineByte*height;
- fileHead.bfReserved1 = 0;
- fileHead.bfReserved2 = 0;
-
- //bfOffBits是图像文件前3个部分所需空间之和
- fileHead.bfOffBits = 54 + colorTablesize;
-
- //写文件头进文件
- fwrite(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp);
-
- //申请位图文件信息头结构变量,填写文件信息头信息
- BITMAPINFOHEADER infoHead;
- infoHead.biSize = 40;
- infoHead.biWidth = width;
- infoHead.biHeight = height;
- infoHead.biPlanes = 1;
- infoHead.biBitCount = biBitCount;
- infoHead.biCompression = 0;
- infoHead.biSizeImage = lineByte*height;
- infoHead.biXPelsPerMeter = 0;
- infoHead.biYPelsPerMeter = 0;
- infoHead.biClrUsed = 0;
- infoHead.biClrImportant = 0;
- fwrite(&infoHead, sizeof(BITMAPINFOHEADER), 1, fp);
- if (biBitCount == 8)
- fwrite(pColorTable, sizeof(RGBQUAD), 256, fp);
-
-
- //写位图数据进文件
- fwrite(imgBuf, height*lineByte, 1, fp);
-
- fclose(fp);
- return 1;
-
- }
- // "bmp.cpp"
- #include<iostream>
- #include"bmp.h"
- using namespace std;
-
- void main()
- {
- Bmpbase bmp,bmp1;
- char* readPath = "hust.bmp";
- bmp=readbmp(readPath);
- //extern int bmpWidth;
- //extern int bmpHeight;
- //extern int biBitCount;
- //extern unsigned char* pBmpBuf;
- //extern RGBQUAD* pColorTable;
- printf("width=%d,height=%d,biBitCount=%d\n", bmp.width_x, bmp.height_y, bmp.deepth);
- bmp1 = imrotate(bmp.buf, bmp.width_x, bmp.height_y, bmp.deepth, bmp.palette,360);
- char* writePath = "hustcpy.bmp";
- saveBmp(writePath, bmp1.buf, bmp1.width_x, bmp1.height_y, bmp1.deepth, bmp1.palette);
-
- delete[]bmp.buf;
- delete[]bmp1.buf;
- if (bmp.deepth== 8)
- delete[]bmp.palette;
-
-
- }<img src="https://img-blog.****.net/20150919152351435?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /><img src="https://img-blog.****.net/20150919152249777?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />

