framebuffer 编程


从第一 步跨进杭电,就表示了研究生的开始,我发过誓我不能才那么弱小,我要和以前不一样。研究生的学习让我觉得是一种充实感,让我觉得我对得起我自己,不是混时间,所以读研的开始的良好的。

研究生的生活其实很单一,就是待实验室学习,你可以做老师安排的,如果老师没安排的话你可以学习自己的。研究生也要上课,不过和大学不一样的是,上课只是为了修学分,因为连上课的老师也是这么觉得的。基本上我都不怎么会去上课的,因为实在是无聊的不行,老是想睡觉,老师讲课和念书差不多....不过这些老师也是牛人啊,只有4个同学上课他也能讲的很有味道...膜拜啊....哈哈哈....

还是说正事吧,开始读书以后基本上都是很忙的,很多新的发现也来不及写出来分享。

导师给我的任务是先把arm开发板的弄熟悉,这个板子其实暑假的时候老师就给我了,我基本上也没有怎么去玩这个,因为我以为只有台式机才能做开发的,哈哈,来了学校我发现我错了,其实只有一根网线,基本就ok了。真是蛋疼啊.....

导师说让我先在板子上实现关于图片的显示,我我觉得这个难度其实挺大的...毕竟以前都是有现成的API,所以关于底层的实现基本上是不清楚,给我的时候我觉得这个难度让我有点不知道怎么办。不过搞arm的好像就我一个人在我们实验室。本以为师兄他们也是搞arm的,可是他们竟然是搞FPGA,到现在我也不知道那是做什么的,哈哈,做他们那个的是真正搞硬件的,他们竟然连C语言都不会,哎...没人可问啊...那就问问Google吧。

首先进入我眼的是QT的移植,这样就可以调用现成API了,不过说要很到的空间,这个我有点慌张的,因为到现在我都不知道那个板子有多少的空间来放东西,反正我感觉是很小的,最近发现他的空间真的很小,大概是5m的空间,不过幸好他还是支持SDcard和U盘,不过这个那个时候也没想,觉得QT移植谁知道会发生什么错误呢。。。。那个时候就直接放弃了这个想法

第二个就是关于framebuffer编程了,我觉得这就体现了LINUX的优越之处了,把什么都看作文件,都可以出操作文件的手段来操作硬件....

关于framebuffer这个编程我也不想多说什么,其实蛮简单的,基本很固定的操作。还有就是关于jpeg库移植,网上有很多关于这个方面的教程,而且这个库的编译与移植问题也不是很大,再说它的使用也是很简单的。

这个程序我花了一天写完的,又花了两天想把他写的更加好看,能重复利用,因为真的要考虑以后忘里面填写的其他功能....所以花时间想写的好一点,不过基本还是很丑陋,因为在我一个一个模块写的过程,发现最后连接起来的时候n多error,让我很郁闷,而且这些问题真的是我没有遇见过的..所以最后还是放弃了大部分的重构。

不过上个星期老师说让我实现视频的播放,这个功能我也觉得难度很大啊,哎...我也没有什么想法,所以一直拖着....不过也不是什么事情都没有做,花了两天的时间看了自己的书藉,分别是<C专家编程>和国人的一本<系统程序员成长计划>,我觉得这两本书偏向的方面不一样,看<C专家编程>会让你懂得更多,但是真的如果说对你的编程能力有多少提高,我觉得没有,毕竟这个是要靠多写锻炼出来的,但是这本书真的很经典,因为他让你在写程序的时候了然于空的感觉...

而国人的那本书我觉得就是一本可以锻炼你编程水平的书,有的人写程序很多年,可是水平依然很水,比如我....惭愧啊....哈哈...它像一本让你成为高手的书籍,你使用它就必须要按他去做,不过看的太快,看一点就把他给你的任务完成,然后在往下看...他先教你方法,然后再让你去学习思考,反正我觉得这个书对于我来说真的很合适啊...

两天看书,后面的时间我就把我上次写的framebuffer 代码重新重构了一下,这个词我还是昨天才知道,叫做重构,好像的意思是对别人的代码进行重新封装之类的。做过重构以后让我更加的了解了重构的难的...我还是自己的code,如果是别人的code让就是一件很让人郁闷的事情了。


下面就贴一下我的code,有什么要改进的要说哦....(额...代码竟然在虚拟机中....郁闷....开了一下虚拟机,卡了我10min啊)

framebuffer.h<这部分主要是包含了对framebuffer文件的处理>

#ifndef FREAMBUFFER_H 
#define FRAMEBUFFER_H

struct _Fb0;
typedef struct _Fb0 Fb0;

