0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

linux下BMP图片旋转

嵌入式技术 来源:嵌入式技术 作者:嵌入式技术 2022-08-16 11:27 次阅读

linux下BMP图片旋转

BMP是英文Bitmap(位图)的简写,它是Windows操作系统中的标准图像文件格式,能够被多种Windows应用程序所支持。随着Windows操作系统的流行与丰富的Windows应用程序的开发,BMP位图格式理所当然地被广泛应用。这种格式的特点是包含的图像信息较丰富,几乎不进行压缩,但由此导致了它与生俱来的缺点–占用磁盘空间过大。所以,目前BMP在单机上比较流行。

在使用图片时我们经常需要用到旋转,本示例主要完成对BMP图片的顺时针旋转90°和逆时针旋转90°。

  • 原始图片
  • 程序执行效果:
[xsw@xsw BMP_stady]$ gcc rivolve.c 
[xsw@xsw BMP_stady]$ ./a.out 
格式:./a.out 
[xsw@xsw BMP_stady]$ ./a.out new.bmp watermark.bmp 

--------------------顺时针旋转90°----------------------
	旋转后图片宽:314
	旋转后图片高:504

--------------------逆时针旋转90°----------------------
	旋转后图片宽:314
	旋转后图片高:504
[xsw@xsw BMP_stady]$ 
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70

顺时针旋转90°示例

/***********************顺时针旋转90°**************************
**
**形参:const char *new_bmp -- 顺时针90°后图片
**     const char *befor_bmp  --原始图片
**返回值:0 -- 成功,其他值 -- 失败
**************************************************************/
int BMP_ClockWise_Revolve90(const char *new_bmp,const char *befor_bmp)
{
    FILE *fp[2];
    fp[0]=fopen(befor_bmp,"rb");
    if(fp[0]==NULL)
    {
        printf("[%s line %d]文件打开失败",__FUNCTION__,__LINE__);
        return 1;
    }
    fp[1]=fopen(new_bmp,"w+b");
    if(fp[1]==NULL)
    {
        printf("[%s line %d]文件打开或创建失败",__FUNCTION__,__LINE__);
        return 2;
    }
    BMP_HEADER bmp_head;
    BMP_INFO bmp_info;
    fread(&bmp_head,sizeof(BMP_HEADER),1,fp[0]);//读取头数据
    if(bmp_head.bfType!=0x4d42)
    {
        printf("[%s line %d]图片格式错误\n",__FUNCTION__,__LINE__);
        fclose(fp[0]);
        fclose(fp[1]);
        return 3;
    }
    fwrite(&bmp_head,sizeof(BMP_HEADER),1,fp[1]);//头数据写入到新的文件中
    int w,h;//旋转90°宽和高需要互换
    fread(&bmp_info,sizeof(BMP_INFO),1,fp[0]);//读取位图数据
    h=bmp_info.biHeight;
    w=bmp_info.biWidth;
    bmp_info.biWidth=h;//旋转后图片宽度
    bmp_info.biHeight=w;//旋转后图片高度
    fwrite(&bmp_info,sizeof(BMP_INFO),1,fp[1]);//写入位图数据
    printf("\n--------------------顺时针旋转90°----------------------\n");
    printf("\t旋转后图片宽:%d\n",bmp_info.biWidth);
    printf("\t旋转后图片高:%d\n",bmp_info.biHeight);
    int befor_oneline_size=w*3;//之前图片一行的字节数
    while(befor_oneline_size%4)befor_oneline_size++;//按4字节对齐
    int new_oneline_size=bmp_info.biWidth*3;//旋转后图片一行字节数
    while(new_oneline_size%4)new_oneline_size++;//按4字节对齐
    int i,j;
    int offset_count=0;
    int rgb=0;
    for(i=w-1;i>=0;i--)
    {
        for(j=0;jbmp_info.biWidth*3)
        {
            fwrite(&rgb,new_oneline_size-bmp_info.biWidth*3,1,fp[1]);//补全为4的倍数
        }
    }
    fclose(fp[0]);
    fclose(fp[1]);
    return 0;
}
;j++)>

逆时针旋转90°示例

