File nand_grading_support.patch of Package libdmtx

diff --git a/dmtx.h b/dmtx.h
index 7651c1e..0d236e2 100644
--- a/dmtx.h
+++ b/dmtx.h
@@ -528,6 +528,36 @@ typedef struct DmtxQuadruplet_struct {
    unsigned char   value[4];
 } DmtxQuadruplet;
 
+typedef struct DmtxDecodeErrorsInfo_struct {
+   int errors[10];
+   int maxCorrectableErrors[10];
+   int checkedBlocks;
+   int totalBlocks;
+   DmtxBoolean readError;
+} DmtxDecodeErrorsInfo;
+
+typedef struct DmtxDecodeStructureInfo_struct {
+   int codeModulesX;
+   int codeModulesY;
+   int fixedXSize;
+   int fixedYSize;
+   int* fixedElementsXs;
+   int* fixedElementsYs;
+   long* structureModules;
+   long* structureFixedModules;
+   long* structureSymbols;
+   long* structureSegments;
+   long* structureBlocks;
+   long* structureParityData;
+   int structureSize;
+   long* helperInverseStructure;
+} DmtxDecodeStructureInfo;
+
+typedef struct DmtxExtractedCodeInfo_struct {
+   DmtxDecodeErrorsInfo errors;
+   DmtxDecodeStructureInfo structure;
+} DmtxExtractedCodeInfo;
+
 /* dmtxtime.c */
 extern DmtxTime dmtxTimeNow(void);
 extern DmtxTime dmtxTimeAdd(DmtxTime t, long msec);
@@ -549,9 +579,16 @@ extern int dmtxDecodeGetProp(DmtxDecode *dec, int prop);
 extern /*@exposed@*/ unsigned char *dmtxDecodeGetCache(DmtxDecode *dec, int x, int y);
 extern DmtxPassFail dmtxDecodeGetPixelValue(DmtxDecode *dec, int x, int y, int channel, /*@out@*/ int *value);
 extern DmtxMessage *dmtxDecodeMatrixRegion(DmtxDecode *dec, DmtxRegion *reg, int fix);
+extern DmtxMessage *dmtxDecodeMatrixRegion2(DmtxDecode *dec, DmtxRegion *reg, int fix, DmtxExtractedCodeInfo* infoOut);
 extern DmtxMessage *dmtxDecodePopulatedArray(int sizeIdx, DmtxMessage *msg, int fix);
+extern DmtxMessage *dmtxDecodePopulatedArray2(int sizeIdx, DmtxMessage *msg, int fix, DmtxExtractedCodeInfo* infoOut);
 extern DmtxMessage *dmtxDecodeMosaicRegion(DmtxDecode *dec, DmtxRegion *reg, int fix);
 extern unsigned char *dmtxDecodeCreateDiagnostic(DmtxDecode *dec, /*@out@*/ int *totalBytes, /*@out@*/ int *headerBytes, int style);
+extern float dmtxGetUEC(const DmtxDecodeErrorsInfo* info);
+extern int dmtxFindTotalErrors(const DmtxDecodeErrorsInfo* info);
+extern int dmtxIsValidResult(const DmtxDecodeErrorsInfo* info);
+extern DmtxExtractedCodeInfo* dmtxExtractedCodeInfoCreate(const DmtxRegion *reg);
+extern DmtxPassFail dmtxExtractedCodeInfoDestroy(DmtxExtractedCodeInfo **info);
 
 /* dmtxregion.c */
 extern DmtxRegion *dmtxRegionCreate(DmtxRegion *reg);
