利用C的BMP图像的读取、保存及旋转的实现

  1. <img src="https://img-blog.csdn.net/20150919152225406?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />//                 "bmp.h"   
  2. #ifndef BMP_H_  
  3. #define BMP_H_  
  4.   
  5. typedef unsigned char BYTE;           //1个字节  
  6. typedef unsigned short WORD;       //2个字节  
  7. typedef unsigned int DWORD;        //4个字节(无符号)  
  8. typedef long LONG;                        //4个字节  
  9.   
  10. #pragma pack(2)                            //设定为2字节对齐方式  
  11. typedef struct  
  12. {  
  13.     WORD bfType;  
  14.     DWORD bfSize;  
  15.     WORD bfReserved1;  
  16.     WORD bfReserved2;  
  17.     DWORD bfOffBits;  
  18. }BITMAPFILEHEADER;                    //文件头  
  19. #pragma pack(pop)  
  20.   
  21. typedef struct  
  22. {  
  23.     DWORD biSize;  
  24.     LONG biWidth;  
  25.     LONG biHeight;  
  26.     WORD biPlanes;  
  27.     WORD biBitCount;  
  28.     DWORD biCompression;  
  29.     DWORD biSizeImage;  
  30.     LONG biXPelsPerMeter;  
  31.     LONG biYPelsPerMeter;  
  32.     DWORD biClrUsed;  
  33.     DWORD biClrImportant;  
  34. }BITMAPINFOHEADER;                  //文件信息头  
  35.   
  36. typedef struct  
  37. {  
  38.     BYTE rgbBlue;  
  39.     BYTE rgbGreen;  
  40.     BYTE rgbRed;  
  41.     BYTE rgbReserved;  
  42. }RGBQUAD;                                    //调色板结构  
  43.   
  44. typedef struct  
  45. {  
  46.     unsigned char* buf;  
  47.     int width_x;  
  48.     int height_y;  
  49.     RGBQUAD* palette;  
  50.     int deepth;  
  51. }Bmpbase;  
  52.   
  53. bool saveBmp(char*, unsigned char*, intintint, RGBQUAD*);  
  54. Bmpbase readbmp(char*);  
  55. Bmpbase imrotate(unsigned char*, intintint, RGBQUAD*,double);  
  56.   
  57. #endif  
[cpp]  view plain  copy
  1. </pre><pre name="code" class="cpp">  
[cpp]  view plain  copy
  1. //                       "readbmp.cpp"  
  2. #include"bmp.h"  
  3. #include<iostream>  
  4. using namespace std;  
  5.   
  6. //unsigned char* pBmpBuf;                        //读入图像数据的指针  
  7. //int bmpWidth;                                         //图像的宽  
  8. //int bmpHeight;                                        //图像的高  
  9. //RGBQUAD* pColorTable;  
  10. //int biBitCount;                                         //图像类型,每个像素的位数  
  11.   
  12. Bmpbase readbmp(char* bmpName)  
  13. {  
  14.     Bmpbase bmp;  
  15.     //二进制读方式打开指定的图像文件  
  16.     FILE* fp = fopen(bmpName, "rb");  
  17.     if (fp == 0)  
  18.         exit;  
  19.   
  20.     //跳过位图文件头结构BITMAPFILEHEADER  
  21.     fseek(fp,sizeof(BITMAPFILEHEADER), 0);   //  
  22.     //定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中  
  23.     BITMAPINFOHEADER head;  
  24.     fread(&head, sizeof(BITMAPINFOHEADER), 1, fp);  
  25.   
  26.     //获取图向宽、高、每个像素所占位数等信息  
  27.     bmp.width_x = head.biWidth;  
  28.     bmp.height_y = head.biHeight;  
  29.     bmp.deepth= head.biBitCount;  
  30.       
  31.     //定义变量,计算图像每行像素所占字节数  
  32.     int lineByte = (bmp.width_x*bmp.deepth / 8 + 3) / 4 * 4;  
  33.     //灰度图有颜色表,且颜色表表项为256  
  34.     if (bmp.deepth == 8)  
  35.     {  
  36.     bmp.palette = new RGBQUAD[256];  
  37.     fread(bmp.palette, sizeof(RGBQUAD), 256, fp);  
  38.     }  
  39.     //申请位图数据所需的空间,读入位图数据进入内存  
  40.     bmp.buf = new unsigned char[lineByte*bmp.height_y];  
  41.       
  42.     fread(bmp.buf, 1, lineByte*bmp.height_y, fp);  
  43.      
  44.     fclose(fp);  
  45.     return bmp;  
  46. }  


