搜索
bottom↓
回复: 4

UCGUI在16位LCD上如何实现渐变色显示效果?

[复制链接]

出0入0汤圆

发表于 2013-3-9 22:52:06 | 显示全部楼层 |阅读模式
本帖最后由 electrlife 于 2013-3-9 23:08 编辑

如题所示,最近想把界面做的好看些,于是似着在UCGUI上实现一个渐变色的函数,如下所示:
一个是常规实现方式,另一个是优化的方式。
如果24位的LCD上显示没问题,可是如果在16位的LCD显示,则不是很理想。因此需要使用
类似Floyd-Steinberg算法的来消除影响。不知各位做过没,效果如何,速度如何,类似单
片机即CORTEX-M3这种MCU在UCGUI环境下使用是否可以流畅显示。

不知大家还有没有其它的方法!

#include "GUI_Protected.h"

typedef void tfDrawLine(int x, int y, int z);

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/
/*********************************************************************
*
*       _DrawGradient
*
*/
#if 1
static void _DrawGradient(int x0, int y0, int x1, int y1, GUI_COLOR Color0, GUI_COLOR Color1,
                          const tfDrawLine *pfDrawLine, int Vertical) {
  GUI_COLOR Color, OldColor;
  int i, r0, g0, b0, r1, g1, b1, r, g, b;
  int dt;

  if (Vertical) {
    dt = y1 - y0 + 1;
  } else {
    dt = x1 - x0 + 1;
  }

  r0 = (Color0>>  0) & 0xff;
  g0 = (Color0>>  8) & 0xff;
  b0 = (Color0>> 16) & 0xff;

  r1 = (Color1>>  0) & 0xff;
  g1 = (Color1>>  8) & 0xff;
  b1 = (Color1>> 16) & 0xff;

  OldColor = GUI_GetColor();
  for (i = 0; i < dt; i++) {
    r = r0 + (i * (r1 - r0)) / dt;
    g = g0 + (i * (g1 - g0)) / dt;
    b = b0 + (i * (b1 - b0)) / dt;

    Color = r + (g << 8) + (b << 16);
    LCD_SetColor(Color);

    if (Vertical) {
      /* void LCD_DrawHLine(int x0, int y,  int x1) */
      pfDrawLine(x0, y0+i, x1);
    } else {
      /* void LCD_DrawVLine(int x, int y0,  int y1) */
      pfDrawLine(x0+i, y0, y1);
    }
  }
  LCD_SetColor(OldColor);
}
#else
static void _DrawGradient(int x0, int y0, int x1, int y1, GUI_COLOR Color0, GUI_COLOR Color1,
                          const tfDrawLine *pfDrawLine, int Vertical) {
  int i, r0, g0, b0, r1, g1, b1, r, g, b;
  int dt;

  GUI_COLOR OldColor = GUI_GetColor();
  
  r0 = (Color0>>  0) & 0xff;
  g0 = (Color0>>  8) & 0xff;
  b0 = (Color0>> 16) & 0xff;

  r1 = (Color1>>  0) & 0xff;
  g1 = (Color1>>  8) & 0xff;
  b1 = (Color1>> 16) & 0xff;
  
  if (Vertical) {
    dt = y1 - y0 + 1;
    y1 = y0;
  } else {
    dt = x1 - x0 + 1;
    x1 = x0;
  }

  for (i = 0; i < dt; i++) {
    r = r0 + (i * (r1 - r0)) / dt;
    g = g0 + (i * (g1 - g0)) / dt;
    b = b0 + (i * (b1 - b0)) / dt;

    Color1 = r + (g << 8) + (b << 16);
    if (Color1 != Color0) {
      LCD_SetColor(Color0);
      if (Vertical) {
        if (y1 != y0) {
          GUI_FillRect(x0, y0, x1, y1);
        } else {
          pfDrawLine(x0, y1, x1);
        }
        y1++;
        y0 = y1;
      } else {
        if (x1 != x0) {
          GUI_FillRect(x0, y0, x1, y1);
        } else {
          pfDrawLine(x1, y0, y1);
        }
        x1++;
        x0 = x1;
      }
      Color0 = Color1;
    } else {
      if (Vertical) {
        y1++;
      } else {
        x1++;
      }
    }
  }
  
  LCD_SetColor(Color0);
  if (Vertical) {
    if (y1 != y0) {
      GUI_FillRect(x0, y0, x1, y1);
    } else {
      pfDrawLine(x0, y1, x1);
    }
  } else {
    if (x1 != x0) {
      GUI_FillRect(x0, y0, x1, y1);
    } else {
      pfDrawLine(x1, y0, y1);
    }
  }

  LCD_SetColor(OldColor);
}
#endif

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/

/*********************************************************************
*
*       GUI_DrawGradientV
*/
void GUI_DrawGradientV(int x0, int y0, int x1, int y1, GUI_COLOR Color0, GUI_COLOR Color1)
{
  #if (GUI_WINSUPPORT)
    GUI_RECT r;
  #endif
  GUI_LOCK();
  #if (GUI_WINSUPPORT)
    WM_ADDORG(x0,y0);
    WM_ADDORG(x1,y1);
    r.x0 = x0; r.x1 = x1;
    r.y0 = y0; r.y1 = y1;
    WM_ITERATE_START(&r); {
  #endif
  _DrawGradient(x0, y0, x1, y1, Color0, Color1, LCD_DrawHLine, 1);
  #if (GUI_WINSUPPORT)
    } WM_ITERATE_END();
  #endif
  GUI_UNLOCK();
}

/*********************************************************************
*
*       GUI_DrawGradientH
*/
void GUI_DrawGradientH(int x0, int y0, int x1, int y1, GUI_COLOR Color0, GUI_COLOR Color1)
{
  #if (GUI_WINSUPPORT)
    GUI_RECT r;
  #endif
  GUI_LOCK();
  #if (GUI_WINSUPPORT)
    WM_ADDORG(x0,y0);
    WM_ADDORG(x1,y1);
    r.x0 = x0; r.x1 = x1;
    r.y0 = y0; r.y1 = y1;
    WM_ITERATE_START(&r); {
  #endif
  _DrawGradient(x0, y0, x1, y1, Color0, Color1, LCD_DrawVLine, 0);
  #if (GUI_WINSUPPORT)
    } WM_ITERATE_END();
  #endif
  GUI_UNLOCK();
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。

出0入0汤圆

发表于 2013-3-10 00:34:37 | 显示全部楼层
你用16位的,你算法没改成相应的16位吗?如这里: r0 = (Color0>>  0) & 0xff;
  g0 = (Color0>>  8) & 0xff;
  b0 = (Color0>> 16) & 0xff;

出0入0汤圆

 楼主| 发表于 2013-3-10 07:24:17 | 显示全部楼层
faduo2012 发表于 2013-3-10 00:34
你用16位的,你算法没改成相应的16位吗?如这里: r0 = (Color0>>  0) & 0xff;
  g0 = (Color0>>  8) & 0xf ...

这个函数接口是在UCGUI系统环境下实现的,用户使用的颜色都是888真彩色,
当调用LCD_SetColor时会把相应的888转变成对应硬件支持的颜色。

出0入0汤圆

 楼主| 发表于 2013-3-11 11:59:21 | 显示全部楼层
自己顶起来,求推荐24BIT BMP转16BIT BMP小失真的软件!!
目前使用Photoshop Fireworks等转换均无果!!

出0入0汤圆

发表于 2013-3-25 14:53:30 | 显示全部楼层
Floyd-Steinberg算法可以比较接近原图的转换,但是我也在找这块资料。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-10-3 05:27

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表