diff --git a/src/bitmap.c b/src/bitmap.c
index 3b3c5b7..8c7ffdf 100644
--- a/src/bitmap.c
+++ b/src/bitmap.c
@@ -103,6 +103,12 @@ static int rgb_palette[] =
     0xfff, 0xfff, 0xfff,
 };
 
+static int rgb_weight[] =
+{
+    //2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
 #if !defined(_DOXYGEN_SKIP_ME)
 #define HSV_XRATIO 6
 #define HSV_YRATIO 3
@@ -541,6 +547,12 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2,
         _increment_dither = increment_random_dither;
         break;
 
+    case CACA_DITHERING_FSTEIN:
+        _init_dither = init_no_dither;
+        _get_dither = get_no_dither;
+        _increment_dither = increment_no_dither;
+        break;
+
     default:
         /* Something wicked happened! */
         return;
@@ -624,15 +636,24 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2,
             continue;
         }
 
-        r += remain_r;
-        g += remain_g;
-        b += remain_b;
-        r += remain_r_next;
-        g += remain_g_next;
-        b += remain_b_next;
-        remain_r_next = fs_r[x+1];
-        remain_g_next = fs_g[x+1];
-        remain_b_next = fs_b[x+1];
+        if(_caca_dithering == CACA_DITHERING_FSTEIN)
+        {
+            r += remain_r;
+            g += remain_g;
+            b += remain_b;
+            r += remain_r_next;
+            g += remain_g_next;
+            b += remain_b_next;
+            remain_r_next = fs_r[x+1];
+            remain_g_next = fs_g[x+1];
+            remain_b_next = fs_b[x+1];
+        }
+        else
+        {
+            r += (_get_dither() - 0x80) * 4;
+            g += (_get_dither() - 0x80) * 4;
+            b += (_get_dither() - 0x80) * 4;
+        }
 
         distmin = INT_MAX;
         for(i = 0; i < 16; i++)
@@ -640,6 +661,7 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2,
             dist = sq(r - rgb_palette[i * 3])
                  + sq(g - rgb_palette[i * 3 + 1])
                  + sq(b - rgb_palette[i * 3 + 2]);