diff --git a/dmtxdecode.c b/dmtxdecode.c
index 567d101..5eeda09 100644
--- a/dmtxdecode.c
+++ b/dmtxdecode.c
@@ -328,7 +328,7 @@ CacheFillQuad(DmtxDecode *dec, DmtxPixelLoc p0, DmtxPixelLoc p1, DmtxPixelLoc p2
  * \return Decoded message
  */
 extern DmtxMessage *
-dmtxDecodeMatrixRegion(DmtxDecode *dec, DmtxRegion *reg, int fix)
+dmtxDecodeMatrixRegion2(DmtxDecode *dec, DmtxRegion *reg, int fix, DmtxExtractedCodeInfo* infoOut)
 {
    //fprintf(stdout, "libdmtx::dmtxDecodeMatrixRegion()\n");
    DmtxMessage *msg;
@@ -339,7 +339,7 @@ dmtxDecodeMatrixRegion(DmtxDecode *dec, DmtxRegion *reg, int fix)
    if(msg == NULL)
       return NULL;
 
-   if(PopulateArrayFromMatrix(dec, reg, msg) != DmtxPass) {
+   if(PopulateArrayFromMatrix(dec, reg, msg, ((infoOut) ? &infoOut->structure : NULL)) != DmtxPass) {
       dmtxMessageDestroy(&msg);
       return NULL;
    }
@@ -365,7 +365,13 @@ dmtxDecodeMatrixRegion(DmtxDecode *dec, DmtxRegion *reg, int fix)
 
    CacheFillQuad(dec, pxTopLeft, pxTopRight, pxBottomRight, pxBottomLeft);
 
-   return dmtxDecodePopulatedArray(reg->sizeIdx, msg, fix);
+   return dmtxDecodePopulatedArray2(reg->sizeIdx, msg, fix, infoOut);
+}
+
+extern DmtxMessage *
+dmtxDecodeMatrixRegion(DmtxDecode *dec, DmtxRegion *reg, int fix)
+{
+   return dmtxDecodeMatrixRegion2(dec, reg, fix, NULL);
 }
 
 /**
@@ -379,7 +385,7 @@ dmtxDecodeMatrixRegion(DmtxDecode *dec, DmtxRegion *reg, int fix)
  *       ex: msg = dmtxDecodePopulatedArray(sizeidx, msg, fix);
  */
 DmtxMessage *
-dmtxDecodePopulatedArray(int sizeIdx, DmtxMessage *msg, int fix)
+dmtxDecodePopulatedArray2(int sizeIdx, DmtxMessage *msg, int fix, DmtxExtractedCodeInfo* infoOut)
 {
    /*
     * Example msg->array indices for a 12x12 datamatrix.
@@ -399,10 +405,11 @@ dmtxDecodePopulatedArray(int sizeIdx, DmtxMessage *msg, int fix)
     * XX XX XX XX XX XX XX XX XX XX XX XX
     *
     */
-    
-   ModulePlacementEcc200(msg->array, msg->code, sizeIdx, DmtxModuleOnRed | DmtxModuleOnGreen | DmtxModuleOnBlue);
 
-   if(RsDecode(msg->code, sizeIdx, fix) == DmtxFail){
+   ModulePlacementEcc200(msg->array, msg->code, sizeIdx, DmtxModuleOnRed | DmtxModuleOnGreen | DmtxModuleOnBlue,
+                         ((infoOut) ? &infoOut->structure : NULL));
+
+   if(RsDecode(msg->code, sizeIdx, infoOut) == DmtxFail && infoOut == NULL){
       dmtxMessageDestroy(&msg);
       msg = NULL;
       return NULL;
@@ -417,6 +424,12 @@ dmtxDecodePopulatedArray(int sizeIdx, DmtxMessage *msg, int fix)
    return msg;
 }
 
+DmtxMessage *
+dmtxDecodePopulatedArray(int sizeIdx, DmtxMessage *msg, int fix)
+{
+   return dmtxDecodePopulatedArray2(sizeIdx, msg, fix, NULL);
+}
+
 /**
  * \brief  Convert fitted Data Mosaic region into a decoded message
  * \param  dec
@@ -693,7 +706,7 @@ TallyModuleJumps(DmtxDecode *dec, DmtxRegion *reg, int tally[][24], int xOrigin,
  * \return DmtxPass | DmtxFail
  */
 static DmtxPassFail
-PopulateArrayFromMatrix(DmtxDecode *dec, DmtxRegion *reg, DmtxMessage *msg)
+PopulateArrayFromMatrix(DmtxDecode *dec, DmtxRegion *reg, DmtxMessage *msg, DmtxDecodeStructureInfo* structureInfoOut)
 {
    //fprintf(stdout, "libdmtx::PopulateArrayFromMatrix()\n");
    int weightFactor;
@@ -704,6 +717,7 @@ PopulateArrayFromMatrix(DmtxDecode *dec, DmtxRegion *reg, DmtxMessage *msg)
    int mapCol, mapRow;
    int colTmp, rowTmp, idx;
    int tally[24][24]; /* Large enough to map largest single region */
+   int regionMarker = 0;
 
 /* memset(msg->array, 0x00, msg->arraySize); */
 
@@ -745,12 +759,22 @@ PopulateArrayFromMatrix(DmtxDecode *dec, DmtxRegion *reg, DmtxMessage *msg)
       /* Y location of mapping region origin in symbol coordinates */
       yOrigin = yRegionCount * (mapHeight + 2) + 1;
 
+      if (structureInfoOut && structureInfoOut->fixedElementsYs) {
+         structureInfoOut->fixedElementsYs[yRegionCount * 2] = yOrigin - 1;
+         structureInfoOut->fixedElementsYs[yRegionCount * 2 + 1] = yOrigin + mapHeight;
+      }
+
       for(xRegionCount = 0; xRegionCount < xRegionTotal; xRegionCount++) {
 
          /* X location of mapping region origin in symbol coordinates */
          xOrigin = xRegionCount * (mapWidth + 2) + 1;
          //fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::xOrigin: %d\n", xOrigin);
 
+         if (structureInfoOut && structureInfoOut->fixedElementsXs) {
+            structureInfoOut->fixedElementsXs[xRegionCount * 2] = xOrigin - 1;
+            structureInfoOut->fixedElementsXs[xRegionCount * 2 + 1] = xOrigin + mapWidth;
+         }
+
          memset(tally, 0x00, 24 * 24 * sizeof(int));
          TallyModuleJumps(dec, reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirUp);
          TallyModuleJumps(dec, reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirLeft);
@@ -770,18 +794,211 @@ PopulateArrayFromMatrix(DmtxDecode *dec, DmtxRegion *reg, DmtxMessage *msg)
                //fprintf(stdout, "%c ",tally[mapRow][mapCol]==DmtxModuleOff ? 'X' : ' ');
                if(tally[mapRow][mapCol]/(double)weightFactor >= 0.5){
                   msg->array[idx] = DmtxModuleOnRGB;
+                  if (structureInfoOut && structureInfoOut->structureModules) {
+                     structureInfoOut->structureModules[idx] = 1;
+                  }
                   //fprintf(stdout, "X ");
                } else {
                   msg->array[idx] = DmtxModuleOff;
+                  if (structureInfoOut && structureInfoOut->structureModules) {
+                     structureInfoOut->structureModules[idx] = 0;
+                  }
                   //fprintf(stdout, "  ");
                }
 
                msg->array[idx] |= DmtxModuleAssigned;
+
+               if (structureInfoOut && structureInfoOut->structureSegments) {
+                  structureInfoOut->structureSegments[idx] = regionMarker;
+               }
             }
             //fprintf(stdout, "\n");
          }
+         ++regionMarker;
       }
    }
 
    return DmtxPass;
 }
+
+extern float
+dmtxGetUEC(const DmtxDecodeErrorsInfo* info)
+{
+   float minUEC = 1.0;
+
+   if (info->checkedBlocks != info->totalBlocks || info->readError == DmtxTrue)
+      return 0.0;
+
+   for (int i = 0; i < info->checkedBlocks; ++i)
+   {
+      float blockUEC;
+
+      if (info->errors[i] > info->maxCorrectableErrors[i])
+      {
+         minUEC = 0.0;
+         break;
+      }
+
+      blockUEC = 1.0 - (float)info->errors[i] / info->maxCorrectableErrors[i];
+      if (blockUEC < minUEC)
+         minUEC = blockUEC;
+   }
+
+   return minUEC;
+}
+
+extern int
+dmtxFindTotalErrors(const DmtxDecodeErrorsInfo* info)
+{
+   int totalErrors = 0;
+
+   for (int i = 0; i < info->checkedBlocks; ++i)
+      totalErrors += info->errors[i];
+
+   return totalErrors;
+}
+
+extern int
+dmtxIsValidResult(const DmtxDecodeErrorsInfo* info)
+{
+   if (info->checkedBlocks != info->totalBlocks || info->readError == DmtxTrue)
+      return 0;
+
+   for (int i = 0; i < info->checkedBlocks; ++i)
+      if (info->errors[i] > info->maxCorrectableErrors[i])
+         return 0;
+
+   return 1;
+}
+
+extern DmtxExtractedCodeInfo*
+dmtxExtractedCodeInfoCreate(const DmtxRegion *reg)
+{
+   DmtxExtractedCodeInfo *info;
+   info = (DmtxExtractedCodeInfo *)calloc(1, sizeof(DmtxExtractedCodeInfo));
+   if(info == NULL) {
+      return NULL;
+   }
+
+   info->structure.structureSize = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, reg->sizeIdx) *
+                                   dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, reg->sizeIdx);
+   info->structure.structureModules = (long*)calloc(1, sizeof(long) * info->structure.structureSize);
+   if(info->structure.structureModules == NULL) {
+      perror("Calloc failed");
+      dmtxExtractedCodeInfoDestroy(&info);
+      return NULL;
+   }
+   info->structure.structureFixedModules = (long*)calloc(1, sizeof(long) * info->structure.structureSize);
+   if(info->structure.structureFixedModules == NULL) {
+      perror("Calloc failed");
+      dmtxExtractedCodeInfoDestroy(&info);
+      return NULL;
+   }
+   info->structure.structureSymbols = (long*)calloc(1, sizeof(long) * info->structure.structureSize);
+   if(info->structure.structureSymbols == NULL) {
+      perror("Calloc failed");
+      dmtxExtractedCodeInfoDestroy(&info);
+      return NULL;
+   }
+   info->structure.structureSegments = (long*)calloc(1, sizeof(long) * info->structure.structureSize);
+   if(info->structure.structureSegments == NULL) {
+      perror("Calloc failed");
+      dmtxExtractedCodeInfoDestroy(&info);
+      return NULL;
+   }
+   info->structure.structureBlocks = (long*)calloc(1, sizeof(long) * info->structure.structureSize);
+   if(info->structure.structureBlocks == NULL) {
+      perror("Calloc failed");
+      dmtxExtractedCodeInfoDestroy(&info);
+      return NULL;
+   }
+   info->structure.structureParityData = (long*)calloc(1, sizeof(long) * info->structure.structureSize);
+   if(info->structure.structureParityData == NULL) {
+      perror("Calloc failed");
+      dmtxExtractedCodeInfoDestroy(&info);
+      return NULL;
+   }
+   info->structure.helperInverseStructure = (long*)calloc(1, sizeof(long) * info->structure.structureSize);
+   if(info->structure.helperInverseStructure == NULL) {
+      perror("Calloc failed");
+      dmtxExtractedCodeInfoDestroy(&info);
+      return NULL;
+   }
+   for (int i = 0; i < info->structure.structureSize; ++i) {
+      info->structure.structureModules[i]= -1;
+      info->structure.structureFixedModules[i]= -1;
+      info->structure.structureSymbols[i]= -1;
+      info->structure.structureSegments[i]= -1;
+      info->structure.structureBlocks[i]= -1;
+      info->structure.structureParityData[i]= -1;
+      info->structure.helperInverseStructure[i]= -1;
+   }
+   info->structure.codeModulesX = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, reg->sizeIdx);
+   info->structure.codeModulesY = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, reg->sizeIdx);
+   info->structure.fixedXSize = dmtxGetSymbolAttribute(DmtxSymAttribHorizDataRegions, reg->sizeIdx) * 2;
+   info->structure.fixedYSize = dmtxGetSymbolAttribute(DmtxSymAttribVertDataRegions, reg->sizeIdx) * 2;
+   info->structure.fixedElementsXs = (int*)calloc(1, sizeof(int) * info->structure.fixedXSize);
+   if(info->structure.fixedElementsXs == NULL) {
+      perror("Calloc failed");
+      dmtxExtractedCodeInfoDestroy(&info);
+      return NULL;
+   }
+   info->structure.fixedElementsYs = (int*)calloc(1, sizeof(int) * info->structure.fixedYSize);
+   if(info->structure.fixedElementsYs == NULL) {
+      perror("Calloc failed");
+      dmtxExtractedCodeInfoDestroy(&info);
+      return NULL;
+   }
+   for (int i = 0; i < info->structure.fixedXSize; ++i) {
+      info->structure.fixedElementsXs[i]= -1;
+   }
+   for (int i = 0; i < info->structure.fixedYSize; ++i) {
+      info->structure.fixedElementsYs[i]= -1;
+   }
+
+   info->errors.checkedBlocks = 0;
+   info->errors.totalBlocks = dmtxGetSymbolAttribute(DmtxSymAttribInterleavedBlocks, reg->sizeIdx);
+   info->errors.readError = DmtxTrue;
+
+   return info;
+}
+
+extern DmtxPassFail
+dmtxExtractedCodeInfoDestroy(DmtxExtractedCodeInfo **info)
+{
+   if(info == NULL || *info == NULL)
+      return DmtxFail;
+
+   if((*info)->structure.structureModules != NULL) {
+      free((*info)->structure.structureModules);
+   }
+   if((*info)->structure.structureFixedModules != NULL) {
+      free((*info)->structure.structureFixedModules);
+   }
+   if((*info)->structure.structureSymbols != NULL) {
+      free((*info)->structure.structureSymbols);
+   }
+   if((*info)->structure.structureSegments != NULL) {
+      free((*info)->structure.structureSegments);
+   }
+   if((*info)->structure.structureBlocks != NULL) {
+      free((*info)->structure.structureBlocks);
+   }
+   if((*info)->structure.structureParityData != NULL) {
+      free((*info)->structure.structureParityData);
+   }
+   if((*info)->structure.helperInverseStructure != NULL) {
+      free((*info)->structure.helperInverseStructure);
+   }
+   if((*info)->structure.fixedElementsXs != NULL) {
+      free((*info)->structure.fixedElementsXs);
+   }
+   if((*info)->structure.fixedElementsYs != NULL) {
+      free((*info)->structure.fixedElementsYs);
+   }
+
+   free(*info);
+   *info = NULL;
+
+   return DmtxPass;
+}
diff --git a/dmtxencode.c b/dmtxencode.c
index 584769d..e0fcc0c 100644
--- a/dmtxencode.c
+++ b/dmtxencode.c
@@ -203,7 +203,7 @@ dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString)
 
    /* Module placement in region */
    ModulePlacementEcc200(enc->message->array, enc->message->code,
-         enc->region.sizeIdx, DmtxModuleOnRGB);
+         enc->region.sizeIdx, DmtxModuleOnRGB, NULL);
 
    width = 2 * enc->marginSize + (enc->region.symbolCols * enc->moduleSize);
    height = 2 * enc->marginSize + (enc->region.symbolRows * enc->moduleSize);