Fb0* Fb0_create();
int Fb0_open(Fb0 *thiz);
int Fb0_destory(Fb0 *thiz);
int Fb0_get_info(Fb0 *thiz);
int Fb0_mmap(Fb0 *thiz);
int Fb0_unmmap(Fb0 *thiz);
int Fb0_display(Fb0 *thiz,unsigned char *pdata);


#endif

framebuffer.c

#include <stdio.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
//#include "test.h"
#include "jpeg.h"
#include "my_algorithm.h"
#include "framebuffer.h"

struct _Fb0
{
    unsigned char *dmen;
    size_t width;
    size_t height;
    size_t bit_pre_pixel;
    size_t screensize;
    int fbfd;
};

Fb0* Fb0_create()
{
    Fb0 *tmp = (Fb0*)malloc(sizeof(Fb0));

    //return_value_if_fail(tmp != NULL,NULL);
    
    tmp->dmen = NULL;
    tmp->width = 0;
    tmp->height = 0;
    tmp->bit_pre_pixel = 0;
    tmp->screensize = 0;
    tmp->fbfd = -1;
    
    return tmp;
}

int Fb0_open(Fb0 *thiz)
{
    //is_null(thiz);
    //return_value_if_fail(thiz != NULL,-1); 
    if((thiz->fbfd = open("/dev/fb0",O_RDWR)) == -1) 
    {
	fprintf(stderr,"this dev open is fail,this error is %s\n",strerror(errno));
	return -1;
    }
    return 0;
}

int Fb0_destory(Fb0 *thiz)
{
    //return_value_if_fail(thiz != NULL,-1); 

    Fb0_unmmap(thiz);
    close(thiz->fbfd);
    free(thiz);
    thiz = NULL;

    return 0;
}

int Fb0_get_info(Fb0 *thiz)
{
    //return_value_if_fail(thiz != NULL,-1); 

    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;

    //get fix info
    if(ioctl(thiz->fbfd,FBIOGET_FSCREENINFO,&finfo) == -1)
    {
	fprintf(stderr,"Get fixinfo is failure,this error is %s\n",strerror(errno));
	return -1;
    }

    //get var info
    if(ioctl(thiz->fbfd,FBIOGET_VSCREENINFO,&vinfo) == -1)
    {
	fprintf(stderr,"Get var info is failure,this error is %s\n",strerror(errno));
	return -1;
    }

    thiz->width = vinfo.xres;
    thiz->height = vinfo.yres;
    thiz->bit_pre_pixel = vinfo.bits_per_pixel;
    thiz->screensize = (thiz->width * thiz->height * thiz->bit_pre_pixel) >> 3; 
    //thiz->dmen = (unsigned char *)malloc(thiz->width * thiz->height);
//-------------------------------------------------------------------------------------------
    //print_msg(&(thiz->width),0);
    //print_msg(&(thiz->height),0);
    //print_msg(&(thiz->bit_pre_pixel),0);
//-------------------------------------------------------------------------------------------
     return 0;
}

int Fb0_mmap(Fb0 *thiz)
{
    //return_value_if_fail(thiz != NULL,-1); 
    //is_null(thiz);

    if((thiz->dmen = (unsigned char*)mmap(0,thiz->screensize ,PROT_READ | PROT_WRITE,MAP_SHARED,thiz->fbfd,0)) == NULL)
    {
    	fprintf(stderr,"thiz mmap is fail,this error is %s\n",strerror(errno));
	
	return -1;
    }
    printf("dev->dmen is %p\n",thiz->dmen);
    return 0;
}

int Fb0_unmmap(Fb0 *thiz)
{
   //return_value_if_fail(thiz != NULL,-1); 
   //is_null(thiz);

   munmap(thiz->dmen,thiz->screensize);

   return 0;
}

static void Fb0_fullpixel(Fb0 *thiz,size_t i, size_t j,unsigned short color)
{
    //is_null(thiz);

    unsigned short* tmp = ((unsigned short*)thiz->dmen + j * (thiz->width) + i);

    *(tmp) = color;
}

int Fb0_display(Fb0 *thiz,unsigned char	*pdata)
{
       //return_value_if_fail(thiz != NULL &&  dis_pic != NULL,-1); 
       size_t i = 0;	        
       size_t j = 0;	
       size_t count = 0;
       printf("pdata is %p\n",pdata);
       printf("thiz->width is %d\n",thiz->width);
       printf("thiz->height is %d\n",thiz->height);

       for(j = 0;j < thiz->height; j++)
       {
	   //printf("this is hello,%d\n",count++);
	    for(i = 0;i < thiz->width;   i++)	    
	    {
		    unsigned short color = rgb888torgb565(*(pdata + j * thiz->width * 3 + i * 3),*(pdata + j * thiz->width * 3 + i * 3 + 1),*(pdata + j * thiz->width * 3 + i * 3 + 2));

		Fb0_fullpixel(thiz,i,j,color);
	    }
       }

       return 0;
}

