/** * \brief Convert fitted Data Mosaic region into a decoded message * \param dec * \param reg * \param fix * \return Decoded message */ extern DmtxMessage * dmtxDecodeMosaicRegion(DmtxDecode *dec, DmtxRegion *reg, int fix) { int offset; int colorPlane; DmtxMessage *oMsg, *rMsg, *gMsg, *bMsg; colorPlane = reg->flowBegin.plane; /** * Consider performing a color cube fit here to identify exact RGB of * all 6 "cube-like" corners based on pixels located within region. Then * force each sample pixel to the "cube-like" corner based o which one * is nearest "sqrt(dr^2+dg^2+db^2)" (except sqrt is unnecessary). * colorPlane = reg->flowBegin.plane; * * To find RGB values of primary colors, perform something like a * histogram except instead of going from black to color N, go from * (127,127,127) to color. Use color bins along with distance to * identify value. An additional method will be required to get actual * RGB instead of just a plane in 3D. */ reg->flowBegin.plane = 0; /* kind of a hack */ rMsg = dmtxDecodeMatrixRegion(dec, reg, fix); reg->flowBegin.plane = 1; /* kind of a hack */ gMsg = dmtxDecodeMatrixRegion(dec, reg, fix); reg->flowBegin.plane = 2; /* kind of a hack */ bMsg = dmtxDecodeMatrixRegion(dec, reg, fix); reg->flowBegin.plane = colorPlane; oMsg = dmtxMessageCreate(reg->sizeIdx, DmtxFormatMosaic); if(oMsg == NULL || rMsg == NULL || gMsg == NULL || bMsg == NULL) { dmtxMessageDestroy(&oMsg); dmtxMessageDestroy(&rMsg); dmtxMessageDestroy(&gMsg); dmtxMessageDestroy(&bMsg); return NULL; } offset = 0; memcpy(oMsg->output + offset, rMsg->output, rMsg->outputIdx); offset += rMsg->outputIdx; memcpy(oMsg->output + offset, gMsg->output, gMsg->outputIdx); offset += gMsg->outputIdx; memcpy(oMsg->output + offset, bMsg->output, bMsg->outputIdx); offset += bMsg->outputIdx; oMsg->outputIdx = offset; dmtxMessageDestroy(&rMsg); dmtxMessageDestroy(&gMsg); dmtxMessageDestroy(&bMsg); return oMsg; }
/** * \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; }
/** * \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; }