@@ -345,7 +345,7 @@ dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString)
    memset(enc->message->array, 0x00, sizeof(unsigned char) *
          enc->region.mappingRows * enc->region.mappingCols);
 
-   ModulePlacementEcc200(enc->message->array, encR->message->code, sizeIdxAttempt, DmtxModuleOnRed);
+   ModulePlacementEcc200(enc->message->array, encR->message->code, sizeIdxAttempt, DmtxModuleOnRed, NULL);
 
    /* Reset DmtxModuleAssigned and DMX_MODULE_VISITED bits */
    for(row = 0; row < mappingRows; row++) {
@@ -354,7 +354,7 @@ dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString)
       }
    }
 
-   ModulePlacementEcc200(enc->message->array, encG->message->code, sizeIdxAttempt, DmtxModuleOnGreen);
+   ModulePlacementEcc200(enc->message->array, encG->message->code, sizeIdxAttempt, DmtxModuleOnGreen, NULL);
 
    /* Reset DmtxModuleAssigned and DMX_MODULE_VISITED bits */
    for(row = 0; row < mappingRows; row++) {
@@ -363,7 +363,7 @@ dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString)
       }
    }
 
-   ModulePlacementEcc200(enc->message->array, encB->message->code, sizeIdxAttempt, DmtxModuleOnBlue);
+   ModulePlacementEcc200(enc->message->array, encB->message->code, sizeIdxAttempt, DmtxModuleOnBlue, NULL);
 
    /* Destroy encR, encG, and encB */
    dmtxEncodeDestroy(&encR);