[cpp]  view plain  copy
  1. //                  "imrotate.cpp"  
  2. #include"bmp.h"  
  3. #include<cmath>  
  4. #include<iostream>  
  5. using namespace std;  
  6.   
  7.   
  8. Bmpbase imrotate(unsigned char* imgbuf, int width, int height, int deep, RGBQUAD* CTable,double theta)  
  9. {  
  10.     Bmpbase bmp1;  
  11.     theta = (theta / 180)*3.1415;                  //角度转化为弧度  
  12.   
  13.   
  14.     //定义四个顶点坐标  
  15.     int x1 = -width / 2, y1 = height / 2;  
  16.   
  17.   
  18.     int x2 = width / 2,  y2 = height / 2;  
  19.   
  20.   
  21.     int x3= width / 2,   y3 =-height / 2;  
  22.   
  23.   
  24.     int x4 = -width / 2, y4 = -height / 2;  
  25.       
  26.     //旋转这四个顶点的坐标  
  27.     double new_x1 = cos(theta)*x1 + sin(theta)*y1;   
  28.     double new_y1 = -sin(theta)*x1 + cos(theta)*y1;  
  29.   
  30.   
  31.     double new_x2 = cos(theta)*x2+ sin(theta)*y2;  
  32.     double new_y2 =-sin(theta)*x2 + cos(theta)*y2;  
  33.   
  34.   
  35.     double new_x3 = cos(theta)*x3 + sin(theta)*y3;  
  36.     double new_y3 =-sin (theta)*x3+ cos(theta)*y3;  
  37.   
  38.   
  39.     double new_x4 = cos(theta)*x4 + sin(theta)*y4;  
  40.     double new_y4 = -sin(theta)*x4 +cos (theta)*y4;  
  41.   
  42.   
  43.     int new_width = fmax(abs(new_x1-new_x3)+0.5,abs(new_x2-new_x4)+0.5);  
  44.     bmp1.width_x = new_width;                     //新图像的宽度  
  45.     int new_height = fmax(abs(new_y1 - new_y3) + 0.5, abs(new_y2 - new_y4) + 0.5);  
  46.     bmp1.height_y = new_height;                   //新图像的高度  
  47.     int old_lineByte = (width*deep / 8 + 3) / 4 * 4;  
  48.     int lineByte = int((new_width*deep / 8 + 3) / 4) * 4;  
  49.     unsigned char* buf = new unsigned char[lineByte*new_height];  
  50.     for (int i = 0; i < lineByte*new_height; i++)  
  51.         *(buf + i) =0;  
  52.     int newX, newY,oldX,oldY,old_i,old_j;  
  53.     for (int i = 0; i < new_width; i++)  
  54.     {  
  55.         for (int j = 0; j < new_height;j++)  
  56.         {  
  57.             newX= i - new_width / 2;  
  58.             newY = j - new_height / 2;  
  59.             oldX = cos(theta)*newX - sin(theta)*newY;  
  60.             oldY = sin(theta)*newX + cos(theta)*newY;  
  61.             if (abs(oldX) <= width / 2 && abs(oldY) <= height / 2)  
  62.             {  
  63.                 old_i = oldX + width / 2>0 ?  (oldX + width / 2):0;  
  64.                 old_j = oldY + height / 2>0 ? (oldY + height / 2):0;  
  65.                 *(buf + j*lineByte + i) = *(imgbuf + old_j*old_lineByte + old_i);  
  66.             }     
  67.         }  
  68.     }  
  69.   
  70.   
  71.     bmp1.buf = buf;  
  72.     bmp1.deepth = deep;  
  73.     bmp1.palette = CTable;  
  74.     return bmp1;  
  75. }  