jpeg.h<关于对jpeg的解压以及获取数据的过程>

#ifndef JPEG_H
#define JPEG_H

struct _Jpeg;
typedef struct _Jpeg Jpeg;

Jpeg* Jpeg_file_link(char *file);
int Jpeg_decompress(Jpeg *thiz);
size_t Jpeg_get_width(Jpeg *thiz);
size_t Jpeg_get_height(Jpeg *thiz);
size_t Jpeg_get_byte_pre_pixel(Jpeg *thiz);
unsigned char* Jpeg_get_pdata(Jpeg *thiz);

int Jpeg_close(Jpeg *thiz);

void Jpeg_set_width(Jpeg *thiz, size_t	width);
void Jpeg_set_height(Jpeg *thiz, size_t height);
void Jpeg_set_pdata(Jpeg *thiz,	unsigned char *pdata);
void Jpeg_set_byte_pre_pixel(Jpeg *thiz,size_t byte_pre_pixel);

#endif

jpeg.c

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<sys/types.h>
#include <jpeglib.h>
#include "jpeg.h"
//#include"test.h"

struct _Jpeg
{
    struct jpeg_decompress_struct cinfo;
    unsigned char *pdata;
    size_t width;
    size_t height;
    size_t byte_pre_pixel;
};

//将具体的图像文件进行link
Jpeg* Jpeg_file_link(char *file)
{

    struct jpeg_error_mgr jerr;
    Jpeg *tmp = (Jpeg*) malloc(sizeof(Jpeg));
    FILE *jfile = NULL;

    if(tmp == NULL)
    {
	printf("assign mem is fail,this error is %s\n",strerror(errno));
	return NULL;
    }

    //return_value_if_fail(tmp != NULL,NULL);

   if(!(jfile = fopen(file,"rb"))) 
   {
       fprintf(stderr,"this file open fail,this error is %s\n",strerror(errno));
       return NULL;
   }

   //link to jpeg
   tmp->cinfo.err = jpeg_std_error(&jerr);// important
   jpeg_create_decompress(&(tmp->cinfo));    
   jpeg_stdio_src(&(tmp->cinfo),jfile);    
   jpeg_read_header(&(tmp->cinfo),TRUE);
    


   tmp->pdata = NULL;
   tmp->width = 0;
   tmp->height = 0;
   tmp->byte_pre_pixel = 0;

   return tmp;
}

int Jpeg_decompress(Jpeg *thiz)
{
    //return_value_if_fail(thiz != NULL,-1);
    //is_null(thiz);
    jpeg_start_decompress(&(thiz->cinfo));

    thiz->width = (thiz->cinfo).output_width;
    thiz->height = (thiz->cinfo).output_height;
    thiz->byte_pre_pixel= (thiz->cinfo).output_components;
    
//------------------------------------------------------------------------------------------------------
	//print_msg(&(thiz->width),0);
	//print_msg(&(thiz->height),0);
	//print_msg(&(thiz->byte_pre_pixel),0);
//------------------------------------------------------------------------------------------------------


    {
	unsigned char *row_byte_count = (unsigned char*)malloc(thiz->width * thiz->byte_pre_pixel);
	thiz->pdata = (unsigned char*)malloc(thiz->width * thiz->height *thiz->byte_pre_pixel);
	unsigned char *pdata_tmp = thiz->pdata;

	if(thiz->pdata == NULL)
	{
	    fprintf(stderr,"thiz->pdata assign mem is fail,this error is %s\n",strerror(errno));
	    return -1;
	}
	while((thiz->cinfo).output_scanline < thiz->height)
	{
	    jpeg_read_scanlines(&(thiz->cinfo),&row_byte_count,1);	 
	    memcpy(pdata_tmp,row_byte_count,thiz->width * thiz->byte_pre_pixel);
	    pdata_tmp += thiz->width * thiz->byte_pre_pixel;
	}
	free(row_byte_count);
    }
}

size_t Jpeg_get_width(Jpeg *thiz)
{
    //is_null(thiz);
    //return_value_if_fail(thiz!= NULL,-1);
    return thiz->width;
}

size_t Jpeg_get_height(Jpeg *thiz)
{
    //is_null(thiz);
    //return_value_if_fail(thiz!= NULL,-1);
    return thiz->height;
}

size_t Jpeg_get_byte_pre_pixel(Jpeg *thiz)
{
    //is_null(thiz);
    //return_value_if_fail(thiz!= NULL,-1);

    return thiz->byte_pre_pixel;
}

