diff --git a/backend/library.c b/backend/library.c
index 48a9c62d..99727b1b 100644
--- a/backend/library.c
+++ b/backend/library.c
@@ -181,6 +181,7 @@ extern int dmatrix(struct zint_symbol *symbol, const unsigned char source[], con
 extern int vin(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* VIN Code (Vehicle Identification Number) */
 extern int mailmark(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* Royal Mail 4-state Mailmark */
 extern int ultracode(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* Ultracode */
+extern int rmqr(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* rMQR */
 
 extern int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to PNG/BMP/PCX */
 extern int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to EPS/EMF/SVG */
@@ -385,7 +386,7 @@ static void check_row_heights(struct zint_symbol *symbol) {
 
 static int check_force_gs1(const int symbology) {
     /* Returns 1 if symbology MUST have GS1 data */
-    
+
     int result = is_composite(symbology);
 
     switch (symbology) {
@@ -397,7 +398,7 @@ static int check_force_gs1(const int symbology) {
             result = 1;
             break;
     }
-    
+
     return result;
 }
 
@@ -414,6 +415,7 @@ static int gs1_compliant(const int symbology) {
         case BARCODE_CODE49:
         case BARCODE_QRCODE:
         case BARCODE_DOTCODE:
+        case BARCODE_RMQR:
             result = 1;
             break;
     }
@@ -440,6 +442,7 @@ static int is_matrix(const int symbology) {
         case BARCODE_HANXIN:
         case BARCODE_DOTCODE:
         case BARCODE_UPNQR:
+        case BARCODE_RMQR:
             result = 1;
             break;
     }
@@ -449,7 +452,7 @@ static int is_matrix(const int symbology) {
 
 static int is_linear(const int symbology) {
     /* Returns 1 if symbology is linear (1 dimensional) */
-    
+
     int result = 0;
     switch (symbology) {
         case BARCODE_CODE11:
@@ -506,7 +509,7 @@ static int is_linear(const int symbology) {
             result = 1;
             break;
     }
-    
+
     return result;
 }
 
@@ -633,6 +636,7 @@ int ZBarcode_ValidID(int symbol_id) {
         case BARCODE_VIN:
         case BARCODE_MAILMARK:
         case BARCODE_ULTRA:
+        case BARCODE_RMQR:
             result = 1;
             break;
     }
@@ -642,7 +646,7 @@ int ZBarcode_ValidID(int symbol_id) {
 
 static int extended_charset(struct zint_symbol *symbol, const unsigned char *source, const int length) {
     int error_number = 0;
-        
+
     /* These are the "elite" standards which can support multiple character sets */
     switch (symbol->symbology) {
         case BARCODE_QRCODE: error_number = qr_code(symbol, source, length);
@@ -655,6 +659,8 @@ static int extended_charset(struct zint_symbol *symbol, const unsigned char *sou
             break;
         case BARCODE_UPNQR: error_number = upnqr(symbol, source, length);
             break;
+        case BARCODE_RMQR: error_number = rmqr(symbol, source, length);
+            break;
     }
 
     return error_number;
@@ -669,7 +675,7 @@ static int reduced_charset(struct zint_symbol *symbol, const unsigned char *sour
 #else
     unsigned char* preprocessed = (unsigned char*) _alloca(in_length + 1);
 #endif
-    
+
     if (symbol->symbology == BARCODE_CODE16K) {
         symbol->whitespace_width = 16;
         symbol->border_width = 2;
@@ -685,7 +691,7 @@ static int reduced_charset(struct zint_symbol *symbol, const unsigned char *sour
             symbol->output_options += BARCODE_BOX;
         }
     }
-    
+
     switch (symbol->input_mode & 0x07) {
         case DATA_MODE:
         case GS1_MODE:
@@ -700,11 +706,11 @@ static int reduced_charset(struct zint_symbol *symbol, const unsigned char *sour
             }
             break;
     }
-    
+
     if ((symbol->height == 0) && is_linear(symbol->symbology)) {
         symbol->height = 50;
     }
-    
+
     switch (symbol->symbology) {
         case BARCODE_C25MATRIX: error_number = matrix_two_of_five(symbol, preprocessed, in_length);
             break;
@@ -894,7 +900,7 @@ int escape_char_process(struct zint_symbol *symbol, unsigned char *input_string,
 
     in_posn = 0;
     out_posn = 0;
-    
+
     do {
         if (input_string[in_posn] == '\\') {
             switch (input_string[in_posn + 1]) {
@@ -968,11 +974,11 @@ int escape_char_process(struct zint_symbol *symbol, unsigned char *input_string,
         }
         out_posn++;
     } while (in_posn < *length);
-    
+
     memcpy(input_string, escaped_string, out_posn);
     input_string[out_posn] = '\0';
     *length = out_posn;
-    
+
     error_number = 0;
 
     return error_number;
@@ -1125,7 +1131,7 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
         }
     }
     /* Everything from 128 up is Zint-specific */
-    if (symbol->symbology >= 145) {
+    if (symbol->symbology > 145) {
         strcpy(symbol->errtxt, "216: Symbology out of range, using Code 128");
         symbol->symbology = BARCODE_CODE128;
         error_number = ZINT_WARN_INVALID_OPTION;
@@ -1193,7 +1199,7 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
     if ((input_mode < 0) || (input_mode > 2)) {
         input_mode = DATA_MODE;
     }
-    
+
     if ((symbol->eci != 0) && (symbol->eci != 26)) {
         input_mode = DATA_MODE;
     }
@@ -1201,13 +1207,14 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
     if (input_mode == UNICODE_MODE) {
         strip_bom(local_source, &in_length);
     }
-    
+
     switch (symbol->symbology) {
         case BARCODE_QRCODE:
         case BARCODE_MICROQR:
         case BARCODE_GRIDMATRIX:
         case BARCODE_HANXIN:
         case BARCODE_UPNQR:
+        case BARCODE_RMQR:
             error_number = extended_charset(symbol, local_source, in_length);
             break;
         default:
@@ -1247,7 +1254,7 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
                 error_number = reduced_charset(symbol, local_source, in_length);
                 break;
         }
-        
+
         if (error_number == 0) {
             error_number = ZINT_WARN_USES_ECI;
             strcpy(symbol->errtxt, "222: Encoded data includes ECI");
@@ -1341,7 +1348,7 @@ int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) {
             error_number = dump_plot(symbol);
         } else
             if (!(strcmp(output, "EPS"))) {
-            error_number = plot_vector(symbol, rotate_angle, OUT_EPS_FILE);  
+            error_number = plot_vector(symbol, rotate_angle, OUT_EPS_FILE);
         } else
             if (!(strcmp(output, "SVG"))) {
             error_number = plot_vector(symbol, rotate_angle, OUT_SVG_FILE);
@@ -1434,7 +1441,7 @@ int ZBarcode_Encode_and_Buffer(struct zint_symbol *symbol, unsigned char *input,
     if (error_number == 0) {
         error_number = first_err;
     }
-    
+
     return error_number;
 }
 
@@ -1452,7 +1459,7 @@ int ZBarcode_Encode_and_Buffer_Vector(struct zint_symbol *symbol, unsigned char
     if (error_number == 0) {
         error_number = first_err;
     }
-    
+
     return error_number;
 }
 
@@ -1523,13 +1530,13 @@ int ZBarcode_Encode_File_and_Print(struct zint_symbol *symbol, char *filename, i
     if (error_number >= 5) {
         return error_number;
     }
-    
+
     first_err = error_number;
     error_number = ZBarcode_Print(symbol, rotate_angle);
     if (error_number == 0) {
         error_number = first_err;
     }
-    
+
     return error_number;
 }
 
@@ -1541,7 +1548,7 @@ int ZBarcode_Encode_File_and_Buffer(struct zint_symbol *symbol, char *filename,
     if (error_number >= 5) {
         return error_number;
     }
-    
+
     first_err = error_number;
     error_number = ZBarcode_Buffer(symbol, rotate_angle);
     if (error_number == 0) {
@@ -1559,7 +1566,7 @@ int ZBarcode_Encode_File_and_Buffer_Vector(struct zint_symbol *symbol, char *fil
     if (error_number >= 5) {
         return error_number;
     }
-    
+
     first_err = error_number;
     error_number = ZBarcode_Buffer_Vector(symbol, rotate_angle);
     if (error_number == 0) {
diff --git a/backend/qr.c b/backend/qr.c
index 6793d6fd..bc321f8f 100644
--- a/backend/qr.c
+++ b/backend/qr.c
@@ -1,8 +1,7 @@
-/* qr.c Handles QR Code */
+/* qr.c Handles QR Code, Micro QR Code, UPNQR and rMQR
 
-/*
     libzint - the open source barcode library
-    Copyright (C) 2009 -2017 Robin Stuart <rstuart114@gmail.com>
+    Copyright (C) 2009 - 2019 Robin Stuart <rstuart114@gmail.com>
 
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions
@@ -147,7 +146,7 @@ static int tribus(const int version,const int a,const int b,const int c) {
 }
 
 /* Convert input data to a binary stream and add padding */
-static void qr_binary(int datastream[], const int version, const int target_binlen, const char mode[], const int jisdata[], const size_t length, const int gs1, const int eci, const int est_binlen,const int debug) {
+static void qr_binary(int datastream[], const int version, const int target_codewords, const char mode[], const int jisdata[], const size_t length, const int gs1, const int eci, const int est_binlen,const int debug) {
     int position = 0;
     int i;
     char padbits;
@@ -163,10 +162,14 @@ static void qr_binary(int datastream[], const int version, const int target_binl
     strcpy(binary, "");
 
     if (gs1) {
-        strcat(binary, "0101"); /* FNC1 */
+        if (version < RMQR_VERSION) {
+            strcat(binary, "0101"); /* FNC1 */
+        } else {
+            strcat(binary, "101");
+        }
     }
 
-    if (eci != 0) {
+    if (eci != 0) { /* Not applicable to RMQR */
         strcat(binary, "0111"); /* ECI (Table 4) */
         if (eci <= 127) {
             bin_append(eci, 8, binary); /* 000000 to 000127 */
@@ -198,10 +201,18 @@ static void qr_binary(int datastream[], const int version, const int target_binl
             case 'K':
                 /* Kanji mode */
                 /* Mode indicator */
-                strcat(binary, "1000");
+                if (version < RMQR_VERSION) {
+                    strcat(binary, "1000");
+                } else {
+                    strcat(binary, "100");
+                }
 
                 /* Character count indicator */
-                bin_append(short_data_block_length, tribus(version, 8, 10, 12), binary);
+                if (version < RMQR_VERSION) {
+                    bin_append(short_data_block_length, tribus(version, 8, 10, 12), binary);
+                } else {
+                    bin_append(short_data_block_length, rmqr_kanji_cci[version - RMQR_VERSION], binary);
+                }
 
                 if (debug) {
                     printf("Kanji block (length %d)\n\t", short_data_block_length);
@@ -235,10 +246,18 @@ static void qr_binary(int datastream[], const int version, const int target_binl
             case 'B':
                 /* Byte mode */
                 /* Mode indicator */
-                strcat(binary, "0100");
+                if (version < RMQR_VERSION) {
+                    strcat(binary, "0100");
+                } else {
+                    strcat(binary, "011");
+                }
 
                 /* Character count indicator */
-                bin_append(short_data_block_length, tribus(version, 8, 16, 16), binary);
+                if (version < RMQR_VERSION) {
+                    bin_append(short_data_block_length, tribus(version, 8, 16, 16), binary);
+                } else {
+                    bin_append(short_data_block_length, rmqr_byte_cci[version - RMQR_VERSION], binary);
+                }
 
                 if (debug) {
                     printf("Byte block (length %d)\n\t", short_data_block_length);
@@ -267,7 +286,11 @@ static void qr_binary(int datastream[], const int version, const int target_binl
             case 'A':
                 /* Alphanumeric mode */
                 /* Mode indicator */
-                strcat(binary, "0010");
+                if (version < RMQR_VERSION) {
+                    strcat(binary, "0010");
+                } else {
+                    strcat(binary, "010");
+                }
 
                 percent_count = 0;
                 for (i = 0; i < short_data_block_length; i++) {
@@ -275,9 +298,13 @@ static void qr_binary(int datastream[], const int version, const int target_binl
                         percent_count++;
                     }
                 }
-                
+
                 /* Character count indicator */
-                bin_append(short_data_block_length + percent_count, tribus(version, 9, 11, 13), binary);
+                if (version < RMQR_VERSION) {
+                    bin_append(short_data_block_length + percent_count, tribus(version, 9, 11, 13), binary);
+                } else {
+                    bin_append(short_data_block_length + percent_count, rmqr_alphanum_cci[version - RMQR_VERSION], binary);
+                }
 
                 if (debug) {
                     printf("Alpha block (length %d)\n\t", short_data_block_length + percent_count);
@@ -365,10 +392,18 @@ static void qr_binary(int datastream[], const int version, const int target_binl
             case 'N':
                 /* Numeric mode */
                 /* Mode indicator */
-                strcat(binary, "0001");
+                if (version >= RMQR_VERSION) {
+                    strcat(binary, "0001");
+                } else {
+                    strcat(binary, "001");
+                }
 
                 /* Character count indicator */
-                bin_append(short_data_block_length, tribus(version, 10, 12, 14), binary);
+                if (version < RMQR_VERSION) {
+                    bin_append(short_data_block_length, tribus(version, 10, 12, 14), binary);
+                } else {
+                    bin_append(short_data_block_length, rmqr_numeric_cci[version - RMQR_VERSION], binary);
+                }
 
                 if (debug) {
                     printf("Number block (length %d)\n\t", short_data_block_length);
@@ -416,7 +451,11 @@ static void qr_binary(int datastream[], const int version, const int target_binl
     } while (position < length);
 
     /* Terminator */
-    strcat(binary, "0000");
+    if (version < RMQR_VERSION) {
+        strcat(binary, "0000");
+    } else {
+        strcat(binary, "000");
+    }
 
     current_binlen = (int)strlen(binary);
     padbits = 8 - (current_binlen % 8);
@@ -443,7 +482,7 @@ static void qr_binary(int datastream[], const int version, const int target_binl
 
     /* Add pad codewords */
     toggle = 0;
-    for (i = current_bytes; i < target_binlen; i++) {
+    for (i = current_bytes; i < target_codewords; i++) {
         if (toggle == 0) {
             datastream[i] = 0xec;
             toggle = 1;
@@ -455,7 +494,7 @@ static void qr_binary(int datastream[], const int version, const int target_binl
 
     if (debug) {
         printf("Resulting codewords:\n\t");
-        for (i = 0; i < target_binlen; i++) {
+        for (i = 0; i < target_codewords; i++) {
             printf("0x%2X ", datastream[i]);
         }
         printf("\n");
@@ -463,14 +502,20 @@ static void qr_binary(int datastream[], const int version, const int target_binl
 }
 
 /* Split data into blocks, add error correction and then interleave the blocks and error correction data */
-static void add_ecc(int fullstream[],const int datastream[],const int version,const int data_cw,const int blocks) {
-    int ecc_cw = qr_total_codewords[version - 1] - data_cw;
+static void add_ecc(int fullstream[],const int datastream[],const int version,const int data_cw,const int blocks,int debug) {
+    int ecc_cw;
+
+    if (version < RMQR_VERSION) {
+        ecc_cw = qr_total_codewords[version - 1] - data_cw;
+    } else {
+        ecc_cw = rmqr_total_codewords[version - RMQR_VERSION] - data_cw;
+    }
+
     int short_data_block_length = data_cw / blocks;
     int qty_long_blocks = data_cw % blocks;
     int qty_short_blocks = blocks - qty_long_blocks;
     int ecc_block_length = ecc_cw / blocks;
-    int i, j, length_this_block, posn, debug = 0;
-
+    int i, j, length_this_block, posn;
 
 #ifndef _MSC_VER
     unsigned char data_block[short_data_block_length + 2];
@@ -670,35 +715,36 @@ static int cwbit(const int* fullstream,const int i) {
     return resultant;
 }
 
-static void populate_grid(unsigned char* grid,const int size,const int* fullstream,const int cw) {
+static void populate_grid(unsigned char* grid,const int h_size,const int v_size,const int* fullstream,const int cw) {
     int direction = 1; /* up */
     int row = 0; /* right hand side */
 
     int i, n, y;
 
     n = cw * 8;
-    y = size - 1;
+    y = v_size - 1;
     i = 0;
     do {
-        int x = (size - 2) - (row * 2);
-        if (x < 6)
+        int x = (h_size - 2) - (row * 2);
+
+        if ((x < 6) && (v_size == h_size))
             x--; /* skip over vertical timing pattern */
 
-        if (!(grid[(y * size) + (x + 1)] & 0xf0)) {
+        if (!(grid[(y * h_size) + (x + 1)] & 0xf0)) {
             if (cwbit(fullstream, i)) {
-                grid[(y * size) + (x + 1)] = 0x01;
+                grid[(y * h_size) + (x + 1)] = 0x01;
             } else {
-                grid[(y * size) + (x + 1)] = 0x00;
+                grid[(y * h_size) + (x + 1)] = 0x00;
             }
             i++;
         }
 
         if (i < n) {
-            if (!(grid[(y * size) + x] & 0xf0)) {
+            if (!(grid[(y * h_size) + x] & 0xf0)) {
                 if (cwbit(fullstream, i)) {
-                    grid[(y * size) + x] = 0x01;
+                    grid[(y * h_size) + x] = 0x01;
                 } else {
-                    grid[(y * size) + x] = 0x00;
+                    grid[(y * h_size) + x] = 0x00;
                 }
                 i++;
             }
@@ -715,10 +761,10 @@ static void populate_grid(unsigned char* grid,const int size,const int* fullstre
             y = 0;
             direction = 0;
         }
-        if (y == size) {
+        if (y == v_size) {
             /* reached the bottom */
             row++;
-            y = size - 1;
+            y = v_size - 1;
             direction = 1;
         }
     } while (i < n);
@@ -1335,11 +1381,15 @@ static int getBinaryLength(const int version,char inputMode[],const int inputDat
     currentMode = ' '; // Null
 
     if (gs1 == 1) {
-        count += 4;
+        if (version < RMQR_VERSION) {
+            count += 4;
+        } else {
+            count += 3;
+        }
     }
 
     if (eci != 0) {
-        count += 12;
+        count += 12; // RMQR does not support ECI
     }
 
     for (i = 0; i < inputLength; i++) {
@@ -1347,11 +1397,19 @@ static int getBinaryLength(const int version,char inputMode[],const int inputDat
             count += 4;
             switch (inputMode[i]) {
                 case 'K':
-                    count += tribus(version, 8, 10, 12);
+                    if (version < RMQR_VERSION) {
+                        count += tribus(version, 8, 10, 12);
+                    } else {
+                        count += 3 + rmqr_kanji_cci[version - RMQR_VERSION];
+                    }
                     count += (blockLength(i, inputMode, inputLength) * 13);
                     break;
                 case 'B':
-                    count += tribus(version, 8, 16, 16);
+                    if (version < RMQR_VERSION) {
+                        count += tribus(version, 8, 16, 16);
+                    } else {
+                        count += 3 + rmqr_byte_cci[version - RMQR_VERSION];
+                    }
                     for (j = i; j < (i + blockLength(i, inputMode, inputLength)); j++) {
                         if (inputData[j] > 0xff) {
                             count += 16;
@@ -1361,7 +1419,11 @@ static int getBinaryLength(const int version,char inputMode[],const int inputDat
                     }
                     break;
                 case 'A':
-                    count += tribus(version, 9, 11, 13);
+                    if (version < RMQR_VERSION) {
+                        count += tribus(version, 9, 11, 13);
+                    } else {
+                        count += 3 + rmqr_alphanum_cci[version - RMQR_VERSION];
+                    }
                     alphalength = blockLength(i, inputMode, inputLength);
                     // In alphanumeric mode % becomes %%
                     for (j = i; j < (i + alphalength); j++) {
@@ -1381,7 +1443,11 @@ static int getBinaryLength(const int version,char inputMode[],const int inputDat
                     }
                     break;
                 case 'N':
-                    count += tribus(version, 10, 12, 14);
+                    if (version < RMQR_VERSION) {
+                        count += tribus(version, 10, 12, 14);
+                    } else {
+                        count += 3 + rmqr_numeric_cci[version - RMQR_VERSION];
+                    }
                     switch (blockLength(i, inputMode, inputLength) % 3) {
                         case 0:
                             count += (blockLength(i, inputMode, inputLength) / 3) * 10;
@@ -1406,7 +1472,7 @@ static int getBinaryLength(const int version,char inputMode[],const int inputDat
 
 int qr_code(struct zint_symbol *symbol, const unsigned char source[], size_t length) {
     int i, j, est_binlen;
-    int ecc_level, autosize, version, max_cw, target_binlen, blocks, size;
+    int ecc_level, autosize, version, max_cw, target_codewords, blocks, size;
     int bitmask, gs1;
     int canShrink;
 
@@ -1569,7 +1635,7 @@ int qr_code(struct zint_symbol *symbol, const unsigned char source[], size_t len
             return ZINT_ERROR_TOO_LONG;
         }
     }
-    
+
     /* Ensure maxium error correction capacity */
     if (est_binlen <= qr_data_codewords_M[version - 1] * 8) {
         ecc_level = LEVEL_M;
@@ -1581,30 +1647,30 @@ int qr_code(struct zint_symbol *symbol, const unsigned char source[], size_t len
         ecc_level = LEVEL_H;
     }
 
-    target_binlen = qr_data_codewords_L[version - 1];
+    target_codewords = qr_data_codewords_L[version - 1];
     blocks = qr_blocks_L[version - 1];
     switch (ecc_level) {
-        case LEVEL_M: target_binlen = qr_data_codewords_M[version - 1];
+        case LEVEL_M: target_codewords = qr_data_codewords_M[version - 1];
             blocks = qr_blocks_M[version - 1];
             break;
-        case LEVEL_Q: target_binlen = qr_data_codewords_Q[version - 1];
+        case LEVEL_Q: target_codewords = qr_data_codewords_Q[version - 1];
             blocks = qr_blocks_Q[version - 1];
             break;
-        case LEVEL_H: target_binlen = qr_data_codewords_H[version - 1];
+        case LEVEL_H: target_codewords = qr_data_codewords_H[version - 1];
             blocks = qr_blocks_H[version - 1];
             break;
     }
 
 #ifndef _MSC_VER
-    int datastream[target_binlen + 1];
+    int datastream[target_codewords + 1];
     int fullstream[qr_total_codewords[version - 1] + 1];
 #else
-    datastream = (int *) _alloca((target_binlen + 1) * sizeof (int));
+    datastream = (int *) _alloca((target_codewords + 1) * sizeof (int));
     fullstream = (int *) _alloca((qr_total_codewords[version - 1] + 1) * sizeof (int));
 #endif
 
-    qr_binary(datastream, version, target_binlen, mode, jisdata, length, gs1, symbol->eci, est_binlen, symbol->debug);
-    add_ecc(fullstream, datastream, version, target_binlen, blocks);
+    qr_binary(datastream, version, target_codewords, mode, jisdata, length, gs1, symbol->eci, est_binlen, symbol->debug);
+    add_ecc(fullstream, datastream, version, target_codewords, blocks, symbol->debug);
 
     size = qr_sizes[version - 1];
 #ifndef _MSC_VER
@@ -1620,7 +1686,7 @@ int qr_code(struct zint_symbol *symbol, const unsigned char source[], size_t len
     }
 
     setup_grid(grid, size, version);
-    populate_grid(grid, size, fullstream, qr_total_codewords[version - 1]);
+    populate_grid(grid, size, size, fullstream, qr_total_codewords[version - 1]);
 
     if (version >= 7) {
         add_version_info(grid, size, version);
@@ -1647,8 +1713,6 @@ int qr_code(struct zint_symbol *symbol, const unsigned char source[], size_t len
     return 0;
 }
 
-/* NOTE: From this point forward concerns Micro QR Code only */
-
 static int micro_qr_intermediate(char binary[], const int jisdata[], const char mode[], const size_t length, int *kanji_used, int *alphanum_used, int *byte_used,const int debug) {
     /* Convert input data to an "intermediate stage" where data is binary encoded but
        control information is not */
@@ -2901,7 +2965,7 @@ int microqr(struct zint_symbol *symbol, const unsigned char source[], size_t len
 /* For UPNQR the symbol size and error correction capacity is fixed */
 int upnqr(struct zint_symbol *symbol, const unsigned char source[], size_t length) {
     int i, j, est_binlen;
-    int ecc_level, version, target_binlen, blocks, size;
+    int ecc_level, version, target_codewords, blocks, size;
     int bitmask, error_number;
 
 #ifndef _MSC_VER
@@ -2958,19 +3022,19 @@ int upnqr(struct zint_symbol *symbol, const unsigned char source[], size_t lengt
 
     version = 15; // 77 x 77
 
-    target_binlen = qr_data_codewords_M[version - 1];
+    target_codewords = qr_data_codewords_M[version - 1];
     blocks = qr_blocks_M[version - 1];
 
 #ifndef _MSC_VER
-    int datastream[target_binlen + 1];
+    int datastream[target_codewords + 1];
     int fullstream[qr_total_codewords[version - 1] + 1];
 #else
-    datastream = (int *) _alloca((target_binlen + 1) * sizeof (int));
+    datastream = (int *) _alloca((target_codewords + 1) * sizeof (int));
     fullstream = (int *) _alloca((qr_total_codewords[version - 1] + 1) * sizeof (int));
 #endif
 
-    qr_binary(datastream, version, target_binlen, mode, jisdata, length, 0, symbol->eci, est_binlen, symbol->debug);
-    add_ecc(fullstream, datastream, version, target_binlen, blocks);
+    qr_binary(datastream, version, target_codewords, mode, jisdata, length, 0, symbol->eci, est_binlen, symbol->debug);
+    add_ecc(fullstream, datastream, version, target_codewords, blocks, symbol->debug);
 
     size = qr_sizes[version - 1];
 #ifndef _MSC_VER
@@ -2986,7 +3050,7 @@ int upnqr(struct zint_symbol *symbol, const unsigned char source[], size_t lengt
     }
 
     setup_grid(grid, size, version);
-    populate_grid(grid, size, fullstream, qr_total_codewords[version - 1]);
+    populate_grid(grid, size, size, fullstream, qr_total_codewords[version - 1]);
 
     add_version_info(grid, size, version);
 
@@ -3009,4 +3073,367 @@ int upnqr(struct zint_symbol *symbol, const unsigned char source[], size_t lengt
     return 0;
 }
 
+static void setup_rmqr_grid(unsigned char* grid,const int h_size,const int v_size,const int version) {
+    int i, j;
+    char alignment[] = {0x1F, 0x11, 0x15, 0x11, 0x1F};
+    int h_version, finder_position;
 
+    /* Add timing patterns - top and bottom */
+    for (i = 0; i < h_size; i++) {
+        if (i % 2) {
+            grid[i] = 0x20;
+            grid[((v_size - 1) * h_size) + i] = 0x20;
+        } else {
+            grid[i] = 0x21;
+            grid[((v_size - 1) * h_size) + i] = 0x21;
+        }
+    }
+
+    /* Add timing patterns - left and right */
+    for (i = 0; i < v_size; i++) {
+        if (i % 2) {
+            grid[i * h_size] = 0x20;
+            grid[(i * h_size) + (h_size - 1)] = 0x20;
+        } else {
+            grid[i * h_size] = 0x21;
+            grid[(i * h_size) + (h_size - 1)] = 0x21;
+        }
+    }
+
+    /* Add finder pattern */
+    place_finder(grid, h_size, 0, 0); // This works because finder is always top left
+
+    /* Add finder sub-pattern to bottom right */
+    for (i = 0; i < 5; i++) {
+        for (j = 0; j < 5; j++) {
+            if (alignment[j] & 0x10 >> i) {
+                grid[((v_size - 5) * h_size) + (h_size * i) + (h_size - 5) + j] = 0x11;
+            } else {
+                grid[((v_size - 5) * h_size) + (h_size * i) + (h_size - 5) + j] = 0x10;
+            }
+        }
+    }
+
+    /* Add corner finder pattern - bottom left */
+    grid[(v_size - 2) * h_size] = 0x11;
+    grid[((v_size - 2) * h_size) + 1] = 0x10;
+    grid[((v_size - 1) * h_size) + 1] = 0x11;
+
+    /* Add corner finder pattern - top right */
+    grid[h_size - 2] = 0x11;
+    grid[(h_size * 2) - 2] = 0x10;
+    grid[(h_size * 2) - 1] = 0x11;
+
+    /* Add seperator */
+    for (i = 0; i < 7; i++) {
+        grid[(i * h_size) + 7] = 0x20;
+    }
+    if (v_size > 7) {
+        // Note for v_size = 9 this overrides the bottom right corner finder pattern
+        for(i = 0; i < 8; i++) {
+            grid[(7 * h_size) + i] = 0x20;
+        }
+    }
+
+    /* Add alignment patterns */
+    if (h_size > 27) {
+        for(i = 0; i < 5; i++) {
+            if (h_size == rmqr_width[i]) {
+                h_version = i;
+            }
+        }
+
+        for(i = 0; i < 4; i++) {
+            finder_position = rmqr_table_d1[(h_version * 4) + i];
+
+            if (finder_position != 0) {
+                for (j = 0; j < v_size; j++) {
+                    if (j % 2) {
+                        grid[(j * h_size) + finder_position] = 0x10;
+                    } else {
+                        grid[(j * h_size) + finder_position] = 0x11;
+                    }
+                }
+
+                // Top square
+                grid[h_size + finder_position - 1] = 0x11;
+                grid[(h_size * 2) + finder_position - 1] = 0x11;
+                grid[h_size + finder_position + 1] = 0x11;
+                grid[(h_size * 2) + finder_position + 1] = 0x11;
+
+                // Bottom square
+                grid[(h_size * (v_size - 3)) + finder_position - 1] = 0x11;
+                grid[(h_size * (v_size - 2)) + finder_position - 1] = 0x11;
+                grid[(h_size * (v_size - 3)) + finder_position + 1] = 0x11;
+                grid[(h_size * (v_size - 2)) + finder_position + 1] = 0x11;
+            }
+        }
+    }
+
+    /* Reserve space for format information */
+    for (i = 0; i < 5; i++) {
+        for (j = 0; j < 3; j++) {
+            grid[(h_size * (i + 1)) + j + 8] = 0x20;
+            grid[(h_size * (v_size - 6)) + (h_size * i) + j + (h_size - 8)] = 0x20;
+        }
+    }
+    grid[(h_size * 1) + 11] = 0x20;
+    grid[(h_size * 2) + 11] = 0x20;
+    grid[(h_size * 3) + 11] = 0x20;
+    grid[(h_size * (v_size - 6)) + (h_size - 5)] = 0x20;
+    grid[(h_size * (v_size - 6)) + (h_size - 4)] = 0x20;
+    grid[(h_size * (v_size - 6)) + (h_size - 3)] = 0x20;
+}
+
+/* rMQR according to 2018 draft standard */
+int rmqr(struct zint_symbol *symbol, const unsigned char source[], size_t length) {
+    int i, j, est_binlen;
+    int ecc_level, autosize, version, max_cw, target_codewords, blocks, h_size, v_size;
+    int gs1;
+    int footprint, best_footprint, format_data;
+    unsigned int left_format_info, right_format_info;
+
+#ifndef _MSC_VER
+    int utfdata[length + 1];
+    int jisdata[length + 1];
+    char mode[length + 1];
+#else
+    int* datastream;
+    int* fullstream;
+    unsigned char* grid;
+    int* utfdata = (int *) _alloca((length + 1) * sizeof (int));
+    int* jisdata = (int *) _alloca((length + 1) * sizeof (int));
+    char* mode = (char *) _alloca(length + 1);
+#endif
+
+    gs1 = (symbol->input_mode == GS1_MODE);
+
+    if ((symbol->input_mode == DATA_MODE) || (symbol->eci != 0)) {
+        for (i = 0; i < length; i++) {
+            jisdata[i] = (int) source[i];
+        }
+    } else {
+        /* Convert Unicode input to Shift-JIS */
+        int error_number = utf8toutf16(symbol, source, utfdata, &length);
+        if (error_number != 0) {
+            return error_number;
+        }
+
+        for (i = 0; i < length; i++) {
+            if (utfdata[i] <= 0xff) {
+                jisdata[i] = utfdata[i];
+            } else {
+                int glyph = 0;
+                j = 0;
+                do {
+                    if (sjis_lookup[j * 2] == utfdata[i]) {
+                        glyph = sjis_lookup[(j * 2) + 1];
+                    }
+                    j++;
+                } while ((j < 6843) && (glyph == 0));
+                if (glyph == 0) {
+                    strcpy(symbol->errtxt, "575: Invalid character in input data");
+                    return ZINT_ERROR_INVALID_DATA;
+                }
+                jisdata[i] = glyph;
+            }
+        }
+    }
+
+    define_mode(mode, jisdata, length, gs1);
+    est_binlen = getBinaryLength(RMQR_VERSION + 31, mode, jisdata, length, gs1, symbol->eci);
+
+    ecc_level = LEVEL_M;
+    max_cw = 152;
+    if (symbol->option_1 == 1) {
+        strcpy(symbol->errtxt, "576: Error correction level L not available in rMQR");
+        return ZINT_ERROR_INVALID_OPTION;
+    }
+
+    if (symbol->option_1 == 3) {
+        strcpy(symbol->errtxt, "577: Error correction level Q not available in rMQR");
+        return ZINT_ERROR_INVALID_OPTION;
+    }
+
+    if (symbol->option_1 == 4) {
+        ecc_level = LEVEL_H;
+        max_cw = 76;
+    }
+
+    if (est_binlen > (8 * max_cw)) {
+        strcpy(symbol->errtxt, "578: Input too long for selected error correction level");
+        return ZINT_ERROR_TOO_LONG;
+    }
+
+    if ((symbol->option_2 < 0) || (symbol->option_2 > 38)) {
+        strcpy(symbol->errtxt, "579: Invalid rMQR symbol size");
+        return ZINT_ERROR_INVALID_OPTION;
+    }
+
+    version = 31; // Set default to keep compiler happy
+
+    if (symbol->option_2 == 0) {
+        // Automatic symbol size
+        autosize = 31;
+        best_footprint = rmqr_height[31] * rmqr_width[31];
+        for (version = 30; version >= 0; version--) {
+            est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, symbol->eci);
+            footprint = rmqr_height[version] * rmqr_width[version];
+            if (ecc_level == LEVEL_M) {
+                if (rmqr_data_codewords_M[version] >= (est_binlen / 8)) {
+                    if (footprint < best_footprint) {
+                        autosize = version;
+                        best_footprint = footprint;
+                    }
+                }
+            } else {
+                if (rmqr_data_codewords_H[version] >= (est_binlen / 8)) {
+                    if (footprint < best_footprint) {
+                        autosize = version;
+                        best_footprint = footprint;
+                    }
+                }
+            }
+        }
+        version = autosize;
+        est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, symbol->eci);
+    }
+
+    if ((symbol->option_2 >= 1) && (symbol->option_2 <= 32)) {
+        // User specified symbol size
+        version = symbol->option_2 - 1;
+    }
+
+    if (symbol->option_2 >= 33) {
+        // User has specified symbol height only
+        version = rmqr_fixed_height_upper_bound[symbol->option_2 - 32];
+        for(i = version - 1; i > rmqr_fixed_height_upper_bound[symbol->option_2 - 33]; i--) {
+            est_binlen = getBinaryLength(RMQR_VERSION + i, mode, jisdata, length, gs1, symbol->eci);
+            if (ecc_level == LEVEL_M) {
+                if (rmqr_data_codewords_M[i] >= (est_binlen / 8)) {
+                    version = i;
+                }
+            } else {
+                if (rmqr_data_codewords_H[i] >= (est_binlen / 8)) {
+                    version = i;
+                }
+            }
+        }
+        est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, symbol->eci);
+    }
+
+    if (symbol->option_1 == -1) {
+        // Detect if there is enough free space to increase ECC level
+        if (est_binlen < (rmqr_data_codewords_H[version] * 8)) {
+            ecc_level = LEVEL_H;
+        }
+    }
+
+    if (ecc_level == LEVEL_M) {
+        target_codewords = rmqr_data_codewords_M[version];
+        blocks = rmqr_blocks_M[version];
+    } else {
+        target_codewords = rmqr_data_codewords_H[version];
+        blocks = rmqr_blocks_H[version];
+    }
+
+    if (est_binlen > (target_codewords * 8)) {
+        // User has selected a symbol too small for the data
+        strcpy(symbol->errtxt, "580: Input too long for selected symbol size");
+        return ZINT_ERROR_TOO_LONG;
+    }
+
+    if (symbol->debug) {
+        printf("Minimum codewords = %d\n", est_binlen / 8);
+        printf("Selected version: %d = R%dx%d-", (version + 1), rmqr_height[version], rmqr_width[version]);
+        if (ecc_level == LEVEL_M) {
+            printf("M\n");
+        } else {
+            printf("H\n");
+        }
+        printf("Number of data codewords in symbol = %d\n", target_codewords);
+        printf("Number of ECC blocks = %d\n", blocks);
+    }
+
+#ifndef _MSC_VER
+    int datastream[target_codewords + 1];
+    int fullstream[rmqr_total_codewords[version] + 1];
+#else
+    datastream = (int *) _alloca((target_codewords + 1) * sizeof (int));
+    fullstream = (int *) _alloca((rmqr_total_codewords[version] + 1) * sizeof (int));
+#endif
+
+    qr_binary(datastream, RMQR_VERSION + version, target_codewords, mode, jisdata, length, gs1, symbol->eci, est_binlen, symbol->debug);
+    add_ecc(fullstream, datastream, RMQR_VERSION + version, target_codewords, blocks, symbol->debug);
+
+    h_size = rmqr_width[version];
+    v_size = rmqr_height[version];
+
+#ifndef _MSC_VER
+    unsigned char grid[h_size * v_size];
+#else
+    grid = (unsigned char *) _alloca((h_size * v_size) * sizeof (unsigned char));
+#endif
+
+    for (i = 0; i < v_size; i++) {
+        for (j = 0; j < h_size; j++) {
+            grid[(i * h_size) + j] = 0;
+        }
+    }
+
+    setup_rmqr_grid(grid, h_size, v_size, version);
+    populate_grid(grid, h_size, v_size, fullstream, rmqr_total_codewords[version]);
+
+    /* apply bitmask */
+    for (i = 0; i < v_size; i++) {
+        for (j = 0; j < h_size; j++) {
+            if ((grid[(i * h_size) + j] & 0xf0) == 0) {
+                // This is a data module
+                if (((i / 2) + (j / 3)) % 2 == 0) { // < This is the data mask from section 7.8.2
+                    // This module needs to be changed
+                    if (grid[(i * h_size) + j] == 0x01) {
+                        grid[(i * h_size) + j] = 0x00;
+                    } else {
+                        grid[(i * h_size) + j] = 0x01;
+                    }
+                }
+            }
+        }
+    }
+
+    /* add format information */
+    format_data = version;
+    if (ecc_level == LEVEL_H) {
+        format_data += 32;
+    }
+    left_format_info = rmqr_format_info_left[format_data];
+    right_format_info = rmqr_format_info_right[format_data];
+
+    for (i = 0; i < 5; i++) {
+        for (j = 0; j < 3; j++) {
+            grid[(h_size * (i + 1)) + j + 8] = (left_format_info >> ((j * 5) + i)) & 0x01;
+            grid[(h_size * (v_size - 6)) + (h_size * i) + j + (h_size - 8)] = (right_format_info >> ((j * 5) + i)) & 0x01;
+        }
+    }
+    grid[(h_size * 1) + 11] = (left_format_info >> 15) & 0x01;
+    grid[(h_size * 2) + 11] = (left_format_info >> 16) & 0x01;
+    grid[(h_size * 3) + 11] = (left_format_info >> 17) & 0x01;
+    grid[(h_size * (v_size - 6)) + (h_size - 5)] = (right_format_info >> 15) & 0x01;
+    grid[(h_size * (v_size - 6)) + (h_size - 4)] = (right_format_info >> 16) & 0x01;
+    grid[(h_size * (v_size - 6)) + (h_size - 3)] = (right_format_info >> 17) & 0x01;
+
+
+    symbol->width = h_size;
+    symbol->rows = v_size;
+
+    for (i = 0; i < v_size; i++) {
+        for (j = 0; j < h_size; j++) {
+            if (grid[(i * h_size) + j] & 0x01) {
+                set_module(symbol, i, j);
+            }
+        }
+        symbol->row_height[i] = 1;
+    }
+
+    return 0;
+}
\ No newline at end of file
diff --git a/backend/qr.h b/backend/qr.h
index c5a23c9e..5f48e53d 100644
--- a/backend/qr.h
+++ b/backend/qr.h
@@ -1,6 +1,5 @@
-/* qr.h Data for QR Code */
+/* qr.h Data for QR Code, Micro QR Code and rMQR
 
-/*
     libzint - the open source barcode library
     Copyright (C) 2008-2017 Robin Stuart <rstuart114@gmail.com>
     Copyright (C) 2006 Kentaro Fukuchi <fukuchi@megaui.net>
@@ -38,6 +37,8 @@
 
 #define RHODIUM "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"
 
+#define RMQR_VERSION    100
+
 /* From ISO/IEC 18004:2006 Table 7 */
 static const unsigned short int qr_data_codewords_L[] = {
     19, 34, 55, 80, 108, 136, 156, 194, 232, 274, 324, 370, 428, 461, 523, 589, 647,
@@ -69,6 +70,92 @@ static const unsigned short int qr_total_codewords[] = {
     2185, 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706
 };
 
+static const unsigned short int rmqr_height[] = {
+    7, 7, 7, 7, 7,
+    9, 9, 9, 9, 9,
+    11, 11, 11, 11, 11, 11,
+    13, 13, 13, 13, 13, 13,
+    15, 15, 15, 15, 15,
+    17, 17, 17, 17, 17
+};
+
+static const unsigned short int rmqr_width[] = {
+    43, 59, 77, 99, 139,
+    43, 59, 77, 99, 139,
+    27, 43, 59, 77, 99, 139,
+    27, 43, 59, 77, 99, 139,
+    43, 59, 77, 99, 139,
+    43, 59, 77, 99, 139
+};
+
+static const unsigned short int rmqr_data_codewords_M[] = {
+    6, 12, 20, 28, 44, // R7x
+    12, 21, 31, 42, 63, // R9x
+    7, 19, 31, 43, 57, 84, // R11x
+    12, 27, 38, 53, 73, 106, // R13x
+    33, 48, 67, 88, 127, // R15x
+    39, 56, 78, 100, 152 // R17x
+};
+
+static const unsigned short int rmqr_data_codewords_H[] = {
+    3, 7, 10, 14, 24, // R7x
+    7, 11, 17, 22, 33, // R9x
+    5, 11, 15, 23, 29, 42, // R11x
+    7, 13, 20, 29, 35, 54, // R13x
+    15, 26, 31, 48, 69, // R15x
+    21, 28, 38, 56, 76 // R17x
+};
+
+static const short int rmqr_fixed_height_upper_bound[] = {
+    -1, 4, 9, 15, 21, 26, 31
+};
+
+static const unsigned short int rmqr_total_codewords[] = {
+    13, 21, 32, 44, 68, // R7x
+    21, 33, 49, 66, 99, // R9x
+    15, 31, 47, 67, 89, 132, // R11x
+    21, 41, 60, 85, 113, 166, // R13x
+    51, 74, 103, 136, 199, // R15x
+    61, 88, 122, 160, 232 // R17x
+};
+
+
+static const unsigned short int rmqr_numeric_cci[] = {
+    4, 5, 6, 7, 7,
+    5, 6, 7, 7, 8,
+    5, 6, 7, 7, 8, 8,
+    5, 7, 7, 8, 8, 8,
+    7, 7, 8, 8, 9,
+    7, 8, 8, 8, 9
+};
+
+static const unsigned short int rmqr_alphanum_cci[] = {
+    4, 5, 5, 6, 6,
+    5, 5, 6, 6, 7,
+    4, 5, 6, 6, 7, 7,
+    5, 6, 6, 7, 7, 8,
+    6, 7, 7, 7, 8,
+    6, 7, 7, 8, 8
+};
+
+static const unsigned short int rmqr_byte_cci[] = {
+    3, 4, 5, 5, 6,
+    4, 5, 5, 6, 6,
+    3, 5, 5, 6, 6, 7,
+    4, 5, 6, 6, 7, 7,
+    6, 6, 7, 7, 7,
+    6, 6, 7, 7, 8
+};
+
+static const unsigned short int rmqr_kanji_cci[] = {
+    2, 3, 4, 5, 5,
+    3, 4, 5, 5, 6,
+    2, 4, 5, 5, 6, 6,
+    3, 5, 5, 6, 6, 7,
+    5, 5, 6, 6, 7,
+    5, 6, 6, 6, 7
+};
+
 static const char qr_blocks_L[] = {
     1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12,
     12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25
@@ -89,6 +176,24 @@ static const char qr_blocks_H[] = {
     32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81
 };
 
+static const char rmqr_blocks_M[] = {
+    1, 1, 1, 1, 1, // R7x
+    1, 1, 1, 1, 2, // R9x
+    1, 1, 1, 1, 2, 2, // R11x
+    1, 1, 1, 2, 2, 3, // R13x
+    1, 1, 2, 2, 3, // R15x
+    1, 2, 2, 3, 4 // R17x
+};
+
+static const char rmqr_blocks_H[] = {
+    1, 1, 1, 1, 2, // R7x
+    1, 1, 2, 2, 3, // R9x
+    1, 1, 2, 2, 2, 3, // R11x
+    1, 1, 2, 2, 3, 4, // R13x
+    2, 2, 3, 4, 5, // R15x
+    2, 2, 3, 4, 6 // R17x
+};
+
 static const unsigned short int qr_sizes[] = {
     21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97,
     101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177
@@ -102,6 +207,7 @@ static const char qr_align_loopsize[] = {
     0, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7
 };
 
+// Table E1 - Row/column coordinates of center module of alignment patterns
 static const unsigned short int qr_table_e1[] = {
     6, 18, 0, 0, 0, 0, 0,
     6, 22, 0, 0, 0, 0, 0,
@@ -144,6 +250,15 @@ static const unsigned short int qr_table_e1[] = {
     6, 30, 58, 86, 114, 142, 170
 };
 
+// Table D1 - Column coordinates of centre module of alignment patterns
+static const unsigned short int rmqr_table_d1[] = {
+    21, 0, 0, 0,
+    19, 39, 0, 0,
+    25, 51, 0, 0,
+    23, 49, 75, 0,
+    27, 55, 83, 111
+};
+
 static const unsigned int qr_annex_c[] = {
     /* Format information bit sequences */
     0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, 0x77c4, 0x72f3, 0x7daa, 0x789d,
@@ -165,3 +280,25 @@ static const unsigned int qr_annex_c1[] = {
     0x7c16, 0x7921, 0x06de, 0x03e9, 0x0cb0, 0x0987, 0x1735, 0x1202, 0x1d5b, 0x186c, 0x2508, 0x203f, 0x2f66, 0x2a51, 0x34e3,
     0x31d4, 0x3e8d, 0x3bba
 };
+
+static const unsigned int rmqr_format_info_left[] = {
+    /* rMQR format information for finder pattern side */
+    0x1FAB2, 0x1E597, 0x1DBDD, 0x1C4F8, 0x1B86C, 0x1A749, 0x19903, 0x18626, 0x17F0E, 0x1602B,
+    0x15E61, 0x14144, 0x13DD0, 0x122F5, 0x11CBF, 0x1039A, 0x0F1CA, 0x0EEEF, 0x0D0A5, 0x0CF80,
+    0x0B314, 0x0AC31, 0x0927B, 0x08D5E, 0x07476, 0x06B53, 0x05519, 0x04A3C, 0x036A8, 0x0298D,
+    0x017C7, 0x008E2, 0x3F367, 0x3EC42, 0x3D208, 0x3CD2D, 0x3B1B9, 0x3AE9C, 0x390D6, 0x38FF3,
+    0x376DB, 0x369FE, 0x357B4, 0x34891, 0x33405, 0x32B20, 0x3156A, 0x30A4F, 0x2F81F, 0x2E73A,
+    0x2D970, 0x2C655, 0x2BAC1, 0x2A5E4, 0x29BAE, 0x2848B, 0x27DA3, 0x26286, 0x25CCC, 0x243E9,
+    0x23F7D, 0x22058, 0x21E12, 0x20137
+};
+
+static const unsigned int rmqr_format_info_right[] = {
+    /* rMQR format information for subfinder pattern side */
+    0x20A7B, 0x2155E, 0x22B14, 0x23431, 0x248A5, 0x25780, 0x269CA, 0x276EF, 0x28FC7, 0x290E2,
+    0x2AEA8, 0x2B18D, 0x2CD19, 0x2D23C, 0x2EC76, 0x2F353, 0x30103, 0x31E26, 0x3206C, 0x33F49,
+    0x343DD, 0x35CF8, 0x362B2, 0x37D97, 0x384BF, 0x39B9A, 0x3A5D0, 0x3BAF5, 0x3C661, 0x3D944,
+    0x3E70E, 0x3F82B, 0x003AE, 0x01C8B, 0x022C1, 0x03DE4, 0x04170, 0x05E55, 0x0601F, 0x07F3A,
+    0x08612, 0x09937, 0x0A77D, 0x0B858, 0x0C4CC, 0x0DBE9, 0x0E5A3, 0x0FA86, 0x108D6, 0x117F3,
+    0x129B9, 0x1369C, 0x14A08, 0x1552D, 0x16B67, 0x17442, 0x18D6A, 0x1924F, 0x1AC05, 0x1B320,
+    0x1CFB4, 0x1D091, 0x1EEDB, 0x1F1FE
+};
\ No newline at end of file
diff --git a/backend/svg.c b/backend/svg.c
index 6cde4635..cbba33e9 100644
--- a/backend/svg.c
+++ b/backend/svg.c
@@ -104,7 +104,7 @@ int svg_plot(struct zint_symbol *symbol) {
 
     int html_len = strlen((char *)symbol->text) + 1;
 
-    for (0; i < strlen((char *)symbol->text); i++) {
+    for (i = 0; i < strlen((char *)symbol->text); i++) {
         switch(symbol->text[i]) {
             case '>':
             case '<':
diff --git a/backend/zint.h b/backend/zint.h
index fc4e41a3..4cb052db 100644
--- a/backend/zint.h
+++ b/backend/zint.h
@@ -1,7 +1,7 @@
 /*  zint.h - definitions for libzint
 
     libzint - the open source barcode library
-    Copyright (C) 2009-2018 Robin Stuart <rstuart114@gmail.com>
+    Copyright (C) 2009-2019 Robin Stuart <rstuart114@gmail.com>
 
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions
@@ -40,7 +40,7 @@ extern "C" {
         float x, y, length, width;
         struct zint_render_line *next; /* Pointer to next line */
     };
-    
+
     struct zint_vector_rect {
         float x, y, height, width;
         int colour;
@@ -54,7 +54,7 @@ extern "C" {
         unsigned char *text;
         struct zint_render_string *next; /* Pointer to next character */
     };
-    
+
     struct zint_vector_string {
         float x, y, fsize;
         float width; /* Suggested string width, may be 0 if none recommended */
@@ -73,7 +73,7 @@ extern "C" {
         int colour;
         struct zint_vector_circle *next; /* Pointer to next circle */
     };
-    
+
     struct zint_render_hexagon {
         float x, y, height;
         struct zint_render_hexagon *next; /* Pointer to next hexagon */
@@ -83,7 +83,7 @@ extern "C" {
         float x, y, diameter;
         struct zint_vector_hexagon *next; /* Pointer to next hexagon */
     };
-    
+
     struct zint_render {
         float width, height;
         struct zint_render_line *lines; /* Pointer to first line */
@@ -91,7 +91,7 @@ extern "C" {
         struct zint_render_ring *rings; /* Pointer to first ring */
         struct zint_render_hexagon *hexagons; /* Pointer to first hexagon */
     };
-    
+
     struct zint_vector {
         float width, height;
         struct zint_vector_rect *rectangles; /* Pointer to first rectangle */
@@ -139,154 +139,155 @@ extern "C" {
 #define ZINT_VERSION_RELEASE    7
 
     /* Tbarcode 7 codes */
-#define BARCODE_CODE11		1
-#define BARCODE_C25MATRIX	2
-#define BARCODE_C25INTER	3
-#define BARCODE_C25IATA		4
-#define BARCODE_C25LOGIC	6
-#define BARCODE_C25IND		7
-#define BARCODE_CODE39		8
-#define BARCODE_EXCODE39	9
-#define BARCODE_EANX		13
+#define BARCODE_CODE11          1
+#define BARCODE_C25MATRIX       2
+#define BARCODE_C25INTER        3
+#define BARCODE_C25IATA         4
+#define BARCODE_C25LOGIC        6
+#define BARCODE_C25IND          7
+#define BARCODE_CODE39          8
+#define BARCODE_EXCODE39        9
+#define BARCODE_EANX            13
 #define BARCODE_EANX_CHK        14
-#define BARCODE_EAN128		16
-#define BARCODE_CODABAR		18
-#define BARCODE_CODE128		20
-#define BARCODE_DPLEIT		21
-#define BARCODE_DPIDENT		22
-#define BARCODE_CODE16K		23
-#define BARCODE_CODE49		24
-#define BARCODE_CODE93		25
-#define BARCODE_FLAT		28
-#define BARCODE_RSS14		29
-#define BARCODE_RSS_LTD		30
-#define BARCODE_RSS_EXP		31
-#define BARCODE_TELEPEN		32
-#define BARCODE_UPCA		34
+#define BARCODE_EAN128          16
+#define BARCODE_CODABAR         18
+#define BARCODE_CODE128         20
+#define BARCODE_DPLEIT          21
+#define BARCODE_DPIDENT         22
+#define BARCODE_CODE16K         23
+#define BARCODE_CODE49          24
+#define BARCODE_CODE93          25
+#define BARCODE_FLAT            28
+#define BARCODE_RSS14           29
+#define BARCODE_RSS_LTD         30
+#define BARCODE_RSS_EXP         31
+#define BARCODE_TELEPEN         32
+#define BARCODE_UPCA            34
 #define BARCODE_UPCA_CHK        35
-#define BARCODE_UPCE		37
+#define BARCODE_UPCE            37
 #define BARCODE_UPCE_CHK        38
-#define BARCODE_POSTNET		40
-#define BARCODE_MSI_PLESSEY	47
-#define BARCODE_FIM		49
-#define BARCODE_LOGMARS		50
-#define BARCODE_PHARMA		51
-#define BARCODE_PZN		52
-#define BARCODE_PHARMA_TWO	53
-#define BARCODE_PDF417		55
-#define BARCODE_PDF417TRUNC	56
-#define BARCODE_MAXICODE	57
-#define BARCODE_QRCODE		58
-#define BARCODE_CODE128B	60
-#define BARCODE_AUSPOST		63
-#define BARCODE_AUSREPLY	66
-#define BARCODE_AUSROUTE	67
-#define BARCODE_AUSREDIRECT	68
-#define BARCODE_ISBNX		69
-#define BARCODE_RM4SCC		70
-#define BARCODE_DATAMATRIX	71
-#define BARCODE_EAN14		72
+#define BARCODE_POSTNET         40
+#define BARCODE_MSI_PLESSEY     47
+#define BARCODE_FIM             49
+#define BARCODE_LOGMARS         50
+#define BARCODE_PHARMA          51
+#define BARCODE_PZN             52
+#define BARCODE_PHARMA_TWO      53
+#define BARCODE_PDF417          55
+#define BARCODE_PDF417TRUNC     56
+#define BARCODE_MAXICODE        57
+#define BARCODE_QRCODE          58
+#define BARCODE_CODE128B        60
+#define BARCODE_AUSPOST         63
+#define BARCODE_AUSREPLY        66
+#define BARCODE_AUSROUTE        67
+#define BARCODE_AUSREDIRECT     68
+#define BARCODE_ISBNX           69
+#define BARCODE_RM4SCC          70
+#define BARCODE_DATAMATRIX      71
+#define BARCODE_EAN14           72
 #define BARCODE_VIN             73
-#define BARCODE_CODABLOCKF	74
-#define BARCODE_NVE18		75
-#define BARCODE_JAPANPOST	76
-#define BARCODE_KOREAPOST	77
-#define BARCODE_RSS14STACK	79
-#define BARCODE_RSS14STACK_OMNI	80
-#define BARCODE_RSS_EXPSTACK	81
-#define BARCODE_PLANET		82
-#define BARCODE_MICROPDF417	84
-#define BARCODE_ONECODE		85
-#define BARCODE_PLESSEY		86
+#define BARCODE_CODABLOCKF      74
+#define BARCODE_NVE18           75
+#define BARCODE_JAPANPOST       76
+#define BARCODE_KOREAPOST       77
+#define BARCODE_RSS14STACK      79
+#define BARCODE_RSS14STACK_OMNI 80
+#define BARCODE_RSS_EXPSTACK    81
+#define BARCODE_PLANET          82
+#define BARCODE_MICROPDF417     84
+#define BARCODE_ONECODE         85
+#define BARCODE_PLESSEY         86
 
     /* Tbarcode 8 codes */
-#define BARCODE_TELEPEN_NUM	87
-#define BARCODE_ITF14		89
-#define BARCODE_KIX		90
-#define BARCODE_AZTEC		92
-#define BARCODE_DAFT		93
-#define BARCODE_MICROQR		97
+#define BARCODE_TELEPEN_NUM     87
+#define BARCODE_ITF14           89
+#define BARCODE_KIX             90
+#define BARCODE_AZTEC           92
+#define BARCODE_DAFT            93
+#define BARCODE_MICROQR         97
 
     /* Tbarcode 9 codes */
-#define BARCODE_HIBC_128	98
-#define BARCODE_HIBC_39		99
-#define BARCODE_HIBC_DM		102
-#define BARCODE_HIBC_QR		104
-#define BARCODE_HIBC_PDF	106
-#define BARCODE_HIBC_MICPDF	108
-#define BARCODE_HIBC_BLOCKF	110
-#define BARCODE_HIBC_AZTEC	112
+#define BARCODE_HIBC_128        98
+#define BARCODE_HIBC_39         99
+#define BARCODE_HIBC_DM         102
+#define BARCODE_HIBC_QR         104
+#define BARCODE_HIBC_PDF        106
+#define BARCODE_HIBC_MICPDF     108
+#define BARCODE_HIBC_BLOCKF     110
+#define BARCODE_HIBC_AZTEC      112
 
     /* Tbarcode 10 codes */
 #define BARCODE_DOTCODE         115
 #define BARCODE_HANXIN          116
-    
+
     /*Tbarcode 11 codes*/
 #define BARCODE_MAILMARK        121
 
     /* Zint specific */
-#define BARCODE_AZRUNE		128
-#define BARCODE_CODE32		129
-#define BARCODE_EANX_CC		130
-#define BARCODE_EAN128_CC	131
-#define BARCODE_RSS14_CC	132
-#define BARCODE_RSS_LTD_CC	133
-#define BARCODE_RSS_EXP_CC	134
-#define BARCODE_UPCA_CC		135
-#define BARCODE_UPCE_CC		136
-#define BARCODE_RSS14STACK_CC	137
-#define BARCODE_RSS14_OMNI_CC	138
-#define BARCODE_RSS_EXPSTACK_CC	139
-#define BARCODE_CHANNEL		140
-#define BARCODE_CODEONE		141
-#define BARCODE_GRIDMATRIX	142
+#define BARCODE_AZRUNE          128
+#define BARCODE_CODE32          129
+#define BARCODE_EANX_CC         130
+#define BARCODE_EAN128_CC       131
+#define BARCODE_RSS14_CC        132
+#define BARCODE_RSS_LTD_CC      133
+#define BARCODE_RSS_EXP_CC      134
+#define BARCODE_UPCA_CC         135
+#define BARCODE_UPCE_CC         136
+#define BARCODE_RSS14STACK_CC   137
+#define BARCODE_RSS14_OMNI_CC   138
+#define BARCODE_RSS_EXPSTACK_CC 139
+#define BARCODE_CHANNEL         140
+#define BARCODE_CODEONE         141
+#define BARCODE_GRIDMATRIX      142
 #define BARCODE_UPNQR           143
-#define BARCODE_ULTRA       144
+#define BARCODE_ULTRA           144
+#define BARCODE_RMQR            145
 
 // Output options
-#define BARCODE_NO_ASCII	1
-#define BARCODE_BIND		2
-#define BARCODE_BOX		4
-#define BARCODE_STDOUT		8
-#define READER_INIT		16
-#define SMALL_TEXT		32
+#define BARCODE_NO_ASCII        1
+#define BARCODE_BIND            2
+#define BARCODE_BOX             4
+#define BARCODE_STDOUT          8
+#define READER_INIT             16
+#define SMALL_TEXT              32
 #define BOLD_TEXT               64
 #define CMYK_COLOUR             128
 #define BARCODE_DOTTY_MODE      256
 #define GS1_GS_SEPARATOR        512
 
 // Input data types
-#define DATA_MODE	0
-#define UNICODE_MODE	1
-#define GS1_MODE	2
-#define ESCAPE_MODE     8
+#define DATA_MODE               0
+#define UNICODE_MODE            1
+#define GS1_MODE                2
+#define ESCAPE_MODE             8
 
 // Data Matrix specific options
-#define DM_SQUARE	100
-#define DM_DMRE	        101
+#define DM_SQUARE               100
+#define DM_DMRE                 101
 
 // Warning and error conditions
-#define ZINT_WARN_INVALID_OPTION	2
+#define ZINT_WARN_INVALID_OPTION        2
 #define ZINT_WARN_USES_ECI              3
-#define ZINT_ERROR_TOO_LONG		5
+#define ZINT_ERROR_TOO_LONG             5
 #define ZINT_ERROR_INVALID_DATA	        6
-#define ZINT_ERROR_INVALID_CHECK	7
-#define ZINT_ERROR_INVALID_OPTION	8
-#define ZINT_ERROR_ENCODING_PROBLEM	9
-#define ZINT_ERROR_FILE_ACCESS	        10
-#define ZINT_ERROR_MEMORY		11
+#define ZINT_ERROR_INVALID_CHECK        7
+#define ZINT_ERROR_INVALID_OPTION       8
+#define ZINT_ERROR_ENCODING_PROBLEM     9
+#define ZINT_ERROR_FILE_ACCESS          10
+#define ZINT_ERROR_MEMORY               11
 
 // Raster file types
-#define OUT_BUFFER          0
-#define OUT_SVG_FILE        10
-#define OUT_EPS_FILE        20
-#define OUT_EMF_FILE        30
-#define	OUT_PNG_FILE        100
-#define	OUT_BMP_FILE        120
-#define OUT_GIF_FILE        140
-#define OUT_PCX_FILE        160
-#define OUT_JPG_FILE        180
-#define OUT_TIF_FILE        200
+#define OUT_BUFFER              0
+#define OUT_SVG_FILE            10
+#define OUT_EPS_FILE            20
+#define OUT_EMF_FILE            30
+#define OUT_PNG_FILE            100
+#define OUT_BMP_FILE            120
+#define OUT_GIF_FILE            140
+#define OUT_PCX_FILE            160
+#define OUT_JPG_FILE            180
+#define OUT_TIF_FILE            200
 
 #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_MSC_VER)
 #if defined (DLL_EXPORT) || defined(PIC) || defined(_USRDLL)
diff --git a/frontend/main.c b/frontend/main.c
index 33dcdad5..bbda6326 100644
--- a/frontend/main.c
+++ b/frontend/main.c
@@ -67,7 +67,7 @@ void types(void) {
             "40: Postnet           86: UK Plessey              141: Code One\n"
             "47: MSI Plessey       87: Telepen Numeric         142: Grid Matrix\n"
             "49: FIM               89: ITF-14                  143: UPNQR\n"
-            "50: Logmars           90: KIX Code\n"
+            "50: Logmars           90: KIX Code                145: rMQR\n"
             );
 }
 
@@ -326,7 +326,7 @@ int batch_process(struct zint_symbol *symbol, char *filename, int mirror_mode, c
                                 output_file[o] = buffer[i];
                         }
                     }
-                    
+
                     // Skip escape characters
                     if ((buffer[i] == 0x5c) && (symbol->input_mode & ESCAPE_MODE)) {
                         i++;
@@ -712,9 +712,9 @@ int main(int argc, char **argv) {
                             fprintf(stderr, "%s\n", my_symbol->errtxt);
                             fflush(stderr);
                     }
-                    if (error_number < 5) {    
+                    if (error_number < 5) {
                         error_number = ZBarcode_Print(my_symbol, rotate_angle);
-                        
+
                         if (error_number != 0) {
                             fprintf(stderr, "%s\n", my_symbol->errtxt);
                             fflush(stderr);