diff --git a/dmtxplacemod.c b/dmtxplacemod.c
index 8cd111a..c965a4b 100644
--- a/dmtxplacemod.c
+++ b/dmtxplacemod.c
@@ -65,10 +65,11 @@ dmtxSymbolModuleStatus(DmtxMessage *message, int sizeIdx, int symbolRow, int sym
  * \return Number of codewords read
  */
 static int
-ModulePlacementEcc200(unsigned char *modules, unsigned char *codewords, int sizeIdx, int moduleOnColor)
+ModulePlacementEcc200(unsigned char *modules, unsigned char *codewords, int sizeIdx, int moduleOnColor, DmtxDecodeStructureInfo* structureInfoOut)
 {
    int row, col, chr;
    int mappingRows, mappingCols;
+   long marker = 0;
 
    assert(moduleOnColor & (DmtxModuleOnRed | DmtxModuleOnGreen | DmtxModuleOnBlue));
 
@@ -83,19 +84,29 @@ ModulePlacementEcc200(unsigned char *modules, unsigned char *codewords, int size
    do {
       /* Repeatedly first check for one of the special corner cases */
       if((row == mappingRows) && (col == 0))
-         PatternShapeSpecial1(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor);
+         PatternShapeSpecial1(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor,
+                              ((structureInfoOut) ? structureInfoOut->structureSymbols : NULL), &marker,
+                              ((structureInfoOut) ? structureInfoOut->helperInverseStructure : NULL));
       else if((row == mappingRows-2) && (col == 0) && (mappingCols%4 != 0))
-         PatternShapeSpecial2(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor);
+         PatternShapeSpecial2(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor,
+                              ((structureInfoOut) ? structureInfoOut->structureSymbols : NULL), &marker,
+                              ((structureInfoOut) ? structureInfoOut->helperInverseStructure : NULL));
       else if((row == mappingRows-2) && (col == 0) && (mappingCols%8 == 4))
-         PatternShapeSpecial3(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor);
+         PatternShapeSpecial3(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor,
+                              ((structureInfoOut) ? structureInfoOut->structureSymbols : NULL), &marker,
+                              ((structureInfoOut) ? structureInfoOut->helperInverseStructure : NULL));
       else if((row == mappingRows+4) && (col == 2) && (mappingCols%8 == 0))
-         PatternShapeSpecial4(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor);
+         PatternShapeSpecial4(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor,
+                              ((structureInfoOut) ? structureInfoOut->structureSymbols : NULL), &marker,
+                              ((structureInfoOut) ? structureInfoOut->helperInverseStructure : NULL));
 
       /* Sweep upward diagonally, inserting successive characters */
       do {
          if((row < mappingRows) && (col >= 0) &&
                !(modules[row*mappingCols+col] & DmtxModuleVisited))
-            PatternShapeStandard(modules, mappingRows, mappingCols, row, col, &(codewords[chr++]), moduleOnColor);
+            PatternShapeStandard(modules, mappingRows, mappingCols, row, col, &(codewords[chr++]), moduleOnColor,
+                                 ((structureInfoOut) ? structureInfoOut->structureSymbols : NULL), &marker,
+                                 ((structureInfoOut) ? structureInfoOut->helperInverseStructure : NULL));
          row -= 2;
          col += 2;
       } while ((row >= 0) && (col < mappingCols));
@@ -106,7 +117,9 @@ ModulePlacementEcc200(unsigned char *modules, unsigned char *codewords, int size
       do {
          if((row >= 0) && (col < mappingCols) &&
                !(modules[row*mappingCols+col] & DmtxModuleVisited))
-            PatternShapeStandard(modules, mappingRows, mappingCols, row, col, &(codewords[chr++]), moduleOnColor);
+            PatternShapeStandard(modules, mappingRows, mappingCols, row, col, &(codewords[chr++]), moduleOnColor,
+                                 ((structureInfoOut) ? structureInfoOut->structureSymbols : NULL), &marker,
+                                 ((structureInfoOut) ? structureInfoOut->helperInverseStructure : NULL));
          row += 2;
          col -= 2;
       } while ((row < mappingRows) && (col >= 0));
@@ -121,6 +134,13 @@ ModulePlacementEcc200(unsigned char *modules, unsigned char *codewords, int size
 
       modules[mappingRows * mappingCols - 1] |= moduleOnColor;
       modules[(mappingRows * mappingCols) - mappingCols - 2] |= moduleOnColor;
+
+      if (structureInfoOut && structureInfoOut->structureSymbols) {
+         structureInfoOut->structureSymbols[mappingRows * mappingCols - 1] = -1;
+         structureInfoOut->structureSymbols[mappingRows * mappingCols - 2] = -1;
+         structureInfoOut->structureSymbols[(mappingRows * mappingCols) - mappingCols - 1] = -1;
+         structureInfoOut->structureSymbols[(mappingRows * mappingCols) - mappingCols - 2] = -1;
+      }
    } /* XXX should this fixed pattern also be used in reading somehow? */
 
    /* XXX compare that chr == region->dataSize here */
@@ -139,16 +159,18 @@ ModulePlacementEcc200(unsigned char *modules, unsigned char *codewords, int size
  * \return void
  */
 static void
-PatternShapeStandard(unsigned char *modules, int mappingRows, int mappingCols, int row, int col, unsigned char *codeword, int moduleOnColor)
+PatternShapeStandard(unsigned char *modules, int mappingRows, int mappingCols, int row, int col, unsigned char *codeword, int moduleOnColor,
+                     long* structure, long* marker, long* helper)
 {
-   PlaceModule(modules, mappingRows, mappingCols, row-2, col-2, codeword, DmtxMaskBit1, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, row-2, col-1, codeword, DmtxMaskBit2, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, row-1, col-2, codeword, DmtxMaskBit3, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, row-1, col-1, codeword, DmtxMaskBit4, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, row-1, col,   codeword, DmtxMaskBit5, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, row,   col-2, codeword, DmtxMaskBit6, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, row,   col-1, codeword, DmtxMaskBit7, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, row,   col,   codeword, DmtxMaskBit8, moduleOnColor);
+   PlaceModule(modules, mappingRows, mappingCols, row-2, col-2, codeword, DmtxMaskBit1, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, row-2, col-1, codeword, DmtxMaskBit2, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, row-1, col-2, codeword, DmtxMaskBit3, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, row-1, col-1, codeword, DmtxMaskBit4, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, row-1, col,   codeword, DmtxMaskBit5, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, row,   col-2, codeword, DmtxMaskBit6, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, row,   col-1, codeword, DmtxMaskBit7, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, row,   col,   codeword, DmtxMaskBit8, moduleOnColor, structure, marker, helper);
+   ++(*marker);
 }
 
 /**
@@ -161,16 +183,18 @@ PatternShapeStandard(unsigned char *modules, int mappingRows, int mappingCols, i
  * \return void
  */
 static void
-PatternShapeSpecial1(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor)
+PatternShapeSpecial1(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor,
+                     long* structure, long* marker, long* helper)
 {
-   PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 0, codeword, DmtxMaskBit1, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 1, codeword, DmtxMaskBit2, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 2, codeword, DmtxMaskBit3, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-2, codeword, DmtxMaskBit4, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-1, codeword, DmtxMaskBit5, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-1, codeword, DmtxMaskBit6, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 2, mappingCols-1, codeword, DmtxMaskBit7, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 3, mappingCols-1, codeword, DmtxMaskBit8, moduleOnColor);
+   PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 0, codeword, DmtxMaskBit1, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 1, codeword, DmtxMaskBit2, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 2, codeword, DmtxMaskBit3, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-2, codeword, DmtxMaskBit4, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-1, codeword, DmtxMaskBit5, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-1, codeword, DmtxMaskBit6, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 2, mappingCols-1, codeword, DmtxMaskBit7, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 3, mappingCols-1, codeword, DmtxMaskBit8, moduleOnColor, structure, marker, helper);
+   ++(*marker);
 }
 
 /**
@@ -183,16 +207,18 @@ PatternShapeSpecial1(unsigned char *modules, int mappingRows, int mappingCols, u
  * \return void
  */
 static void
-PatternShapeSpecial2(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor)
+PatternShapeSpecial2(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor,
+                     long* structure, long* marker, long* helper)
 {
-   PlaceModule(modules, mappingRows, mappingCols, mappingRows-3, 0, codeword, DmtxMaskBit1, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, mappingRows-2, 0, codeword, DmtxMaskBit2, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 0, codeword, DmtxMaskBit3, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-4, codeword, DmtxMaskBit4, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-3, codeword, DmtxMaskBit5, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-2, codeword, DmtxMaskBit6, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-1, codeword, DmtxMaskBit7, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-1, codeword, DmtxMaskBit8, moduleOnColor);
+   PlaceModule(modules, mappingRows, mappingCols, mappingRows-3, 0, codeword, DmtxMaskBit1, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, mappingRows-2, 0, codeword, DmtxMaskBit2, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 0, codeword, DmtxMaskBit3, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-4, codeword, DmtxMaskBit4, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-3, codeword, DmtxMaskBit5, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-2, codeword, DmtxMaskBit6, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-1, codeword, DmtxMaskBit7, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-1, codeword, DmtxMaskBit8, moduleOnColor, structure, marker, helper);
+   ++(*marker);
 }
 
 /**
@@ -205,16 +231,18 @@ PatternShapeSpecial2(unsigned char *modules, int mappingRows, int mappingCols, u
  * \return void
  */
 static void
-PatternShapeSpecial3(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor)
+PatternShapeSpecial3(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor,
+                     long* structure, long* marker, long* helper)
 {
-   PlaceModule(modules, mappingRows, mappingCols, mappingRows-3, 0, codeword, DmtxMaskBit1, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, mappingRows-2, 0, codeword, DmtxMaskBit2, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 0, codeword, DmtxMaskBit3, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-2, codeword, DmtxMaskBit4, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-1, codeword, DmtxMaskBit5, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-1, codeword, DmtxMaskBit6, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 2, mappingCols-1, codeword, DmtxMaskBit7, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 3, mappingCols-1, codeword, DmtxMaskBit8, moduleOnColor);
+   PlaceModule(modules, mappingRows, mappingCols, mappingRows-3, 0, codeword, DmtxMaskBit1, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, mappingRows-2, 0, codeword, DmtxMaskBit2, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 0, codeword, DmtxMaskBit3, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-2, codeword, DmtxMaskBit4, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-1, codeword, DmtxMaskBit5, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-1, codeword, DmtxMaskBit6, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 2, mappingCols-1, codeword, DmtxMaskBit7, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 3, mappingCols-1, codeword, DmtxMaskBit8, moduleOnColor, structure, marker, helper);
+   ++(*marker);
 }
 
 /**
@@ -227,16 +255,18 @@ PatternShapeSpecial3(unsigned char *modules, int mappingRows, int mappingCols, u
  * \return void
  */
 static void
-PatternShapeSpecial4(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor)
+PatternShapeSpecial4(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor,
+                     long* structure, long* marker, long* helper)
 {
-   PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 0, codeword, DmtxMaskBit1, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, mappingCols-1, codeword, DmtxMaskBit2, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-3, codeword, DmtxMaskBit3, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-2, codeword, DmtxMaskBit4, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-1, codeword, DmtxMaskBit5, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-3, codeword, DmtxMaskBit6, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-2, codeword, DmtxMaskBit7, moduleOnColor);
-   PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-1, codeword, DmtxMaskBit8, moduleOnColor);
+   PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, 0, codeword, DmtxMaskBit1, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, mappingRows-1, mappingCols-1, codeword, DmtxMaskBit2, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-3, codeword, DmtxMaskBit3, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-2, codeword, DmtxMaskBit4, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 0, mappingCols-1, codeword, DmtxMaskBit5, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-3, codeword, DmtxMaskBit6, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-2, codeword, DmtxMaskBit7, moduleOnColor, structure, marker, helper);
+   PlaceModule(modules, mappingRows, mappingCols, 1, mappingCols-1, codeword, DmtxMaskBit8, moduleOnColor, structure, marker, helper);
+   ++(*marker);
 }
 
 /**
@@ -252,7 +282,8 @@ PatternShapeSpecial4(unsigned char *modules, int mappingRows, int mappingCols, u
  * \return void
  */
 static void
-PlaceModule(unsigned char *modules, int mappingRows, int mappingCols, int row, int col, unsigned char *codeword, int mask, int moduleOnColor)
+PlaceModule(unsigned char *modules, int mappingRows, int mappingCols, int row, int col, unsigned char *codeword, int mask, int moduleOnColor,
+            long* structure, long* marker, long* helper)
 {
    if(row < 0) {
       row += mappingRows;
@@ -269,6 +300,36 @@ PlaceModule(unsigned char *modules, int mappingRows, int mappingCols, int row, i
          *codeword |= mask;
       else
          *codeword &= (0xff ^ mask);
+
+      if (structure && helper && marker) {
+         structure[row*mappingCols+col] = *marker;
+         switch (mask) {
+            case DmtxMaskBit1:
+               helper[(*marker) * 8 + 0] = row*mappingCols+col;
+               break;
+            case DmtxMaskBit2:
+               helper[(*marker) * 8 + 1] = row*mappingCols+col;
+               break;
+            case DmtxMaskBit3:
+               helper[(*marker) * 8 + 2] = row*mappingCols+col;
+               break;
+            case DmtxMaskBit4:
+               helper[(*marker) * 8 + 3] = row*mappingCols+col;
+               break;
+            case DmtxMaskBit5:
+               helper[(*marker) * 8 + 4] = row*mappingCols+col;
+               break;
+            case DmtxMaskBit6:
+               helper[(*marker) * 8 + 5] = row*mappingCols+col;
+               break;
+            case DmtxMaskBit7:
+               helper[(*marker) * 8 + 6] = row*mappingCols+col;
+               break;
+            case DmtxMaskBit8:
+               helper[(*marker) * 8 + 7] = row*mappingCols+col;
+               break;
+         }
+      }
    }
    /* Otherwise we are encoding the codewords into a pattern */
    else {
diff --git a/dmtxreedsol.c b/dmtxreedsol.c
index 96b08b9..1d767ef 100644
--- a/dmtxreedsol.c
+++ b/dmtxreedsol.c
@@ -148,7 +148,7 @@ RsEncode(DmtxMessage *message, int sizeIdx)
 #undef CHKPASS
 #define CHKPASS { if(passFail == DmtxFail) return DmtxFail; }
 static DmtxPassFail
-RsDecode(unsigned char *code, int sizeIdx, int fix)
+RsDecode(unsigned char *code, int sizeIdx, DmtxExtractedCodeInfo* infoOut)
 {
    int i;
    int blockStride, blockIdx;
@@ -156,6 +156,8 @@ RsDecode(unsigned char *code, int sizeIdx, int fix)
 //   int blockDataWords, blockErrorWords, blockTotalWords, blockMaxCorrectable;
    int symbolDataWords, symbolErrorWords, symbolTotalWords;
    DmtxBoolean error, repairable;
+   DmtxBoolean globalError;
+   int currErrs;
    DmtxPassFail passFail;
    unsigned char *word;
    DmtxByte elpStorage[MAX_ERROR_WORD_COUNT];
@@ -174,6 +176,13 @@ RsDecode(unsigned char *code, int sizeIdx, int fix)
    symbolErrorWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolErrorWords, sizeIdx);
    symbolTotalWords = symbolDataWords + symbolErrorWords;
 
+   if (infoOut) {
+      infoOut->errors.checkedBlocks = 0;
+      infoOut->errors.totalBlocks = blockStride;
+   }
+
+   globalError = DmtxFalse;
+
    /* For each interleaved block */
    for(blockIdx = 0; blockIdx < blockStride; blockIdx++)
    {
@@ -188,6 +197,14 @@ RsDecode(unsigned char *code, int sizeIdx, int fix)
       word = code + symbolTotalWords + blockIdx - blockStride;
       for(i = 0; i < blockErrorWords; i++)
       {
+         if (infoOut && infoOut->structure.helperInverseStructure && infoOut->structure.structureBlocks && infoOut->structure.structureParityData) {
+            int idx = (word - code) * 8;
+            for (int bn = 0; bn < 8; ++bn) {
+               infoOut->structure.structureBlocks[infoOut->structure.helperInverseStructure[idx + bn]] = blockIdx;
+               infoOut->structure.structureParityData[infoOut->structure.helperInverseStructure[idx + bn]] = 1;
+            }
+         }
+
          dmtxByteListPush(&rec, *word, &passFail); CHKPASS;
          word -= blockStride;
       }
@@ -196,6 +213,14 @@ RsDecode(unsigned char *code, int sizeIdx, int fix)
       word = code + blockIdx + (blockStride * (blockDataWords - 1));
       for(i = 0; i < blockDataWords; i++)
       {
+         if (infoOut && infoOut->structure.helperInverseStructure && infoOut->structure.structureBlocks && infoOut->structure.structureParityData) {
+            int idx = (word - code) * 8;
+            for (int bn = 0; bn < 8; ++bn) {
+               infoOut->structure.structureBlocks[infoOut->structure.helperInverseStructure[idx + bn]] = blockIdx;
+               infoOut->structure.structureParityData[infoOut->structure.helperInverseStructure[idx + bn]] = 0;
+            }
+         }
+
          dmtxByteListPush(&rec, *word, &passFail); CHKPASS;
          word -= blockStride;
       }
@@ -203,21 +228,38 @@ RsDecode(unsigned char *code, int sizeIdx, int fix)
       /* Compute syndromes (syn) */
       error = RsComputeSyndromes(&syn, &rec, blockErrorWords);
 
+      currErrs = 0;
       /* Error(s) detected: Attempt repair */
       if(error)
       {
          /* Find error locator polynomial (elp) */
-         repairable = RsFindErrorLocatorPoly(&elp, &syn, blockErrorWords, blockMaxCorrectable);
-         if(!repairable)
-            return DmtxFail;
+         repairable = RsFindErrorLocatorPoly(&elp, &syn, blockErrorWords, blockMaxCorrectable, &currErrs);
 
-         /* Find error positions (loc) */
-         repairable = RsFindErrorLocations(&loc, &elp);
-         if(!repairable)
-            return DmtxFail;
+         if (!repairable)
+         {
+            globalError = DmtxTrue;
+         }
+         else
+         {
+            /* Find error positions (loc) */
+            repairable = RsFindErrorLocations(&loc, &elp);
+
+            if (!repairable)
+            {
+               globalError = DmtxTrue;
+            }
+            else
+            {
+               /* Find error values and repair */
+               RsRepairErrors(&rec, &loc, &elp, &syn);
+            }
+         }
+      }
 
-         /* Find error values and repair */
-         RsRepairErrors(&rec, &loc, &elp, &syn);
+      if (infoOut) {
+         infoOut->errors.errors[blockIdx] = currErrs;
+         infoOut->errors.maxCorrectableErrors[blockIdx] = blockMaxCorrectable;
+         infoOut->errors.checkedBlocks += 1;
       }
 
       /*
@@ -229,6 +271,19 @@ RsDecode(unsigned char *code, int sizeIdx, int fix)
       for(i = 0; i < blockDataWords; i++)
       {
          *word = dmtxByteListPop(&rec, &passFail); CHKPASS;
+
+         if (infoOut && infoOut->structure.helperInverseStructure && infoOut->structure.structureFixedModules) {
+            int idx = (word - code) * 8;
+            infoOut->structure.structureFixedModules[infoOut->structure.helperInverseStructure[idx + 0]] = !!(*word & DmtxMaskBit1);
+            infoOut->structure.structureFixedModules[infoOut->structure.helperInverseStructure[idx + 1]] = !!(*word & DmtxMaskBit2);
+            infoOut->structure.structureFixedModules[infoOut->structure.helperInverseStructure[idx + 2]] = !!(*word & DmtxMaskBit3);
+            infoOut->structure.structureFixedModules[infoOut->structure.helperInverseStructure[idx + 3]] = !!(*word & DmtxMaskBit4);
+            infoOut->structure.structureFixedModules[infoOut->structure.helperInverseStructure[idx + 4]] = !!(*word & DmtxMaskBit5);
+            infoOut->structure.structureFixedModules[infoOut->structure.helperInverseStructure[idx + 5]] = !!(*word & DmtxMaskBit6);
+            infoOut->structure.structureFixedModules[infoOut->structure.helperInverseStructure[idx + 6]] = !!(*word & DmtxMaskBit7);
+            infoOut->structure.structureFixedModules[infoOut->structure.helperInverseStructure[idx + 7]] = !!(*word & DmtxMaskBit8);
+         }
+
          word += blockStride;
       }
 
@@ -237,11 +292,27 @@ RsDecode(unsigned char *code, int sizeIdx, int fix)
       for(i = 0; i < blockErrorWords; i++)
       {
          *word = dmtxByteListPop(&rec, &passFail); CHKPASS;
+
+         if (infoOut && infoOut->structure.helperInverseStructure && infoOut->structure.structureFixedModules) {
+            int idx = (word - code) * 8;
+            infoOut->structure.structureFixedModules[infoOut->structure.helperInverseStructure[idx + 0]] = !!(*word & DmtxMaskBit1);
+            infoOut->structure.structureFixedModules[infoOut->structure.helperInverseStructure[idx + 1]] = !!(*word & DmtxMaskBit2);
+            infoOut->structure.structureFixedModules[infoOut->structure.helperInverseStructure[idx + 2]] = !!(*word & DmtxMaskBit3);
+            infoOut->structure.structureFixedModules[infoOut->structure.helperInverseStructure[idx + 3]] = !!(*word & DmtxMaskBit4);
+            infoOut->structure.structureFixedModules[infoOut->structure.helperInverseStructure[idx + 4]] = !!(*word & DmtxMaskBit5);
+            infoOut->structure.structureFixedModules[infoOut->structure.helperInverseStructure[idx + 5]] = !!(*word & DmtxMaskBit6);
+            infoOut->structure.structureFixedModules[infoOut->structure.helperInverseStructure[idx + 6]] = !!(*word & DmtxMaskBit7);
+            infoOut->structure.structureFixedModules[infoOut->structure.helperInverseStructure[idx + 7]] = !!(*word & DmtxMaskBit8);
+         }
+
          word += blockStride;
       }
    }
 
-   return DmtxPass;
+   if (infoOut) {
+      infoOut->errors.readError = globalError;
+   }
+   return (globalError) ? DmtxFail : DmtxPass;
 }
 
 /**
@@ -327,7 +398,7 @@ RsComputeSyndromes(DmtxByteList *syn, const DmtxByteList *rec, int blockErrorWor
 #undef CHKPASS
 #define CHKPASS { if(passFail == DmtxFail) return DmtxFalse; }
 static DmtxBoolean
-RsFindErrorLocatorPoly(DmtxByteList *elpOut, const DmtxByteList *syn, int errorWordCount, int maxCorrectable)
+RsFindErrorLocatorPoly(DmtxByteList *elpOut, const DmtxByteList *syn, int errorWordCount, int maxCorrectable, int* errorsOut)
 {
    int i, iNext, j;
    int m, mCmp, lambda;
@@ -381,7 +452,7 @@ RsFindErrorLocatorPoly(DmtxByteList *elpOut, const DmtxByteList *syn, int errorW
       }
 
       lambda = elp[iNext].length - 1;
-      if(i == errorWordCount || i >= lambda + maxCorrectable)
+      if(i == errorWordCount || i > lambda + maxCorrectable)
          break;
 
       /* Calculate discrepancy dis.b[i] */
@@ -394,6 +465,8 @@ RsFindErrorLocatorPoly(DmtxByteList *elpOut, const DmtxByteList *syn, int errorW
 
    dmtxByteListCopy(elpOut, &elp[iNext], &passFail); CHKPASS;
 
+   *errorsOut = lambda;
+
    return (lambda <= maxCorrectable) ? DmtxTrue : DmtxFalse;
 }
 
diff --git a/dmtxstatic.h b/dmtxstatic.h
index e467e92..562227f 100644
--- a/dmtxstatic.h
+++ b/dmtxstatic.h
@@ -154,7 +154,7 @@ static DmtxPassFail BresLineStep(DmtxBresLine *line, int travel, int outward);
 
 /* dmtxdecode.c */
 static void TallyModuleJumps(DmtxDecode *dec, DmtxRegion *reg, int tally[][24], int xOrigin, int yOrigin, int mapWidth, int mapHeight, DmtxDirection dir);
-static DmtxPassFail PopulateArrayFromMatrix(DmtxDecode *dec, DmtxRegion *reg, DmtxMessage *msg);
+static DmtxPassFail PopulateArrayFromMatrix(DmtxDecode *dec, DmtxRegion *reg, DmtxMessage *msg, DmtxDecodeStructureInfo* structureInfoOut);
 
 /* dmtxdecodescheme.c */
 static DmtxPassFail DecodeDataStream(DmtxMessage *msg, int sizeIdx, unsigned char *outputStart);
@@ -174,21 +174,26 @@ static void PrintPattern(DmtxEncode *encode);
 static int EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1);
 
 /* dmtxplacemod.c */
-static int ModulePlacementEcc200(unsigned char *modules, unsigned char *codewords, int sizeIdx, int moduleOnColor);
-static void PatternShapeStandard(unsigned char *modules, int mappingRows, int mappingCols, int row, int col, unsigned char *codeword, int moduleOnColor);
-static void PatternShapeSpecial1(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor);
-static void PatternShapeSpecial2(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor);
-static void PatternShapeSpecial3(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor);
-static void PatternShapeSpecial4(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor);
-static void PlaceModule(unsigned char *modules, int mappingRows, int mappingCols, int row, int col,
-      unsigned char *codeword, int mask, int moduleOnColor);
+static int ModulePlacementEcc200(unsigned char *modules, unsigned char *codewords, int sizeIdx, int moduleOnColor, DmtxDecodeStructureInfo* structureInfoOuts);
+static void PatternShapeStandard(unsigned char *modules, int mappingRows, int mappingCols, int row, int col, unsigned char *codeword, int moduleOnColor,
+                                 long* structure, long* marker, long* helper);
+static void PatternShapeSpecial1(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor,
+                                 long* structure, long* marker, long* helper);
+static void PatternShapeSpecial2(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor,
+                                 long* structure, long* marker, long* helper);
+static void PatternShapeSpecial3(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor,
+                                 long* structure, long* marker, long* helper);
+static void PatternShapeSpecial4(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor,
+                                 long* structure, long* marker, long* helper);
+static void PlaceModule(unsigned char *modules, int mappingRows, int mappingCols, int row, int col, unsigned char *codeword, int mask, int moduleOnColor,
+                        long* structure, long* marker, long* helper);
 
 /* dmtxreedsol.c */
 static DmtxPassFail RsEncode(DmtxMessage *message, int sizeIdx);
-static DmtxPassFail RsDecode(unsigned char *code, int sizeIdx, int fix);
+static DmtxPassFail RsDecode(unsigned char *code, int sizeIdx, DmtxExtractedCodeInfo* infoOut);
 static DmtxPassFail RsGenPoly(DmtxByteList *gen, int errorWordCount);
 static DmtxBoolean RsComputeSyndromes(DmtxByteList *syn, const DmtxByteList *rec, int blockErrorWords);
-static DmtxBoolean RsFindErrorLocatorPoly(DmtxByteList *elp, const DmtxByteList *syn, int errorWordCount, int maxCorrectable);
+static DmtxBoolean RsFindErrorLocatorPoly(DmtxByteList *elp, const DmtxByteList *syn, int errorWordCount, int maxCorrectable, int* errorsOut);
 static DmtxBoolean RsFindErrorLocations(DmtxByteList *loc, const DmtxByteList *elp);
 static DmtxPassFail RsRepairErrors(DmtxByteList *rec, const DmtxByteList *loc, const DmtxByteList *elp, const DmtxByteList *syn);
 
openSUSE Build Service is sponsored by