unsigned char* Jpeg_get_pdata(Jpeg *thiz)
{
    //is_null(thiz);
    return thiz->pdata;
}

int Jpeg_close(Jpeg *thiz)
{
    //is_null(thiz);
    //return_value_if_fail(thiz!= NULL,-1);

    jpeg_finish_decompress(&(thiz->cinfo));
    jpeg_destroy_decompress(&(thiz->cinfo));
    free(thiz->pdata);
    free(thiz);
    thiz = NULL;

    return 0;
}

void Jpeg_set_width(Jpeg *thiz, size_t width)
{
    //is_null(thiz);
    thiz->width = width;
}

void Jpeg_set_height(Jpeg *thiz, size_t height)
{
    //is_null(thiz);
    thiz->height = height;
}

void Jpeg_set_pdata(Jpeg *thiz, unsigned char *pdata)
{
    //is_null(thiz);
    free(thiz->pdata);
    thiz->pdata = pdata;
}

void Jpeg_set_byte_pre_pixel(Jpeg *thiz, size_t byte_pre_pixel)
{
    //is_null(thiz);
    thiz->byte_pre_pixel = byte_pre_pixel;
}

my_algorithm.h <算法的实现,比如放缩,我使用的是最简单的放缩>

#ifndef ALGORITHM_H
#define ALGORITHM_H

unsigned short rgb888torgb565(unsigned char red,unsigned char green,unsigned char blue);
void zoom(Jpeg *thiz,size_t width,size_t height);

#endif

my_algorithm.c

#include <sys/types.h>
#include <stdio.h>
#include "jpeg.h"
#include "my_algorithm.h"
//#include "test.h"

struct _Three
{
    unsigned char a;
    unsigned char b;
    unsigned char c;
}__attribute__((packed));

typedef struct _Three Three;

unsigned short rgb888torgb565(unsigned char  red, unsigned char green, unsigned char blue)
{
    unsigned short blue_tmp = (blue >> 3) & (0x001f);
    unsigned short green_tmp = ((green >> 2) << 5) & (0x07e0);
    unsigned short red_tmp = ((red >> 3) << 11) & (0xf800);

    return red_tmp | green_tmp | blue_tmp;
}

void zoom(Jpeg *thiz,size_t width, size_t height)
{
    //is_null(thiz);
    printf("hello,algorithm\n");


    unsigned char *pdata_tmp = (unsigned char*)malloc(width * height * Jpeg_get_byte_pre_pixel(thiz));
    int i = 0;
    int j = 0;
    unsigned char *pdata = Jpeg_get_pdata(thiz);
    
    printf("thiz_tmp is %p and pdata is %p\n",pdata_tmp,pdata);
    printf("thiz pixel byte is %d\n",Jpeg_get_byte_pre_pixel(thiz));
    printf("this three is %d\n",sizeof(Three));
    for(j = 0;j < height; j++)
    {
	for(i = 0;i < width; i++)
	{
	    int srcx = (Jpeg_get_width(thiz) * i) / width;
	    int srcy = (Jpeg_get_height(thiz) * j) / height;
	    
	    (((Three*)(pdata_tmp + j * width * Jpeg_get_byte_pre_pixel(thiz)))[i]) = (((Three*)(pdata + srcy * Jpeg_get_width(thiz) * Jpeg_get_byte_pre_pixel(thiz)))[srcx]);
	}
    }
    Jpeg_set_width(thiz,width);
    Jpeg_set_height(thiz,height);
    Jpeg_set_pdata(thiz,pdata_tmp);
}

关于main函数就不写了,因为也就是上面的调用,哈哈哈,在上面的程序的过程中我学习了很多很多的知识,各种各样的错误。

1.比如头文件的顺序不一样造成了上面的头文件要下面的头文件按的定义,哎....以前都没想到过

2.就是关于指针的传值,以为用指针传值可以放心的保证函数会对数据进行改变,却没想到在我本来就是想让指针本身改变

3.还有就是想做成动态连接库的形式,作为还是放弃了,因为又生成了很多问题

4.还有就是用arm-linux-gcc 编译的时候一些头文件和库文件参数的设置


总之这次的精益求精让我受益匪浅,在这里我使用了新的方法,比如在头文件中不声明结构体的具体成员之类的。对数据的封装做的也挺好的....不过不足之处还有有的,就是关于检查NULL的这个检查我没写进去,本来想通过宏来解决的,可是一直不成功,就没写,所以就先放着吧...以后再说....


哈哈,研究生让我有很好的开始,以后2年以后能学有所成.....就这样吧....




你可能感兴趣的:(framebuffer 编程)