RGB888转RGB565 抖动算法

试试这种抖动算法。
https://en.wikipedia.org/wiki/Ordered_dithering

============================================

/* Dither Tresshold for Red Channel */
static const BYTE dither_tresshold_r[64] = {
  1, 7, 3, 5, 0, 8, 2, 6,
  7, 1, 5, 3, 8, 0, 6, 2,
  3, 5, 0, 8, 2, 6, 1, 7,
  5, 3, 8, 0, 6, 2, 7, 1,

  0, 8, 2, 6, 1, 7, 3, 5,
  8, 0, 6, 2, 7, 1, 5, 3,
  2, 6, 1, 7, 3, 5, 0, 8,
  6, 2, 7, 1, 5, 3, 8, 0
};

/* Dither Tresshold for Green Channel */
static const BYTE dither_tresshold_g[64] = {
  1, 3, 2, 2, 3, 1, 2, 2,
  2, 2, 0, 4, 2, 2, 4, 0,
  3, 1, 2, 2, 1, 3, 2, 2,
  2, 2, 4, 0, 2, 2, 0, 4,

  1, 3, 2, 2, 3, 1, 2, 2,
  2, 2, 0, 4, 2, 2, 4, 0,
  3, 1, 2, 2, 1, 3, 2, 2,
  2, 2, 4, 0, 2, 2, 0, 4
};

/* Dither Tresshold for Blue Channel */
static const BYTE dither_tresshold_b[64] = {
  5, 3, 8, 0, 6, 2, 7, 1,
  3, 5, 0, 8, 2, 6, 1, 7,
  8, 0, 6, 2, 7, 1, 5, 3,
  0, 8, 2, 6, 1, 7, 3, 5,

  6, 2, 7, 1, 5, 3, 8, 0,
  2, 6, 1, 7, 3, 5, 0, 8,
  7, 1, 5, 3, 8, 0, 6, 2,
  1, 7, 3, 5, 0, 8, 2, 6
};

/* Get 16bit closest color */
BYTE closest_rb(BYTE c) { 
  return (c >> 3 << 3); /* red & blue */
}
BYTE closest_g(BYTE c) {
  return (c >> 2 << 2); /* green */
}

/* RGB565 */
WORD RGB16BIT(BYTE r, BYTE g, BYTE b) {
  return ((WORD)((r>>3)<<11)|((g>>2)<<5)|(b>>3));
}

/* Dithering by individual subpixel */
WORD dither_xy(
  int x, 
  int y, 
  BYTE r, 
  BYTE g, 
  BYTE b
){
  /* Get Tresshold Index */
  BYTE tresshold_id = ((y & 7) << 3) + (x & 7);

  r = closest_rb(
          MIN(r + dither_tresshold_r[tresshold_id], 0xff)
       );
  g = closest_g(
          MIN(g + dither_tresshold_g[tresshold_id], 0xff)
       );
  b = closest_rb(
          MIN(b + dither_tresshold_b[tresshold_id], 0xff)
       );
  return RGB16BIT(r, g, b);
}

/* Dithering Pixel from 32/24bit RGB 
*
* GetR, GetG, GetB -> Function to get individual color in pixel
*
*/
WORD dither_color_xy(int x, int y, DWORD col) {
  return dither_xy(x, y, GetR(col), GetG(col), GetB(col));
}

/* EXAMPLES */
void ExampleDither1(WORD * dest, DWORD * src, int width, int height){
  int x, y;
  for (y=0; y<height; y++){
    for (x=0; x<width; x++){
      int pos = y * width + x;
      dest[pos] = dither_color_xy(x,y,src[pos]);
    }
  }
}
void ExampleDither2(WORD * dest, BYTE * src, int width, int height){
  int x, y;
  for (y=0; y<height; y++){
    for (x=0; x<width; x++){
      int pos = y * width + x;
      dest[pos] = dither_xy(x,y,src[pos*3],src[pos*3+1],src[pos*3+2]);
    }
  }
}

 

来源:https://www.amobbs.com/thread-5633005-1-1.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要将 RGB888 转换RGB565 并应用抖动,可以按照以下步骤进行: 1. 从 RGB888 中提取红色(R)、绿色(G)和蓝色(B)的值。 2. 对每个颜色通道的值进行量化。对于 RGB565,红色通道需要保留 5 位,绿色通道需要保留 6 位,蓝色通道需要保留 5 位。可以通过右移和按位与操作来实现。 - R5 = R8 >> 3 - G6 = G8 >> 2 - B5 = B8 >> 3 3. 计算每个颜色通道的误差并应用抖动。误差是当前值减去量化值。你可以使用 Floyd-Steinberg 抖动算法来分配误差,并将其传播到相邻像素。对于当前像素的每个通道,按照以下公式计算: - R_error = R8 - (R5 << 3) - G_error = G8 - (G6 << 2) - B_error = B8 - (B5 << 3) 将误差分配给相邻像素时,可以根据权重分配给下一个像素。常见的权重分配如下: ``` [ [ 0, 0, 0 ], [ 0, 0, 7 ], [ 3, 5, 1 ] ] ``` 对于当前像素的右下方像素,将 R_error、G_error 和 B_error 分别乘以权重矩阵的相应元素,并将结果分配给右下方像素的通道值。确保将结果限制在 0 到 255 之间。 4. 将 R5、G6 和 B5 组合成一个 16 位的 RGB565 值。可以使用按位或操作来完成。 - RGB565 = (R5 << 11) | (G6 << 5) | B5 5. 重复以上步骤,将转换后的 RGB565 值应用于每个像素,直到完成图像的转换。 请注意,这只是一个基本的 RGB888RGB565转换抖动过程。在实际应用中,可能需要考虑图像边界处理、量化误差的传播方式以及其他优化技巧。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值