コード例 #1
0
/**
 * \brief  Convert fitted Data Matrix region into a decoded message
 * \param  dec
 * \param  reg
 * \param  fix
 * \return Decoded message
 */
extern DmtxMessage *
dmtxDecodeMatrixRegion(DmtxDecode *dec, DmtxRegion *reg, int fix)
{
   DmtxMessage *msg;
   DmtxVector2 topLeft, topRight, bottomLeft, bottomRight;
   DmtxPixelLoc pxTopLeft, pxTopRight, pxBottomLeft, pxBottomRight;

   msg = dmtxMessageCreate(reg->sizeIdx, DmtxFormatMatrix);
   if(msg == NULL)
      return NULL;

   if(PopulateArrayFromMatrix(dec, reg, msg) != DmtxPass) {
      dmtxMessageDestroy(&msg);
      return NULL;
   }

   /* maybe place remaining logic into new dmtxDecodePopulatedArray()
      function so other people can pass in their own arrays */

   ModulePlacementEcc200(msg->array, msg->code,
         reg->sizeIdx, DmtxModuleOnRed | DmtxModuleOnGreen | DmtxModuleOnBlue);

   if(RsDecode(msg->code, reg->sizeIdx, fix) == DmtxFail)
   {
      dmtxMessageDestroy(&msg);
      return NULL;
   }

   topLeft.X = bottomLeft.X = topLeft.Y = topRight.Y = -0.1;
   topRight.X = bottomRight.X = bottomLeft.Y = bottomRight.Y = 1.1;

   dmtxMatrix3VMultiplyBy(&topLeft, reg->fit2raw);
   dmtxMatrix3VMultiplyBy(&topRight, reg->fit2raw);
   dmtxMatrix3VMultiplyBy(&bottomLeft, reg->fit2raw);
   dmtxMatrix3VMultiplyBy(&bottomRight, reg->fit2raw);

   pxTopLeft.X = (int)(0.5 + topLeft.X);
   pxTopLeft.Y = (int)(0.5 + topLeft.Y);
   pxBottomLeft.X = (int)(0.5 + bottomLeft.X);
   pxBottomLeft.Y = (int)(0.5 + bottomLeft.Y);
   pxTopRight.X = (int)(0.5 + topRight.X);
   pxTopRight.Y = (int)(0.5 + topRight.Y);
   pxBottomRight.X = (int)(0.5 + bottomRight.X);
   pxBottomRight.Y = (int)(0.5 + bottomRight.Y);

   CacheFillQuad(dec, pxTopLeft, pxTopRight, pxBottomRight, pxBottomLeft);

   DecodeDataStream(msg, reg->sizeIdx, NULL);

   return msg;
}
コード例 #2
0
ファイル: dmtxencode.c プロジェクト: dmtx/libdmtx
/**
 * \brief  Convert message into Data Mosaic image
 *
 *  1) count how many codewords it would take to encode the whole thing
 *  2) take ceiling N of codeword count divided by 3
 *  3) using minimum symbol size that can accomodate N codewords:
 *  4) create several barcodes over iterations of increasing numbers of
 *     input codewords until you go one too far
 *  5) if codewords remain after filling R, G, and B barcodes then go back
 *     to 3 and try with next larger size
 *  6) take the 3 different images you created and write out a new barcode
 *
 * \param  enc
 * \param  inputSize
 * \param  inputString
 * \param  sizeIdxRequest
 * \return DmtxPass | DmtxFail
 */
