diff --git a/examples/img2twit.cpp b/examples/img2twit.cpp
index 9ff776e..fccfaaf 100644
--- a/examples/img2twit.cpp
+++ b/examples/img2twit.cpp
@@ -244,7 +244,7 @@ static void fwrite_utf8(FILE *f, uint32_t x)
 class bitstack
 {
 public:
-    bitstack() { alloc(); init(0); }
+    bitstack(int max) { alloc(max); init(0); }
 
     ~bitstack() { delete[] digits; delete[] str; }
 
@@ -285,38 +285,39 @@ public:
     }
 
 private:
-    bitstack(uint32_t i) { alloc(); init(i); }
+    bitstack(int max, uint32_t x) { alloc(max); init(x); }
 
     bitstack(bitstack &b)
     {
-        alloc();
+        alloc(b.max_size);
         msb = b.msb;
-        memcpy(digits, b.digits, (MAX_MSG_LEN + 1) * sizeof(uint32_t));
+        memcpy(digits, b.digits, (max_size + 1) * sizeof(uint32_t));
     }
 
     bitstack(bitstack const &b)
     {
-        alloc();
+        alloc(b.max_size);
         msb = b.msb;
-        memcpy(digits, b.digits, (MAX_MSG_LEN + 1) * sizeof(uint32_t));
+        memcpy(digits, b.digits, (max_size + 1) * sizeof(uint32_t));
     }
 
-    void alloc()
+    void alloc(int max)
     {
-        digits = new uint32_t[MAX_MSG_LEN + 1];
-        str = new char[(MAX_MSG_LEN + 1) * 8 + 1];
+        max_size = max;
+        digits = new uint32_t[max_size + 1];
+        str = new char[(max_size + 1) * 8 + 1];
     }
 
     void init(uint32_t i)
     {
         msb = 0;
-        memset(digits, 0, (MAX_MSG_LEN + 1) * sizeof(uint32_t));
+        memset(digits, 0, (max_size + 1) * sizeof(uint32_t));
         digits[0] = i;
     }
 
     /* Could be done much faster, but we don't care! */
-    void add(uint32_t x) { add(bitstack(x)); }
-    void sub(uint32_t x) { sub(bitstack(x)); }
+    void add(uint32_t x) { add(bitstack(max_size, x)); }
+    void sub(uint32_t x) { sub(bitstack(max_size, x)); }
 
     void add(bitstack const &_b)
     {
@@ -409,7 +410,7 @@ private:
         return b.digits[0];
     }
 
-    int msb;
+    int msb, max_size;
     uint32_t *digits;
     char *str;
 };
@@ -794,7 +795,7 @@ static void analyse(pipi_image_t *src)
 
 int main(int argc, char *argv[])
 {
-    uint32_t unicode_data[4096]; /* FIXME: allocate this dynamically */
+    uint32_t unicode_data[2048];
     int opstats[2 * NB_OPS];
     char const *srcname = NULL, *dstname = NULL;
     pipi_image_t *src, *tmp, *dst;
@@ -898,29 +899,59 @@ int main(int argc, char *argv[])
 
     /* Decoding mode: read UTF-8 text from stdin */
     if(dstname)
-        for(int i = 0; i < MAX_MSG_LEN; i++)
-            unicode_data[i] = fread_utf8(stdin);
-
-    /* Autodetect charset if decoding, otherwise switch to CJK. */
-    if(!unichars)
-    {
-        if(dstname)
+        for(MAX_MSG_LEN = 0; ;)
         {
-            if(unicode_data[0] >= 0x0021 && unicode_data[0] < 0x007f)
-                unichars = unichars_ascii;
-            else if(unicode_data[0] >= 0x4e00 && unicode_data[0] < 0x9fa6)
-                unichars = unichars_cjk;
-            else if(unicode_data[0] >= 0x25a0 && unicode_data[0] < 0x27bf)
-                unichars = unichars_symbols;
-            else
+            uint32_t ch = fread_utf8(stdin);
+            if(ch == 0xffffffff || ch == '\n')
+                break;
+            if(ch <= ' ')
+                continue;
+            unicode_data[MAX_MSG_LEN++] = ch;
+
+            if(MAX_MSG_LEN >= 2048)
             {
-                fprintf(stderr, "Error: unable to detect charset\n");
+                fprintf(stderr, "Error: message too long.\n");
                 return EXIT_FAILURE;
             }
         }
-        else
+
+    if(MAX_MSG_LEN == 0)
+    {
+        fprintf(stderr, "Error: empty message.\n");
+        return EXIT_FAILURE;
+    }
+
+    /* Autodetect charset if decoding, otherwise switch to CJK. */
+    if(dstname)
+    {
+        char const *charset;
+
+        if(unicode_data[0] >= 0x0021 && unicode_data[0] < 0x007f)
+        {
+            unichars = unichars_ascii;
+            charset = "ascii";
+        }
+        else if(unicode_data[0] >= 0x4e00 && unicode_data[0] < 0x9fa6)
+        {
             unichars = unichars_cjk;
+            charset = "cjk";
+        }
+        else if(unicode_data[0] >= 0x25a0 && unicode_data[0] < 0x27bf)
+        {
+            unichars = unichars_symbols;
+            charset = "symbols";
+        }
+        else
+        {
+            fprintf(stderr, "Error: unable to detect charset\n");
+            return EXIT_FAILURE;
+        }
+
+        if(DEBUG_MODE)
+            fprintf(stderr, "Detected charset \"%s\"\n", charset);
     }
+    else if(!unichars)
+        unichars = unichars_cjk;
 
     pipi_set_gamma(1.0);
 
@@ -941,8 +972,8 @@ int main(int argc, char *argv[])
     TOTAL_CELLS = (int)(DATA_BITS / CELL_BITS);
     MAX_ITERATIONS = ITERATIONS_PER_POINT * POINTS_PER_CELL * TOTAL_CELLS;
 
-    bitstack b; /* We cannot declare this before, because MAX_MSG_LEN
-                 * wouldn't be defined. */
+    bitstack b(MAX_MSG_LEN); /* We cannot declare this before, because
+                              * MAX_MSG_LEN wouldn't be defined. */
 
     if(dstname)
     {
@@ -993,7 +1024,7 @@ int main(int argc, char *argv[])
     /* Print debug information */
     if(DEBUG_MODE)
     {
-        fprintf(stderr, "Maximum message size: %i\n", MAX_MSG_LEN);
+        fprintf(stderr, "Message size: %i\n", MAX_MSG_LEN);
         fprintf(stderr, "Available characters: %i\n", NUM_CHARACTERS);
         fprintf(stderr, "Available bits: %f\n", TOTAL_BITS);
         fprintf(stderr, "Maximum image resolution: %ix%i\n", MAX_W, MAX_H);