[cpp]  view plain  copy
  1. //              "saveBmp.cpp"  
  2. #include"bmp.h"  
  3. #include<iostream>  
  4. using namespace std;  
  5. /* 
  6. char* bmpName                            文件名字及路径 
  7. unsigned char* imgBuf                  待存盘的位图数据 
  8. int width                                        以像素为单位待存盘位图的宽 
  9. int height                                       以像素为单位待存盘位图的高 
  10. int biBitCount                                每个像素所占位数 
  11. RGBQUAD* pColorTable                 颜色表指针 
  12. */  
  13.   
  14. bool saveBmp(char* bmpName, unsigned char* imgBuf, int width, int height, int biBitCount, RGBQUAD* pColorTable)  
  15. {  
  16.     if (!imgBuf)  
  17.         return 0;  
  18.   
  19.     //颜色表大小  
  20.     int colorTablesize = 0;  
  21.     if (biBitCount == 8)  
  22.         colorTablesize = 1024;  
  23.   
  24.     //带存储图像每行字节数  
  25.     int lineByte = (width*biBitCount / 8 + 3) / 4 * 4;  
  26.   
  27.     //以二进制写的方式打开文件  
  28.     FILE* fp = fopen(bmpName, "wb");  
  29.     if (fp == 0)  
  30.         return 0;  
  31.     //申请位图文件头结构变量,填写文件头信息  
  32.     BITMAPFILEHEADER fileHead;  
  33.     fileHead.bfType = 0x4D42;      //bmp类型  
  34.     //bfSize是图像文件4个组成部分之和  
  35.     fileHead.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTablesize + lineByte*height;  
  36.     fileHead.bfReserved1 = 0;  
  37.     fileHead.bfReserved2 = 0;  
  38.   
  39.     //bfOffBits是图像文件前3个部分所需空间之和  
  40.     fileHead.bfOffBits = 54 + colorTablesize;  
  41.   
  42.     //写文件头进文件  
  43.     fwrite(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp);  
  44.   
  45.     //申请位图文件信息头结构变量,填写文件信息头信息  
  46.     BITMAPINFOHEADER infoHead;  
  47.     infoHead.biSize = 40;  
  48.     infoHead.biWidth = width;  
  49.     infoHead.biHeight = height;  
  50.     infoHead.biPlanes = 1;  
  51.     infoHead.biBitCount = biBitCount;  
  52.     infoHead.biCompression = 0;  
  53.     infoHead.biSizeImage = lineByte*height;  
  54.     infoHead.biXPelsPerMeter = 0;  
  55.     infoHead.biYPelsPerMeter = 0;  
  56.     infoHead.biClrUsed = 0;  
  57.     infoHead.biClrImportant = 0;  
  58.     fwrite(&infoHead, sizeof(BITMAPINFOHEADER), 1, fp);  
  59.     if (biBitCount == 8)  
  60.         fwrite(pColorTable, sizeof(RGBQUAD), 256, fp);  
  61.       
  62.   
  63.     //写位图数据进文件  
  64.     fwrite(imgBuf, height*lineByte, 1, fp);  
  65.       
  66.     fclose(fp);  
  67.     return 1;  
  68.   
  69. }  

[cpp]  view plain  copy
  1. //                       "bmp.cpp"  
  2. #include<iostream>  
  3. #include"bmp.h"  
  4. using namespace std;  
  5.   
  6. void main()  
  7. {  
  8. Bmpbase bmp,bmp1;  
  9. char* readPath = "hust.bmp";  
  10. bmp=readbmp(readPath);  
  11. //extern int bmpWidth;  
  12. //extern int bmpHeight;  
  13. //extern int biBitCount;  
  14. //extern unsigned char* pBmpBuf;  
  15. //extern RGBQUAD* pColorTable;  
  16. printf("width=%d,height=%d,biBitCount=%d\n", bmp.width_x, bmp.height_y, bmp.deepth);  
  17. bmp1 = imrotate(bmp.buf, bmp.width_x, bmp.height_y, bmp.deepth, bmp.palette,360);  
  18. char* writePath = "hustcpy.bmp";  
  19. saveBmp(writePath, bmp1.buf, bmp1.width_x, bmp1.height_y, bmp1.deepth, bmp1.palette);  
  20.   
  21. delete[]bmp.buf;  
  22. delete[]bmp1.buf;  
  23. if (bmp.deepth== 8)  
  24. delete[]bmp.palette;  
  25.   
  26.   
  27. }<img src="https://img-blog.csdn.net/20150919152351435?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /><img src="https://img-blog.csdn.net/20150919152249777?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />  


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值