extern DmtxPassFail
dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString)
{
   unsigned char *inputStringR, *inputStringG, *inputStringB;
   int tmpInputSize;
   int inputSizeR, inputSizeG, inputSizeB;
   int sizeIdxAttempt, sizeIdxFirst, sizeIdxLast;
   int row, col, mappingRows, mappingCols;
   DmtxEncode *encR, *encG, *encB;

   /* Use 1/3 (ceiling) of inputSize establish input size target */
   tmpInputSize = (inputSize + 2) / 3;
   inputSizeR = tmpInputSize;
   inputSizeG = tmpInputSize;
   inputSizeB = inputSize - (inputSizeR + inputSizeG);

   inputStringR = inputString;
   inputStringG = inputStringR + inputSizeR;
   inputStringB = inputStringG + inputSizeG;

   /* Use 1/3 (floor) of dataWordCount establish first symbol size attempt */
   sizeIdxFirst = FindSymbolSize(tmpInputSize, enc->sizeIdxRequest);
   if(sizeIdxFirst == DmtxUndefined)
      return DmtxFail;

   /* Set the last possible symbol size for this symbol shape or specific size request */
   if(enc->sizeIdxRequest == DmtxSymbolSquareAuto)
      sizeIdxLast = DmtxSymbolSquareCount - 1;
   else if(enc->sizeIdxRequest == DmtxSymbolRectAuto)
      sizeIdxLast = DmtxSymbolSquareCount + DmtxSymbolRectCount - 1;
   else
      sizeIdxLast = sizeIdxFirst;

   encR = encG = encB = NULL;

   /* Try increasing symbol sizes until 3 of them can hold all input values */
   for(sizeIdxAttempt = sizeIdxFirst; sizeIdxAttempt <= sizeIdxLast; sizeIdxAttempt++)
   {
      dmtxEncodeDestroy(&encR);
      dmtxEncodeDestroy(&encG);
      dmtxEncodeDestroy(&encB);

      encR = dmtxEncodeCreate();
      encG = dmtxEncodeCreate();
      encB = dmtxEncodeCreate();

      /* Copy all settings from master DmtxEncode, including pointer to image
         and message, which is initially null */
      *encR = *encG = *encB = *enc;

      dmtxEncodeSetProp(encR, DmtxPropSizeRequest, sizeIdxAttempt);
      dmtxEncodeSetProp(encG, DmtxPropSizeRequest, sizeIdxAttempt);
      dmtxEncodeSetProp(encB, DmtxPropSizeRequest, sizeIdxAttempt);

      /* RED LAYER - Holds temporary copy */
      dmtxEncodeDataMatrix(encR, inputSizeR, inputStringR);
      if(encR->region.sizeIdx != sizeIdxAttempt)
         continue;

      /* GREEN LAYER - Holds temporary copy */
      dmtxEncodeDataMatrix(encG, inputSizeG, inputStringG);
      if(encG->region.sizeIdx != sizeIdxAttempt)
         continue;

      /* BLUE LAYER - Holds temporary copy */
      dmtxEncodeDataMatrix(encB, inputSizeB, inputStringB);
      if(encB->region.sizeIdx != sizeIdxAttempt)
         continue;

      /* If we get this far we found a fit */
      break;
   }

   if(encR == NULL || encG == NULL || encB == NULL)
   {
      dmtxEncodeDestroy(&encR);
      dmtxEncodeDestroy(&encG);
      dmtxEncodeDestroy(&encB);
      return DmtxFail;
   }

   /* Now we have the correct sizeIdxAttempt, and they all fit into the desired size */

   /* Perform the red portion of the final encode to set internals correctly */
   dmtxEncodeSetProp(enc, DmtxPropSizeRequest, sizeIdxAttempt);
   dmtxEncodeDataMatrix(enc, inputSizeR, inputStringR);

   /* Zero out the array and overwrite the bits in 3 passes */
   mappingRows = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, sizeIdxAttempt);
   mappingCols = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, sizeIdxAttempt);
   memset(enc->message->array, 0x00, sizeof(unsigned char) *
         enc->region.mappingRows * enc->region.mappingCols);

   ModulePlacementEcc200(enc->message->array, encR->message->code, sizeIdxAttempt, DmtxModuleOnRed);

   /* Reset DmtxModuleAssigned and DMX_MODULE_VISITED bits */
   for(row = 0; row < mappingRows; row++) {
      for(col = 0; col < mappingCols; col++) {
         enc->message->array[row*mappingCols+col] &= (0xff ^ (DmtxModuleAssigned | DmtxModuleVisited));
      }
   }

   ModulePlacementEcc200(enc->message->array, encG->message->code, sizeIdxAttempt, DmtxModuleOnGreen);

   /* Reset DmtxModuleAssigned and DMX_MODULE_VISITED bits */
   for(row = 0; row < mappingRows; row++) {
      for(col = 0; col < mappingCols; col++) {
         enc->message->array[row*mappingCols+col] &= (0xff ^ (DmtxModuleAssigned | DmtxModuleVisited));
      }
   }

   ModulePlacementEcc200(enc->message->array, encB->message->code, sizeIdxAttempt, DmtxModuleOnBlue);

   /* Destroy encR, encG, and encB */
   dmtxEncodeDestroy(&encR);
   dmtxEncodeDestroy(&encG);
   dmtxEncodeDestroy(&encB);

   PrintPattern(enc);

   return DmtxPass;
}
コード例 #3
0
ファイル: dmtxencode.c プロジェクト: dmtx/libdmtx
/**
 * \brief  Convert message into Data Matrix image
 * \param  enc
 * \param  inputSize
 * \param  inputString
 * \param  sizeIdxRequest
 * \return DmtxPass | DmtxFail
 */