+            dist *= rgb_weight[i];
             if(dist < distmin)
             {
                 outbg = i;
@@ -658,6 +680,7 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2,
             dist = sq(r - rgb_palette[i * 3])
                  + sq(g - rgb_palette[i * 3 + 1])
                  + sq(b - rgb_palette[i * 3 + 2]);
+            dist *= rgb_weight[i];
             if(dist < distmin)
             {
                 outfg = i;
@@ -686,24 +709,27 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2,
         }
         outch = density_chars[4 * ch];
 
-        remain_r = r - (fg_r * ch + bg_r * ((2*DCHMAX-1) - ch)) / (2*DCHMAX-1);
-        remain_g = g - (fg_g * ch + bg_g * ((2*DCHMAX-1) - ch)) / (2*DCHMAX-1);
-        remain_b = b - (fg_b * ch + bg_b * ((2*DCHMAX-1) - ch)) / (2*DCHMAX-1);
-        remain_r_next = fs_r[x+1];
-        remain_g_next = fs_g[x+1];
-        remain_b_next = fs_b[x+1];
-        fs_r[x-1] += 3 * remain_r / 16;
-        fs_g[x-1] += 3 * remain_g / 16;
-        fs_b[x-1] += 3 * remain_b / 16;
-        fs_r[x] = 5 * remain_r / 16;
-        fs_g[x] = 5 * remain_g / 16;
-        fs_b[x] = 5 * remain_b / 16;
-        fs_r[x+1] = 1 * remain_r / 16;
-        fs_g[x+1] = 1 * remain_g / 16;
-        fs_b[x+1] = 1 * remain_b / 16;
-        remain_r = 7 * remain_r / 16;
-        remain_g = 7 * remain_g / 16;
-        remain_b = 7 * remain_b / 16;
+        if(_caca_dithering == CACA_DITHERING_FSTEIN)
+        {
+            remain_r = r - (fg_r * ch + bg_r * ((2*DCHMAX-1) - ch)) / (2*DCHMAX-1);
+            remain_g = g - (fg_g * ch + bg_g * ((2*DCHMAX-1) - ch)) / (2*DCHMAX-1);
+            remain_b = b - (fg_b * ch + bg_b * ((2*DCHMAX-1) - ch)) / (2*DCHMAX-1);
+            remain_r_next = fs_r[x+1];
+            remain_g_next = fs_g[x+1];
+            remain_b_next = fs_b[x+1];
+            fs_r[x-1] += 3 * remain_r / 16;
+            fs_g[x-1] += 3 * remain_g / 16;
+            fs_b[x-1] += 3 * remain_b / 16;
+            fs_r[x] = 5 * remain_r / 16;
+            fs_g[x] = 5 * remain_g / 16;
+            fs_b[x] = 5 * remain_b / 16;
+            fs_r[x+1] = 1 * remain_r / 16;
+            fs_g[x+1] = 1 * remain_g / 16;
+            fs_b[x+1] = 1 * remain_b / 16;
+            remain_r = 7 * remain_r / 16;
+            remain_g = 7 * remain_g / 16;
+            remain_b = 7 * remain_b / 16;
+        }
 
         /* Now output the character */
         caca_set_color(outfg, outbg);
diff --git a/src/caca.c b/src/caca.c
index 02ef4ec..613faa9 100644
--- a/src/caca.c
+++ b/src/caca.c
@@ -319,12 +319,13 @@ void caca_set_feature(enum caca_feature feature)
             break;
 
         case CACA_DITHERING:
-            feature = CACA_DITHERING_ORDERED4;
+            feature = CACA_DITHERING_FSTEIN;
         case CACA_DITHERING_NONE:
         case CACA_DITHERING_ORDERED2:
         case CACA_DITHERING_ORDERED4:
         case CACA_DITHERING_ORDERED8:
         case CACA_DITHERING_RANDOM:
+        case CACA_DITHERING_FSTEIN:
             _caca_dithering = feature;
             break;
 
@@ -356,6 +357,7 @@ char const *caca_get_feature_name(enum caca_feature feature)
         case CACA_DITHERING_ORDERED4: return "4x4 ordered dithering";
         case CACA_DITHERING_ORDERED8: return "8x8 ordered dithering";
         case CACA_DITHERING_RANDOM:   return "random dithering";
+        case CACA_DITHERING_FSTEIN:   return "Floyd-Steinberg dithering";
 
         default: return "unknown";
     }
@@ -541,6 +543,8 @@ static void caca_init_features(void)
             caca_set_feature(CACA_DITHERING_ORDERED8);
         else if(!strcasecmp("random", var))
             caca_set_feature(CACA_DITHERING_RANDOM);
+        else if(!strcasecmp("fstein", var))
+            caca_set_feature(CACA_DITHERING_FSTEIN);
     }
 #endif
 }
diff --git a/src/caca.h b/src/caca.h
index 84d251d..6036514 100644
--- a/src/caca.h
+++ b/src/caca.h
@@ -151,8 +151,9 @@ enum caca_feature
     CACA_DITHERING_ORDERED4 = 0x33, /**< Ordered 4x4 Bayer dithering. */
     CACA_DITHERING_ORDERED8 = 0x34, /**< Ordered 8x8 Bayer dithering. */
     CACA_DITHERING_RANDOM   = 0x35, /**< Random dithering. */
+    CACA_DITHERING_FSTEIN   = 0x36, /**< Floyd-Steinberg dithering. */
 #define CACA_DITHERING_MIN    0x31 /**< First dithering feature. */
-#define CACA_DITHERING_MAX    0x35 /**< Last dithering feature. */
+#define CACA_DITHERING_MAX    0x36 /**< Last dithering feature. */
 
     CACA_FEATURE_UNKNOWN = 0xffff /**< Unknown feature. */
 };