zoukankan      html  css  js  c++  java
  • s3c2440裸机-LCD编程(五、LCD上实现画点、线、圆)

    1.画点

    无论是何种图形,都是基于点来构成的,因此我们需要先实现画点,其他的都是上层的一些数据处理了,像各种图形、甚至色彩鲜艳的图片无非都是一些由点构造出的数据而已。

    我们在在farmebuffer.c实现画点,在geomentry.c实现画线、画圆等几何图形,font.c实现画字。

    那么一个像素点要显示到lcd上,我们要知道它的位置坐标,然后还要知道它的颜色值,假设该像素点的坐标为(x,y),那么该像素的地址为:

    (x,y)= fb_base + (xres*(bpp/8))*y +x*bpp/8;
    

    那么所以在画点前需要先获取lcd参数:fb_base、xres、yres、bpp;

    static unsigned int fb_base;
    static int xres, yres, bpp;
    
    void fb_get_lcd_params(void)
    {
    	get_lcd_params(&fb_base, &xres, &yres, &bpp);
    }
    

    然后画点函数如下:

    static unsigned int fb_base;
    static int xres, yres, bpp;
    void fb_put_pixel(int x, int y, unsigned int color)
    {
    	unsigned char  *pc;  /* 8bpp */
    	unsigned short *pw;  /* 16bpp */
    	unsigned int   *pdw; /* 32bpp */
    
    	unsigned int pixel_base = fb_base + (xres * bpp / 8) * y + x * bpp / 8;
    
    	switch (bpp)//根据像素不同bpp格式,在Frame buffer中存放方式不一样,但对用户来说,不关心颜色格式,通通当做32位色颜色处理,所以这里需要做格式转换
    	{
    		case 8:
    			pc = (unsigned char *) pixel_base;
    			*pc = color;
    			break;
    		case 16:
    			pw = (unsigned short *) pixel_base;
    			*pw = convert32bppto16bpp(color);
    			break;
    		case 32:
    			pdw = (unsigned int *) pixel_base;
    			*pdw = color;
    			break;
    	}
    }
    

    用户传入的颜色数据一般都是32bit的,即格式为:0x00RRGGBB,

    对于8PP,通过的是调色板索引实现的,这个后续再讲解,直接*pc = color即可(这样只取了高8位,低精度的数据就丢了)。

    对于16PP,那么需要进行颜色转换后再存放进frame buffer。

    对于32PP,大小刚好对应,直接*pc = color即可。

    使用convert32bppto16bpp()函数进行颜色数据转换:

    //先分别取出RGB,再相应的清除低位数据,实现将RGB888变为RGB565
    unsigned short convert32bppto16bpp(unsigned int rgb)
    {
    	int r = (rgb >> 16)& 0xff;
    	int g = (rgb >> 8) & 0xff;
    	int b = rgb & 0xff;
    	
    	/* rgb565 */
    	r = r >> 3;//取低5位
    	g = g >> 2;//取低6位
    	b = b >> 3;//取低5位
    
    	return ((r<<11) | (g<<5) | (b));
    }
    

    2.画线画圆

    画圆画线的具体原理不是本主题的重点,这些属于研究算法的范畴了,比如这里就有现成的算法可以用,如这篇博客:https://blog.csdn.net/p1126500468/article/details/50428613,里面有画圆画线的函数实现,直接使用就可以了,套用画点的"轮子"就可以了。

    3.测试

    新建一个geometry.c,复制博客中代码,替换里面的描点显示函数即可。

    /* 画线 */
    draw_line(0, 0, xres - 1, 0, 0xff0000); //(0,0) 到(xres - 1, 0)两点间的线
    draw_line(xres - 1, 0, xres - 1, yres - 1, 0xffff00);
    draw_line(0, yres - 1, xres - 1, yres - 1, 0xff00aa);
    draw_line(0, 0, 0, yres - 1, 0xff00ef);
    draw_line(0, 0, xres - 1, yres - 1, 0xff4500);
    draw_line(xres - 1, 0, 0, yres - 1, 0xff0780);
    
    delay(1000000);
    
    /* 画圆 */
    draw_circle(xres/2, yres/2, yres/4, 0xff00);
    

    测试结果如下:

  • 相关阅读:
    vs错误集合及解决方案
    使用内存映射文件进行EXE、DLL通信(非MFC)
    visual studio使用小技巧(以vs2012为例)
    GetModuleHandle(NULL)获取当前DLL模块基址?
    格式化输出中的%s和%S的陷阱
    关于字符编码
    远程附加调试服务的方法
    结构体内包含位段,其数据内存分布
    微信个人公众号开发-java
    Docker-常用基建的安装与部署
  • 原文地址:https://www.cnblogs.com/fuzidage/p/13268118.html
Copyright © 2011-2022 走看看