/***********************逆时针旋转90°**************************
**
**形参:const char *new_bmp -- 逆时针90°后图片
**     const char *befor_bmp  --原始图片
**返回值:0 -- 成功,其他值 -- 失败
**************************************************************/
int BMP_antiClockWise_Revolve90(const char *new_bmp,const char *befor_bmp)
{
    FILE *fp[2];
    fp[0]=fopen(befor_bmp,"rb");
    if(fp[0]==NULL)
    {
        printf("[%s line %d]文件打开失败",__FUNCTION__,__LINE__);
        return 1;
    }
    fp[1]=fopen(new_bmp,"w+b");
    if(fp[1]==NULL)
    {
        printf("[%s line %d]文件打开或创建失败",__FUNCTION__,__LINE__);
        return 2;
    }
    BMP_HEADER bmp_head;
    BMP_INFO bmp_info;
    fread(&bmp_head,sizeof(BMP_HEADER),1,fp[0]);//读取头数据
    if(bmp_head.bfType!=0x4d42)
    {
        printf("[%s line %d]图片格式错误\n",__FUNCTION__,__LINE__);
        fclose(fp[0]);
        fclose(fp[1]);
        return 3;
    }
    fwrite(&bmp_head,sizeof(BMP_HEADER),1,fp[1]);//头数据写入到新的文件中
    int w,h;//旋转90°宽和高需要互换
    fread(&bmp_info,sizeof(BMP_INFO),1,fp[0]);//读取位图数据
    h=bmp_info.biHeight;
    w=bmp_info.biWidth;
    bmp_info.biWidth=h;//旋转后图片宽度
    bmp_info.biHeight=w;//旋转后图片高度
    fwrite(&bmp_info,sizeof(BMP_INFO),1,fp[1]);//写入位图数据
    printf("\n--------------------逆时针旋转90°----------------------\n");
    printf("\t旋转后图片宽:%d\n",bmp_info.biWidth);
    printf("\t旋转后图片高:%d\n",bmp_info.biHeight); 
    int befor_oneline_size=w*3;//之前图片一行的字节数
    while(befor_oneline_size%4)befor_oneline_size++;//按4字节对齐
    int new_oneline_size=bmp_info.biWidth*3;//旋转后图片一行字节数
    while(new_oneline_size%4)new_oneline_size++;//按4字节对齐
    int i,j;
    int offset_count=0;
    int rgb=0;  
    int cnt=0;
    unsigned char buff[new_oneline_size];//存放新图片一行字节数
    for(i=0;i=0;j--)
        {
            //先读取最后一行的第一个像素点
            offset_count=bmp_head.bfOffBits+i*3+j*befor_oneline_size;
            fseek(fp[0],offset_count,SEEK_SET);
            fread(&rgb,3,1,fp[0]);//读取一个像素点数据
            buff[cnt++]=(rgb)&0xff;
            buff[cnt++]=(rgb>>8)&0xff;
            buff[cnt++]=(rgb>>16)&0xff;
        }
        fwrite(buff,cnt,1,fp[1]);//将一行颜色数据写入到新文件中
        if(cnt!=new_oneline_size)//补全为4的整数倍
        {
            rgb=0;
            fwrite(&rgb,new_oneline_size-cnt,1,fp[1]); 
        }
    }
    fclose(fp[0]);
    fclose(fp[1]);
    return 0;
}
;i++)>
  • BMP位图结构体
#pragma pack(1)  /* 必须在结构体定义之前使用,这是为了让结构体中各成员按1字节对齐*/
/*图片头*/
typedef struct BitMapFileHEADER
{
	unsigned short bfType;      //保存图片类型。 'BM'
	unsigned long  bfSize;      //图片文件的总大小,以字节为单位(3-6字节,低位在前)
	unsigned short bfReserved1;//位图文件保留字,必须为0(7-8字节)
	unsigned short bfReserved2;//位图文件保留字,必须为0(9-10字节) 
	unsigned long  bfOffBits;  //RGB数据偏移地址,位图数据的起始位置,以相对于位图(11-14字节,低位在前)//文件头的偏移量表示,以字节为单位
}BMP_HEADER;

/*图片信息*/
typedef struct BitMapFileInfo{
	unsigned long  biSize;      //本结构所占用字节数(15-18字节)
	unsigned long  biWidth;     //位图的宽度,以像素为单位(19-22字节)
	unsigned long  biHeight;    //位图的高度,以像素为单位(23-26字节)
	unsigned short biPlanes;    //目标设备的级别,必须为1(27-28字节)
	unsigned short biBitCount;   //每个像素所需的位数,必须是1(双色)(29-30字节),4(16色),8(256色)16(高彩色)或24(真彩色)之一
	unsigned long  biCompression;//位图压缩类型,必须是0(不压缩),(31-34字节)
//1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
	unsigned long  biSizeImage;  //位图的大小(其中包含了为了补齐行数是4的倍数而添加的空字节),以字节为单位(35-38字节)
	unsigned long  biXPelsPerMeter;//位图水平分辨率,每米像素数(39-42字节)
	unsigned long  biYPelsPerMeter;//位图垂直分辨率,每米像素数(43-46字节)
	unsigned long  biClrUsed;      //位图实际使用的颜色表中的颜色数(47-50字节)
	unsigned long  biClrImportant; //位图显示过程中重要的颜色数(51-54字节)
}BMP_INFO;

主函数

int main(int argc,char **argv)
{
    if(argc!=3)
    {
        printf("格式:./a.out \n");
        return 0;
    }
    int stat=0;
    char buff[20];
    stat=BMP_ClockWise_Revolve90(argv[1],argv[2]);//顺时针90°
    if(stat)
        printf("[%s line %d] err %d\n",__FUNCTION__,__LINE__,stat);
    else 
    {
        snprintf(buff,sizeof(buff),"eog %s",argv[1]);//字符串拼接
        system(buff);//创建进程
    }
    stat=BMP_antiClockWise_Revolve90(argv[1],argv[2]);//逆时针旋转90°
    if(stat)
        printf("[%s line %d] err %d\n",__FUNCTION__,__LINE__,stat);
    else 
    {
        snprintf(buff,sizeof(buff),"eog %s",argv[1]);//字符串拼接
        system(buff);//创建进程
    }

    return 0;
}