extern DmtxPassFail
dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString)
{
   int sizeIdx;
   int width, height, bitsPerPixel;
   unsigned char *pxl;
   DmtxByte outputStorage[4096];
   DmtxByteList output = dmtxByteListBuild(outputStorage, sizeof(outputStorage));
   DmtxByteList input = dmtxByteListBuild(inputString, inputSize);

   input.length = inputSize;

   /* Future: stream = StreamInit() ... */
   /* Future: EncodeDataCodewords(&stream) ... */

   /* Encode input string into data codewords */
   sizeIdx = EncodeDataCodewords(&input, &output, enc->sizeIdxRequest, enc->scheme, enc->fnc1);
   if(sizeIdx == DmtxUndefined || output.length <= 0)
      return DmtxFail;

   /* EncodeDataCodewords() should have updated any auto sizeIdx to a real one */
   assert(sizeIdx != DmtxSymbolSquareAuto && sizeIdx != DmtxSymbolRectAuto);

   /* XXX we can remove a lot of this redundant data */
   enc->region.sizeIdx = sizeIdx;
   enc->region.symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, sizeIdx);
   enc->region.symbolCols = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, sizeIdx);
   enc->region.mappingRows = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, sizeIdx);
   enc->region.mappingCols = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, sizeIdx);

   /* Allocate memory for message and array */
   enc->message = dmtxMessageCreate(sizeIdx, DmtxFormatMatrix);
   enc->message->padCount = 0; /* XXX this needs to be added back */
   memcpy(enc->message->code, output.b, output.length);

   /* Generate error correction codewords */
   RsEncode(enc->message, enc->region.sizeIdx);

   /* Module placement in region */
   ModulePlacementEcc200(enc->message->array, enc->message->code,
         enc->region.sizeIdx, DmtxModuleOnRGB);

   width = 2 * enc->marginSize + (enc->region.symbolCols * enc->moduleSize);
   height = 2 * enc->marginSize + (enc->region.symbolRows * enc->moduleSize);
   bitsPerPixel = GetBitsPerPixel(enc->pixelPacking);
   if(bitsPerPixel == DmtxUndefined)
      return DmtxFail;
   assert(bitsPerPixel % 8 == 0);

   /* Allocate memory for the image to be generated */
   pxl = (unsigned char *)malloc((width * bitsPerPixel / 8 + enc->rowPadBytes) * height);
   if(pxl == NULL) {
      perror("pixel malloc error");
      return DmtxFail;
   }

   enc->image = dmtxImageCreate(pxl, width, height, enc->pixelPacking);
   if(enc->image == NULL) {
      perror("image malloc error");
      return DmtxFail;
   }

   dmtxImageSetProp(enc->image, DmtxPropImageFlip, enc->imageFlip);
   dmtxImageSetProp(enc->image, DmtxPropRowPadBytes, enc->rowPadBytes);

   /* Insert finder and aligment pattern modules */
   PrintPattern(enc);

   return DmtxPass;
}