在arm开发板上实现播放内存里所有的jpg和bmp格式图片
之前学习的时候一个作业,趁机会发表一下做个记录,bmp图片较为简单就可以实现了,关于bmp图片的原理可参考这个链接https://blog.csdn.net/u013066730/article/details/82625158,jpg的话是使用了官方的jpg库,可自行去官方下载http://www.ijg.org/
下面是一些代码
main.c 的内容
/*查找整个系统中的bmp和jpg格式图片,并打印出他们的信息,同时在开发板上显示这张图片*/#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>#define BLACK 0x000000int read_JPEG_file (char * filename,int *lcd); //读取JPG格式图片信息/*显示.JPG格式的图片*/
void show_jpg(char *photo_path)
{//打开需要映射的硬件设备 int lcd_fd = open("/dev/fb0",O_RDWR);if(lcd_fd < 0){perror("open fail");exit(0); }//映射文件到虚拟内存空间中 int *lcd_p = mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd_fd,0);//对JPEG 图片解码并显示read_JPEG_file(photo_path,lcd_p);sleep(1);int i=0;for(i=0;i<800*480;i++){*(lcd_p+i) = BLACK;}//关闭映射和打开的文件munmap(lcd_p,800*480*4);close(lcd_fd);
}/*显示.BMP格式的图片*/
void show_bmp(char *photo_path)
{//打开需要映射的硬件设备int lcd_fd = open("/dev/fb0",O_RDWR);if(!lcd_fd){perror("open");exit(1);}//映射文件到虚拟内存空间中int *lcd_p = mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd_fd,0);int bmp_fd = open(photo_path,O_RDWR);if(!bmp_fd){perror("open");exit(2);}//读取图片的头信息unsigned char head[54]={0};read(bmp_fd,head,54);//处理头数据int chang = *((int *)&head[18]);int kuan = *((int *)&head[22]);int bit = *((int *)&head[28]);printf("chang=%d,kuan=%d,bit=%d\n",chang,kuan,bit);//根据头数据定义像素数据的缓存地址 char color_buf[chang*kuan*(bit/8)];int size = read(bmp_fd,color_buf,sizeof(color_buf));printf("size=%d\n",size);//定义一个数据的缓冲区int buf24[chang*kuan];int i=0;for(i=0;i<chang*kuan;i++){buf24[i] = color_buf[i*3+0] | color_buf[i*3+1]<< 8 | color_buf[i*3+2] << 16;//B 0-7 G 8-15 R:16 - 23}//把图像的数据写入到lcd屏幕设备中int x=0,y=0; for(y=0;y<kuan;y++){ for(x=0;x<chang;x++){//超出显示屏范围跳出 if(x >= 800 || y >= 480)break;//图片没有超出显示屏范围else if(chang <= 800 && kuan <= 480 ){*(lcd_p + (800*(480-kuan)/2 + (800-chang)/2) + x + y*800) = buf24[x + (kuan-1-y)*chang];}// 图片长和宽都超出屏幕,显示图片中间800*480部分else if(chang > 800 && kuan > 480){*(lcd_p + x + y*800) = buf24[(chang-800)/2 + x + (kuan - (kuan-480)/2 - 1 - y) * chang];}// 图片长超出,宽没有,居中显示else if(chang > 800 && kuan <= 480){*(lcd_p + (800*(480-kuan)/2) + x + y*800) = buf24[(chang-800)/2 + x + (kuan-1-y)*chang];}// 图片宽超出,长没有,居中显示else if(chang <= 800 && kuan > 480){*(lcd_p + (800-chang)/2 + x + y*800) = buf24[x + (kuan - (kuan-480)/2 - 1 - y) * chang];}}}/*图片显示一秒后清屏进入下一张图片*/sleep(1);for(i=0;i<800*480;i++){*(lcd_p+i) = BLACK;}//关闭映射和打开的文件munmap(lcd_p,800*480*4);close(bmp_fd);close(lcd_fd);
}/*实现搜索整个系统中的 .bmp .jpg 文件 */
int find(char *path)
{DIR *dir=opendir(path);if(dir==NULL){/*根目录下一些文件无法打开,为了不影响观看效果,不打印错误结果*///perror("opedndir");return -1;}while(1){struct dirent *ep = readdir(dir);if(ep==NULL){break;}//跳过隐藏文件if( ep->d_name[0] == '.' ){continue;}//目录if(ep->d_type==DT_DIR){char buf[4096]={0};if(strcmp(path,"/")==0)sprintf(buf,"%s%s",path,ep->d_name);elsesprintf(buf,"%s/%s",path,ep->d_name);// printf("%s\n",buf);find(buf);}//文件if(ep->d_type==DT_REG){/* *.bmp 文件 */if(strstr(ep->d_name,".bmp") != NULL ){if(strcmp(strstr(ep->d_name,".bmp"),".bmp") == 0){if(strcmp(path,"/")==0)printf("%s%s",path,ep->d_name);elseprintf("%s/%s\n",path,ep->d_name);char buf1[4096]={0};if(strcmp(path,"/")==0)sprintf(buf1,"%s%s",path,ep->d_name);elsesprintf(buf1,"%s/%s",path,ep->d_name);show_bmp(buf1);}}/* *.jpg 文件 */if(strstr(ep->d_name,".jpg") != NULL){if(strcmp(strstr(ep->d_name,".jpg"),".jpg") == 0){if(strcmp(path,"/")==0)printf("%s%s",path,ep->d_name);elseprintf("%s/%s\n",path,ep->d_name);char buf2[4096]={0};if(strcmp(path,"/")==0)sprintf(buf2,"%s%s",path,ep->d_name);elsesprintf(buf2,"%s/%s",path,ep->d_name);show_jpg(buf2);}}}}closedir(dir);
}int main(int argc,char *argv[])
{find("/");printf("\nOver!!!");printf("\n\n");
}
jpg.c的内容
#include <stdio.h>
#include "jpeglib.h"
#include <setjmp.h>extern JSAMPLE * image_buffer; /* Points to large array of R,G,B-order data */
extern int image_height; /* Number of rows in image */
extern int image_width; /* Number of columns in image */struct my_error_mgr {struct jpeg_error_mgr pub; /* "public" fields */jmp_buf setjmp_buffer; /* for return to caller */
};typedef struct my_error_mgr * my_error_ptr;/** Here's the routine that will replace the standard error_exit method:*/METHODDEF(void)
my_error_exit (j_common_ptr cinfo)
{/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */my_error_ptr myerr = (my_error_ptr) cinfo->err;/* Always display the message. *//* We could postpone this until after returning, if we chose. */(*cinfo->err->output_message) (cinfo);/* Return control to the setjmp point */longjmp(myerr->setjmp_buffer, 1);
}//功能:读取jpeg 文件中的数据转换成 r g b 值
int read_JPEG_file (char * filename,int *lcd)
{//定义一个 jpeg 的解码对象 struct jpeg_decompress_struct cinfo;//定义一个jpeg 的出错对象 struct my_error_mgr jerr;/* More stuff */FILE * infile; /*源文件*/JSAMPARRAY buffer; /*输出行缓存*/int row_stride; /*输出行缓存的宽度*///打开源文件if ((infile = fopen(filename, "rb")) == NULL) {fprintf(stderr, "can't open %s\n", filename);return 0;}/* Step 1: 初始化JPEG 解码对象*//*初始化出错对象 */cinfo.err = jpeg_std_error(&jerr.pub);jerr.pub.error_exit = my_error_exit;/* Establish the setjmp return context for my_error_exit to use. */if (setjmp(jerr.setjmp_buffer)) {jpeg_destroy_decompress(&cinfo);fclose(infile);return 0;}/*初始化解码对象*/jpeg_create_decompress(&cinfo);/* Step 2: 关联源文件与解码对象*/jpeg_stdio_src(&cinfo, infile);/* Step 3: 读取jpeg图像的头数据*/(void) jpeg_read_header(&cinfo, TRUE);/* Step 5: 开始解码*/(void) jpeg_start_decompress(&cinfo);/* 一行所占用的字节数 */row_stride = cinfo.output_width * cinfo.output_components;/*为输出行缓存分配堆空间*/buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);//cinfo.output_width * cinfo.output_componentsint buf24[cinfo.output_width*cinfo.output_height];//重点!!!!! 循环对每一行数据进行解码!! while (cinfo.output_scanline < cinfo.output_height) {//printf("%d\n",cinfo.output_scanline);//读取一行数据进行解码 并 写入到 buffer 中(void) jpeg_read_scanlines(&cinfo, buffer, 1);char *p = buffer[0]; //指向数据的R G B 数据的缓存首地址 int i=0; for(i=0;i<cinfo.output_width;i++) //把一行的 R G B 值全部都取出来 { char r = *p++; char g = *p++;char b = *p++; buf24[i + (cinfo.output_scanline-1) * cinfo.output_width] = r << 16 | g << 8 | b; // 处理 jpeg 中的RGB 数据 }} //把图像的数据写入到lcd屏幕设备中int x = 0, y = 0;for(y=0;y<cinfo.output_height;y++){for(x=0;x<cinfo.output_width;x++){//超出显示屏范围跳出 if(x >= 800 || y >= 480)break;//图片没有超出显示屏范围else if(cinfo.output_width <= 800 && cinfo.output_height <= 480 ){*(lcd + (800*(480-cinfo.output_height)/2 + (800-cinfo.output_width)/2) + x + y*800) = buf24[x + y*cinfo.output_width];}// 图片长和宽都超出屏幕,显示图片中间800*480部分else if(cinfo.output_width > 800 && cinfo.output_height > 480){*(lcd + x + y*800) = buf24[(cinfo.output_width-800)/2 + x + ((cinfo.output_height-480)/2 + y) * cinfo.output_width];}// 图片长超出,宽没有,居中显示else if(cinfo.output_width > 800 && cinfo.output_height <= 480){*(lcd + (800*(480-cinfo.output_height)/2) + x + y*800) = buf24[(cinfo.output_width-800)/2 + x + y*cinfo.output_width];}// 图片宽超出,长没有,居中显示else if(cinfo.output_width <= 800 && cinfo.output_height > 480){*(lcd + (800-cinfo.output_width)/2 + x + y*800) = buf24[x + ((cinfo.output_height-480)/2 +y) * cinfo.output_width];}}}//*(lcd + (cinfo.output_scanline - 1)*800 + i) = color; //把转换后的颜色数据赋值给 lcd 屏幕 //cinfo.output_scanline*800 第几行 //把解码后的数据输出 LCD 屏幕中// put_scanline_someplace(buffer[0], row_stride);/* Step 7: Finish decompression */(void) jpeg_finish_decompress(&cinfo);jpeg_destroy_decompress(&cinfo);fclose(infile);return 1;
}
测试用的机器是arm架构、linux系统的粤嵌公司的6818开发板,最终实现效果就是在屏幕上轮流播放内存里面的所有bmp和jpg格式的图片。
在arm开发板上实现播放内存里所有的jpg和bmp格式图片相关推荐
- 将linux内核烧进arm板,ARM开发板上uClinux内核移植
<ARM开发板上uClinux内核移植>由会员分享,可在线阅读,更多相关<ARM开发板上uClinux内核移植(19页珍藏版)>请在人人文库网上搜索. 1.纷傲掌秀悸篷益哑檀扬 ...
- 【linux】ARM开发板上设置RTC时间,断电重启后,设置失效的原因分析
问题描述 linux中使用date设置时间后用hwclock -w同步到RTC,断电重启后,有时会失效 原因分析 保存时间戳 1.使用命令关机(halt)会调用rc0.d中的脚本: 2.使用命令重启( ...
- 如何在ARM开发板上从源码编译安装OpenCV和OpenCV contrib
点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 本文主要介绍如何在ARM开发板上从源码编译安装OpenCV和OpenCV contrib. OpenC ...
- ARM开发板上iconv_open(utf-8, gb2312) 调用失败的解决方法(转)
ARM开发板上iconv_open("utf-8", "gb2312") 调用失败的解决方法 应用程序代码如下: static int code_convert ...
- 摄像头在liunx上的QT显示和OK6410 ARM开发板上的使用
摄像头在liunx上的QT显示和OK6410 ARM开发板上的使用 发布者:旺旺雪饼 时间:2013-01-05 16:56:09 环境: Ubuntu10.04 arm linux OS: 3. ...
- python交叉编译_交叉编译Python3.6.2,使用海思arm-hisiv200-linux-gcc,移植到arm开发板上...
最近在学习Python,感觉使用Python可以快速的写出程序,比之前使用的C语言快多了,能省出很多时间.多学一点知识有更多的选择.本职工作是嵌入式开发,学习了Python后想移植到开发板上,尝试嵌入 ...
- linux usb视频开发板,ARM开发板上USB 摄像头图像采集实现
开发板上的arm是AT91RM9200,摄像头选用的是网眼的pc350,主控芯片是ov511+.系统内核是2.4,宿主机是fedora core 6,交叉编译器是2.95.3.就是这些家底了,:-). ...
- 在ARM开发板上实现LCD+USB键盘
一.LCD驱动 这个地方先留着 二.USB键盘驱动 在linux内核里边提供了usbkbd.c可以直接借助这个模块,编译生成驱动模块加载进内核,其实对于驱动程序,这里还不是重点,最后想要实现的是直接在 ...
- arm开发板上4G网络转为以太网口供其他设备使用
一个设备和ARM开发板的以太网口连接使用4G模块实现上网 最后做完发现只要思路对,没什么特别难的东西要做,开始我一直以为是路由表.arp的问题,其实都不是,只是IP地址转换的问题,其他都不需要动.之前 ...
最新文章
- 若变量均已正确定义并赋值,以下合法的c语言赋值语句是,若变量均已正确定义并赋值,以下合法的C语言赋值语句是()...
- 香港大学提出OneNet:一阶段端到端目标检测网络,无需NMS!无需二分匹配!
- harris角点检测_角点检测(2) - harris算子 - 理论与Python代码
- 《漫画算法2》源码整理-6 两数之和 三数之和
- » Markdown/reST 编辑器 ReText 3.0 发布 Wow! Ubuntu
- Linux/Centos Tomcat 配置日志切分以及脚本自动清理
- RHCE 学习笔记(24) - LVM 逻辑卷
- 课程 预编译框架,开发高性能应用 - 微软技术暨生态大会 2018
- CentOS7显卡驱动问题
- pt-heartbeat 监测RDS延迟
- 苹果宣布取消AirPower 因技术难题无法攻克
- JavaScript——事件,DOM,Browser Object Model 浏览器对象模型,电灯开关,HTML DOM,表单动态添加
- php源码比赛,TSRC挑战赛: PHP防御绕过挑战实录
- CF 1538 G. Gift Set (贪心+思维)
- 大一计算机题库百度云,《大学计算机基础》试题题库及答案.doc
- 注意力CBMA到底在网络中做了什么事
- 如何写好一篇论文的摘要?
- PXIEBPMCx4载板转接卡
- Halcon每月授权license如何更新
- 基于AT89C51单片机的温度计设计