在对BMP图片进行90°旋转时需要注意的点:
  1.每一行的字节数,当行字节数不是4的倍数需要用0补齐
  2.旋转后的图片的宽=原图片的高;新图片的高=原图片的宽

注:以上示例均在32位redHat6.3 linux下实现,若是64位linux系统需要注意结构体大小。

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    10969

    浏览量

    206644
  • 操作系统
    +关注

    关注

    37

    文章

    6254

    浏览量

    121820
  • BMP
    BMP
    +关注

    关注

    0

    文章

    48

    浏览量

    16962
收藏 人收藏

    评论

    相关推荐

    第11章 BMP图片显示

    读取数据并显示,这种办法的好处就是不要大的RAM需求,每次读取一些数据显示一次,缺点就是显示速度比较的慢。 这里有一点必须的要说明一,官方支持的这个BMP图片的显示速度没有咱们平时用的在TFT上面开窗
    发表于 10-12 10:18

    移植SDL到JZ2440显示BMP图片

    /lib-lSDL3、拷贝SDL库,应用程序、bmp图片到文件系统拷贝方法不需要再细讲了吧,笔者习惯用NFS,笔者的内核已经烧到jz2440,只需拷贝应用程序和bmp图片到文件系统
    发表于 06-29 11:19

    BMP to pcb软件工具(将BMP图片转插入PCB文件)

    BMP to pcb 工具(将BMP图片转插入PCB文件的软件) 使用说明: 1.这个软件可以将一幅BMP图形转换为  PCB格式。2.
    发表于 04-10 15:50 744次下载

    BMP图片分析软件

    使用说明 本软件目前只支持8位、16位和24位的BMP图片,至于其他格式图片,暂不支持。在后面我将会实时进行软件升级,谢谢大家的支持!
    发表于 01-12 15:44 82次下载

    BMP图片文件详解

    BMP图片文件详解,很好的资料,快来学习吧
    发表于 02-18 14:16 0次下载

    LCD彩色图片转换工具BMP_to_H

    LCD彩色图片转换工具BMP_to_H
    发表于 12-28 10:16 11次下载

    基于STM32的BMP图片的解码系统

    基于STM32的BMP图片的解码系统
    发表于 09-25 11:12 12次下载
    基于STM32的<b class='flag-5'>BMP</b><b class='flag-5'>图片</b>的解码系统

    嵌入式linux操作framebuffer显示bmp图片

    编译后拷贝进开发板即可使用使用方法./fb_show_bmp test.bmp显示的图片由参数指定,上面指令中test.bmp为测试用的bmp
    发表于 11-01 17:06 10次下载
    嵌入式<b class='flag-5'>linux</b>操作framebuffer显示<b class='flag-5'>bmp</b><b class='flag-5'>图片</b>

    剖析BMP图片文件

    剖析BMP图片文件
    发表于 01-23 10:05 2次下载

    Linux应用开发-LCD显示BMP图片

    为了解BMP格式,这篇文章就采用Linux开发板作为实验平台,在LCD屏上读取BMP图片,完成绘制,不需要借助任何第三方库,全部由纯C语言代码一行一行敲出来,深入理解
    的头像 发表于 08-14 09:18 2292次阅读

    LinuxBMP图片截图

    BMP位图格式理所当然地被广泛应用。这种格式的特点是包含的图像信息较丰富,几乎不进行压缩,但由此导致了它与生俱来的缺点–占用磁盘空间过大。所以,目前BMP在单机上比较流行。
    的头像 发表于 08-18 17:09 887次阅读

    LinuxBMP图片缩放

    BMP位图格式理所当然地被广泛应用。这种格式的特点是包含的图像信息较丰富,几乎不进行压缩,但由此导致了它与生俱来的缺点–占用磁盘空间过大。所以,目前BMP在单机上比较流行。
    的头像 发表于 08-18 17:14 1473次阅读
    <b class='flag-5'>Linux</b>下<b class='flag-5'>BMP</b><b class='flag-5'>图片</b>缩放

    Linux开发_文件目录操作介绍、创建BMP图片

    介绍C语言文件编程,创建BMP图片BMP图片结构介绍,介绍目录接口编程,Makefile知识点。
    的头像 发表于 09-17 15:44 1159次阅读
    <b class='flag-5'>Linux</b>开发_文件目录操作介绍、创建<b class='flag-5'>BMP</b><b class='flag-5'>图片</b>

    Linux开发_介绍BMP图片上下翻转、添加水印

    介绍BMP图片上下翻转、添加水印、通过学习BMP图片结构学习文件编程。
    的头像 发表于 09-17 15:43 1341次阅读

    Linux开发_BMP图片编程(翻转、添加水印)

    接收BMP图片编程,完成BMP图片翻转、水印添加等知识点。
    的头像 发表于 09-17 15:33 1128次阅读
    <b class='flag-5'>Linux</b>开发_<b class='flag-5'>BMP</b><b class='flag-5'>图片</b>编程(翻转、添加水印)