运算符和表达式
运算符和表达式
1.表达式
C语言中,表达某一个问题的式子,合法的表达式都会有一个值
表达式一般是由运算符连接的式子
2.运算符
用来进行某一种运算的符号
主要研究运算符的以下一些属性:
带几个操作数
几目运算符?该运算符需要带几个操作数
单目运算符,该运算符只需要带一个操作数 ~,++,–
双目运算符,该运算符需要带两个操作数 +,-,*,/,%…
三目运算符,该运算符需要带三个操作数 ?:
结合性:计算方向的问题,从左至右,从右至左(=)
计算机计算操作数的值,不可能同时计算,先计算哪一个操作数
*优先级:在含有多个运算符的表达式中,先计算哪一个运算符的问题
单目运算符(~,++,--) > 算术运算符(+-*/) > 关系运算符(>,<,==) > 逻辑运算符(||,&&) > 条件运算符(?:) >赋值运算符 > 逗号运算符(,)
写代码的时候,搞不清优先级,就打括号,
2.1 算术运算符:进行算术运算的运算符
单目运算符:++ --
双目运算符: * / % + - 结合性是从左至右的
例子:
3+5 ====> 8
5/4 ====> 1(整数进行算术运算的结果一定是整数)
5.0/4 ====> 1.25
double(表达式);把表达式的值转换为double类型
(类型)表达式; 把表达式转换为指定的类型
double(3/2) ====> 1.0
(double)3/2 ====> 1.5
如何使用C语言的表达式来描述数学表达式a/b呢?
a*1.0/b
(double)a/b
%:取余,要求两个操作数都必须是整数
5%4 ====>1
4%5 ====> 4
%,/右边的操作数都不能为0
a+b 与 b+a 在C语言中含义是不一样的!
int i=5,j=6;
(i++) + (i+j) ---> 17
(i+j) + (i++) ---> 16
++:自增运算符
--:自减运算符
只要一个操作数,能作为左值(是一个可写的地址)
int x = 1;
x++; ===>x = x+1,后++,先取值,再+1
++x; ===>x = x+1,前++,先+1,在取值
int a,x = 1;
a = x++; //a为1;x为2
int a,x = 1;
a = ++x; //a为2;x为2
int a,x = 1;
a = x--; //a为1;x为0
int a,x = 1;
a = --x; //a为0;x为0
真值表:
表达式 表达式的值 完成表达式后i的值
i++ i i+1
++i i+1 i+1
i-- i i-1
--i i-1 i-1
5++; //ERR
int a,b;
(a+b)++; //ERROR,(a+b)是一个值,
int i;
(i++)++; //ERROR
int i = 5;
a = i++; //把表达式i++的值赋值给a,i++这个表达式的值就是i,a为5
a = ++i; //把表达式++i的值赋值给a,++i这个表达式的值就是i+1,a为6
用算计运算符连接的式子,是算术表达式
算术表达式的值,就是计算之后的结果
int i = 100;
int sum = 0;
while(i–) //当括号内数据为真(非0),就执行循环体
{
sum = sum+i;
}
sum:4950
i:-1
int i = 100;
int sum = 0;
while(–i) //当括号内数据为真(非0),就执行循环体
{
sum = sum+i;
}
sum:4950
i:0
2.2 关系运算符:用来判断两个对象的大小关系
< <= > >= == !=
双目运算符,结合性都是从左至右
关系表示式就是使用关系运算符连接起来的式子
关系表示式的值,“关系成立(1)”,“关系不成立(0)”
如:
5>4 ----> 1
3<=4 ----> 1
int i = 0;
int sum = 0;
while(i++ <= 100) //当括号内数据为真(非0),就执行循环体
{
sum = sum+i;
}
sum:5151
i:102
5>4>3 合法吗? 是一个合法的表达式
值:0
用表达式(5>4)的值与3进行比较
5>4>3 ---->(5>4) > 3
1>3 ===>0
在C语言中,5>4>3这个表达式和数学上的意思是不一样的
C语言中如何表达数学上的"5>4>3"
5>4 并且 4>3
在C语言中,如何描述“并且”这个意思呢??
2.3 逻辑运算符:用来表示逻辑关系的运算符
! 逻辑非 单目运算符 "取反"
!真 -----> 假
!假 -----> 真
!0 ----> 1
!100 ----> 0
&& 逻辑与,双目运算符,结合性从左至右 "并且"
必须两边都为真,结果才为真
|| 逻辑或,双目运算符,结合性从左至右 "或者"
任意一边为真,结果就为真
逻辑表达式就是使用逻辑运算符连接的式子
逻辑表达式的值: 逻辑真(1,非0) 逻辑假(0)
例子:
a = 4, b= 5;
a&&b ----> 1
a||b ---->1
4&&0||2 ----> 1
优先级:
! > && > ||
5>3&&8<4-!0 ---->0
练习:
int a,b,c,d,m,n;
a = 1;
b = 2;
c = 3;
d = 4;
m = n = 1;
(m=a>b)&&(n=c>d)
m:0
n:1
C语言中的"惰性运算"
当逻辑表达式中结果已经确定的时候,后面的运算将不会进行了
(1).a && b && c
只有a为真的时候,才需要判断b的值
只有a和b都为真的时候,才需要判断c的值
(2).a || b || c
只要a为真,就不需要判断b和c的值了
只有a为假的时候,才需要判断b的值
只有a和b都为假的时候,才需要判断c的值
如果事先指定表达式的值了m那么后面的运算符(或者表达式)就不需要被执行了,这就是C语言的惰性运算
练习:
使用逻辑表达式来判断年份y是否为闰年
(1).能被4整除,但是不能被100整除
(2).能被4整除,又能被400整除
满足上面的条件之一,则为闰年
int year;
if(表达式) //表达式成立则执行if下面的语句
{
printf(是闰年!!!!);
}
(1) || (2)
(1) 能被4整除 && 不能被100整除
(year%4 == 0)&&(year%100 != 0)
(2) 能被4整除 && 被400整除
(year%4 == 0)&&(year%400 == 0)
====>
(year%400 == 0)
((year%4 == 0)&&(year%100 != 0)) || (year%400 == 0)
if( ((year%4 == 0)&&(year%100 != 0)) || (year%400 == 0) )
{
printf("YES\n");
}
不为闰年?
if( !((year%4 == 0)&&(year%100 != 0)) || (year%400 == 0) )
{
printf(“NO\n”);
}
2.4 位运算符 重点!!!
位运算符是指按照bit位来进行的运算(没有借位和进位),位运算有如下一些:
& 按位与
| 按位或
^ 按位异或
~ 按位取反
<< 按位左移
>> 按位右移
位运算一般只针对于整型数据
除了~是单目运算符外,其他的都是双目运算符,结合性都是从左至右
所有位运算都需要把操作数变成bit位的序列,然后在进行计算
~ 按位取反
0 ----> 1
1 ----> 0
int a = ~3;
printf("%d\n",a); // -4
printf("%u\n",a); // 2^32 - 4
~3:
00000000 00000000 00000000 00000011 (3)
11111111 11111111 11111111 11111100
%d:
11111111 11111111 11111111 11111100 是一个负数
计算原码的绝对值
11111111 11111111 11111111 11111011 -1
00000000 00000000 00000000 00000100 (4)
%u:
11111111 11111111 11111111 11111100
都是数值位
int a = ~(-3);
printf("%d\n",a); // 2
printf("%u\n",a); // 2
00000000 00000000 00000000 00000011 (3)
11111111 11111111 11111111 11111100 (取反)
11111111 11111111 11111111 11111101 (-3在内存中的存放方式)
~(-3)
00000000 00000000 00000000 00000010
& 按位与 双目运算符
真值表
a b a&b
1 1 1
1 0 0
0 1 0
0 0 0
& 如果两个bit位操作数都为1,结果才为1,否则为0‘’
3&5 == ?
0000 0011 (3)
& 0000 0101 (5)
0000 0001 (1)
清零:置为0
置位:设置为1
八位:从右至左,第0个bit~第7个bit
假如有一个8位寄存器a,需要把a的第5个bit位清0,其他位不变怎么操作?
a = a & 0xdf;
=====>
a = a & ~(1<<5);
结论:
一个bit位与0进行“按位与”操作,结果为0
x & 0 -----> 0
一个bit位与1进行“按位与”操作,结果不变
x & 1 -----> x
| 按位或 双目运算符
真值表
a b a|b
1 1 1
1 0 1
0 1 1
0 0 0
| 如果两个bit位操作数都为0,结果才为0,否则为1
3|5 == ?
0000 0011 (3)
| 0000 0101 (5)
0000 0111 (7)
假如有一个8位寄存器a,需要把a的第5个bit位置位,其他位不变怎么操作?
a = a | 0x20;
a = a | (1<<5);
结论:
一个bit位与0进行“按位或”操作,结果不变
x | 0 -----> 0
一个bit位与1进行“按位或”操作,结果置位
x & 1 -----> 1
^ 按位异或 双目运算符
真值表
a b a^b
1 1 0
1 0 1
0 1 1
0 0 0
^ 如果两个bit位操作数相同为0,不同为1
3^5 == ?
0000 0011 (3)
^ 0000 0101 (5)
0000 0110 (6)
假如有一个8位寄存器a,需要把a的第5个bit位保留,其他位取反怎么操作?
a = a ^ 0xdf;
a = a ^ ~(1<<5);
结论:
一个bit位与0进行“按位异或”操作,结果不变
x ^ 0 -----> 0
一个bit位与1进行“按位异或”操作,结果取反位
x ^ 1 -----> ~x
练习:
交换两个整数a与b的值,不使用临时变量。
a = 3,b = 5;
a = a+b; //a = 8,b = 5;
b = a-b; //a = 8,b = 3;
a = a-b; //a = 5,b = 3;
a = a^b;
b = b^a;
a = a^b;
一个数异或同一个数两次,结果保持不变
位运算只和当前位有关,没有借位和进位
a b a=a^b b=b^a a=a^b
1 1 0 1 1
1 0 1 1 0
0 1 1 0 1
0 0 0 0 0
<< 按位左移 双目运算符,按bit位整体向左边移动
a << n 把a按bit位整体向左边移动n位
高位左移后舍弃,低位补0
如果舍弃的高位全部是0,那么左移n位,就标识原值乘以2的n次方
如:
3<<2
0000 0011 <<2
000000 1100 ----> 0000 1100 (12)
>> 按位右移 双目运算符,按bit位整体向右边移动
a>>n 把a按bit位整体向右边移动n位
低位右移后直接舍弃,高位补什么????
对于有符号数,高位补符号位
对于无符号数,高位补0
“逻辑移位” 补0
“算术移位” 补符号位
int a = -1;
a = a >> 31;
a:-1
00000000 00000000 00000000 00000001 (1)
11111111 11111111 11111111 11111110
11111111 11111111 11111111 11111111 (-1) >>31
11111111 11111111 11111111 11111111
------------------------------------------------
unsisned int a = -1;
a = a >> 31;
a:1
00000000 00000000 00000000 00000001 (1)
11111111 11111111 11111111 11111110
11111111 11111111 11111111 11111111 赋值给a
11111111 11111111 11111111 11111111 a >> 31
a是一个无符号数,补0
00000000 00000000 00000000 00000001
2.5 赋值运算符(=)
双目运算符,从右至左,先计算右边的操作数,优先级排倒数第二,仅比逗号运算符高
赋值运算符的左边(左操作数)必须是一个“可写的地址(左值)”
int a;
a = 5+3;
5 = 5;//ERROR
2+3=5;//ERROR
i++ = 6; //ERROR
赋值表达式:由赋值运算符连接起来的式子,叫做赋值表达式
赋值表达式的值就是赋值后左边变量的那一个值。
(为什么我们C语言支持连等号)
a = b = 1;
====>
a = (b = 1);
b = 1,这个表达式的值就是1
(b=a)=6; //ERROR
int a = 0;
if(a=1) //如果 if后面的表达式为真,就会执行if后面的语句
{
printf(“hehe\n”);
}else //否则
{
printf(“haha\n”);
}
选择:
A.不知道 B.编译错误 C.hehe D.haha E.以上都不对
C,a=1是一个合法的表达式,合法的表达式都有一个值,
可以使用复合的赋值运算符:赋值运算符可以和算术运算符,位运算符组成复合的赋值运算符
+= -= *= %= /=
<<= >>= |= &= ^= ....
如:
a += b; ====>a = a+b;
a += 5+6 =====> a=a+(5+6);
2.6 条件运算符
?: 三目运算符
条件运算符具有右结合性
基本形式:
expression?a:b
如果expression为真(非0),则整个表达式的值为a
如果expression为假(0),则整个表达式的值为b
a = 5>4?4:3; a:4
2.7 逗号运算符
双目运算符,优先级是最低的,结合性从左至右
表达式1,表达式2
逗号表达式的求值顺序,先计算表达式1的值,然后再计算表达式2的值
整个逗号表达式的值是表达式2的值
int a=5,b=6;
a = (a=6,a+b);
a=12
逗号表达式扩展
表达式1,表达式2,表达式3.....表达式n
求值顺序,先求表达式1的值,再求表达式2的值....求表达式n的值,
整个表达式的值就是表达式n的值
2.8 指针运算符(*,&) 指针的时候再讲
2.9 求字节运算符(sizeof)
sizeof(表达式)
计算表达式的类型占用的内存大小,不管对象存不存在,只有后面的类型正确就可以了
sizeof计算类型占用的内存大小。
sizeof(int) == 4
sizeof(float) == 4
sizeof(1) == 4
sizeof(1.0) == 8
sizeof(1.0f) == 4
sizeof(1.0l) == 16
sizeof('A') == 4 C语言中,字符其实是使用整数实现的
sizeof(char) == 1
int a = 1;
sizeof(a+1.0) == 8 数据会自动的往高精度转换
2.10 分量运算符(.,->) 结构体的时候讲
2.11 下标运算符([]) 数组的时候讲
2.12 函数调用运算符 函数的时候讲
2.13 强制类型转换
(类型)值;
把对应的值转换为指定的类型
float f = 3.6;
(int)f+3.5 = 6.5
(int)(f+3.5) = 7
BMP图像文件解析与显示
bmp图像文件它是一种简单也是常见的图像数据存储格式
BMP是将图像的数据不经过任何压缩处理就直接存储在文件中的一种存储格式
即文件中的数据就是图像每个像素点的颜色值
BMP图片文件的数据存储格式如下图所示:
BITMAP文件头:记录文件信息
BMP是一种二进制文件,所谓的二进制文件是一种用来给计算机看的文件,其文件内容是以二进制数的ASCII形式存储在文件中,并且是在特定文字存储特定长度的数据来表示特定的含义
比如:在BMP文件的0X02位置,以小端模式存储了四个字节数据,表示文件的大小
虽然打开二进制文件直接看我们看不懂,但我们应当可以写一个程序来解析文件中的数据
用到的函数:open read close lseek
NAME
lseek - reposition read/write file offset
SYNOPSIS
#include <sys/types.h>
#include <unistd.h>
lseek用来控制文件中的文件偏移量(光标)的位置
off_t lseek(int fd, off_t offset, int whence);
@fd:文件描述符,指定要操作的文件
@offset:指定偏移量,即将"光标"移动多少个字节
正数 表示将"光标"向后移动
负数 表示将"光标"向前移动
0 表示不动
@whence 整数,表示将"光标"从那个地方开始移动
SEEK_SET:从文件头开始移动
SEEK_END:从文件末尾开始移动
SEKK_CUR:从"光标"当前所在位置开始移动
返回值
成功返回光标距离文件头从距离,单位 字节
失败返回-1,并且errno被设置
解析二进制文件的步骤:
1 打开二进制文件
2 移动光标到我们需要的数据所在的位置
3 读取我们需要的数据内容
4 按照数据格式对数据进行解析
end (如果不再解析别的数据),关闭文件
eg:解析BMP图片中记录的位图数据的宽度
//读取位图数据宽度
lseek(bmpfd,0x12,SEEK_SET);//光标移动到0X12的位置
read(bmpfd,ch,4);
width = ch[0]&0xff |(ch[1]&0xff)<<8 |(ch[2]&0xff)<<16 |(ch[3]&0xff)<<24;
printf("BMP width:%d\n",width );
任务:
编写bmp.c和bmp.h的文件,用于解析bmp文件,并且尝试结合lcd.c和lcd.h将解析到的像素数组的颜色值显示到屏幕对应的位置
注意
1 bmp文件需要解析的内容有:魔数(用来判断是不是bmp文件)、像素数组的起始位置、位图宽度、高度、色深(一个像素点在像素数组中对应几个字节)
2 如果宽度和高度都是正数,则我们从像素数组中解析出来的第一个像素点是左下角的第一个点的颜色值
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
int main (void)
{
int bmpfd=0;
ssize_t rsize = 0;
int file_size = 0;
int width = 0;
unsigned char ch[10] = {0};
int x,y;
//打开bmp图片
bmpfd = open("./../pic/2.bmp",O_RDONLY);
if (-1 == bmpfd)
{
perror("open bmp error");
return -1;
}
//读取bmp图片的前两个字节=》bmp文件魔数
rsize = read(bmpfd,ch,2);
if (-1 == rsize)
{
perror("read bmp error");
close(bmpfd);
return -1;
}
printf("BMP: %c %c\n",ch[0] ,ch[1]);
//读取bmo文件的大小
rsize = read(bmpfd,ch,4);
if (-1 == rsize)
{
perror("read bmp error");
close(bmpfd);
return -1;
}
printf("BMP: %x %x %x %x\n",ch[0] ,ch[1],ch[2],ch[3]);
file_size = ch[0]&0xff |(ch[1]&0xff)<<8 |(ch[2]&0xff)<<16 |(ch[3]&0xff)<<24;
//&0xff其实是避免ch有符号,运算时只取数据的低八位,避免短型和长型运算时,短型数据高位补位的干扰
printf("BMP file sizd %d\n", file_size);
//读取位图数据宽度
lseek(bmpfd,0x12,SEEK_SET);//光标移动到0X12的位置
read(bmpfd,ch,4);
width = ch[0]&0xff |(ch[1]&0xff)<<8 |(ch[2]&0xff)<<16 |(ch[3]&0xff)<<24;
printf("BMP width:%d\n",width );
//......
//像素数组的解析
unsigned char *data = (unsigned char*)malloc(width*hight*pix_bit/8);
//申请一个数组空间用来保存从图片中读取到的像素数组的数据
int color = 0;//解析得到的颜色
unsigned char a,r,g,b;//用来临时保存从数组中获取到的颜色分量
int i = 0;//用来计数
lseek(bmpfd,pix_offset,SEEK_SET);//pix_offset是解析0x0a处的四个字节得到的地址
read(bmpfd,data,width*hight*pix_bit/8);//读取整个像素数组的颜色数据,保存到data指向的数组
//解析每一个像素点的颜色值
for ( y = 0; y < hight; y++)
{
for ( x = 0; x < width; x++)
{
b = data[i++];
g = data[i++];
r = data[i++];
a =((pix_bit == 32)?data[i++]:0);
color = (a&0xff)<<24|(r&0xff)<<16|(g&0xff)<<8|b&0xff
}
}
close(bmpfd);
}
width = ch[0]&0xff |(ch[1]&0xff)<<8 |(ch[2]&0xff)<<16 |(ch[3]&0xff)<<24;
ch[0]=0x11 ch[1]=0x02 ch[2]=0x03 ch[3]=0x04
widht = 0x 00 00 00 00
ch[0]&0xff 0x 00 00 00 11
|(ch[1]&0xff)<<8 0x 00 00 02 00
|(ch[2]&0xff)<<16 0x 00 03 00 00
|(ch[3]&0xff)<<24 0x 04 00 00 00
widht = 0x 04 03 02 11
案例1:在gec6818开发板上显示bmp图片
bmp.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <unistd.h>
#include <sys/types.h>
#include <unistd.h>
//off_t lseek(int fd, off_t offset, int whence);
//ssize_t read(int fd, void *buf, size_t count);
//ssize_t write(int fd, const void *buf, size_t count);
//int open(const char *pathname, int flags);
int main()
{
//1.打开屏幕
int fd=0; //接受open的返回值
fd=open("/dev/fb0", O_RDWR);
if(fd==-1) //做错误判断
{
perror("open fb0 fail");
}
//打开图片
int bmp_fd=0; //接受open的返回值
bmp_fd=open("./func.bmp", O_RDWR);//修改图片路径
if(bmp_fd==-1) //做错误判断
{
perror("open func.bmp fail");
}
//2.偏移54字节
lseek(bmp_fd,54,SEEK_SET);
//3.读取像素数据 800*480
unsigned char bmp[800*480*3]={0};
read(bmp_fd,bmp,sizeof(bmp));
//4.数据处理
/*
bmp[0]--B
bmp[1]--G
bmp[2]--R
bmp[3]--B
....
lcd[0]=bmp[0] | bmp[1]<<8 | bmp[2]<<16;
lcd[1]=bmp[3] | bmp[4]<<8 | bmp[5]<<16;
lcd[2]=bmp[6] | bmp[7]<<8 | bmp[8]<<16;
*/
unsigned int temp[800*480]={0};
unsigned int lcd[800*480]={0};
int i=0;
int j=0;
for(i=0;i<800*480;i++)
{
temp[i]=bmp[3*i] | bmp[3*i+1]<<8 | bmp[3*i+2]<<16;
}
for(i=0;i<480;i++)
{
for(j=0;j<800;j++)
{
lcd[(480-1-i)*800+j]=temp[i*800+j];
}
}
//5.写入屏幕
int w_ret=0;
w_ret=write(fd, lcd, sizeof(lcd));
if(w_ret==-1)//做错误判断
{
perror("write fail");
}
//6.关闭文件
close(bmp_fd);
close(fd);
}
案例2:在gec6818开发板上显示电子相册
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <unistd.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/mman.h>
#include <linux/input.h>
//void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
//off_t lseek(int fd, off_t offset, int whence);
//ssize_t read(int fd, void *buf, size_t count);
//ssize_t write(int fd, const void *buf, size_t count);
//int open(const char *pathname, int flags);
//函数声明
int show_bmp(const char *bmpname);
int show_anybmp(const char *bmpname);
int show_anywherebmp(int x0,int y0,const char *bmpname);
int get_xy(int *x,int *y);
int main()
{
int x=-1;
int y=-1;
int tmp=0;
char photo[][30]={"./1.bmp","./2.bmp","./3.bmp"};
//1.显示主界面
show_anybmp("./func.bmp"); //规则界面
while(1)
{
//2.获取坐标
get_xy(&x,&y);
if(x>=400) //下一张
{
tmp=(tmp+1)%3;
show_bmp(photo[tmp]);
}
else if(x<400) //上一张
{
tmp=tmp-1;
if(tmp==-1){
tmp=2;
}
show_bmp(photo[tmp]);
}
//用完坐标得清零 坐标
x=-1;
y=-1;
}
}
//函数实现
//显示800*480的图片
int show_bmp(const char *bmpname)
{
//1.打开屏幕
int fd=0; //接受open的返回值
fd=open("/dev/fb0", O_RDWR);
if(fd==-1) //做错误判断
{
perror("open fb0 fail");
}
//建立屏幕映射
unsigned int* lcd = mmap(NULL, 800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
//打开图片
int bmp_fd=0; //接受open的返回值
bmp_fd=open(bmpname, O_RDWR);
if(bmp_fd==-1) //做错误判断
{
perror("open func.bmp fail");
}
//2.偏移54字节
lseek(bmp_fd,54,SEEK_SET);
//3.读取像素数据 800*480
unsigned char bmp[800*480*3]={0};
read(bmp_fd,bmp,sizeof(bmp));
//4.数据处理
/*
bmp[0]--B
bmp[1]--G
bmp[2]--R
bmp[3]--B
....
lcd[0]=bmp[0] | bmp[1]<<8 | bmp[2]<<16;
lcd[1]=bmp[3] | bmp[4]<<8 | bmp[5]<<16;
lcd[2]=bmp[6] | bmp[7]<<8 | bmp[8]<<16;
*/
unsigned int temp[800*480]={0};
int i=0;
int j=0;
for(i=0;i<800*480;i++)
{
temp[i]=bmp[3*i] | bmp[3*i+1]<<8 | bmp[3*i+2]<<16;
}
//解决上下颠倒 把一维数组 二维化思考
for(i=0;i<480;i++)
{
for(j=0;j<800;j++)
{
lcd[(480-1-i)*800+j]=temp[i*800+j];
}
}
//解除映射
munmap(lcd,800*480*4);
//6.关闭文件
close(bmp_fd);
close(fd);
}
//显示任意大小图片
int show_anybmp(const char *bmpname)
{
//1.打开屏幕
int fd=0; //接受open的返回值
fd=open("/dev/fb0", O_RDWR);
if(fd==-1) //做错误判断
{
perror("open fb0 fail");
}
//建立屏幕映射
unsigned int* lcd = mmap(NULL, 800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
//打开图片
int bmp_fd=0; //接受open的返回值
bmp_fd=open(bmpname, O_RDWR);
if(bmp_fd==-1) //做错误判断
{
perror("open func.bmp fail");
}
//2.偏移54字节
//先提取到宽
lseek(bmp_fd,18,SEEK_SET);
int w=0;
read(bmp_fd,&w,4);
//printf("w=%d\n",w);//打印宽度信息
//再提取高
lseek(bmp_fd,22,SEEK_SET);
int h=0;
read(bmp_fd,&h,4);
//printf("h=%d\n",h);//打印宽度信息
lseek(bmp_fd,54,SEEK_SET);
//3.读取像素数据 800*480
unsigned char bmp[w*h*3];
read(bmp_fd,bmp,sizeof(bmp));
//4.数据处理
/*
bmp[0]--B
bmp[1]--G
bmp[2]--R
bmp[3]--B
....
lcd[0]=bmp[0] | bmp[1]<<8 | bmp[2]<<16;
lcd[1]=bmp[3] | bmp[4]<<8 | bmp[5]<<16;
lcd[2]=bmp[6] | bmp[7]<<8 | bmp[8]<<16;
*/
unsigned int temp[800*480]={0};
int i=0;
int j=0;
for(i=0;i<w*h;i++)
{
temp[i]=bmp[3*i] | bmp[3*i+1]<<8 | bmp[3*i+2]<<16;
}
//解决上下颠倒 把一维数组 二维化思考
for(i=0;i<h;i++)
{
for(j=0;j<w;j++)
{
lcd[(h-1-i)*800+j]=temp[i*w+j];
}
}
//解除映射
munmap(lcd,800*480*4);
//6.关闭文件
close(bmp_fd);
close(fd);
}
//在指定位置显示图片 x0,y0为起点坐标
int show_anywherebmp(int x0,int y0,const char *bmpname)
{
//1.打开屏幕
int fd=0; //接受open的返回值
fd=open("/dev/fb0", O_RDWR);
if(fd==-1) //做错误判断
{
perror("open fb0 fail");
}
//建立屏幕映射
unsigned int* lcd = mmap(NULL, 800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
//打开图片
int bmp_fd=0; //接受open的返回值
bmp_fd=open(bmpname, O_RDWR);
if(bmp_fd==-1) //做错误判断
{
perror("open func.bmp fail");
}
//2.偏移54字节
//先提取到宽
lseek(bmp_fd,18,SEEK_SET);
int w=0;
read(bmp_fd,&w,4);
printf("w=%d\n",w);//打印宽度信息
//再提取高
lseek(bmp_fd,22,SEEK_SET);
int h=0;
read(bmp_fd,&h,4);
printf("h=%d\n",h);//打印宽度信息
lseek(bmp_fd,54,SEEK_SET);
//3.读取像素数据 800*480
unsigned char bmp[w*h*3];
read(bmp_fd,bmp,sizeof(bmp));
//4.数据处理
/*
bmp[0]--B
bmp[1]--G
bmp[2]--R
bmp[3]--B
....
lcd[0]=bmp[0] | bmp[1]<<8 | bmp[2]<<16;
lcd[1]=bmp[3] | bmp[4]<<8 | bmp[5]<<16;
lcd[2]=bmp[6] | bmp[7]<<8 | bmp[8]<<16;
*/
unsigned int temp[800*480]={0};
int i=0;
int j=0;
for(i=0;i<w*h;i++)
{
temp[i]=bmp[3*i] | bmp[3*i+1]<<8 | bmp[3*i+2]<<16;
}
//解决上下颠倒 把一维数组 二维化思考
for(i=0;i<h;i++)
{
for(j=0;j<w;j++)
{
lcd[(h-1-i+y0)*800+j+x0]=temp[i*w+j];
}
}
//解除映射
munmap(lcd,800*480*4);
//6.关闭文件
close(bmp_fd);
close(fd);
}
int get_xy(int *x,int *y)
{
int count=0;
//1.打开触摸屏
int tsfd =open("/dev/input/event0",O_RDWR);
if(tsfd == -1)
{
perror("open ts fail");
}
//2.read
struct input_event ts;
while(1)
{
read(tsfd,&ts,sizeof(struct input_event));
//筛选
if(ts.type ==EV_ABS && ts.code==ABS_X )
{
*x=ts.value; //适合蓝底屏幕
//*x= ts.value*800/1024; //适合黑底屏幕
count++;
}
if(ts.type ==EV_ABS && ts.code==ABS_Y )
{
*y=ts.value; //适合蓝底屏幕
//*y= ts.value*480/600; //适合黑底屏幕
count++;
}
if(count == 2)
{
break;
}
}
//关闭触摸屏
close(tsfd);
}