From 0017252cc8c9c8c10ab16f08322203c78bc7142a Mon Sep 17 00:00:00 2001 From: gpongelli Date: Wed, 14 Dec 2022 18:44:19 +0100 Subject: [PATCH 01/13] four space alignment --- dmtxencodescheme.c | 254 ++++++++++++++++++++++----------------------- 1 file changed, 127 insertions(+), 127 deletions(-) diff --git a/dmtxencodescheme.c b/dmtxencodescheme.c index dff76a12..462c119b 100644 --- a/dmtxencodescheme.c +++ b/dmtxencodescheme.c @@ -85,29 +85,29 @@ * */ static int -EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1) +EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, bool bReaderProgramming) { - DmtxEncodeStream stream; + DmtxEncodeStream stream; - stream = StreamInit(input, output); - stream.fnc1 = fnc1; + stream = StreamInit(input, output); + stream.fnc1 = fnc1; - /* 1st FNC1 special case, encode before scheme switch */ - if (fnc1 != DmtxUndefined && (int)(input->b[0]) == fnc1) - { - StreamInputAdvanceNext(&stream); - AppendValueAscii(&stream, DmtxValueFNC1); - } + /* 1st FNC1 special case, encode before scheme switch */ + if (fnc1 != DmtxUndefined && (int)(input->b[0]) == fnc1) + { + StreamInputAdvanceNext(&stream); + AppendValueAscii(&stream, DmtxValueFNC1); + } - /* Continue encoding until complete */ - while(stream.status == DmtxStatusEncoding) - EncodeNextChunk(&stream, scheme, DmtxEncodeNormal, sizeIdxRequest); + /* Continue encoding until complete */ + while(stream.status == DmtxStatusEncoding) + EncodeNextChunk(&stream, scheme, DmtxEncodeNormal, sizeIdxRequest); - /* Verify encoding completed and all inputs were consumed */ - if(stream.status != DmtxStatusComplete || StreamInputHasNext(&stream)) - return DmtxUndefined; + /* Verify encoding completed and all inputs were consumed */ + if(stream.status != DmtxStatusComplete || StreamInputHasNext(&stream)) + return DmtxUndefined; - return stream.sizeIdx; + return stream.sizeIdx; } /** @@ -120,48 +120,48 @@ EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest static void EncodeNextChunk(DmtxEncodeStream *stream, int scheme, int option, int sizeIdxRequest) { - /* Special case: Prevent X12 from entering state with no way to unlatch */ - if(stream->currentScheme != DmtxSchemeX12 && scheme == DmtxSchemeX12) - { - if(PartialX12ChunkRemains(stream)) - scheme = DmtxSchemeAscii; - } + /* Special case: Prevent X12 from entering state with no way to unlatch */ + if(stream->currentScheme != DmtxSchemeX12 && scheme == DmtxSchemeX12) + { + if(PartialX12ChunkRemains(stream)) + scheme = DmtxSchemeAscii; + } - /* Change to target scheme if necessary */ - if(stream->currentScheme != scheme) - { - EncodeChangeScheme(stream, scheme, DmtxUnlatchExplicit); CHKERR; - CHKSCHEME(scheme); - } + /* Change to target scheme if necessary */ + if(stream->currentScheme != scheme) + { + EncodeChangeScheme(stream, scheme, DmtxUnlatchExplicit); CHKERR; + CHKSCHEME(scheme); + } - /* Special case: Edifact may be done before writing first word */ - if(scheme == DmtxSchemeEdifact) - CompleteIfDoneEdifact(stream, sizeIdxRequest); CHKERR; + /* Special case: Edifact may be done before writing first word */ + if(scheme == DmtxSchemeEdifact) + CompleteIfDoneEdifact(stream, sizeIdxRequest); CHKERR; - switch(stream->currentScheme) - { - case DmtxSchemeAscii: - EncodeNextChunkAscii(stream, option); CHKERR; - CompleteIfDoneAscii(stream, sizeIdxRequest); CHKERR; - break; - case DmtxSchemeC40: - case DmtxSchemeText: - case DmtxSchemeX12: - EncodeNextChunkCTX(stream, sizeIdxRequest); CHKERR; - CompleteIfDoneCTX(stream, sizeIdxRequest); CHKERR; - break; - case DmtxSchemeEdifact: - EncodeNextChunkEdifact(stream); CHKERR; - CompleteIfDoneEdifact(stream, sizeIdxRequest); CHKERR; - break; - case DmtxSchemeBase256: - EncodeNextChunkBase256(stream); CHKERR; - CompleteIfDoneBase256(stream, sizeIdxRequest); CHKERR; - break; - default: - StreamMarkFatal(stream, DmtxErrorUnknown); - break; - } + switch(stream->currentScheme) + { + case DmtxSchemeAscii: + EncodeNextChunkAscii(stream, option); CHKERR; + CompleteIfDoneAscii(stream, sizeIdxRequest); CHKERR; + break; + case DmtxSchemeC40: + case DmtxSchemeText: + case DmtxSchemeX12: + EncodeNextChunkCTX(stream, sizeIdxRequest); CHKERR; + CompleteIfDoneCTX(stream, sizeIdxRequest); CHKERR; + break; + case DmtxSchemeEdifact: + EncodeNextChunkEdifact(stream); CHKERR; + CompleteIfDoneEdifact(stream, sizeIdxRequest); CHKERR; + break; + case DmtxSchemeBase256: + EncodeNextChunkBase256(stream); CHKERR; + CompleteIfDoneBase256(stream, sizeIdxRequest); CHKERR; + break; + default: + StreamMarkFatal(stream, DmtxErrorUnknown); + break; + } } /** @@ -171,69 +171,69 @@ EncodeNextChunk(DmtxEncodeStream *stream, int scheme, int option, int sizeIdxReq static void EncodeChangeScheme(DmtxEncodeStream *stream, DmtxScheme targetScheme, int unlatchType) { - /* Nothing to do */ - if(stream->currentScheme == targetScheme) - return; + /* Nothing to do */ + if(stream->currentScheme == targetScheme) + return; - /* Every latch must go through ASCII */ - switch(stream->currentScheme) - { - case DmtxSchemeC40: - case DmtxSchemeText: - case DmtxSchemeX12: - if(unlatchType == DmtxUnlatchExplicit) - { - AppendUnlatchCTX(stream); CHKERR; - } - break; - case DmtxSchemeEdifact: - if(unlatchType == DmtxUnlatchExplicit) - { - AppendValueEdifact(stream, DmtxValueEdifactUnlatch); CHKERR; - } - break; - default: - /* Nothing to do for ASCII or Base 256 */ - assert(stream->currentScheme == DmtxSchemeAscii || - stream->currentScheme == DmtxSchemeBase256); - break; - } - stream->currentScheme = DmtxSchemeAscii; + /* Every latch must go through ASCII */ + switch(stream->currentScheme) + { + case DmtxSchemeC40: + case DmtxSchemeText: + case DmtxSchemeX12: + if(unlatchType == DmtxUnlatchExplicit) + { + AppendUnlatchCTX(stream); CHKERR; + } + break; + case DmtxSchemeEdifact: + if(unlatchType == DmtxUnlatchExplicit) + { + AppendValueEdifact(stream, DmtxValueEdifactUnlatch); CHKERR; + } + break; + default: + /* Nothing to do for ASCII or Base 256 */ + assert(stream->currentScheme == DmtxSchemeAscii || + stream->currentScheme == DmtxSchemeBase256); + break; + } + stream->currentScheme = DmtxSchemeAscii; - /* Anything other than ASCII (the default) requires a latch */ - switch(targetScheme) - { - case DmtxSchemeC40: - AppendValueAscii(stream, DmtxValueC40Latch); CHKERR; - break; - case DmtxSchemeText: - AppendValueAscii(stream, DmtxValueTextLatch); CHKERR; - break; - case DmtxSchemeX12: - AppendValueAscii(stream, DmtxValueX12Latch); CHKERR; - break; - case DmtxSchemeEdifact: - AppendValueAscii(stream, DmtxValueEdifactLatch); CHKERR; - break; - case DmtxSchemeBase256: - AppendValueAscii(stream, DmtxValueBase256Latch); CHKERR; - break; - default: - /* Nothing to do for ASCII */ - CHKSCHEME(DmtxSchemeAscii); - break; - } - stream->currentScheme = targetScheme; + /* Anything other than ASCII (the default) requires a latch */ + switch(targetScheme) + { + case DmtxSchemeC40: + AppendValueAscii(stream, DmtxValueC40Latch); CHKERR; + break; + case DmtxSchemeText: + AppendValueAscii(stream, DmtxValueTextLatch); CHKERR; + break; + case DmtxSchemeX12: + AppendValueAscii(stream, DmtxValueX12Latch); CHKERR; + break; + case DmtxSchemeEdifact: + AppendValueAscii(stream, DmtxValueEdifactLatch); CHKERR; + break; + case DmtxSchemeBase256: + AppendValueAscii(stream, DmtxValueBase256Latch); CHKERR; + break; + default: + /* Nothing to do for ASCII */ + CHKSCHEME(DmtxSchemeAscii); + break; + } + stream->currentScheme = targetScheme; - /* Reset new chain length to zero */ - stream->outputChainWordCount = 0; - stream->outputChainValueCount = 0; + /* Reset new chain length to zero */ + stream->outputChainWordCount = 0; + stream->outputChainValueCount = 0; - /* Insert header byte if just latched to Base256 */ - if(targetScheme == DmtxSchemeBase256) - { - UpdateBase256ChainHeader(stream, DmtxUndefined); CHKERR; - } + /* Insert header byte if just latched to Base256 */ + if(targetScheme == DmtxSchemeBase256) + { + UpdateBase256ChainHeader(stream, DmtxUndefined); CHKERR; + } } /** @@ -243,18 +243,18 @@ EncodeChangeScheme(DmtxEncodeStream *stream, DmtxScheme targetScheme, int unlatc static int GetRemainingSymbolCapacity(int outputLength, int sizeIdx) { - int capacity; - int remaining; + int capacity; + int remaining; - if(sizeIdx == DmtxUndefined) - { - remaining = DmtxUndefined; - } - else - { - capacity = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx); - remaining = capacity - outputLength; - } + if(sizeIdx == DmtxUndefined) + { + remaining = DmtxUndefined; + } + else + { + capacity = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx); + remaining = capacity - outputLength; + } - return remaining; + return remaining; } From 5229e5b2dff3dbca5435648cea9d3995bdd0ea58 Mon Sep 17 00:00:00 2001 From: gpongelli Date: Wed, 14 Dec 2022 18:57:17 +0100 Subject: [PATCH 02/13] add flag to control reader programming label and implementation. --- dmtx.h | 4 +++- dmtxencode.c | 18 ++++++++++-------- dmtxencodescheme.c | 5 +++++ dmtxstatic.h | 4 ++-- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/dmtx.h b/dmtx.h index 7651c1ed..547000fe 100644 --- a/dmtx.h +++ b/dmtx.h @@ -24,6 +24,8 @@ extern "C" { /* Time headers required for DmtxTime struct below */ #include +#include + #ifdef HAVE_SYS_TIME_H #include #endif @@ -538,7 +540,7 @@ extern DmtxEncode *dmtxEncodeCreate(void); extern DmtxPassFail dmtxEncodeDestroy(DmtxEncode **enc); extern DmtxPassFail dmtxEncodeSetProp(DmtxEncode *enc, int prop, int value); extern int dmtxEncodeGetProp(DmtxEncode *enc, int prop); -extern DmtxPassFail dmtxEncodeDataMatrix(DmtxEncode *enc, int n, unsigned char *s); +extern DmtxPassFail dmtxEncodeDataMatrix(DmtxEncode *enc, int n, unsigned char *s, bool bReaderProgramming); extern DmtxPassFail dmtxEncodeDataMosaic(DmtxEncode *enc, int n, unsigned char *s); /* dmtxdecode.c */ diff --git a/dmtxencode.c b/dmtxencode.c index 584769d2..09772c6d 100644 --- a/dmtxencode.c +++ b/dmtxencode.c @@ -161,10 +161,11 @@ dmtxEncodeGetProp(DmtxEncode *enc, int prop) * \param inputSize * \param inputString * \param sizeIdxRequest + * \param bReaderProgramming * \return DmtxPass | DmtxFail */ extern DmtxPassFail -dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString) +dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString, bool bReaderProgramming) { int sizeIdx; int width, height, bitsPerPixel; @@ -179,7 +180,7 @@ dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString) /* Future: EncodeDataCodewords(&stream) ... */ /* Encode input string into data codewords */ - sizeIdx = EncodeDataCodewords(&input, &output, enc->sizeIdxRequest, enc->scheme, enc->fnc1); + sizeIdx = EncodeDataCodewords(&input, &output, enc->sizeIdxRequest, enc->scheme, enc->fnc1, bReaderProgramming); if(sizeIdx == DmtxUndefined || output.length <= 0) return DmtxFail; @@ -307,17 +308,17 @@ dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString) dmtxEncodeSetProp(encB, DmtxPropSizeRequest, sizeIdxAttempt); /* RED LAYER - Holds temporary copy */ - dmtxEncodeDataMatrix(encR, inputSizeR, inputStringR); + dmtxEncodeDataMatrix(encR, inputSizeR, inputStringR, false); if(encR->region.sizeIdx != sizeIdxAttempt) continue; /* GREEN LAYER - Holds temporary copy */ - dmtxEncodeDataMatrix(encG, inputSizeG, inputStringG); + dmtxEncodeDataMatrix(encG, inputSizeG, inputStringG, false); if(encG->region.sizeIdx != sizeIdxAttempt) continue; /* BLUE LAYER - Holds temporary copy */ - dmtxEncodeDataMatrix(encB, inputSizeB, inputStringB); + dmtxEncodeDataMatrix(encB, inputSizeB, inputStringB, false); if(encB->region.sizeIdx != sizeIdxAttempt) continue; @@ -337,7 +338,7 @@ dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString) /* Perform the red portion of the final encode to set internals correctly */ dmtxEncodeSetProp(enc, DmtxPropSizeRequest, sizeIdxAttempt); - dmtxEncodeDataMatrix(enc, inputSizeR, inputStringR); + dmtxEncodeDataMatrix(enc, inputSizeR, inputStringR, false); /* Zero out the array and overwrite the bits in 3 passes */ mappingRows = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, sizeIdxAttempt); @@ -382,13 +383,14 @@ dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString) * \param inputSize * \param scheme * \param sizeIdx + * \param bReaderProgramming * \return Count of encoded data words * * Future: pass DmtxEncode to this function with an error reason field, which * goes to EncodeSingle... too */ static int -EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1) +EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, bool bReaderProgramming) { int sizeIdx; @@ -402,7 +404,7 @@ EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxReques sizeIdx = DmtxUndefined; /* EncodeAutoFast(input, output, sizeIdxRequest, passFail); */ break; default: - sizeIdx = EncodeSingleScheme(input, output, sizeIdxRequest, scheme, fnc1); + sizeIdx = EncodeSingleScheme(input, output, sizeIdxRequest, scheme, fnc1, bReaderProgramming); break; } diff --git a/dmtxencodescheme.c b/dmtxencodescheme.c index 462c119b..be92503f 100644 --- a/dmtxencodescheme.c +++ b/dmtxencodescheme.c @@ -92,6 +92,11 @@ EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest stream = StreamInit(input, output); stream.fnc1 = fnc1; + if (bReaderProgramming == true) { + /* change to have reader programming label */ + AppendValueAscii(&stream, DmtxValueReaderProgramming); + } + /* 1st FNC1 special case, encode before scheme switch */ if (fnc1 != DmtxUndefined && (int)(input->b[0]) == fnc1) { diff --git a/dmtxstatic.h b/dmtxstatic.h index e467e923..15def3d8 100644 --- a/dmtxstatic.h +++ b/dmtxstatic.h @@ -171,7 +171,7 @@ static unsigned char *DecodeSchemeBase256(DmtxMessage *msg, unsigned char *ptr, /* dmtxencode.c */ static void PrintPattern(DmtxEncode *encode); -static int EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1); +static int EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, bool bReaderProgramming); /* dmtxplacemod.c */ static int ModulePlacementEcc200(unsigned char *modules, unsigned char *codewords, int sizeIdx, int moduleOnColor); @@ -219,7 +219,7 @@ static DmtxByte StreamInputAdvanceNext(DmtxEncodeStream *stream); static void StreamInputAdvancePrev(DmtxEncodeStream *stream); /* dmtxencodescheme.c */ -static int EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1); +static int EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, bool bReaderProgramming); static void EncodeNextChunk(DmtxEncodeStream *stream, int scheme, int subScheme, int sizeIdxRequest); static void EncodeChangeScheme(DmtxEncodeStream *stream, DmtxScheme targetScheme, int unlatchType); static int GetRemainingSymbolCapacity(int outputLength, int sizeIdx); From 5c4cb5caec2f3d4fcdd2bcc315468c957e4fa7b1 Mon Sep 17 00:00:00 2001 From: gpongelli Date: Thu, 15 Dec 2022 11:52:42 +0100 Subject: [PATCH 03/13] remove bool to be ANSI C compliant --- dmtx.h | 4 +--- dmtxencode.c | 12 ++++++------ dmtxencodescheme.c | 4 ++-- dmtxstatic.h | 4 ++-- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/dmtx.h b/dmtx.h index 547000fe..05bad0bc 100644 --- a/dmtx.h +++ b/dmtx.h @@ -24,8 +24,6 @@ extern "C" { /* Time headers required for DmtxTime struct below */ #include -#include - #ifdef HAVE_SYS_TIME_H #include #endif @@ -540,7 +538,7 @@ extern DmtxEncode *dmtxEncodeCreate(void); extern DmtxPassFail dmtxEncodeDestroy(DmtxEncode **enc); extern DmtxPassFail dmtxEncodeSetProp(DmtxEncode *enc, int prop, int value); extern int dmtxEncodeGetProp(DmtxEncode *enc, int prop); -extern DmtxPassFail dmtxEncodeDataMatrix(DmtxEncode *enc, int n, unsigned char *s, bool bReaderProgramming); +extern DmtxPassFail dmtxEncodeDataMatrix(DmtxEncode *enc, int n, unsigned char *s, DmtxBoolean bReaderProgramming); extern DmtxPassFail dmtxEncodeDataMosaic(DmtxEncode *enc, int n, unsigned char *s); /* dmtxdecode.c */ diff --git a/dmtxencode.c b/dmtxencode.c index 09772c6d..072211f1 100644 --- a/dmtxencode.c +++ b/dmtxencode.c @@ -165,7 +165,7 @@ dmtxEncodeGetProp(DmtxEncode *enc, int prop) * \return DmtxPass | DmtxFail */ extern DmtxPassFail -dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString, bool bReaderProgramming) +dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString, DmtxBoolean bReaderProgramming) { int sizeIdx; int width, height, bitsPerPixel; @@ -308,17 +308,17 @@ dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString) dmtxEncodeSetProp(encB, DmtxPropSizeRequest, sizeIdxAttempt); /* RED LAYER - Holds temporary copy */ - dmtxEncodeDataMatrix(encR, inputSizeR, inputStringR, false); + dmtxEncodeDataMatrix(encR, inputSizeR, inputStringR, DmtxFalse); if(encR->region.sizeIdx != sizeIdxAttempt) continue; /* GREEN LAYER - Holds temporary copy */ - dmtxEncodeDataMatrix(encG, inputSizeG, inputStringG, false); + dmtxEncodeDataMatrix(encG, inputSizeG, inputStringG, DmtxFalse); if(encG->region.sizeIdx != sizeIdxAttempt) continue; /* BLUE LAYER - Holds temporary copy */ - dmtxEncodeDataMatrix(encB, inputSizeB, inputStringB, false); + dmtxEncodeDataMatrix(encB, inputSizeB, inputStringB, DmtxFalse); if(encB->region.sizeIdx != sizeIdxAttempt) continue; @@ -338,7 +338,7 @@ dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString) /* Perform the red portion of the final encode to set internals correctly */ dmtxEncodeSetProp(enc, DmtxPropSizeRequest, sizeIdxAttempt); - dmtxEncodeDataMatrix(enc, inputSizeR, inputStringR, false); + dmtxEncodeDataMatrix(enc, inputSizeR, inputStringR, DmtxFalse); /* Zero out the array and overwrite the bits in 3 passes */ mappingRows = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, sizeIdxAttempt); @@ -390,7 +390,7 @@ dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString) * goes to EncodeSingle... too */ static int -EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, bool bReaderProgramming) +EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming) { int sizeIdx; diff --git a/dmtxencodescheme.c b/dmtxencodescheme.c index be92503f..362b4219 100644 --- a/dmtxencodescheme.c +++ b/dmtxencodescheme.c @@ -85,14 +85,14 @@ * */ static int -EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, bool bReaderProgramming) +EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming) { DmtxEncodeStream stream; stream = StreamInit(input, output); stream.fnc1 = fnc1; - if (bReaderProgramming == true) { + if (bReaderProgramming == DmtxTrue) { /* change to have reader programming label */ AppendValueAscii(&stream, DmtxValueReaderProgramming); } diff --git a/dmtxstatic.h b/dmtxstatic.h index 15def3d8..0aeda98d 100644 --- a/dmtxstatic.h +++ b/dmtxstatic.h @@ -171,7 +171,7 @@ static unsigned char *DecodeSchemeBase256(DmtxMessage *msg, unsigned char *ptr, /* dmtxencode.c */ static void PrintPattern(DmtxEncode *encode); -static int EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, bool bReaderProgramming); +static int EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming); /* dmtxplacemod.c */ static int ModulePlacementEcc200(unsigned char *modules, unsigned char *codewords, int sizeIdx, int moduleOnColor); @@ -219,7 +219,7 @@ static DmtxByte StreamInputAdvanceNext(DmtxEncodeStream *stream); static void StreamInputAdvancePrev(DmtxEncodeStream *stream); /* dmtxencodescheme.c */ -static int EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, bool bReaderProgramming); +static int EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming); static void EncodeNextChunk(DmtxEncodeStream *stream, int scheme, int subScheme, int sizeIdxRequest); static void EncodeChangeScheme(DmtxEncodeStream *stream, DmtxScheme targetScheme, int unlatchType); static int GetRemainingSymbolCapacity(int outputLength, int sizeIdx); From e1df1a755fb0a8d98aed22abe37393001c0d17e8 Mon Sep 17 00:00:00 2001 From: gpongelli Date: Fri, 16 Dec 2022 18:13:13 +0100 Subject: [PATCH 04/13] use defined flag from config.h into header files --- dmtx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dmtx.c b/dmtx.c index a5b949ae..778dd07b 100644 --- a/dmtx.c +++ b/dmtx.c @@ -24,13 +24,14 @@ #include #include #include -#include "dmtx.h" -#include "dmtxstatic.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif +#include "dmtx.h" +#include "dmtxstatic.h" + #ifndef CALLBACK_POINT_PLOT #define CALLBACK_POINT_PLOT(a,b,c,d) #endif From 386be86b272f873635aa73093a14246175961323 Mon Sep 17 00:00:00 2001 From: gpongelli Date: Fri, 16 Dec 2022 18:14:49 +0100 Subject: [PATCH 05/13] add configure CLI flag and wrap calls with #ifdef --- configure.ac | 7 ++++ dmtx.h | 6 +++- dmtxencode.c | 58 ++++++++++++++++++++++++++++------ dmtxencodescheme.c | 19 +++++++---- dmtxstatic.h | 17 ++++++++-- test/simple_test/simple_test.c | 6 +++- 6 files changed, 93 insertions(+), 20 deletions(-) diff --git a/configure.ac b/configure.ac index d4fa8e63..80a0859b 100644 --- a/configure.ac +++ b/configure.ac @@ -14,6 +14,13 @@ AC_PROG_CC AC_PROG_LIBTOOL AM_PROG_CC_C_O + +AC_ARG_ENABLE([reader_programming], [AS_HELP_STRING([--disable-reader-programming], [Disable Reader Programming breaking feature.])], [], [enable_reader_programming=yes] ) +AS_IF([test "x$enable_reader_programming" != "xno"], [ + AC_DEFINE([HAVE_READER_PROGRAMMING], [1], [Reader Programming breaking feature.]) +]) + + AC_SEARCH_LIBS([sin], [m] ,[], AC_MSG_ERROR([libdmtx requires libm])) AC_SEARCH_LIBS([cos], [m] ,[], AC_MSG_ERROR([libdmtx requires libm])) AC_SEARCH_LIBS([atan2], [m] ,[], AC_MSG_ERROR([libdmtx requires libm])) diff --git a/dmtx.h b/dmtx.h index 05bad0bc..d76d1faa 100644 --- a/dmtx.h +++ b/dmtx.h @@ -538,7 +538,11 @@ extern DmtxEncode *dmtxEncodeCreate(void); extern DmtxPassFail dmtxEncodeDestroy(DmtxEncode **enc); extern DmtxPassFail dmtxEncodeSetProp(DmtxEncode *enc, int prop, int value); extern int dmtxEncodeGetProp(DmtxEncode *enc, int prop); -extern DmtxPassFail dmtxEncodeDataMatrix(DmtxEncode *enc, int n, unsigned char *s, DmtxBoolean bReaderProgramming); +#ifdef HAVE_READER_PROGRAMMING + extern DmtxPassFail dmtxEncodeDataMatrix(DmtxEncode *enc, int n, unsigned char *s, DmtxBoolean bReaderProgramming); +#else + extern DmtxPassFail dmtxEncodeDataMatrix(DmtxEncode *enc, int n, unsigned char *s); +#endif extern DmtxPassFail dmtxEncodeDataMosaic(DmtxEncode *enc, int n, unsigned char *s); /* dmtxdecode.c */ diff --git a/dmtxencode.c b/dmtxencode.c index 072211f1..c7f17948 100644 --- a/dmtxencode.c +++ b/dmtxencode.c @@ -17,6 +17,10 @@ #undef ISDIGIT #define ISDIGIT(n) (n > 47 && n < 58) +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /** * \brief Initialize encode struct with default values * \return Initialized DmtxEncode struct @@ -164,8 +168,13 @@ dmtxEncodeGetProp(DmtxEncode *enc, int prop) * \param bReaderProgramming * \return DmtxPass | DmtxFail */ -extern DmtxPassFail -dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString, DmtxBoolean bReaderProgramming) +#ifdef HAVE_READER_PROGRAMMING + extern DmtxPassFail + dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString, DmtxBoolean bReaderProgramming) +#else + extern DmtxPassFail + dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString) +#endif { int sizeIdx; int width, height, bitsPerPixel; @@ -180,7 +189,11 @@ dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString, /* Future: EncodeDataCodewords(&stream) ... */ /* Encode input string into data codewords */ - sizeIdx = EncodeDataCodewords(&input, &output, enc->sizeIdxRequest, enc->scheme, enc->fnc1, bReaderProgramming); + #ifdef HAVE_READER_PROGRAMMING + sizeIdx = EncodeDataCodewords(&input, &output, enc->sizeIdxRequest, enc->scheme, enc->fnc1, bReaderProgramming); + #else + sizeIdx = EncodeDataCodewords(&input, &output, enc->sizeIdxRequest, enc->scheme, enc->fnc1); + #endif if(sizeIdx == DmtxUndefined || output.length <= 0) return DmtxFail; @@ -308,17 +321,29 @@ dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString) dmtxEncodeSetProp(encB, DmtxPropSizeRequest, sizeIdxAttempt); /* RED LAYER - Holds temporary copy */ - dmtxEncodeDataMatrix(encR, inputSizeR, inputStringR, DmtxFalse); + #ifdef HAVE_READER_PROGRAMMING + dmtxEncodeDataMatrix(encR, inputSizeR, inputStringR, DmtxFalse); + #else + dmtxEncodeDataMatrix(encR, inputSizeR, inputStringR); + #endif if(encR->region.sizeIdx != sizeIdxAttempt) continue; /* GREEN LAYER - Holds temporary copy */ - dmtxEncodeDataMatrix(encG, inputSizeG, inputStringG, DmtxFalse); + #ifdef HAVE_READER_PROGRAMMING + dmtxEncodeDataMatrix(encG, inputSizeG, inputStringG, DmtxFalse); + #else + dmtxEncodeDataMatrix(encG, inputSizeG, inputStringG); + #endif if(encG->region.sizeIdx != sizeIdxAttempt) continue; /* BLUE LAYER - Holds temporary copy */ - dmtxEncodeDataMatrix(encB, inputSizeB, inputStringB, DmtxFalse); + #ifdef HAVE_READER_PROGRAMMING + dmtxEncodeDataMatrix(encB, inputSizeB, inputStringB, DmtxFalse); + #else + dmtxEncodeDataMatrix(encB, inputSizeB, inputStringB); + #endif if(encB->region.sizeIdx != sizeIdxAttempt) continue; @@ -338,7 +363,11 @@ dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString) /* Perform the red portion of the final encode to set internals correctly */ dmtxEncodeSetProp(enc, DmtxPropSizeRequest, sizeIdxAttempt); - dmtxEncodeDataMatrix(enc, inputSizeR, inputStringR, DmtxFalse); + #ifdef HAVE_READER_PROGRAMMING + dmtxEncodeDataMatrix(enc, inputSizeR, inputStringR, DmtxFalse); + #else + dmtxEncodeDataMatrix(enc, inputSizeR, inputStringR); + #endif /* Zero out the array and overwrite the bits in 3 passes */ mappingRows = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, sizeIdxAttempt); @@ -389,8 +418,13 @@ dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString) * Future: pass DmtxEncode to this function with an error reason field, which * goes to EncodeSingle... too */ -static int -EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming) +#ifdef HAVE_READER_PROGRAMMING + static int + EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming) +#else + static int + EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1) +#endif { int sizeIdx; @@ -404,7 +438,11 @@ EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxReques sizeIdx = DmtxUndefined; /* EncodeAutoFast(input, output, sizeIdxRequest, passFail); */ break; default: - sizeIdx = EncodeSingleScheme(input, output, sizeIdxRequest, scheme, fnc1, bReaderProgramming); + #ifdef HAVE_READER_PROGRAMMING + sizeIdx = EncodeSingleScheme(input, output, sizeIdxRequest, scheme, fnc1, bReaderProgramming); + #else + sizeIdx = EncodeSingleScheme(input, output, sizeIdxRequest, scheme, fnc1); + #endif break; } diff --git a/dmtxencodescheme.c b/dmtxencodescheme.c index 362b4219..a20c3996 100644 --- a/dmtxencodescheme.c +++ b/dmtxencodescheme.c @@ -84,18 +84,25 @@ * * */ -static int -EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming) +#ifdef HAVE_READER_PROGRAMMING + static int + EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming) +#else + static int + EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1) +#endif { DmtxEncodeStream stream; stream = StreamInit(input, output); stream.fnc1 = fnc1; - if (bReaderProgramming == DmtxTrue) { - /* change to have reader programming label */ - AppendValueAscii(&stream, DmtxValueReaderProgramming); - } + #ifdef HAVE_READER_PROGRAMMING + if (bReaderProgramming == DmtxTrue) { + /* change to have reader programming label */ + AppendValueAscii(&stream, DmtxValueReaderProgramming); + } + #endif /* 1st FNC1 special case, encode before scheme switch */ if (fnc1 != DmtxUndefined && (int)(input->b[0]) == fnc1) diff --git a/dmtxstatic.h b/dmtxstatic.h index 0aeda98d..3672ccea 100644 --- a/dmtxstatic.h +++ b/dmtxstatic.h @@ -17,6 +17,10 @@ #ifndef __DMTXSTATIC_H__ #define __DMTXSTATIC_H__ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define DmtxAlmostZero 0.000001 #define DmtxAlmostInfinity -1 @@ -171,7 +175,11 @@ static unsigned char *DecodeSchemeBase256(DmtxMessage *msg, unsigned char *ptr, /* dmtxencode.c */ static void PrintPattern(DmtxEncode *encode); -static int EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming); +#ifdef HAVE_READER_PROGRAMMING + static int EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming); +#else + static int EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1); +#endif /* dmtxplacemod.c */ static int ModulePlacementEcc200(unsigned char *modules, unsigned char *codewords, int sizeIdx, int moduleOnColor); @@ -219,7 +227,12 @@ static DmtxByte StreamInputAdvanceNext(DmtxEncodeStream *stream); static void StreamInputAdvancePrev(DmtxEncodeStream *stream); /* dmtxencodescheme.c */ -static int EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming); +#ifdef HAVE_READER_PROGRAMMING + static int EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming); +#else + static int EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1); +#endif + static void EncodeNextChunk(DmtxEncodeStream *stream, int scheme, int subScheme, int sizeIdxRequest); static void EncodeChangeScheme(DmtxEncodeStream *stream, DmtxScheme targetScheme, int unlatchType); static int GetRemainingSymbolCapacity(int outputLength, int sizeIdx); diff --git a/test/simple_test/simple_test.c b/test/simple_test/simple_test.c index 52a7f928..6d520f63 100644 --- a/test/simple_test/simple_test.c +++ b/test/simple_test/simple_test.c @@ -47,7 +47,11 @@ main(int argc, char *argv[]) */ assert(enc != NULL); - dmtxEncodeDataMatrix(enc, strlen((const char *)str), str); + #ifdef HAVE_READER_PROGRAMMING + dmtxEncodeDataMatrix(enc, strlen((const char *)str), str, DmtxFalse); + #else + dmtxEncodeDataMatrix(enc, strlen((const char *)str), str); + #endif /* 2) COPY the new image data before releasing encoding memory */ From 03962bd75cdb986bfbcf177eebc0eb48038d7bc5 Mon Sep 17 00:00:00 2001 From: gpongelli Date: Mon, 19 Dec 2022 10:45:54 +0100 Subject: [PATCH 06/13] added github workflow --- .github/workflows/config_make.yml | 71 +++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 .github/workflows/config_make.yml diff --git a/.github/workflows/config_make.yml b/.github/workflows/config_make.yml new file mode 100644 index 00000000..04c155a0 --- /dev/null +++ b/.github/workflows/config_make.yml @@ -0,0 +1,71 @@ +# libdmtx - Data Matrix Encoding/Decoding Library +# +# Copyright 2008, 2009 Mike Laughton. All rights reserved. +# Copyright 2012-2016 Vadim A. Misbakh-Soloviov. All rights reserved. +# Copyright 2016 Tim Zaman. All rights reserved. +# +# See LICENSE file in the main project directory for full +# terms of use and distribution. +# +# Contact: +# Vadim A. Misbakh-Soloviov +# Mike Laughton + +name: config make +description: Build project with configure and make + +on: + push: + branches: [ master, main ] + pull_request: + branches: [ master, main ] + + workflow_dispatch: + + +jobs: + with_reader_prog: + name: Reader Programming + + strategy: + matrix: + os: [ubuntu-latest] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v3 + - name: Run Configure + run: ./configure --enable-static=yes --enable-shared=yes + - name: Build + run: make + - name: Build Tests + run: make check + - name: Run Test + run: | + make check + cd test/simple_test + ./simple_test + + without_reader_prog: + name: No reader programming + + strategy: + matrix: + os: [ubuntu-latest] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v3 + - name: Run Configure + run: ./configure --enable-static=yes --enable-shared=yes --disable-reader-programming + - name: Build + run: make + - name: Build Tests + run: make check + - name: Run Test + run: | + make check + cd test/simple_test + ./simple_test From 2946a93634ba52acf35ab5a35af1c948aab33d19 Mon Sep 17 00:00:00 2001 From: gpongelli Date: Tue, 20 Dec 2022 15:49:35 +0100 Subject: [PATCH 07/13] beautify code with VS Code tool. it's all about spaces and alignment --- dmtx.c | 10 +- dmtx.h | 1152 ++++++++------- dmtxbytelist.c | 100 +- dmtxdecode.c | 1178 ++++++++------- dmtxdecodescheme.c | 750 +++++----- dmtxencode.c | 760 +++++----- dmtxencodeascii.c | 277 ++-- dmtxencodebase256.c | 393 ++--- dmtxencodec40textx12.c | 981 ++++++------ dmtxencodeedifact.c | 285 ++-- dmtxencodeoptimize.c | 642 ++++---- dmtxencodescheme.c | 217 +-- dmtxencodestream.c | 150 +- dmtximage.c | 508 +++---- dmtxmatrix3.c | 152 +- dmtxmessage.c | 119 +- dmtxplacemod.c | 279 ++-- dmtxreedsol.c | 686 +++++---- dmtxregion.c | 3199 +++++++++++++++++++++------------------- dmtxscangrid.c | 219 +-- dmtxstatic.h | 84 +- dmtxsymbol.c | 182 +-- dmtxtime.c | 91 +- dmtxvector2.c | 97 +- 24 files changed, 6518 insertions(+), 5993 deletions(-) diff --git a/dmtx.c b/dmtx.c index 778dd07b..fdb8b44a 100644 --- a/dmtx.c +++ b/dmtx.c @@ -33,15 +33,15 @@ #include "dmtxstatic.h" #ifndef CALLBACK_POINT_PLOT -#define CALLBACK_POINT_PLOT(a,b,c,d) +#define CALLBACK_POINT_PLOT(a, b, c, d) #endif #ifndef CALLBACK_POINT_XFRM -#define CALLBACK_POINT_XFRM(a,b,c,d) +#define CALLBACK_POINT_XFRM(a, b, c, d) #endif #ifndef CALLBACK_MODULE -#define CALLBACK_MODULE(a,b,c,d,e) +#define CALLBACK_MODULE(a, b, c, d, e) #endif #ifndef CALLBACK_MATRIX @@ -49,7 +49,7 @@ #endif #ifndef CALLBACK_FINAL -#define CALLBACK_FINAL(a,b) +#define CALLBACK_FINAL(a, b) #endif /** @@ -88,5 +88,5 @@ extern char * dmtxVersion(void) { - return DmtxVersion; + return DmtxVersion; } diff --git a/dmtx.h b/dmtx.h index d76d1faa..310a3a29 100644 --- a/dmtx.h +++ b/dmtx.h @@ -19,7 +19,8 @@ #define __DMTX_H__ #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif /* Time headers required for DmtxTime struct below */ @@ -65,573 +66,598 @@ extern "C" { #define DmtxModuleVisited 0x20 #define DmtxModuleData 0x40 -#define DMTX_CHECK_BOUNDS(l,i) (assert((i) >= 0 && (i) < (l)->length && (l)->length <= (l)->capacity)) - -typedef enum { - DmtxStatusEncoding, /* Encoding is currently underway */ - DmtxStatusComplete, /* Encoding is done and everything went well */ - DmtxStatusInvalid, /* Something bad happened that sometimes happens */ - DmtxStatusFatal /* Something happened that should never happen */ -} DmtxStatus; - -typedef enum { - DmtxSchemeAutoFast = -2, - DmtxSchemeAutoBest = -1, - DmtxSchemeAscii = 0, - DmtxSchemeC40, - DmtxSchemeText, - DmtxSchemeX12, - DmtxSchemeEdifact, - DmtxSchemeBase256 -} DmtxScheme; - -typedef enum { - DmtxSymbolRectAuto = -3, - DmtxSymbolSquareAuto = -2, - DmtxSymbolShapeAuto = -1, - DmtxSymbol10x10 = 0, - DmtxSymbol12x12, - DmtxSymbol14x14, - DmtxSymbol16x16, - DmtxSymbol18x18, - DmtxSymbol20x20, - DmtxSymbol22x22, - DmtxSymbol24x24, - DmtxSymbol26x26, - DmtxSymbol32x32, - DmtxSymbol36x36, - DmtxSymbol40x40, - DmtxSymbol44x44, - DmtxSymbol48x48, - DmtxSymbol52x52, - DmtxSymbol64x64, - DmtxSymbol72x72, - DmtxSymbol80x80, - DmtxSymbol88x88, - DmtxSymbol96x96, - DmtxSymbol104x104, - DmtxSymbol120x120, - DmtxSymbol132x132, - DmtxSymbol144x144, - DmtxSymbol8x18, - DmtxSymbol8x32, - DmtxSymbol12x26, - DmtxSymbol12x36, - DmtxSymbol16x36, - DmtxSymbol16x48 -} DmtxSymbolSize; - -typedef enum { - DmtxDirNone = 0x00, - DmtxDirUp = 0x01 << 0, - DmtxDirLeft = 0x01 << 1, - DmtxDirDown = 0x01 << 2, - DmtxDirRight = 0x01 << 3, - DmtxDirHorizontal = DmtxDirLeft | DmtxDirRight, - DmtxDirVertical = DmtxDirUp | DmtxDirDown, - DmtxDirRightUp = DmtxDirRight | DmtxDirUp, - DmtxDirLeftDown = DmtxDirLeft | DmtxDirDown -} DmtxDirection; - -typedef enum { - DmtxSymAttribSymbolRows, - DmtxSymAttribSymbolCols, - DmtxSymAttribDataRegionRows, - DmtxSymAttribDataRegionCols, - DmtxSymAttribHorizDataRegions, - DmtxSymAttribVertDataRegions, - DmtxSymAttribMappingMatrixRows, - DmtxSymAttribMappingMatrixCols, - DmtxSymAttribInterleavedBlocks, - DmtxSymAttribBlockErrorWords, - DmtxSymAttribBlockMaxCorrectable, - DmtxSymAttribSymbolDataWords, - DmtxSymAttribSymbolErrorWords, - DmtxSymAttribSymbolMaxCorrectable -} DmtxSymAttribute; - -typedef enum { - DmtxCorner00 = 0x01 << 0, - DmtxCorner10 = 0x01 << 1, - DmtxCorner11 = 0x01 << 2, - DmtxCorner01 = 0x01 << 3 -} DmtxCornerLoc; - -typedef enum { - /* Encoding properties */ - DmtxPropScheme = 100, - DmtxPropSizeRequest, - DmtxPropMarginSize, - DmtxPropModuleSize, - DmtxPropFnc1, - /* Decoding properties */ - DmtxPropEdgeMin = 200, - DmtxPropEdgeMax, - DmtxPropScanGap, - DmtxPropSquareDevn, - DmtxPropSymbolSize, - DmtxPropEdgeThresh, - /* Image properties */ - DmtxPropWidth = 300, - DmtxPropHeight, - DmtxPropPixelPacking, - DmtxPropBitsPerPixel, - DmtxPropBytesPerPixel, - DmtxPropRowPadBytes, - DmtxPropRowSizeBytes, - DmtxPropImageFlip, - DmtxPropChannelCount, - /* Image modifiers */ - DmtxPropXmin = 400, - DmtxPropXmax, - DmtxPropYmin, - DmtxPropYmax, - DmtxPropScale -} DmtxProperty; - -typedef enum { - /* Custom format */ - DmtxPackCustom = 100, - /* 1 bpp */ - DmtxPack1bppK = 200, - /* 8 bpp grayscale */ - DmtxPack8bppK = 300, - /* 16 bpp formats */ - DmtxPack16bppRGB = 400, - DmtxPack16bppRGBX, - DmtxPack16bppXRGB, - DmtxPack16bppBGR, - DmtxPack16bppBGRX, - DmtxPack16bppXBGR, - DmtxPack16bppYCbCr, - /* 24 bpp formats */ - DmtxPack24bppRGB = 500, - DmtxPack24bppBGR, - DmtxPack24bppYCbCr, - /* 32 bpp formats */ - DmtxPack32bppRGBX = 600, - DmtxPack32bppXRGB, - DmtxPack32bppBGRX, - DmtxPack32bppXBGR, - DmtxPack32bppCMYK -} DmtxPackOrder; - -typedef enum { - DmtxFlipNone = 0x00, - DmtxFlipX = 0x01 << 0, - DmtxFlipY = 0x01 << 1 -} DmtxFlip; - -typedef double DmtxMatrix3[3][3]; - -/** - * @struct DmtxPixelLoc - * @brief DmtxPixelLoc - */ -typedef struct DmtxPixelLoc_struct { - int X; - int Y; -} DmtxPixelLoc; - -/** - * @struct DmtxVector2 - * @brief DmtxVector2 - */ -typedef struct DmtxVector2_struct { - double X; - double Y; -} DmtxVector2; - -/** - * @struct DmtxRay2 - * @brief DmtxRay2 - */ -typedef struct DmtxRay2_struct { - double tMin; - double tMax; - DmtxVector2 p; - DmtxVector2 v; -} DmtxRay2; - -typedef unsigned char DmtxByte; - -/** - * @struct DmtxByteList - * @brief DmtxByteList - * Use signed int for length fields instead of size_t to play nicely with RS - * arithmetic - */ -typedef struct DmtxByteList_struct DmtxByteList; -struct DmtxByteList_struct -{ - int length; - int capacity; - DmtxByte *b; -}; - -typedef struct DmtxEncodeStream_struct DmtxEncodeStream; -struct DmtxEncodeStream_struct -{ - int currentScheme; /* Current encodation scheme */ - int inputNext; /* Index of next unprocessed input word in queue */ - int outputChainValueCount; /* Count of output values pushed within current scheme chain */ - int outputChainWordCount; /* Count of output words pushed within current scheme chain */ - char *reason; /* Reason for status */ - int sizeIdx; /* Symbol size of completed stream */ - int fnc1; /* Character to represent FNC1, or DmtxUndefined */ - DmtxStatus status; - DmtxByteList *input; - DmtxByteList *output; -}; - -/** - * @struct DmtxImage - * @brief DmtxImage - */ -typedef struct DmtxImage_struct { - int width; - int height; - int pixelPacking; - int bitsPerPixel; - int bytesPerPixel; - int rowPadBytes; - int rowSizeBytes; - int imageFlip; - int channelCount; - int channelStart[4]; - int bitsPerChannel[4]; - unsigned char *pxl; -} DmtxImage; - -/** - * @struct DmtxPointFlow - * @brief DmtxPointFlow - */ -typedef struct DmtxPointFlow_struct { - int plane; - int arrive; - int depart; - int mag; - DmtxPixelLoc loc; -} DmtxPointFlow; - -/** - * @struct DmtxBestLine - * @brief DmtxBestLine - */ -typedef struct DmtxBestLine_struct { - int angle; - int hOffset; - int mag; - int stepBeg; - int stepPos; - int stepNeg; - int distSq; - double devn; - DmtxPixelLoc locBeg; - DmtxPixelLoc locPos; - DmtxPixelLoc locNeg; -} DmtxBestLine; - -/** - * @struct DmtxRegion - * @brief DmtxRegion - */ -typedef struct DmtxRegion_struct { - - /* Trail blazing values */ - int jumpToPos; /* */ - int jumpToNeg; /* */ - int stepsTotal; /* */ - DmtxPixelLoc finalPos; /* */ - DmtxPixelLoc finalNeg; /* */ - DmtxPixelLoc boundMin; /* */ - DmtxPixelLoc boundMax; /* */ - DmtxPointFlow flowBegin; /* */ - - /* Orientation values */ - int polarity; /* */ - int stepR; - int stepT; - DmtxPixelLoc locR; /* remove if stepR works above */ - DmtxPixelLoc locT; /* remove if stepT works above */ - - /* Region fitting values */ - int leftKnown; /* known == 1; unknown == 0 */ - int leftAngle; /* hough angle of left edge */ - DmtxPixelLoc leftLoc; /* known (arbitrary) location on left edge */ - DmtxBestLine leftLine; /* */ - int bottomKnown; /* known == 1; unknown == 0 */ - int bottomAngle; /* hough angle of bottom edge */ - DmtxPixelLoc bottomLoc; /* known (arbitrary) location on bottom edge */ - DmtxBestLine bottomLine; /* */ - int topKnown; /* known == 1; unknown == 0 */ - int topAngle; /* hough angle of top edge */ - DmtxPixelLoc topLoc; /* known (arbitrary) location on top edge */ - int rightKnown; /* known == 1; unknown == 0 */ - int rightAngle; /* hough angle of right edge */ - DmtxPixelLoc rightLoc; /* known (arbitrary) location on right edge */ - - /* Region calibration values */ - int onColor; /* */ - int offColor; /* */ - int sizeIdx; /* Index of arrays that store Data Matrix constants */ - int symbolRows; /* Number of total rows in symbol including alignment patterns */ - int symbolCols; /* Number of total columns in symbol including alignment patterns */ - int mappingRows; /* Number of data rows in symbol */ - int mappingCols; /* Number of data columns in symbol */ - - /* Transform values */ - DmtxMatrix3 raw2fit; /* 3x3 transformation from raw image to fitted barcode grid */ - DmtxMatrix3 fit2raw; /* 3x3 transformation from fitted barcode grid to raw image */ -} DmtxRegion; - -/** - * @struct DmtxMessage - * @brief DmtxMessage - */ -typedef struct DmtxMessage_struct { - size_t arraySize; /* mappingRows * mappingCols */ - size_t codeSize; /* Size of encoded data (data words + error words) */ - size_t outputSize; /* Size of buffer used to hold decoded data */ - int outputIdx; /* Internal index used to store output progress */ - int padCount; - int fnc1; /* Character to represent FNC1, or DmtxUndefined */ - unsigned char *array; /* Pointer to internal representation of Data Matrix modules */ - unsigned char *code; /* Pointer to internal storage of code words (data and error) */ - unsigned char *output; /* Pointer to internal storage of decoded output */ -} DmtxMessage; - -/** - * @struct DmtxScanGrid - * @brief DmtxScanGrid - */ -typedef struct DmtxScanGrid_struct { - /* set once */ - int minExtent; /* Smallest cross size used in scan */ - int maxExtent; /* Size of bounding grid region (2^N - 1) */ - int xOffset; /* Offset to obtain image X coordinate */ - int yOffset; /* Offset to obtain image Y coordinate */ - int xMin; /* Minimum X in image coordinate system */ - int xMax; /* Maximum X in image coordinate system */ - int yMin; /* Minimum Y in image coordinate system */ - int yMax; /* Maximum Y in image coordinate system */ - - /* reset for each level */ - int total; /* Total number of crosses at this size */ - int extent; /* Length/width of cross in pixels */ - int jumpSize; /* Distance in pixels between cross centers */ - int pixelTotal; /* Total pixel count within an individual cross path */ - int startPos; /* X and Y coordinate of first cross center in pattern */ - - /* reset for each cross */ - int pixelCount; /* Progress (pixel count) within current cross pattern */ - int xCenter; /* X center of current cross pattern */ - int yCenter; /* Y center of current cross pattern */ -} DmtxScanGrid; - -/** - * @struct DmtxTime - * @brief DmtxTime - */ -typedef struct DmtxTime_struct { - time_t sec; - unsigned long usec; -} DmtxTime; - -/** - * @struct DmtxDecode - * @brief DmtxDecode - */ -typedef struct DmtxDecode_struct { - /* Options */ - int edgeMin; - int edgeMax; - int scanGap; - int fnc1; - double squareDevn; - int sizeIdxExpected; - int edgeThresh; - - /* Image modifiers */ - int xMin; - int xMax; - int yMin; - int yMax; - int scale; - - /* Internals */ -/* int cacheComplete; */ - unsigned char *cache; - DmtxImage *image; - DmtxScanGrid grid; -} DmtxDecode; - -/** - * @struct DmtxEncode - * @brief DmtxEncode - */ -typedef struct DmtxEncode_struct { - int method; - int scheme; - int sizeIdxRequest; - int marginSize; - int moduleSize; - int pixelPacking; - int imageFlip; - int rowPadBytes; - int fnc1; - DmtxMessage *message; - DmtxImage *image; - DmtxRegion region; - DmtxMatrix3 xfrm; /* XXX still necessary? */ - DmtxMatrix3 rxfrm; /* XXX still necessary? */ -} DmtxEncode; - -/** - * @struct DmtxChannel - * @brief DmtxChannel - */ -typedef struct DmtxChannel_struct { - int encScheme; /* current encodation scheme */ - int invalid; /* channel status (invalid if non-zero) */ - unsigned char *inputPtr; /* pointer to current input character */ - unsigned char *inputStop; /* pointer to position after final input character */ - int encodedLength; /* encoded length (units of 2/3 bits) */ - int currentLength; /* current length (units of 2/3 bits) */ - int firstCodeWord; /* */ - unsigned char encodedWords[1558]; -} DmtxChannel; - -/* Wrap in a struct for fast copies */ -/** - * @struct DmtxChannelGroup - * @brief DmtxChannelGroup - */ -typedef struct DmtxChannelGroup_struct { - DmtxChannel channel[6]; -} DmtxChannelGroup; - -/** - * @struct DmtxTriplet - * @brief DmtxTriplet - */ -typedef struct DmtxTriplet_struct { - unsigned char value[3]; -} DmtxTriplet; - -/** - * @struct DmtxQuadruplet - * @brief DmtxQuadruplet - */ -typedef struct DmtxQuadruplet_struct { - unsigned char value[4]; -} DmtxQuadruplet; - -/* dmtxtime.c */ -extern DmtxTime dmtxTimeNow(void); -extern DmtxTime dmtxTimeAdd(DmtxTime t, long msec); -extern int dmtxTimeExceeded(DmtxTime timeout); - -/* dmtxencode.c */ -extern DmtxEncode *dmtxEncodeCreate(void); -extern DmtxPassFail dmtxEncodeDestroy(DmtxEncode **enc); -extern DmtxPassFail dmtxEncodeSetProp(DmtxEncode *enc, int prop, int value); -extern int dmtxEncodeGetProp(DmtxEncode *enc, int prop); +#define DMTX_CHECK_BOUNDS(l, i) (assert((i) >= 0 && (i) < (l)->length && (l)->length <= (l)->capacity)) + + typedef enum + { + DmtxStatusEncoding, /* Encoding is currently underway */ + DmtxStatusComplete, /* Encoding is done and everything went well */ + DmtxStatusInvalid, /* Something bad happened that sometimes happens */ + DmtxStatusFatal /* Something happened that should never happen */ + } DmtxStatus; + + typedef enum + { + DmtxSchemeAutoFast = -2, + DmtxSchemeAutoBest = -1, + DmtxSchemeAscii = 0, + DmtxSchemeC40, + DmtxSchemeText, + DmtxSchemeX12, + DmtxSchemeEdifact, + DmtxSchemeBase256 + } DmtxScheme; + + typedef enum + { + DmtxSymbolRectAuto = -3, + DmtxSymbolSquareAuto = -2, + DmtxSymbolShapeAuto = -1, + DmtxSymbol10x10 = 0, + DmtxSymbol12x12, + DmtxSymbol14x14, + DmtxSymbol16x16, + DmtxSymbol18x18, + DmtxSymbol20x20, + DmtxSymbol22x22, + DmtxSymbol24x24, + DmtxSymbol26x26, + DmtxSymbol32x32, + DmtxSymbol36x36, + DmtxSymbol40x40, + DmtxSymbol44x44, + DmtxSymbol48x48, + DmtxSymbol52x52, + DmtxSymbol64x64, + DmtxSymbol72x72, + DmtxSymbol80x80, + DmtxSymbol88x88, + DmtxSymbol96x96, + DmtxSymbol104x104, + DmtxSymbol120x120, + DmtxSymbol132x132, + DmtxSymbol144x144, + DmtxSymbol8x18, + DmtxSymbol8x32, + DmtxSymbol12x26, + DmtxSymbol12x36, + DmtxSymbol16x36, + DmtxSymbol16x48 + } DmtxSymbolSize; + + typedef enum + { + DmtxDirNone = 0x00, + DmtxDirUp = 0x01 << 0, + DmtxDirLeft = 0x01 << 1, + DmtxDirDown = 0x01 << 2, + DmtxDirRight = 0x01 << 3, + DmtxDirHorizontal = DmtxDirLeft | DmtxDirRight, + DmtxDirVertical = DmtxDirUp | DmtxDirDown, + DmtxDirRightUp = DmtxDirRight | DmtxDirUp, + DmtxDirLeftDown = DmtxDirLeft | DmtxDirDown + } DmtxDirection; + + typedef enum + { + DmtxSymAttribSymbolRows, + DmtxSymAttribSymbolCols, + DmtxSymAttribDataRegionRows, + DmtxSymAttribDataRegionCols, + DmtxSymAttribHorizDataRegions, + DmtxSymAttribVertDataRegions, + DmtxSymAttribMappingMatrixRows, + DmtxSymAttribMappingMatrixCols, + DmtxSymAttribInterleavedBlocks, + DmtxSymAttribBlockErrorWords, + DmtxSymAttribBlockMaxCorrectable, + DmtxSymAttribSymbolDataWords, + DmtxSymAttribSymbolErrorWords, + DmtxSymAttribSymbolMaxCorrectable + } DmtxSymAttribute; + + typedef enum + { + DmtxCorner00 = 0x01 << 0, + DmtxCorner10 = 0x01 << 1, + DmtxCorner11 = 0x01 << 2, + DmtxCorner01 = 0x01 << 3 + } DmtxCornerLoc; + + typedef enum + { + /* Encoding properties */ + DmtxPropScheme = 100, + DmtxPropSizeRequest, + DmtxPropMarginSize, + DmtxPropModuleSize, + DmtxPropFnc1, + /* Decoding properties */ + DmtxPropEdgeMin = 200, + DmtxPropEdgeMax, + DmtxPropScanGap, + DmtxPropSquareDevn, + DmtxPropSymbolSize, + DmtxPropEdgeThresh, + /* Image properties */ + DmtxPropWidth = 300, + DmtxPropHeight, + DmtxPropPixelPacking, + DmtxPropBitsPerPixel, + DmtxPropBytesPerPixel, + DmtxPropRowPadBytes, + DmtxPropRowSizeBytes, + DmtxPropImageFlip, + DmtxPropChannelCount, + /* Image modifiers */ + DmtxPropXmin = 400, + DmtxPropXmax, + DmtxPropYmin, + DmtxPropYmax, + DmtxPropScale + } DmtxProperty; + + typedef enum + { + /* Custom format */ + DmtxPackCustom = 100, + /* 1 bpp */ + DmtxPack1bppK = 200, + /* 8 bpp grayscale */ + DmtxPack8bppK = 300, + /* 16 bpp formats */ + DmtxPack16bppRGB = 400, + DmtxPack16bppRGBX, + DmtxPack16bppXRGB, + DmtxPack16bppBGR, + DmtxPack16bppBGRX, + DmtxPack16bppXBGR, + DmtxPack16bppYCbCr, + /* 24 bpp formats */ + DmtxPack24bppRGB = 500, + DmtxPack24bppBGR, + DmtxPack24bppYCbCr, + /* 32 bpp formats */ + DmtxPack32bppRGBX = 600, + DmtxPack32bppXRGB, + DmtxPack32bppBGRX, + DmtxPack32bppXBGR, + DmtxPack32bppCMYK + } DmtxPackOrder; + + typedef enum + { + DmtxFlipNone = 0x00, + DmtxFlipX = 0x01 << 0, + DmtxFlipY = 0x01 << 1 + } DmtxFlip; + + typedef double DmtxMatrix3[3][3]; + + /** + * @struct DmtxPixelLoc + * @brief DmtxPixelLoc + */ + typedef struct DmtxPixelLoc_struct + { + int X; + int Y; + } DmtxPixelLoc; + + /** + * @struct DmtxVector2 + * @brief DmtxVector2 + */ + typedef struct DmtxVector2_struct + { + double X; + double Y; + } DmtxVector2; + + /** + * @struct DmtxRay2 + * @brief DmtxRay2 + */ + typedef struct DmtxRay2_struct + { + double tMin; + double tMax; + DmtxVector2 p; + DmtxVector2 v; + } DmtxRay2; + + typedef unsigned char DmtxByte; + + /** + * @struct DmtxByteList + * @brief DmtxByteList + * Use signed int for length fields instead of size_t to play nicely with RS + * arithmetic + */ + typedef struct DmtxByteList_struct DmtxByteList; + struct DmtxByteList_struct + { + int length; + int capacity; + DmtxByte *b; + }; + + typedef struct DmtxEncodeStream_struct DmtxEncodeStream; + struct DmtxEncodeStream_struct + { + int currentScheme; /* Current encodation scheme */ + int inputNext; /* Index of next unprocessed input word in queue */ + int outputChainValueCount; /* Count of output values pushed within current scheme chain */ + int outputChainWordCount; /* Count of output words pushed within current scheme chain */ + char *reason; /* Reason for status */ + int sizeIdx; /* Symbol size of completed stream */ + int fnc1; /* Character to represent FNC1, or DmtxUndefined */ + DmtxStatus status; + DmtxByteList *input; + DmtxByteList *output; + }; + + /** + * @struct DmtxImage + * @brief DmtxImage + */ + typedef struct DmtxImage_struct + { + int width; + int height; + int pixelPacking; + int bitsPerPixel; + int bytesPerPixel; + int rowPadBytes; + int rowSizeBytes; + int imageFlip; + int channelCount; + int channelStart[4]; + int bitsPerChannel[4]; + unsigned char *pxl; + } DmtxImage; + + /** + * @struct DmtxPointFlow + * @brief DmtxPointFlow + */ + typedef struct DmtxPointFlow_struct + { + int plane; + int arrive; + int depart; + int mag; + DmtxPixelLoc loc; + } DmtxPointFlow; + + /** + * @struct DmtxBestLine + * @brief DmtxBestLine + */ + typedef struct DmtxBestLine_struct + { + int angle; + int hOffset; + int mag; + int stepBeg; + int stepPos; + int stepNeg; + int distSq; + double devn; + DmtxPixelLoc locBeg; + DmtxPixelLoc locPos; + DmtxPixelLoc locNeg; + } DmtxBestLine; + + /** + * @struct DmtxRegion + * @brief DmtxRegion + */ + typedef struct DmtxRegion_struct + { + + /* Trail blazing values */ + int jumpToPos; /* */ + int jumpToNeg; /* */ + int stepsTotal; /* */ + DmtxPixelLoc finalPos; /* */ + DmtxPixelLoc finalNeg; /* */ + DmtxPixelLoc boundMin; /* */ + DmtxPixelLoc boundMax; /* */ + DmtxPointFlow flowBegin; /* */ + + /* Orientation values */ + int polarity; /* */ + int stepR; + int stepT; + DmtxPixelLoc locR; /* remove if stepR works above */ + DmtxPixelLoc locT; /* remove if stepT works above */ + + /* Region fitting values */ + int leftKnown; /* known == 1; unknown == 0 */ + int leftAngle; /* hough angle of left edge */ + DmtxPixelLoc leftLoc; /* known (arbitrary) location on left edge */ + DmtxBestLine leftLine; /* */ + int bottomKnown; /* known == 1; unknown == 0 */ + int bottomAngle; /* hough angle of bottom edge */ + DmtxPixelLoc bottomLoc; /* known (arbitrary) location on bottom edge */ + DmtxBestLine bottomLine; /* */ + int topKnown; /* known == 1; unknown == 0 */ + int topAngle; /* hough angle of top edge */ + DmtxPixelLoc topLoc; /* known (arbitrary) location on top edge */ + int rightKnown; /* known == 1; unknown == 0 */ + int rightAngle; /* hough angle of right edge */ + DmtxPixelLoc rightLoc; /* known (arbitrary) location on right edge */ + + /* Region calibration values */ + int onColor; /* */ + int offColor; /* */ + int sizeIdx; /* Index of arrays that store Data Matrix constants */ + int symbolRows; /* Number of total rows in symbol including alignment patterns */ + int symbolCols; /* Number of total columns in symbol including alignment patterns */ + int mappingRows; /* Number of data rows in symbol */ + int mappingCols; /* Number of data columns in symbol */ + + /* Transform values */ + DmtxMatrix3 raw2fit; /* 3x3 transformation from raw image to fitted barcode grid */ + DmtxMatrix3 fit2raw; /* 3x3 transformation from fitted barcode grid to raw image */ + } DmtxRegion; + + /** + * @struct DmtxMessage + * @brief DmtxMessage + */ + typedef struct DmtxMessage_struct + { + size_t arraySize; /* mappingRows * mappingCols */ + size_t codeSize; /* Size of encoded data (data words + error words) */ + size_t outputSize; /* Size of buffer used to hold decoded data */ + int outputIdx; /* Internal index used to store output progress */ + int padCount; + int fnc1; /* Character to represent FNC1, or DmtxUndefined */ + unsigned char *array; /* Pointer to internal representation of Data Matrix modules */ + unsigned char *code; /* Pointer to internal storage of code words (data and error) */ + unsigned char *output; /* Pointer to internal storage of decoded output */ + } DmtxMessage; + + /** + * @struct DmtxScanGrid + * @brief DmtxScanGrid + */ + typedef struct DmtxScanGrid_struct + { + /* set once */ + int minExtent; /* Smallest cross size used in scan */ + int maxExtent; /* Size of bounding grid region (2^N - 1) */ + int xOffset; /* Offset to obtain image X coordinate */ + int yOffset; /* Offset to obtain image Y coordinate */ + int xMin; /* Minimum X in image coordinate system */ + int xMax; /* Maximum X in image coordinate system */ + int yMin; /* Minimum Y in image coordinate system */ + int yMax; /* Maximum Y in image coordinate system */ + + /* reset for each level */ + int total; /* Total number of crosses at this size */ + int extent; /* Length/width of cross in pixels */ + int jumpSize; /* Distance in pixels between cross centers */ + int pixelTotal; /* Total pixel count within an individual cross path */ + int startPos; /* X and Y coordinate of first cross center in pattern */ + + /* reset for each cross */ + int pixelCount; /* Progress (pixel count) within current cross pattern */ + int xCenter; /* X center of current cross pattern */ + int yCenter; /* Y center of current cross pattern */ + } DmtxScanGrid; + + /** + * @struct DmtxTime + * @brief DmtxTime + */ + typedef struct DmtxTime_struct + { + time_t sec; + unsigned long usec; + } DmtxTime; + + /** + * @struct DmtxDecode + * @brief DmtxDecode + */ + typedef struct DmtxDecode_struct + { + /* Options */ + int edgeMin; + int edgeMax; + int scanGap; + int fnc1; + double squareDevn; + int sizeIdxExpected; + int edgeThresh; + + /* Image modifiers */ + int xMin; + int xMax; + int yMin; + int yMax; + int scale; + + /* Internals */ + /* int cacheComplete; */ + unsigned char *cache; + DmtxImage *image; + DmtxScanGrid grid; + } DmtxDecode; + + /** + * @struct DmtxEncode + * @brief DmtxEncode + */ + typedef struct DmtxEncode_struct + { + int method; + int scheme; + int sizeIdxRequest; + int marginSize; + int moduleSize; + int pixelPacking; + int imageFlip; + int rowPadBytes; + int fnc1; + DmtxMessage *message; + DmtxImage *image; + DmtxRegion region; + DmtxMatrix3 xfrm; /* XXX still necessary? */ + DmtxMatrix3 rxfrm; /* XXX still necessary? */ + } DmtxEncode; + + /** + * @struct DmtxChannel + * @brief DmtxChannel + */ + typedef struct DmtxChannel_struct + { + int encScheme; /* current encodation scheme */ + int invalid; /* channel status (invalid if non-zero) */ + unsigned char *inputPtr; /* pointer to current input character */ + unsigned char *inputStop; /* pointer to position after final input character */ + int encodedLength; /* encoded length (units of 2/3 bits) */ + int currentLength; /* current length (units of 2/3 bits) */ + int firstCodeWord; /* */ + unsigned char encodedWords[1558]; + } DmtxChannel; + + /* Wrap in a struct for fast copies */ + /** + * @struct DmtxChannelGroup + * @brief DmtxChannelGroup + */ + typedef struct DmtxChannelGroup_struct + { + DmtxChannel channel[6]; + } DmtxChannelGroup; + + /** + * @struct DmtxTriplet + * @brief DmtxTriplet + */ + typedef struct DmtxTriplet_struct + { + unsigned char value[3]; + } DmtxTriplet; + + /** + * @struct DmtxQuadruplet + * @brief DmtxQuadruplet + */ + typedef struct DmtxQuadruplet_struct + { + unsigned char value[4]; + } DmtxQuadruplet; + + /* dmtxtime.c */ + extern DmtxTime dmtxTimeNow(void); + extern DmtxTime dmtxTimeAdd(DmtxTime t, long msec); + extern int dmtxTimeExceeded(DmtxTime timeout); + + /* dmtxencode.c */ + extern DmtxEncode *dmtxEncodeCreate(void); + extern DmtxPassFail dmtxEncodeDestroy(DmtxEncode **enc); + extern DmtxPassFail dmtxEncodeSetProp(DmtxEncode *enc, int prop, int value); + extern int dmtxEncodeGetProp(DmtxEncode *enc, int prop); #ifdef HAVE_READER_PROGRAMMING extern DmtxPassFail dmtxEncodeDataMatrix(DmtxEncode *enc, int n, unsigned char *s, DmtxBoolean bReaderProgramming); #else extern DmtxPassFail dmtxEncodeDataMatrix(DmtxEncode *enc, int n, unsigned char *s); #endif -extern DmtxPassFail dmtxEncodeDataMosaic(DmtxEncode *enc, int n, unsigned char *s); - -/* dmtxdecode.c */ -extern DmtxDecode *dmtxDecodeCreate(DmtxImage *img, int scale); -extern DmtxPassFail dmtxDecodeDestroy(DmtxDecode **dec); -extern DmtxPassFail dmtxDecodeSetProp(DmtxDecode *dec, int prop, int value); -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 *dmtxDecodePopulatedArray(int sizeIdx, DmtxMessage *msg, int fix); -extern DmtxMessage *dmtxDecodeMosaicRegion(DmtxDecode *dec, DmtxRegion *reg, int fix); -extern unsigned char *dmtxDecodeCreateDiagnostic(DmtxDecode *dec, /*@out@*/ int *totalBytes, /*@out@*/ int *headerBytes, int style); - -/* dmtxregion.c */ -extern DmtxRegion *dmtxRegionCreate(DmtxRegion *reg); -extern DmtxPassFail dmtxRegionDestroy(DmtxRegion **reg); -extern DmtxRegion *dmtxRegionFindNext(DmtxDecode *dec, DmtxTime *timeout); -extern DmtxRegion *dmtxRegionScanPixel(DmtxDecode *dec, int x, int y); -extern DmtxPassFail dmtxRegionUpdateCorners(DmtxDecode *dec, DmtxRegion *reg, DmtxVector2 p00, - DmtxVector2 p10, DmtxVector2 p11, DmtxVector2 p01); -extern DmtxPassFail dmtxRegionUpdateXfrms(DmtxDecode *dec, DmtxRegion *reg); - -/* dmtxmessage.c */ -extern DmtxMessage *dmtxMessageCreate(int sizeIdx, int symbolFormat); -extern DmtxPassFail dmtxMessageDestroy(DmtxMessage **msg); - -/* dmtximage.c */ -extern DmtxImage *dmtxImageCreate(unsigned char *pxl, int width, int height, int pack); -extern DmtxPassFail dmtxImageDestroy(DmtxImage **img); -extern DmtxPassFail dmtxImageSetChannel(DmtxImage *img, int channelStart, int bitsPerChannel); -extern DmtxPassFail dmtxImageSetProp(DmtxImage *img, int prop, int value); -extern int dmtxImageGetProp(DmtxImage *img, int prop); -extern int dmtxImageGetByteOffset(DmtxImage *img, int x, int y); -extern DmtxPassFail dmtxImageGetPixelValue(DmtxImage *img, int x, int y, int channel, /*@out@*/ int *value); -extern DmtxPassFail dmtxImageSetPixelValue(DmtxImage *img, int x, int y, int channel, int value); -extern DmtxBoolean dmtxImageContainsInt(DmtxImage *img, int margin, int x, int y); -extern DmtxBoolean dmtxImageContainsFloat(DmtxImage *img, double x, double y); - -/* dmtxvector2.c */ -extern DmtxVector2 *dmtxVector2AddTo(DmtxVector2 *v1, const DmtxVector2 *v2); -extern DmtxVector2 *dmtxVector2Add(/*@out@*/ DmtxVector2 *vOut, const DmtxVector2 *v1, const DmtxVector2 *v2); -extern DmtxVector2 *dmtxVector2SubFrom(DmtxVector2 *v1, const DmtxVector2 *v2); -extern DmtxVector2 *dmtxVector2Sub(/*@out@*/ DmtxVector2 *vOut, const DmtxVector2 *v1, const DmtxVector2 *v2); -extern DmtxVector2 *dmtxVector2ScaleBy(DmtxVector2 *v, double s); -extern DmtxVector2 *dmtxVector2Scale(/*@out@*/ DmtxVector2 *vOut, const DmtxVector2 *v, double s); -extern double dmtxVector2Cross(const DmtxVector2 *v1, const DmtxVector2 *v2); -extern double dmtxVector2Norm(DmtxVector2 *v); -extern double dmtxVector2Dot(const DmtxVector2 *v1, const DmtxVector2 *v2); -extern double dmtxVector2Mag(const DmtxVector2 *v); -extern double dmtxDistanceFromRay2(const DmtxRay2 *r, const DmtxVector2 *q); -extern double dmtxDistanceAlongRay2(const DmtxRay2 *r, const DmtxVector2 *q); -extern DmtxPassFail dmtxRay2Intersect(/*@out@*/ DmtxVector2 *point, const DmtxRay2 *p0, const DmtxRay2 *p1); -extern DmtxPassFail dmtxPointAlongRay2(/*@out@*/ DmtxVector2 *point, const DmtxRay2 *r, double t); - -/* dmtxmatrix3.c */ -extern void dmtxMatrix3Copy(/*@out@*/ DmtxMatrix3 m0, DmtxMatrix3 m1); -extern void dmtxMatrix3Identity(/*@out@*/ DmtxMatrix3 m); -extern void dmtxMatrix3Translate(/*@out@*/ DmtxMatrix3 m, double tx, double ty); -extern void dmtxMatrix3Rotate(/*@out@*/ DmtxMatrix3 m, double angle); -extern void dmtxMatrix3Scale(/*@out@*/ DmtxMatrix3 m, double sx, double sy); -extern void dmtxMatrix3Shear(/*@out@*/ DmtxMatrix3 m, double shx, double shy); -extern void dmtxMatrix3LineSkewTop(/*@out@*/ DmtxMatrix3 m, double b0, double b1, double sz); -extern void dmtxMatrix3LineSkewTopInv(/*@out@*/ DmtxMatrix3 m, double b0, double b1, double sz); -extern void dmtxMatrix3LineSkewSide(/*@out@*/ DmtxMatrix3 m, double b0, double b1, double sz); -extern void dmtxMatrix3LineSkewSideInv(/*@out@*/ DmtxMatrix3 m, double b0, double b1, double sz); -extern void dmtxMatrix3Multiply(/*@out@*/ DmtxMatrix3 mOut, DmtxMatrix3 m0, DmtxMatrix3 m1); -extern void dmtxMatrix3MultiplyBy(DmtxMatrix3 m0, DmtxMatrix3 m1); -extern int dmtxMatrix3VMultiply(/*@out@*/ DmtxVector2 *vOut, DmtxVector2 *vIn, DmtxMatrix3 m); -extern int dmtxMatrix3VMultiplyBy(DmtxVector2 *v, DmtxMatrix3 m); -extern void dmtxMatrix3Print(DmtxMatrix3 m); - -/* dmtxsymbol.c */ -extern int dmtxSymbolModuleStatus(DmtxMessage *mapping, int sizeIdx, int row, int col); -extern int dmtxGetSymbolAttribute(int attribute, int sizeIdx); -extern int dmtxGetBlockDataSize(int sizeIdx, int blockIdx); -extern int getSizeIdxFromSymbolDimension(int rows, int cols); - -/* dmtxbytelist.c */ -extern DmtxByteList dmtxByteListBuild(DmtxByte *storage, int capacity); -extern void dmtxByteListInit(DmtxByteList *list, int length, DmtxByte value, DmtxPassFail *passFail); -extern void dmtxByteListClear(DmtxByteList *list); -extern DmtxBoolean dmtxByteListHasCapacity(DmtxByteList *list); -extern void dmtxByteListCopy(DmtxByteList *dst, const DmtxByteList *src, DmtxPassFail *passFail); -extern void dmtxByteListPush(DmtxByteList *list, DmtxByte value, DmtxPassFail *passFail); -extern DmtxByte dmtxByteListPop(DmtxByteList *list, DmtxPassFail *passFail); -extern void dmtxByteListPrint(DmtxByteList *list, char *prefix); - -extern char *dmtxVersion(void); + extern DmtxPassFail dmtxEncodeDataMosaic(DmtxEncode *enc, int n, unsigned char *s); + + /* dmtxdecode.c */ + extern DmtxDecode *dmtxDecodeCreate(DmtxImage *img, int scale); + extern DmtxPassFail dmtxDecodeDestroy(DmtxDecode **dec); + extern DmtxPassFail dmtxDecodeSetProp(DmtxDecode *dec, int prop, int value); + 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 *dmtxDecodePopulatedArray(int sizeIdx, DmtxMessage *msg, int fix); + extern DmtxMessage *dmtxDecodeMosaicRegion(DmtxDecode *dec, DmtxRegion *reg, int fix); + extern unsigned char *dmtxDecodeCreateDiagnostic(DmtxDecode *dec, /*@out@*/ int *totalBytes, /*@out@*/ int *headerBytes, int style); + + /* dmtxregion.c */ + extern DmtxRegion *dmtxRegionCreate(DmtxRegion *reg); + extern DmtxPassFail dmtxRegionDestroy(DmtxRegion **reg); + extern DmtxRegion *dmtxRegionFindNext(DmtxDecode *dec, DmtxTime *timeout); + extern DmtxRegion *dmtxRegionScanPixel(DmtxDecode *dec, int x, int y); + extern DmtxPassFail dmtxRegionUpdateCorners(DmtxDecode *dec, DmtxRegion *reg, DmtxVector2 p00, + DmtxVector2 p10, DmtxVector2 p11, DmtxVector2 p01); + extern DmtxPassFail dmtxRegionUpdateXfrms(DmtxDecode *dec, DmtxRegion *reg); + + /* dmtxmessage.c */ + extern DmtxMessage *dmtxMessageCreate(int sizeIdx, int symbolFormat); + extern DmtxPassFail dmtxMessageDestroy(DmtxMessage **msg); + + /* dmtximage.c */ + extern DmtxImage *dmtxImageCreate(unsigned char *pxl, int width, int height, int pack); + extern DmtxPassFail dmtxImageDestroy(DmtxImage **img); + extern DmtxPassFail dmtxImageSetChannel(DmtxImage *img, int channelStart, int bitsPerChannel); + extern DmtxPassFail dmtxImageSetProp(DmtxImage *img, int prop, int value); + extern int dmtxImageGetProp(DmtxImage *img, int prop); + extern int dmtxImageGetByteOffset(DmtxImage *img, int x, int y); + extern DmtxPassFail dmtxImageGetPixelValue(DmtxImage *img, int x, int y, int channel, /*@out@*/ int *value); + extern DmtxPassFail dmtxImageSetPixelValue(DmtxImage *img, int x, int y, int channel, int value); + extern DmtxBoolean dmtxImageContainsInt(DmtxImage *img, int margin, int x, int y); + extern DmtxBoolean dmtxImageContainsFloat(DmtxImage *img, double x, double y); + + /* dmtxvector2.c */ + extern DmtxVector2 *dmtxVector2AddTo(DmtxVector2 *v1, const DmtxVector2 *v2); + extern DmtxVector2 *dmtxVector2Add(/*@out@*/ DmtxVector2 *vOut, const DmtxVector2 *v1, const DmtxVector2 *v2); + extern DmtxVector2 *dmtxVector2SubFrom(DmtxVector2 *v1, const DmtxVector2 *v2); + extern DmtxVector2 *dmtxVector2Sub(/*@out@*/ DmtxVector2 *vOut, const DmtxVector2 *v1, const DmtxVector2 *v2); + extern DmtxVector2 *dmtxVector2ScaleBy(DmtxVector2 *v, double s); + extern DmtxVector2 *dmtxVector2Scale(/*@out@*/ DmtxVector2 *vOut, const DmtxVector2 *v, double s); + extern double dmtxVector2Cross(const DmtxVector2 *v1, const DmtxVector2 *v2); + extern double dmtxVector2Norm(DmtxVector2 *v); + extern double dmtxVector2Dot(const DmtxVector2 *v1, const DmtxVector2 *v2); + extern double dmtxVector2Mag(const DmtxVector2 *v); + extern double dmtxDistanceFromRay2(const DmtxRay2 *r, const DmtxVector2 *q); + extern double dmtxDistanceAlongRay2(const DmtxRay2 *r, const DmtxVector2 *q); + extern DmtxPassFail dmtxRay2Intersect(/*@out@*/ DmtxVector2 *point, const DmtxRay2 *p0, const DmtxRay2 *p1); + extern DmtxPassFail dmtxPointAlongRay2(/*@out@*/ DmtxVector2 *point, const DmtxRay2 *r, double t); + + /* dmtxmatrix3.c */ + extern void dmtxMatrix3Copy(/*@out@*/ DmtxMatrix3 m0, DmtxMatrix3 m1); + extern void dmtxMatrix3Identity(/*@out@*/ DmtxMatrix3 m); + extern void dmtxMatrix3Translate(/*@out@*/ DmtxMatrix3 m, double tx, double ty); + extern void dmtxMatrix3Rotate(/*@out@*/ DmtxMatrix3 m, double angle); + extern void dmtxMatrix3Scale(/*@out@*/ DmtxMatrix3 m, double sx, double sy); + extern void dmtxMatrix3Shear(/*@out@*/ DmtxMatrix3 m, double shx, double shy); + extern void dmtxMatrix3LineSkewTop(/*@out@*/ DmtxMatrix3 m, double b0, double b1, double sz); + extern void dmtxMatrix3LineSkewTopInv(/*@out@*/ DmtxMatrix3 m, double b0, double b1, double sz); + extern void dmtxMatrix3LineSkewSide(/*@out@*/ DmtxMatrix3 m, double b0, double b1, double sz); + extern void dmtxMatrix3LineSkewSideInv(/*@out@*/ DmtxMatrix3 m, double b0, double b1, double sz); + extern void dmtxMatrix3Multiply(/*@out@*/ DmtxMatrix3 mOut, DmtxMatrix3 m0, DmtxMatrix3 m1); + extern void dmtxMatrix3MultiplyBy(DmtxMatrix3 m0, DmtxMatrix3 m1); + extern int dmtxMatrix3VMultiply(/*@out@*/ DmtxVector2 *vOut, DmtxVector2 *vIn, DmtxMatrix3 m); + extern int dmtxMatrix3VMultiplyBy(DmtxVector2 *v, DmtxMatrix3 m); + extern void dmtxMatrix3Print(DmtxMatrix3 m); + + /* dmtxsymbol.c */ + extern int dmtxSymbolModuleStatus(DmtxMessage *mapping, int sizeIdx, int row, int col); + extern int dmtxGetSymbolAttribute(int attribute, int sizeIdx); + extern int dmtxGetBlockDataSize(int sizeIdx, int blockIdx); + extern int getSizeIdxFromSymbolDimension(int rows, int cols); + + /* dmtxbytelist.c */ + extern DmtxByteList dmtxByteListBuild(DmtxByte *storage, int capacity); + extern void dmtxByteListInit(DmtxByteList *list, int length, DmtxByte value, DmtxPassFail *passFail); + extern void dmtxByteListClear(DmtxByteList *list); + extern DmtxBoolean dmtxByteListHasCapacity(DmtxByteList *list); + extern void dmtxByteListCopy(DmtxByteList *dst, const DmtxByteList *src, DmtxPassFail *passFail); + extern void dmtxByteListPush(DmtxByteList *list, DmtxByte value, DmtxPassFail *passFail); + extern DmtxByte dmtxByteListPop(DmtxByteList *list, DmtxPassFail *passFail); + extern void dmtxByteListPrint(DmtxByteList *list, char *prefix); + + extern char *dmtxVersion(void); #ifdef __cplusplus } diff --git a/dmtxbytelist.c b/dmtxbytelist.c index 42147a03..1220cc48 100644 --- a/dmtxbytelist.c +++ b/dmtxbytelist.c @@ -20,13 +20,13 @@ extern DmtxByteList dmtxByteListBuild(DmtxByte *storage, int capacity) { - DmtxByteList list; + DmtxByteList list; - list.b = storage; - list.capacity = capacity; - list.length = 0; + list.b = storage; + list.capacity = capacity; + list.length = 0; - return list; + return list; } /** @@ -36,16 +36,16 @@ dmtxByteListBuild(DmtxByte *storage, int capacity) extern void dmtxByteListInit(DmtxByteList *list, int length, DmtxByte value, DmtxPassFail *passFail) { - if(length > list->capacity) - { - *passFail = DmtxFail; - } - else - { - list->length = length; - memset(list->b, value, sizeof(DmtxByte) * list->capacity); - *passFail = DmtxPass; - } + if (length > list->capacity) + { + *passFail = DmtxFail; + } + else + { + list->length = length; + memset(list->b, value, sizeof(DmtxByte) * list->capacity); + *passFail = DmtxPass; + } } /** @@ -55,8 +55,8 @@ dmtxByteListInit(DmtxByteList *list, int length, DmtxByte value, DmtxPassFail *p extern void dmtxByteListClear(DmtxByteList *list) { - memset(list->b, 0x00, sizeof(DmtxByte) * list->capacity); - list->length = 0; + memset(list->b, 0x00, sizeof(DmtxByte) * list->capacity); + list->length = 0; } /** @@ -66,7 +66,7 @@ dmtxByteListClear(DmtxByteList *list) extern DmtxBoolean dmtxByteListHasCapacity(DmtxByteList *list) { - return (list->length < list->capacity) ? DmtxTrue : DmtxFalse; + return (list->length < list->capacity) ? DmtxTrue : DmtxFalse; } /** @@ -76,21 +76,21 @@ dmtxByteListHasCapacity(DmtxByteList *list) extern void dmtxByteListCopy(DmtxByteList *dst, const DmtxByteList *src, DmtxPassFail *passFail) { - int length; - - if(dst->capacity < src->length) - { - *passFail = DmtxFail; /* dst must be large enough to hold src data */ - } - else - { - /* Copy as many bytes as dst can hold or src can provide (smaller of two) */ - length = (dst->capacity < src->capacity) ? dst->capacity : src->capacity; - - dst->length = src->length; - memcpy(dst->b, src->b, sizeof(unsigned char) * length); - *passFail = DmtxPass; - } + int length; + + if (dst->capacity < src->length) + { + *passFail = DmtxFail; /* dst must be large enough to hold src data */ + } + else + { + /* Copy as many bytes as dst can hold or src can provide (smaller of two) */ + length = (dst->capacity < src->capacity) ? dst->capacity : src->capacity; + + dst->length = src->length; + memcpy(dst->b, src->b, sizeof(unsigned char) * length); + *passFail = DmtxPass; + } } /** @@ -100,15 +100,15 @@ dmtxByteListCopy(DmtxByteList *dst, const DmtxByteList *src, DmtxPassFail *passF extern void dmtxByteListPush(DmtxByteList *list, DmtxByte value, DmtxPassFail *passFail) { - if(list->length >= list->capacity) - { - *passFail = DmtxFail; - } - else - { - list->b[list->length++] = value; - *passFail = DmtxPass; - } + if (list->length >= list->capacity) + { + *passFail = DmtxFail; + } + else + { + list->b[list->length++] = value; + *passFail = DmtxPass; + } } /** @@ -118,9 +118,9 @@ dmtxByteListPush(DmtxByteList *list, DmtxByte value, DmtxPassFail *passFail) extern DmtxByte dmtxByteListPop(DmtxByteList *list, DmtxPassFail *passFail) { - *passFail = (list->length > 0) ? DmtxPass : DmtxFail; + *passFail = (list->length > 0) ? DmtxPass : DmtxFail; - return list->b[--(list->length)]; + return list->b[--(list->length)]; } /** @@ -130,13 +130,13 @@ dmtxByteListPop(DmtxByteList *list, DmtxPassFail *passFail) extern void dmtxByteListPrint(DmtxByteList *list, char *prefix) { - int i; + int i; - if(prefix != NULL) - fprintf(stdout, "%s", prefix); + if (prefix != NULL) + fprintf(stdout, "%s", prefix); - for(i = 0; i < list->length; i++) - fprintf(stdout, " %d", list->b[i]); + for (i = 0; i < list->length; i++) + fprintf(stdout, " %d", list->b[i]); - fputc('\n', stdout); + fputc('\n', stdout); } diff --git a/dmtxdecode.c b/dmtxdecode.c index 6721660e..894c3989 100644 --- a/dmtxdecode.c +++ b/dmtxdecode.c @@ -27,41 +27,42 @@ extern DmtxDecode * dmtxDecodeCreate(DmtxImage *img, int scale) { - DmtxDecode *dec; - int width, height; - - dec = (DmtxDecode *)calloc(1, sizeof(DmtxDecode)); - if(dec == NULL) - return NULL; - - width = dmtxImageGetProp(img, DmtxPropWidth) / scale; - height = dmtxImageGetProp(img, DmtxPropHeight) / scale; - - dec->fnc1 = DmtxUndefined; - - dec->edgeMin = DmtxUndefined; - dec->edgeMax = DmtxUndefined; - dec->scanGap = 1; - dec->squareDevn = cos(50 * (M_PI/180)); - dec->sizeIdxExpected = DmtxSymbolShapeAuto; - dec->edgeThresh = 10; - - dec->xMin = 0; - dec->xMax = width - 1; - dec->yMin = 0; - dec->yMax = height - 1; - dec->scale = scale; - - dec->cache = (unsigned char *)calloc(width * height, sizeof(unsigned char)); - if(dec->cache == NULL) { - free(dec); - return NULL; - } - - dec->image = img; - dec->grid = InitScanGrid(dec); - - return dec; + DmtxDecode *dec; + int width, height; + + dec = (DmtxDecode *)calloc(1, sizeof(DmtxDecode)); + if (dec == NULL) + return NULL; + + width = dmtxImageGetProp(img, DmtxPropWidth) / scale; + height = dmtxImageGetProp(img, DmtxPropHeight) / scale; + + dec->fnc1 = DmtxUndefined; + + dec->edgeMin = DmtxUndefined; + dec->edgeMax = DmtxUndefined; + dec->scanGap = 1; + dec->squareDevn = cos(50 * (M_PI / 180)); + dec->sizeIdxExpected = DmtxSymbolShapeAuto; + dec->edgeThresh = 10; + + dec->xMin = 0; + dec->xMax = width - 1; + dec->yMin = 0; + dec->yMax = height - 1; + dec->scale = scale; + + dec->cache = (unsigned char *)calloc(width * height, sizeof(unsigned char)); + if (dec->cache == NULL) + { + free(dec); + return NULL; + } + + dec->image = img; + dec->grid = InitScanGrid(dec); + + return dec; } /** @@ -72,17 +73,17 @@ dmtxDecodeCreate(DmtxImage *img, int scale) extern DmtxPassFail dmtxDecodeDestroy(DmtxDecode **dec) { - if(dec == NULL || *dec == NULL) - return DmtxFail; + if (dec == NULL || *dec == NULL) + return DmtxFail; - if((*dec)->cache != NULL) - free((*dec)->cache); + if ((*dec)->cache != NULL) + free((*dec)->cache); - free(*dec); + free(*dec); - *dec = NULL; + *dec = NULL; - return DmtxPass; + return DmtxPass; } /** @@ -95,58 +96,59 @@ dmtxDecodeDestroy(DmtxDecode **dec) extern DmtxPassFail dmtxDecodeSetProp(DmtxDecode *dec, int prop, int value) { - switch(prop) { - case DmtxPropEdgeMin: - dec->edgeMin = value; - break; - case DmtxPropEdgeMax: - dec->edgeMax = value; - break; - case DmtxPropScanGap: - dec->scanGap = value; /* XXX Should this be scaled? */ - break; - case DmtxPropFnc1: - dec->fnc1 = value; - break; - case DmtxPropSquareDevn: - dec->squareDevn = cos(value * (M_PI/180.0)); - break; - case DmtxPropSymbolSize: - dec->sizeIdxExpected = value; - break; - case DmtxPropEdgeThresh: - dec->edgeThresh = value; - break; - /* Min and Max values arrive unscaled */ - case DmtxPropXmin: - dec->xMin = value / dec->scale; - break; - case DmtxPropXmax: - dec->xMax = value / dec->scale; - break; - case DmtxPropYmin: - dec->yMin = value / dec->scale; - break; - case DmtxPropYmax: - dec->yMax = value / dec->scale; - break; - default: - break; - } - - if(dec->squareDevn <= 0.0 || dec->squareDevn >= 1.0) - return DmtxFail; - - if(dec->scanGap < 1) - return DmtxFail; - - if(dec->edgeThresh < 1 || dec->edgeThresh > 100) - return DmtxFail; - - /* Reinitialize scangrid in case any inputs changed */ - dec->grid = InitScanGrid(dec); - - return DmtxPass; + switch (prop) + { + case DmtxPropEdgeMin: + dec->edgeMin = value; + break; + case DmtxPropEdgeMax: + dec->edgeMax = value; + break; + case DmtxPropScanGap: + dec->scanGap = value; /* XXX Should this be scaled? */ + break; + case DmtxPropFnc1: + dec->fnc1 = value; + break; + case DmtxPropSquareDevn: + dec->squareDevn = cos(value * (M_PI / 180.0)); + break; + case DmtxPropSymbolSize: + dec->sizeIdxExpected = value; + break; + case DmtxPropEdgeThresh: + dec->edgeThresh = value; + break; + /* Min and Max values arrive unscaled */ + case DmtxPropXmin: + dec->xMin = value / dec->scale; + break; + case DmtxPropXmax: + dec->xMax = value / dec->scale; + break; + case DmtxPropYmin: + dec->yMin = value / dec->scale; + break; + case DmtxPropYmax: + dec->yMax = value / dec->scale; + break; + default: + break; + } + + if (dec->squareDevn <= 0.0 || dec->squareDevn >= 1.0) + return DmtxFail; + + if (dec->scanGap < 1) + return DmtxFail; + + if (dec->edgeThresh < 1 || dec->edgeThresh > 100) + return DmtxFail; + + /* Reinitialize scangrid in case any inputs changed */ + dec->grid = InitScanGrid(dec); + + return DmtxPass; } /** @@ -158,40 +160,41 @@ dmtxDecodeSetProp(DmtxDecode *dec, int prop, int value) extern int dmtxDecodeGetProp(DmtxDecode *dec, int prop) { - switch(prop) { - case DmtxPropEdgeMin: - return dec->edgeMin; - case DmtxPropEdgeMax: - return dec->edgeMax; - case DmtxPropScanGap: - return dec->scanGap; - case DmtxPropFnc1: - return dec->fnc1; - case DmtxPropSquareDevn: - return (int)(acos(dec->squareDevn) * 180.0/M_PI); - case DmtxPropSymbolSize: - return dec->sizeIdxExpected; - case DmtxPropEdgeThresh: - return dec->edgeThresh; - case DmtxPropXmin: - return dec->xMin; - case DmtxPropXmax: - return dec->xMax; - case DmtxPropYmin: - return dec->yMin; - case DmtxPropYmax: - return dec->yMax; - case DmtxPropScale: - return dec->scale; - case DmtxPropWidth: - return dmtxImageGetProp(dec->image, DmtxPropWidth) / dec->scale; - case DmtxPropHeight: - return dmtxImageGetProp(dec->image, DmtxPropHeight) / dec->scale; - default: - break; - } - - return DmtxUndefined; + switch (prop) + { + case DmtxPropEdgeMin: + return dec->edgeMin; + case DmtxPropEdgeMax: + return dec->edgeMax; + case DmtxPropScanGap: + return dec->scanGap; + case DmtxPropFnc1: + return dec->fnc1; + case DmtxPropSquareDevn: + return (int)(acos(dec->squareDevn) * 180.0 / M_PI); + case DmtxPropSymbolSize: + return dec->sizeIdxExpected; + case DmtxPropEdgeThresh: + return dec->edgeThresh; + case DmtxPropXmin: + return dec->xMin; + case DmtxPropXmax: + return dec->xMax; + case DmtxPropYmin: + return dec->yMin; + case DmtxPropYmax: + return dec->yMax; + case DmtxPropScale: + return dec->scale; + case DmtxPropWidth: + return dmtxImageGetProp(dec->image, DmtxPropWidth) / dec->scale; + case DmtxPropHeight: + return dmtxImageGetProp(dec->image, DmtxPropHeight) / dec->scale; + default: + break; + } + + return DmtxUndefined; } /** @@ -204,20 +207,20 @@ dmtxDecodeGetProp(DmtxDecode *dec, int prop) extern unsigned char * dmtxDecodeGetCache(DmtxDecode *dec, int x, int y) { - int width, height; + int width, height; - assert(dec != NULL); + assert(dec != NULL); -/* if(dec.cacheComplete == DmtxFalse) - CacheImage(); */ + /* if(dec.cacheComplete == DmtxFalse) + CacheImage(); */ - width = dmtxDecodeGetProp(dec, DmtxPropWidth); - height = dmtxDecodeGetProp(dec, DmtxPropHeight); + width = dmtxDecodeGetProp(dec, DmtxPropWidth); + height = dmtxDecodeGetProp(dec, DmtxPropHeight); - if(x < 0 || x >= width || y < 0 || y >= height) - return NULL; + if (x < 0 || x >= width || y < 0 || y >= height) + return NULL; - return &(dec->cache[y * width + x]); + return &(dec->cache[y * width + x]); } /** @@ -227,38 +230,38 @@ dmtxDecodeGetCache(DmtxDecode *dec, int x, int y) extern DmtxPassFail dmtxDecodeGetPixelValue(DmtxDecode *dec, int x, int y, int channel, int *value) { - int xUnscaled, yUnscaled; - DmtxPassFail err; + int xUnscaled, yUnscaled; + DmtxPassFail err; - xUnscaled = x * dec->scale; - yUnscaled = y * dec->scale; + xUnscaled = x * dec->scale; + yUnscaled = y * dec->scale; -/* Remove spherical lens distortion */ -/* int width, height; - double radiusPow2, radiusPow4; - double factor; - DmtxVector2 pointShifted; - DmtxVector2 correctedPoint; + /* Remove spherical lens distortion */ + /* int width, height; + double radiusPow2, radiusPow4; + double factor; + DmtxVector2 pointShifted; + DmtxVector2 correctedPoint; - width = dmtxImageGetProp(img, DmtxPropWidth); - height = dmtxImageGetProp(img, DmtxPropHeight); + width = dmtxImageGetProp(img, DmtxPropWidth); + height = dmtxImageGetProp(img, DmtxPropHeight); - pointShifted.X = point.X - width/2.0; - pointShifted.Y = point.Y - height/2.0; + pointShifted.X = point.X - width/2.0; + pointShifted.Y = point.Y - height/2.0; - radiusPow2 = pointShifted.X * pointShifted.X + pointShifted.Y * pointShifted.Y; - radiusPow4 = radiusPow2 * radiusPow2; + radiusPow2 = pointShifted.X * pointShifted.X + pointShifted.Y * pointShifted.Y; + radiusPow4 = radiusPow2 * radiusPow2; - factor = 1 + (k1 * radiusPow2) + (k2 * radiusPow4); + factor = 1 + (k1 * radiusPow2) + (k2 * radiusPow4); - correctedPoint.X = pointShifted.X * factor + width/2.0; - correctedPoint.Y = pointShifted.Y * factor + height/2.0; + correctedPoint.X = pointShifted.X * factor + width/2.0; + correctedPoint.Y = pointShifted.Y * factor + height/2.0; - return correctedPoint; */ + return correctedPoint; */ - err = dmtxImageGetPixelValue(dec->image, xUnscaled, yUnscaled, channel, value); + err = dmtxImageGetPixelValue(dec->image, xUnscaled, yUnscaled, channel, value); - return err; + return err; } /** @@ -267,57 +270,65 @@ dmtxDecodeGetPixelValue(DmtxDecode *dec, int x, int y, int channel, int *value) static void CacheFillQuad(DmtxDecode *dec, DmtxPixelLoc p0, DmtxPixelLoc p1, DmtxPixelLoc p2, DmtxPixelLoc p3) { - DmtxBresLine lines[4]; - DmtxPixelLoc pEmpty = { 0, 0 }; - unsigned char *cache; - int *scanlineMin, *scanlineMax; - int minY, maxY, sizeY, posY, posX; - int i, idx; - - lines[0] = BresLineInit(p0, p1, pEmpty); - lines[1] = BresLineInit(p1, p2, pEmpty); - lines[2] = BresLineInit(p2, p3, pEmpty); - lines[3] = BresLineInit(p3, p0, pEmpty); - - minY = dec->yMax; - maxY = 0; - - minY = min(minY, p0.Y); maxY = max(maxY, p0.Y); - minY = min(minY, p1.Y); maxY = max(maxY, p1.Y); - minY = min(minY, p2.Y); maxY = max(maxY, p2.Y); - minY = min(minY, p3.Y); maxY = max(maxY, p3.Y); - - sizeY = maxY - minY + 1; - - scanlineMin = (int *)malloc(sizeY * sizeof(int)); - scanlineMax = (int *)calloc(sizeY, sizeof(int)); - - assert(scanlineMin); /* XXX handle this better */ - assert(scanlineMax); /* XXX handle this better */ - - for(i = 0; i < sizeY; i++) - scanlineMin[i] = dec->xMax; - - for(i = 0; i < 4; i++) { - while(lines[i].loc.X != lines[i].loc1.X || lines[i].loc.Y != lines[i].loc1.Y) { - idx = lines[i].loc.Y - minY; - scanlineMin[idx] = min(scanlineMin[idx], lines[i].loc.X); - scanlineMax[idx] = max(scanlineMax[idx], lines[i].loc.X); - BresLineStep(lines + i, 1, 0); - } - } - - for(posY = minY; posY < maxY && posY < dec->yMax; posY++) { - idx = posY - minY; - for(posX = scanlineMin[idx]; posX < scanlineMax[idx] && posX < dec->xMax; posX++) { - cache = dmtxDecodeGetCache(dec, posX, posY); - if(cache != NULL) - *cache |= 0x80; - } - } - - free(scanlineMin); - free(scanlineMax); + DmtxBresLine lines[4]; + DmtxPixelLoc pEmpty = {0, 0}; + unsigned char *cache; + int *scanlineMin, *scanlineMax; + int minY, maxY, sizeY, posY, posX; + int i, idx; + + lines[0] = BresLineInit(p0, p1, pEmpty); + lines[1] = BresLineInit(p1, p2, pEmpty); + lines[2] = BresLineInit(p2, p3, pEmpty); + lines[3] = BresLineInit(p3, p0, pEmpty); + + minY = dec->yMax; + maxY = 0; + + minY = min(minY, p0.Y); + maxY = max(maxY, p0.Y); + minY = min(minY, p1.Y); + maxY = max(maxY, p1.Y); + minY = min(minY, p2.Y); + maxY = max(maxY, p2.Y); + minY = min(minY, p3.Y); + maxY = max(maxY, p3.Y); + + sizeY = maxY - minY + 1; + + scanlineMin = (int *)malloc(sizeY * sizeof(int)); + scanlineMax = (int *)calloc(sizeY, sizeof(int)); + + assert(scanlineMin); /* XXX handle this better */ + assert(scanlineMax); /* XXX handle this better */ + + for (i = 0; i < sizeY; i++) + scanlineMin[i] = dec->xMax; + + for (i = 0; i < 4; i++) + { + while (lines[i].loc.X != lines[i].loc1.X || lines[i].loc.Y != lines[i].loc1.Y) + { + idx = lines[i].loc.Y - minY; + scanlineMin[idx] = min(scanlineMin[idx], lines[i].loc.X); + scanlineMax[idx] = max(scanlineMax[idx], lines[i].loc.X); + BresLineStep(lines + i, 1, 0); + } + } + + for (posY = minY; posY < maxY && posY < dec->yMax; posY++) + { + idx = posY - minY; + for (posX = scanlineMin[idx]; posX < scanlineMax[idx] && posX < dec->xMax; posX++) + { + cache = dmtxDecodeGetCache(dec, posX, posY); + if (cache != NULL) + *cache |= 0x80; + } + } + + free(scanlineMin); + free(scanlineMax); } /** @@ -330,42 +341,43 @@ CacheFillQuad(DmtxDecode *dec, DmtxPixelLoc p0, DmtxPixelLoc p1, DmtxPixelLoc p2 extern DmtxMessage * dmtxDecodeMatrixRegion(DmtxDecode *dec, DmtxRegion *reg, int fix) { - //fprintf(stdout, "libdmtx::dmtxDecodeMatrixRegion()\n"); - 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; - } - - msg->fnc1 = dec->fnc1; - - 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); - - return dmtxDecodePopulatedArray(reg->sizeIdx, msg, fix); + // fprintf(stdout, "libdmtx::dmtxDecodeMatrixRegion()\n"); + 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; + } + + msg->fnc1 = dec->fnc1; + + 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); + + return dmtxDecodePopulatedArray(reg->sizeIdx, msg, fix); } /** @@ -399,22 +411,42 @@ 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){ - dmtxMessageDestroy(&msg); - msg = NULL; - return NULL; - } - - if(DecodeDataStream(msg, sizeIdx, NULL) == DmtxFail) { - dmtxMessageDestroy(&msg); - msg = NULL; - return NULL; - } - - return msg; + /* + * Example msg->array indices for a 12x12 datamatrix. + * also, the 'L' color (usually black) is defined as 'DmtxModuleOnRGB' + * + * XX XX XX XX XX XX + * XX 0 1 2 3 4 5 6 7 8 9 XX + * XX 10 11 12 13 14 15 16 17 18 19 + * XX 20 21 22 23 24 25 26 27 28 29 XX + * XX 30 31 32 33 34 35 36 37 38 39 + * XX 40 41 42 43 44 45 46 47 48 49 XX + * XX 50 51 52 53 54 55 56 57 58 59 + * XX 60 61 62 63 64 65 66 67 68 69 XX + * XX 70 71 72 73 74 75 76 77 78 79 + * XX 80 81 82 83 84 85 86 87 88 89 XX + * XX 90 91 92 93 94 95 96 97 98 99 + * 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) + { + dmtxMessageDestroy(&msg); + msg = NULL; + return NULL; + } + + if (DecodeDataStream(msg, sizeIdx, NULL) == DmtxFail) + { + dmtxMessageDestroy(&msg); + msg = NULL; + return NULL; + } + + return msg; } /** @@ -427,61 +459,62 @@ dmtxDecodePopulatedArray(int sizeIdx, DmtxMessage *msg, int fix) 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; + 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; } /** @@ -491,81 +524,88 @@ dmtxDecodeMosaicRegion(DmtxDecode *dec, DmtxRegion *reg, int fix) extern unsigned char * dmtxDecodeCreateDiagnostic(DmtxDecode *dec, int *totalBytes, int *headerBytes, int style) { - int i, row, col; - int width, height; - int widthDigits, heightDigits; - int count, channelCount; - int rgb[3]; - double shade; - unsigned char *pnm, *output, *cache; + int i, row, col; + int width, height; + int widthDigits, heightDigits; + int count, channelCount; + int rgb[3]; + double shade; + unsigned char *pnm, *output, *cache; - width = dmtxDecodeGetProp(dec, DmtxPropWidth); - height = dmtxDecodeGetProp(dec, DmtxPropHeight); - channelCount = dmtxImageGetProp(dec->image, DmtxPropChannelCount); + width = dmtxDecodeGetProp(dec, DmtxPropWidth); + height = dmtxDecodeGetProp(dec, DmtxPropHeight); + channelCount = dmtxImageGetProp(dec->image, DmtxPropChannelCount); - style = 1; /* this doesn't mean anything yet */ + style = 1; /* this doesn't mean anything yet */ - /* Count width digits */ - for(widthDigits = 0, i = width; i > 0; i /= 10) - widthDigits++; + /* Count width digits */ + for (widthDigits = 0, i = width; i > 0; i /= 10) + widthDigits++; - /* Count height digits */ - for(heightDigits = 0, i = height; i > 0; i /= 10) - heightDigits++; + /* Count height digits */ + for (heightDigits = 0, i = height; i > 0; i /= 10) + heightDigits++; - *headerBytes = widthDigits + heightDigits + 9; - *totalBytes = *headerBytes + width * height * 3; + *headerBytes = widthDigits + heightDigits + 9; + *totalBytes = *headerBytes + width * height * 3; - pnm = (unsigned char *)malloc(*totalBytes); - if(pnm == NULL) - return NULL; + pnm = (unsigned char *)malloc(*totalBytes); + if (pnm == NULL) + return NULL; #if defined(_MSC_VER) && (_MSC_VER < 1700) - count = sprintf_s((char *)pnm, *headerBytes + 1, "P6\n%d %d\n255\n", width, height); + count = sprintf_s((char *)pnm, *headerBytes + 1, "P6\n%d %d\n255\n", width, height); #else - count = snprintf((char *)pnm, *headerBytes + 1, "P6\n%d %d\n255\n", width, height); + count = snprintf((char *)pnm, *headerBytes + 1, "P6\n%d %d\n255\n", width, height); #endif - if(count != *headerBytes) { - free(pnm); - return NULL; - } - - output = pnm + (*headerBytes); - for(row = height - 1; row >= 0; row--) { - for(col = 0; col < width; col++) { - cache = dmtxDecodeGetCache(dec, col, row); - if(cache == NULL) { - rgb[0] = 0; - rgb[1] = 0; - rgb[2] = 128; - } - else if(*cache & 0x40) { - rgb[0] = 255; - rgb[1] = 0; - rgb[2] = 0; - } - else { - shade = (*cache & 0x80) ? 0.0 : 0.7; - for(i = 0; i < 3; i++) { - if(i < channelCount) - dmtxDecodeGetPixelValue(dec, col, row, i, &rgb[i]); - else - dmtxDecodeGetPixelValue(dec, col, row, 0, &rgb[i]); - - rgb[i] += (int)(shade * (double)(255 - rgb[i]) + 0.5); - if(rgb[i] > 255) - rgb[i] = 255; + if (count != *headerBytes) + { + free(pnm); + return NULL; + } + + output = pnm + (*headerBytes); + for (row = height - 1; row >= 0; row--) + { + for (col = 0; col < width; col++) + { + cache = dmtxDecodeGetCache(dec, col, row); + if (cache == NULL) + { + rgb[0] = 0; + rgb[1] = 0; + rgb[2] = 128; + } + else if (*cache & 0x40) + { + rgb[0] = 255; + rgb[1] = 0; + rgb[2] = 0; + } + else + { + shade = (*cache & 0x80) ? 0.0 : 0.7; + for (i = 0; i < 3; i++) + { + if (i < channelCount) + dmtxDecodeGetPixelValue(dec, col, row, i, &rgb[i]); + else + dmtxDecodeGetPixelValue(dec, col, row, 0, &rgb[i]); + + rgb[i] += (int)(shade * (double)(255 - rgb[i]) + 0.5); + if (rgb[i] > 255) + rgb[i] = 255; + } } - } - *(output++) = (unsigned char)rgb[0]; - *(output++) = (unsigned char)rgb[1]; - *(output++) = (unsigned char)rgb[2]; - } - } - assert(output == pnm + *totalBytes); - - return pnm; + *(output++) = (unsigned char)rgb[0]; + *(output++) = (unsigned char)rgb[1]; + *(output++) = (unsigned char)rgb[2]; + } + } + assert(output == pnm + *totalBytes); + + return pnm; } /** @@ -583,106 +623,116 @@ dmtxDecodeCreateDiagnostic(DmtxDecode *dec, int *totalBytes, int *headerBytes, i static void TallyModuleJumps(DmtxDecode *dec, DmtxRegion *reg, int tally[][24], int xOrigin, int yOrigin, int mapWidth, int mapHeight, DmtxDirection dir) { - int extent, weight; - int travelStep; - int symbolRow, symbolCol; - int mapRow, mapCol; - int lineStart, lineStop; - int travelStart, travelStop; - int *line, *travel; - int jumpThreshold; - int darkOnLight; - int color; - int statusPrev, statusModule; - int tPrev, tModule; - - assert(dir == DmtxDirUp || dir == DmtxDirLeft || dir == DmtxDirDown || dir == DmtxDirRight); - - travelStep = (dir == DmtxDirUp || dir == DmtxDirRight) ? 1 : -1; - - /* Abstract row and column progress using pointers to allow grid - traversal in all 4 directions using same logic */ - - if((dir & DmtxDirHorizontal) != 0x00) { - line = &symbolRow; - travel = &symbolCol; - extent = mapWidth; - lineStart = yOrigin; - lineStop = yOrigin + mapHeight; - travelStart = (travelStep == 1) ? xOrigin - 1 : xOrigin + mapWidth; - travelStop = (travelStep == 1) ? xOrigin + mapWidth : xOrigin - 1; - } - else { - assert(dir & DmtxDirVertical); - line = &symbolCol; - travel = &symbolRow; - extent = mapHeight; - lineStart = xOrigin; - lineStop = xOrigin + mapWidth; - travelStart = (travelStep == 1) ? yOrigin - 1: yOrigin + mapHeight; - travelStop = (travelStep == 1) ? yOrigin + mapHeight : yOrigin - 1; - } - - - darkOnLight = (int)(reg->offColor > reg->onColor); - jumpThreshold = abs((int)(0.4 * (reg->offColor - reg->onColor) + 0.5)); - - assert(jumpThreshold >= 0); - - for(*line = lineStart; *line < lineStop; (*line)++) { - - /* Capture tModule for each leading border module as normal but - decide status based on predictable barcode border pattern */ - - - - *travel = travelStart; - color = ReadModuleColor(dec, reg, symbolRow, symbolCol, reg->sizeIdx, reg->flowBegin.plane); - tModule = (darkOnLight) ? reg->offColor - color : color - reg->offColor; - - statusModule = (travelStep == 1 || (*line & 0x01) == 0) ? DmtxModuleOnRGB : DmtxModuleOff; - - weight = extent; - - while((*travel += travelStep) != travelStop) { - - tPrev = tModule; - statusPrev = statusModule; - - /* For normal data-bearing modules capture color and decide - module status based on comparison to previous "known" module */ - - color = ReadModuleColor(dec, reg, symbolRow, symbolCol, reg->sizeIdx, reg->flowBegin.plane); - tModule = (darkOnLight) ? reg->offColor - color : color - reg->offColor; - - if(statusPrev == DmtxModuleOnRGB) { - if(tModule < tPrev - jumpThreshold){ - statusModule = DmtxModuleOff; - } else { - statusModule = DmtxModuleOnRGB; + int extent, weight; + int travelStep; + int symbolRow, symbolCol; + int mapRow, mapCol; + int lineStart, lineStop; + int travelStart, travelStop; + int *line, *travel; + int jumpThreshold; + int darkOnLight; + int color; + int statusPrev, statusModule; + int tPrev, tModule; + + assert(dir == DmtxDirUp || dir == DmtxDirLeft || dir == DmtxDirDown || dir == DmtxDirRight); + + travelStep = (dir == DmtxDirUp || dir == DmtxDirRight) ? 1 : -1; + + /* Abstract row and column progress using pointers to allow grid + traversal in all 4 directions using same logic */ + + if ((dir & DmtxDirHorizontal) != 0x00) + { + line = &symbolRow; + travel = &symbolCol; + extent = mapWidth; + lineStart = yOrigin; + lineStop = yOrigin + mapHeight; + travelStart = (travelStep == 1) ? xOrigin - 1 : xOrigin + mapWidth; + travelStop = (travelStep == 1) ? xOrigin + mapWidth : xOrigin - 1; + } + else + { + assert(dir & DmtxDirVertical); + line = &symbolCol; + travel = &symbolRow; + extent = mapHeight; + lineStart = xOrigin; + lineStop = xOrigin + mapWidth; + travelStart = (travelStep == 1) ? yOrigin - 1 : yOrigin + mapHeight; + travelStop = (travelStep == 1) ? yOrigin + mapHeight : yOrigin - 1; + } + + darkOnLight = (int)(reg->offColor > reg->onColor); + jumpThreshold = abs((int)(0.4 * (reg->offColor - reg->onColor) + 0.5)); + + assert(jumpThreshold >= 0); + + for (*line = lineStart; *line < lineStop; (*line)++) + { + + /* Capture tModule for each leading border module as normal but + decide status based on predictable barcode border pattern */ + + *travel = travelStart; + color = ReadModuleColor(dec, reg, symbolRow, symbolCol, reg->sizeIdx, reg->flowBegin.plane); + tModule = (darkOnLight) ? reg->offColor - color : color - reg->offColor; + + statusModule = (travelStep == 1 || (*line & 0x01) == 0) ? DmtxModuleOnRGB : DmtxModuleOff; + + weight = extent; + + while ((*travel += travelStep) != travelStop) + { + + tPrev = tModule; + statusPrev = statusModule; + + /* For normal data-bearing modules capture color and decide + module status based on comparison to previous "known" module */ + + color = ReadModuleColor(dec, reg, symbolRow, symbolCol, reg->sizeIdx, reg->flowBegin.plane); + tModule = (darkOnLight) ? reg->offColor - color : color - reg->offColor; + + if (statusPrev == DmtxModuleOnRGB) + { + if (tModule < tPrev - jumpThreshold) + { + statusModule = DmtxModuleOff; + } + else + { + statusModule = DmtxModuleOnRGB; + } } - } - else if(statusPrev == DmtxModuleOff) { - if(tModule > tPrev + jumpThreshold) { - statusModule = DmtxModuleOnRGB; - } else { - statusModule = DmtxModuleOff; + else if (statusPrev == DmtxModuleOff) + { + if (tModule > tPrev + jumpThreshold) + { + statusModule = DmtxModuleOnRGB; + } + else + { + statusModule = DmtxModuleOff; + } } - } - mapRow = symbolRow - yOrigin; - mapCol = symbolCol - xOrigin; - assert(mapRow < 24 && mapCol < 24); + mapRow = symbolRow - yOrigin; + mapCol = symbolCol - xOrigin; + assert(mapRow < 24 && mapCol < 24); - if(statusModule == DmtxModuleOnRGB){ - tally[mapRow][mapCol] += (2 * weight); - } + if (statusModule == DmtxModuleOnRGB) + { + tally[mapRow][mapCol] += (2 * weight); + } - weight--; - } + weight--; + } - assert(weight == 0); - } + assert(weight == 0); + } } /** @@ -695,93 +745,99 @@ TallyModuleJumps(DmtxDecode *dec, DmtxRegion *reg, int tally[][24], int xOrigin, static DmtxPassFail PopulateArrayFromMatrix(DmtxDecode *dec, DmtxRegion *reg, DmtxMessage *msg) { - //fprintf(stdout, "libdmtx::PopulateArrayFromMatrix()\n"); - int weightFactor; - int mapWidth, mapHeight; - int xRegionTotal, yRegionTotal; - int xRegionCount, yRegionCount; - int xOrigin, yOrigin; - int mapCol, mapRow; - int colTmp, rowTmp, idx; - int tally[24][24]; /* Large enough to map largest single region */ - -/* memset(msg->array, 0x00, msg->arraySize); */ - - /* Capture number of regions present in barcode */ - xRegionTotal = dmtxGetSymbolAttribute(DmtxSymAttribHorizDataRegions, reg->sizeIdx); - yRegionTotal = dmtxGetSymbolAttribute(DmtxSymAttribVertDataRegions, reg->sizeIdx); - - /* Capture region dimensions (not including border modules) */ - mapWidth = dmtxGetSymbolAttribute(DmtxSymAttribDataRegionCols, reg->sizeIdx); - mapHeight = dmtxGetSymbolAttribute(DmtxSymAttribDataRegionRows, reg->sizeIdx); - - weightFactor = 2 * (mapHeight + mapWidth + 2); - assert(weightFactor > 0); - - //fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::reg->sizeIdx: %d\n", reg->sizeIdx); - //fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::reg->flowBegin.plane: %d\n", reg->flowBegin.plane); - //fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::reg->onColor: %d\n", reg->onColor); - //fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::reg->offColor: %d\n", reg->offColor); - //fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::xRegionTotal: %d\n", xRegionTotal); - //fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::yRegionTotal: %d\n", yRegionTotal); - //fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::mapWidth: %d\n", mapWidth); - //fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::mapHeight: %d\n", mapHeight); - //fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::weightFactor: %d\n", weightFactor); - //reg->fit2raw[1][0]=0; - //reg->fit2raw[0][1]=0; - //reg->fit2raw[0][2]=0; - //reg->fit2raw[2][2]=1; - //reg->fit2raw[1][2]=0; - //reg->fit2raw[2][0]=10; //translation - //reg->fit2raw[2][1]=10; //translation - //reg->fit2raw[0][0]=60; //scale - //reg->fit2raw[1][1]=60; //scale - //dmtxMatrix3Print(reg->fit2raw); - - - /* Tally module changes for each region in each direction */ - for(yRegionCount = 0; yRegionCount < yRegionTotal; yRegionCount++) { - - /* Y location of mapping region origin in symbol coordinates */ - yOrigin = yRegionCount * (mapHeight + 2) + 1; - - 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); - - 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); - TallyModuleJumps(dec, reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirDown); - TallyModuleJumps(dec, reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirRight); - - /* Decide module status based on final tallies */ - for(mapRow = 0; mapRow < mapHeight; mapRow++) { - //for(mapRow = mapHeight-1; mapRow >= 0; mapRow--) { - for(mapCol = 0; mapCol < mapWidth; mapCol++) { - - rowTmp = (yRegionCount * mapHeight) + mapRow; - rowTmp = yRegionTotal * mapHeight - rowTmp - 1; - colTmp = (xRegionCount * mapWidth) + mapCol; - idx = (rowTmp * xRegionTotal * mapWidth) + colTmp; - //fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::idx: %d @ %d,%d\n", idx, mapCol, mapRow); - //fprintf(stdout, "%c ",tally[mapRow][mapCol]==DmtxModuleOff ? 'X' : ' '); - if(tally[mapRow][mapCol]/(double)weightFactor >= 0.5){ - msg->array[idx] = DmtxModuleOnRGB; - //fprintf(stdout, "X "); - } else { - msg->array[idx] = DmtxModuleOff; - //fprintf(stdout, " "); - } - - msg->array[idx] |= DmtxModuleAssigned; + // fprintf(stdout, "libdmtx::PopulateArrayFromMatrix()\n"); + int weightFactor; + int mapWidth, mapHeight; + int xRegionTotal, yRegionTotal; + int xRegionCount, yRegionCount; + int xOrigin, yOrigin; + int mapCol, mapRow; + int colTmp, rowTmp, idx; + int tally[24][24]; /* Large enough to map largest single region */ + + /* memset(msg->array, 0x00, msg->arraySize); */ + + /* Capture number of regions present in barcode */ + xRegionTotal = dmtxGetSymbolAttribute(DmtxSymAttribHorizDataRegions, reg->sizeIdx); + yRegionTotal = dmtxGetSymbolAttribute(DmtxSymAttribVertDataRegions, reg->sizeIdx); + + /* Capture region dimensions (not including border modules) */ + mapWidth = dmtxGetSymbolAttribute(DmtxSymAttribDataRegionCols, reg->sizeIdx); + mapHeight = dmtxGetSymbolAttribute(DmtxSymAttribDataRegionRows, reg->sizeIdx); + + weightFactor = 2 * (mapHeight + mapWidth + 2); + assert(weightFactor > 0); + + // fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::reg->sizeIdx: %d\n", reg->sizeIdx); + // fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::reg->flowBegin.plane: %d\n", reg->flowBegin.plane); + // fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::reg->onColor: %d\n", reg->onColor); + // fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::reg->offColor: %d\n", reg->offColor); + // fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::xRegionTotal: %d\n", xRegionTotal); + // fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::yRegionTotal: %d\n", yRegionTotal); + // fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::mapWidth: %d\n", mapWidth); + // fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::mapHeight: %d\n", mapHeight); + // fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::weightFactor: %d\n", weightFactor); + // reg->fit2raw[1][0]=0; + // reg->fit2raw[0][1]=0; + // reg->fit2raw[0][2]=0; + // reg->fit2raw[2][2]=1; + // reg->fit2raw[1][2]=0; + // reg->fit2raw[2][0]=10; //translation + // reg->fit2raw[2][1]=10; //translation + // reg->fit2raw[0][0]=60; //scale + // reg->fit2raw[1][1]=60; //scale + // dmtxMatrix3Print(reg->fit2raw); + + /* Tally module changes for each region in each direction */ + for (yRegionCount = 0; yRegionCount < yRegionTotal; yRegionCount++) + { + + /* Y location of mapping region origin in symbol coordinates */ + yOrigin = yRegionCount * (mapHeight + 2) + 1; + + 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); + + 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); + TallyModuleJumps(dec, reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirDown); + TallyModuleJumps(dec, reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirRight); + + /* Decide module status based on final tallies */ + for (mapRow = 0; mapRow < mapHeight; mapRow++) + { + // for(mapRow = mapHeight-1; mapRow >= 0; mapRow--) { + for (mapCol = 0; mapCol < mapWidth; mapCol++) + { + + rowTmp = (yRegionCount * mapHeight) + mapRow; + rowTmp = yRegionTotal * mapHeight - rowTmp - 1; + colTmp = (xRegionCount * mapWidth) + mapCol; + idx = (rowTmp * xRegionTotal * mapWidth) + colTmp; + // fprintf(stdout, "libdmtx::PopulateArrayFromMatrix::idx: %d @ %d,%d\n", idx, mapCol, mapRow); + // fprintf(stdout, "%c ",tally[mapRow][mapCol]==DmtxModuleOff ? 'X' : ' '); + if (tally[mapRow][mapCol] / (double)weightFactor >= 0.5) + { + msg->array[idx] = DmtxModuleOnRGB; + // fprintf(stdout, "X "); + } + else + { + msg->array[idx] = DmtxModuleOff; + // fprintf(stdout, " "); + } + + msg->array[idx] |= DmtxModuleAssigned; + } + // fprintf(stdout, "\n"); } - //fprintf(stdout, "\n"); - } - } - } + } + } - return DmtxPass; + return DmtxPass; } diff --git a/dmtxdecodescheme.c b/dmtxdecodescheme.c index e710cf2b..a7ad4806 100644 --- a/dmtxdecodescheme.c +++ b/dmtxdecodescheme.c @@ -24,68 +24,71 @@ extern DmtxPassFail DecodeDataStream(DmtxMessage *msg, int sizeIdx, unsigned char *outputStart) { - //fprintf(stdout, "libdmtx::DecodeDataStream()\n"); - //int oned = sqrt(msg->arraySize); - //for (int i=0; iarraySize; i++){ - // fprintf(stdout, " %c.", msg->array[i]); - // if (i%oned==oned-1){ - // fprintf(stdout, "\n"); - // } - //} - - DmtxBoolean macro = DmtxFalse; - DmtxScheme encScheme; - unsigned char *ptr, *dataEnd; - - msg->output = (outputStart == NULL) ? msg->output : outputStart; - msg->outputIdx = 0; - - ptr = msg->code; - dataEnd = ptr + dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx); - - /* Print macro header if first codeword triggers it */ - if(*ptr == DmtxValue05Macro || *ptr == DmtxValue06Macro) { - PushOutputMacroHeader(msg, *ptr); - macro = DmtxTrue; - } - - while(ptr < dataEnd) { - - encScheme = GetEncodationScheme(*ptr); - if(encScheme != DmtxSchemeAscii) - ptr++; - - switch(encScheme) { - case DmtxSchemeAscii: + // fprintf(stdout, "libdmtx::DecodeDataStream()\n"); + // int oned = sqrt(msg->arraySize); + // for (int i=0; iarraySize; i++){ + // fprintf(stdout, " %c.", msg->array[i]); + // if (i%oned==oned-1){ + // fprintf(stdout, "\n"); + // } + // } + + DmtxBoolean macro = DmtxFalse; + DmtxScheme encScheme; + unsigned char *ptr, *dataEnd; + + msg->output = (outputStart == NULL) ? msg->output : outputStart; + msg->outputIdx = 0; + + ptr = msg->code; + dataEnd = ptr + dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx); + + /* Print macro header if first codeword triggers it */ + if (*ptr == DmtxValue05Macro || *ptr == DmtxValue06Macro) + { + PushOutputMacroHeader(msg, *ptr); + macro = DmtxTrue; + } + + while (ptr < dataEnd) + { + + encScheme = GetEncodationScheme(*ptr); + if (encScheme != DmtxSchemeAscii) + ptr++; + + switch (encScheme) + { + case DmtxSchemeAscii: ptr = DecodeSchemeAscii(msg, ptr, dataEnd); break; - case DmtxSchemeC40: - case DmtxSchemeText: + case DmtxSchemeC40: + case DmtxSchemeText: ptr = DecodeSchemeC40Text(msg, ptr, dataEnd, encScheme); break; - case DmtxSchemeX12: + case DmtxSchemeX12: ptr = DecodeSchemeX12(msg, ptr, dataEnd); break; - case DmtxSchemeEdifact: + case DmtxSchemeEdifact: ptr = DecodeSchemeEdifact(msg, ptr, dataEnd); break; - case DmtxSchemeBase256: + case DmtxSchemeBase256: ptr = DecodeSchemeBase256(msg, ptr, dataEnd); break; - default: + default: /* error */ break; - } + } - if(ptr == NULL) - return DmtxFail; - } + if (ptr == NULL) + return DmtxFail; + } - /* Print macro trailer if required */ - if(macro == DmtxTrue) - PushOutputMacroTrailer(msg); + /* Print macro trailer if required */ + if (macro == DmtxTrue) + PushOutputMacroTrailer(msg); - return DmtxPass; + return DmtxPass; } /** @@ -97,30 +100,31 @@ DecodeDataStream(DmtxMessage *msg, int sizeIdx, unsigned char *outputStart) static int GetEncodationScheme(unsigned char cw) { - DmtxScheme encScheme; - - switch(cw) { - case DmtxValueC40Latch: - encScheme = DmtxSchemeC40; - break; - case DmtxValueTextLatch: - encScheme = DmtxSchemeText; - break; - case DmtxValueX12Latch: - encScheme = DmtxSchemeX12; - break; - case DmtxValueEdifactLatch: - encScheme = DmtxSchemeEdifact; - break; - case DmtxValueBase256Latch: - encScheme = DmtxSchemeBase256; - break; - default: - encScheme = DmtxSchemeAscii; - break; - } - - return encScheme; + DmtxScheme encScheme; + + switch (cw) + { + case DmtxValueC40Latch: + encScheme = DmtxSchemeC40; + break; + case DmtxValueTextLatch: + encScheme = DmtxSchemeText; + break; + case DmtxValueX12Latch: + encScheme = DmtxSchemeX12; + break; + case DmtxValueEdifactLatch: + encScheme = DmtxSchemeEdifact; + break; + case DmtxValueBase256Latch: + encScheme = DmtxSchemeBase256; + break; + default: + encScheme = DmtxSchemeAscii; + break; + } + + return encScheme; } /** @@ -130,19 +134,19 @@ GetEncodationScheme(unsigned char cw) static void PushOutputWord(DmtxMessage *msg, int value) { - assert(value >= 0 && value < 256); + assert(value >= 0 && value < 256); - msg->output[msg->outputIdx++] = (unsigned char)value; + msg->output[msg->outputIdx++] = (unsigned char)value; } /** -* -* -*/ + * + * + */ static DmtxBoolean ValidOutputWord(int value) { - return (value >= 0 && value < 256) ? DmtxTrue : DmtxFalse; + return (value >= 0 && value < 256) ? DmtxTrue : DmtxFalse; } /** @@ -152,19 +156,20 @@ ValidOutputWord(int value) static void PushOutputC40TextWord(DmtxMessage *msg, C40TextState *state, int value) { - assert(value >= 0 && value < 256); + assert(value >= 0 && value < 256); - msg->output[msg->outputIdx] = (unsigned char)value; + msg->output[msg->outputIdx] = (unsigned char)value; - if(state->upperShift == DmtxTrue) { - assert(value < 128); - msg->output[msg->outputIdx] += 128; - } + if (state->upperShift == DmtxTrue) + { + assert(value < 128); + msg->output[msg->outputIdx] += 128; + } - msg->outputIdx++; + msg->outputIdx++; - state->shift = DmtxC40TextBasicSet; - state->upperShift = DmtxFalse; + state->shift = DmtxC40TextBasicSet; + state->upperShift = DmtxFalse; } /** @@ -174,19 +179,19 @@ PushOutputC40TextWord(DmtxMessage *msg, C40TextState *state, int value) static void PushOutputMacroHeader(DmtxMessage *msg, int macroType) { - PushOutputWord(msg, '['); - PushOutputWord(msg, ')'); - PushOutputWord(msg, '>'); - PushOutputWord(msg, 30); /* ASCII RS */ - PushOutputWord(msg, '0'); - - assert(macroType == DmtxValue05Macro || macroType == DmtxValue06Macro); - if(macroType == DmtxValue05Macro) - PushOutputWord(msg, '5'); - else - PushOutputWord(msg, '6'); - - PushOutputWord(msg, 29); /* ASCII GS */ + PushOutputWord(msg, '['); + PushOutputWord(msg, ')'); + PushOutputWord(msg, '>'); + PushOutputWord(msg, 30); /* ASCII RS */ + PushOutputWord(msg, '0'); + + assert(macroType == DmtxValue05Macro || macroType == DmtxValue06Macro); + if (macroType == DmtxValue05Macro) + PushOutputWord(msg, '5'); + else + PushOutputWord(msg, '6'); + + PushOutputWord(msg, 29); /* ASCII GS */ } /** @@ -196,8 +201,8 @@ PushOutputMacroHeader(DmtxMessage *msg, int macroType) static void PushOutputMacroTrailer(DmtxMessage *msg) { - PushOutputWord(msg, 30); /* ASCII RS */ - PushOutputWord(msg, 4); /* ASCII EOT */ + PushOutputWord(msg, 30); /* ASCII RS */ + PushOutputWord(msg, 4); /* ASCII EOT */ } /** @@ -211,54 +216,63 @@ PushOutputMacroTrailer(DmtxMessage *msg) static unsigned char * DecodeSchemeAscii(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd) { - int upperShift = DmtxFalse; - - while(ptr < dataEnd) { - int codeword = (int)(*ptr); - - if(GetEncodationScheme(*ptr) != DmtxSchemeAscii) - return ptr; - else - ptr++; - - if(upperShift == DmtxTrue) { - int pushword = codeword + 127; - if (ValidOutputWord(pushword) != DmtxTrue) - return NULL; - PushOutputWord(msg, pushword); - upperShift = DmtxFalse; - } - else if(codeword == DmtxValueAsciiUpperShift) { - upperShift = DmtxTrue; - } - else if(codeword == DmtxValueAsciiPad) { - assert(dataEnd >= ptr); - assert(dataEnd - ptr <= INT_MAX); - msg->padCount = (int)(dataEnd - ptr); - return dataEnd; - } - else if(codeword == 0 || codeword >= 242) { - return ptr; - } - else if(codeword <= 128) { - PushOutputWord(msg, codeword - 1); - } - else if(codeword <= 229) { - int digits = codeword - 130; - PushOutputWord(msg, digits/10 + '0'); - PushOutputWord(msg, digits - (digits/10)*10 + '0'); - } - else if(codeword == DmtxValueFNC1) { - if(msg->fnc1 != DmtxUndefined) { - int pushword = msg->fnc1; - if (ValidOutputWord(pushword) != DmtxTrue) + int upperShift = DmtxFalse; + + while (ptr < dataEnd) + { + int codeword = (int)(*ptr); + + if (GetEncodationScheme(*ptr) != DmtxSchemeAscii) + return ptr; + else + ptr++; + + if (upperShift == DmtxTrue) + { + int pushword = codeword + 127; + if (ValidOutputWord(pushword) != DmtxTrue) return NULL; - PushOutputWord(msg, pushword); - } - } - } + PushOutputWord(msg, pushword); + upperShift = DmtxFalse; + } + else if (codeword == DmtxValueAsciiUpperShift) + { + upperShift = DmtxTrue; + } + else if (codeword == DmtxValueAsciiPad) + { + assert(dataEnd >= ptr); + assert(dataEnd - ptr <= INT_MAX); + msg->padCount = (int)(dataEnd - ptr); + return dataEnd; + } + else if (codeword == 0 || codeword >= 242) + { + return ptr; + } + else if (codeword <= 128) + { + PushOutputWord(msg, codeword - 1); + } + else if (codeword <= 229) + { + int digits = codeword - 130; + PushOutputWord(msg, digits / 10 + '0'); + PushOutputWord(msg, digits - (digits / 10) * 10 + '0'); + } + else if (codeword == DmtxValueFNC1) + { + if (msg->fnc1 != DmtxUndefined) + { + int pushword = msg->fnc1; + if (ValidOutputWord(pushword) != DmtxTrue) + return NULL; + PushOutputWord(msg, pushword); + } + } + } - return ptr; + return ptr; } /** @@ -272,97 +286,117 @@ DecodeSchemeAscii(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd) static unsigned char * DecodeSchemeC40Text(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd, DmtxScheme encScheme) { - int i; - int packed; - int c40Values[3]; - C40TextState state; - - state.shift = DmtxC40TextBasicSet; - state.upperShift = DmtxFalse; + int i; + int packed; + int c40Values[3]; + C40TextState state; - assert(encScheme == DmtxSchemeC40 || encScheme == DmtxSchemeText); + state.shift = DmtxC40TextBasicSet; + state.upperShift = DmtxFalse; - /* Unlatch is implied if only one codeword remains */ - if(dataEnd - ptr < 2) - return ptr; + assert(encScheme == DmtxSchemeC40 || encScheme == DmtxSchemeText); - while(ptr < dataEnd) { - - /* FIXME Also check that ptr+1 is safe to access */ - packed = (*ptr << 8) | *(ptr+1); - c40Values[0] = ((packed - 1)/1600); - c40Values[1] = ((packed - 1)/40) % 40; - c40Values[2] = (packed - 1) % 40; - ptr += 2; + /* Unlatch is implied if only one codeword remains */ + if (dataEnd - ptr < 2) + return ptr; - for(i = 0; i < 3; i++) { - if(state.shift == DmtxC40TextBasicSet) { /* Basic set */ - if(c40Values[i] <= 2) { - state.shift = c40Values[i] + 1; - } - else if(c40Values[i] == 3) { - PushOutputC40TextWord(msg, &state, ' '); - } - else if(c40Values[i] <= 13) { - PushOutputC40TextWord(msg, &state, c40Values[i] - 13 + '9'); /* 0-9 */ + while (ptr < dataEnd) + { + + /* FIXME Also check that ptr+1 is safe to access */ + packed = (*ptr << 8) | *(ptr + 1); + c40Values[0] = ((packed - 1) / 1600); + c40Values[1] = ((packed - 1) / 40) % 40; + c40Values[2] = (packed - 1) % 40; + ptr += 2; + + for (i = 0; i < 3; i++) + { + if (state.shift == DmtxC40TextBasicSet) + { /* Basic set */ + if (c40Values[i] <= 2) + { + state.shift = c40Values[i] + 1; + } + else if (c40Values[i] == 3) + { + PushOutputC40TextWord(msg, &state, ' '); + } + else if (c40Values[i] <= 13) + { + PushOutputC40TextWord(msg, &state, c40Values[i] - 13 + '9'); /* 0-9 */ + } + else if (c40Values[i] <= 39) + { + if (encScheme == DmtxSchemeC40) + { + PushOutputC40TextWord(msg, &state, c40Values[i] - 39 + 'Z'); /* A-Z */ + } + else if (encScheme == DmtxSchemeText) + { + PushOutputC40TextWord(msg, &state, c40Values[i] - 39 + 'z'); /* a-z */ + } + } } - else if(c40Values[i] <= 39) { - if(encScheme == DmtxSchemeC40) { - PushOutputC40TextWord(msg, &state, c40Values[i] - 39 + 'Z'); /* A-Z */ - } - else if(encScheme == DmtxSchemeText) { - PushOutputC40TextWord(msg, &state, c40Values[i] - 39 + 'z'); /* a-z */ - } + else if (state.shift == DmtxC40TextShift1) + { /* Shift 1 set */ + PushOutputC40TextWord(msg, &state, c40Values[i]); /* ASCII 0 - 31 */ } - } - else if(state.shift == DmtxC40TextShift1) { /* Shift 1 set */ - PushOutputC40TextWord(msg, &state, c40Values[i]); /* ASCII 0 - 31 */ - } - else if(state.shift == DmtxC40TextShift2) { /* Shift 2 set */ - if(c40Values[i] <= 14) { - PushOutputC40TextWord(msg, &state, c40Values[i] + 33); /* ASCII 33 - 47 */ + else if (state.shift == DmtxC40TextShift2) + { /* Shift 2 set */ + if (c40Values[i] <= 14) + { + PushOutputC40TextWord(msg, &state, c40Values[i] + 33); /* ASCII 33 - 47 */ + } + else if (c40Values[i] <= 21) + { + PushOutputC40TextWord(msg, &state, c40Values[i] + 43); /* ASCII 58 - 64 */ + } + else if (c40Values[i] <= 26) + { + PushOutputC40TextWord(msg, &state, c40Values[i] + 69); /* ASCII 91 - 95 */ + } + else if (c40Values[i] == 27) + { + if (msg->fnc1 != DmtxUndefined) + { + PushOutputC40TextWord(msg, &state, msg->fnc1); + } + } + else if (c40Values[i] == 30) + { + state.upperShift = DmtxTrue; + state.shift = DmtxC40TextBasicSet; + } } - else if(c40Values[i] <= 21) { - PushOutputC40TextWord(msg, &state, c40Values[i] + 43); /* ASCII 58 - 64 */ + else if (state.shift == DmtxC40TextShift3) + { /* Shift 3 set */ + if (encScheme == DmtxSchemeC40) + { + PushOutputC40TextWord(msg, &state, c40Values[i] + 96); + } + else if (encScheme == DmtxSchemeText) + { + if (c40Values[i] == 0) + PushOutputC40TextWord(msg, &state, c40Values[i] + 96); + else if (c40Values[i] <= 26) + PushOutputC40TextWord(msg, &state, c40Values[i] - 26 + 'Z'); /* A-Z */ + else + PushOutputC40TextWord(msg, &state, c40Values[i] - 31 + 127); /* { | } ~ DEL */ + } } - else if(c40Values[i] <= 26) { - PushOutputC40TextWord(msg, &state, c40Values[i] + 69); /* ASCII 91 - 95 */ - } - else if(c40Values[i] == 27) { - if(msg->fnc1 != DmtxUndefined) { - PushOutputC40TextWord(msg, &state, msg->fnc1); - } - } - else if(c40Values[i] == 30) { - state.upperShift = DmtxTrue; - state.shift = DmtxC40TextBasicSet; - } - } - else if(state.shift == DmtxC40TextShift3) { /* Shift 3 set */ - if(encScheme == DmtxSchemeC40) { - PushOutputC40TextWord(msg, &state, c40Values[i] + 96); - } - else if(encScheme == DmtxSchemeText) { - if(c40Values[i] == 0) - PushOutputC40TextWord(msg, &state, c40Values[i] + 96); - else if(c40Values[i] <= 26) - PushOutputC40TextWord(msg, &state, c40Values[i] - 26 + 'Z'); /* A-Z */ - else - PushOutputC40TextWord(msg, &state, c40Values[i] - 31 + 127); /* { | } ~ DEL */ - } - } - } + } - /* Unlatch if codeword 254 follows 2 codewords in C40/Text encodation */ - if(*ptr == DmtxValueCTXUnlatch) - return ptr + 1; + /* Unlatch if codeword 254 follows 2 codewords in C40/Text encodation */ + if (*ptr == DmtxValueCTXUnlatch) + return ptr + 1; - /* Unlatch is implied if only one codeword remains */ - if(dataEnd - ptr < 2) - return ptr; - } + /* Unlatch is implied if only one codeword remains */ + if (dataEnd - ptr < 2) + return ptr; + } - return ptr; + return ptr; } /** @@ -375,48 +409,50 @@ DecodeSchemeC40Text(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd static unsigned char * DecodeSchemeX12(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd) { - int i; - int packed; - int x12Values[3]; - - /* Unlatch is implied if only one codeword remains */ - if(dataEnd - ptr < 2) - return ptr; - - while(ptr < dataEnd) { - - /* FIXME Also check that ptr+1 is safe to access */ - packed = (*ptr << 8) | *(ptr+1); - x12Values[0] = ((packed - 1)/1600); - x12Values[1] = ((packed - 1)/40) % 40; - x12Values[2] = (packed - 1) % 40; - ptr += 2; - - for(i = 0; i < 3; i++) { - if(x12Values[i] == 0) - PushOutputWord(msg, 13); - else if(x12Values[i] == 1) - PushOutputWord(msg, 42); - else if(x12Values[i] == 2) - PushOutputWord(msg, 62); - else if(x12Values[i] == 3) - PushOutputWord(msg, 32); - else if(x12Values[i] <= 13) - PushOutputWord(msg, x12Values[i] + 44); - else if(x12Values[i] <= 90) - PushOutputWord(msg, x12Values[i] + 51); - } - - /* Unlatch if codeword 254 follows 2 codewords in C40/Text encodation */ - if(*ptr == DmtxValueCTXUnlatch) - return ptr + 1; - - /* Unlatch is implied if only one codeword remains */ - if(dataEnd - ptr < 2) - return ptr; - } - - return ptr; + int i; + int packed; + int x12Values[3]; + + /* Unlatch is implied if only one codeword remains */ + if (dataEnd - ptr < 2) + return ptr; + + while (ptr < dataEnd) + { + + /* FIXME Also check that ptr+1 is safe to access */ + packed = (*ptr << 8) | *(ptr + 1); + x12Values[0] = ((packed - 1) / 1600); + x12Values[1] = ((packed - 1) / 40) % 40; + x12Values[2] = (packed - 1) % 40; + ptr += 2; + + for (i = 0; i < 3; i++) + { + if (x12Values[i] == 0) + PushOutputWord(msg, 13); + else if (x12Values[i] == 1) + PushOutputWord(msg, 42); + else if (x12Values[i] == 2) + PushOutputWord(msg, 62); + else if (x12Values[i] == 3) + PushOutputWord(msg, 32); + else if (x12Values[i] <= 13) + PushOutputWord(msg, x12Values[i] + 44); + else if (x12Values[i] <= 90) + PushOutputWord(msg, x12Values[i] + 51); + } + + /* Unlatch if codeword 254 follows 2 codewords in C40/Text encodation */ + if (*ptr == DmtxValueCTXUnlatch) + return ptr + 1; + + /* Unlatch is implied if only one codeword remains */ + if (dataEnd - ptr < 2) + return ptr; + } + + return ptr; } /** @@ -429,76 +465,79 @@ DecodeSchemeX12(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd) static unsigned char * DecodeSchemeEdifact(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd) { - int i; - unsigned char unpacked[4]; - - /* Unlatch is implied if fewer than 3 codewords remain */ - if(dataEnd - ptr < 3) - return ptr; + int i; + unsigned char unpacked[4]; - while(ptr < dataEnd) { - - /* FIXME Also check that ptr+2 is safe to access -- shouldn't be a - problem because I'm guessing you can guarantee there will always - be at least 3 error codewords */ - unpacked[0] = (*ptr & 0xfc) >> 2; - unpacked[1] = (*ptr & 0x03) << 4 | (*(ptr+1) & 0xf0) >> 4; - unpacked[2] = (*(ptr+1) & 0x0f) << 2 | (*(ptr+2) & 0xc0) >> 6; - unpacked[3] = *(ptr+2) & 0x3f; + /* Unlatch is implied if fewer than 3 codewords remain */ + if (dataEnd - ptr < 3) + return ptr; - for(i = 0; i < 4; i++) { + while (ptr < dataEnd) + { + + /* FIXME Also check that ptr+2 is safe to access -- shouldn't be a + problem because I'm guessing you can guarantee there will always + be at least 3 error codewords */ + unpacked[0] = (*ptr & 0xfc) >> 2; + unpacked[1] = (*ptr & 0x03) << 4 | (*(ptr + 1) & 0xf0) >> 4; + unpacked[2] = (*(ptr + 1) & 0x0f) << 2 | (*(ptr + 2) & 0xc0) >> 6; + unpacked[3] = *(ptr + 2) & 0x3f; + + for (i = 0; i < 4; i++) + { + + /* Advance input ptr (4th value comes from already-read 3rd byte) */ + if (i < 3) + ptr++; + + /* Test for unlatch condition */ + if (unpacked[i] == DmtxValueEdifactUnlatch) + { + assert(msg->output[msg->outputIdx] == 0); /* XXX dirty why? */ + return ptr; + } - /* Advance input ptr (4th value comes from already-read 3rd byte) */ - if(i < 3) - ptr++; + PushOutputWord(msg, unpacked[i] ^ (((unpacked[i] & 0x20) ^ 0x20) << 1)); + } - /* Test for unlatch condition */ - if(unpacked[i] == DmtxValueEdifactUnlatch) { - assert(msg->output[msg->outputIdx] == 0); /* XXX dirty why? */ + /* Unlatch is implied if fewer than 3 codewords remain */ + if (dataEnd - ptr < 3) return ptr; - } - - PushOutputWord(msg, unpacked[i] ^ (((unpacked[i] & 0x20) ^ 0x20) << 1)); - } - - /* Unlatch is implied if fewer than 3 codewords remain */ - if(dataEnd - ptr < 3) - return ptr; - } + } - return ptr; + return ptr; -/* XXX the following version should be safer, but requires testing before replacing the old version - int bits = 0; - int bitCount = 0; - int value; + /* XXX the following version should be safer, but requires testing before replacing the old version + int bits = 0; + int bitCount = 0; + int value; - while(ptr < dataEnd) { + while(ptr < dataEnd) { - if(bitCount < 6) { - bits = (bits << 8) | *(ptr++); - bitCount += 8; - } + if(bitCount < 6) { + bits = (bits << 8) | *(ptr++); + bitCount += 8; + } - value = bits >> (bitCount - 6); - bits -= (value << (bitCount - 6)); - bitCount -= 6; + value = bits >> (bitCount - 6); + bits -= (value << (bitCount - 6)); + bitCount -= 6; - if(value == 0x1f) { - assert(bits == 0); // should be padded with zero-value bits - return ptr; - } - PushOutputWord(msg, value ^ (((value & 0x20) ^ 0x20) << 1)); + if(value == 0x1f) { + assert(bits == 0); // should be padded with zero-value bits + return ptr; + } + PushOutputWord(msg, value ^ (((value & 0x20) ^ 0x20) << 1)); - // Unlatch implied if just completed triplet and 1 or 2 words are left - if(bitCount == 0 && dataEnd - ptr - 1 > 0 && dataEnd - ptr - 1 < 3) - return ptr; - } + // Unlatch implied if just completed triplet and 1 or 2 words are left + if(bitCount == 0 && dataEnd - ptr - 1 > 0 && dataEnd - ptr - 1 < 3) + return ptr; + } - assert(bits == 0); // should be padded with zero-value bits - assert(bitCount == 0); // should be padded with zero-value bits - return ptr; -*/ + assert(bits == 0); // should be padded with zero-value bits + assert(bitCount == 0); // should be padded with zero-value bits + return ptr; + */ } /** @@ -512,32 +551,35 @@ DecodeSchemeEdifact(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd static unsigned char * DecodeSchemeBase256(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd) { - int d0, d1; - int idx; - unsigned char *ptrEnd; - - /* Find positional index used for unrandomizing */ - assert(ptr + 1 >= msg->code); - assert(ptr + 1 - msg->code <= INT_MAX); - idx = (int)(ptr + 1 - msg->code); - - d0 = UnRandomize255State(*(ptr++), idx++); - if(d0 == 0) { - ptrEnd = dataEnd; - } - else if(d0 <= 249) { - ptrEnd = ptr + d0; - } - else { - d1 = UnRandomize255State(*(ptr++), idx++); - ptrEnd = ptr + (d0 - 249) * 250 + d1; - } - - if(ptrEnd > dataEnd) - return NULL; - - while(ptr < ptrEnd) - PushOutputWord(msg, UnRandomize255State(*(ptr++), idx++)); - - return ptr; + int d0, d1; + int idx; + unsigned char *ptrEnd; + + /* Find positional index used for unrandomizing */ + assert(ptr + 1 >= msg->code); + assert(ptr + 1 - msg->code <= INT_MAX); + idx = (int)(ptr + 1 - msg->code); + + d0 = UnRandomize255State(*(ptr++), idx++); + if (d0 == 0) + { + ptrEnd = dataEnd; + } + else if (d0 <= 249) + { + ptrEnd = ptr + d0; + } + else + { + d1 = UnRandomize255State(*(ptr++), idx++); + ptrEnd = ptr + (d0 - 249) * 250 + d1; + } + + if (ptrEnd > dataEnd) + return NULL; + + while (ptr < ptrEnd) + PushOutputWord(msg, UnRandomize255State(*(ptr++), idx++)); + + return ptr; } diff --git a/dmtxencode.c b/dmtxencode.c index c7f17948..f1eaa493 100644 --- a/dmtxencode.c +++ b/dmtxencode.c @@ -28,34 +28,34 @@ extern DmtxEncode * dmtxEncodeCreate(void) { - DmtxEncode *enc; + DmtxEncode *enc; - enc = (DmtxEncode *)calloc(1, sizeof(DmtxEncode)); - if(enc == NULL) - return NULL; + enc = (DmtxEncode *)calloc(1, sizeof(DmtxEncode)); + if (enc == NULL) + return NULL; - enc->scheme = DmtxSchemeAscii; - enc->sizeIdxRequest = DmtxSymbolSquareAuto; - enc->marginSize = 10; - enc->moduleSize = 5; - enc->pixelPacking = DmtxPack24bppRGB; - enc->imageFlip = DmtxFlipNone; - enc->rowPadBytes = 0; + enc->scheme = DmtxSchemeAscii; + enc->sizeIdxRequest = DmtxSymbolSquareAuto; + enc->marginSize = 10; + enc->moduleSize = 5; + enc->pixelPacking = DmtxPack24bppRGB; + enc->imageFlip = DmtxFlipNone; + enc->rowPadBytes = 0; - enc->fnc1 = DmtxUndefined; + enc->fnc1 = DmtxUndefined; - /* Initialize background color to white */ -/* enc.region.gradient.ray.p.R = 255.0; - enc.region.gradient.ray.p.G = 255.0; - enc.region.gradient.ray.p.B = 255.0; */ + /* Initialize background color to white */ + /* enc.region.gradient.ray.p.R = 255.0; + enc.region.gradient.ray.p.G = 255.0; + enc.region.gradient.ray.p.B = 255.0; */ - /* Initialize foreground color to black */ -/* enc.region.gradient.tMin = 0.0; - enc.region.gradient.tMax = xyz; */ + /* Initialize foreground color to black */ + /* enc.region.gradient.tMin = 0.0; + enc.region.gradient.tMax = xyz; */ - dmtxMatrix3Identity(enc->xfrm); + dmtxMatrix3Identity(enc->xfrm); - return enc; + return enc; } /** @@ -66,23 +66,24 @@ dmtxEncodeCreate(void) extern DmtxPassFail dmtxEncodeDestroy(DmtxEncode **enc) { - if(enc == NULL || *enc == NULL) - return DmtxFail; + if (enc == NULL || *enc == NULL) + return DmtxFail; - /* Free pixel array allocated in dmtxEncodeDataMatrix() */ - if((*enc)->image != NULL && (*enc)->image->pxl != NULL) { - free((*enc)->image->pxl); - (*enc)->image->pxl = NULL; - } + /* Free pixel array allocated in dmtxEncodeDataMatrix() */ + if ((*enc)->image != NULL && (*enc)->image->pxl != NULL) + { + free((*enc)->image->pxl); + (*enc)->image->pxl = NULL; + } - dmtxImageDestroy(&((*enc)->image)); - dmtxMessageDestroy(&((*enc)->message)); + dmtxImageDestroy(&((*enc)->image)); + dmtxMessageDestroy(&((*enc)->message)); - free(*enc); + free(*enc); - *enc = NULL; + *enc = NULL; - return DmtxPass; + return DmtxPass; } /** @@ -95,43 +96,44 @@ dmtxEncodeDestroy(DmtxEncode **enc) extern DmtxPassFail dmtxEncodeSetProp(DmtxEncode *enc, int prop, int value) { - switch(prop) { - - /* Encoding details */ - case DmtxPropScheme: - enc->scheme = value; - break; - case DmtxPropSizeRequest: - if(value == DmtxSymbolShapeAuto) + switch (prop) + { + + /* Encoding details */ + case DmtxPropScheme: + enc->scheme = value; + break; + case DmtxPropSizeRequest: + if (value == DmtxSymbolShapeAuto) return DmtxFail; - enc->sizeIdxRequest = value; - break; - case DmtxPropFnc1: - enc->fnc1 = value; - break; - - /* Presentation details */ - case DmtxPropMarginSize: - enc->marginSize = value; - break; - case DmtxPropModuleSize: - enc->moduleSize = value; - break; - - /* Image properties */ - case DmtxPropPixelPacking: - enc->pixelPacking = value; - break; - case DmtxPropImageFlip: - enc->imageFlip = value; - break; - case DmtxPropRowPadBytes: - enc->rowPadBytes = value; - default: - break; - } - - return DmtxPass; + enc->sizeIdxRequest = value; + break; + case DmtxPropFnc1: + enc->fnc1 = value; + break; + + /* Presentation details */ + case DmtxPropMarginSize: + enc->marginSize = value; + break; + case DmtxPropModuleSize: + enc->moduleSize = value; + break; + + /* Image properties */ + case DmtxPropPixelPacking: + enc->pixelPacking = value; + break; + case DmtxPropImageFlip: + enc->imageFlip = value; + break; + case DmtxPropRowPadBytes: + enc->rowPadBytes = value; + default: + break; + } + + return DmtxPass; } /** @@ -143,20 +145,21 @@ dmtxEncodeSetProp(DmtxEncode *enc, int prop, int value) extern int dmtxEncodeGetProp(DmtxEncode *enc, int prop) { - switch(prop) { - case DmtxPropMarginSize: - return enc->marginSize; - case DmtxPropModuleSize: - return enc->moduleSize; - case DmtxPropScheme: - return enc->scheme; - case DmtxPropFnc1: - return enc->fnc1; - default: - break; - } - - return DmtxUndefined; + switch (prop) + { + case DmtxPropMarginSize: + return enc->marginSize; + case DmtxPropModuleSize: + return enc->moduleSize; + case DmtxPropScheme: + return enc->scheme; + case DmtxPropFnc1: + return enc->fnc1; + default: + break; + } + + return DmtxUndefined; } /** @@ -169,83 +172,85 @@ dmtxEncodeGetProp(DmtxEncode *enc, int prop) * \return DmtxPass | DmtxFail */ #ifdef HAVE_READER_PROGRAMMING - extern DmtxPassFail - dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString, DmtxBoolean bReaderProgramming) +extern DmtxPassFail +dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString, DmtxBoolean bReaderProgramming) #else - extern DmtxPassFail - dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString) +extern DmtxPassFail +dmtxEncodeDataMatrix(DmtxEncode *enc, int inputSize, unsigned char *inputString) #endif { - 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 */ - #ifdef HAVE_READER_PROGRAMMING - sizeIdx = EncodeDataCodewords(&input, &output, enc->sizeIdxRequest, enc->scheme, enc->fnc1, bReaderProgramming); - #else - sizeIdx = EncodeDataCodewords(&input, &output, enc->sizeIdxRequest, enc->scheme, enc->fnc1); - #endif - 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; + 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 */ +#ifdef HAVE_READER_PROGRAMMING + sizeIdx = EncodeDataCodewords(&input, &output, enc->sizeIdxRequest, enc->scheme, enc->fnc1, bReaderProgramming); +#else + sizeIdx = EncodeDataCodewords(&input, &output, enc->sizeIdxRequest, enc->scheme, enc->fnc1); +#endif + 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; } /** @@ -269,140 +274,143 @@ dmtxEncodeGetProp(DmtxEncode *enc, int prop) 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 */ - #ifdef HAVE_READER_PROGRAMMING + 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 */ +#ifdef HAVE_READER_PROGRAMMING dmtxEncodeDataMatrix(encR, inputSizeR, inputStringR, DmtxFalse); - #else +#else dmtxEncodeDataMatrix(encR, inputSizeR, inputStringR); - #endif - if(encR->region.sizeIdx != sizeIdxAttempt) - continue; +#endif + if (encR->region.sizeIdx != sizeIdxAttempt) + continue; - /* GREEN LAYER - Holds temporary copy */ - #ifdef HAVE_READER_PROGRAMMING +/* GREEN LAYER - Holds temporary copy */ +#ifdef HAVE_READER_PROGRAMMING dmtxEncodeDataMatrix(encG, inputSizeG, inputStringG, DmtxFalse); - #else +#else dmtxEncodeDataMatrix(encG, inputSizeG, inputStringG); - #endif - if(encG->region.sizeIdx != sizeIdxAttempt) - continue; +#endif + if (encG->region.sizeIdx != sizeIdxAttempt) + continue; - /* BLUE LAYER - Holds temporary copy */ - #ifdef HAVE_READER_PROGRAMMING +/* BLUE LAYER - Holds temporary copy */ +#ifdef HAVE_READER_PROGRAMMING dmtxEncodeDataMatrix(encB, inputSizeB, inputStringB, DmtxFalse); - #else +#else dmtxEncodeDataMatrix(encB, inputSizeB, inputStringB); - #endif - 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); - #ifdef HAVE_READER_PROGRAMMING - dmtxEncodeDataMatrix(enc, inputSizeR, inputStringR, DmtxFalse); - #else - dmtxEncodeDataMatrix(enc, inputSizeR, inputStringR); - #endif - - /* 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; +#endif + 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); +#ifdef HAVE_READER_PROGRAMMING + dmtxEncodeDataMatrix(enc, inputSizeR, inputStringR, DmtxFalse); +#else + dmtxEncodeDataMatrix(enc, inputSizeR, inputStringR); +#endif + + /* 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; } /** @@ -419,34 +427,34 @@ dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString) * goes to EncodeSingle... too */ #ifdef HAVE_READER_PROGRAMMING - static int - EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming) +static int +EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming) #else - static int - EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1) +static int +EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1) #endif { - int sizeIdx; - - /* Encode input string into data codewords */ - switch(scheme) - { - case DmtxSchemeAutoBest: - sizeIdx = EncodeOptimizeBest(input, output, sizeIdxRequest, fnc1); - break; - case DmtxSchemeAutoFast: - sizeIdx = DmtxUndefined; /* EncodeAutoFast(input, output, sizeIdxRequest, passFail); */ - break; - default: - #ifdef HAVE_READER_PROGRAMMING - sizeIdx = EncodeSingleScheme(input, output, sizeIdxRequest, scheme, fnc1, bReaderProgramming); - #else - sizeIdx = EncodeSingleScheme(input, output, sizeIdxRequest, scheme, fnc1); - #endif - break; - } - - return sizeIdx; + int sizeIdx; + + /* Encode input string into data codewords */ + switch (scheme) + { + case DmtxSchemeAutoBest: + sizeIdx = EncodeOptimizeBest(input, output, sizeIdxRequest, fnc1); + break; + case DmtxSchemeAutoFast: + sizeIdx = DmtxUndefined; /* EncodeAutoFast(input, output, sizeIdxRequest, passFail); */ + break; + default: +#ifdef HAVE_READER_PROGRAMMING + sizeIdx = EncodeSingleScheme(input, output, sizeIdxRequest, scheme, fnc1, bReaderProgramming); +#else + sizeIdx = EncodeSingleScheme(input, output, sizeIdxRequest, scheme, fnc1); +#endif + break; + } + + return sizeIdx; } /** @@ -457,69 +465,75 @@ dmtxEncodeDataMosaic(DmtxEncode *enc, int inputSize, unsigned char *inputString) static void PrintPattern(DmtxEncode *enc) { - int i, j; - int symbolRow, symbolCol; - int pixelRow, pixelCol; - int moduleStatus; - size_t rowSize, height; - int rgb[3]; - double sxy, txy; - DmtxMatrix3 m1, m2; - DmtxVector2 vIn, vOut; - - txy = enc->marginSize; - sxy = 1.0/enc->moduleSize; - - dmtxMatrix3Translate(m1, -txy, -txy); - dmtxMatrix3Scale(m2, sxy, -sxy); - dmtxMatrix3Multiply(enc->xfrm, m1, m2); - - dmtxMatrix3Translate(m1, txy, txy); - dmtxMatrix3Scale(m2, enc->moduleSize, enc->moduleSize); - dmtxMatrix3Multiply(enc->rxfrm, m2, m1); - - rowSize = dmtxImageGetProp(enc->image, DmtxPropRowSizeBytes); - height = dmtxImageGetProp(enc->image, DmtxPropHeight); - - memset(enc->image->pxl, 0xff, rowSize * height); - - for(symbolRow = 0; symbolRow < enc->region.symbolRows; symbolRow++) { - for(symbolCol = 0; symbolCol < enc->region.symbolCols; symbolCol++) { - - vIn.X = symbolCol; - vIn.Y = symbolRow; - - dmtxMatrix3VMultiply(&vOut, &vIn, enc->rxfrm); - - pixelCol = (int)(vOut.X); - pixelRow = (int)(vOut.Y); - - moduleStatus = dmtxSymbolModuleStatus(enc->message, - enc->region.sizeIdx, symbolRow, symbolCol); - - if (enc->image->bytesPerPixel == 1) - { - for(i = pixelRow; i < pixelRow + enc->moduleSize; i++) { - for(j = pixelCol; j < pixelCol + enc->moduleSize; j++) { - rgb[0] = ((moduleStatus & DmtxModuleOnRed) != 0x00) ? 0 : 255; - dmtxImageSetPixelValue(enc->image, j, i, 0, rgb[0]); - } - } - } - else - { - for(i = pixelRow; i < pixelRow + enc->moduleSize; i++) { - for(j = pixelCol; j < pixelCol + enc->moduleSize; j++) { - rgb[0] = ((moduleStatus & DmtxModuleOnRed) != 0x00) ? 0 : 255; - rgb[1] = ((moduleStatus & DmtxModuleOnGreen) != 0x00) ? 0 : 255; - rgb[2] = ((moduleStatus & DmtxModuleOnBlue) != 0x00) ? 0 : 255; - /* dmtxImageSetRgb(enc->image, j, i, rgb); */ - dmtxImageSetPixelValue(enc->image, j, i, 0, rgb[0]); - dmtxImageSetPixelValue(enc->image, j, i, 1, rgb[1]); - dmtxImageSetPixelValue(enc->image, j, i, 2, rgb[2]); - } - } - } - } - } + int i, j; + int symbolRow, symbolCol; + int pixelRow, pixelCol; + int moduleStatus; + size_t rowSize, height; + int rgb[3]; + double sxy, txy; + DmtxMatrix3 m1, m2; + DmtxVector2 vIn, vOut; + + txy = enc->marginSize; + sxy = 1.0 / enc->moduleSize; + + dmtxMatrix3Translate(m1, -txy, -txy); + dmtxMatrix3Scale(m2, sxy, -sxy); + dmtxMatrix3Multiply(enc->xfrm, m1, m2); + + dmtxMatrix3Translate(m1, txy, txy); + dmtxMatrix3Scale(m2, enc->moduleSize, enc->moduleSize); + dmtxMatrix3Multiply(enc->rxfrm, m2, m1); + + rowSize = dmtxImageGetProp(enc->image, DmtxPropRowSizeBytes); + height = dmtxImageGetProp(enc->image, DmtxPropHeight); + + memset(enc->image->pxl, 0xff, rowSize * height); + + for (symbolRow = 0; symbolRow < enc->region.symbolRows; symbolRow++) + { + for (symbolCol = 0; symbolCol < enc->region.symbolCols; symbolCol++) + { + + vIn.X = symbolCol; + vIn.Y = symbolRow; + + dmtxMatrix3VMultiply(&vOut, &vIn, enc->rxfrm); + + pixelCol = (int)(vOut.X); + pixelRow = (int)(vOut.Y); + + moduleStatus = dmtxSymbolModuleStatus(enc->message, + enc->region.sizeIdx, symbolRow, symbolCol); + + if (enc->image->bytesPerPixel == 1) + { + for (i = pixelRow; i < pixelRow + enc->moduleSize; i++) + { + for (j = pixelCol; j < pixelCol + enc->moduleSize; j++) + { + rgb[0] = ((moduleStatus & DmtxModuleOnRed) != 0x00) ? 0 : 255; + dmtxImageSetPixelValue(enc->image, j, i, 0, rgb[0]); + } + } + } + else + { + for (i = pixelRow; i < pixelRow + enc->moduleSize; i++) + { + for (j = pixelCol; j < pixelCol + enc->moduleSize; j++) + { + rgb[0] = ((moduleStatus & DmtxModuleOnRed) != 0x00) ? 0 : 255; + rgb[1] = ((moduleStatus & DmtxModuleOnGreen) != 0x00) ? 0 : 255; + rgb[2] = ((moduleStatus & DmtxModuleOnBlue) != 0x00) ? 0 : 255; + /* dmtxImageSetRgb(enc->image, j, i, rgb); */ + dmtxImageSetPixelValue(enc->image, j, i, 0, rgb[0]); + dmtxImageSetPixelValue(enc->image, j, i, 1, rgb[1]); + dmtxImageSetPixelValue(enc->image, j, i, 2, rgb[2]); + } + } + } + } + } } diff --git a/dmtxencodeascii.c b/dmtxencodeascii.c index c4d4a6ec..695bd087 100644 --- a/dmtxencodeascii.c +++ b/dmtxencodeascii.c @@ -30,65 +30,73 @@ static void EncodeNextChunkAscii(DmtxEncodeStream *stream, int option) { - DmtxByte v0, v1; - DmtxBoolean compactDigits; + DmtxByte v0, v1; + DmtxBoolean compactDigits; - if(StreamInputHasNext(stream)) - { - v0 = StreamInputAdvanceNext(stream); CHKERR; + if (StreamInputHasNext(stream)) + { + v0 = StreamInputAdvanceNext(stream); + CHKERR; - if((option == DmtxEncodeCompact || option == DmtxEncodeNormal) && + if ((option == DmtxEncodeCompact || option == DmtxEncodeNormal) && StreamInputHasNext(stream)) - { - v1 = StreamInputPeekNext(stream); CHKERR; - - /* Check for FNC1 character */ - if(stream->fnc1 != DmtxUndefined && (int)v1 == stream->fnc1) - { + { + v1 = StreamInputPeekNext(stream); + CHKERR; + + /* Check for FNC1 character */ + if (stream->fnc1 != DmtxUndefined && (int)v1 == stream->fnc1) + { + v1 = 0; + compactDigits = DmtxFalse; + } + else + compactDigits = (ISDIGIT(v0) && ISDIGIT(v1)) ? DmtxTrue : DmtxFalse; + } + else /* option == DmtxEncodeFull */ + { v1 = 0; compactDigits = DmtxFalse; - } - else - compactDigits = (ISDIGIT(v0) && ISDIGIT(v1)) ? DmtxTrue : DmtxFalse; - } - else /* option == DmtxEncodeFull */ - { - v1 = 0; - compactDigits = DmtxFalse; - } - - if(compactDigits == DmtxTrue) - { - /* Two adjacent digit chars: Make peek progress official and encode */ - StreamInputAdvanceNext(stream); CHKERR; - AppendValueAscii(stream, 10 * (v0-'0') + (v1-'0') + 130); CHKERR; - } - else if(option == DmtxEncodeCompact) - { - /* Can't compact non-digits */ - StreamMarkInvalid(stream, DmtxErrorCantCompactNonDigits); - } - else - { - /* Encode single ASCII value */ - if(stream->fnc1 != DmtxUndefined && (int)v0 == stream->fnc1) - { - /* FNC1 */ - AppendValueAscii(stream, DmtxValueFNC1); CHKERR; - } - else if(v0 < 128) - { - /* Regular ASCII */ - AppendValueAscii(stream, v0 + 1); CHKERR; - } - else - { - /* Extended ASCII */ - AppendValueAscii(stream, DmtxValueAsciiUpperShift); CHKERR; - AppendValueAscii(stream, v0 - 127); CHKERR; - } - } - } + } + + if (compactDigits == DmtxTrue) + { + /* Two adjacent digit chars: Make peek progress official and encode */ + StreamInputAdvanceNext(stream); + CHKERR; + AppendValueAscii(stream, 10 * (v0 - '0') + (v1 - '0') + 130); + CHKERR; + } + else if (option == DmtxEncodeCompact) + { + /* Can't compact non-digits */ + StreamMarkInvalid(stream, DmtxErrorCantCompactNonDigits); + } + else + { + /* Encode single ASCII value */ + if (stream->fnc1 != DmtxUndefined && (int)v0 == stream->fnc1) + { + /* FNC1 */ + AppendValueAscii(stream, DmtxValueFNC1); + CHKERR; + } + else if (v0 < 128) + { + /* Regular ASCII */ + AppendValueAscii(stream, v0 + 1); + CHKERR; + } + else + { + /* Extended ASCII */ + AppendValueAscii(stream, DmtxValueAsciiUpperShift); + CHKERR; + AppendValueAscii(stream, v0 - 127); + CHKERR; + } + } + } } /** @@ -98,10 +106,11 @@ EncodeNextChunkAscii(DmtxEncodeStream *stream, int option) static void AppendValueAscii(DmtxEncodeStream *stream, DmtxByte value) { - CHKSCHEME(DmtxSchemeAscii); + CHKSCHEME(DmtxSchemeAscii); - StreamOutputChainAppend(stream, value); CHKERR; - stream->outputChainValueCount++; + StreamOutputChainAppend(stream, value); + CHKERR; + stream->outputChainValueCount++; } /** @@ -111,17 +120,19 @@ AppendValueAscii(DmtxEncodeStream *stream, DmtxByte value) static void CompleteIfDoneAscii(DmtxEncodeStream *stream, int sizeIdxRequest) { - int sizeIdx; - - if(stream->status == DmtxStatusComplete) - return; - - if(!StreamInputHasNext(stream)) - { - sizeIdx = FindSymbolSize(stream->output->length, sizeIdxRequest); CHKSIZE; - PadRemainingInAscii(stream, sizeIdx); CHKERR; - StreamMarkComplete(stream, sizeIdx); - } + int sizeIdx; + + if (stream->status == DmtxStatusComplete) + return; + + if (!StreamInputHasNext(stream)) + { + sizeIdx = FindSymbolSize(stream->output->length, sizeIdxRequest); + CHKSIZE; + PadRemainingInAscii(stream, sizeIdx); + CHKERR; + StreamMarkComplete(stream, sizeIdx); + } } /** @@ -131,29 +142,31 @@ CompleteIfDoneAscii(DmtxEncodeStream *stream, int sizeIdxRequest) static void PadRemainingInAscii(DmtxEncodeStream *stream, int sizeIdx) { - int symbolRemaining; - DmtxByte padValue; - - CHKSCHEME(DmtxSchemeAscii); - CHKSIZE; - - symbolRemaining = GetRemainingSymbolCapacity(stream->output->length, sizeIdx); - - /* First pad character is not randomized */ - if(symbolRemaining > 0) - { - padValue = DmtxValueAsciiPad; - StreamOutputChainAppend(stream, padValue); CHKERR; - symbolRemaining--; - } - - /* All remaining pad characters are randomized based on character position */ - while(symbolRemaining > 0) - { - padValue = Randomize253State(DmtxValueAsciiPad, stream->output->length + 1); - StreamOutputChainAppend(stream, padValue); CHKERR; - symbolRemaining--; - } + int symbolRemaining; + DmtxByte padValue; + + CHKSCHEME(DmtxSchemeAscii); + CHKSIZE; + + symbolRemaining = GetRemainingSymbolCapacity(stream->output->length, sizeIdx); + + /* First pad character is not randomized */ + if (symbolRemaining > 0) + { + padValue = DmtxValueAsciiPad; + StreamOutputChainAppend(stream, padValue); + CHKERR; + symbolRemaining--; + } + + /* All remaining pad characters are randomized based on character position */ + while (symbolRemaining > 0) + { + padValue = Randomize253State(DmtxValueAsciiPad, stream->output->length + 1); + StreamOutputChainAppend(stream, padValue); + CHKERR; + symbolRemaining--; + } } /** @@ -161,41 +174,41 @@ PadRemainingInAscii(DmtxEncodeStream *stream, int sizeIdx) */ static DmtxByteList EncodeTmpRemainingInAscii(DmtxEncodeStream *stream, DmtxByte *storage, - int capacity, DmtxPassFail *passFail) + int capacity, DmtxPassFail *passFail) { - DmtxEncodeStream streamAscii; - DmtxByteList output = dmtxByteListBuild(storage, capacity); - - /* Create temporary copy of stream that writes to storage */ - streamAscii = *stream; - streamAscii.currentScheme = DmtxSchemeAscii; - streamAscii.outputChainValueCount = 0; - streamAscii.outputChainWordCount = 0; - streamAscii.reason = NULL; - streamAscii.sizeIdx = DmtxUndefined; - streamAscii.status = DmtxStatusEncoding; - streamAscii.output = &output; - - while(dmtxByteListHasCapacity(streamAscii.output)) - { - if(StreamInputHasNext(&streamAscii)) - EncodeNextChunkAscii(&streamAscii, DmtxEncodeNormal); /* No CHKERR */ - else - break; - } - - /* - * We stopped encoding before attempting to write beyond output boundary so - * any stream errors are truly unexpected. The passFail status indicates - * whether output.length can be trusted by the calling function. - */ - - if(streamAscii.status == DmtxStatusInvalid || streamAscii.status == DmtxStatusFatal) - *passFail = DmtxFail; - else - *passFail = DmtxPass; - - return output; + DmtxEncodeStream streamAscii; + DmtxByteList output = dmtxByteListBuild(storage, capacity); + + /* Create temporary copy of stream that writes to storage */ + streamAscii = *stream; + streamAscii.currentScheme = DmtxSchemeAscii; + streamAscii.outputChainValueCount = 0; + streamAscii.outputChainWordCount = 0; + streamAscii.reason = NULL; + streamAscii.sizeIdx = DmtxUndefined; + streamAscii.status = DmtxStatusEncoding; + streamAscii.output = &output; + + while (dmtxByteListHasCapacity(streamAscii.output)) + { + if (StreamInputHasNext(&streamAscii)) + EncodeNextChunkAscii(&streamAscii, DmtxEncodeNormal); /* No CHKERR */ + else + break; + } + + /* + * We stopped encoding before attempting to write beyond output boundary so + * any stream errors are truly unexpected. The passFail status indicates + * whether output.length can be trusted by the calling function. + */ + + if (streamAscii.status == DmtxStatusInvalid || streamAscii.status == DmtxStatusFatal) + *passFail = DmtxFail; + else + *passFail = DmtxPass; + + return output; } /** @@ -207,14 +220,14 @@ EncodeTmpRemainingInAscii(DmtxEncodeStream *stream, DmtxByte *storage, static DmtxByte Randomize253State(DmtxByte cwValue, int cwPosition) { - int pseudoRandom, tmp; + int pseudoRandom, tmp; - pseudoRandom = ((149 * cwPosition) % 253) + 1; - tmp = cwValue + pseudoRandom; - if(tmp > 254) - tmp -= 254; + pseudoRandom = ((149 * cwPosition) % 253) + 1; + tmp = cwValue + pseudoRandom; + if (tmp > 254) + tmp -= 254; - assert(tmp >= 0 && tmp < 256); + assert(tmp >= 0 && tmp < 256); - return (DmtxByte)tmp; + return (DmtxByte)tmp; } diff --git a/dmtxencodebase256.c b/dmtxencodebase256.c index eff60e0a..f070be59 100644 --- a/dmtxencodebase256.c +++ b/dmtxencodebase256.c @@ -21,23 +21,29 @@ static void EncodeNextChunkBase256(DmtxEncodeStream *stream) { - DmtxByte value; - - if(StreamInputHasNext(stream)) - { - /* Check for FNC1 character, which needs to be sent in ASCII */ - value = StreamInputPeekNext(stream); CHKERR; - if(stream->fnc1 != DmtxUndefined && (int)value == stream->fnc1) { - EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchExplicit); - - StreamInputAdvanceNext(stream); CHKERR; - AppendValueAscii(stream, DmtxValueFNC1); CHKERR; - return; - } - - value = StreamInputAdvanceNext(stream); CHKERR; - AppendValueBase256(stream, value); CHKERR; - } + DmtxByte value; + + if (StreamInputHasNext(stream)) + { + /* Check for FNC1 character, which needs to be sent in ASCII */ + value = StreamInputPeekNext(stream); + CHKERR; + if (stream->fnc1 != DmtxUndefined && (int)value == stream->fnc1) + { + EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchExplicit); + + StreamInputAdvanceNext(stream); + CHKERR; + AppendValueAscii(stream, DmtxValueFNC1); + CHKERR; + return; + } + + value = StreamInputAdvanceNext(stream); + CHKERR; + AppendValueBase256(stream, value); + CHKERR; + } } /** @@ -47,12 +53,14 @@ EncodeNextChunkBase256(DmtxEncodeStream *stream) static void AppendValueBase256(DmtxEncodeStream *stream, DmtxByte value) { - CHKSCHEME(DmtxSchemeBase256); + CHKSCHEME(DmtxSchemeBase256); - StreamOutputChainAppend(stream, Randomize255State(value, stream->output->length + 1)); CHKERR; - stream->outputChainValueCount++; + StreamOutputChainAppend(stream, Randomize255State(value, stream->output->length + 1)); + CHKERR; + stream->outputChainValueCount++; - UpdateBase256ChainHeader(stream, DmtxUndefined); CHKERR; + UpdateBase256ChainHeader(stream, DmtxUndefined); + CHKERR; } /** @@ -64,43 +72,45 @@ AppendValueBase256(DmtxEncodeStream *stream, DmtxByte value) static void CompleteIfDoneBase256(DmtxEncodeStream *stream, int sizeIdxRequest) { - int sizeIdx; - int headerByteCount, outputLength, symbolRemaining; - - if(stream->status == DmtxStatusComplete) - return; - - if(!StreamInputHasNext(stream)) - { - headerByteCount = stream->outputChainWordCount - stream->outputChainValueCount; - assert(headerByteCount == 1 || headerByteCount == 2); - - /* Check for special case where every last symbol word is used */ - if(headerByteCount == 2) - { - /* Find symbol size as if headerByteCount was only 1 */ - outputLength = stream->output->length - 1; - sizeIdx = FindSymbolSize(outputLength, sizeIdxRequest); /* No CHKSIZE */ - if(sizeIdx != DmtxUndefined) - { - symbolRemaining = GetRemainingSymbolCapacity(outputLength, sizeIdx); - - if(symbolRemaining == 0) + int sizeIdx; + int headerByteCount, outputLength, symbolRemaining; + + if (stream->status == DmtxStatusComplete) + return; + + if (!StreamInputHasNext(stream)) + { + headerByteCount = stream->outputChainWordCount - stream->outputChainValueCount; + assert(headerByteCount == 1 || headerByteCount == 2); + + /* Check for special case where every last symbol word is used */ + if (headerByteCount == 2) + { + /* Find symbol size as if headerByteCount was only 1 */ + outputLength = stream->output->length - 1; + sizeIdx = FindSymbolSize(outputLength, sizeIdxRequest); /* No CHKSIZE */ + if (sizeIdx != DmtxUndefined) { - /* Perfect fit -- complete encoding */ - UpdateBase256ChainHeader(stream, sizeIdx); CHKERR; - StreamMarkComplete(stream, sizeIdx); - return; + symbolRemaining = GetRemainingSymbolCapacity(outputLength, sizeIdx); + + if (symbolRemaining == 0) + { + /* Perfect fit -- complete encoding */ + UpdateBase256ChainHeader(stream, sizeIdx); + CHKERR; + StreamMarkComplete(stream, sizeIdx); + return; + } } - } - } - - /* Normal case */ - sizeIdx = FindSymbolSize(stream->output->length, sizeIdxRequest); CHKSIZE; - EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchImplicit); - PadRemainingInAscii(stream, sizeIdx); - StreamMarkComplete(stream, sizeIdx); - } + } + + /* Normal case */ + sizeIdx = FindSymbolSize(stream->output->length, sizeIdxRequest); + CHKSIZE; + EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchImplicit); + PadRemainingInAscii(stream, sizeIdx); + StreamMarkComplete(stream, sizeIdx); + } } /** @@ -110,89 +120,96 @@ CompleteIfDoneBase256(DmtxEncodeStream *stream, int sizeIdxRequest) static void UpdateBase256ChainHeader(DmtxEncodeStream *stream, int perfectSizeIdx) { - int headerIndex; - int outputLength; - int headerByteCount; - int symbolDataWords; - DmtxBoolean perfectFit; - DmtxByte headerValue0; - DmtxByte headerValue1; - - outputLength = stream->outputChainValueCount; - headerIndex = stream->output->length - stream->outputChainWordCount; - headerByteCount = stream->outputChainWordCount - stream->outputChainValueCount; - perfectFit = (perfectSizeIdx == DmtxUndefined) ? DmtxFalse : DmtxTrue; - - /* - * If requested perfect fit verify symbol capacity against final length - */ - - if(perfectFit) - { - symbolDataWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, perfectSizeIdx); - if(symbolDataWords != stream->output->length - 1) - { - StreamMarkFatal(stream, DmtxErrorUnknown); - return; - } - } - - /* - * Adjust header to hold correct number of bytes, not worrying about the - * values held there until below. Note: Header bytes are not considered - * scheme "values" so we can insert or remove them without updating the - * outputChainValueCount. - */ - - if(headerByteCount == 0 && stream->outputChainWordCount == 0) - { - /* No output words written yet -- insert single header byte */ - StreamOutputChainAppend(stream, 0); CHKERR; - headerByteCount++; - } - else if(!perfectFit && headerByteCount == 1 && outputLength > 249) - { - /* Beyond 249 bytes requires a second header byte */ - Base256OutputChainInsertFirst(stream); CHKERR; - headerByteCount++; - } - else if(perfectFit && headerByteCount == 2) - { - /* Encoding to exact end of symbol only requires single byte */ - Base256OutputChainRemoveFirst(stream); CHKERR; - headerByteCount--; - } - - /* - * Encode header byte(s) with current length - */ - - if(!perfectFit && headerByteCount == 1 && outputLength <= 249) - { - /* Normal condition for chain length < 250 bytes */ - headerValue0 = Randomize255State(outputLength, headerIndex + 1); - StreamOutputSet(stream, headerIndex, headerValue0); CHKERR; - } - else if(!perfectFit && headerByteCount == 2 && outputLength > 249) - { - /* Normal condition for chain length >= 250 bytes */ - headerValue0 = Randomize255State(outputLength/250 + 249, headerIndex + 1); - StreamOutputSet(stream, headerIndex, headerValue0); CHKERR; - - headerValue1 = Randomize255State(outputLength%250, headerIndex + 2); - StreamOutputSet(stream, headerIndex + 1, headerValue1); CHKERR; - } - else if(perfectFit && headerByteCount == 1) - { - /* Special condition when Base 256 stays in effect to end of symbol */ - headerValue0 = Randomize255State(0, headerIndex + 1); /* XXX replace magic value 0? */ - StreamOutputSet(stream, headerIndex, headerValue0); CHKERR; - } - else - { - StreamMarkFatal(stream, DmtxErrorUnknown); - return; - } + int headerIndex; + int outputLength; + int headerByteCount; + int symbolDataWords; + DmtxBoolean perfectFit; + DmtxByte headerValue0; + DmtxByte headerValue1; + + outputLength = stream->outputChainValueCount; + headerIndex = stream->output->length - stream->outputChainWordCount; + headerByteCount = stream->outputChainWordCount - stream->outputChainValueCount; + perfectFit = (perfectSizeIdx == DmtxUndefined) ? DmtxFalse : DmtxTrue; + + /* + * If requested perfect fit verify symbol capacity against final length + */ + + if (perfectFit) + { + symbolDataWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, perfectSizeIdx); + if (symbolDataWords != stream->output->length - 1) + { + StreamMarkFatal(stream, DmtxErrorUnknown); + return; + } + } + + /* + * Adjust header to hold correct number of bytes, not worrying about the + * values held there until below. Note: Header bytes are not considered + * scheme "values" so we can insert or remove them without updating the + * outputChainValueCount. + */ + + if (headerByteCount == 0 && stream->outputChainWordCount == 0) + { + /* No output words written yet -- insert single header byte */ + StreamOutputChainAppend(stream, 0); + CHKERR; + headerByteCount++; + } + else if (!perfectFit && headerByteCount == 1 && outputLength > 249) + { + /* Beyond 249 bytes requires a second header byte */ + Base256OutputChainInsertFirst(stream); + CHKERR; + headerByteCount++; + } + else if (perfectFit && headerByteCount == 2) + { + /* Encoding to exact end of symbol only requires single byte */ + Base256OutputChainRemoveFirst(stream); + CHKERR; + headerByteCount--; + } + + /* + * Encode header byte(s) with current length + */ + + if (!perfectFit && headerByteCount == 1 && outputLength <= 249) + { + /* Normal condition for chain length < 250 bytes */ + headerValue0 = Randomize255State(outputLength, headerIndex + 1); + StreamOutputSet(stream, headerIndex, headerValue0); + CHKERR; + } + else if (!perfectFit && headerByteCount == 2 && outputLength > 249) + { + /* Normal condition for chain length >= 250 bytes */ + headerValue0 = Randomize255State(outputLength / 250 + 249, headerIndex + 1); + StreamOutputSet(stream, headerIndex, headerValue0); + CHKERR; + + headerValue1 = Randomize255State(outputLength % 250, headerIndex + 2); + StreamOutputSet(stream, headerIndex + 1, headerValue1); + CHKERR; + } + else if (perfectFit && headerByteCount == 1) + { + /* Special condition when Base 256 stays in effect to end of symbol */ + headerValue0 = Randomize255State(0, headerIndex + 1); /* XXX replace magic value 0? */ + StreamOutputSet(stream, headerIndex, headerValue0); + CHKERR; + } + else + { + StreamMarkFatal(stream, DmtxErrorUnknown); + return; + } } /** @@ -202,26 +219,26 @@ UpdateBase256ChainHeader(DmtxEncodeStream *stream, int perfectSizeIdx) static void Base256OutputChainInsertFirst(DmtxEncodeStream *stream) { - DmtxByte value; - DmtxPassFail passFail; - int i, chainStart; - - chainStart = stream->output->length - stream->outputChainWordCount; - dmtxByteListPush(stream->output, 0, &passFail); - if(passFail == DmtxPass) - { - for(i = stream->output->length - 1; i > chainStart; i--) - { - value = UnRandomize255State(stream->output->b[i-1], i); - stream->output->b[i] = Randomize255State(value, i + 1); - } - - stream->outputChainWordCount++; - } - else - { - StreamMarkFatal(stream, DmtxErrorUnknown); - } + DmtxByte value; + DmtxPassFail passFail; + int i, chainStart; + + chainStart = stream->output->length - stream->outputChainWordCount; + dmtxByteListPush(stream->output, 0, &passFail); + if (passFail == DmtxPass) + { + for (i = stream->output->length - 1; i > chainStart; i--) + { + value = UnRandomize255State(stream->output->b[i - 1], i); + stream->output->b[i] = Randomize255State(value, i + 1); + } + + stream->outputChainWordCount++; + } + else + { + StreamMarkFatal(stream, DmtxErrorUnknown); + } } /** @@ -231,23 +248,23 @@ Base256OutputChainInsertFirst(DmtxEncodeStream *stream) static void Base256OutputChainRemoveFirst(DmtxEncodeStream *stream) { - DmtxByte value; - DmtxPassFail passFail; - int i, chainStart; - - chainStart = stream->output->length - stream->outputChainWordCount; - - for(i = chainStart; i < stream->output->length - 1; i++) - { - value = UnRandomize255State(stream->output->b[i+1], i+2); - stream->output->b[i] = Randomize255State(value, i + 1); - } - - dmtxByteListPop(stream->output, &passFail); - if(passFail == DmtxPass) - stream->outputChainWordCount--; - else - StreamMarkFatal(stream, DmtxErrorUnknown); + DmtxByte value; + DmtxPassFail passFail; + int i, chainStart; + + chainStart = stream->output->length - stream->outputChainWordCount; + + for (i = chainStart; i < stream->output->length - 1; i++) + { + value = UnRandomize255State(stream->output->b[i + 1], i + 2); + stream->output->b[i] = Randomize255State(value, i + 1); + } + + dmtxByteListPop(stream->output, &passFail); + if (passFail == DmtxPass) + stream->outputChainWordCount--; + else + StreamMarkFatal(stream, DmtxErrorUnknown); } /** @@ -259,12 +276,12 @@ Base256OutputChainRemoveFirst(DmtxEncodeStream *stream) static DmtxByte Randomize255State(DmtxByte value, int position) { - int pseudoRandom, tmp; + int pseudoRandom, tmp; - pseudoRandom = ((149 * position) % 255) + 1; - tmp = value + pseudoRandom; + pseudoRandom = ((149 * position) % 255) + 1; + tmp = value + pseudoRandom; - return (tmp <= 255) ? tmp : tmp - 256; + return (tmp <= 255) ? tmp : tmp - 256; } /** @@ -276,15 +293,15 @@ Randomize255State(DmtxByte value, int position) static unsigned char UnRandomize255State(unsigned char value, int idx) { - int pseudoRandom; - int tmp; + int pseudoRandom; + int tmp; - pseudoRandom = ((149 * idx) % 255) + 1; - tmp = value - pseudoRandom; - if(tmp < 0) - tmp += 256; + pseudoRandom = ((149 * idx) % 255) + 1; + tmp = value - pseudoRandom; + if (tmp < 0) + tmp += 256; - assert(tmp >= 0 && tmp < 256); + assert(tmp >= 0 && tmp < 256); - return (unsigned char)tmp; + return (unsigned char)tmp; } diff --git a/dmtxencodec40textx12.c b/dmtxencodec40textx12.c index 9a0b02b7..c1a2d59c 100644 --- a/dmtxencodec40textx12.c +++ b/dmtxencodec40textx12.c @@ -15,16 +15,40 @@ */ #undef CHKERR -#define CHKERR { if(stream->status != DmtxStatusEncoding) { return; } } +#define CHKERR \ + { \ + if (stream->status != DmtxStatusEncoding) \ + { \ + return; \ + } \ + } #undef CHKSIZE -#define CHKSIZE { if(sizeIdx == DmtxUndefined) { StreamMarkInvalid(stream, DmtxErrorUnknown); return; } } +#define CHKSIZE \ + { \ + if (sizeIdx == DmtxUndefined) \ + { \ + StreamMarkInvalid(stream, DmtxErrorUnknown); \ + return; \ + } \ + } #undef CHKPASS -#define CHKPASS { if(passFail == DmtxFail) { StreamMarkFatal(stream, DmtxErrorUnknown); return; } } +#define CHKPASS \ + { \ + if (passFail == DmtxFail) \ + { \ + StreamMarkFatal(stream, DmtxErrorUnknown); \ + return; \ + } \ + } #undef RETURN_IF_FAIL -#define RETURN_IF_FAIL { if(*passFail == DmtxFail) return; } +#define RETURN_IF_FAIL \ + { \ + if (*passFail == DmtxFail) \ + return; \ + } /** * @@ -33,74 +57,88 @@ static void EncodeNextChunkCTX(DmtxEncodeStream *stream, int sizeIdxRequest) { - int i; - DmtxPassFail passFail; - DmtxByte inputValue; - DmtxByte valueListStorage[6]; - DmtxByteList valueList = dmtxByteListBuild(valueListStorage, sizeof(valueListStorage)); - - while(StreamInputHasNext(stream)) - { - if(stream->currentScheme == DmtxSchemeX12) - { - /* Check for FNC1 character */ - inputValue = StreamInputPeekNext(stream); CHKERR; - if(stream->fnc1 != DmtxUndefined && (int)inputValue == stream->fnc1) { - /* X12 does not allow partial blocks, resend last 1 or 2 as ASCII */ - EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchExplicit); CHKERR; - for(i = 0; i < valueList.length % 3; i++) - StreamInputAdvancePrev(stream); CHKERR; - - while(i) { - inputValue = StreamInputAdvanceNext(stream); CHKERR; - AppendValueAscii(stream, inputValue + 1); CHKERR; - i--; - } - - StreamInputAdvanceNext(stream); CHKERR; - AppendValueAscii(stream, DmtxValueFNC1); CHKERR; - return; - } - } - inputValue = StreamInputAdvanceNext(stream); CHKERR; - - /* Expand next input value into up to 4 CTX values and add to valueList */ - PushCTXValues(&valueList, inputValue, stream->currentScheme, &passFail, stream->fnc1); - if(passFail == DmtxFail) - { - /* XXX Perhaps PushCTXValues should return this error code */ - StreamMarkInvalid(stream, DmtxErrorUnsupportedCharacter); - return; - } - - /* If there at least 3 CTX values available encode them to output */ - while(valueList.length >= 3) - { - AppendValuesCTX(stream, &valueList); CHKERR; - ShiftValueListBy3(&valueList, &passFail); CHKPASS; - } - - /* Finished on byte boundary -- done with current chunk */ - if(valueList.length == 0) - break; - } - - /* - * Special case: If all input values have been consumed and 1 or 2 unwritten - * C40/Text/X12 values remain, finish encoding the symbol according to the - * established end-of-symbol conditions. - */ - if(!StreamInputHasNext(stream) && valueList.length > 0) - { - if(stream->currentScheme == DmtxSchemeX12) - { - CompletePartialX12(stream, &valueList, sizeIdxRequest); CHKERR; - } - else - { - CompletePartialC40Text(stream, &valueList, sizeIdxRequest); CHKERR; - } - } + int i; + DmtxPassFail passFail; + DmtxByte inputValue; + DmtxByte valueListStorage[6]; + DmtxByteList valueList = dmtxByteListBuild(valueListStorage, sizeof(valueListStorage)); + + while (StreamInputHasNext(stream)) + { + if (stream->currentScheme == DmtxSchemeX12) + { + /* Check for FNC1 character */ + inputValue = StreamInputPeekNext(stream); + CHKERR; + if (stream->fnc1 != DmtxUndefined && (int)inputValue == stream->fnc1) + { + /* X12 does not allow partial blocks, resend last 1 or 2 as ASCII */ + EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchExplicit); + CHKERR; + for (i = 0; i < valueList.length % 3; i++) + StreamInputAdvancePrev(stream); + CHKERR; + + while (i) + { + inputValue = StreamInputAdvanceNext(stream); + CHKERR; + AppendValueAscii(stream, inputValue + 1); + CHKERR; + i--; + } + + StreamInputAdvanceNext(stream); + CHKERR; + AppendValueAscii(stream, DmtxValueFNC1); + CHKERR; + return; + } + } + inputValue = StreamInputAdvanceNext(stream); + CHKERR; + + /* Expand next input value into up to 4 CTX values and add to valueList */ + PushCTXValues(&valueList, inputValue, stream->currentScheme, &passFail, stream->fnc1); + if (passFail == DmtxFail) + { + /* XXX Perhaps PushCTXValues should return this error code */ + StreamMarkInvalid(stream, DmtxErrorUnsupportedCharacter); + return; + } + + /* If there at least 3 CTX values available encode them to output */ + while (valueList.length >= 3) + { + AppendValuesCTX(stream, &valueList); + CHKERR; + ShiftValueListBy3(&valueList, &passFail); + CHKPASS; + } + + /* Finished on byte boundary -- done with current chunk */ + if (valueList.length == 0) + break; + } + + /* + * Special case: If all input values have been consumed and 1 or 2 unwritten + * C40/Text/X12 values remain, finish encoding the symbol according to the + * established end-of-symbol conditions. + */ + if (!StreamInputHasNext(stream) && valueList.length > 0) + { + if (stream->currentScheme == DmtxSchemeX12) + { + CompletePartialX12(stream, &valueList, sizeIdxRequest); + CHKERR; + } + else + { + CompletePartialC40Text(stream, &valueList, sizeIdxRequest); + CHKERR; + } + } } /** @@ -110,32 +148,34 @@ EncodeNextChunkCTX(DmtxEncodeStream *stream, int sizeIdxRequest) static void AppendValuesCTX(DmtxEncodeStream *stream, DmtxByteList *valueList) { - int pairValue; - DmtxByte cw0, cw1; - - if(!IsCTX(stream->currentScheme)) - { - StreamMarkFatal(stream, DmtxErrorUnexpectedScheme); - return; - } - - if(valueList->length < 3) - { - StreamMarkFatal(stream, DmtxErrorIncompleteValueList); - return; - } - - /* Build codewords from computed value */ - pairValue = (1600 * valueList->b[0]) + (40 * valueList->b[1]) + valueList->b[2] + 1; - cw0 = pairValue / 256; - cw1 = pairValue % 256; - - /* Append 2 codewords */ - StreamOutputChainAppend(stream, cw0); CHKERR; - StreamOutputChainAppend(stream, cw1); CHKERR; - - /* Update count for 3 encoded values */ - stream->outputChainValueCount += 3; + int pairValue; + DmtxByte cw0, cw1; + + if (!IsCTX(stream->currentScheme)) + { + StreamMarkFatal(stream, DmtxErrorUnexpectedScheme); + return; + } + + if (valueList->length < 3) + { + StreamMarkFatal(stream, DmtxErrorIncompleteValueList); + return; + } + + /* Build codewords from computed value */ + pairValue = (1600 * valueList->b[0]) + (40 * valueList->b[1]) + valueList->b[2] + 1; + cw0 = pairValue / 256; + cw1 = pairValue % 256; + + /* Append 2 codewords */ + StreamOutputChainAppend(stream, cw0); + CHKERR; + StreamOutputChainAppend(stream, cw1); + CHKERR; + + /* Update count for 3 encoded values */ + stream->outputChainValueCount += 3; } /** @@ -145,22 +185,23 @@ AppendValuesCTX(DmtxEncodeStream *stream, DmtxByteList *valueList) static void AppendUnlatchCTX(DmtxEncodeStream *stream) { - if(!IsCTX(stream->currentScheme)) - { - StreamMarkFatal(stream, DmtxErrorUnexpectedScheme); - return; - } - - /* Verify we are on byte boundary */ - if(stream->outputChainValueCount % 3 != 0) - { - StreamMarkInvalid(stream, DmtxErrorNotOnByteBoundary); - return; - } - - StreamOutputChainAppend(stream, DmtxValueCTXUnlatch); CHKERR; - - stream->outputChainValueCount++; + if (!IsCTX(stream->currentScheme)) + { + StreamMarkFatal(stream, DmtxErrorUnexpectedScheme); + return; + } + + /* Verify we are on byte boundary */ + if (stream->outputChainValueCount % 3 != 0) + { + StreamMarkInvalid(stream, DmtxErrorNotOnByteBoundary); + return; + } + + StreamOutputChainAppend(stream, DmtxValueCTXUnlatch); + CHKERR; + + stream->outputChainValueCount++; } /** @@ -175,25 +216,27 @@ AppendUnlatchCTX(DmtxEncodeStream *stream) static void CompleteIfDoneCTX(DmtxEncodeStream *stream, int sizeIdxRequest) { - int sizeIdx; - int symbolRemaining; - - if(stream->status == DmtxStatusComplete) - return; - - if(!StreamInputHasNext(stream)) - { - sizeIdx = FindSymbolSize(stream->output->length, sizeIdxRequest); CHKSIZE; - symbolRemaining = GetRemainingSymbolCapacity(stream->output->length, sizeIdx); - - if(symbolRemaining > 0) - { - EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchExplicit); CHKERR; - PadRemainingInAscii(stream, sizeIdx); - } - - StreamMarkComplete(stream, sizeIdx); - } + int sizeIdx; + int symbolRemaining; + + if (stream->status == DmtxStatusComplete) + return; + + if (!StreamInputHasNext(stream)) + { + sizeIdx = FindSymbolSize(stream->output->length, sizeIdxRequest); + CHKSIZE; + symbolRemaining = GetRemainingSymbolCapacity(stream->output->length, sizeIdx); + + if (symbolRemaining > 0) + { + EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchExplicit); + CHKERR; + PadRemainingInAscii(stream, sizeIdx); + } + + StreamMarkComplete(stream, sizeIdx); + } } /** @@ -224,88 +267,97 @@ CompleteIfDoneCTX(DmtxEncodeStream *stream, int sizeIdxRequest) static void CompletePartialC40Text(DmtxEncodeStream *stream, DmtxByteList *valueList, int sizeIdxRequest) { - int i; - int sizeIdx1, sizeIdx2; - int symbolRemaining1, symbolRemaining2; - DmtxPassFail passFail; - DmtxByte inputValue; - DmtxByte outputTmpStorage[4]; - DmtxByteList outputTmp = dmtxByteListBuild(outputTmpStorage, sizeof(outputTmpStorage)); - - if(stream->currentScheme != DmtxSchemeC40 && stream->currentScheme != DmtxSchemeText) - { - StreamMarkFatal(stream, DmtxErrorUnexpectedScheme); - return; - } - - /* Should have exactly one or two input values left */ - assert(valueList->length == 1 || valueList->length == 2); - - sizeIdx1 = FindSymbolSize(stream->output->length + 1, sizeIdxRequest); - sizeIdx2 = FindSymbolSize(stream->output->length + 2, sizeIdxRequest); - - symbolRemaining1 = GetRemainingSymbolCapacity(stream->output->length, sizeIdx1); - symbolRemaining2 = GetRemainingSymbolCapacity(stream->output->length, sizeIdx2); - - if(valueList->length == 2 && symbolRemaining2 == 2) - { - /* End of symbol condition (b) -- Use Shift1 to pad final list value */ - dmtxByteListPush(valueList, DmtxValueCTXShift1, &passFail); CHKPASS; - AppendValuesCTX(stream, valueList); CHKERR; - StreamMarkComplete(stream, sizeIdx2); - } - else - { - /* - * Rollback progress of previously consumed input value(s) since ASCII - * encoder will be used to finish the symbol. 2 rollbacks are needed if - * valueList holds 2 data words (i.e., not shifts or upper shifts). - */ - - StreamInputAdvancePrev(stream); CHKERR; - inputValue = StreamInputPeekNext(stream); CHKERR; - - /* Test-encode most recently consumed input value to C40/Text/X12 */ - PushCTXValues(&outputTmp, inputValue, stream->currentScheme, &passFail, stream->fnc1); - if(valueList->length == 2 && outputTmp.length == 1) - StreamInputAdvancePrev(stream); CHKERR; - - /* Re-use outputTmp to hold ASCII representation of 1-2 input values */ - /* XXX Refactor how the DmtxByteList is passed back here */ - outputTmp = EncodeTmpRemainingInAscii(stream, outputTmpStorage, - sizeof(outputTmpStorage), &passFail); - - if(passFail == DmtxFail) - { - StreamMarkFatal(stream, DmtxErrorUnknown); - return; - } - - if(outputTmp.length == 1 && symbolRemaining1 == 1) - { - /* End of symbol condition (d) */ - EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchImplicit); CHKERR; - AppendValueAscii(stream, outputTmp.b[0]); CHKERR; - - /* Register progress since encoding happened outside normal path */ - stream->inputNext = stream->input->length; - StreamMarkComplete(stream, sizeIdx1); - } - else - { - /* Finish in ASCII (c) */ - EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchExplicit); CHKERR; - for(i = 0; i < outputTmp.length; i++) - AppendValueAscii(stream, outputTmp.b[i]); CHKERR; - - sizeIdx1 = FindSymbolSize(stream->output->length, sizeIdxRequest); - PadRemainingInAscii(stream, sizeIdx1); - - /* Register progress since encoding happened outside normal path */ - stream->inputNext = stream->input->length; - StreamMarkComplete(stream, sizeIdx1); - } - } + int i; + int sizeIdx1, sizeIdx2; + int symbolRemaining1, symbolRemaining2; + DmtxPassFail passFail; + DmtxByte inputValue; + DmtxByte outputTmpStorage[4]; + DmtxByteList outputTmp = dmtxByteListBuild(outputTmpStorage, sizeof(outputTmpStorage)); + + if (stream->currentScheme != DmtxSchemeC40 && stream->currentScheme != DmtxSchemeText) + { + StreamMarkFatal(stream, DmtxErrorUnexpectedScheme); + return; + } + + /* Should have exactly one or two input values left */ + assert(valueList->length == 1 || valueList->length == 2); + + sizeIdx1 = FindSymbolSize(stream->output->length + 1, sizeIdxRequest); + sizeIdx2 = FindSymbolSize(stream->output->length + 2, sizeIdxRequest); + + symbolRemaining1 = GetRemainingSymbolCapacity(stream->output->length, sizeIdx1); + symbolRemaining2 = GetRemainingSymbolCapacity(stream->output->length, sizeIdx2); + + if (valueList->length == 2 && symbolRemaining2 == 2) + { + /* End of symbol condition (b) -- Use Shift1 to pad final list value */ + dmtxByteListPush(valueList, DmtxValueCTXShift1, &passFail); + CHKPASS; + AppendValuesCTX(stream, valueList); + CHKERR; + StreamMarkComplete(stream, sizeIdx2); + } + else + { + /* + * Rollback progress of previously consumed input value(s) since ASCII + * encoder will be used to finish the symbol. 2 rollbacks are needed if + * valueList holds 2 data words (i.e., not shifts or upper shifts). + */ + + StreamInputAdvancePrev(stream); + CHKERR; + inputValue = StreamInputPeekNext(stream); + CHKERR; + + /* Test-encode most recently consumed input value to C40/Text/X12 */ + PushCTXValues(&outputTmp, inputValue, stream->currentScheme, &passFail, stream->fnc1); + if (valueList->length == 2 && outputTmp.length == 1) + StreamInputAdvancePrev(stream); + CHKERR; + + /* Re-use outputTmp to hold ASCII representation of 1-2 input values */ + /* XXX Refactor how the DmtxByteList is passed back here */ + outputTmp = EncodeTmpRemainingInAscii(stream, outputTmpStorage, + sizeof(outputTmpStorage), &passFail); + + if (passFail == DmtxFail) + { + StreamMarkFatal(stream, DmtxErrorUnknown); + return; + } + + if (outputTmp.length == 1 && symbolRemaining1 == 1) + { + /* End of symbol condition (d) */ + EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchImplicit); + CHKERR; + AppendValueAscii(stream, outputTmp.b[0]); + CHKERR; + + /* Register progress since encoding happened outside normal path */ + stream->inputNext = stream->input->length; + StreamMarkComplete(stream, sizeIdx1); + } + else + { + /* Finish in ASCII (c) */ + EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchExplicit); + CHKERR; + for (i = 0; i < outputTmp.length; i++) + AppendValueAscii(stream, outputTmp.b[i]); + CHKERR; + + sizeIdx1 = FindSymbolSize(stream->output->length, sizeIdxRequest); + PadRemainingInAscii(stream, sizeIdx1); + + /* Register progress since encoding happened outside normal path */ + stream->inputNext = stream->input->length; + StreamMarkComplete(stream, sizeIdx1); + } + } } /** @@ -316,59 +368,64 @@ CompletePartialC40Text(DmtxEncodeStream *stream, DmtxByteList *valueList, int si static void CompletePartialX12(DmtxEncodeStream *stream, DmtxByteList *valueList, int sizeIdxRequest) { - int i; - int sizeIdx; - int symbolRemaining; - DmtxPassFail passFail; - DmtxByte outputTmpStorage[2]; - DmtxByteList outputTmp; - - if(stream->currentScheme != DmtxSchemeX12) - { - StreamMarkFatal(stream, DmtxErrorUnexpectedScheme); - return; - } - - /* Should have exactly one or two input values left */ - assert(valueList->length == 1 || valueList->length == 2); - - /* Roll back input progress */ - for(i = 0; i < valueList->length; i++) - { - StreamInputAdvancePrev(stream); CHKERR; - } - - /* Encode up to 2 codewords to a temporary stream */ - outputTmp = EncodeTmpRemainingInAscii(stream, outputTmpStorage, - sizeof(outputTmpStorage), &passFail); - - sizeIdx = FindSymbolSize(stream->output->length + 1, sizeIdxRequest); - symbolRemaining = GetRemainingSymbolCapacity(stream->output->length, sizeIdx); - - if(outputTmp.length == 1 && symbolRemaining == 1) - { - /* End of symbol condition (XXX) */ - EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchImplicit); CHKERR; - AppendValueAscii(stream, outputTmp.b[0]); CHKERR; - - /* Register progress since encoding happened outside normal path */ - stream->inputNext = stream->input->length; - StreamMarkComplete(stream, sizeIdx); - } - else - { - /* Finish in ASCII (XXX) */ - EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchExplicit); CHKERR; - for(i = 0; i < outputTmp.length; i++) - AppendValueAscii(stream, outputTmp.b[i]); CHKERR; - - sizeIdx = FindSymbolSize(stream->output->length, sizeIdxRequest); - PadRemainingInAscii(stream, sizeIdx); - - /* Register progress since encoding happened outside normal path */ - stream->inputNext = stream->input->length; - StreamMarkComplete(stream, sizeIdx); - } + int i; + int sizeIdx; + int symbolRemaining; + DmtxPassFail passFail; + DmtxByte outputTmpStorage[2]; + DmtxByteList outputTmp; + + if (stream->currentScheme != DmtxSchemeX12) + { + StreamMarkFatal(stream, DmtxErrorUnexpectedScheme); + return; + } + + /* Should have exactly one or two input values left */ + assert(valueList->length == 1 || valueList->length == 2); + + /* Roll back input progress */ + for (i = 0; i < valueList->length; i++) + { + StreamInputAdvancePrev(stream); + CHKERR; + } + + /* Encode up to 2 codewords to a temporary stream */ + outputTmp = EncodeTmpRemainingInAscii(stream, outputTmpStorage, + sizeof(outputTmpStorage), &passFail); + + sizeIdx = FindSymbolSize(stream->output->length + 1, sizeIdxRequest); + symbolRemaining = GetRemainingSymbolCapacity(stream->output->length, sizeIdx); + + if (outputTmp.length == 1 && symbolRemaining == 1) + { + /* End of symbol condition (XXX) */ + EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchImplicit); + CHKERR; + AppendValueAscii(stream, outputTmp.b[0]); + CHKERR; + + /* Register progress since encoding happened outside normal path */ + stream->inputNext = stream->input->length; + StreamMarkComplete(stream, sizeIdx); + } + else + { + /* Finish in ASCII (XXX) */ + EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchExplicit); + CHKERR; + for (i = 0; i < outputTmp.length; i++) + AppendValueAscii(stream, outputTmp.b[i]); + CHKERR; + + sizeIdx = FindSymbolSize(stream->output->length, sizeIdxRequest); + PadRemainingInAscii(stream, sizeIdx); + + /* Register progress since encoding happened outside normal path */ + stream->inputNext = stream->input->length; + StreamMarkComplete(stream, sizeIdx); + } } /** @@ -377,45 +434,45 @@ CompletePartialX12(DmtxEncodeStream *stream, DmtxByteList *valueList, int sizeId static DmtxBoolean PartialX12ChunkRemains(DmtxEncodeStream *stream) { - DmtxEncodeStream streamTmp; - DmtxByte inputValue; - DmtxByte valueListStorage[6]; - DmtxByteList valueList = dmtxByteListBuild(valueListStorage, sizeof(valueListStorage)); - DmtxPassFail passFail; - - /* Create temporary copy of stream to track test input progress */ - streamTmp = *stream; - streamTmp.currentScheme = DmtxSchemeX12; - streamTmp.outputChainValueCount = 0; - streamTmp.outputChainWordCount = 0; - streamTmp.reason = NULL; - streamTmp.sizeIdx = DmtxUndefined; - streamTmp.status = DmtxStatusEncoding; - streamTmp.output = NULL; - - while(StreamInputHasNext(&streamTmp)) - { - inputValue = StreamInputAdvanceNext(&streamTmp); - if(stream->status != DmtxStatusEncoding) - { - StreamMarkInvalid(stream, DmtxErrorUnknown); - return DmtxFalse; - } - - /* Expand next input value into up to 4 CTX values and add to valueList */ - PushCTXValues(&valueList, inputValue, streamTmp.currentScheme, &passFail, stream->fnc1); - if(passFail == DmtxFail) - { - StreamMarkInvalid(stream, DmtxErrorUnknown); - return DmtxFalse; - } - - /* Not a final partial chunk */ - if(valueList.length >= 3) - return DmtxFalse; - } - - return (valueList.length == 0) ? DmtxFalse : DmtxTrue; + DmtxEncodeStream streamTmp; + DmtxByte inputValue; + DmtxByte valueListStorage[6]; + DmtxByteList valueList = dmtxByteListBuild(valueListStorage, sizeof(valueListStorage)); + DmtxPassFail passFail; + + /* Create temporary copy of stream to track test input progress */ + streamTmp = *stream; + streamTmp.currentScheme = DmtxSchemeX12; + streamTmp.outputChainValueCount = 0; + streamTmp.outputChainWordCount = 0; + streamTmp.reason = NULL; + streamTmp.sizeIdx = DmtxUndefined; + streamTmp.status = DmtxStatusEncoding; + streamTmp.output = NULL; + + while (StreamInputHasNext(&streamTmp)) + { + inputValue = StreamInputAdvanceNext(&streamTmp); + if (stream->status != DmtxStatusEncoding) + { + StreamMarkInvalid(stream, DmtxErrorUnknown); + return DmtxFalse; + } + + /* Expand next input value into up to 4 CTX values and add to valueList */ + PushCTXValues(&valueList, inputValue, streamTmp.currentScheme, &passFail, stream->fnc1); + if (passFail == DmtxFail) + { + StreamMarkInvalid(stream, DmtxErrorUnknown); + return DmtxFalse; + } + + /* Not a final partial chunk */ + if (valueList.length >= 3) + return DmtxFalse; + } + + return (valueList.length == 0) ? DmtxFalse : DmtxTrue; } /** @@ -424,128 +481,156 @@ PartialX12ChunkRemains(DmtxEncodeStream *stream) */ static void PushCTXValues(DmtxByteList *valueList, DmtxByte inputValue, int targetScheme, - DmtxPassFail *passFail, int fnc1) + DmtxPassFail *passFail, int fnc1) { - assert(valueList->length <= 2); - - /* Handle extended ASCII with Upper Shift character */ - if(inputValue > 127 && (fnc1 == DmtxUndefined || (int)inputValue != fnc1)) - { - if(targetScheme == DmtxSchemeX12) - { - *passFail = DmtxFail; - return; - } - else - { - dmtxByteListPush(valueList, DmtxValueCTXShift2, passFail); RETURN_IF_FAIL; - dmtxByteListPush(valueList, 30, passFail); RETURN_IF_FAIL; - inputValue -= 128; - } - } - - /* Handle all other characters according to encodation scheme */ - if(targetScheme == DmtxSchemeX12) - { - if(inputValue == 13) - { - dmtxByteListPush(valueList, 0, passFail); RETURN_IF_FAIL; - } - else if(inputValue == 42) - { - dmtxByteListPush(valueList, 1, passFail); RETURN_IF_FAIL; - } - else if(inputValue == 62) - { - dmtxByteListPush(valueList, 2, passFail); RETURN_IF_FAIL; - } - else if(inputValue == 32) - { - dmtxByteListPush(valueList, 3, passFail); RETURN_IF_FAIL; - } - else if(inputValue >= 48 && inputValue <= 57) - { - dmtxByteListPush(valueList, inputValue - 44, passFail); RETURN_IF_FAIL; - } - else if(inputValue >= 65 && inputValue <= 90) - { - dmtxByteListPush(valueList, inputValue - 51, passFail); RETURN_IF_FAIL; - } - else - { - *passFail = DmtxFail; - return; - } - } - else - { - /* targetScheme is C40 or Text */ - - /* Check for FNC1 character */ - if(fnc1 != DmtxUndefined && (int)inputValue == fnc1) - { - dmtxByteListPush(valueList, DmtxValueCTXShift2, passFail); RETURN_IF_FAIL; - dmtxByteListPush(valueList, 27, passFail); RETURN_IF_FAIL; /* C40 version of FNC1 */ - } - else if(inputValue <= 31) - { - dmtxByteListPush(valueList, DmtxValueCTXShift1, passFail); RETURN_IF_FAIL; - dmtxByteListPush(valueList, inputValue, passFail); RETURN_IF_FAIL; - } - else if(inputValue == 32) - { - dmtxByteListPush(valueList, 3, passFail); RETURN_IF_FAIL; - } - else if(inputValue <= 47) - { - dmtxByteListPush(valueList, DmtxValueCTXShift2, passFail); RETURN_IF_FAIL; - dmtxByteListPush(valueList, inputValue - 33, passFail); RETURN_IF_FAIL; - } - else if(inputValue <= 57) - { - dmtxByteListPush(valueList, inputValue - 44, passFail); RETURN_IF_FAIL; - } - else if(inputValue <= 64) - { - dmtxByteListPush(valueList, DmtxValueCTXShift2, passFail); RETURN_IF_FAIL; - dmtxByteListPush(valueList, inputValue - 43, passFail); RETURN_IF_FAIL; - } - else if(inputValue <= 90 && targetScheme == DmtxSchemeC40) - { - dmtxByteListPush(valueList, inputValue - 51, passFail); RETURN_IF_FAIL; - } - else if(inputValue <= 90 && targetScheme == DmtxSchemeText) - { - dmtxByteListPush(valueList, DmtxValueCTXShift3, passFail); RETURN_IF_FAIL; - dmtxByteListPush(valueList, inputValue - 64, passFail); RETURN_IF_FAIL; - } - else if(inputValue <= 95) - { - dmtxByteListPush(valueList, DmtxValueCTXShift2, passFail); RETURN_IF_FAIL; - dmtxByteListPush(valueList, inputValue - 69, passFail); RETURN_IF_FAIL; - } - else if(inputValue == 96 && targetScheme == DmtxSchemeText) - { - dmtxByteListPush(valueList, DmtxValueCTXShift3, passFail); RETURN_IF_FAIL; - dmtxByteListPush(valueList, 0, passFail); RETURN_IF_FAIL; - } - else if(inputValue <= 122 && targetScheme == DmtxSchemeText) - { - dmtxByteListPush(valueList, inputValue - 83, passFail); RETURN_IF_FAIL; - } - else if(inputValue <= 127) - { - dmtxByteListPush(valueList, DmtxValueCTXShift3, passFail); RETURN_IF_FAIL; - dmtxByteListPush(valueList, inputValue - 96, passFail); RETURN_IF_FAIL; - } - else - { - *passFail = DmtxFail; - return; - } - } - - *passFail = DmtxPass; + assert(valueList->length <= 2); + + /* Handle extended ASCII with Upper Shift character */ + if (inputValue > 127 && (fnc1 == DmtxUndefined || (int)inputValue != fnc1)) + { + if (targetScheme == DmtxSchemeX12) + { + *passFail = DmtxFail; + return; + } + else + { + dmtxByteListPush(valueList, DmtxValueCTXShift2, passFail); + RETURN_IF_FAIL; + dmtxByteListPush(valueList, 30, passFail); + RETURN_IF_FAIL; + inputValue -= 128; + } + } + + /* Handle all other characters according to encodation scheme */ + if (targetScheme == DmtxSchemeX12) + { + if (inputValue == 13) + { + dmtxByteListPush(valueList, 0, passFail); + RETURN_IF_FAIL; + } + else if (inputValue == 42) + { + dmtxByteListPush(valueList, 1, passFail); + RETURN_IF_FAIL; + } + else if (inputValue == 62) + { + dmtxByteListPush(valueList, 2, passFail); + RETURN_IF_FAIL; + } + else if (inputValue == 32) + { + dmtxByteListPush(valueList, 3, passFail); + RETURN_IF_FAIL; + } + else if (inputValue >= 48 && inputValue <= 57) + { + dmtxByteListPush(valueList, inputValue - 44, passFail); + RETURN_IF_FAIL; + } + else if (inputValue >= 65 && inputValue <= 90) + { + dmtxByteListPush(valueList, inputValue - 51, passFail); + RETURN_IF_FAIL; + } + else + { + *passFail = DmtxFail; + return; + } + } + else + { + /* targetScheme is C40 or Text */ + + /* Check for FNC1 character */ + if (fnc1 != DmtxUndefined && (int)inputValue == fnc1) + { + dmtxByteListPush(valueList, DmtxValueCTXShift2, passFail); + RETURN_IF_FAIL; + dmtxByteListPush(valueList, 27, passFail); + RETURN_IF_FAIL; /* C40 version of FNC1 */ + } + else if (inputValue <= 31) + { + dmtxByteListPush(valueList, DmtxValueCTXShift1, passFail); + RETURN_IF_FAIL; + dmtxByteListPush(valueList, inputValue, passFail); + RETURN_IF_FAIL; + } + else if (inputValue == 32) + { + dmtxByteListPush(valueList, 3, passFail); + RETURN_IF_FAIL; + } + else if (inputValue <= 47) + { + dmtxByteListPush(valueList, DmtxValueCTXShift2, passFail); + RETURN_IF_FAIL; + dmtxByteListPush(valueList, inputValue - 33, passFail); + RETURN_IF_FAIL; + } + else if (inputValue <= 57) + { + dmtxByteListPush(valueList, inputValue - 44, passFail); + RETURN_IF_FAIL; + } + else if (inputValue <= 64) + { + dmtxByteListPush(valueList, DmtxValueCTXShift2, passFail); + RETURN_IF_FAIL; + dmtxByteListPush(valueList, inputValue - 43, passFail); + RETURN_IF_FAIL; + } + else if (inputValue <= 90 && targetScheme == DmtxSchemeC40) + { + dmtxByteListPush(valueList, inputValue - 51, passFail); + RETURN_IF_FAIL; + } + else if (inputValue <= 90 && targetScheme == DmtxSchemeText) + { + dmtxByteListPush(valueList, DmtxValueCTXShift3, passFail); + RETURN_IF_FAIL; + dmtxByteListPush(valueList, inputValue - 64, passFail); + RETURN_IF_FAIL; + } + else if (inputValue <= 95) + { + dmtxByteListPush(valueList, DmtxValueCTXShift2, passFail); + RETURN_IF_FAIL; + dmtxByteListPush(valueList, inputValue - 69, passFail); + RETURN_IF_FAIL; + } + else if (inputValue == 96 && targetScheme == DmtxSchemeText) + { + dmtxByteListPush(valueList, DmtxValueCTXShift3, passFail); + RETURN_IF_FAIL; + dmtxByteListPush(valueList, 0, passFail); + RETURN_IF_FAIL; + } + else if (inputValue <= 122 && targetScheme == DmtxSchemeText) + { + dmtxByteListPush(valueList, inputValue - 83, passFail); + RETURN_IF_FAIL; + } + else if (inputValue <= 127) + { + dmtxByteListPush(valueList, DmtxValueCTXShift3, passFail); + RETURN_IF_FAIL; + dmtxByteListPush(valueList, inputValue - 96, passFail); + RETURN_IF_FAIL; + } + else + { + *passFail = DmtxFail; + return; + } + } + + *passFail = DmtxPass; } /** @@ -555,14 +640,14 @@ PushCTXValues(DmtxByteList *valueList, DmtxByte inputValue, int targetScheme, static DmtxBoolean IsCTX(int scheme) { - DmtxBoolean isCTX; + DmtxBoolean isCTX; - if(scheme == DmtxSchemeC40 || scheme == DmtxSchemeText || scheme == DmtxSchemeX12) - isCTX = DmtxTrue; - else - isCTX = DmtxFalse; + if (scheme == DmtxSchemeC40 || scheme == DmtxSchemeText || scheme == DmtxSchemeX12) + isCTX = DmtxTrue; + else + isCTX = DmtxFalse; - return isCTX; + return isCTX; } /** @@ -572,22 +657,22 @@ IsCTX(int scheme) static void ShiftValueListBy3(DmtxByteList *list, DmtxPassFail *passFail) { - int i; + int i; - /* Shift values */ - for(i = 0; i < list->length - 3; i++) - list->b[i] = list->b[i+3]; + /* Shift values */ + for (i = 0; i < list->length - 3; i++) + list->b[i] = list->b[i + 3]; - /* Shorten list by 3 (or less) */ - for(i = 0; i < 3; i++) - { - dmtxByteListPop(list, passFail); - if(*passFail == DmtxFail) - return; + /* Shorten list by 3 (or less) */ + for (i = 0; i < 3; i++) + { + dmtxByteListPop(list, passFail); + if (*passFail == DmtxFail) + return; - if(list->length == 0) - break; - } + if (list->length == 0) + break; + } - *passFail = DmtxPass; + *passFail = DmtxPass; } diff --git a/dmtxencodeedifact.c b/dmtxencodeedifact.c index ad48df62..04cb46d9 100644 --- a/dmtxencodeedifact.c +++ b/dmtxencodeedifact.c @@ -21,29 +21,37 @@ static void EncodeNextChunkEdifact(DmtxEncodeStream *stream) { - DmtxByte value; + DmtxByte value; - if(StreamInputHasNext(stream)) - { - /* Check for FNC1 character, which needs to be sent in ASCII */ - value = StreamInputPeekNext(stream); CHKERR; + if (StreamInputHasNext(stream)) + { + /* Check for FNC1 character, which needs to be sent in ASCII */ + value = StreamInputPeekNext(stream); + CHKERR; - if((value < 32 || value > 94)) { - StreamMarkInvalid(stream, DmtxChannelUnsupportedChar); - return; - } + if ((value < 32 || value > 94)) + { + StreamMarkInvalid(stream, DmtxChannelUnsupportedChar); + return; + } - if (stream->fnc1 != DmtxUndefined && (int)value == stream->fnc1) { - EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchExplicit); CHKERR; + if (stream->fnc1 != DmtxUndefined && (int)value == stream->fnc1) + { + EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchExplicit); + CHKERR; - StreamInputAdvanceNext(stream); CHKERR; - AppendValueAscii(stream, DmtxValueFNC1); CHKERR; - return; - } + StreamInputAdvanceNext(stream); + CHKERR; + AppendValueAscii(stream, DmtxValueFNC1); + CHKERR; + return; + } - value = StreamInputAdvanceNext(stream); CHKERR; - AppendValueEdifact(stream, value); CHKERR; - } + value = StreamInputAdvanceNext(stream); + CHKERR; + AppendValueEdifact(stream, value); + CHKERR; + } } /** @@ -53,45 +61,54 @@ EncodeNextChunkEdifact(DmtxEncodeStream *stream) static void AppendValueEdifact(DmtxEncodeStream *stream, DmtxByte value) { - DmtxByte edifactValue, previousOutput; - - CHKSCHEME(DmtxSchemeEdifact); - - /* - * TODO: KECA -> korean, circles - * TODO: UNOX -> ISO-2022-JP - * TODO: and so on - */ - if(value < 31 || value > 94) - { - StreamMarkInvalid(stream, DmtxChannelUnsupportedChar); - return; - } - - edifactValue = (value & 0x3f) << 2; - - switch(stream->outputChainValueCount % 4) - { - case 0: - StreamOutputChainAppend(stream, edifactValue); CHKERR; - break; - case 1: - previousOutput = StreamOutputChainRemoveLast(stream); CHKERR; - StreamOutputChainAppend(stream, previousOutput | (edifactValue >> 6)); CHKERR; - StreamOutputChainAppend(stream, edifactValue << 2); CHKERR; - break; - case 2: - previousOutput = StreamOutputChainRemoveLast(stream); CHKERR; - StreamOutputChainAppend(stream, previousOutput | (edifactValue >> 4)); CHKERR; - StreamOutputChainAppend(stream, edifactValue << 4); CHKERR; - break; - case 3: - previousOutput = StreamOutputChainRemoveLast(stream); CHKERR; - StreamOutputChainAppend(stream, previousOutput | (edifactValue >> 2)); CHKERR; - break; - } - - stream->outputChainValueCount++; + DmtxByte edifactValue, previousOutput; + + CHKSCHEME(DmtxSchemeEdifact); + + /* + * TODO: KECA -> korean, circles + * TODO: UNOX -> ISO-2022-JP + * TODO: and so on + */ + if (value < 31 || value > 94) + { + StreamMarkInvalid(stream, DmtxChannelUnsupportedChar); + return; + } + + edifactValue = (value & 0x3f) << 2; + + switch (stream->outputChainValueCount % 4) + { + case 0: + StreamOutputChainAppend(stream, edifactValue); + CHKERR; + break; + case 1: + previousOutput = StreamOutputChainRemoveLast(stream); + CHKERR; + StreamOutputChainAppend(stream, previousOutput | (edifactValue >> 6)); + CHKERR; + StreamOutputChainAppend(stream, edifactValue << 2); + CHKERR; + break; + case 2: + previousOutput = StreamOutputChainRemoveLast(stream); + CHKERR; + StreamOutputChainAppend(stream, previousOutput | (edifactValue >> 4)); + CHKERR; + StreamOutputChainAppend(stream, edifactValue << 4); + CHKERR; + break; + case 3: + previousOutput = StreamOutputChainRemoveLast(stream); + CHKERR; + StreamOutputChainAppend(stream, previousOutput | (edifactValue >> 2)); + CHKERR; + break; + } + + stream->outputChainValueCount++; } /** @@ -113,78 +130,88 @@ AppendValueEdifact(DmtxEncodeStream *stream, DmtxByte value) static void CompleteIfDoneEdifact(DmtxEncodeStream *stream, int sizeIdxRequest) { - int i; - int sizeIdx; - int symbolRemaining; - DmtxBoolean cleanBoundary; - DmtxPassFail passFail; - DmtxByte outputTmpStorage[3]; - DmtxByteList outputTmp; - - if(stream->status == DmtxStatusComplete) - return; - - /* - * If we just completed a triplet (cleanBoundary), 1 or 2 symbol codewords - * remain, and our remaining inputs (if any) represented in ASCII would fit - * in the remaining space, encode them in ASCII with an implicit unlatch. - */ - - cleanBoundary = (stream->outputChainValueCount % 4 == 0) ? DmtxTrue : DmtxFalse; - - if(cleanBoundary == DmtxTrue) - { - /* Encode up to 3 codewords to a temporary stream */ - outputTmp = EncodeTmpRemainingInAscii(stream, outputTmpStorage, - sizeof(outputTmpStorage), &passFail); - - if(passFail == DmtxFail) - { - StreamMarkFatal(stream, DmtxErrorUnknown); - return; - } - - if(outputTmp.length < 3) - { - /* Find minimum symbol size for projected length */ - sizeIdx = FindSymbolSize(stream->output->length + outputTmp.length, sizeIdxRequest); CHKSIZE; - - /* Find remaining capacity over current length */ - symbolRemaining = GetRemainingSymbolCapacity(stream->output->length, sizeIdx); CHKERR; - - if(symbolRemaining < 3 && outputTmp.length <= symbolRemaining) - { - EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchImplicit); CHKERR; - - for(i = 0; i < outputTmp.length; i++) - { - AppendValueAscii(stream, outputTmp.b[i]); CHKERR; - } + int i; + int sizeIdx; + int symbolRemaining; + DmtxBoolean cleanBoundary; + DmtxPassFail passFail; + DmtxByte outputTmpStorage[3]; + DmtxByteList outputTmp; + + if (stream->status == DmtxStatusComplete) + return; + + /* + * If we just completed a triplet (cleanBoundary), 1 or 2 symbol codewords + * remain, and our remaining inputs (if any) represented in ASCII would fit + * in the remaining space, encode them in ASCII with an implicit unlatch. + */ + + cleanBoundary = (stream->outputChainValueCount % 4 == 0) ? DmtxTrue : DmtxFalse; + + if (cleanBoundary == DmtxTrue) + { + /* Encode up to 3 codewords to a temporary stream */ + outputTmp = EncodeTmpRemainingInAscii(stream, outputTmpStorage, + sizeof(outputTmpStorage), &passFail); + + if (passFail == DmtxFail) + { + StreamMarkFatal(stream, DmtxErrorUnknown); + return; + } - /* Register progress since encoding happened outside normal path */ - stream->inputNext = stream->input->length; + if (outputTmp.length < 3) + { + /* Find minimum symbol size for projected length */ + sizeIdx = FindSymbolSize(stream->output->length + outputTmp.length, sizeIdxRequest); + CHKSIZE; - /* Pad remaining if necessary */ - PadRemainingInAscii(stream, sizeIdx); CHKERR; - StreamMarkComplete(stream, sizeIdx); - return; - } - } - } - - if(!StreamInputHasNext(stream)) - { - sizeIdx = FindSymbolSize(stream->output->length, sizeIdxRequest); CHKSIZE; - symbolRemaining = GetRemainingSymbolCapacity(stream->output->length, sizeIdx); CHKERR; - - /* Explicit unlatch required unless on clean boundary and full symbol */ - if(cleanBoundary == DmtxFalse || symbolRemaining > 0) - { - EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchExplicit); CHKERR; - sizeIdx = FindSymbolSize(stream->output->length, sizeIdxRequest); CHKSIZE; - PadRemainingInAscii(stream, sizeIdx); CHKERR; - } - - StreamMarkComplete(stream, sizeIdx); - } + /* Find remaining capacity over current length */ + symbolRemaining = GetRemainingSymbolCapacity(stream->output->length, sizeIdx); + CHKERR; + + if (symbolRemaining < 3 && outputTmp.length <= symbolRemaining) + { + EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchImplicit); + CHKERR; + + for (i = 0; i < outputTmp.length; i++) + { + AppendValueAscii(stream, outputTmp.b[i]); + CHKERR; + } + + /* Register progress since encoding happened outside normal path */ + stream->inputNext = stream->input->length; + + /* Pad remaining if necessary */ + PadRemainingInAscii(stream, sizeIdx); + CHKERR; + StreamMarkComplete(stream, sizeIdx); + return; + } + } + } + + if (!StreamInputHasNext(stream)) + { + sizeIdx = FindSymbolSize(stream->output->length, sizeIdxRequest); + CHKSIZE; + symbolRemaining = GetRemainingSymbolCapacity(stream->output->length, sizeIdx); + CHKERR; + + /* Explicit unlatch required unless on clean boundary and full symbol */ + if (cleanBoundary == DmtxFalse || symbolRemaining > 0) + { + EncodeChangeScheme(stream, DmtxSchemeAscii, DmtxUnlatchExplicit); + CHKERR; + sizeIdx = FindSymbolSize(stream->output->length, sizeIdxRequest); + CHKSIZE; + PadRemainingInAscii(stream, sizeIdx); + CHKERR; + } + + StreamMarkComplete(stream, sizeIdx); + } } diff --git a/dmtxencodeoptimize.c b/dmtxencodeoptimize.c index 7b48219b..580f1586 100644 --- a/dmtxencodeoptimize.c +++ b/dmtxencodeoptimize.c @@ -40,38 +40,38 @@ enum SchemeState { #if DUMPSTREAMS static void DumpStreams(DmtxEncodeStream *streamBest) { - enum SchemeState state; - char prefix[32]; + enum SchemeState state; + char prefix[32]; - fprintf(stdout, "----------------------------------------\n"); - for(state = 0; state < SchemeStateCount; state++) - { - if(streamBest[state].status == DmtxStatusEncoding || + fprintf(stdout, "----------------------------------------\n"); + for (state = 0; state < SchemeStateCount; state++) + { + if (streamBest[state].status == DmtxStatusEncoding || streamBest[state].status == DmtxStatusComplete) - fprintf(stdout, "\"%c\" ", streamBest[state].input->b[streamBest[state].inputNext-1]); - else - fprintf(stdout, " "); + fprintf(stdout, "\"%c\" ", streamBest[state].input->b[streamBest[state].inputNext - 1]); + else + fprintf(stdout, " "); - switch(streamBest[state].status) { - case DmtxStatusEncoding: + switch (streamBest[state].status) + { + case DmtxStatusEncoding: snprintf(prefix, sizeof(prefix), "%2d (%s): ", state, " encode "); break; - case DmtxStatusComplete: + case DmtxStatusComplete: snprintf(prefix, sizeof(prefix), "%2d (%s): ", state, "complete"); break; - case DmtxStatusInvalid: + case DmtxStatusInvalid: snprintf(prefix, sizeof(prefix), "%2d (%s): ", state, "invalid "); break; - case DmtxStatusFatal: + case DmtxStatusFatal: snprintf(prefix, sizeof(prefix), "%2d (%s): ", state, " fatal "); break; - } - dmtxByteListPrint(streamBest[state].output, prefix); - } + } + dmtxByteListPrint(streamBest[state].output, prefix); + } } #endif - /** * * @@ -79,106 +79,106 @@ static void DumpStreams(DmtxEncodeStream *streamBest) static int EncodeOptimizeBest(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, int fnc1) { - enum SchemeState state; - int inputNext, c40ValueCount, textValueCount, x12ValueCount; - int sizeIdx; - DmtxEncodeStream *winner; - DmtxPassFail passFail; - DmtxEncodeStream streamsBest[SchemeStateCount]; - DmtxEncodeStream streamsTemp[SchemeStateCount]; - DmtxByte outputsBestStorage[SchemeStateCount][4096]; - DmtxByte outputsTempStorage[SchemeStateCount][4096]; - DmtxByte ctxTempStorage[4]; - DmtxByteList outputsBest[SchemeStateCount]; - DmtxByteList outputsTemp[SchemeStateCount]; - DmtxByteList ctxTemp = dmtxByteListBuild(ctxTempStorage, sizeof(ctxTempStorage)); - - /* Initialize all streams with their own output storage */ - for(state = 0; state < SchemeStateCount; state++) - { - outputsBest[state] = dmtxByteListBuild(outputsBestStorage[state], sizeof(outputsBestStorage[state])); - outputsTemp[state] = dmtxByteListBuild(outputsTempStorage[state], sizeof(outputsTempStorage[state])); - streamsBest[state] = StreamInit(input, &(outputsBest[state])); - streamsTemp[state] = StreamInit(input, &(outputsTemp[state])); - streamsBest[state].fnc1 = fnc1; - streamsTemp[state].fnc1 = fnc1; - } - - c40ValueCount = textValueCount = x12ValueCount = 0; - - for(inputNext = 0; inputNext < input->length; inputNext++) - { - StreamAdvanceFromBest(streamsTemp, streamsBest, AsciiFull, sizeIdxRequest); - - AdvanceAsciiCompact(streamsTemp, streamsBest, AsciiCompactOffset0, inputNext, sizeIdxRequest); - AdvanceAsciiCompact(streamsTemp, streamsBest, AsciiCompactOffset1, inputNext, sizeIdxRequest); - - AdvanceCTX(streamsTemp, streamsBest, C40Offset0, inputNext, c40ValueCount, sizeIdxRequest); - AdvanceCTX(streamsTemp, streamsBest, C40Offset1, inputNext, c40ValueCount, sizeIdxRequest); - AdvanceCTX(streamsTemp, streamsBest, C40Offset2, inputNext, c40ValueCount, sizeIdxRequest); - - AdvanceCTX(streamsTemp, streamsBest, TextOffset0, inputNext, textValueCount, sizeIdxRequest); - AdvanceCTX(streamsTemp, streamsBest, TextOffset1, inputNext, textValueCount, sizeIdxRequest); - AdvanceCTX(streamsTemp, streamsBest, TextOffset2, inputNext, textValueCount, sizeIdxRequest); - - AdvanceCTX(streamsTemp, streamsBest, X12Offset0, inputNext, x12ValueCount, sizeIdxRequest); - AdvanceCTX(streamsTemp, streamsBest, X12Offset1, inputNext, x12ValueCount, sizeIdxRequest); - AdvanceCTX(streamsTemp, streamsBest, X12Offset2, inputNext, x12ValueCount, sizeIdxRequest); - - AdvanceEdifact(streamsTemp, streamsBest, EdifactOffset0, inputNext, sizeIdxRequest); - AdvanceEdifact(streamsTemp, streamsBest, EdifactOffset1, inputNext, sizeIdxRequest); - AdvanceEdifact(streamsTemp, streamsBest, EdifactOffset2, inputNext, sizeIdxRequest); - AdvanceEdifact(streamsTemp, streamsBest, EdifactOffset3, inputNext, sizeIdxRequest); - - StreamAdvanceFromBest(streamsTemp, streamsBest, Base256, sizeIdxRequest); - - /* Overwrite best streams with new results */ - for(state = 0; state < SchemeStateCount; state++) - { - if(streamsBest[state].status != DmtxStatusComplete) - StreamCopy(&(streamsBest[state]), &(streamsTemp[state])); - } - - dmtxByteListClear(&ctxTemp); - PushCTXValues(&ctxTemp, input->b[inputNext], DmtxSchemeC40, &passFail, fnc1); - c40ValueCount += ((passFail == DmtxPass) ? ctxTemp.length : 1); - - dmtxByteListClear(&ctxTemp); - PushCTXValues(&ctxTemp, input->b[inputNext], DmtxSchemeText, &passFail, fnc1); - textValueCount += ((passFail == DmtxPass) ? ctxTemp.length : 1); - - dmtxByteListClear(&ctxTemp); - PushCTXValues(&ctxTemp, input->b[inputNext], DmtxSchemeX12, &passFail, fnc1); - x12ValueCount += ((passFail == DmtxPass) ? ctxTemp.length : 1); + enum SchemeState state; + int inputNext, c40ValueCount, textValueCount, x12ValueCount; + int sizeIdx; + DmtxEncodeStream *winner; + DmtxPassFail passFail; + DmtxEncodeStream streamsBest[SchemeStateCount]; + DmtxEncodeStream streamsTemp[SchemeStateCount]; + DmtxByte outputsBestStorage[SchemeStateCount][4096]; + DmtxByte outputsTempStorage[SchemeStateCount][4096]; + DmtxByte ctxTempStorage[4]; + DmtxByteList outputsBest[SchemeStateCount]; + DmtxByteList outputsTemp[SchemeStateCount]; + DmtxByteList ctxTemp = dmtxByteListBuild(ctxTempStorage, sizeof(ctxTempStorage)); + + /* Initialize all streams with their own output storage */ + for (state = 0; state < SchemeStateCount; state++) + { + outputsBest[state] = dmtxByteListBuild(outputsBestStorage[state], sizeof(outputsBestStorage[state])); + outputsTemp[state] = dmtxByteListBuild(outputsTempStorage[state], sizeof(outputsTempStorage[state])); + streamsBest[state] = StreamInit(input, &(outputsBest[state])); + streamsTemp[state] = StreamInit(input, &(outputsTemp[state])); + streamsBest[state].fnc1 = fnc1; + streamsTemp[state].fnc1 = fnc1; + } + + c40ValueCount = textValueCount = x12ValueCount = 0; + + for (inputNext = 0; inputNext < input->length; inputNext++) + { + StreamAdvanceFromBest(streamsTemp, streamsBest, AsciiFull, sizeIdxRequest); + + AdvanceAsciiCompact(streamsTemp, streamsBest, AsciiCompactOffset0, inputNext, sizeIdxRequest); + AdvanceAsciiCompact(streamsTemp, streamsBest, AsciiCompactOffset1, inputNext, sizeIdxRequest); + + AdvanceCTX(streamsTemp, streamsBest, C40Offset0, inputNext, c40ValueCount, sizeIdxRequest); + AdvanceCTX(streamsTemp, streamsBest, C40Offset1, inputNext, c40ValueCount, sizeIdxRequest); + AdvanceCTX(streamsTemp, streamsBest, C40Offset2, inputNext, c40ValueCount, sizeIdxRequest); + + AdvanceCTX(streamsTemp, streamsBest, TextOffset0, inputNext, textValueCount, sizeIdxRequest); + AdvanceCTX(streamsTemp, streamsBest, TextOffset1, inputNext, textValueCount, sizeIdxRequest); + AdvanceCTX(streamsTemp, streamsBest, TextOffset2, inputNext, textValueCount, sizeIdxRequest); + + AdvanceCTX(streamsTemp, streamsBest, X12Offset0, inputNext, x12ValueCount, sizeIdxRequest); + AdvanceCTX(streamsTemp, streamsBest, X12Offset1, inputNext, x12ValueCount, sizeIdxRequest); + AdvanceCTX(streamsTemp, streamsBest, X12Offset2, inputNext, x12ValueCount, sizeIdxRequest); + + AdvanceEdifact(streamsTemp, streamsBest, EdifactOffset0, inputNext, sizeIdxRequest); + AdvanceEdifact(streamsTemp, streamsBest, EdifactOffset1, inputNext, sizeIdxRequest); + AdvanceEdifact(streamsTemp, streamsBest, EdifactOffset2, inputNext, sizeIdxRequest); + AdvanceEdifact(streamsTemp, streamsBest, EdifactOffset3, inputNext, sizeIdxRequest); + + StreamAdvanceFromBest(streamsTemp, streamsBest, Base256, sizeIdxRequest); + + /* Overwrite best streams with new results */ + for (state = 0; state < SchemeStateCount; state++) + { + if (streamsBest[state].status != DmtxStatusComplete) + StreamCopy(&(streamsBest[state]), &(streamsTemp[state])); + } + + dmtxByteListClear(&ctxTemp); + PushCTXValues(&ctxTemp, input->b[inputNext], DmtxSchemeC40, &passFail, fnc1); + c40ValueCount += ((passFail == DmtxPass) ? ctxTemp.length : 1); + + dmtxByteListClear(&ctxTemp); + PushCTXValues(&ctxTemp, input->b[inputNext], DmtxSchemeText, &passFail, fnc1); + textValueCount += ((passFail == DmtxPass) ? ctxTemp.length : 1); + + dmtxByteListClear(&ctxTemp); + PushCTXValues(&ctxTemp, input->b[inputNext], DmtxSchemeX12, &passFail, fnc1); + x12ValueCount += ((passFail == DmtxPass) ? ctxTemp.length : 1); #if DUMPSTREAMS - DumpStreams(streamsBest); + DumpStreams(streamsBest); #endif - } - - /* Choose the overall winner */ - winner = NULL; - for(state = 0; state < SchemeStateCount; state++) - { - if(streamsBest[state].status == DmtxStatusComplete) - { - if(winner == NULL || streamsBest[state].output->length < winner->output->length) - winner = &(streamsBest[state]); - } - } - - /* Copy winner to output */ - if(winner == NULL) - { - sizeIdx = DmtxUndefined; - } - else - { - dmtxByteListCopy(output, winner->output, &passFail); - sizeIdx = (passFail == DmtxPass) ? winner->sizeIdx : DmtxUndefined; - } - - return sizeIdx; + } + + /* Choose the overall winner */ + winner = NULL; + for (state = 0; state < SchemeStateCount; state++) + { + if (streamsBest[state].status == DmtxStatusComplete) + { + if (winner == NULL || streamsBest[state].output->length < winner->output->length) + winner = &(streamsBest[state]); + } + } + + /* Copy winner to output */ + if (winner == NULL) + { + sizeIdx = DmtxUndefined; + } + else + { + dmtxByteListCopy(output, winner->output, &passFail); + sizeIdx = (passFail == DmtxPass) ? winner->sizeIdx : DmtxUndefined; + } + + return sizeIdx; } /** @@ -188,43 +188,43 @@ EncodeOptimizeBest(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest */ static void StreamAdvanceFromBest(DmtxEncodeStream *streamsNext, DmtxEncodeStream *streamsBest, - int targetState, int sizeIdxRequest) + int targetState, int sizeIdxRequest) { - enum SchemeState fromState; - DmtxScheme targetScheme; - DmtxEncodeOption encodeOption; - DmtxByte outputTempStorage[4096]; - DmtxByteList outputTemp = dmtxByteListBuild(outputTempStorage, sizeof(outputTempStorage)); - DmtxEncodeStream streamTemp; - DmtxEncodeStream *targetStream = &(streamsNext[targetState]); - - streamTemp.output = &outputTemp; /* Set directly instead of calling StreamInit() */ - targetScheme = GetScheme(targetState); - - if(targetState == AsciiFull) - encodeOption = DmtxEncodeFull; - else if(targetState == AsciiCompactOffset0 || targetState == AsciiCompactOffset1) - encodeOption = DmtxEncodeCompact; - else - encodeOption = DmtxEncodeNormal; - - for(fromState = 0; fromState < SchemeStateCount; fromState++) - { - if(streamsBest[fromState].status != DmtxStatusEncoding || + enum SchemeState fromState; + DmtxScheme targetScheme; + DmtxEncodeOption encodeOption; + DmtxByte outputTempStorage[4096]; + DmtxByteList outputTemp = dmtxByteListBuild(outputTempStorage, sizeof(outputTempStorage)); + DmtxEncodeStream streamTemp; + DmtxEncodeStream *targetStream = &(streamsNext[targetState]); + + streamTemp.output = &outputTemp; /* Set directly instead of calling StreamInit() */ + targetScheme = GetScheme(targetState); + + if (targetState == AsciiFull) + encodeOption = DmtxEncodeFull; + else if (targetState == AsciiCompactOffset0 || targetState == AsciiCompactOffset1) + encodeOption = DmtxEncodeCompact; + else + encodeOption = DmtxEncodeNormal; + + for (fromState = 0; fromState < SchemeStateCount; fromState++) + { + if (streamsBest[fromState].status != DmtxStatusEncoding || ValidStateSwitch(fromState, targetState) == DmtxFalse) - { - continue; - } - - StreamCopy(&streamTemp, &(streamsBest[fromState])); - EncodeNextChunk(&streamTemp, targetScheme, encodeOption, sizeIdxRequest); - - if(fromState == 0 || (streamTemp.status != DmtxStatusInvalid && - streamTemp.output->length < targetStream->output->length)) - { - StreamCopy(targetStream, &streamTemp); - } - } + { + continue; + } + + StreamCopy(&streamTemp, &(streamsBest[fromState])); + EncodeNextChunk(&streamTemp, targetScheme, encodeOption, sizeIdxRequest); + + if (fromState == 0 || (streamTemp.status != DmtxStatusInvalid && + streamTemp.output->length < targetStream->output->length)) + { + StreamCopy(targetStream, &streamTemp); + } + } } /** @@ -232,40 +232,40 @@ StreamAdvanceFromBest(DmtxEncodeStream *streamsNext, DmtxEncodeStream *streamsBe */ static void AdvanceAsciiCompact(DmtxEncodeStream *streamsNext, DmtxEncodeStream *streamsBest, - int targetState, int inputNext, int sizeIdxRequest) + int targetState, int inputNext, int sizeIdxRequest) { - DmtxEncodeStream *currentStream = &(streamsBest[targetState]); - DmtxEncodeStream *targetStream = &(streamsNext[targetState]); - DmtxBoolean isStartState; - - switch(targetState) - { - case AsciiCompactOffset0: - isStartState = (inputNext % 2 == 0) ? DmtxTrue : DmtxFalse; - break; - - case AsciiCompactOffset1: - isStartState = (inputNext % 2 == 1) ? DmtxTrue : DmtxFalse; - break; - - default: - StreamMarkFatal(targetStream, DmtxErrorIllegalParameterValue); - return; - } - - if(inputNext < currentStream->inputNext) - { - StreamCopy(targetStream, currentStream); - } - else if(isStartState == DmtxTrue) - { - StreamAdvanceFromBest(streamsNext, streamsBest, targetState, sizeIdxRequest); - } - else - { - StreamCopy(targetStream, currentStream); - StreamMarkInvalid(targetStream, DmtxErrorUnknown); - } + DmtxEncodeStream *currentStream = &(streamsBest[targetState]); + DmtxEncodeStream *targetStream = &(streamsNext[targetState]); + DmtxBoolean isStartState; + + switch (targetState) + { + case AsciiCompactOffset0: + isStartState = (inputNext % 2 == 0) ? DmtxTrue : DmtxFalse; + break; + + case AsciiCompactOffset1: + isStartState = (inputNext % 2 == 1) ? DmtxTrue : DmtxFalse; + break; + + default: + StreamMarkFatal(targetStream, DmtxErrorIllegalParameterValue); + return; + } + + if (inputNext < currentStream->inputNext) + { + StreamCopy(targetStream, currentStream); + } + else if (isStartState == DmtxTrue) + { + StreamAdvanceFromBest(streamsNext, streamsBest, targetState, sizeIdxRequest); + } + else + { + StreamCopy(targetStream, currentStream); + StreamMarkInvalid(targetStream, DmtxErrorUnknown); + } } /** @@ -273,51 +273,51 @@ AdvanceAsciiCompact(DmtxEncodeStream *streamsNext, DmtxEncodeStream *streamsBest */ static void AdvanceCTX(DmtxEncodeStream *streamsNext, DmtxEncodeStream *streamsBest, - int targetState, int inputNext, int ctxValueCount, int sizeIdxRequest) + int targetState, int inputNext, int ctxValueCount, int sizeIdxRequest) { - DmtxEncodeStream *currentStream = &(streamsBest[targetState]); - DmtxEncodeStream *targetStream = &(streamsNext[targetState]); - DmtxBoolean isStartState; - - /* we won't actually use inputNext here */ - switch(targetState) - { - case C40Offset0: - case TextOffset0: - case X12Offset0: - isStartState = (ctxValueCount % 3 == 0) ? DmtxTrue : DmtxFalse; - break; - - case C40Offset1: - case TextOffset1: - case X12Offset1: - isStartState = (ctxValueCount % 3 == 1) ? DmtxTrue : DmtxFalse; - break; - - case C40Offset2: - case TextOffset2: - case X12Offset2: - isStartState = (ctxValueCount % 3 == 2) ? DmtxTrue : DmtxFalse; - break; - - default: - StreamMarkFatal(targetStream, DmtxErrorIllegalParameterValue); - return; - } - - if(inputNext < currentStream->inputNext) - { - StreamCopy(targetStream, currentStream); - } - else if(isStartState == DmtxTrue) - { - StreamAdvanceFromBest(streamsNext, streamsBest, targetState, sizeIdxRequest); - } - else - { - StreamCopy(targetStream, currentStream); - StreamMarkInvalid(targetStream, DmtxErrorUnknown); - } + DmtxEncodeStream *currentStream = &(streamsBest[targetState]); + DmtxEncodeStream *targetStream = &(streamsNext[targetState]); + DmtxBoolean isStartState; + + /* we won't actually use inputNext here */ + switch (targetState) + { + case C40Offset0: + case TextOffset0: + case X12Offset0: + isStartState = (ctxValueCount % 3 == 0) ? DmtxTrue : DmtxFalse; + break; + + case C40Offset1: + case TextOffset1: + case X12Offset1: + isStartState = (ctxValueCount % 3 == 1) ? DmtxTrue : DmtxFalse; + break; + + case C40Offset2: + case TextOffset2: + case X12Offset2: + isStartState = (ctxValueCount % 3 == 2) ? DmtxTrue : DmtxFalse; + break; + + default: + StreamMarkFatal(targetStream, DmtxErrorIllegalParameterValue); + return; + } + + if (inputNext < currentStream->inputNext) + { + StreamCopy(targetStream, currentStream); + } + else if (isStartState == DmtxTrue) + { + StreamAdvanceFromBest(streamsNext, streamsBest, targetState, sizeIdxRequest); + } + else + { + StreamCopy(targetStream, currentStream); + StreamMarkInvalid(targetStream, DmtxErrorUnknown); + } } /** @@ -325,47 +325,47 @@ AdvanceCTX(DmtxEncodeStream *streamsNext, DmtxEncodeStream *streamsBest, */ static void AdvanceEdifact(DmtxEncodeStream *streamsNext, DmtxEncodeStream *streamsBest, - int targetState, int inputNext, int sizeIdxRequest) + int targetState, int inputNext, int sizeIdxRequest) { - DmtxEncodeStream *currentStream = &(streamsBest[targetState]); - DmtxEncodeStream *targetStream = &(streamsNext[targetState]); - DmtxBoolean isStartState; - - switch(targetState) - { - case EdifactOffset0: - isStartState = (inputNext % 4 == 0) ? DmtxTrue : DmtxFalse; - break; - - case EdifactOffset1: - isStartState = (inputNext % 4 == 1) ? DmtxTrue : DmtxFalse; - break; - - case EdifactOffset2: - isStartState = (inputNext % 4 == 2) ? DmtxTrue : DmtxFalse; - break; - - case EdifactOffset3: - isStartState = (inputNext % 4 == 3) ? DmtxTrue : DmtxFalse; - break; - - default: - StreamMarkFatal(targetStream, DmtxErrorIllegalParameterValue); - return; - } - - if(isStartState == DmtxTrue) - { - StreamAdvanceFromBest(streamsNext, streamsBest, targetState, sizeIdxRequest); - } - else - { - StreamCopy(targetStream, currentStream); - if(currentStream->status == DmtxStatusEncoding && currentStream->currentScheme == DmtxSchemeEdifact) - EncodeNextChunk(targetStream, DmtxSchemeEdifact, DmtxEncodeNormal, sizeIdxRequest); - else - StreamMarkInvalid(targetStream, DmtxErrorUnknown); - } + DmtxEncodeStream *currentStream = &(streamsBest[targetState]); + DmtxEncodeStream *targetStream = &(streamsNext[targetState]); + DmtxBoolean isStartState; + + switch (targetState) + { + case EdifactOffset0: + isStartState = (inputNext % 4 == 0) ? DmtxTrue : DmtxFalse; + break; + + case EdifactOffset1: + isStartState = (inputNext % 4 == 1) ? DmtxTrue : DmtxFalse; + break; + + case EdifactOffset2: + isStartState = (inputNext % 4 == 2) ? DmtxTrue : DmtxFalse; + break; + + case EdifactOffset3: + isStartState = (inputNext % 4 == 3) ? DmtxTrue : DmtxFalse; + break; + + default: + StreamMarkFatal(targetStream, DmtxErrorIllegalParameterValue); + return; + } + + if (isStartState == DmtxTrue) + { + StreamAdvanceFromBest(streamsNext, streamsBest, targetState, sizeIdxRequest); + } + else + { + StreamCopy(targetStream, currentStream); + if (currentStream->status == DmtxStatusEncoding && currentStream->currentScheme == DmtxSchemeEdifact) + EncodeNextChunk(targetStream, DmtxSchemeEdifact, DmtxEncodeNormal, sizeIdxRequest); + else + StreamMarkInvalid(targetStream, DmtxErrorUnknown); + } } /** @@ -375,45 +375,45 @@ AdvanceEdifact(DmtxEncodeStream *streamsNext, DmtxEncodeStream *streamsBest, static int GetScheme(int state) { - DmtxScheme scheme; - - switch(state) - { - case AsciiFull: - case AsciiCompactOffset0: - case AsciiCompactOffset1: - scheme = DmtxSchemeAscii; - break; - case C40Offset0: - case C40Offset1: - case C40Offset2: - scheme = DmtxSchemeC40; - break; - case TextOffset0: - case TextOffset1: - case TextOffset2: - scheme = DmtxSchemeText; - break; - case X12Offset0: - case X12Offset1: - case X12Offset2: - scheme = DmtxSchemeX12; - break; - case EdifactOffset0: - case EdifactOffset1: - case EdifactOffset2: - case EdifactOffset3: - scheme = DmtxSchemeEdifact; - break; - case Base256: - scheme = DmtxSchemeBase256; - break; - default: - scheme = DmtxUndefined; - break; - } - - return scheme; + DmtxScheme scheme; + + switch (state) + { + case AsciiFull: + case AsciiCompactOffset0: + case AsciiCompactOffset1: + scheme = DmtxSchemeAscii; + break; + case C40Offset0: + case C40Offset1: + case C40Offset2: + scheme = DmtxSchemeC40; + break; + case TextOffset0: + case TextOffset1: + case TextOffset2: + scheme = DmtxSchemeText; + break; + case X12Offset0: + case X12Offset1: + case X12Offset2: + scheme = DmtxSchemeX12; + break; + case EdifactOffset0: + case EdifactOffset1: + case EdifactOffset2: + case EdifactOffset3: + scheme = DmtxSchemeEdifact; + break; + case Base256: + scheme = DmtxSchemeBase256; + break; + default: + scheme = DmtxUndefined; + break; + } + + return scheme; } /** @@ -423,19 +423,19 @@ GetScheme(int state) static DmtxBoolean ValidStateSwitch(int fromState, int targetState) { - DmtxBoolean validStateSwitch; - DmtxScheme fromScheme = GetScheme(fromState); - DmtxScheme toScheme = GetScheme(targetState); - - if(fromScheme == toScheme && fromState != targetState && - fromState != AsciiFull && targetState != AsciiFull) - { - validStateSwitch = DmtxFalse; - } - else - { - validStateSwitch = DmtxTrue; - } - - return validStateSwitch; + DmtxBoolean validStateSwitch; + DmtxScheme fromScheme = GetScheme(fromState); + DmtxScheme toScheme = GetScheme(targetState); + + if (fromScheme == toScheme && fromState != targetState && + fromState != AsciiFull && targetState != AsciiFull) + { + validStateSwitch = DmtxFalse; + } + else + { + validStateSwitch = DmtxTrue; + } + + return validStateSwitch; } diff --git a/dmtxencodescheme.c b/dmtxencodescheme.c index a20c3996..08e59d12 100644 --- a/dmtxencodescheme.c +++ b/dmtxencodescheme.c @@ -66,30 +66,44 @@ */ /* Verify stream is using expected scheme */ -#define CHKSCHEME(s) { \ - if(stream->currentScheme != (s)) { StreamMarkFatal(stream, DmtxErrorUnexpectedScheme); return; } \ -} +#define CHKSCHEME(s) \ + { \ + if (stream->currentScheme != (s)) \ + { \ + StreamMarkFatal(stream, DmtxErrorUnexpectedScheme); \ + return; \ + } \ + } /* CHKERR should follow any call that might alter stream status */ -#define CHKERR { \ - if(stream->status != DmtxStatusEncoding) { return; } \ -} +#define CHKERR \ + { \ + if (stream->status != DmtxStatusEncoding) \ + { \ + return; \ + } \ + } /* CHKSIZE should follows typical calls to FindSymbolSize() */ -#define CHKSIZE { \ - if(sizeIdx == DmtxUndefined) { StreamMarkInvalid(stream, DmtxErrorUnknown); return; } \ -} +#define CHKSIZE \ + { \ + if (sizeIdx == DmtxUndefined) \ + { \ + StreamMarkInvalid(stream, DmtxErrorUnknown); \ + return; \ + } \ + } /** * * */ #ifdef HAVE_READER_PROGRAMMING - static int - EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming) +static int +EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming) #else - static int - EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1) +static int +EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1) #endif { DmtxEncodeStream stream; @@ -97,12 +111,13 @@ stream = StreamInit(input, output); stream.fnc1 = fnc1; - #ifdef HAVE_READER_PROGRAMMING - if (bReaderProgramming == DmtxTrue) { - /* change to have reader programming label */ - AppendValueAscii(&stream, DmtxValueReaderProgramming); - } - #endif +#ifdef HAVE_READER_PROGRAMMING + if (bReaderProgramming == DmtxTrue) + { + /* change to have reader programming label */ + AppendValueAscii(&stream, DmtxValueReaderProgramming); + } +#endif /* 1st FNC1 special case, encode before scheme switch */ if (fnc1 != DmtxUndefined && (int)(input->b[0]) == fnc1) @@ -112,11 +127,11 @@ } /* Continue encoding until complete */ - while(stream.status == DmtxStatusEncoding) + while (stream.status == DmtxStatusEncoding) EncodeNextChunk(&stream, scheme, DmtxEncodeNormal, sizeIdxRequest); /* Verify encoding completed and all inputs were consumed */ - if(stream.status != DmtxStatusComplete || StreamInputHasNext(&stream)) + if (stream.status != DmtxStatusComplete || StreamInputHasNext(&stream)) return DmtxUndefined; return stream.sizeIdx; @@ -133,46 +148,56 @@ static void EncodeNextChunk(DmtxEncodeStream *stream, int scheme, int option, int sizeIdxRequest) { /* Special case: Prevent X12 from entering state with no way to unlatch */ - if(stream->currentScheme != DmtxSchemeX12 && scheme == DmtxSchemeX12) + if (stream->currentScheme != DmtxSchemeX12 && scheme == DmtxSchemeX12) { - if(PartialX12ChunkRemains(stream)) + if (PartialX12ChunkRemains(stream)) scheme = DmtxSchemeAscii; } /* Change to target scheme if necessary */ - if(stream->currentScheme != scheme) + if (stream->currentScheme != scheme) { - EncodeChangeScheme(stream, scheme, DmtxUnlatchExplicit); CHKERR; + EncodeChangeScheme(stream, scheme, DmtxUnlatchExplicit); + CHKERR; CHKSCHEME(scheme); } /* Special case: Edifact may be done before writing first word */ - if(scheme == DmtxSchemeEdifact) - CompleteIfDoneEdifact(stream, sizeIdxRequest); CHKERR; + if (scheme == DmtxSchemeEdifact) + CompleteIfDoneEdifact(stream, sizeIdxRequest); + CHKERR; - switch(stream->currentScheme) + switch (stream->currentScheme) { - case DmtxSchemeAscii: - EncodeNextChunkAscii(stream, option); CHKERR; - CompleteIfDoneAscii(stream, sizeIdxRequest); CHKERR; - break; - case DmtxSchemeC40: - case DmtxSchemeText: - case DmtxSchemeX12: - EncodeNextChunkCTX(stream, sizeIdxRequest); CHKERR; - CompleteIfDoneCTX(stream, sizeIdxRequest); CHKERR; - break; - case DmtxSchemeEdifact: - EncodeNextChunkEdifact(stream); CHKERR; - CompleteIfDoneEdifact(stream, sizeIdxRequest); CHKERR; - break; - case DmtxSchemeBase256: - EncodeNextChunkBase256(stream); CHKERR; - CompleteIfDoneBase256(stream, sizeIdxRequest); CHKERR; - break; - default: - StreamMarkFatal(stream, DmtxErrorUnknown); - break; + case DmtxSchemeAscii: + EncodeNextChunkAscii(stream, option); + CHKERR; + CompleteIfDoneAscii(stream, sizeIdxRequest); + CHKERR; + break; + case DmtxSchemeC40: + case DmtxSchemeText: + case DmtxSchemeX12: + EncodeNextChunkCTX(stream, sizeIdxRequest); + CHKERR; + CompleteIfDoneCTX(stream, sizeIdxRequest); + CHKERR; + break; + case DmtxSchemeEdifact: + EncodeNextChunkEdifact(stream); + CHKERR; + CompleteIfDoneEdifact(stream, sizeIdxRequest); + CHKERR; + break; + case DmtxSchemeBase256: + EncodeNextChunkBase256(stream); + CHKERR; + CompleteIfDoneBase256(stream, sizeIdxRequest); + CHKERR; + break; + default: + StreamMarkFatal(stream, DmtxErrorUnknown); + break; } } @@ -184,56 +209,63 @@ static void EncodeChangeScheme(DmtxEncodeStream *stream, DmtxScheme targetScheme, int unlatchType) { /* Nothing to do */ - if(stream->currentScheme == targetScheme) + if (stream->currentScheme == targetScheme) return; /* Every latch must go through ASCII */ - switch(stream->currentScheme) + switch (stream->currentScheme) { - case DmtxSchemeC40: - case DmtxSchemeText: - case DmtxSchemeX12: - if(unlatchType == DmtxUnlatchExplicit) - { - AppendUnlatchCTX(stream); CHKERR; - } - break; - case DmtxSchemeEdifact: - if(unlatchType == DmtxUnlatchExplicit) - { - AppendValueEdifact(stream, DmtxValueEdifactUnlatch); CHKERR; - } - break; - default: - /* Nothing to do for ASCII or Base 256 */ - assert(stream->currentScheme == DmtxSchemeAscii || - stream->currentScheme == DmtxSchemeBase256); - break; + case DmtxSchemeC40: + case DmtxSchemeText: + case DmtxSchemeX12: + if (unlatchType == DmtxUnlatchExplicit) + { + AppendUnlatchCTX(stream); + CHKERR; + } + break; + case DmtxSchemeEdifact: + if (unlatchType == DmtxUnlatchExplicit) + { + AppendValueEdifact(stream, DmtxValueEdifactUnlatch); + CHKERR; + } + break; + default: + /* Nothing to do for ASCII or Base 256 */ + assert(stream->currentScheme == DmtxSchemeAscii || + stream->currentScheme == DmtxSchemeBase256); + break; } stream->currentScheme = DmtxSchemeAscii; /* Anything other than ASCII (the default) requires a latch */ - switch(targetScheme) + switch (targetScheme) { - case DmtxSchemeC40: - AppendValueAscii(stream, DmtxValueC40Latch); CHKERR; - break; - case DmtxSchemeText: - AppendValueAscii(stream, DmtxValueTextLatch); CHKERR; - break; - case DmtxSchemeX12: - AppendValueAscii(stream, DmtxValueX12Latch); CHKERR; - break; - case DmtxSchemeEdifact: - AppendValueAscii(stream, DmtxValueEdifactLatch); CHKERR; - break; - case DmtxSchemeBase256: - AppendValueAscii(stream, DmtxValueBase256Latch); CHKERR; - break; - default: - /* Nothing to do for ASCII */ + case DmtxSchemeC40: + AppendValueAscii(stream, DmtxValueC40Latch); + CHKERR; + break; + case DmtxSchemeText: + AppendValueAscii(stream, DmtxValueTextLatch); + CHKERR; + break; + case DmtxSchemeX12: + AppendValueAscii(stream, DmtxValueX12Latch); + CHKERR; + break; + case DmtxSchemeEdifact: + AppendValueAscii(stream, DmtxValueEdifactLatch); + CHKERR; + break; + case DmtxSchemeBase256: + AppendValueAscii(stream, DmtxValueBase256Latch); + CHKERR; + break; + default: + /* Nothing to do for ASCII */ CHKSCHEME(DmtxSchemeAscii); - break; + break; } stream->currentScheme = targetScheme; @@ -242,9 +274,10 @@ EncodeChangeScheme(DmtxEncodeStream *stream, DmtxScheme targetScheme, int unlatc stream->outputChainValueCount = 0; /* Insert header byte if just latched to Base256 */ - if(targetScheme == DmtxSchemeBase256) + if (targetScheme == DmtxSchemeBase256) { - UpdateBase256ChainHeader(stream, DmtxUndefined); CHKERR; + UpdateBase256ChainHeader(stream, DmtxUndefined); + CHKERR; } } @@ -258,7 +291,7 @@ GetRemainingSymbolCapacity(int outputLength, int sizeIdx) int capacity; int remaining; - if(sizeIdx == DmtxUndefined) + if (sizeIdx == DmtxUndefined) { remaining = DmtxUndefined; } diff --git a/dmtxencodestream.c b/dmtxencodestream.c index fae95839..9d1bc1bc 100644 --- a/dmtxencodestream.c +++ b/dmtxencodestream.c @@ -21,20 +21,20 @@ static DmtxEncodeStream StreamInit(DmtxByteList *input, DmtxByteList *output) { - DmtxEncodeStream stream; + DmtxEncodeStream stream; - stream.input = input; - stream.output = output; + stream.input = input; + stream.output = output; - stream.currentScheme = DmtxSchemeAscii; - stream.inputNext = 0; - stream.outputChainValueCount = 0; - stream.outputChainWordCount = 0; - stream.reason = NULL; - stream.sizeIdx = DmtxUndefined; - stream.status = DmtxStatusEncoding; + stream.currentScheme = DmtxSchemeAscii; + stream.inputNext = 0; + stream.outputChainValueCount = 0; + stream.outputChainWordCount = 0; + stream.reason = NULL; + stream.sizeIdx = DmtxUndefined; + stream.status = DmtxStatusEncoding; - return stream; + return stream; } /** @@ -44,19 +44,19 @@ StreamInit(DmtxByteList *input, DmtxByteList *output) static void StreamCopy(DmtxEncodeStream *dst, DmtxEncodeStream *src) { - DmtxPassFail passFail; - - dst->currentScheme = src->currentScheme; - dst->inputNext = src->inputNext; - dst->outputChainValueCount = src->outputChainValueCount; - dst->outputChainWordCount = src->outputChainWordCount; - dst->reason = src->reason; - dst->sizeIdx = src->sizeIdx; - dst->status = src->status; - dst->input = src->input; - dst->fnc1 = src->fnc1; - - dmtxByteListCopy(dst->output, src->output, &passFail); + DmtxPassFail passFail; + + dst->currentScheme = src->currentScheme; + dst->inputNext = src->inputNext; + dst->outputChainValueCount = src->outputChainValueCount; + dst->outputChainWordCount = src->outputChainWordCount; + dst->reason = src->reason; + dst->sizeIdx = src->sizeIdx; + dst->status = src->status; + dst->input = src->input; + dst->fnc1 = src->fnc1; + + dmtxByteListCopy(dst->output, src->output, &passFail); } /** @@ -66,12 +66,12 @@ StreamCopy(DmtxEncodeStream *dst, DmtxEncodeStream *src) static void StreamMarkComplete(DmtxEncodeStream *stream, int sizeIdx) { - if(stream->status == DmtxStatusEncoding) - { - stream->sizeIdx = sizeIdx; - stream->status = DmtxStatusComplete; - assert(stream->reason == NULL); - } + if (stream->status == DmtxStatusEncoding) + { + stream->sizeIdx = sizeIdx; + stream->status = DmtxStatusComplete; + assert(stream->reason == NULL); + } } /** @@ -81,8 +81,8 @@ StreamMarkComplete(DmtxEncodeStream *stream, int sizeIdx) static void StreamMarkInvalid(DmtxEncodeStream *stream, int reasonIdx) { - stream->status = DmtxStatusInvalid; - stream->reason = dmtxErrorMessage[reasonIdx]; + stream->status = DmtxStatusInvalid; + stream->reason = dmtxErrorMessage[reasonIdx]; } /** @@ -92,8 +92,8 @@ StreamMarkInvalid(DmtxEncodeStream *stream, int reasonIdx) static void StreamMarkFatal(DmtxEncodeStream *stream, int reasonIdx) { - stream->status = DmtxStatusFatal; - stream->reason = dmtxErrorMessage[reasonIdx]; + stream->status = DmtxStatusFatal; + stream->reason = dmtxErrorMessage[reasonIdx]; } /** @@ -103,14 +103,14 @@ StreamMarkFatal(DmtxEncodeStream *stream, int reasonIdx) static void StreamOutputChainAppend(DmtxEncodeStream *stream, DmtxByte value) { - DmtxPassFail passFail; + DmtxPassFail passFail; - dmtxByteListPush(stream->output, value, &passFail); + dmtxByteListPush(stream->output, value, &passFail); - if(passFail == DmtxPass) - stream->outputChainWordCount++; - else - StreamMarkFatal(stream, DmtxErrorOutOfBounds); + if (passFail == DmtxPass) + stream->outputChainWordCount++; + else + StreamMarkFatal(stream, DmtxErrorOutOfBounds); } /** @@ -120,21 +120,21 @@ StreamOutputChainAppend(DmtxEncodeStream *stream, DmtxByte value) static DmtxByte StreamOutputChainRemoveLast(DmtxEncodeStream *stream) { - DmtxByte value; - DmtxPassFail passFail; - - if(stream->outputChainWordCount > 0) - { - value = dmtxByteListPop(stream->output, &passFail); - stream->outputChainWordCount--; - } - else - { - value = 0; - StreamMarkFatal(stream, DmtxErrorEmptyList); - } - - return value; + DmtxByte value; + DmtxPassFail passFail; + + if (stream->outputChainWordCount > 0) + { + value = dmtxByteListPop(stream->output, &passFail); + stream->outputChainWordCount--; + } + else + { + value = 0; + StreamMarkFatal(stream, DmtxErrorEmptyList); + } + + return value; } /** @@ -144,10 +144,10 @@ StreamOutputChainRemoveLast(DmtxEncodeStream *stream) static void StreamOutputSet(DmtxEncodeStream *stream, int index, DmtxByte value) { - if(index < 0 || index >= stream->output->length) - StreamMarkFatal(stream, DmtxErrorOutOfBounds); - else - stream->output->b[index] = value; + if (index < 0 || index >= stream->output->length) + StreamMarkFatal(stream, DmtxErrorOutOfBounds); + else + stream->output->b[index] = value; } /** @@ -157,7 +157,7 @@ StreamOutputSet(DmtxEncodeStream *stream, int index, DmtxByte value) static DmtxBoolean StreamInputHasNext(DmtxEncodeStream *stream) { - return (stream->inputNext < stream->input->length) ? DmtxTrue : DmtxFalse; + return (stream->inputNext < stream->input->length) ? DmtxTrue : DmtxFalse; } /** @@ -167,14 +167,14 @@ StreamInputHasNext(DmtxEncodeStream *stream) static DmtxByte StreamInputPeekNext(DmtxEncodeStream *stream) { - DmtxByte value = 0; + DmtxByte value = 0; - if(StreamInputHasNext(stream)) - value = stream->input->b[stream->inputNext]; - else - StreamMarkFatal(stream, DmtxErrorOutOfBounds); + if (StreamInputHasNext(stream)) + value = stream->input->b[stream->inputNext]; + else + StreamMarkFatal(stream, DmtxErrorOutOfBounds); - return value; + return value; } /** @@ -186,14 +186,14 @@ StreamInputPeekNext(DmtxEncodeStream *stream) static DmtxByte StreamInputAdvanceNext(DmtxEncodeStream *stream) { - DmtxByte value; + DmtxByte value; - value = StreamInputPeekNext(stream); + value = StreamInputPeekNext(stream); - if(stream->status == DmtxStatusEncoding) - stream->inputNext++; /* XXX is this what we really mean here? */ + if (stream->status == DmtxStatusEncoding) + stream->inputNext++; /* XXX is this what we really mean here? */ - return value; + return value; } /** @@ -205,8 +205,8 @@ StreamInputAdvanceNext(DmtxEncodeStream *stream) static void StreamInputAdvancePrev(DmtxEncodeStream *stream) { - if(stream->inputNext > 0) - stream->inputNext--; - else - StreamMarkFatal(stream, DmtxErrorOutOfBounds); + if (stream->inputNext > 0) + stream->inputNext--; + else + StreamMarkFatal(stream, DmtxErrorOutOfBounds); } diff --git a/dmtximage.c b/dmtximage.c index bb1b9cf2..a208b95f 100644 --- a/dmtximage.c +++ b/dmtximage.c @@ -62,84 +62,85 @@ extern DmtxImage * dmtxImageCreate(unsigned char *pxl, int width, int height, int pack) { -// DmtxPassFail err; - DmtxImage *img; - - if(pxl == NULL || width < 1 || height < 1) - return NULL; - - img = (DmtxImage *)calloc(1, sizeof(DmtxImage)); - if(img == NULL) - return NULL; - - img->pxl = pxl; - img->width = width; - img->height = height; - img->pixelPacking = pack; - img->bitsPerPixel = GetBitsPerPixel(pack); - img->bytesPerPixel = img->bitsPerPixel/8; - img->rowPadBytes = 0; - img->rowSizeBytes = img->width * img->bytesPerPixel + img->rowPadBytes; - img->imageFlip = DmtxFlipNone; - - /* Leave channelStart[] and bitsPerChannel[] with zeros from calloc */ - img->channelCount = 0; - - switch(pack) { - case DmtxPackCustom: - break; - case DmtxPack1bppK: - dmtxImageSetChannel(img, 0, 1); - return NULL; /* unsupported packing order */ -/* break; */ - case DmtxPack8bppK: - dmtxImageSetChannel(img, 0, 8); - break; - case DmtxPack16bppRGB: - case DmtxPack16bppBGR: - case DmtxPack16bppYCbCr: - dmtxImageSetChannel(img, 0, 5); - dmtxImageSetChannel(img, 5, 5); - dmtxImageSetChannel(img, 10, 5); - break; - case DmtxPack24bppRGB: - case DmtxPack24bppBGR: - case DmtxPack24bppYCbCr: - case DmtxPack32bppRGBX: - case DmtxPack32bppBGRX: - dmtxImageSetChannel(img, 0, 8); - dmtxImageSetChannel(img, 8, 8); - dmtxImageSetChannel(img, 16, 8); - break; - case DmtxPack16bppRGBX: - case DmtxPack16bppBGRX: - dmtxImageSetChannel(img, 0, 5); - dmtxImageSetChannel(img, 5, 5); - dmtxImageSetChannel(img, 10, 5); - break; - case DmtxPack16bppXRGB: - case DmtxPack16bppXBGR: - dmtxImageSetChannel(img, 1, 5); - dmtxImageSetChannel(img, 6, 5); - dmtxImageSetChannel(img, 11, 5); - break; - case DmtxPack32bppXRGB: - case DmtxPack32bppXBGR: - dmtxImageSetChannel(img, 8, 8); - dmtxImageSetChannel(img, 16, 8); - dmtxImageSetChannel(img, 24, 8); - break; - case DmtxPack32bppCMYK: - dmtxImageSetChannel(img, 0, 8); - dmtxImageSetChannel(img, 8, 8); - dmtxImageSetChannel(img, 16, 8); - dmtxImageSetChannel(img, 24, 8); - break; - default: - return NULL; - } - - return img; + // DmtxPassFail err; + DmtxImage *img; + + if (pxl == NULL || width < 1 || height < 1) + return NULL; + + img = (DmtxImage *)calloc(1, sizeof(DmtxImage)); + if (img == NULL) + return NULL; + + img->pxl = pxl; + img->width = width; + img->height = height; + img->pixelPacking = pack; + img->bitsPerPixel = GetBitsPerPixel(pack); + img->bytesPerPixel = img->bitsPerPixel / 8; + img->rowPadBytes = 0; + img->rowSizeBytes = img->width * img->bytesPerPixel + img->rowPadBytes; + img->imageFlip = DmtxFlipNone; + + /* Leave channelStart[] and bitsPerChannel[] with zeros from calloc */ + img->channelCount = 0; + + switch (pack) + { + case DmtxPackCustom: + break; + case DmtxPack1bppK: + dmtxImageSetChannel(img, 0, 1); + return NULL; /* unsupported packing order */ + /* break; */ + case DmtxPack8bppK: + dmtxImageSetChannel(img, 0, 8); + break; + case DmtxPack16bppRGB: + case DmtxPack16bppBGR: + case DmtxPack16bppYCbCr: + dmtxImageSetChannel(img, 0, 5); + dmtxImageSetChannel(img, 5, 5); + dmtxImageSetChannel(img, 10, 5); + break; + case DmtxPack24bppRGB: + case DmtxPack24bppBGR: + case DmtxPack24bppYCbCr: + case DmtxPack32bppRGBX: + case DmtxPack32bppBGRX: + dmtxImageSetChannel(img, 0, 8); + dmtxImageSetChannel(img, 8, 8); + dmtxImageSetChannel(img, 16, 8); + break; + case DmtxPack16bppRGBX: + case DmtxPack16bppBGRX: + dmtxImageSetChannel(img, 0, 5); + dmtxImageSetChannel(img, 5, 5); + dmtxImageSetChannel(img, 10, 5); + break; + case DmtxPack16bppXRGB: + case DmtxPack16bppXBGR: + dmtxImageSetChannel(img, 1, 5); + dmtxImageSetChannel(img, 6, 5); + dmtxImageSetChannel(img, 11, 5); + break; + case DmtxPack32bppXRGB: + case DmtxPack32bppXBGR: + dmtxImageSetChannel(img, 8, 8); + dmtxImageSetChannel(img, 16, 8); + dmtxImageSetChannel(img, 24, 8); + break; + case DmtxPack32bppCMYK: + dmtxImageSetChannel(img, 0, 8); + dmtxImageSetChannel(img, 8, 8); + dmtxImageSetChannel(img, 16, 8); + dmtxImageSetChannel(img, 24, 8); + break; + default: + return NULL; + } + + return img; } /** @@ -150,14 +151,14 @@ dmtxImageCreate(unsigned char *pxl, int width, int height, int pack) extern DmtxPassFail dmtxImageDestroy(DmtxImage **img) { - if(img == NULL || *img == NULL) - return DmtxFail; + if (img == NULL || *img == NULL) + return DmtxFail; - free(*img); + free(*img); - *img = NULL; + *img = NULL; - return DmtxPass; + return DmtxPass; } /** @@ -167,18 +168,18 @@ dmtxImageDestroy(DmtxImage **img) extern DmtxPassFail dmtxImageSetChannel(DmtxImage *img, int channelStart, int bitsPerChannel) { - if(img->channelCount >= 4) /* IMAGE_MAX_CHANNEL */ - return DmtxFail; + if (img->channelCount >= 4) /* IMAGE_MAX_CHANNEL */ + return DmtxFail; - /* New channel extends beyond pixel data */ -/* if(channelStart + bitsPerChannel > img->bitsPerPixel) - return DmtxFail; */ + /* New channel extends beyond pixel data */ + /* if(channelStart + bitsPerChannel > img->bitsPerPixel) + return DmtxFail; */ - img->bitsPerChannel[img->channelCount] = bitsPerChannel; - img->channelStart[img->channelCount] = channelStart; - (img->channelCount)++; + img->bitsPerChannel[img->channelCount] = bitsPerChannel; + img->channelStart[img->channelCount] = channelStart; + (img->channelCount)++; - return DmtxPass; + return DmtxPass; } /** @@ -189,22 +190,23 @@ dmtxImageSetChannel(DmtxImage *img, int channelStart, int bitsPerChannel) extern DmtxPassFail dmtxImageSetProp(DmtxImage *img, int prop, int value) { - if(img == NULL) - return DmtxFail; - - switch(prop) { - case DmtxPropRowPadBytes: - img->rowPadBytes = value; - img->rowSizeBytes = img->width * (img->bitsPerPixel/8) + img->rowPadBytes; - break; - case DmtxPropImageFlip: - img->imageFlip = value; - break; - default: - break; - } - - return DmtxPass; + if (img == NULL) + return DmtxFail; + + switch (prop) + { + case DmtxPropRowPadBytes: + img->rowPadBytes = value; + img->rowSizeBytes = img->width * (img->bitsPerPixel / 8) + img->rowPadBytes; + break; + case DmtxPropImageFlip: + img->imageFlip = value; + break; + default: + break; + } + + return DmtxPass; } /** @@ -215,33 +217,34 @@ dmtxImageSetProp(DmtxImage *img, int prop, int value) extern int dmtxImageGetProp(DmtxImage *img, int prop) { - if(img == NULL) - return DmtxUndefined; - - switch(prop) { - case DmtxPropWidth: - return img->width; - case DmtxPropHeight: - return img->height; - case DmtxPropPixelPacking: - return img->pixelPacking; - case DmtxPropBitsPerPixel: - return img->bitsPerPixel; - case DmtxPropBytesPerPixel: - return img->bytesPerPixel; - case DmtxPropRowPadBytes: - return img->rowPadBytes; - case DmtxPropRowSizeBytes: - return img->rowSizeBytes; - case DmtxPropImageFlip: - return img->imageFlip; - case DmtxPropChannelCount: - return img->channelCount; - default: - break; - } - - return DmtxUndefined; + if (img == NULL) + return DmtxUndefined; + + switch (prop) + { + case DmtxPropWidth: + return img->width; + case DmtxPropHeight: + return img->height; + case DmtxPropPixelPacking: + return img->pixelPacking; + case DmtxPropBitsPerPixel: + return img->bitsPerPixel; + case DmtxPropBytesPerPixel: + return img->bytesPerPixel; + case DmtxPropRowPadBytes: + return img->rowPadBytes; + case DmtxPropRowSizeBytes: + return img->rowSizeBytes; + case DmtxPropImageFlip: + return img->imageFlip; + case DmtxPropChannelCount: + return img->channelCount; + default: + break; + } + + return DmtxUndefined; } /** @@ -254,16 +257,16 @@ dmtxImageGetProp(DmtxImage *img, int prop) extern int dmtxImageGetByteOffset(DmtxImage *img, int x, int y) { - assert(img != NULL); - assert(!(img->imageFlip & DmtxFlipX)); /* DmtxFlipX is not an option */ + assert(img != NULL); + assert(!(img->imageFlip & DmtxFlipX)); /* DmtxFlipX is not an option */ - if(dmtxImageContainsInt(img, 0, x, y) == DmtxFalse) - return DmtxUndefined; + if (dmtxImageContainsInt(img, 0, x, y) == DmtxFalse) + return DmtxUndefined; - if(img->imageFlip & DmtxFlipY) - return (y * img->rowSizeBytes + x * img->bytesPerPixel); + if (img->imageFlip & DmtxFlipY) + return (y * img->rowSizeBytes + x * img->bytesPerPixel); - return ((img->height - y - 1) * img->rowSizeBytes + x * img->bytesPerPixel); + return ((img->height - y - 1) * img->rowSizeBytes + x * img->bytesPerPixel); } /** @@ -273,42 +276,43 @@ dmtxImageGetByteOffset(DmtxImage *img, int x, int y) extern DmtxPassFail dmtxImageGetPixelValue(DmtxImage *img, int x, int y, int channel, int *value) { - int offset; -/* unsigned char *pixelPtr; - int pixelValue; - int mask; - int bitShift; */ - - assert(img != NULL); - assert(channel < img->channelCount); - - offset = dmtxImageGetByteOffset(img, x, y); - if(offset == DmtxUndefined) - return DmtxFail; - - switch(img->bitsPerChannel[channel]) { - case 1: -/* assert(img->bitsPerPixel == 1); - mask = 0x01 << (7 - offset%8); - *value = (img->pxl[offset/8] & mask) ? 255 : 0; */ - break; - case 5: - /* XXX might be expensive if we want to scale perfect 0-255 range */ -/* assert(img->bitsPerPixel == 16); - pixelPtr = img->pxl + (offset * (img->bitsPerPixel/8)); - pixelValue = (*pixelPtr << 8) | (*(pixelPtr+1)); - bitShift = img->bitsPerPixel - 5 - img->channelStart[channel]; - mask = 0x1f << bitShift; - *value = (((pixelValue & mask) >> bitShift) << 3); */ - break; - case 8: - assert(img->channelStart[channel] % 8 == 0); - assert(img->bitsPerPixel % 8 == 0); - *value = img->pxl[offset + channel]; - break; - } - - return DmtxPass; + int offset; + /* unsigned char *pixelPtr; + int pixelValue; + int mask; + int bitShift; */ + + assert(img != NULL); + assert(channel < img->channelCount); + + offset = dmtxImageGetByteOffset(img, x, y); + if (offset == DmtxUndefined) + return DmtxFail; + + switch (img->bitsPerChannel[channel]) + { + case 1: + /* assert(img->bitsPerPixel == 1); + mask = 0x01 << (7 - offset%8); + *value = (img->pxl[offset/8] & mask) ? 255 : 0; */ + break; + case 5: + /* XXX might be expensive if we want to scale perfect 0-255 range */ + /* assert(img->bitsPerPixel == 16); + pixelPtr = img->pxl + (offset * (img->bitsPerPixel/8)); + pixelValue = (*pixelPtr << 8) | (*(pixelPtr+1)); + bitShift = img->bitsPerPixel - 5 - img->channelStart[channel]; + mask = 0x1f << bitShift; + *value = (((pixelValue & mask) >> bitShift) << 3); */ + break; + case 8: + assert(img->channelStart[channel] % 8 == 0); + assert(img->bitsPerPixel % 8 == 0); + *value = img->pxl[offset + channel]; + break; + } + + return DmtxPass; } /** @@ -318,42 +322,43 @@ dmtxImageGetPixelValue(DmtxImage *img, int x, int y, int channel, int *value) extern DmtxPassFail dmtxImageSetPixelValue(DmtxImage *img, int x, int y, int channel, int value) { - int offset; -/* unsigned char *pixelPtr; */ -/* int pixelValue; */ -/* int mask; */ -/* int bitShift; */ - - assert(img != NULL); - assert(channel < img->channelCount); - - offset = dmtxImageGetByteOffset(img, x, y); - if(offset == DmtxUndefined) - return DmtxFail; - - switch(img->bitsPerChannel[channel]) { - case 1: -/* assert(img->bitsPerPixel == 1); - mask = 0x01 << (7 - offset%8); - *value = (img->pxl[offset/8] & mask) ? 255 : 0; */ - break; - case 5: - /* XXX might be expensive if we want to scale perfect 0-255 range */ -/* assert(img->bitsPerPixel == 16); - pixelPtr = img->pxl + (offset * (img->bitsPerPixel/8)); - pixelValue = (*pixelPtr << 8) | (*(pixelPtr+1)); - bitShift = img->bitsPerPixel - 5 - img->channelStart[channel]; - mask = 0x1f << bitShift; - *value = (((pixelValue & mask) >> bitShift) << 3); */ - break; - case 8: - assert(img->channelStart[channel] % 8 == 0); - assert(img->bitsPerPixel % 8 == 0); - img->pxl[offset + channel] = value; - break; - } - - return DmtxPass; + int offset; + /* unsigned char *pixelPtr; */ + /* int pixelValue; */ + /* int mask; */ + /* int bitShift; */ + + assert(img != NULL); + assert(channel < img->channelCount); + + offset = dmtxImageGetByteOffset(img, x, y); + if (offset == DmtxUndefined) + return DmtxFail; + + switch (img->bitsPerChannel[channel]) + { + case 1: + /* assert(img->bitsPerPixel == 1); + mask = 0x01 << (7 - offset%8); + *value = (img->pxl[offset/8] & mask) ? 255 : 0; */ + break; + case 5: + /* XXX might be expensive if we want to scale perfect 0-255 range */ + /* assert(img->bitsPerPixel == 16); + pixelPtr = img->pxl + (offset * (img->bitsPerPixel/8)); + pixelValue = (*pixelPtr << 8) | (*(pixelPtr+1)); + bitShift = img->bitsPerPixel - 5 - img->channelStart[channel]; + mask = 0x1f << bitShift; + *value = (((pixelValue & mask) >> bitShift) << 3); */ + break; + case 8: + assert(img->channelStart[channel] % 8 == 0); + assert(img->bitsPerPixel % 8 == 0); + img->pxl[offset + channel] = value; + break; + } + + return DmtxPass; } /** @@ -367,13 +372,13 @@ dmtxImageSetPixelValue(DmtxImage *img, int x, int y, int channel, int value) extern DmtxBoolean dmtxImageContainsInt(DmtxImage *img, int margin, int x, int y) { - assert(img != NULL); + assert(img != NULL); - if(x - margin >= 0 && x + margin < img->width && - y - margin >= 0 && y + margin < img->height) - return DmtxTrue; + if (x - margin >= 0 && x + margin < img->width && + y - margin >= 0 && y + margin < img->height) + return DmtxTrue; - return DmtxFalse; + return DmtxFalse; } /** @@ -386,12 +391,12 @@ dmtxImageContainsInt(DmtxImage *img, int margin, int x, int y) extern DmtxBoolean dmtxImageContainsFloat(DmtxImage *img, double x, double y) { - assert(img != NULL); + assert(img != NULL); - if(x >= 0.0 && x < (double)img->width && y >= 0.0 && y < (double)img->height) - return DmtxTrue; + if (x >= 0.0 && x < (double)img->width && y >= 0.0 && y < (double)img->height) + return DmtxTrue; - return DmtxFalse; + return DmtxFalse; } /** @@ -401,32 +406,33 @@ dmtxImageContainsFloat(DmtxImage *img, double x, double y) static int GetBitsPerPixel(int pack) { - switch(pack) { - case DmtxPack1bppK: - return 1; - case DmtxPack8bppK: - return 8; - case DmtxPack16bppRGB: - case DmtxPack16bppRGBX: - case DmtxPack16bppXRGB: - case DmtxPack16bppBGR: - case DmtxPack16bppBGRX: - case DmtxPack16bppXBGR: - case DmtxPack16bppYCbCr: - return 16; - case DmtxPack24bppRGB: - case DmtxPack24bppBGR: - case DmtxPack24bppYCbCr: - return 24; - case DmtxPack32bppRGBX: - case DmtxPack32bppXRGB: - case DmtxPack32bppBGRX: - case DmtxPack32bppXBGR: - case DmtxPack32bppCMYK: - return 32; - default: - break; - } - - return DmtxUndefined; + switch (pack) + { + case DmtxPack1bppK: + return 1; + case DmtxPack8bppK: + return 8; + case DmtxPack16bppRGB: + case DmtxPack16bppRGBX: + case DmtxPack16bppXRGB: + case DmtxPack16bppBGR: + case DmtxPack16bppBGRX: + case DmtxPack16bppXBGR: + case DmtxPack16bppYCbCr: + return 16; + case DmtxPack24bppRGB: + case DmtxPack24bppBGR: + case DmtxPack24bppYCbCr: + return 24; + case DmtxPack32bppRGBX: + case DmtxPack32bppXRGB: + case DmtxPack32bppBGRX: + case DmtxPack32bppXBGR: + case DmtxPack32bppCMYK: + return 32; + default: + break; + } + + return DmtxUndefined; } diff --git a/dmtxmatrix3.c b/dmtxmatrix3.c index 341474de..d81cdfd7 100644 --- a/dmtxmatrix3.c +++ b/dmtxmatrix3.c @@ -23,7 +23,7 @@ extern void dmtxMatrix3Copy(DmtxMatrix3 m0, DmtxMatrix3 m1) { - memcpy(m0, m1, sizeof(DmtxMatrix3)); + memcpy(m0, m1, sizeof(DmtxMatrix3)); } /** @@ -48,10 +48,10 @@ dmtxMatrix3Copy(DmtxMatrix3 m0, DmtxMatrix3 m1) extern void dmtxMatrix3Identity(DmtxMatrix3 m) { - static DmtxMatrix3 tmp = { {1, 0, 0}, + static DmtxMatrix3 tmp = {{1, 0, 0}, {0, 1, 0}, - {0, 0, 1} }; - dmtxMatrix3Copy(m, tmp); + {0, 0, 1}}; + dmtxMatrix3Copy(m, tmp); } /** @@ -77,9 +77,9 @@ dmtxMatrix3Identity(DmtxMatrix3 m) */ void dmtxMatrix3Translate(DmtxMatrix3 m, double tx, double ty) { - dmtxMatrix3Identity(m); - m[2][0] = tx; - m[2][1] = ty; + dmtxMatrix3Identity(m); + m[2][0] = tx; + m[2][1] = ty; } /** @@ -104,16 +104,16 @@ void dmtxMatrix3Translate(DmtxMatrix3 m, double tx, double ty) extern void dmtxMatrix3Rotate(DmtxMatrix3 m, double angle) { - double sinAngle, cosAngle; + double sinAngle, cosAngle; - sinAngle = sin(angle); - cosAngle = cos(angle); + sinAngle = sin(angle); + cosAngle = cos(angle); - dmtxMatrix3Identity(m); - m[0][0] = cosAngle; - m[0][1] = sinAngle; - m[1][0] = -sinAngle; - m[1][1] = cosAngle; + dmtxMatrix3Identity(m); + m[0][0] = cosAngle; + m[0][1] = sinAngle; + m[1][0] = -sinAngle; + m[1][1] = cosAngle; } /** @@ -140,9 +140,9 @@ dmtxMatrix3Rotate(DmtxMatrix3 m, double angle) extern void dmtxMatrix3Scale(DmtxMatrix3 m, double sx, double sy) { - dmtxMatrix3Identity(m); - m[0][0] = sx; - m[1][1] = sy; + dmtxMatrix3Identity(m); + m[0][0] = sx; + m[1][1] = sy; } /** @@ -159,9 +159,9 @@ dmtxMatrix3Scale(DmtxMatrix3 m, double sx, double sy) extern void dmtxMatrix3Shear(DmtxMatrix3 m, double shx, double shy) { - dmtxMatrix3Identity(m); - m[1][0] = shx; - m[0][1] = shy; + dmtxMatrix3Identity(m); + m[1][0] = shx; + m[0][1] = shy; } /** @@ -193,12 +193,12 @@ dmtxMatrix3Shear(DmtxMatrix3 m, double shx, double shy) extern void dmtxMatrix3LineSkewTop(DmtxMatrix3 m, double b0, double b1, double sz) { - assert(b0 >= DmtxAlmostZero); + assert(b0 >= DmtxAlmostZero); - dmtxMatrix3Identity(m); - m[0][0] = b1/b0; - m[1][1] = sz/b0; - m[0][2] = (b1 - b0)/(sz*b0); + dmtxMatrix3Identity(m); + m[0][0] = b1 / b0; + m[1][1] = sz / b0; + m[0][2] = (b1 - b0) / (sz * b0); } /** @@ -212,12 +212,12 @@ dmtxMatrix3LineSkewTop(DmtxMatrix3 m, double b0, double b1, double sz) extern void dmtxMatrix3LineSkewTopInv(DmtxMatrix3 m, double b0, double b1, double sz) { - assert(b1 >= DmtxAlmostZero); + assert(b1 >= DmtxAlmostZero); - dmtxMatrix3Identity(m); - m[0][0] = b0/b1; - m[1][1] = b0/sz; - m[0][2] = (b0 - b1)/(sz*b1); + dmtxMatrix3Identity(m); + m[0][0] = b0 / b1; + m[1][1] = b0 / sz; + m[0][2] = (b0 - b1) / (sz * b1); } /** @@ -231,12 +231,12 @@ dmtxMatrix3LineSkewTopInv(DmtxMatrix3 m, double b0, double b1, double sz) extern void dmtxMatrix3LineSkewSide(DmtxMatrix3 m, double b0, double b1, double sz) { - assert(b0 >= DmtxAlmostZero); + assert(b0 >= DmtxAlmostZero); - dmtxMatrix3Identity(m); - m[0][0] = sz/b0; - m[1][1] = b1/b0; - m[1][2] = (b1 - b0)/(sz*b0); + dmtxMatrix3Identity(m); + m[0][0] = sz / b0; + m[1][1] = b1 / b0; + m[1][2] = (b1 - b0) / (sz * b0); } /** @@ -250,12 +250,12 @@ dmtxMatrix3LineSkewSide(DmtxMatrix3 m, double b0, double b1, double sz) extern void dmtxMatrix3LineSkewSideInv(DmtxMatrix3 m, double b0, double b1, double sz) { - assert(b1 >= DmtxAlmostZero); + assert(b1 >= DmtxAlmostZero); - dmtxMatrix3Identity(m); - m[0][0] = b0/sz; - m[1][1] = b0/b1; - m[1][2] = (b0 - b1)/(sz*b1); + dmtxMatrix3Identity(m); + m[0][0] = b0 / sz; + m[1][1] = b0 / b1; + m[1][2] = (b0 - b1) / (sz * b1); } /** @@ -268,18 +268,21 @@ dmtxMatrix3LineSkewSideInv(DmtxMatrix3 m, double b0, double b1, double sz) extern void dmtxMatrix3Multiply(DmtxMatrix3 mOut, DmtxMatrix3 m0, DmtxMatrix3 m1) { - int i, j, k; - double val; + int i, j, k; + double val; - for(i = 0; i < 3; i++) { - for(j = 0; j < 3; j++) { - val = 0.0; - for(k = 0; k < 3; k++) { - val += m0[i][k] * m1[k][j]; - } - mOut[i][j] = val; - } - } + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + val = 0.0; + for (k = 0; k < 3; k++) + { + val += m0[i][k] * m1[k][j]; + } + mOut[i][j] = val; + } + } } /** @@ -291,10 +294,10 @@ dmtxMatrix3Multiply(DmtxMatrix3 mOut, DmtxMatrix3 m0, DmtxMatrix3 m1) extern void dmtxMatrix3MultiplyBy(DmtxMatrix3 m0, DmtxMatrix3 m1) { - DmtxMatrix3 mTmp; + DmtxMatrix3 mTmp; - dmtxMatrix3Copy(mTmp, m0); - dmtxMatrix3Multiply(m0, mTmp, m1); + dmtxMatrix3Copy(mTmp, m0); + dmtxMatrix3Multiply(m0, mTmp, m1); } /** @@ -307,19 +310,20 @@ dmtxMatrix3MultiplyBy(DmtxMatrix3 m0, DmtxMatrix3 m1) extern int dmtxMatrix3VMultiply(DmtxVector2 *vOut, DmtxVector2 *vIn, DmtxMatrix3 m) { - double w; + double w; - w = vIn->X*m[0][2] + vIn->Y*m[1][2] + m[2][2]; - if(fabs(w) <= DmtxAlmostZero) { - vOut->X = FLT_MAX; - vOut->Y = FLT_MAX; - return DmtxFail; - } + w = vIn->X * m[0][2] + vIn->Y * m[1][2] + m[2][2]; + if (fabs(w) <= DmtxAlmostZero) + { + vOut->X = FLT_MAX; + vOut->Y = FLT_MAX; + return DmtxFail; + } - vOut->X = (vIn->X*m[0][0] + vIn->Y*m[1][0] + m[2][0])/w; - vOut->Y = (vIn->X*m[0][1] + vIn->Y*m[1][1] + m[2][1])/w; + vOut->X = (vIn->X * m[0][0] + vIn->Y * m[1][0] + m[2][0]) / w; + vOut->Y = (vIn->X * m[0][1] + vIn->Y * m[1][1] + m[2][1]) / w; - return DmtxPass; + return DmtxPass; } /** @@ -331,13 +335,13 @@ dmtxMatrix3VMultiply(DmtxVector2 *vOut, DmtxVector2 *vIn, DmtxMatrix3 m) extern int dmtxMatrix3VMultiplyBy(DmtxVector2 *v, DmtxMatrix3 m) { - int success; - DmtxVector2 vOut; + int success; + DmtxVector2 vOut; - success = dmtxMatrix3VMultiply(&vOut, v, m); - *v = vOut; + success = dmtxMatrix3VMultiply(&vOut, v, m); + *v = vOut; - return success; + return success; } /** @@ -348,8 +352,8 @@ dmtxMatrix3VMultiplyBy(DmtxVector2 *v, DmtxMatrix3 m) extern void dmtxMatrix3Print(DmtxMatrix3 m) { - fprintf(stdout, "%8.8f\t%8.8f\t%8.8f\n", m[0][0], m[0][1], m[0][2]); - fprintf(stdout, "%8.8f\t%8.8f\t%8.8f\n", m[1][0], m[1][1], m[1][2]); - fprintf(stdout, "%8.8f\t%8.8f\t%8.8f\n", m[2][0], m[2][1], m[2][2]); - fprintf(stdout, "\n"); + fprintf(stdout, "%8.8f\t%8.8f\t%8.8f\n", m[0][0], m[0][1], m[0][2]); + fprintf(stdout, "%8.8f\t%8.8f\t%8.8f\n", m[1][0], m[1][1], m[1][2]); + fprintf(stdout, "%8.8f\t%8.8f\t%8.8f\n", m[2][0], m[2][1], m[2][2]); + fprintf(stdout, "\n"); } diff --git a/dmtxmessage.c b/dmtxmessage.c index 217d8e7e..523a9127 100644 --- a/dmtxmessage.c +++ b/dmtxmessage.c @@ -23,53 +23,56 @@ extern DmtxMessage * dmtxMessageCreate(int sizeIdx, int symbolFormat) { - DmtxMessage *message; - int mappingRows, mappingCols; - - assert(symbolFormat == DmtxFormatMatrix || symbolFormat == DmtxFormatMosaic); - - mappingRows = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, sizeIdx); - mappingCols = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, sizeIdx); - - message = (DmtxMessage *)calloc(1, sizeof(DmtxMessage)); - if(message == NULL) - return NULL; - - message->arraySize = sizeof(unsigned char) * mappingRows * mappingCols; - - message->array = (unsigned char *)calloc(1, message->arraySize); - if(message->array == NULL) { - perror("Calloc failed"); - dmtxMessageDestroy(&message); - return NULL; - } - - message->codeSize = sizeof(unsigned char) * - dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx) + - dmtxGetSymbolAttribute(DmtxSymAttribSymbolErrorWords, sizeIdx); - - if(symbolFormat == DmtxFormatMosaic) - message->codeSize *= 3; - - message->code = (unsigned char *)calloc(message->codeSize, sizeof(unsigned char)); - if(message->code == NULL) { - perror("Calloc failed"); - dmtxMessageDestroy(&message); - return NULL; - } - - /* XXX not sure if this is the right place or even the right approach. - Trying to allocate memory for the decoded data stream and will - initially assume that decoded data will not be larger than 2x encoded data */ - message->outputSize = sizeof(unsigned char) * message->codeSize * 10; - message->output = (unsigned char *)calloc(message->outputSize, sizeof(unsigned char)); - if(message->output == NULL) { - perror("Calloc failed"); - dmtxMessageDestroy(&message); - return NULL; - } - - return message; + DmtxMessage *message; + int mappingRows, mappingCols; + + assert(symbolFormat == DmtxFormatMatrix || symbolFormat == DmtxFormatMosaic); + + mappingRows = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, sizeIdx); + mappingCols = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, sizeIdx); + + message = (DmtxMessage *)calloc(1, sizeof(DmtxMessage)); + if (message == NULL) + return NULL; + + message->arraySize = sizeof(unsigned char) * mappingRows * mappingCols; + + message->array = (unsigned char *)calloc(1, message->arraySize); + if (message->array == NULL) + { + perror("Calloc failed"); + dmtxMessageDestroy(&message); + return NULL; + } + + message->codeSize = sizeof(unsigned char) * + dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx) + + dmtxGetSymbolAttribute(DmtxSymAttribSymbolErrorWords, sizeIdx); + + if (symbolFormat == DmtxFormatMosaic) + message->codeSize *= 3; + + message->code = (unsigned char *)calloc(message->codeSize, sizeof(unsigned char)); + if (message->code == NULL) + { + perror("Calloc failed"); + dmtxMessageDestroy(&message); + return NULL; + } + + /* XXX not sure if this is the right place or even the right approach. + Trying to allocate memory for the decoded data stream and will + initially assume that decoded data will not be larger than 2x encoded data */ + message->outputSize = sizeof(unsigned char) * message->codeSize * 10; + message->output = (unsigned char *)calloc(message->outputSize, sizeof(unsigned char)); + if (message->output == NULL) + { + perror("Calloc failed"); + dmtxMessageDestroy(&message); + return NULL; + } + + return message; } /** @@ -80,21 +83,21 @@ dmtxMessageCreate(int sizeIdx, int symbolFormat) extern DmtxPassFail dmtxMessageDestroy(DmtxMessage **msg) { - if(msg == NULL || *msg == NULL) - return DmtxFail; + if (msg == NULL || *msg == NULL) + return DmtxFail; - if((*msg)->array != NULL) - free((*msg)->array); + if ((*msg)->array != NULL) + free((*msg)->array); - if((*msg)->code != NULL) - free((*msg)->code); + if ((*msg)->code != NULL) + free((*msg)->code); - if((*msg)->output != NULL) - free((*msg)->output); + if ((*msg)->output != NULL) + free((*msg)->output); - free(*msg); + free(*msg); - *msg = NULL; + *msg = NULL; - return DmtxPass; + return DmtxPass; } diff --git a/dmtxplacemod.c b/dmtxplacemod.c index 8cd111a3..e701fb5d 100644 --- a/dmtxplacemod.c +++ b/dmtxplacemod.c @@ -22,38 +22,37 @@ * DmtxModuleData / !DmtxModuleData (DmtxModuleAlignment) * row and col are expressed in symbol coordinates, so (0,0) is the intersection of the "L" */ -int -dmtxSymbolModuleStatus(DmtxMessage *message, int sizeIdx, int symbolRow, int symbolCol) +int dmtxSymbolModuleStatus(DmtxMessage *message, int sizeIdx, int symbolRow, int symbolCol) { - int symbolRowReverse; - int mappingRow, mappingCol; - int dataRegionRows, dataRegionCols; - int symbolRows, mappingCols; + int symbolRowReverse; + int mappingRow, mappingCol; + int dataRegionRows, dataRegionCols; + int symbolRows, mappingCols; - dataRegionRows = dmtxGetSymbolAttribute(DmtxSymAttribDataRegionRows, sizeIdx); - dataRegionCols = dmtxGetSymbolAttribute(DmtxSymAttribDataRegionCols, sizeIdx); - symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, sizeIdx); - mappingCols = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, sizeIdx); + dataRegionRows = dmtxGetSymbolAttribute(DmtxSymAttribDataRegionRows, sizeIdx); + dataRegionCols = dmtxGetSymbolAttribute(DmtxSymAttribDataRegionCols, sizeIdx); + symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, sizeIdx); + mappingCols = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, sizeIdx); - symbolRowReverse = symbolRows - symbolRow - 1; - mappingRow = symbolRowReverse - 1 - 2 * (symbolRowReverse / (dataRegionRows+2)); - mappingCol = symbolCol - 1 - 2 * (symbolCol / (dataRegionCols+2)); + symbolRowReverse = symbolRows - symbolRow - 1; + mappingRow = symbolRowReverse - 1 - 2 * (symbolRowReverse / (dataRegionRows + 2)); + mappingCol = symbolCol - 1 - 2 * (symbolCol / (dataRegionCols + 2)); - /* Solid portion of alignment patterns */ - if(symbolRow % (dataRegionRows+2) == 0 || - symbolCol % (dataRegionCols+2) == 0) - return (DmtxModuleOnRGB | (!DmtxModuleData)); + /* Solid portion of alignment patterns */ + if (symbolRow % (dataRegionRows + 2) == 0 || + symbolCol % (dataRegionCols + 2) == 0) + return (DmtxModuleOnRGB | (!DmtxModuleData)); - /* Horinzontal calibration bars */ - if((symbolRow+1) % (dataRegionRows+2) == 0) - return (((symbolCol & 0x01) ? 0 : DmtxModuleOnRGB) | (!DmtxModuleData)); + /* Horinzontal calibration bars */ + if ((symbolRow + 1) % (dataRegionRows + 2) == 0) + return (((symbolCol & 0x01) ? 0 : DmtxModuleOnRGB) | (!DmtxModuleData)); - /* Vertical calibration bars */ - if((symbolCol+1) % (dataRegionCols+2) == 0) - return (((symbolRow & 0x01) ? 0 : DmtxModuleOnRGB) | (!DmtxModuleData)); + /* Vertical calibration bars */ + if ((symbolCol + 1) % (dataRegionCols + 2) == 0) + return (((symbolRow & 0x01) ? 0 : DmtxModuleOnRGB) | (!DmtxModuleData)); - /* Data modules */ - return (message->array[mappingRow * mappingCols + mappingCol] | DmtxModuleData); + /* Data modules */ + return (message->array[mappingRow * mappingCols + mappingCol] | DmtxModuleData); } /** @@ -67,64 +66,68 @@ dmtxSymbolModuleStatus(DmtxMessage *message, int sizeIdx, int symbolRow, int sym static int ModulePlacementEcc200(unsigned char *modules, unsigned char *codewords, int sizeIdx, int moduleOnColor) { - int row, col, chr; - int mappingRows, mappingCols; + int row, col, chr; + int mappingRows, mappingCols; - assert(moduleOnColor & (DmtxModuleOnRed | DmtxModuleOnGreen | DmtxModuleOnBlue)); + assert(moduleOnColor & (DmtxModuleOnRed | DmtxModuleOnGreen | DmtxModuleOnBlue)); - mappingRows = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, sizeIdx); - mappingCols = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, sizeIdx); + mappingRows = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, sizeIdx); + mappingCols = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, sizeIdx); - /* Start in the nominal location for the 8th bit of the first character */ - chr = 0; - row = 4; - col = 0; + /* Start in the nominal location for the 8th bit of the first character */ + chr = 0; + row = 4; + col = 0; - do { - /* Repeatedly first check for one of the special corner cases */ - if((row == mappingRows) && (col == 0)) - PatternShapeSpecial1(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor); - else if((row == mappingRows-2) && (col == 0) && (mappingCols%4 != 0)) - PatternShapeSpecial2(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor); - else if((row == mappingRows-2) && (col == 0) && (mappingCols%8 == 4)) - PatternShapeSpecial3(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor); - else if((row == mappingRows+4) && (col == 2) && (mappingCols%8 == 0)) - PatternShapeSpecial4(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor); + do + { + /* Repeatedly first check for one of the special corner cases */ + if ((row == mappingRows) && (col == 0)) + PatternShapeSpecial1(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor); + else if ((row == mappingRows - 2) && (col == 0) && (mappingCols % 4 != 0)) + PatternShapeSpecial2(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor); + else if ((row == mappingRows - 2) && (col == 0) && (mappingCols % 8 == 4)) + PatternShapeSpecial3(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor); + else if ((row == mappingRows + 4) && (col == 2) && (mappingCols % 8 == 0)) + PatternShapeSpecial4(modules, mappingRows, mappingCols, &(codewords[chr++]), moduleOnColor); - /* 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); - row -= 2; - col += 2; - } while ((row >= 0) && (col < mappingCols)); - row += 1; - col += 3; + /* 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); + row -= 2; + col += 2; + } while ((row >= 0) && (col < mappingCols)); + row += 1; + col += 3; - /* Sweep downward diagonally, inserting successive characters */ - do { - if((row >= 0) && (col < mappingCols) && - !(modules[row*mappingCols+col] & DmtxModuleVisited)) - PatternShapeStandard(modules, mappingRows, mappingCols, row, col, &(codewords[chr++]), moduleOnColor); - row += 2; - col -= 2; - } while ((row < mappingRows) && (col >= 0)); - row += 3; - col += 1; - /* ... until the entire modules array is scanned */ - } while ((row < mappingRows) || (col < mappingCols)); + /* Sweep downward diagonally, inserting successive characters */ + do + { + if ((row >= 0) && (col < mappingCols) && + !(modules[row * mappingCols + col] & DmtxModuleVisited)) + PatternShapeStandard(modules, mappingRows, mappingCols, row, col, &(codewords[chr++]), moduleOnColor); + row += 2; + col -= 2; + } while ((row < mappingRows) && (col >= 0)); + row += 3; + col += 1; + /* ... until the entire modules array is scanned */ + } while ((row < mappingRows) || (col < mappingCols)); - /* If lower righthand corner is untouched then fill in the fixed pattern */ - if(!(modules[mappingRows * mappingCols - 1] & - DmtxModuleVisited)) { + /* If lower righthand corner is untouched then fill in the fixed pattern */ + if (!(modules[mappingRows * mappingCols - 1] & + DmtxModuleVisited)) + { - modules[mappingRows * mappingCols - 1] |= moduleOnColor; - modules[(mappingRows * mappingCols) - mappingCols - 2] |= moduleOnColor; - } /* XXX should this fixed pattern also be used in reading somehow? */ + modules[mappingRows * mappingCols - 1] |= moduleOnColor; + modules[(mappingRows * mappingCols) - mappingCols - 2] |= moduleOnColor; + } /* XXX should this fixed pattern also be used in reading somehow? */ - /* XXX compare that chr == region->dataSize here */ - return chr; /* XXX number of codewords read off */ + /* XXX compare that chr == region->dataSize here */ + return chr; /* XXX number of codewords read off */ } /** @@ -141,14 +144,14 @@ ModulePlacementEcc200(unsigned char *modules, unsigned char *codewords, int size static void PatternShapeStandard(unsigned char *modules, int mappingRows, int mappingCols, int row, int col, unsigned char *codeword, int moduleOnColor) { - 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); + 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); } /** @@ -163,14 +166,14 @@ PatternShapeStandard(unsigned char *modules, int mappingRows, int mappingCols, i static void PatternShapeSpecial1(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor) { - 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); + 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); } /** @@ -185,14 +188,14 @@ PatternShapeSpecial1(unsigned char *modules, int mappingRows, int mappingCols, u static void PatternShapeSpecial2(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor) { - 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); + 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); } /** @@ -207,14 +210,14 @@ PatternShapeSpecial2(unsigned char *modules, int mappingRows, int mappingCols, u static void PatternShapeSpecial3(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor) { - 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); + 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); } /** @@ -229,14 +232,14 @@ PatternShapeSpecial3(unsigned char *modules, int mappingRows, int mappingCols, u static void PatternShapeSpecial4(unsigned char *modules, int mappingRows, int mappingCols, unsigned char *codeword, int moduleOnColor) { - 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); + 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); } /** @@ -254,29 +257,33 @@ PatternShapeSpecial4(unsigned char *modules, int mappingRows, int mappingCols, u static void PlaceModule(unsigned char *modules, int mappingRows, int mappingCols, int row, int col, unsigned char *codeword, int mask, int moduleOnColor) { - if(row < 0) { - row += mappingRows; - col += 4 - ((mappingRows+4)%8); - } - if(col < 0) { - col += mappingCols; - row += 4 - ((mappingCols+4)%8); - } + if (row < 0) + { + row += mappingRows; + col += 4 - ((mappingRows + 4) % 8); + } + if (col < 0) + { + col += mappingCols; + row += 4 - ((mappingCols + 4) % 8); + } - /* If module has already been assigned then we are decoding the pattern into codewords */ - if((modules[row*mappingCols+col] & DmtxModuleAssigned) != 0) { - if((modules[row*mappingCols+col] & moduleOnColor) != 0) - *codeword |= mask; - else - *codeword &= (0xff ^ mask); - } - /* Otherwise we are encoding the codewords into a pattern */ - else { - if((*codeword & mask) != 0x00) - modules[row*mappingCols+col] |= moduleOnColor; + /* If module has already been assigned then we are decoding the pattern into codewords */ + if ((modules[row * mappingCols + col] & DmtxModuleAssigned) != 0) + { + if ((modules[row * mappingCols + col] & moduleOnColor) != 0) + *codeword |= mask; + else + *codeword &= (0xff ^ mask); + } + /* Otherwise we are encoding the codewords into a pattern */ + else + { + if ((*codeword & mask) != 0x00) + modules[row * mappingCols + col] |= moduleOnColor; - modules[row*mappingCols+col] |= DmtxModuleAssigned; - } + modules[row * mappingCols + col] |= DmtxModuleAssigned; + } - modules[row*mappingCols+col] |= DmtxModuleVisited; + modules[row * mappingCols + col] |= DmtxModuleVisited; } diff --git a/dmtxreedsol.c b/dmtxreedsol.c index 96b08b92..93a92e37 100644 --- a/dmtxreedsol.c +++ b/dmtxreedsol.c @@ -28,16 +28,16 @@ #define MAX_ERROR_WORD_COUNT 68 /* GF add (a + b) */ -#define GfAdd(a,b) \ - ((a) ^ (b)) +#define GfAdd(a, b) \ + ((a) ^ (b)) /* GF multiply (a * b) */ -#define GfMult(a,b) \ - (((a) == 0 || (b) == 0) ? 0 : antilog301[(log301[(a)] + log301[(b)]) % NN]) +#define GfMult(a, b) \ + (((a) == 0 || (b) == 0) ? 0 : antilog301[(log301[(a)] + log301[(b)]) % NN]) /* GF multiply by antilog (a * alpha**b) */ -#define GfMultAntilog(a,b) \ - (((a) == 0) ? 0 : antilog301[(log301[(a)] + (b)) % NN]) +#define GfMultAntilog(a, b) \ + (((a) == 0) ? 0 : antilog301[(log301[(a)] + (b)) % NN]) /* GF(256) log values using primitive polynomial 301 */ static DmtxByte log301[] = @@ -85,56 +85,63 @@ static DmtxByte antilog301[] = * \return Function success (DmtxPass|DmtxFail) */ #undef CHKPASS -#define CHKPASS { if(passFail == DmtxFail) return DmtxFail; } +#define CHKPASS \ + { \ + if (passFail == DmtxFail) \ + return DmtxFail; \ + } static DmtxPassFail RsEncode(DmtxMessage *message, int sizeIdx) { - int i, j; - int blockStride, blockIdx; - int blockErrorWords, symbolDataWords, symbolErrorWords, symbolTotalWords; - DmtxPassFail passFail; - DmtxByte val, *eccPtr; - DmtxByte genStorage[MAX_ERROR_WORD_COUNT]; - DmtxByte eccStorage[MAX_ERROR_WORD_COUNT]; - DmtxByteList gen = dmtxByteListBuild(genStorage, sizeof(genStorage)); - DmtxByteList ecc = dmtxByteListBuild(eccStorage, sizeof(eccStorage)); - - blockStride = dmtxGetSymbolAttribute(DmtxSymAttribInterleavedBlocks, sizeIdx); - blockErrorWords = dmtxGetSymbolAttribute(DmtxSymAttribBlockErrorWords, sizeIdx); - symbolDataWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx); - symbolErrorWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolErrorWords, sizeIdx); - symbolTotalWords = symbolDataWords + symbolErrorWords; - - /* Populate generator polynomial */ - RsGenPoly(&gen, blockErrorWords); - - /* For each interleaved block... */ - for(blockIdx = 0; blockIdx < blockStride; blockIdx++) - { - /* Generate error codewords */ - dmtxByteListInit(&ecc, blockErrorWords, 0, &passFail); CHKPASS; - for(i = blockIdx; i < symbolDataWords; i += blockStride) - { - val = GfAdd(ecc.b[blockErrorWords-1], message->code[i]); - - for(j = blockErrorWords - 1; j > 0; j--) - { - DMTX_CHECK_BOUNDS(&ecc, j); DMTX_CHECK_BOUNDS(&ecc, j-1); DMTX_CHECK_BOUNDS(&gen, j); - ecc.b[j] = GfAdd(ecc.b[j-1], GfMult(gen.b[j], val)); - } - - ecc.b[0] = GfMult(gen.b[0], val); - } - - /* Copy to output message */ - eccPtr = ecc.b + blockErrorWords; - for(i = symbolDataWords + blockIdx; i < symbolTotalWords; i += blockStride) - message->code[i] = *(--eccPtr); - - assert(ecc.b == eccPtr); - } - - return DmtxPass; + int i, j; + int blockStride, blockIdx; + int blockErrorWords, symbolDataWords, symbolErrorWords, symbolTotalWords; + DmtxPassFail passFail; + DmtxByte val, *eccPtr; + DmtxByte genStorage[MAX_ERROR_WORD_COUNT]; + DmtxByte eccStorage[MAX_ERROR_WORD_COUNT]; + DmtxByteList gen = dmtxByteListBuild(genStorage, sizeof(genStorage)); + DmtxByteList ecc = dmtxByteListBuild(eccStorage, sizeof(eccStorage)); + + blockStride = dmtxGetSymbolAttribute(DmtxSymAttribInterleavedBlocks, sizeIdx); + blockErrorWords = dmtxGetSymbolAttribute(DmtxSymAttribBlockErrorWords, sizeIdx); + symbolDataWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx); + symbolErrorWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolErrorWords, sizeIdx); + symbolTotalWords = symbolDataWords + symbolErrorWords; + + /* Populate generator polynomial */ + RsGenPoly(&gen, blockErrorWords); + + /* For each interleaved block... */ + for (blockIdx = 0; blockIdx < blockStride; blockIdx++) + { + /* Generate error codewords */ + dmtxByteListInit(&ecc, blockErrorWords, 0, &passFail); + CHKPASS; + for (i = blockIdx; i < symbolDataWords; i += blockStride) + { + val = GfAdd(ecc.b[blockErrorWords - 1], message->code[i]); + + for (j = blockErrorWords - 1; j > 0; j--) + { + DMTX_CHECK_BOUNDS(&ecc, j); + DMTX_CHECK_BOUNDS(&ecc, j - 1); + DMTX_CHECK_BOUNDS(&gen, j); + ecc.b[j] = GfAdd(ecc.b[j - 1], GfMult(gen.b[j], val)); + } + + ecc.b[0] = GfMult(gen.b[0], val); + } + + /* Copy to output message */ + eccPtr = ecc.b + blockErrorWords; + for (i = symbolDataWords + blockIdx; i < symbolTotalWords; i += blockStride) + message->code[i] = *(--eccPtr); + + assert(ecc.b == eccPtr); + } + + return DmtxPass; } /** @@ -146,102 +153,111 @@ RsEncode(DmtxMessage *message, int sizeIdx) * \return Function success (DmtxPass|DmtxFail) */ #undef CHKPASS -#define CHKPASS { if(passFail == DmtxFail) return DmtxFail; } +#define CHKPASS \ + { \ + if (passFail == DmtxFail) \ + return DmtxFail; \ + } static DmtxPassFail RsDecode(unsigned char *code, int sizeIdx, int fix) { - int i; - int blockStride, blockIdx; - int blockDataWords, blockErrorWords, blockMaxCorrectable; -// int blockDataWords, blockErrorWords, blockTotalWords, blockMaxCorrectable; - int symbolDataWords, symbolErrorWords, symbolTotalWords; - DmtxBoolean error, repairable; - DmtxPassFail passFail; - unsigned char *word; - DmtxByte elpStorage[MAX_ERROR_WORD_COUNT]; - DmtxByte synStorage[MAX_ERROR_WORD_COUNT+1]; - DmtxByte recStorage[NN]; - DmtxByte locStorage[NN]; - DmtxByteList elp = dmtxByteListBuild(elpStorage, sizeof(elpStorage)); - DmtxByteList syn = dmtxByteListBuild(synStorage, sizeof(synStorage)); - DmtxByteList rec = dmtxByteListBuild(recStorage, sizeof(recStorage)); - DmtxByteList loc = dmtxByteListBuild(locStorage, sizeof(locStorage)); - - blockStride = dmtxGetSymbolAttribute(DmtxSymAttribInterleavedBlocks, sizeIdx); - blockErrorWords = dmtxGetSymbolAttribute(DmtxSymAttribBlockErrorWords, sizeIdx); - blockMaxCorrectable = dmtxGetSymbolAttribute(DmtxSymAttribBlockMaxCorrectable, sizeIdx); - symbolDataWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx); - symbolErrorWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolErrorWords, sizeIdx); - symbolTotalWords = symbolDataWords + symbolErrorWords; - - /* For each interleaved block */ - for(blockIdx = 0; blockIdx < blockStride; blockIdx++) - { - /* Data word count depends on blockIdx due to special case at 144x144 */ - blockDataWords = dmtxGetBlockDataSize(sizeIdx, blockIdx); -// blockTotalWords = blockErrorWords + blockDataWords; - - /* Populate received list (rec) with data and error codewords */ - dmtxByteListInit(&rec, 0, 0, &passFail); CHKPASS; - - /* Start with final error word and work backward */ - word = code + symbolTotalWords + blockIdx - blockStride; - for(i = 0; i < blockErrorWords; i++) - { - dmtxByteListPush(&rec, *word, &passFail); CHKPASS; - word -= blockStride; - } - - /* Start with final data word and work backward */ - word = code + blockIdx + (blockStride * (blockDataWords - 1)); - for(i = 0; i < blockDataWords; i++) - { - dmtxByteListPush(&rec, *word, &passFail); CHKPASS; - word -= blockStride; - } - - /* Compute syndromes (syn) */ - error = RsComputeSyndromes(&syn, &rec, blockErrorWords); - - /* Error(s) detected: Attempt repair */ - if(error) - { - /* Find error locator polynomial (elp) */ - repairable = RsFindErrorLocatorPoly(&elp, &syn, blockErrorWords, blockMaxCorrectable); - if(!repairable) - return DmtxFail; - - /* Find error positions (loc) */ - repairable = RsFindErrorLocations(&loc, &elp); - if(!repairable) - return DmtxFail; - - /* Find error values and repair */ - RsRepairErrors(&rec, &loc, &elp, &syn); - } - - /* - * Overwrite output with correct/corrected values - */ - - /* Start with first data word and work forward */ - word = code + blockIdx; - for(i = 0; i < blockDataWords; i++) - { - *word = dmtxByteListPop(&rec, &passFail); CHKPASS; - word += blockStride; - } - - /* Start with first error word and work forward */ - word = code + symbolDataWords + blockIdx; - for(i = 0; i < blockErrorWords; i++) - { - *word = dmtxByteListPop(&rec, &passFail); CHKPASS; - word += blockStride; - } - } - - return DmtxPass; + int i; + int blockStride, blockIdx; + int blockDataWords, blockErrorWords, blockMaxCorrectable; + // int blockDataWords, blockErrorWords, blockTotalWords, blockMaxCorrectable; + int symbolDataWords, symbolErrorWords, symbolTotalWords; + DmtxBoolean error, repairable; + DmtxPassFail passFail; + unsigned char *word; + DmtxByte elpStorage[MAX_ERROR_WORD_COUNT]; + DmtxByte synStorage[MAX_ERROR_WORD_COUNT + 1]; + DmtxByte recStorage[NN]; + DmtxByte locStorage[NN]; + DmtxByteList elp = dmtxByteListBuild(elpStorage, sizeof(elpStorage)); + DmtxByteList syn = dmtxByteListBuild(synStorage, sizeof(synStorage)); + DmtxByteList rec = dmtxByteListBuild(recStorage, sizeof(recStorage)); + DmtxByteList loc = dmtxByteListBuild(locStorage, sizeof(locStorage)); + + blockStride = dmtxGetSymbolAttribute(DmtxSymAttribInterleavedBlocks, sizeIdx); + blockErrorWords = dmtxGetSymbolAttribute(DmtxSymAttribBlockErrorWords, sizeIdx); + blockMaxCorrectable = dmtxGetSymbolAttribute(DmtxSymAttribBlockMaxCorrectable, sizeIdx); + symbolDataWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx); + symbolErrorWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolErrorWords, sizeIdx); + symbolTotalWords = symbolDataWords + symbolErrorWords; + + /* For each interleaved block */ + for (blockIdx = 0; blockIdx < blockStride; blockIdx++) + { + /* Data word count depends on blockIdx due to special case at 144x144 */ + blockDataWords = dmtxGetBlockDataSize(sizeIdx, blockIdx); + // blockTotalWords = blockErrorWords + blockDataWords; + + /* Populate received list (rec) with data and error codewords */ + dmtxByteListInit(&rec, 0, 0, &passFail); + CHKPASS; + + /* Start with final error word and work backward */ + word = code + symbolTotalWords + blockIdx - blockStride; + for (i = 0; i < blockErrorWords; i++) + { + dmtxByteListPush(&rec, *word, &passFail); + CHKPASS; + word -= blockStride; + } + + /* Start with final data word and work backward */ + word = code + blockIdx + (blockStride * (blockDataWords - 1)); + for (i = 0; i < blockDataWords; i++) + { + dmtxByteListPush(&rec, *word, &passFail); + CHKPASS; + word -= blockStride; + } + + /* Compute syndromes (syn) */ + error = RsComputeSyndromes(&syn, &rec, blockErrorWords); + + /* Error(s) detected: Attempt repair */ + if (error) + { + /* Find error locator polynomial (elp) */ + repairable = RsFindErrorLocatorPoly(&elp, &syn, blockErrorWords, blockMaxCorrectable); + if (!repairable) + return DmtxFail; + + /* Find error positions (loc) */ + repairable = RsFindErrorLocations(&loc, &elp); + if (!repairable) + return DmtxFail; + + /* Find error values and repair */ + RsRepairErrors(&rec, &loc, &elp, &syn); + } + + /* + * Overwrite output with correct/corrected values + */ + + /* Start with first data word and work forward */ + word = code + blockIdx; + for (i = 0; i < blockDataWords; i++) + { + *word = dmtxByteListPop(&rec, &passFail); + CHKPASS; + word += blockStride; + } + + /* Start with first error word and work forward */ + word = code + symbolDataWords + blockIdx; + for (i = 0; i < blockErrorWords; i++) + { + *word = dmtxByteListPop(&rec, &passFail); + CHKPASS; + word += blockStride; + } + } + + return DmtxPass; } /** @@ -252,28 +268,33 @@ RsDecode(unsigned char *code, int sizeIdx, int fix) * \return Function success (DmtxPass|DmtxFail) */ #undef CHKPASS -#define CHKPASS { if(passFail == DmtxFail) return DmtxFail; } +#define CHKPASS \ + { \ + if (passFail == DmtxFail) \ + return DmtxFail; \ + } static DmtxPassFail RsGenPoly(DmtxByteList *gen, int errorWordCount) { - int i, j; - DmtxPassFail passFail; - - /* Initialize all coefficients to 1 */ - dmtxByteListInit(gen, errorWordCount, 1, &passFail); CHKPASS; - - /* Generate polynomial */ - for(i = 0; i < gen->length; i++) - { - for(j = i; j >= 0; j--) - { - gen->b[j] = GfMultAntilog(gen->b[j], i+1); - if(j > 0) - gen->b[j] = GfAdd(gen->b[j], gen->b[j-1]); - } - } - - return DmtxPass; + int i, j; + DmtxPassFail passFail; + + /* Initialize all coefficients to 1 */ + dmtxByteListInit(gen, errorWordCount, 1, &passFail); + CHKPASS; + + /* Generate polynomial */ + for (i = 0; i < gen->length; i++) + { + for (j = i; j >= 0; j--) + { + gen->b[j] = GfMultAntilog(gen->b[j], i + 1); + if (j > 0) + gen->b[j] = GfAdd(gen->b[j], gen->b[j - 1]); + } + } + + return DmtxPass; } /** @@ -289,29 +310,34 @@ RsGenPoly(DmtxByteList *gen, int errorWordCount) */ /* XXX this CHKPASS isn't doing what we want ... really need a error reporting strategy */ #undef CHKPASS -#define CHKPASS { if(passFail == DmtxFail) return DmtxTrue; } +#define CHKPASS \ + { \ + if (passFail == DmtxFail) \ + return DmtxTrue; \ + } static DmtxBoolean RsComputeSyndromes(DmtxByteList *syn, const DmtxByteList *rec, int blockErrorWords) { - int i, j; - DmtxPassFail passFail; - DmtxBoolean error = DmtxFalse; - - /* Initialize all coefficients to 0 */ - dmtxByteListInit(syn, blockErrorWords + 1, 0, &passFail); CHKPASS; - - for(i = 1; i < syn->length; i++) - { - /* Calculate syndrome at i */ - for(j = 0; j < rec->length; j++) /* alternatively: j < blockTotalWords */ - syn->b[i] = GfAdd(syn->b[i], GfMultAntilog(rec->b[j], i*j)); - - /* Non-zero syndrome indicates presence of error(s) */ - if(syn->b[i] != 0) - error = DmtxTrue; - } - - return error; + int i, j; + DmtxPassFail passFail; + DmtxBoolean error = DmtxFalse; + + /* Initialize all coefficients to 0 */ + dmtxByteListInit(syn, blockErrorWords + 1, 0, &passFail); + CHKPASS; + + for (i = 1; i < syn->length; i++) + { + /* Calculate syndrome at i */ + for (j = 0; j < rec->length; j++) /* alternatively: j < blockTotalWords */ + syn->b[i] = GfAdd(syn->b[i], GfMultAntilog(rec->b[j], i * j)); + + /* Non-zero syndrome indicates presence of error(s) */ + if (syn->b[i] != 0) + error = DmtxTrue; + } + + return error; } /** @@ -325,76 +351,87 @@ RsComputeSyndromes(DmtxByteList *syn, const DmtxByteList *rec, int blockErrorWor */ /* XXX this CHKPASS isn't doing what we want ... really need a error reporting strategy */ #undef CHKPASS -#define CHKPASS { if(passFail == DmtxFail) return DmtxFalse; } +#define CHKPASS \ + { \ + if (passFail == DmtxFail) \ + return DmtxFalse; \ + } static DmtxBoolean RsFindErrorLocatorPoly(DmtxByteList *elpOut, const DmtxByteList *syn, int errorWordCount, int maxCorrectable) { - int i, iNext, j; - int m, mCmp, lambda; - DmtxByte disTmp, disStorage[MAX_ERROR_WORD_COUNT+1]; - DmtxByte elpStorage[MAX_ERROR_WORD_COUNT+2][MAX_ERROR_WORD_COUNT]; - DmtxByteList dis, elp[MAX_ERROR_WORD_COUNT+2]; - DmtxPassFail passFail; - - dis = dmtxByteListBuild(disStorage, sizeof(disStorage)); - dmtxByteListInit(&dis, 0, 0, &passFail); CHKPASS; - - for(i = 0; i < MAX_ERROR_WORD_COUNT + 2; i++) - { - elp[i] = dmtxByteListBuild(elpStorage[i], sizeof(elpStorage[i])); - dmtxByteListInit(&elp[i], 0, 0, &passFail); CHKPASS; - } - - /* iNext = 0 */ - dmtxByteListPush(&elp[0], 1, &passFail); CHKPASS; - dmtxByteListPush(&dis, 1, &passFail); CHKPASS; - - /* iNext = 1 */ - dmtxByteListPush(&elp[1], 1, &passFail); CHKPASS; - dmtxByteListPush(&dis, syn->b[1], &passFail); CHKPASS; - - for(iNext = 2, i = 1; /* explicit break */; i = iNext++) - { - if(dis.b[i] == 0) - { - /* Simple case: Copy directly from previous iteration */ - dmtxByteListCopy(&elp[iNext], &elp[i], &passFail); CHKPASS; - } - else - { - /* Find earlier iteration (m) that provides maximal (m - lambda) */ - for(m = 0, mCmp = 1; mCmp < i; mCmp++) - if(dis.b[mCmp] != 0 && (mCmp - elp[mCmp].length) >= (m - elp[m].length)) - m = mCmp; - - /* Calculate error location polynomial elp[i] (set 1st term) */ - for(lambda = elp[m].length - 1, j = 0; j <= lambda; j++) - elp[iNext].b[j+i-m] = (elp[i - 1].b[j] == 0) ? 0 : - antilog301[(NN - log301[dis.b[m]] + - log301[dis.b[i]] + log301[elp[m].b[j]]) % NN]; - - /* Calculate error location polynomial elp[i] (add 2nd term) */ - for(lambda = elp[i].length - 1, j = 0; j <= lambda; j++) - elp[iNext].b[j] = GfAdd(elp[iNext].b[j], elp[i].b[j]); - - elp[iNext].length = max(elp[i].length, elp[m].length + i - m); - } - - lambda = elp[iNext].length - 1; - if(i == errorWordCount || i >= lambda + maxCorrectable) - break; - - /* Calculate discrepancy dis.b[i] */ - for(disTmp = syn->b[iNext], j = 1; j <= lambda; j++) - disTmp = GfAdd(disTmp, GfMult(syn->b[iNext-j], elp[iNext].b[j])); - - assert(dis.length == iNext); - dmtxByteListPush(&dis, disTmp, &passFail); CHKPASS; - } - - dmtxByteListCopy(elpOut, &elp[iNext], &passFail); CHKPASS; - - return (lambda <= maxCorrectable) ? DmtxTrue : DmtxFalse; + int i, iNext, j; + int m, mCmp, lambda; + DmtxByte disTmp, disStorage[MAX_ERROR_WORD_COUNT + 1]; + DmtxByte elpStorage[MAX_ERROR_WORD_COUNT + 2][MAX_ERROR_WORD_COUNT]; + DmtxByteList dis, elp[MAX_ERROR_WORD_COUNT + 2]; + DmtxPassFail passFail; + + dis = dmtxByteListBuild(disStorage, sizeof(disStorage)); + dmtxByteListInit(&dis, 0, 0, &passFail); + CHKPASS; + + for (i = 0; i < MAX_ERROR_WORD_COUNT + 2; i++) + { + elp[i] = dmtxByteListBuild(elpStorage[i], sizeof(elpStorage[i])); + dmtxByteListInit(&elp[i], 0, 0, &passFail); + CHKPASS; + } + + /* iNext = 0 */ + dmtxByteListPush(&elp[0], 1, &passFail); + CHKPASS; + dmtxByteListPush(&dis, 1, &passFail); + CHKPASS; + + /* iNext = 1 */ + dmtxByteListPush(&elp[1], 1, &passFail); + CHKPASS; + dmtxByteListPush(&dis, syn->b[1], &passFail); + CHKPASS; + + for (iNext = 2, i = 1; /* explicit break */; i = iNext++) + { + if (dis.b[i] == 0) + { + /* Simple case: Copy directly from previous iteration */ + dmtxByteListCopy(&elp[iNext], &elp[i], &passFail); + CHKPASS; + } + else + { + /* Find earlier iteration (m) that provides maximal (m - lambda) */ + for (m = 0, mCmp = 1; mCmp < i; mCmp++) + if (dis.b[mCmp] != 0 && (mCmp - elp[mCmp].length) >= (m - elp[m].length)) + m = mCmp; + + /* Calculate error location polynomial elp[i] (set 1st term) */ + for (lambda = elp[m].length - 1, j = 0; j <= lambda; j++) + elp[iNext].b[j + i - m] = (elp[i - 1].b[j] == 0) ? 0 : antilog301[(NN - log301[dis.b[m]] + log301[dis.b[i]] + log301[elp[m].b[j]]) % NN]; + + /* Calculate error location polynomial elp[i] (add 2nd term) */ + for (lambda = elp[i].length - 1, j = 0; j <= lambda; j++) + elp[iNext].b[j] = GfAdd(elp[iNext].b[j], elp[i].b[j]); + + elp[iNext].length = max(elp[i].length, elp[m].length + i - m); + } + + lambda = elp[iNext].length - 1; + if (i == errorWordCount || i >= lambda + maxCorrectable) + break; + + /* Calculate discrepancy dis.b[i] */ + for (disTmp = syn->b[iNext], j = 1; j <= lambda; j++) + disTmp = GfAdd(disTmp, GfMult(syn->b[iNext - j], elp[iNext].b[j])); + + assert(dis.length == iNext); + dmtxByteListPush(&dis, disTmp, &passFail); + CHKPASS; + } + + dmtxByteListCopy(elpOut, &elp[iNext], &passFail); + CHKPASS; + + return (lambda <= maxCorrectable) ? DmtxTrue : DmtxFalse; } /** @@ -408,34 +445,41 @@ RsFindErrorLocatorPoly(DmtxByteList *elpOut, const DmtxByteList *syn, int errorW * \return Is block repairable? (DmtxTrue|DmtxFalse) */ #undef CHKPASS -#define CHKPASS { if(passFail == DmtxFail) return DmtxFalse; } +#define CHKPASS \ + { \ + if (passFail == DmtxFail) \ + return DmtxFalse; \ + } static DmtxBoolean RsFindErrorLocations(DmtxByteList *loc, const DmtxByteList *elp) { - int i, j; - int lambda = elp->length - 1; - DmtxPassFail passFail; - DmtxByte q, regStorage[MAX_ERROR_WORD_COUNT]; - DmtxByteList reg = dmtxByteListBuild(regStorage, sizeof(regStorage)); - - dmtxByteListCopy(®, elp, &passFail); CHKPASS; - dmtxByteListInit(loc, 0, 0, &passFail); CHKPASS; - - for(i = 1; i <= NN; i++) - { - for(q = 1, j = 1; j <= lambda; j++) - { - reg.b[j] = GfMultAntilog(reg.b[j], j); - q = GfAdd(q, reg.b[j]); - } - - if(q == 0) - { - dmtxByteListPush(loc, NN - i, &passFail); CHKPASS; - } - } - - return (loc->length == lambda) ? DmtxTrue : DmtxFalse; + int i, j; + int lambda = elp->length - 1; + DmtxPassFail passFail; + DmtxByte q, regStorage[MAX_ERROR_WORD_COUNT]; + DmtxByteList reg = dmtxByteListBuild(regStorage, sizeof(regStorage)); + + dmtxByteListCopy(®, elp, &passFail); + CHKPASS; + dmtxByteListInit(loc, 0, 0, &passFail); + CHKPASS; + + for (i = 1; i <= NN; i++) + { + for (q = 1, j = 1; j <= lambda; j++) + { + reg.b[j] = GfMultAntilog(reg.b[j], j); + q = GfAdd(q, reg.b[j]); + } + + if (q == 0) + { + dmtxByteListPush(loc, NN - i, &passFail); + CHKPASS; + } + } + + return (loc->length == lambda) ? DmtxTrue : DmtxFalse; } /** @@ -453,48 +497,54 @@ RsFindErrorLocations(DmtxByteList *loc, const DmtxByteList *elp) * \param syn */ #undef CHKPASS -#define CHKPASS { if(passFail == DmtxFail) return DmtxFail; } +#define CHKPASS \ + { \ + if (passFail == DmtxFail) \ + return DmtxFail; \ + } static DmtxPassFail RsRepairErrors(DmtxByteList *rec, const DmtxByteList *loc, const DmtxByteList *elp, const DmtxByteList *syn) { - int i, j, q; - int lambda = elp->length - 1; - DmtxPassFail passFail; - DmtxByte zVal, root, err; - DmtxByte zStorage[MAX_ERROR_WORD_COUNT+1]; - DmtxByteList z = dmtxByteListBuild(zStorage, sizeof(zStorage)); - - /* Form polynomial z(x) */ - dmtxByteListPush(&z, 1, &passFail); CHKPASS; - for(i = 1; i <= lambda; i++) - { - for(zVal = GfAdd(syn->b[i], elp->b[i]), j = 1; j < i; j++) - zVal= GfAdd(zVal, GfMult(elp->b[i-j], syn->b[j])); - dmtxByteListPush(&z, zVal, &passFail); CHKPASS; - } - - for(i = 0; i < lambda; i++) - { - /* Calculate numerator of error term */ - root = NN - loc->b[i]; - - for(err = 1, j = 1; j <= lambda; j++) - err = GfAdd(err, GfMultAntilog(z.b[j], j * root)); - - if(err == 0) - continue; - - /* Calculate denominator of error term */ - for(q = 0, j = 0; j < lambda; j++) - { - if(j != i) - q += log301[1 ^ antilog301[(loc->b[j] + root) % NN]]; - } - q %= NN; - - err = GfMultAntilog(err, NN - q); - rec->b[loc->b[i]] = GfAdd(rec->b[loc->b[i]], err); - } - - return DmtxPass; + int i, j, q; + int lambda = elp->length - 1; + DmtxPassFail passFail; + DmtxByte zVal, root, err; + DmtxByte zStorage[MAX_ERROR_WORD_COUNT + 1]; + DmtxByteList z = dmtxByteListBuild(zStorage, sizeof(zStorage)); + + /* Form polynomial z(x) */ + dmtxByteListPush(&z, 1, &passFail); + CHKPASS; + for (i = 1; i <= lambda; i++) + { + for (zVal = GfAdd(syn->b[i], elp->b[i]), j = 1; j < i; j++) + zVal = GfAdd(zVal, GfMult(elp->b[i - j], syn->b[j])); + dmtxByteListPush(&z, zVal, &passFail); + CHKPASS; + } + + for (i = 0; i < lambda; i++) + { + /* Calculate numerator of error term */ + root = NN - loc->b[i]; + + for (err = 1, j = 1; j <= lambda; j++) + err = GfAdd(err, GfMultAntilog(z.b[j], j * root)); + + if (err == 0) + continue; + + /* Calculate denominator of error term */ + for (q = 0, j = 0; j < lambda; j++) + { + if (j != i) + q += log301[1 ^ antilog301[(loc->b[j] + root) % NN]]; + } + q %= NN; + + err = GfMultAntilog(err, NN - q); + rec->b[loc->b[i]] = GfAdd(rec->b[loc->b[i]], err); + } + + return DmtxPass; } diff --git a/dmtxregion.c b/dmtxregion.c index b51461ce..91061aa6 100644 --- a/dmtxregion.c +++ b/dmtxregion.c @@ -25,15 +25,15 @@ extern DmtxRegion * dmtxRegionCreate(DmtxRegion *reg) { - DmtxRegion *regCopy; + DmtxRegion *regCopy; - regCopy = (DmtxRegion *)malloc(sizeof(DmtxRegion)); - if(regCopy == NULL) - return NULL; + regCopy = (DmtxRegion *)malloc(sizeof(DmtxRegion)); + if (regCopy == NULL) + return NULL; - memcpy(regCopy, reg, sizeof(DmtxRegion)); + memcpy(regCopy, reg, sizeof(DmtxRegion)); - return regCopy; + return regCopy; } /** @@ -44,14 +44,14 @@ dmtxRegionCreate(DmtxRegion *reg) extern DmtxPassFail dmtxRegionDestroy(DmtxRegion **reg) { - if(reg == NULL || *reg == NULL) - return DmtxFail; + if (reg == NULL || *reg == NULL) + return DmtxFail; - free(*reg); + free(*reg); - *reg = NULL; + *reg = NULL; - return DmtxPass; + return DmtxPass; } /** @@ -63,27 +63,28 @@ dmtxRegionDestroy(DmtxRegion **reg) extern DmtxRegion * dmtxRegionFindNext(DmtxDecode *dec, DmtxTime *timeout) { - int locStatus; - DmtxPixelLoc loc; - DmtxRegion *reg; - - /* Continue until we find a region or run out of chances */ - for(;;) { - locStatus = PopGridLocation(&(dec->grid), &loc); - if(locStatus == DmtxRangeEnd) - break; - - /* Scan location for presence of valid barcode region */ - reg = dmtxRegionScanPixel(dec, loc.X, loc.Y); - if(reg != NULL) - return reg; - - /* Ran out of time? */ - if(timeout != NULL && dmtxTimeExceeded(*timeout)) - break; - } - - return NULL; + int locStatus; + DmtxPixelLoc loc; + DmtxRegion *reg; + + /* Continue until we find a region or run out of chances */ + for (;;) + { + locStatus = PopGridLocation(&(dec->grid), &loc); + if (locStatus == DmtxRangeEnd) + break; + + /* Scan location for presence of valid barcode region */ + reg = dmtxRegionScanPixel(dec, loc.X, loc.Y); + if (reg != NULL) + return reg; + + /* Ran out of time? */ + if (timeout != NULL && dmtxTimeExceeded(*timeout)) + break; + } + + return NULL; } /** @@ -95,54 +96,54 @@ dmtxRegionFindNext(DmtxDecode *dec, DmtxTime *timeout) extern DmtxRegion * dmtxRegionScanPixel(DmtxDecode *dec, int x, int y) { - unsigned char *cache; - DmtxRegion reg; - DmtxPointFlow flowBegin; - DmtxPixelLoc loc; - - loc.X = x; - loc.Y = y; - - cache = dmtxDecodeGetCache(dec, loc.X, loc.Y); - if(cache == NULL) - return NULL; - - if((int)(*cache & 0x80) != 0x00) - return NULL; - - /* Test for presence of any reasonable edge at this location */ - flowBegin = MatrixRegionSeekEdge(dec, loc); - if(flowBegin.mag < (int)(dec->edgeThresh * 7.65 + 0.5)) - return NULL; - - memset(®, 0x00, sizeof(DmtxRegion)); - - /* Determine barcode orientation */ - if(MatrixRegionOrientation(dec, ®, flowBegin) == DmtxFail) - return NULL; - if(dmtxRegionUpdateXfrms(dec, ®) == DmtxFail) - return NULL; - - /* Define top edge */ - if(MatrixRegionAlignCalibEdge(dec, ®, DmtxEdgeTop) == DmtxFail) - return NULL; - if(dmtxRegionUpdateXfrms(dec, ®) == DmtxFail) - return NULL; - - /* Define right edge */ - if(MatrixRegionAlignCalibEdge(dec, ®, DmtxEdgeRight) == DmtxFail) - return NULL; - if(dmtxRegionUpdateXfrms(dec, ®) == DmtxFail) - return NULL; - - CALLBACK_MATRIX(®); - - /* Calculate the best fitting symbol size */ - if(MatrixRegionFindSize(dec, ®) == DmtxFail) - return NULL; - - /* Found a valid matrix region */ - return dmtxRegionCreate(®); + unsigned char *cache; + DmtxRegion reg; + DmtxPointFlow flowBegin; + DmtxPixelLoc loc; + + loc.X = x; + loc.Y = y; + + cache = dmtxDecodeGetCache(dec, loc.X, loc.Y); + if (cache == NULL) + return NULL; + + if ((int)(*cache & 0x80) != 0x00) + return NULL; + + /* Test for presence of any reasonable edge at this location */ + flowBegin = MatrixRegionSeekEdge(dec, loc); + if (flowBegin.mag < (int)(dec->edgeThresh * 7.65 + 0.5)) + return NULL; + + memset(®, 0x00, sizeof(DmtxRegion)); + + /* Determine barcode orientation */ + if (MatrixRegionOrientation(dec, ®, flowBegin) == DmtxFail) + return NULL; + if (dmtxRegionUpdateXfrms(dec, ®) == DmtxFail) + return NULL; + + /* Define top edge */ + if (MatrixRegionAlignCalibEdge(dec, ®, DmtxEdgeTop) == DmtxFail) + return NULL; + if (dmtxRegionUpdateXfrms(dec, ®) == DmtxFail) + return NULL; + + /* Define right edge */ + if (MatrixRegionAlignCalibEdge(dec, ®, DmtxEdgeRight) == DmtxFail) + return NULL; + if (dmtxRegionUpdateXfrms(dec, ®) == DmtxFail) + return NULL; + + CALLBACK_MATRIX(®); + + /* Calculate the best fitting symbol size */ + if (MatrixRegionFindSize(dec, ®) == DmtxFail) + return NULL; + + /* Found a valid matrix region */ + return dmtxRegionCreate(®); } /** @@ -152,42 +153,45 @@ dmtxRegionScanPixel(DmtxDecode *dec, int x, int y) static DmtxPointFlow MatrixRegionSeekEdge(DmtxDecode *dec, DmtxPixelLoc loc) { - int i; - int strongIdx; - int channelCount; - DmtxPointFlow flow, flowPlane[3]; - DmtxPointFlow flowPos, flowPosBack; - DmtxPointFlow flowNeg, flowNegBack; - - channelCount = dec->image->channelCount; - - /* Find whether red, green, or blue shows the strongest edge */ - strongIdx = 0; - for(i = 0; i < channelCount; i++) { - flowPlane[i] = GetPointFlow(dec, i, loc, dmtxNeighborNone); - if(i > 0 && flowPlane[i].mag > flowPlane[strongIdx].mag) - strongIdx = i; - } - - if(flowPlane[strongIdx].mag < 10) - return dmtxBlankEdge; - - flow = flowPlane[strongIdx]; - - flowPos = FindStrongestNeighbor(dec, flow, +1); - flowNeg = FindStrongestNeighbor(dec, flow, -1); - if(flowPos.mag != 0 && flowNeg.mag != 0) { - flowPosBack = FindStrongestNeighbor(dec, flowPos, -1); - flowNegBack = FindStrongestNeighbor(dec, flowNeg, +1); - if(flowPos.arrive == (flowPosBack.arrive+4)%8 && - flowNeg.arrive == (flowNegBack.arrive+4)%8) { - flow.arrive = dmtxNeighborNone; - CALLBACK_POINT_PLOT(flow.loc, 1, 1, 1); - return flow; - } - } - - return dmtxBlankEdge; + int i; + int strongIdx; + int channelCount; + DmtxPointFlow flow, flowPlane[3]; + DmtxPointFlow flowPos, flowPosBack; + DmtxPointFlow flowNeg, flowNegBack; + + channelCount = dec->image->channelCount; + + /* Find whether red, green, or blue shows the strongest edge */ + strongIdx = 0; + for (i = 0; i < channelCount; i++) + { + flowPlane[i] = GetPointFlow(dec, i, loc, dmtxNeighborNone); + if (i > 0 && flowPlane[i].mag > flowPlane[strongIdx].mag) + strongIdx = i; + } + + if (flowPlane[strongIdx].mag < 10) + return dmtxBlankEdge; + + flow = flowPlane[strongIdx]; + + flowPos = FindStrongestNeighbor(dec, flow, +1); + flowNeg = FindStrongestNeighbor(dec, flow, -1); + if (flowPos.mag != 0 && flowNeg.mag != 0) + { + flowPosBack = FindStrongestNeighbor(dec, flowPos, -1); + flowNegBack = FindStrongestNeighbor(dec, flowNeg, +1); + if (flowPos.arrive == (flowPosBack.arrive + 4) % 8 && + flowNeg.arrive == (flowNegBack.arrive + 4) % 8) + { + flow.arrive = dmtxNeighborNone; + CALLBACK_POINT_PLOT(flow.loc, 1, 1, 1); + return flow; + } + } + + return dmtxBlankEdge; } /** @@ -197,160 +201,173 @@ MatrixRegionSeekEdge(DmtxDecode *dec, DmtxPixelLoc loc) static DmtxPassFail MatrixRegionOrientation(DmtxDecode *dec, DmtxRegion *reg, DmtxPointFlow begin) { - int cross; - int minArea; - int scale; - int symbolShape; - int maxDiagonal; - DmtxPassFail err; - DmtxBestLine line1x, line2x; - DmtxBestLine line2n, line2p; - DmtxFollow fTmp; - - if(dec->sizeIdxExpected == DmtxSymbolSquareAuto || - (dec->sizeIdxExpected >= DmtxSymbol10x10 && + int cross; + int minArea; + int scale; + int symbolShape; + int maxDiagonal; + DmtxPassFail err; + DmtxBestLine line1x, line2x; + DmtxBestLine line2n, line2p; + DmtxFollow fTmp; + + if (dec->sizeIdxExpected == DmtxSymbolSquareAuto || + (dec->sizeIdxExpected >= DmtxSymbol10x10 && dec->sizeIdxExpected <= DmtxSymbol144x144)) - symbolShape = DmtxSymbolSquareAuto; - else if(dec->sizeIdxExpected == DmtxSymbolRectAuto || - (dec->sizeIdxExpected >= DmtxSymbol8x18 && - dec->sizeIdxExpected <= DmtxSymbol16x48)) - symbolShape = DmtxSymbolRectAuto; - else - symbolShape = DmtxSymbolShapeAuto; - - if(dec->edgeMax != DmtxUndefined) { - if(symbolShape == DmtxSymbolRectAuto) - maxDiagonal = (int)(1.23 * dec->edgeMax + 0.5); /* sqrt(5/4) + 10% */ - else - maxDiagonal = (int)(1.56 * dec->edgeMax + 0.5); /* sqrt(2) + 10% */ - } - else { - maxDiagonal = DmtxUndefined; - } - - /* Follow to end in both directions */ - err = TrailBlazeContinuous(dec, reg, begin, maxDiagonal); - if(err == DmtxFail || reg->stepsTotal < 40) { - TrailClear(dec, reg, 0x40); - return DmtxFail; - } - - /* Filter out region candidates that are smaller than expected */ - if(dec->edgeMin != DmtxUndefined) { - scale = dmtxDecodeGetProp(dec, DmtxPropScale); - - if(symbolShape == DmtxSymbolSquareAuto) - minArea = (dec->edgeMin * dec->edgeMin)/(scale * scale); - else - minArea = (2 * dec->edgeMin * dec->edgeMin)/(scale * scale); - - if((reg->boundMax.X - reg->boundMin.X) * (reg->boundMax.Y - reg->boundMin.Y) < minArea) { - TrailClear(dec, reg, 0x40); - return DmtxFail; - } - } - - line1x = FindBestSolidLine(dec, reg, 0, 0, +1, DmtxUndefined); - if(line1x.mag < 5) { - TrailClear(dec, reg, 0x40); - return DmtxFail; - } - - err = FindTravelLimits(dec, reg, &line1x); - if(line1x.distSq < 100 || line1x.devn * 10 >= sqrt((double)line1x.distSq)) { - TrailClear(dec, reg, 0x40); - return DmtxFail; - } - assert(line1x.stepPos >= line1x.stepNeg); - - fTmp = FollowSeek(dec, reg, line1x.stepPos + 5); - line2p = FindBestSolidLine(dec, reg, fTmp.step, line1x.stepNeg, +1, line1x.angle); - - fTmp = FollowSeek(dec, reg, line1x.stepNeg - 5); - line2n = FindBestSolidLine(dec, reg, fTmp.step, line1x.stepPos, -1, line1x.angle); - if(max(line2p.mag, line2n.mag) < 5) - return DmtxFail; - - if(line2p.mag > line2n.mag) { - line2x = line2p; - err = FindTravelLimits(dec, reg, &line2x); - if(line2x.distSq < 100 || line2x.devn * 10 >= sqrt((double)line2x.distSq)) - return DmtxFail; - - cross = ((line1x.locPos.X - line1x.locNeg.X) * (line2x.locPos.Y - line2x.locNeg.Y)) - - ((line1x.locPos.Y - line1x.locNeg.Y) * (line2x.locPos.X - line2x.locNeg.X)); - if(cross > 0) { - /* Condition 2 */ - reg->polarity = +1; - reg->locR = line2x.locPos; - reg->stepR = line2x.stepPos; - reg->locT = line1x.locNeg; - reg->stepT = line1x.stepNeg; - reg->leftLoc = line1x.locBeg; - reg->leftAngle = line1x.angle; - reg->bottomLoc = line2x.locBeg; - reg->bottomAngle = line2x.angle; - reg->leftLine = line1x; - reg->bottomLine = line2x; - } - else { - /* Condition 3 */ - reg->polarity = -1; - reg->locR = line1x.locNeg; - reg->stepR = line1x.stepNeg; - reg->locT = line2x.locPos; - reg->stepT = line2x.stepPos; - reg->leftLoc = line2x.locBeg; - reg->leftAngle = line2x.angle; - reg->bottomLoc = line1x.locBeg; - reg->bottomAngle = line1x.angle; - reg->leftLine = line2x; - reg->bottomLine = line1x; - } - } - else { - line2x = line2n; - err = FindTravelLimits(dec, reg, &line2x); - if(line2x.distSq < 100 || line2x.devn / sqrt((double)line2x.distSq) >= 0.1) - return DmtxFail; - - cross = ((line1x.locNeg.X - line1x.locPos.X) * (line2x.locNeg.Y - line2x.locPos.Y)) - - ((line1x.locNeg.Y - line1x.locPos.Y) * (line2x.locNeg.X - line2x.locPos.X)); - if(cross > 0) { - /* Condition 1 */ - reg->polarity = -1; - reg->locR = line2x.locNeg; - reg->stepR = line2x.stepNeg; - reg->locT = line1x.locPos; - reg->stepT = line1x.stepPos; - reg->leftLoc = line1x.locBeg; - reg->leftAngle = line1x.angle; - reg->bottomLoc = line2x.locBeg; - reg->bottomAngle = line2x.angle; - reg->leftLine = line1x; - reg->bottomLine = line2x; - } - else { - /* Condition 4 */ - reg->polarity = +1; - reg->locR = line1x.locPos; - reg->stepR = line1x.stepPos; - reg->locT = line2x.locNeg; - reg->stepT = line2x.stepNeg; - reg->leftLoc = line2x.locBeg; - reg->leftAngle = line2x.angle; - reg->bottomLoc = line1x.locBeg; - reg->bottomAngle = line1x.angle; - reg->leftLine = line2x; - reg->bottomLine = line1x; - } - } -/* CALLBACK_POINT_PLOT(reg->locR, 2, 1, 1); - CALLBACK_POINT_PLOT(reg->locT, 2, 1, 1); */ - - reg->leftKnown = reg->bottomKnown = 1; - - return DmtxPass; + symbolShape = DmtxSymbolSquareAuto; + else if (dec->sizeIdxExpected == DmtxSymbolRectAuto || + (dec->sizeIdxExpected >= DmtxSymbol8x18 && + dec->sizeIdxExpected <= DmtxSymbol16x48)) + symbolShape = DmtxSymbolRectAuto; + else + symbolShape = DmtxSymbolShapeAuto; + + if (dec->edgeMax != DmtxUndefined) + { + if (symbolShape == DmtxSymbolRectAuto) + maxDiagonal = (int)(1.23 * dec->edgeMax + 0.5); /* sqrt(5/4) + 10% */ + else + maxDiagonal = (int)(1.56 * dec->edgeMax + 0.5); /* sqrt(2) + 10% */ + } + else + { + maxDiagonal = DmtxUndefined; + } + + /* Follow to end in both directions */ + err = TrailBlazeContinuous(dec, reg, begin, maxDiagonal); + if (err == DmtxFail || reg->stepsTotal < 40) + { + TrailClear(dec, reg, 0x40); + return DmtxFail; + } + + /* Filter out region candidates that are smaller than expected */ + if (dec->edgeMin != DmtxUndefined) + { + scale = dmtxDecodeGetProp(dec, DmtxPropScale); + + if (symbolShape == DmtxSymbolSquareAuto) + minArea = (dec->edgeMin * dec->edgeMin) / (scale * scale); + else + minArea = (2 * dec->edgeMin * dec->edgeMin) / (scale * scale); + + if ((reg->boundMax.X - reg->boundMin.X) * (reg->boundMax.Y - reg->boundMin.Y) < minArea) + { + TrailClear(dec, reg, 0x40); + return DmtxFail; + } + } + + line1x = FindBestSolidLine(dec, reg, 0, 0, +1, DmtxUndefined); + if (line1x.mag < 5) + { + TrailClear(dec, reg, 0x40); + return DmtxFail; + } + + err = FindTravelLimits(dec, reg, &line1x); + if (line1x.distSq < 100 || line1x.devn * 10 >= sqrt((double)line1x.distSq)) + { + TrailClear(dec, reg, 0x40); + return DmtxFail; + } + assert(line1x.stepPos >= line1x.stepNeg); + + fTmp = FollowSeek(dec, reg, line1x.stepPos + 5); + line2p = FindBestSolidLine(dec, reg, fTmp.step, line1x.stepNeg, +1, line1x.angle); + + fTmp = FollowSeek(dec, reg, line1x.stepNeg - 5); + line2n = FindBestSolidLine(dec, reg, fTmp.step, line1x.stepPos, -1, line1x.angle); + if (max(line2p.mag, line2n.mag) < 5) + return DmtxFail; + + if (line2p.mag > line2n.mag) + { + line2x = line2p; + err = FindTravelLimits(dec, reg, &line2x); + if (line2x.distSq < 100 || line2x.devn * 10 >= sqrt((double)line2x.distSq)) + return DmtxFail; + + cross = ((line1x.locPos.X - line1x.locNeg.X) * (line2x.locPos.Y - line2x.locNeg.Y)) - + ((line1x.locPos.Y - line1x.locNeg.Y) * (line2x.locPos.X - line2x.locNeg.X)); + if (cross > 0) + { + /* Condition 2 */ + reg->polarity = +1; + reg->locR = line2x.locPos; + reg->stepR = line2x.stepPos; + reg->locT = line1x.locNeg; + reg->stepT = line1x.stepNeg; + reg->leftLoc = line1x.locBeg; + reg->leftAngle = line1x.angle; + reg->bottomLoc = line2x.locBeg; + reg->bottomAngle = line2x.angle; + reg->leftLine = line1x; + reg->bottomLine = line2x; + } + else + { + /* Condition 3 */ + reg->polarity = -1; + reg->locR = line1x.locNeg; + reg->stepR = line1x.stepNeg; + reg->locT = line2x.locPos; + reg->stepT = line2x.stepPos; + reg->leftLoc = line2x.locBeg; + reg->leftAngle = line2x.angle; + reg->bottomLoc = line1x.locBeg; + reg->bottomAngle = line1x.angle; + reg->leftLine = line2x; + reg->bottomLine = line1x; + } + } + else + { + line2x = line2n; + err = FindTravelLimits(dec, reg, &line2x); + if (line2x.distSq < 100 || line2x.devn / sqrt((double)line2x.distSq) >= 0.1) + return DmtxFail; + + cross = ((line1x.locNeg.X - line1x.locPos.X) * (line2x.locNeg.Y - line2x.locPos.Y)) - + ((line1x.locNeg.Y - line1x.locPos.Y) * (line2x.locNeg.X - line2x.locPos.X)); + if (cross > 0) + { + /* Condition 1 */ + reg->polarity = -1; + reg->locR = line2x.locNeg; + reg->stepR = line2x.stepNeg; + reg->locT = line1x.locPos; + reg->stepT = line1x.stepPos; + reg->leftLoc = line1x.locBeg; + reg->leftAngle = line1x.angle; + reg->bottomLoc = line2x.locBeg; + reg->bottomAngle = line2x.angle; + reg->leftLine = line1x; + reg->bottomLine = line2x; + } + else + { + /* Condition 4 */ + reg->polarity = +1; + reg->locR = line1x.locPos; + reg->stepR = line1x.stepPos; + reg->locT = line2x.locNeg; + reg->stepT = line2x.stepNeg; + reg->leftLoc = line2x.locBeg; + reg->leftAngle = line2x.angle; + reg->bottomLoc = line1x.locBeg; + reg->bottomAngle = line1x.angle; + reg->leftLine = line2x; + reg->bottomLine = line1x; + } + } + /* CALLBACK_POINT_PLOT(reg->locR, 2, 1, 1); + CALLBACK_POINT_PLOT(reg->locT, 2, 1, 1); */ + + reg->leftKnown = reg->bottomKnown = 1; + + return DmtxPass; } /** @@ -360,12 +377,12 @@ MatrixRegionOrientation(DmtxDecode *dec, DmtxRegion *reg, DmtxPointFlow begin) static long DistanceSquared(DmtxPixelLoc a, DmtxPixelLoc b) { - long xDelta, yDelta; + long xDelta, yDelta; - xDelta = a.X - b.X; - yDelta = a.Y - b.Y; + xDelta = a.X - b.X; + yDelta = a.Y - b.Y; - return (xDelta * xDelta) + (yDelta * yDelta); + return (xDelta * xDelta) + (yDelta * yDelta); } /** @@ -374,101 +391,101 @@ DistanceSquared(DmtxPixelLoc a, DmtxPixelLoc b) */ extern DmtxPassFail dmtxRegionUpdateCorners(DmtxDecode *dec, DmtxRegion *reg, DmtxVector2 p00, - DmtxVector2 p10, DmtxVector2 p11, DmtxVector2 p01) + DmtxVector2 p10, DmtxVector2 p11, DmtxVector2 p01) { - double xMax, yMax; - double tx, ty, phi, shx, scx, scy, skx, sky; - double dimOT, dimOR, dimTX, dimRX, ratio; - DmtxVector2 vOT, vOR, vTX, vRX, vTmp; - DmtxMatrix3 m, mtxy, mphi, mshx, mscx, mscy, mscxy, msky, mskx; - - xMax = (double)(dmtxDecodeGetProp(dec, DmtxPropWidth) - 1); - yMax = (double)(dmtxDecodeGetProp(dec, DmtxPropHeight) - 1); - - if(p00.X < 0.0 || p00.Y < 0.0 || p00.X > xMax || p00.Y > yMax || - p01.X < 0.0 || p01.Y < 0.0 || p01.X > xMax || p01.Y > yMax || - p10.X < 0.0 || p10.Y < 0.0 || p10.X > xMax || p10.Y > yMax) - return DmtxFail; - - dimOT = dmtxVector2Mag(dmtxVector2Sub(&vOT, &p01, &p00)); /* XXX could use MagSquared() */ - dimOR = dmtxVector2Mag(dmtxVector2Sub(&vOR, &p10, &p00)); - dimTX = dmtxVector2Mag(dmtxVector2Sub(&vTX, &p11, &p01)); - dimRX = dmtxVector2Mag(dmtxVector2Sub(&vRX, &p11, &p10)); - - /* Verify that sides are reasonably long */ - if(dimOT <= 8.0 || dimOR <= 8.0 || dimTX <= 8.0 || dimRX <= 8.0) - return DmtxFail; - - /* Verify that the 4 corners define a reasonably fat quadrilateral */ - ratio = dimOT / dimRX; - if(ratio <= 0.5 || ratio >= 2.0) - return DmtxFail; - - ratio = dimOR / dimTX; - if(ratio <= 0.5 || ratio >= 2.0) - return DmtxFail; - - /* Verify this is not a bowtie shape */ - if(dmtxVector2Cross(&vOR, &vRX) <= 0.0 || - dmtxVector2Cross(&vOT, &vTX) >= 0.0) - return DmtxFail; - - if(RightAngleTrueness(p00, p10, p11, M_PI_2) <= dec->squareDevn) - return DmtxFail; - if(RightAngleTrueness(p10, p11, p01, M_PI_2) <= dec->squareDevn) - return DmtxFail; - - /* Calculate values needed for transformations */ - tx = -1 * p00.X; - ty = -1 * p00.Y; - dmtxMatrix3Translate(mtxy, tx, ty); - - phi = atan2(vOT.X, vOT.Y); - dmtxMatrix3Rotate(mphi, phi); - dmtxMatrix3Multiply(m, mtxy, mphi); - - dmtxMatrix3VMultiply(&vTmp, &p10, m); - shx = -vTmp.Y / vTmp.X; - dmtxMatrix3Shear(mshx, 0.0, shx); - dmtxMatrix3MultiplyBy(m, mshx); - - scx = 1.0/vTmp.X; - dmtxMatrix3Scale(mscx, scx, 1.0); - dmtxMatrix3MultiplyBy(m, mscx); - - dmtxMatrix3VMultiply(&vTmp, &p11, m); - scy = 1.0/vTmp.Y; - dmtxMatrix3Scale(mscy, 1.0, scy); - dmtxMatrix3MultiplyBy(m, mscy); - - dmtxMatrix3VMultiply(&vTmp, &p11, m); - skx = vTmp.X; - dmtxMatrix3LineSkewSide(mskx, 1.0, skx, 1.0); - dmtxMatrix3MultiplyBy(m, mskx); - - dmtxMatrix3VMultiply(&vTmp, &p01, m); - sky = vTmp.Y; - dmtxMatrix3LineSkewTop(msky, sky, 1.0, 1.0); - dmtxMatrix3Multiply(reg->raw2fit, m, msky); - - /* Create inverse matrix by reverse (avoid straight matrix inversion) */ - dmtxMatrix3LineSkewTopInv(msky, sky, 1.0, 1.0); - dmtxMatrix3LineSkewSideInv(mskx, 1.0, skx, 1.0); - dmtxMatrix3Multiply(m, msky, mskx); - - dmtxMatrix3Scale(mscxy, 1.0/scx, 1.0/scy); - dmtxMatrix3MultiplyBy(m, mscxy); - - dmtxMatrix3Shear(mshx, 0.0, -shx); - dmtxMatrix3MultiplyBy(m, mshx); - - dmtxMatrix3Rotate(mphi, -phi); - dmtxMatrix3MultiplyBy(m, mphi); - - dmtxMatrix3Translate(mtxy, -tx, -ty); - dmtxMatrix3Multiply(reg->fit2raw, m, mtxy); - - return DmtxPass; + double xMax, yMax; + double tx, ty, phi, shx, scx, scy, skx, sky; + double dimOT, dimOR, dimTX, dimRX, ratio; + DmtxVector2 vOT, vOR, vTX, vRX, vTmp; + DmtxMatrix3 m, mtxy, mphi, mshx, mscx, mscy, mscxy, msky, mskx; + + xMax = (double)(dmtxDecodeGetProp(dec, DmtxPropWidth) - 1); + yMax = (double)(dmtxDecodeGetProp(dec, DmtxPropHeight) - 1); + + if (p00.X < 0.0 || p00.Y < 0.0 || p00.X > xMax || p00.Y > yMax || + p01.X < 0.0 || p01.Y < 0.0 || p01.X > xMax || p01.Y > yMax || + p10.X < 0.0 || p10.Y < 0.0 || p10.X > xMax || p10.Y > yMax) + return DmtxFail; + + dimOT = dmtxVector2Mag(dmtxVector2Sub(&vOT, &p01, &p00)); /* XXX could use MagSquared() */ + dimOR = dmtxVector2Mag(dmtxVector2Sub(&vOR, &p10, &p00)); + dimTX = dmtxVector2Mag(dmtxVector2Sub(&vTX, &p11, &p01)); + dimRX = dmtxVector2Mag(dmtxVector2Sub(&vRX, &p11, &p10)); + + /* Verify that sides are reasonably long */ + if (dimOT <= 8.0 || dimOR <= 8.0 || dimTX <= 8.0 || dimRX <= 8.0) + return DmtxFail; + + /* Verify that the 4 corners define a reasonably fat quadrilateral */ + ratio = dimOT / dimRX; + if (ratio <= 0.5 || ratio >= 2.0) + return DmtxFail; + + ratio = dimOR / dimTX; + if (ratio <= 0.5 || ratio >= 2.0) + return DmtxFail; + + /* Verify this is not a bowtie shape */ + if (dmtxVector2Cross(&vOR, &vRX) <= 0.0 || + dmtxVector2Cross(&vOT, &vTX) >= 0.0) + return DmtxFail; + + if (RightAngleTrueness(p00, p10, p11, M_PI_2) <= dec->squareDevn) + return DmtxFail; + if (RightAngleTrueness(p10, p11, p01, M_PI_2) <= dec->squareDevn) + return DmtxFail; + + /* Calculate values needed for transformations */ + tx = -1 * p00.X; + ty = -1 * p00.Y; + dmtxMatrix3Translate(mtxy, tx, ty); + + phi = atan2(vOT.X, vOT.Y); + dmtxMatrix3Rotate(mphi, phi); + dmtxMatrix3Multiply(m, mtxy, mphi); + + dmtxMatrix3VMultiply(&vTmp, &p10, m); + shx = -vTmp.Y / vTmp.X; + dmtxMatrix3Shear(mshx, 0.0, shx); + dmtxMatrix3MultiplyBy(m, mshx); + + scx = 1.0 / vTmp.X; + dmtxMatrix3Scale(mscx, scx, 1.0); + dmtxMatrix3MultiplyBy(m, mscx); + + dmtxMatrix3VMultiply(&vTmp, &p11, m); + scy = 1.0 / vTmp.Y; + dmtxMatrix3Scale(mscy, 1.0, scy); + dmtxMatrix3MultiplyBy(m, mscy); + + dmtxMatrix3VMultiply(&vTmp, &p11, m); + skx = vTmp.X; + dmtxMatrix3LineSkewSide(mskx, 1.0, skx, 1.0); + dmtxMatrix3MultiplyBy(m, mskx); + + dmtxMatrix3VMultiply(&vTmp, &p01, m); + sky = vTmp.Y; + dmtxMatrix3LineSkewTop(msky, sky, 1.0, 1.0); + dmtxMatrix3Multiply(reg->raw2fit, m, msky); + + /* Create inverse matrix by reverse (avoid straight matrix inversion) */ + dmtxMatrix3LineSkewTopInv(msky, sky, 1.0, 1.0); + dmtxMatrix3LineSkewSideInv(mskx, 1.0, skx, 1.0); + dmtxMatrix3Multiply(m, msky, mskx); + + dmtxMatrix3Scale(mscxy, 1.0 / scx, 1.0 / scy); + dmtxMatrix3MultiplyBy(m, mscxy); + + dmtxMatrix3Shear(mshx, 0.0, -shx); + dmtxMatrix3MultiplyBy(m, mshx); + + dmtxMatrix3Rotate(mphi, -phi); + dmtxMatrix3MultiplyBy(m, mphi); + + dmtxMatrix3Translate(mtxy, -tx, -ty); + dmtxMatrix3Multiply(reg->fit2raw, m, mtxy); + + return DmtxPass; } /** @@ -478,87 +495,91 @@ dmtxRegionUpdateCorners(DmtxDecode *dec, DmtxRegion *reg, DmtxVector2 p00, extern DmtxPassFail dmtxRegionUpdateXfrms(DmtxDecode *dec, DmtxRegion *reg) { - double radians; - DmtxRay2 rLeft, rBottom, rTop, rRight; - DmtxVector2 p00, p10, p11, p01; - - assert(reg->leftKnown != 0 && reg->bottomKnown != 0); - - /* Build ray representing left edge */ - rLeft.p.X = (double)reg->leftLoc.X; - rLeft.p.Y = (double)reg->leftLoc.Y; - radians = reg->leftAngle * (M_PI/DMTX_HOUGH_RES); - rLeft.v.X = cos(radians); - rLeft.v.Y = sin(radians); - rLeft.tMin = 0.0; - rLeft.tMax = dmtxVector2Norm(&rLeft.v); - - /* Build ray representing bottom edge */ - rBottom.p.X = (double)reg->bottomLoc.X; - rBottom.p.Y = (double)reg->bottomLoc.Y; - radians = reg->bottomAngle * (M_PI/DMTX_HOUGH_RES); - rBottom.v.X = cos(radians); - rBottom.v.Y = sin(radians); - rBottom.tMin = 0.0; - rBottom.tMax = dmtxVector2Norm(&rBottom.v); - - /* Build ray representing top edge */ - if(reg->topKnown != 0) { - rTop.p.X = (double)reg->topLoc.X; - rTop.p.Y = (double)reg->topLoc.Y; - radians = reg->topAngle * (M_PI/DMTX_HOUGH_RES); - rTop.v.X = cos(radians); - rTop.v.Y = sin(radians); - rTop.tMin = 0.0; - rTop.tMax = dmtxVector2Norm(&rTop.v); - } - else { - rTop.p.X = (double)reg->locT.X; - rTop.p.Y = (double)reg->locT.Y; - radians = reg->bottomAngle * (M_PI/DMTX_HOUGH_RES); - rTop.v.X = cos(radians); - rTop.v.Y = sin(radians); - rTop.tMin = 0.0; - rTop.tMax = rBottom.tMax; - } - - /* Build ray representing right edge */ - if(reg->rightKnown != 0) { - rRight.p.X = (double)reg->rightLoc.X; - rRight.p.Y = (double)reg->rightLoc.Y; - radians = reg->rightAngle * (M_PI/DMTX_HOUGH_RES); - rRight.v.X = cos(radians); - rRight.v.Y = sin(radians); - rRight.tMin = 0.0; - rRight.tMax = dmtxVector2Norm(&rRight.v); - } - else { - rRight.p.X = (double)reg->locR.X; - rRight.p.Y = (double)reg->locR.Y; - radians = reg->leftAngle * (M_PI/DMTX_HOUGH_RES); - rRight.v.X = cos(radians); - rRight.v.Y = sin(radians); - rRight.tMin = 0.0; - rRight.tMax = rLeft.tMax; - } - - /* Calculate 4 corners, real or imagined */ - if(dmtxRay2Intersect(&p00, &rLeft, &rBottom) == DmtxFail) - return DmtxFail; - - if(dmtxRay2Intersect(&p10, &rBottom, &rRight) == DmtxFail) - return DmtxFail; - - if(dmtxRay2Intersect(&p11, &rRight, &rTop) == DmtxFail) - return DmtxFail; - - if(dmtxRay2Intersect(&p01, &rTop, &rLeft) == DmtxFail) - return DmtxFail; - - if(dmtxRegionUpdateCorners(dec, reg, p00, p10, p11, p01) != DmtxPass) - return DmtxFail; - - return DmtxPass; + double radians; + DmtxRay2 rLeft, rBottom, rTop, rRight; + DmtxVector2 p00, p10, p11, p01; + + assert(reg->leftKnown != 0 && reg->bottomKnown != 0); + + /* Build ray representing left edge */ + rLeft.p.X = (double)reg->leftLoc.X; + rLeft.p.Y = (double)reg->leftLoc.Y; + radians = reg->leftAngle * (M_PI / DMTX_HOUGH_RES); + rLeft.v.X = cos(radians); + rLeft.v.Y = sin(radians); + rLeft.tMin = 0.0; + rLeft.tMax = dmtxVector2Norm(&rLeft.v); + + /* Build ray representing bottom edge */ + rBottom.p.X = (double)reg->bottomLoc.X; + rBottom.p.Y = (double)reg->bottomLoc.Y; + radians = reg->bottomAngle * (M_PI / DMTX_HOUGH_RES); + rBottom.v.X = cos(radians); + rBottom.v.Y = sin(radians); + rBottom.tMin = 0.0; + rBottom.tMax = dmtxVector2Norm(&rBottom.v); + + /* Build ray representing top edge */ + if (reg->topKnown != 0) + { + rTop.p.X = (double)reg->topLoc.X; + rTop.p.Y = (double)reg->topLoc.Y; + radians = reg->topAngle * (M_PI / DMTX_HOUGH_RES); + rTop.v.X = cos(radians); + rTop.v.Y = sin(radians); + rTop.tMin = 0.0; + rTop.tMax = dmtxVector2Norm(&rTop.v); + } + else + { + rTop.p.X = (double)reg->locT.X; + rTop.p.Y = (double)reg->locT.Y; + radians = reg->bottomAngle * (M_PI / DMTX_HOUGH_RES); + rTop.v.X = cos(radians); + rTop.v.Y = sin(radians); + rTop.tMin = 0.0; + rTop.tMax = rBottom.tMax; + } + + /* Build ray representing right edge */ + if (reg->rightKnown != 0) + { + rRight.p.X = (double)reg->rightLoc.X; + rRight.p.Y = (double)reg->rightLoc.Y; + radians = reg->rightAngle * (M_PI / DMTX_HOUGH_RES); + rRight.v.X = cos(radians); + rRight.v.Y = sin(radians); + rRight.tMin = 0.0; + rRight.tMax = dmtxVector2Norm(&rRight.v); + } + else + { + rRight.p.X = (double)reg->locR.X; + rRight.p.Y = (double)reg->locR.Y; + radians = reg->leftAngle * (M_PI / DMTX_HOUGH_RES); + rRight.v.X = cos(radians); + rRight.v.Y = sin(radians); + rRight.tMin = 0.0; + rRight.tMax = rLeft.tMax; + } + + /* Calculate 4 corners, real or imagined */ + if (dmtxRay2Intersect(&p00, &rLeft, &rBottom) == DmtxFail) + return DmtxFail; + + if (dmtxRay2Intersect(&p10, &rBottom, &rRight) == DmtxFail) + return DmtxFail; + + if (dmtxRay2Intersect(&p11, &rRight, &rTop) == DmtxFail) + return DmtxFail; + + if (dmtxRay2Intersect(&p01, &rTop, &rLeft) == DmtxFail) + return DmtxFail; + + if (dmtxRegionUpdateCorners(dec, reg, p00, p10, p11, p01) != DmtxPass) + return DmtxFail; + + return DmtxPass; } /** @@ -568,16 +589,16 @@ dmtxRegionUpdateXfrms(DmtxDecode *dec, DmtxRegion *reg) static double RightAngleTrueness(DmtxVector2 c0, DmtxVector2 c1, DmtxVector2 c2, double angle) { - DmtxVector2 vA, vB; - DmtxMatrix3 m; + DmtxVector2 vA, vB; + DmtxMatrix3 m; - dmtxVector2Norm(dmtxVector2Sub(&vA, &c0, &c1)); - dmtxVector2Norm(dmtxVector2Sub(&vB, &c2, &c1)); + dmtxVector2Norm(dmtxVector2Sub(&vA, &c0, &c1)); + dmtxVector2Norm(dmtxVector2Sub(&vB, &c2, &c1)); - dmtxMatrix3Rotate(m, angle); - dmtxMatrix3VMultiplyBy(&vB, m); + dmtxMatrix3Rotate(m, angle); + dmtxMatrix3VMultiplyBy(&vB, m); - return dmtxVector2Dot(&vA, &vB); + return dmtxVector2Dot(&vA, &vB); } /** @@ -591,34 +612,35 @@ RightAngleTrueness(DmtxVector2 c0, DmtxVector2 c1, DmtxVector2 c2, double angle) */ static int ReadModuleColor(DmtxDecode *dec, DmtxRegion *reg, int symbolRow, int symbolCol, - int sizeIdx, int colorPlane) + int sizeIdx, int colorPlane) { - int i; - int symbolRows, symbolCols; - int color, colorTmp; - double sampleX[] = { 0.5, 0.4, 0.5, 0.6, 0.5 }; - double sampleY[] = { 0.5, 0.5, 0.4, 0.5, 0.6 }; - DmtxVector2 p; + int i; + int symbolRows, symbolCols; + int color, colorTmp; + double sampleX[] = {0.5, 0.4, 0.5, 0.6, 0.5}; + double sampleY[] = {0.5, 0.5, 0.4, 0.5, 0.6}; + DmtxVector2 p; - symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, sizeIdx); - symbolCols = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, sizeIdx); + symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, sizeIdx); + symbolCols = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, sizeIdx); - color = 0; - for(i = 0; i < 5; i++) { + color = 0; + for (i = 0; i < 5; i++) + { - p.X = (1.0/symbolCols) * (symbolCol + sampleX[i]); - p.Y = (1.0/symbolRows) * (symbolRow + sampleY[i]); + p.X = (1.0 / symbolCols) * (symbolCol + sampleX[i]); + p.Y = (1.0 / symbolRows) * (symbolRow + sampleY[i]); - dmtxMatrix3VMultiplyBy(&p, reg->fit2raw); + dmtxMatrix3VMultiplyBy(&p, reg->fit2raw); - //fprintf(stdout, "%dx%d\n", (int)(p.X + 0.5), (int)(p.Y + 0.5)); + // fprintf(stdout, "%dx%d\n", (int)(p.X + 0.5), (int)(p.Y + 0.5)); - dmtxDecodeGetPixelValue(dec, (int)(p.X + 0.5), (int)(p.Y + 0.5), - colorPlane, &colorTmp); - color += colorTmp; - } - //fprintf(stdout, "\n"); - return color/5; + dmtxDecodeGetPixelValue(dec, (int)(p.X + 0.5), (int)(p.Y + 0.5), + colorPlane, &colorTmp); + color += colorTmp; + } + // fprintf(stdout, "\n"); + return color / 5; } /** @@ -630,134 +652,142 @@ ReadModuleColor(DmtxDecode *dec, DmtxRegion *reg, int symbolRow, int symbolCol, static DmtxPassFail MatrixRegionFindSize(DmtxDecode *dec, DmtxRegion *reg) { - int row, col; - int sizeIdxBeg, sizeIdxEnd; - int sizeIdx, bestSizeIdx; - int symbolRows, symbolCols; - int jumpCount, errors; - int color; - int colorOnAvg, bestColorOnAvg; - int colorOffAvg, bestColorOffAvg; - int contrast, bestContrast; -// DmtxImage *img; - -// img = dec->image; - bestSizeIdx = DmtxUndefined; - bestContrast = 0; - bestColorOnAvg = bestColorOffAvg = 0; - - if(dec->sizeIdxExpected == DmtxSymbolShapeAuto) { - sizeIdxBeg = 0; - sizeIdxEnd = DmtxSymbolSquareCount + DmtxSymbolRectCount; - } - else if(dec->sizeIdxExpected == DmtxSymbolSquareAuto) { - sizeIdxBeg = 0; - sizeIdxEnd = DmtxSymbolSquareCount; - } - else if(dec->sizeIdxExpected == DmtxSymbolRectAuto) { - sizeIdxBeg = DmtxSymbolSquareCount; - sizeIdxEnd = DmtxSymbolSquareCount + DmtxSymbolRectCount; - } - else { - sizeIdxBeg = dec->sizeIdxExpected; - sizeIdxEnd = dec->sizeIdxExpected + 1; - } - - /* Test each barcode size to find best contrast in calibration modules */ - for(sizeIdx = sizeIdxBeg; sizeIdx < sizeIdxEnd; sizeIdx++) { - - symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, sizeIdx); - symbolCols = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, sizeIdx); - colorOnAvg = colorOffAvg = 0; - - /* Sum module colors along horizontal calibration bar */ - row = symbolRows - 1; - for(col = 0; col < symbolCols; col++) { - color = ReadModuleColor(dec, reg, row, col, sizeIdx, reg->flowBegin.plane); - if((col & 0x01) != 0x00) - colorOffAvg += color; - else - colorOnAvg += color; - } - - /* Sum module colors along vertical calibration bar */ - col = symbolCols - 1; - for(row = 0; row < symbolRows; row++) { - color = ReadModuleColor(dec, reg, row, col, sizeIdx, reg->flowBegin.plane); - if((row & 0x01) != 0x00) - colorOffAvg += color; - else - colorOnAvg += color; - } - - colorOnAvg = (colorOnAvg * 2)/(symbolRows + symbolCols); - colorOffAvg = (colorOffAvg * 2)/(symbolRows + symbolCols); - - contrast = abs(colorOnAvg - colorOffAvg); - if(contrast < 20) - continue; - - if(contrast > bestContrast) { - bestContrast = contrast; - bestSizeIdx = sizeIdx; - bestColorOnAvg = colorOnAvg; - bestColorOffAvg = colorOffAvg; - } - } - - /* If no sizes produced acceptable contrast then call it quits */ - if(bestSizeIdx == DmtxUndefined || bestContrast < 20) - return DmtxFail; - - reg->sizeIdx = bestSizeIdx; - reg->onColor = bestColorOnAvg; - reg->offColor = bestColorOffAvg; - - reg->symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, reg->sizeIdx); - reg->symbolCols = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, reg->sizeIdx); - reg->mappingRows = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, reg->sizeIdx); - reg->mappingCols = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, reg->sizeIdx); - - /* Tally jumps on horizontal calibration bar to verify sizeIdx */ - jumpCount = CountJumpTally(dec, reg, 0, reg->symbolRows - 1, DmtxDirRight); - errors = abs(1 + jumpCount - reg->symbolCols); - if(jumpCount < 0 || errors > 2) - return DmtxFail; - - /* Tally jumps on vertical calibration bar to verify sizeIdx */ - jumpCount = CountJumpTally(dec, reg, reg->symbolCols - 1, 0, DmtxDirUp); - errors = abs(1 + jumpCount - reg->symbolRows); - if(jumpCount < 0 || errors > 2) - return DmtxFail; - - /* Tally jumps on horizontal finder bar to verify sizeIdx */ - errors = CountJumpTally(dec, reg, 0, 0, DmtxDirRight); - if(jumpCount < 0 || errors > 2) - return DmtxFail; - - /* Tally jumps on vertical finder bar to verify sizeIdx */ - errors = CountJumpTally(dec, reg, 0, 0, DmtxDirUp); - if(errors < 0 || errors > 2) - return DmtxFail; - - /* Tally jumps on surrounding whitespace, else fail */ - errors = CountJumpTally(dec, reg, 0, -1, DmtxDirRight); - if(errors < 0 || errors > 2) - return DmtxFail; - - errors = CountJumpTally(dec, reg, -1, 0, DmtxDirUp); - if(errors < 0 || errors > 2) - return DmtxFail; - - errors = CountJumpTally(dec, reg, 0, reg->symbolRows, DmtxDirRight); - if(errors < 0 || errors > 2) - return DmtxFail; - - errors = CountJumpTally(dec, reg, reg->symbolCols, 0, DmtxDirUp); - if(errors < 0 || errors > 2) - return DmtxFail; - - return DmtxPass; + int row, col; + int sizeIdxBeg, sizeIdxEnd; + int sizeIdx, bestSizeIdx; + int symbolRows, symbolCols; + int jumpCount, errors; + int color; + int colorOnAvg, bestColorOnAvg; + int colorOffAvg, bestColorOffAvg; + int contrast, bestContrast; + // DmtxImage *img; + + // img = dec->image; + bestSizeIdx = DmtxUndefined; + bestContrast = 0; + bestColorOnAvg = bestColorOffAvg = 0; + + if (dec->sizeIdxExpected == DmtxSymbolShapeAuto) + { + sizeIdxBeg = 0; + sizeIdxEnd = DmtxSymbolSquareCount + DmtxSymbolRectCount; + } + else if (dec->sizeIdxExpected == DmtxSymbolSquareAuto) + { + sizeIdxBeg = 0; + sizeIdxEnd = DmtxSymbolSquareCount; + } + else if (dec->sizeIdxExpected == DmtxSymbolRectAuto) + { + sizeIdxBeg = DmtxSymbolSquareCount; + sizeIdxEnd = DmtxSymbolSquareCount + DmtxSymbolRectCount; + } + else + { + sizeIdxBeg = dec->sizeIdxExpected; + sizeIdxEnd = dec->sizeIdxExpected + 1; + } + + /* Test each barcode size to find best contrast in calibration modules */ + for (sizeIdx = sizeIdxBeg; sizeIdx < sizeIdxEnd; sizeIdx++) + { + + symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, sizeIdx); + symbolCols = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, sizeIdx); + colorOnAvg = colorOffAvg = 0; + + /* Sum module colors along horizontal calibration bar */ + row = symbolRows - 1; + for (col = 0; col < symbolCols; col++) + { + color = ReadModuleColor(dec, reg, row, col, sizeIdx, reg->flowBegin.plane); + if ((col & 0x01) != 0x00) + colorOffAvg += color; + else + colorOnAvg += color; + } + + /* Sum module colors along vertical calibration bar */ + col = symbolCols - 1; + for (row = 0; row < symbolRows; row++) + { + color = ReadModuleColor(dec, reg, row, col, sizeIdx, reg->flowBegin.plane); + if ((row & 0x01) != 0x00) + colorOffAvg += color; + else + colorOnAvg += color; + } + + colorOnAvg = (colorOnAvg * 2) / (symbolRows + symbolCols); + colorOffAvg = (colorOffAvg * 2) / (symbolRows + symbolCols); + + contrast = abs(colorOnAvg - colorOffAvg); + if (contrast < 20) + continue; + + if (contrast > bestContrast) + { + bestContrast = contrast; + bestSizeIdx = sizeIdx; + bestColorOnAvg = colorOnAvg; + bestColorOffAvg = colorOffAvg; + } + } + + /* If no sizes produced acceptable contrast then call it quits */ + if (bestSizeIdx == DmtxUndefined || bestContrast < 20) + return DmtxFail; + + reg->sizeIdx = bestSizeIdx; + reg->onColor = bestColorOnAvg; + reg->offColor = bestColorOffAvg; + + reg->symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, reg->sizeIdx); + reg->symbolCols = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, reg->sizeIdx); + reg->mappingRows = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, reg->sizeIdx); + reg->mappingCols = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, reg->sizeIdx); + + /* Tally jumps on horizontal calibration bar to verify sizeIdx */ + jumpCount = CountJumpTally(dec, reg, 0, reg->symbolRows - 1, DmtxDirRight); + errors = abs(1 + jumpCount - reg->symbolCols); + if (jumpCount < 0 || errors > 2) + return DmtxFail; + + /* Tally jumps on vertical calibration bar to verify sizeIdx */ + jumpCount = CountJumpTally(dec, reg, reg->symbolCols - 1, 0, DmtxDirUp); + errors = abs(1 + jumpCount - reg->symbolRows); + if (jumpCount < 0 || errors > 2) + return DmtxFail; + + /* Tally jumps on horizontal finder bar to verify sizeIdx */ + errors = CountJumpTally(dec, reg, 0, 0, DmtxDirRight); + if (jumpCount < 0 || errors > 2) + return DmtxFail; + + /* Tally jumps on vertical finder bar to verify sizeIdx */ + errors = CountJumpTally(dec, reg, 0, 0, DmtxDirUp); + if (errors < 0 || errors > 2) + return DmtxFail; + + /* Tally jumps on surrounding whitespace, else fail */ + errors = CountJumpTally(dec, reg, 0, -1, DmtxDirRight); + if (errors < 0 || errors > 2) + return DmtxFail; + + errors = CountJumpTally(dec, reg, -1, 0, DmtxDirUp); + if (errors < 0 || errors > 2) + return DmtxFail; + + errors = CountJumpTally(dec, reg, 0, reg->symbolRows, DmtxDirRight); + if (errors < 0 || errors > 2) + return DmtxFail; + + errors = CountJumpTally(dec, reg, reg->symbolCols, 0, DmtxDirUp); + if (errors < 0 || errors > 2) + return DmtxFail; + + return DmtxPass; } /** @@ -772,56 +802,61 @@ MatrixRegionFindSize(DmtxDecode *dec, DmtxRegion *reg) static int CountJumpTally(DmtxDecode *dec, DmtxRegion *reg, int xStart, int yStart, DmtxDirection dir) { - int x, xInc = 0; - int y, yInc = 0; - int state = DmtxModuleOn; - int jumpCount = 0; - int jumpThreshold; - int tModule, tPrev; - int darkOnLight; - int color; - - assert(xStart == 0 || yStart == 0); - assert(dir == DmtxDirRight || dir == DmtxDirUp); - - if(dir == DmtxDirRight) - xInc = 1; - else - yInc = 1; - - if(xStart == -1 || xStart == reg->symbolCols || - yStart == -1 || yStart == reg->symbolRows) - state = DmtxModuleOff; - - darkOnLight = (int)(reg->offColor > reg->onColor); - jumpThreshold = abs((int)(0.4 * (reg->onColor - reg->offColor) + 0.5)); - color = ReadModuleColor(dec, reg, yStart, xStart, reg->sizeIdx, reg->flowBegin.plane); - tModule = (darkOnLight) ? reg->offColor - color : color - reg->offColor; - - for(x = xStart + xInc, y = yStart + yInc; + int x, xInc = 0; + int y, yInc = 0; + int state = DmtxModuleOn; + int jumpCount = 0; + int jumpThreshold; + int tModule, tPrev; + int darkOnLight; + int color; + + assert(xStart == 0 || yStart == 0); + assert(dir == DmtxDirRight || dir == DmtxDirUp); + + if (dir == DmtxDirRight) + xInc = 1; + else + yInc = 1; + + if (xStart == -1 || xStart == reg->symbolCols || + yStart == -1 || yStart == reg->symbolRows) + state = DmtxModuleOff; + + darkOnLight = (int)(reg->offColor > reg->onColor); + jumpThreshold = abs((int)(0.4 * (reg->onColor - reg->offColor) + 0.5)); + color = ReadModuleColor(dec, reg, yStart, xStart, reg->sizeIdx, reg->flowBegin.plane); + tModule = (darkOnLight) ? reg->offColor - color : color - reg->offColor; + + for (x = xStart + xInc, y = yStart + yInc; (dir == DmtxDirRight && x < reg->symbolCols) || (dir == DmtxDirUp && y < reg->symbolRows); - x += xInc, y += yInc) { - - tPrev = tModule; - color = ReadModuleColor(dec, reg, y, x, reg->sizeIdx, reg->flowBegin.plane); - tModule = (darkOnLight) ? reg->offColor - color : color - reg->offColor; - - if(state == DmtxModuleOff) { - if(tModule > tPrev + jumpThreshold) { - jumpCount++; - state = DmtxModuleOn; - } - } - else { - if(tModule < tPrev - jumpThreshold) { - jumpCount++; - state = DmtxModuleOff; - } - } - } - - return jumpCount; + x += xInc, y += yInc) + { + + tPrev = tModule; + color = ReadModuleColor(dec, reg, y, x, reg->sizeIdx, reg->flowBegin.plane); + tModule = (darkOnLight) ? reg->offColor - color : color - reg->offColor; + + if (state == DmtxModuleOff) + { + if (tModule > tPrev + jumpThreshold) + { + jumpCount++; + state = DmtxModuleOn; + } + } + else + { + if (tModule < tPrev - jumpThreshold) + { + jumpCount++; + state = DmtxModuleOff; + } + } + } + + return jumpCount; } /** @@ -831,66 +866,70 @@ CountJumpTally(DmtxDecode *dec, DmtxRegion *reg, int xStart, int yStart, DmtxDir static DmtxPointFlow GetPointFlow(DmtxDecode *dec, int colorPlane, DmtxPixelLoc loc, int arrive) { - static const int coefficient[] = { 0, 1, 2, 1, 0, -1, -2, -1 }; - int err; - int patternIdx, coefficientIdx; - int compass, compassMax; - int mag[4] = { 0 }; - int xAdjust, yAdjust; - int color, colorPattern[8]; - DmtxPointFlow flow; - - for(patternIdx = 0; patternIdx < 8; patternIdx++) { - xAdjust = loc.X + dmtxPatternX[patternIdx]; - yAdjust = loc.Y + dmtxPatternY[patternIdx]; - err = dmtxDecodeGetPixelValue(dec, xAdjust, yAdjust, colorPlane, - &colorPattern[patternIdx]); - if(err == DmtxFail) - return dmtxBlankEdge; - } - - /* Calculate this pixel's flow intensity for each direction (-45, 0, 45, 90) */ - compassMax = 0; - for(compass = 0; compass < 4; compass++) { - - /* Add portion from each position in the convolution matrix pattern */ - for(patternIdx = 0; patternIdx < 8; patternIdx++) { - - coefficientIdx = (patternIdx - compass + 8) % 8; - if(coefficient[coefficientIdx] == 0) - continue; + static const int coefficient[] = {0, 1, 2, 1, 0, -1, -2, -1}; + int err; + int patternIdx, coefficientIdx; + int compass, compassMax; + int mag[4] = {0}; + int xAdjust, yAdjust; + int color, colorPattern[8]; + DmtxPointFlow flow; + + for (patternIdx = 0; patternIdx < 8; patternIdx++) + { + xAdjust = loc.X + dmtxPatternX[patternIdx]; + yAdjust = loc.Y + dmtxPatternY[patternIdx]; + err = dmtxDecodeGetPixelValue(dec, xAdjust, yAdjust, colorPlane, + &colorPattern[patternIdx]); + if (err == DmtxFail) + return dmtxBlankEdge; + } + + /* Calculate this pixel's flow intensity for each direction (-45, 0, 45, 90) */ + compassMax = 0; + for (compass = 0; compass < 4; compass++) + { - color = colorPattern[patternIdx]; + /* Add portion from each position in the convolution matrix pattern */ + for (patternIdx = 0; patternIdx < 8; patternIdx++) + { - switch(coefficient[coefficientIdx]) { + coefficientIdx = (patternIdx - compass + 8) % 8; + if (coefficient[coefficientIdx] == 0) + continue; + + color = colorPattern[patternIdx]; + + switch (coefficient[coefficientIdx]) + { case 2: - mag[compass] += color; - /* Fall through */ + mag[compass] += color; + /* Fall through */ case 1: - mag[compass] += color; - break; + mag[compass] += color; + break; case -2: - mag[compass] -= color; - /* Fall through */ + mag[compass] -= color; + /* Fall through */ case -1: - mag[compass] -= color; - break; - } - } - - /* Identify strongest compass flow */ - if(compass != 0 && abs(mag[compass]) > abs(mag[compassMax])) - compassMax = compass; - } - - /* Convert signed compass direction into unique flow directions (0-7) */ - flow.plane = colorPlane; - flow.arrive = arrive; - flow.depart = (mag[compassMax] > 0) ? compassMax + 4 : compassMax; - flow.mag = abs(mag[compassMax]); - flow.loc = loc; - - return flow; + mag[compass] -= color; + break; + } + } + + /* Identify strongest compass flow */ + if (compass != 0 && abs(mag[compass]) > abs(mag[compassMax])) + compassMax = compass; + } + + /* Convert signed compass direction into unique flow directions (0-7) */ + flow.plane = colorPlane; + flow.arrive = arrive; + flow.depart = (mag[compassMax] > 0) ? compassMax + 4 : compassMax; + flow.mag = abs(mag[compassMax]); + flow.loc = loc; + + return flow; } /** @@ -900,49 +939,52 @@ GetPointFlow(DmtxDecode *dec, int colorPlane, DmtxPixelLoc loc, int arrive) static DmtxPointFlow FindStrongestNeighbor(DmtxDecode *dec, DmtxPointFlow center, int sign) { - int i; - int strongIdx; - int attempt, attemptDiff; - int occupied; - unsigned char *cache; - DmtxPixelLoc loc; - DmtxPointFlow flow[8]; - - attempt = (sign < 0) ? center.depart : (center.depart+4)%8; - - occupied = 0; - strongIdx = DmtxUndefined; - for(i = 0; i < 8; i++) { - - loc.X = center.loc.X + dmtxPatternX[i]; - loc.Y = center.loc.Y + dmtxPatternY[i]; + int i; + int strongIdx; + int attempt, attemptDiff; + int occupied; + unsigned char *cache; + DmtxPixelLoc loc; + DmtxPointFlow flow[8]; + + attempt = (sign < 0) ? center.depart : (center.depart + 4) % 8; + + occupied = 0; + strongIdx = DmtxUndefined; + for (i = 0; i < 8; i++) + { + + loc.X = center.loc.X + dmtxPatternX[i]; + loc.Y = center.loc.Y + dmtxPatternY[i]; + + cache = dmtxDecodeGetCache(dec, loc.X, loc.Y); + if (cache == NULL) + continue; - cache = dmtxDecodeGetCache(dec, loc.X, loc.Y); - if(cache == NULL) - continue; + if ((int)(*cache & 0x80) != 0x00) + { + if (++occupied > 2) + return dmtxBlankEdge; + else + continue; + } - if((int)(*cache & 0x80) != 0x00) { - if(++occupied > 2) - return dmtxBlankEdge; - else + attemptDiff = abs(attempt - i); + if (attemptDiff > 4) + attemptDiff = 8 - attemptDiff; + if (attemptDiff > 1) continue; - } - - attemptDiff = abs(attempt - i); - if(attemptDiff > 4) - attemptDiff = 8 - attemptDiff; - if(attemptDiff > 1) - continue; - flow[i] = GetPointFlow(dec, center.plane, loc, i); + flow[i] = GetPointFlow(dec, center.plane, loc, i); - if(strongIdx == DmtxUndefined || flow[i].mag > flow[strongIdx].mag || - (flow[i].mag == flow[strongIdx].mag && ((i & 0x01) != 0))) { - strongIdx = i; - } - } + if (strongIdx == DmtxUndefined || flow[i].mag > flow[strongIdx].mag || + (flow[i].mag == flow[strongIdx].mag && ((i & 0x01) != 0))) + { + strongIdx = i; + } + } - return (strongIdx == DmtxUndefined) ? dmtxBlankEdge : flow[strongIdx]; + return (strongIdx == DmtxUndefined) ? dmtxBlankEdge : flow[strongIdx]; } /** @@ -952,24 +994,25 @@ FindStrongestNeighbor(DmtxDecode *dec, DmtxPointFlow center, int sign) static DmtxFollow FollowSeek(DmtxDecode *dec, DmtxRegion *reg, int seek) { - int i; - int sign; - DmtxFollow follow; - - follow.loc = reg->flowBegin.loc; - follow.step = 0; - follow.ptr = dmtxDecodeGetCache(dec, follow.loc.X, follow.loc.Y); - assert(follow.ptr != NULL); - follow.neighbor = *follow.ptr; - - sign = (seek > 0) ? +1 : -1; - for(i = 0; i != seek; i += sign) { - follow = FollowStep(dec, reg, follow, sign); - assert(follow.ptr != NULL); - assert(abs(follow.step) <= reg->stepsTotal); - } - - return follow; + int i; + int sign; + DmtxFollow follow; + + follow.loc = reg->flowBegin.loc; + follow.step = 0; + follow.ptr = dmtxDecodeGetCache(dec, follow.loc.X, follow.loc.Y); + assert(follow.ptr != NULL); + follow.neighbor = *follow.ptr; + + sign = (seek > 0) ? +1 : -1; + for (i = 0; i != seek; i += sign) + { + follow = FollowStep(dec, reg, follow, sign); + assert(follow.ptr != NULL); + assert(abs(follow.step) <= reg->stepsTotal); + } + + return follow; } /** @@ -979,18 +1022,17 @@ FollowSeek(DmtxDecode *dec, DmtxRegion *reg, int seek) static DmtxFollow FollowSeekLoc(DmtxDecode *dec, DmtxPixelLoc loc) { - DmtxFollow follow; + DmtxFollow follow; - follow.loc = loc; - follow.step = 0; - follow.ptr = dmtxDecodeGetCache(dec, follow.loc.X, follow.loc.Y); - assert(follow.ptr != NULL); - follow.neighbor = *follow.ptr; + follow.loc = loc; + follow.step = 0; + follow.ptr = dmtxDecodeGetCache(dec, follow.loc.X, follow.loc.Y); + assert(follow.ptr != NULL); + follow.neighbor = *follow.ptr; - return follow; + return follow; } - /** * * @@ -998,41 +1040,44 @@ FollowSeekLoc(DmtxDecode *dec, DmtxPixelLoc loc) static DmtxFollow FollowStep(DmtxDecode *dec, DmtxRegion *reg, DmtxFollow followBeg, int sign) { - int patternIdx; - int stepMod; - int factor; - DmtxFollow follow; - - assert(abs(sign) == 1); - assert((int)(followBeg.neighbor & 0x40) != 0x00); - - factor = reg->stepsTotal + 1; - if(sign > 0) - stepMod = (factor + (followBeg.step % factor)) % factor; - else - stepMod = (factor - (followBeg.step % factor)) % factor; - - /* End of positive trail -- magic jump */ - if(sign > 0 && stepMod == reg->jumpToNeg) { - follow.loc = reg->finalNeg; - } - /* End of negative trail -- magic jump */ - else if(sign < 0 && stepMod == reg->jumpToPos) { - follow.loc = reg->finalPos; - } - /* Trail in progress -- normal jump */ - else { - patternIdx = (sign < 0) ? followBeg.neighbor & 0x07 : ((followBeg.neighbor & 0x38) >> 3); - follow.loc.X = followBeg.loc.X + dmtxPatternX[patternIdx]; - follow.loc.Y = followBeg.loc.Y + dmtxPatternY[patternIdx]; - } - - follow.step = followBeg.step + sign; - follow.ptr = dmtxDecodeGetCache(dec, follow.loc.X, follow.loc.Y); - assert(follow.ptr != NULL); - follow.neighbor = *follow.ptr; - - return follow; + int patternIdx; + int stepMod; + int factor; + DmtxFollow follow; + + assert(abs(sign) == 1); + assert((int)(followBeg.neighbor & 0x40) != 0x00); + + factor = reg->stepsTotal + 1; + if (sign > 0) + stepMod = (factor + (followBeg.step % factor)) % factor; + else + stepMod = (factor - (followBeg.step % factor)) % factor; + + /* End of positive trail -- magic jump */ + if (sign > 0 && stepMod == reg->jumpToNeg) + { + follow.loc = reg->finalNeg; + } + /* End of negative trail -- magic jump */ + else if (sign < 0 && stepMod == reg->jumpToPos) + { + follow.loc = reg->finalPos; + } + /* Trail in progress -- normal jump */ + else + { + patternIdx = (sign < 0) ? followBeg.neighbor & 0x07 : ((followBeg.neighbor & 0x38) >> 3); + follow.loc.X = followBeg.loc.X + dmtxPatternX[patternIdx]; + follow.loc.Y = followBeg.loc.Y + dmtxPatternY[patternIdx]; + } + + follow.step = followBeg.step + sign; + follow.ptr = dmtxDecodeGetCache(dec, follow.loc.X, follow.loc.Y); + assert(follow.ptr != NULL); + follow.neighbor = *follow.ptr; + + return follow; } /** @@ -1042,22 +1087,22 @@ FollowStep(DmtxDecode *dec, DmtxRegion *reg, DmtxFollow followBeg, int sign) static DmtxFollow FollowStep2(DmtxDecode *dec, DmtxFollow followBeg, int sign) { - int patternIdx; - DmtxFollow follow; + int patternIdx; + DmtxFollow follow; - assert(abs(sign) == 1); - assert((int)(followBeg.neighbor & 0x40) != 0x00); + assert(abs(sign) == 1); + assert((int)(followBeg.neighbor & 0x40) != 0x00); - patternIdx = (sign < 0) ? followBeg.neighbor & 0x07 : ((followBeg.neighbor & 0x38) >> 3); - follow.loc.X = followBeg.loc.X + dmtxPatternX[patternIdx]; - follow.loc.Y = followBeg.loc.Y + dmtxPatternY[patternIdx]; + patternIdx = (sign < 0) ? followBeg.neighbor & 0x07 : ((followBeg.neighbor & 0x38) >> 3); + follow.loc.X = followBeg.loc.X + dmtxPatternX[patternIdx]; + follow.loc.Y = followBeg.loc.Y + dmtxPatternY[patternIdx]; - follow.step = followBeg.step + sign; - follow.ptr = dmtxDecodeGetCache(dec, follow.loc.X, follow.loc.Y); - assert(follow.ptr != NULL); - follow.neighbor = *follow.ptr; + follow.step = followBeg.step + sign; + follow.ptr = dmtxDecodeGetCache(dec, follow.loc.X, follow.loc.Y); + assert(follow.ptr != NULL); + follow.neighbor = *follow.ptr; - return follow; + return follow; } /** @@ -1071,96 +1116,100 @@ FollowStep2(DmtxDecode *dec, DmtxFollow followBeg, int sign) static DmtxPassFail TrailBlazeContinuous(DmtxDecode *dec, DmtxRegion *reg, DmtxPointFlow flowBegin, int maxDiagonal) { - int posAssigns, negAssigns, clears; - int sign; - int steps; - unsigned char *cache, *cacheNext, *cacheBeg; - DmtxPointFlow flow, flowNext; - DmtxPixelLoc boundMin, boundMax; - - boundMin = boundMax = flowBegin.loc; - cacheBeg = dmtxDecodeGetCache(dec, flowBegin.loc.X, flowBegin.loc.Y); - if(cacheBeg == NULL) - return DmtxFail; - *cacheBeg = (0x80 | 0x40); /* Mark location as visited and assigned */ - - reg->flowBegin = flowBegin; - - posAssigns = negAssigns = 0; - for(sign = 1; sign >= -1; sign -= 2) { - - flow = flowBegin; - cache = cacheBeg; - - for(steps = 0; ; steps++) { - - if(maxDiagonal != DmtxUndefined && (boundMax.X - boundMin.X > maxDiagonal || - boundMax.Y - boundMin.Y > maxDiagonal)) - break; - - /* Find the strongest eligible neighbor */ - flowNext = FindStrongestNeighbor(dec, flow, sign); - if(flowNext.mag < 50) - break; + int posAssigns, negAssigns, clears; + int sign; + int steps; + unsigned char *cache, *cacheNext, *cacheBeg; + DmtxPointFlow flow, flowNext; + DmtxPixelLoc boundMin, boundMax; + + boundMin = boundMax = flowBegin.loc; + cacheBeg = dmtxDecodeGetCache(dec, flowBegin.loc.X, flowBegin.loc.Y); + if (cacheBeg == NULL) + return DmtxFail; + *cacheBeg = (0x80 | 0x40); /* Mark location as visited and assigned */ + + reg->flowBegin = flowBegin; + + posAssigns = negAssigns = 0; + for (sign = 1; sign >= -1; sign -= 2) + { + + flow = flowBegin; + cache = cacheBeg; + + for (steps = 0;; steps++) + { + + if (maxDiagonal != DmtxUndefined && (boundMax.X - boundMin.X > maxDiagonal || + boundMax.Y - boundMin.Y > maxDiagonal)) + break; + + /* Find the strongest eligible neighbor */ + flowNext = FindStrongestNeighbor(dec, flow, sign); + if (flowNext.mag < 50) + break; + + /* Get the neighbor's cache location */ + cacheNext = dmtxDecodeGetCache(dec, flowNext.loc.X, flowNext.loc.Y); + if (cacheNext == NULL) + break; + assert(!(*cacheNext & 0x80)); + + /* Mark departure from current location. If flowing downstream + * (sign < 0) then departure vector here is the arrival vector + * of the next location. Upstream flow uses the opposite rule. */ + *cache |= (sign < 0) ? flowNext.arrive : flowNext.arrive << 3; + + /* Mark known direction for next location */ + /* If testing downstream (sign < 0) then next upstream is opposite of next arrival */ + /* If testing upstream (sign > 0) then next downstream is opposite of next arrival */ + *cacheNext = (sign < 0) ? (((flowNext.arrive + 4) % 8) << 3) : ((flowNext.arrive + 4) % 8); + *cacheNext |= (0x80 | 0x40); /* Mark location as visited and assigned */ + if (sign > 0) + posAssigns++; + else + negAssigns++; + cache = cacheNext; + flow = flowNext; - /* Get the neighbor's cache location */ - cacheNext = dmtxDecodeGetCache(dec, flowNext.loc.X, flowNext.loc.Y); - if(cacheNext == NULL) - break; - assert(!(*cacheNext & 0x80)); - - /* Mark departure from current location. If flowing downstream - * (sign < 0) then departure vector here is the arrival vector - * of the next location. Upstream flow uses the opposite rule. */ - *cache |= (sign < 0) ? flowNext.arrive : flowNext.arrive << 3; - - /* Mark known direction for next location */ - /* If testing downstream (sign < 0) then next upstream is opposite of next arrival */ - /* If testing upstream (sign > 0) then next downstream is opposite of next arrival */ - *cacheNext = (sign < 0) ? (((flowNext.arrive + 4)%8) << 3) : ((flowNext.arrive + 4)%8); - *cacheNext |= (0x80 | 0x40); /* Mark location as visited and assigned */ - if(sign > 0) - posAssigns++; - else - negAssigns++; - cache = cacheNext; - flow = flowNext; - - if(flow.loc.X > boundMax.X) - boundMax.X = flow.loc.X; - else if(flow.loc.X < boundMin.X) - boundMin.X = flow.loc.X; - if(flow.loc.Y > boundMax.Y) - boundMax.Y = flow.loc.Y; - else if(flow.loc.Y < boundMin.Y) - boundMin.Y = flow.loc.Y; - -/* CALLBACK_POINT_PLOT(flow.loc, (sign > 0) ? 2 : 3, 1, 2); */ - } - - if(sign > 0) { - reg->finalPos = flow.loc; - reg->jumpToNeg = steps; - } - else { - reg->finalNeg = flow.loc; - reg->jumpToPos = steps; - } - } - reg->stepsTotal = reg->jumpToPos + reg->jumpToNeg; - reg->boundMin = boundMin; - reg->boundMax = boundMax; - - /* Clear "visited" bit from trail */ - clears = TrailClear(dec, reg, 0x80); - assert(posAssigns + negAssigns == clears - 1); - - /* XXX clean this up ... redundant test above */ - if(maxDiagonal != DmtxUndefined && (boundMax.X - boundMin.X > maxDiagonal || - boundMax.Y - boundMin.Y > maxDiagonal)) - return DmtxFail; - - return DmtxPass; + if (flow.loc.X > boundMax.X) + boundMax.X = flow.loc.X; + else if (flow.loc.X < boundMin.X) + boundMin.X = flow.loc.X; + if (flow.loc.Y > boundMax.Y) + boundMax.Y = flow.loc.Y; + else if (flow.loc.Y < boundMin.Y) + boundMin.Y = flow.loc.Y; + + /* CALLBACK_POINT_PLOT(flow.loc, (sign > 0) ? 2 : 3, 1, 2); */ + } + + if (sign > 0) + { + reg->finalPos = flow.loc; + reg->jumpToNeg = steps; + } + else + { + reg->finalNeg = flow.loc; + reg->jumpToPos = steps; + } + } + reg->stepsTotal = reg->jumpToPos + reg->jumpToNeg; + reg->boundMin = boundMin; + reg->boundMax = boundMax; + + /* Clear "visited" bit from trail */ + clears = TrailClear(dec, reg, 0x80); + assert(posAssigns + negAssigns == clears - 1); + + /* XXX clean this up ... redundant test above */ + if (maxDiagonal != DmtxUndefined && (boundMax.X - boundMin.X > maxDiagonal || + boundMax.Y - boundMin.Y > maxDiagonal)) + return DmtxFail; + + return DmtxPass; } /** @@ -1171,90 +1220,100 @@ TrailBlazeContinuous(DmtxDecode *dec, DmtxRegion *reg, DmtxPointFlow flowBegin, static int TrailBlazeGapped(DmtxDecode *dec, DmtxRegion *reg, DmtxBresLine line, int streamDir) { - unsigned char *beforeCache, *afterCache; - DmtxBoolean onEdge; - int distSq, distSqMax; - int travel, outward; - int xDiff, yDiff; - int steps; - int stepDir, dirMap[] = { 0, 1, 2, 7, 8, 3, 6, 5, 4 }; - DmtxPassFail err; - DmtxPixelLoc beforeStep, afterStep; - DmtxPointFlow flow, flowNext; - DmtxPixelLoc loc0; - int xStep, yStep; - - loc0 = line.loc; - flow = GetPointFlow(dec, reg->flowBegin.plane, loc0, dmtxNeighborNone); - distSqMax = (line.xDelta * line.xDelta) + (line.yDelta * line.yDelta); - steps = 0; - onEdge = DmtxTrue; - - beforeStep = loc0; - beforeCache = dmtxDecodeGetCache(dec, loc0.X, loc0.Y); - if(beforeCache == NULL) - return DmtxFail; - else - *beforeCache = 0x00; /* probably should just overwrite one direction */ - - do { - if(onEdge == DmtxTrue) { - flowNext = FindStrongestNeighbor(dec, flow, streamDir); - if(flowNext.mag == DmtxUndefined) - break; + unsigned char *beforeCache, *afterCache; + DmtxBoolean onEdge; + int distSq, distSqMax; + int travel, outward; + int xDiff, yDiff; + int steps; + int stepDir, dirMap[] = {0, 1, 2, 7, 8, 3, 6, 5, 4}; + DmtxPassFail err; + DmtxPixelLoc beforeStep, afterStep; + DmtxPointFlow flow, flowNext; + DmtxPixelLoc loc0; + int xStep, yStep; + + loc0 = line.loc; + flow = GetPointFlow(dec, reg->flowBegin.plane, loc0, dmtxNeighborNone); + distSqMax = (line.xDelta * line.xDelta) + (line.yDelta * line.yDelta); + steps = 0; + onEdge = DmtxTrue; + + beforeStep = loc0; + beforeCache = dmtxDecodeGetCache(dec, loc0.X, loc0.Y); + if (beforeCache == NULL) + return DmtxFail; + else + *beforeCache = 0x00; /* probably should just overwrite one direction */ + + do + { + if (onEdge == DmtxTrue) + { + flowNext = FindStrongestNeighbor(dec, flow, streamDir); + if (flowNext.mag == DmtxUndefined) + break; + + err = BresLineGetStep(line, flowNext.loc, &travel, &outward); + if (err == DmtxFail) + { + return DmtxFail; + } - err = BresLineGetStep(line, flowNext.loc, &travel, &outward); - if (err == DmtxFail) { return DmtxFail; } + if (flowNext.mag < 50 || outward < 0 || (outward == 0 && travel < 0)) + { + onEdge = DmtxFalse; + } + else + { + BresLineStep(&line, travel, outward); + flow = flowNext; + } + } + + if (onEdge == DmtxFalse) + { + BresLineStep(&line, 1, 0); + flow = GetPointFlow(dec, reg->flowBegin.plane, line.loc, dmtxNeighborNone); + if (flow.mag > 50) + onEdge = DmtxTrue; + } + + afterStep = line.loc; + afterCache = dmtxDecodeGetCache(dec, afterStep.X, afterStep.Y); + if (afterCache == NULL) + break; - if(flowNext.mag < 50 || outward < 0 || (outward == 0 && travel < 0)) { - onEdge = DmtxFalse; - } - else { - BresLineStep(&line, travel, outward); - flow = flowNext; - } - } - - if(onEdge == DmtxFalse) { - BresLineStep(&line, 1, 0); - flow = GetPointFlow(dec, reg->flowBegin.plane, line.loc, dmtxNeighborNone); - if(flow.mag > 50) - onEdge = DmtxTrue; - } - - afterStep = line.loc; - afterCache = dmtxDecodeGetCache(dec, afterStep.X, afterStep.Y); - if(afterCache == NULL) - break; - - /* Determine step direction using pure magic */ - xStep = afterStep.X - beforeStep.X; - yStep = afterStep.Y - beforeStep.Y; - assert(abs(xStep) <= 1 && abs(yStep) <= 1); - stepDir = dirMap[3 * yStep + xStep + 4]; - assert(stepDir != 8); - - if(streamDir < 0) { - *beforeCache |= (0x40 | stepDir); - *afterCache = (((stepDir + 4)%8) << 3); - } - else { - *beforeCache |= (0x40 | (stepDir << 3)); - *afterCache = ((stepDir + 4)%8); - } - - /* Guaranteed to have taken one step since top of loop */ - xDiff = line.loc.X - loc0.X; - yDiff = line.loc.Y - loc0.Y; - distSq = (xDiff * xDiff) + (yDiff * yDiff); - - beforeStep = line.loc; - beforeCache = afterCache; - steps++; - - } while(distSq < distSqMax); - - return steps; + /* Determine step direction using pure magic */ + xStep = afterStep.X - beforeStep.X; + yStep = afterStep.Y - beforeStep.Y; + assert(abs(xStep) <= 1 && abs(yStep) <= 1); + stepDir = dirMap[3 * yStep + xStep + 4]; + assert(stepDir != 8); + + if (streamDir < 0) + { + *beforeCache |= (0x40 | stepDir); + *afterCache = (((stepDir + 4) % 8) << 3); + } + else + { + *beforeCache |= (0x40 | (stepDir << 3)); + *afterCache = ((stepDir + 4) % 8); + } + + /* Guaranteed to have taken one step since top of loop */ + xDiff = line.loc.X - loc0.X; + yDiff = line.loc.Y - loc0.Y; + distSq = (xDiff * xDiff) + (yDiff * yDiff); + + beforeStep = line.loc; + beforeCache = afterCache; + steps++; + + } while (distSq < distSqMax); + + return steps; } /** @@ -1264,22 +1323,23 @@ TrailBlazeGapped(DmtxDecode *dec, DmtxRegion *reg, DmtxBresLine line, int stream static int TrailClear(DmtxDecode *dec, DmtxRegion *reg, int clearMask) { - int clears; - DmtxFollow follow; - - assert((clearMask | 0xff) == 0xff); - - /* Clear "visited" bit from trail */ - clears = 0; - follow = FollowSeek(dec, reg, 0); - while(abs(follow.step) <= reg->stepsTotal) { - assert((int)(*follow.ptr & clearMask) != 0x00); - *follow.ptr &= (clearMask ^ 0xff); - follow = FollowStep(dec, reg, follow, +1); - clears++; - } - - return clears; + int clears; + DmtxFollow follow; + + assert((clearMask | 0xff) == 0xff); + + /* Clear "visited" bit from trail */ + clears = 0; + follow = FollowSeek(dec, reg, 0); + while (abs(follow.step) <= reg->stepsTotal) + { + assert((int)(*follow.ptr & clearMask) != 0x00); + *follow.ptr &= (clearMask ^ 0xff); + follow = FollowStep(dec, reg, follow, +1); + clears++; + } + + return clears; } /** @@ -1289,117 +1349,129 @@ TrailClear(DmtxDecode *dec, DmtxRegion *reg, int clearMask) static DmtxBestLine FindBestSolidLine(DmtxDecode *dec, DmtxRegion *reg, int step0, int step1, int streamDir, int houghAvoid) { - int hough[3][DMTX_HOUGH_RES] = { { 0 } }; - int houghMin, houghMax; - char houghTest[DMTX_HOUGH_RES]; - int i; - int step; - int sign; - int tripSteps; - int angleBest; - int hOffset, hOffsetBest; - int xDiff, yDiff; - int dH; - DmtxRay2 rH; - DmtxFollow follow; - DmtxBestLine line; - DmtxPixelLoc rHp; - - memset(&line, 0x00, sizeof(DmtxBestLine)); - memset(&rH, 0x00, sizeof(DmtxRay2)); - angleBest = 0; - hOffset = hOffsetBest = 0; - - sign = 0; - - /* Always follow path flowing away from the trail start */ - if(step0 != 0) { - if(step0 > 0) { - sign = +1; - tripSteps = (step1 - step0 + reg->stepsTotal) % reg->stepsTotal; - } - else { - sign = -1; - tripSteps = (step0 - step1 + reg->stepsTotal) % reg->stepsTotal; - } - if(tripSteps == 0) - tripSteps = reg->stepsTotal; - } - else if(step1 != 0) { - sign = (step1 > 0) ? +1 : -1; - tripSteps = abs(step1); - } - else if(step1 == 0) { - sign = +1; - tripSteps = reg->stepsTotal; - } - assert(sign == streamDir); - - follow = FollowSeek(dec, reg, step0); - rHp = follow.loc; - - line.stepBeg = line.stepPos = line.stepNeg = step0; - line.locBeg = follow.loc; - line.locPos = follow.loc; - line.locNeg = follow.loc; - - /* Predetermine which angles to test */ - for(i = 0; i < DMTX_HOUGH_RES; i++) { - if(houghAvoid == DmtxUndefined) { - houghTest[i] = 1; - } - else { - houghMin = (houghAvoid + DMTX_HOUGH_RES/6) % DMTX_HOUGH_RES; - houghMax = (houghAvoid - DMTX_HOUGH_RES/6 + DMTX_HOUGH_RES) % DMTX_HOUGH_RES; - if(houghMin > houghMax) - houghTest[i] = (i > houghMin || i < houghMax) ? 1 : 0; - else - houghTest[i] = (i > houghMin && i < houghMax) ? 1 : 0; - } - } - - /* Test each angle for steps along path */ - for(step = 0; step < tripSteps; step++) { - - xDiff = follow.loc.X - rHp.X; - yDiff = follow.loc.Y - rHp.Y; - - /* Increment Hough accumulator */ - for(i = 0; i < DMTX_HOUGH_RES; i++) { - - if((int)houghTest[i] == 0) - continue; - - dH = (rHvX[i] * yDiff) - (rHvY[i] * xDiff); - if(dH >= -384 && dH <= 384) { - - if(dH > 128) - hOffset = 2; - else if(dH >= -128) - hOffset = 1; + int hough[3][DMTX_HOUGH_RES] = {{0}}; + int houghMin, houghMax; + char houghTest[DMTX_HOUGH_RES]; + int i; + int step; + int sign; + int tripSteps; + int angleBest; + int hOffset, hOffsetBest; + int xDiff, yDiff; + int dH; + DmtxRay2 rH; + DmtxFollow follow; + DmtxBestLine line; + DmtxPixelLoc rHp; + + memset(&line, 0x00, sizeof(DmtxBestLine)); + memset(&rH, 0x00, sizeof(DmtxRay2)); + angleBest = 0; + hOffset = hOffsetBest = 0; + + sign = 0; + + /* Always follow path flowing away from the trail start */ + if (step0 != 0) + { + if (step0 > 0) + { + sign = +1; + tripSteps = (step1 - step0 + reg->stepsTotal) % reg->stepsTotal; + } + else + { + sign = -1; + tripSteps = (step0 - step1 + reg->stepsTotal) % reg->stepsTotal; + } + if (tripSteps == 0) + tripSteps = reg->stepsTotal; + } + else if (step1 != 0) + { + sign = (step1 > 0) ? +1 : -1; + tripSteps = abs(step1); + } + else if (step1 == 0) + { + sign = +1; + tripSteps = reg->stepsTotal; + } + assert(sign == streamDir); + + follow = FollowSeek(dec, reg, step0); + rHp = follow.loc; + + line.stepBeg = line.stepPos = line.stepNeg = step0; + line.locBeg = follow.loc; + line.locPos = follow.loc; + line.locNeg = follow.loc; + + /* Predetermine which angles to test */ + for (i = 0; i < DMTX_HOUGH_RES; i++) + { + if (houghAvoid == DmtxUndefined) + { + houghTest[i] = 1; + } + else + { + houghMin = (houghAvoid + DMTX_HOUGH_RES / 6) % DMTX_HOUGH_RES; + houghMax = (houghAvoid - DMTX_HOUGH_RES / 6 + DMTX_HOUGH_RES) % DMTX_HOUGH_RES; + if (houghMin > houghMax) + houghTest[i] = (i > houghMin || i < houghMax) ? 1 : 0; else - hOffset = 0; - - hough[hOffset][i]++; - - /* New angle takes over lead */ - if(hough[hOffset][i] > hough[hOffsetBest][angleBest]) { - angleBest = i; - hOffsetBest = hOffset; + houghTest[i] = (i > houghMin && i < houghMax) ? 1 : 0; + } + } + + /* Test each angle for steps along path */ + for (step = 0; step < tripSteps; step++) + { + + xDiff = follow.loc.X - rHp.X; + yDiff = follow.loc.Y - rHp.Y; + + /* Increment Hough accumulator */ + for (i = 0; i < DMTX_HOUGH_RES; i++) + { + + if ((int)houghTest[i] == 0) + continue; + + dH = (rHvX[i] * yDiff) - (rHvY[i] * xDiff); + if (dH >= -384 && dH <= 384) + { + + if (dH > 128) + hOffset = 2; + else if (dH >= -128) + hOffset = 1; + else + hOffset = 0; + + hough[hOffset][i]++; + + /* New angle takes over lead */ + if (hough[hOffset][i] > hough[hOffsetBest][angleBest]) + { + angleBest = i; + hOffsetBest = hOffset; + } } - } - } + } -/* CALLBACK_POINT_PLOT(follow.loc, (sign > 1) ? 4 : 3, 1, 2); */ + /* CALLBACK_POINT_PLOT(follow.loc, (sign > 1) ? 4 : 3, 1, 2); */ - follow = FollowStep(dec, reg, follow, sign); - } + follow = FollowStep(dec, reg, follow, sign); + } - line.angle = angleBest; - line.hOffset = hOffsetBest; - line.mag = hough[hOffsetBest][angleBest]; + line.angle = angleBest; + line.hOffset = hOffsetBest; + line.mag = hough[hOffsetBest][angleBest]; - return line; + return line; } /** @@ -1409,85 +1481,92 @@ FindBestSolidLine(DmtxDecode *dec, DmtxRegion *reg, int step0, int step1, int st static DmtxBestLine FindBestSolidLine2(DmtxDecode *dec, DmtxPixelLoc loc0, int tripSteps, int sign, int houghAvoid) { - int hough[3][DMTX_HOUGH_RES] = { { 0 } }; - int houghMin, houghMax; - char houghTest[DMTX_HOUGH_RES]; - int i; - int step; - int angleBest; - int hOffset, hOffsetBest; - int xDiff, yDiff; - int dH; - DmtxRay2 rH; - DmtxBestLine line; - DmtxPixelLoc rHp; - DmtxFollow follow; - - memset(&line, 0x00, sizeof(DmtxBestLine)); - memset(&rH, 0x00, sizeof(DmtxRay2)); - angleBest = 0; - hOffset = hOffsetBest = 0; - - follow = FollowSeekLoc(dec, loc0); - rHp = line.locBeg = line.locPos = line.locNeg = follow.loc; - line.stepBeg = line.stepPos = line.stepNeg = 0; - - /* Predetermine which angles to test */ - for(i = 0; i < DMTX_HOUGH_RES; i++) { - if(houghAvoid == DmtxUndefined) { - houghTest[i] = 1; - } - else { - houghMin = (houghAvoid + DMTX_HOUGH_RES/6) % DMTX_HOUGH_RES; - houghMax = (houghAvoid - DMTX_HOUGH_RES/6 + DMTX_HOUGH_RES) % DMTX_HOUGH_RES; - if(houghMin > houghMax) - houghTest[i] = (i > houghMin || i < houghMax) ? 1 : 0; - else - houghTest[i] = (i > houghMin && i < houghMax) ? 1 : 0; - } - } - - /* Test each angle for steps along path */ - for(step = 0; step < tripSteps; step++) { - - xDiff = follow.loc.X - rHp.X; - yDiff = follow.loc.Y - rHp.Y; - - /* Increment Hough accumulator */ - for(i = 0; i < DMTX_HOUGH_RES; i++) { - - if((int)houghTest[i] == 0) - continue; - - dH = (rHvX[i] * yDiff) - (rHvY[i] * xDiff); - if(dH >= -384 && dH <= 384) { - if(dH > 128) - hOffset = 2; - else if(dH >= -128) - hOffset = 1; + int hough[3][DMTX_HOUGH_RES] = {{0}}; + int houghMin, houghMax; + char houghTest[DMTX_HOUGH_RES]; + int i; + int step; + int angleBest; + int hOffset, hOffsetBest; + int xDiff, yDiff; + int dH; + DmtxRay2 rH; + DmtxBestLine line; + DmtxPixelLoc rHp; + DmtxFollow follow; + + memset(&line, 0x00, sizeof(DmtxBestLine)); + memset(&rH, 0x00, sizeof(DmtxRay2)); + angleBest = 0; + hOffset = hOffsetBest = 0; + + follow = FollowSeekLoc(dec, loc0); + rHp = line.locBeg = line.locPos = line.locNeg = follow.loc; + line.stepBeg = line.stepPos = line.stepNeg = 0; + + /* Predetermine which angles to test */ + for (i = 0; i < DMTX_HOUGH_RES; i++) + { + if (houghAvoid == DmtxUndefined) + { + houghTest[i] = 1; + } + else + { + houghMin = (houghAvoid + DMTX_HOUGH_RES / 6) % DMTX_HOUGH_RES; + houghMax = (houghAvoid - DMTX_HOUGH_RES / 6 + DMTX_HOUGH_RES) % DMTX_HOUGH_RES; + if (houghMin > houghMax) + houghTest[i] = (i > houghMin || i < houghMax) ? 1 : 0; else - hOffset = 0; - - hough[hOffset][i]++; - - /* New angle takes over lead */ - if(hough[hOffset][i] > hough[hOffsetBest][angleBest]) { - angleBest = i; - hOffsetBest = hOffset; + houghTest[i] = (i > houghMin && i < houghMax) ? 1 : 0; + } + } + + /* Test each angle for steps along path */ + for (step = 0; step < tripSteps; step++) + { + + xDiff = follow.loc.X - rHp.X; + yDiff = follow.loc.Y - rHp.Y; + + /* Increment Hough accumulator */ + for (i = 0; i < DMTX_HOUGH_RES; i++) + { + + if ((int)houghTest[i] == 0) + continue; + + dH = (rHvX[i] * yDiff) - (rHvY[i] * xDiff); + if (dH >= -384 && dH <= 384) + { + if (dH > 128) + hOffset = 2; + else if (dH >= -128) + hOffset = 1; + else + hOffset = 0; + + hough[hOffset][i]++; + + /* New angle takes over lead */ + if (hough[hOffset][i] > hough[hOffsetBest][angleBest]) + { + angleBest = i; + hOffsetBest = hOffset; + } } - } - } + } -/* CALLBACK_POINT_PLOT(follow.loc, (sign > 1) ? 4 : 3, 1, 2); */ + /* CALLBACK_POINT_PLOT(follow.loc, (sign > 1) ? 4 : 3, 1, 2); */ - follow = FollowStep2(dec, follow, sign); - } + follow = FollowStep2(dec, follow, sign); + } - line.angle = angleBest; - line.hOffset = hOffsetBest; - line.mag = hough[hOffsetBest][angleBest]; + line.angle = angleBest; + line.hOffset = hOffsetBest; + line.mag = hough[hOffsetBest][angleBest]; - return line; + return line; } /** @@ -1497,101 +1576,112 @@ FindBestSolidLine2(DmtxDecode *dec, DmtxPixelLoc loc0, int tripSteps, int sign, static DmtxPassFail FindTravelLimits(DmtxDecode *dec, DmtxRegion *reg, DmtxBestLine *line) { - int i; - int distSq, distSqMax; - int xDiff, yDiff; - int posRunning, negRunning; - int posTravel, negTravel; - int posWander, posWanderMin, posWanderMax, posWanderMinLock, posWanderMaxLock; - int negWander, negWanderMin, negWanderMax, negWanderMinLock, negWanderMaxLock; - int cosAngle, sinAngle; - DmtxFollow followPos, followNeg; - DmtxPixelLoc loc0, posMax, negMax; - - /* line->stepBeg is already known to sit on the best Hough line */ - followPos = followNeg = FollowSeek(dec, reg, line->stepBeg); - loc0 = followPos.loc; - - cosAngle = rHvX[line->angle]; - sinAngle = rHvY[line->angle]; - - distSqMax = 0; - posMax = negMax = followPos.loc; - - posTravel = negTravel = 0; - posWander = posWanderMin = posWanderMax = posWanderMinLock = posWanderMaxLock = 0; - negWander = negWanderMin = negWanderMax = negWanderMinLock = negWanderMaxLock = 0; - - for(i = 0; i < reg->stepsTotal/2; i++) { - - posRunning = (int)(i < 10 || abs(posWander) < abs(posTravel)); - negRunning = (int)(i < 10 || abs(negWander) < abs(negTravel)); - - if(posRunning != 0) { - xDiff = followPos.loc.X - loc0.X; - yDiff = followPos.loc.Y - loc0.Y; - posTravel = (cosAngle * xDiff) + (sinAngle * yDiff); - posWander = (cosAngle * yDiff) - (sinAngle * xDiff); - - if(posWander >= -3*256 && posWander <= 3*256) { - distSq = DistanceSquared(followPos.loc, negMax); - if(distSq > distSqMax) { - posMax = followPos.loc; - distSqMax = distSq; - line->stepPos = followPos.step; - line->locPos = followPos.loc; - posWanderMinLock = posWanderMin; - posWanderMaxLock = posWanderMax; + int i; + int distSq, distSqMax; + int xDiff, yDiff; + int posRunning, negRunning; + int posTravel, negTravel; + int posWander, posWanderMin, posWanderMax, posWanderMinLock, posWanderMaxLock; + int negWander, negWanderMin, negWanderMax, negWanderMinLock, negWanderMaxLock; + int cosAngle, sinAngle; + DmtxFollow followPos, followNeg; + DmtxPixelLoc loc0, posMax, negMax; + + /* line->stepBeg is already known to sit on the best Hough line */ + followPos = followNeg = FollowSeek(dec, reg, line->stepBeg); + loc0 = followPos.loc; + + cosAngle = rHvX[line->angle]; + sinAngle = rHvY[line->angle]; + + distSqMax = 0; + posMax = negMax = followPos.loc; + + posTravel = negTravel = 0; + posWander = posWanderMin = posWanderMax = posWanderMinLock = posWanderMaxLock = 0; + negWander = negWanderMin = negWanderMax = negWanderMinLock = negWanderMaxLock = 0; + + for (i = 0; i < reg->stepsTotal / 2; i++) + { + + posRunning = (int)(i < 10 || abs(posWander) < abs(posTravel)); + negRunning = (int)(i < 10 || abs(negWander) < abs(negTravel)); + + if (posRunning != 0) + { + xDiff = followPos.loc.X - loc0.X; + yDiff = followPos.loc.Y - loc0.Y; + posTravel = (cosAngle * xDiff) + (sinAngle * yDiff); + posWander = (cosAngle * yDiff) - (sinAngle * xDiff); + + if (posWander >= -3 * 256 && posWander <= 3 * 256) + { + distSq = DistanceSquared(followPos.loc, negMax); + if (distSq > distSqMax) + { + posMax = followPos.loc; + distSqMax = distSq; + line->stepPos = followPos.step; + line->locPos = followPos.loc; + posWanderMinLock = posWanderMin; + posWanderMaxLock = posWanderMax; + } } - } - else { - posWanderMin = min(posWanderMin, posWander); - posWanderMax = max(posWanderMax, posWander); - } - } - else if(!negRunning) { - break; - } - - if(negRunning != 0) { - xDiff = followNeg.loc.X - loc0.X; - yDiff = followNeg.loc.Y - loc0.Y; - negTravel = (cosAngle * xDiff) + (sinAngle * yDiff); - negWander = (cosAngle * yDiff) - (sinAngle * xDiff); - - if(negWander >= -3*256 && negWander < 3*256) { - distSq = DistanceSquared(followNeg.loc, posMax); - if(distSq > distSqMax) { - negMax = followNeg.loc; - distSqMax = distSq; - line->stepNeg = followNeg.step; - line->locNeg = followNeg.loc; - negWanderMinLock = negWanderMin; - negWanderMaxLock = negWanderMax; + else + { + posWanderMin = min(posWanderMin, posWander); + posWanderMax = max(posWanderMax, posWander); + } + } + else if (!negRunning) + { + break; + } + + if (negRunning != 0) + { + xDiff = followNeg.loc.X - loc0.X; + yDiff = followNeg.loc.Y - loc0.Y; + negTravel = (cosAngle * xDiff) + (sinAngle * yDiff); + negWander = (cosAngle * yDiff) - (sinAngle * xDiff); + + if (negWander >= -3 * 256 && negWander < 3 * 256) + { + distSq = DistanceSquared(followNeg.loc, posMax); + if (distSq > distSqMax) + { + negMax = followNeg.loc; + distSqMax = distSq; + line->stepNeg = followNeg.step; + line->locNeg = followNeg.loc; + negWanderMinLock = negWanderMin; + negWanderMaxLock = negWanderMax; + } + } + else + { + negWanderMin = min(negWanderMin, negWander); + negWanderMax = max(negWanderMax, negWander); } - } - else { - negWanderMin = min(negWanderMin, negWander); - negWanderMax = max(negWanderMax, negWander); - } - } - else if(!posRunning) { - break; - } - -/* CALLBACK_POINT_PLOT(followPos.loc, 2, 1, 2); - CALLBACK_POINT_PLOT(followNeg.loc, 4, 1, 2); */ - - followPos = FollowStep(dec, reg, followPos, +1); - followNeg = FollowStep(dec, reg, followNeg, -1); - } - line->devn = max(posWanderMaxLock - posWanderMinLock, negWanderMaxLock - negWanderMinLock)/256; - line->distSq = distSqMax; - -/* CALLBACK_POINT_PLOT(posMax, 2, 1, 1); - CALLBACK_POINT_PLOT(negMax, 2, 1, 1); */ - - return DmtxPass; + } + else if (!posRunning) + { + break; + } + + /* CALLBACK_POINT_PLOT(followPos.loc, 2, 1, 2); + CALLBACK_POINT_PLOT(followNeg.loc, 4, 1, 2); */ + + followPos = FollowStep(dec, reg, followPos, +1); + followNeg = FollowStep(dec, reg, followNeg, -1); + } + line->devn = max(posWanderMaxLock - posWanderMinLock, negWanderMaxLock - negWanderMinLock) / 256; + line->distSq = distSqMax; + + /* CALLBACK_POINT_PLOT(posMax, 2, 1, 1); + CALLBACK_POINT_PLOT(negMax, 2, 1, 1); */ + + return DmtxPass; } /** @@ -1601,76 +1691,81 @@ FindTravelLimits(DmtxDecode *dec, DmtxRegion *reg, DmtxBestLine *line) static DmtxPassFail MatrixRegionAlignCalibEdge(DmtxDecode *dec, DmtxRegion *reg, int edgeLoc) { - int streamDir; - int steps; - int avoidAngle; - int symbolShape; - DmtxVector2 pTmp; - DmtxPixelLoc loc0, loc1, locOrigin; - DmtxBresLine line; - DmtxFollow follow; - DmtxBestLine bestLine; - - /* Determine pixel coordinates of origin */ - pTmp.X = 0.0; - pTmp.Y = 0.0; - dmtxMatrix3VMultiplyBy(&pTmp, reg->fit2raw); - locOrigin.X = (int)(pTmp.X + 0.5); - locOrigin.Y = (int)(pTmp.Y + 0.5); - - if(dec->sizeIdxExpected == DmtxSymbolSquareAuto || - (dec->sizeIdxExpected >= DmtxSymbol10x10 && + int streamDir; + int steps; + int avoidAngle; + int symbolShape; + DmtxVector2 pTmp; + DmtxPixelLoc loc0, loc1, locOrigin; + DmtxBresLine line; + DmtxFollow follow; + DmtxBestLine bestLine; + + /* Determine pixel coordinates of origin */ + pTmp.X = 0.0; + pTmp.Y = 0.0; + dmtxMatrix3VMultiplyBy(&pTmp, reg->fit2raw); + locOrigin.X = (int)(pTmp.X + 0.5); + locOrigin.Y = (int)(pTmp.Y + 0.5); + + if (dec->sizeIdxExpected == DmtxSymbolSquareAuto || + (dec->sizeIdxExpected >= DmtxSymbol10x10 && dec->sizeIdxExpected <= DmtxSymbol144x144)) - symbolShape = DmtxSymbolSquareAuto; - else if(dec->sizeIdxExpected == DmtxSymbolRectAuto || - (dec->sizeIdxExpected >= DmtxSymbol8x18 && - dec->sizeIdxExpected <= DmtxSymbol16x48)) - symbolShape = DmtxSymbolRectAuto; - else - symbolShape = DmtxSymbolShapeAuto; - - /* Determine end locations of test line */ - if(edgeLoc == DmtxEdgeTop) { - streamDir = reg->polarity * -1; - avoidAngle = reg->leftLine.angle; - follow = FollowSeekLoc(dec, reg->locT); - pTmp.X = 0.8; - pTmp.Y = (symbolShape == DmtxSymbolRectAuto) ? 0.2 : 0.6; - } - else { - assert(edgeLoc == DmtxEdgeRight); - streamDir = reg->polarity; - avoidAngle = reg->bottomLine.angle; - follow = FollowSeekLoc(dec, reg->locR); - pTmp.X = (symbolShape == DmtxSymbolSquareAuto) ? 0.7 : 0.9; - pTmp.Y = 0.8; - } - - dmtxMatrix3VMultiplyBy(&pTmp, reg->fit2raw); - loc1.X = (int)(pTmp.X + 0.5); - loc1.Y = (int)(pTmp.Y + 0.5); - - loc0 = follow.loc; - line = BresLineInit(loc0, loc1, locOrigin); - steps = TrailBlazeGapped(dec, reg, line, streamDir); - - bestLine = FindBestSolidLine2(dec, loc0, steps, streamDir, avoidAngle); - if(bestLine.mag < 5) { - ; - } - - if(edgeLoc == DmtxEdgeTop) { - reg->topKnown = 1; - reg->topAngle = bestLine.angle; - reg->topLoc = bestLine.locBeg; - } - else { - reg->rightKnown = 1; - reg->rightAngle = bestLine.angle; - reg->rightLoc = bestLine.locBeg; - } - - return DmtxPass; + symbolShape = DmtxSymbolSquareAuto; + else if (dec->sizeIdxExpected == DmtxSymbolRectAuto || + (dec->sizeIdxExpected >= DmtxSymbol8x18 && + dec->sizeIdxExpected <= DmtxSymbol16x48)) + symbolShape = DmtxSymbolRectAuto; + else + symbolShape = DmtxSymbolShapeAuto; + + /* Determine end locations of test line */ + if (edgeLoc == DmtxEdgeTop) + { + streamDir = reg->polarity * -1; + avoidAngle = reg->leftLine.angle; + follow = FollowSeekLoc(dec, reg->locT); + pTmp.X = 0.8; + pTmp.Y = (symbolShape == DmtxSymbolRectAuto) ? 0.2 : 0.6; + } + else + { + assert(edgeLoc == DmtxEdgeRight); + streamDir = reg->polarity; + avoidAngle = reg->bottomLine.angle; + follow = FollowSeekLoc(dec, reg->locR); + pTmp.X = (symbolShape == DmtxSymbolSquareAuto) ? 0.7 : 0.9; + pTmp.Y = 0.8; + } + + dmtxMatrix3VMultiplyBy(&pTmp, reg->fit2raw); + loc1.X = (int)(pTmp.X + 0.5); + loc1.Y = (int)(pTmp.Y + 0.5); + + loc0 = follow.loc; + line = BresLineInit(loc0, loc1, locOrigin); + steps = TrailBlazeGapped(dec, reg, line, streamDir); + + bestLine = FindBestSolidLine2(dec, loc0, steps, streamDir, avoidAngle); + if (bestLine.mag < 5) + { + ; + } + + if (edgeLoc == DmtxEdgeTop) + { + reg->topKnown = 1; + reg->topAngle = bestLine.angle; + reg->topLoc = bestLine.locBeg; + } + else + { + reg->rightKnown = 1; + reg->rightAngle = bestLine.angle; + reg->rightLoc = bestLine.locBeg; + } + + return DmtxPass; } /** @@ -1680,65 +1775,71 @@ MatrixRegionAlignCalibEdge(DmtxDecode *dec, DmtxRegion *reg, int edgeLoc) static DmtxBresLine BresLineInit(DmtxPixelLoc loc0, DmtxPixelLoc loc1, DmtxPixelLoc locInside) { - int cp; - DmtxBresLine line; - DmtxPixelLoc *locBeg, *locEnd; - - /* XXX Verify that loc0 and loc1 are inbounds */ - - /* Values that stay the same after initialization */ - line.loc0 = loc0; - line.loc1 = loc1; - line.xStep = (loc0.X < loc1.X) ? +1 : -1; - line.yStep = (loc0.Y < loc1.Y) ? +1 : -1; - line.xDelta = abs(loc1.X - loc0.X); - line.yDelta = abs(loc1.Y - loc0.Y); - line.steep = (int)(line.yDelta > line.xDelta); - - /* Take cross product to determine outward step */ - if(line.steep != 0) { - /* Point first vector up to get correct sign */ - if(loc0.Y < loc1.Y) { - locBeg = &loc0; - locEnd = &loc1; - } - else { - locBeg = &loc1; - locEnd = &loc0; - } - cp = (((locEnd->X - locBeg->X) * (locInside.Y - locEnd->Y)) - - ((locEnd->Y - locBeg->Y) * (locInside.X - locEnd->X))); - - line.xOut = (cp > 0) ? +1 : -1; - line.yOut = 0; - } - else { - /* Point first vector left to get correct sign */ - if(loc0.X > loc1.X) { - locBeg = &loc0; - locEnd = &loc1; - } - else { - locBeg = &loc1; - locEnd = &loc0; - } - cp = (((locEnd->X - locBeg->X) * (locInside.Y - locEnd->Y)) - - ((locEnd->Y - locBeg->Y) * (locInside.X - locEnd->X))); - - line.xOut = 0; - line.yOut = (cp > 0) ? +1 : -1; - } - - /* Values that change while stepping through line */ - line.loc = loc0; - line.travel = 0; - line.outward = 0; - line.error = (line.steep) ? line.yDelta/2 : line.xDelta/2; - -/* CALLBACK_POINT_PLOT(loc0, 3, 1, 1); - CALLBACK_POINT_PLOT(loc1, 3, 1, 1); */ - - return line; + int cp; + DmtxBresLine line; + DmtxPixelLoc *locBeg, *locEnd; + + /* XXX Verify that loc0 and loc1 are inbounds */ + + /* Values that stay the same after initialization */ + line.loc0 = loc0; + line.loc1 = loc1; + line.xStep = (loc0.X < loc1.X) ? +1 : -1; + line.yStep = (loc0.Y < loc1.Y) ? +1 : -1; + line.xDelta = abs(loc1.X - loc0.X); + line.yDelta = abs(loc1.Y - loc0.Y); + line.steep = (int)(line.yDelta > line.xDelta); + + /* Take cross product to determine outward step */ + if (line.steep != 0) + { + /* Point first vector up to get correct sign */ + if (loc0.Y < loc1.Y) + { + locBeg = &loc0; + locEnd = &loc1; + } + else + { + locBeg = &loc1; + locEnd = &loc0; + } + cp = (((locEnd->X - locBeg->X) * (locInside.Y - locEnd->Y)) - + ((locEnd->Y - locBeg->Y) * (locInside.X - locEnd->X))); + + line.xOut = (cp > 0) ? +1 : -1; + line.yOut = 0; + } + else + { + /* Point first vector left to get correct sign */ + if (loc0.X > loc1.X) + { + locBeg = &loc0; + locEnd = &loc1; + } + else + { + locBeg = &loc1; + locEnd = &loc0; + } + cp = (((locEnd->X - locBeg->X) * (locInside.Y - locEnd->Y)) - + ((locEnd->Y - locBeg->Y) * (locInside.X - locEnd->X))); + + line.xOut = 0; + line.yOut = (cp > 0) ? +1 : -1; + } + + /* Values that change while stepping through line */ + line.loc = loc0; + line.travel = 0; + line.outward = 0; + line.error = (line.steep) ? line.yDelta / 2 : line.xDelta / 2; + + /* CALLBACK_POINT_PLOT(loc0, 3, 1, 1); + CALLBACK_POINT_PLOT(loc1, 3, 1, 1); */ + + return line; } /** @@ -1748,21 +1849,23 @@ BresLineInit(DmtxPixelLoc loc0, DmtxPixelLoc loc1, DmtxPixelLoc locInside) static DmtxPassFail BresLineGetStep(DmtxBresLine line, DmtxPixelLoc target, int *travel, int *outward) { - /* Determine necessary step along and outward from Bresenham line */ - if(line.steep != 0) { - *travel = (line.yStep > 0) ? target.Y - line.loc.Y : line.loc.Y - target.Y; - BresLineStep(&line, *travel, 0); - *outward = (line.xOut > 0) ? target.X - line.loc.X : line.loc.X - target.X; - assert(line.yOut == 0); - } - else { - *travel = (line.xStep > 0) ? target.X - line.loc.X : line.loc.X - target.X; - BresLineStep(&line, *travel, 0); - *outward = (line.yOut > 0) ? target.Y - line.loc.Y : line.loc.Y - target.Y; - assert(line.xOut == 0); - } - - return DmtxPass; + /* Determine necessary step along and outward from Bresenham line */ + if (line.steep != 0) + { + *travel = (line.yStep > 0) ? target.Y - line.loc.Y : line.loc.Y - target.Y; + BresLineStep(&line, *travel, 0); + *outward = (line.xOut > 0) ? target.X - line.loc.X : line.loc.X - target.X; + assert(line.yOut == 0); + } + else + { + *travel = (line.xStep > 0) ? target.X - line.loc.X : line.loc.X - target.X; + BresLineStep(&line, *travel, 0); + *outward = (line.yOut > 0) ? target.Y - line.loc.Y : line.loc.Y - target.Y; + assert(line.xOut == 0); + } + + return DmtxPass; } /** @@ -1772,64 +1875,75 @@ BresLineGetStep(DmtxBresLine line, DmtxPixelLoc target, int *travel, int *outwar static DmtxPassFail BresLineStep(DmtxBresLine *line, int travel, int outward) { - int i; - DmtxBresLine lineNew; + int i; + DmtxBresLine lineNew; - lineNew = *line; + lineNew = *line; - assert(abs(travel) < 2); - assert(abs(outward) >= 0); + assert(abs(travel) < 2); + assert(abs(outward) >= 0); - /* Perform forward step */ - if(travel > 0) { - lineNew.travel++; - if(lineNew.steep != 0) { - lineNew.loc.Y += lineNew.yStep; - lineNew.error -= lineNew.xDelta; - if(lineNew.error < 0) { - lineNew.loc.X += lineNew.xStep; - lineNew.error += lineNew.yDelta; - } - } - else { - lineNew.loc.X += lineNew.xStep; - lineNew.error -= lineNew.yDelta; - if(lineNew.error < 0) { + /* Perform forward step */ + if (travel > 0) + { + lineNew.travel++; + if (lineNew.steep != 0) + { lineNew.loc.Y += lineNew.yStep; - lineNew.error += lineNew.xDelta; - } - } - } - else if(travel < 0) { - lineNew.travel--; - if(lineNew.steep != 0) { - lineNew.loc.Y -= lineNew.yStep; - lineNew.error += lineNew.xDelta; - if(lineNew.error >= lineNew.yDelta) { - lineNew.loc.X -= lineNew.xStep; + lineNew.error -= lineNew.xDelta; + if (lineNew.error < 0) + { + lineNew.loc.X += lineNew.xStep; + lineNew.error += lineNew.yDelta; + } + } + else + { + lineNew.loc.X += lineNew.xStep; lineNew.error -= lineNew.yDelta; - } - } - else { - lineNew.loc.X -= lineNew.xStep; - lineNew.error += lineNew.yDelta; - if(lineNew.error >= lineNew.xDelta) { + if (lineNew.error < 0) + { + lineNew.loc.Y += lineNew.yStep; + lineNew.error += lineNew.xDelta; + } + } + } + else if (travel < 0) + { + lineNew.travel--; + if (lineNew.steep != 0) + { lineNew.loc.Y -= lineNew.yStep; - lineNew.error -= lineNew.xDelta; - } - } - } + lineNew.error += lineNew.xDelta; + if (lineNew.error >= lineNew.yDelta) + { + lineNew.loc.X -= lineNew.xStep; + lineNew.error -= lineNew.yDelta; + } + } + else + { + lineNew.loc.X -= lineNew.xStep; + lineNew.error += lineNew.yDelta; + if (lineNew.error >= lineNew.xDelta) + { + lineNew.loc.Y -= lineNew.yStep; + lineNew.error -= lineNew.xDelta; + } + } + } - for(i = 0; i < outward; i++) { - /* Outward steps */ - lineNew.outward++; - lineNew.loc.X += lineNew.xOut; - lineNew.loc.Y += lineNew.yOut; - } + for (i = 0; i < outward; i++) + { + /* Outward steps */ + lineNew.outward++; + lineNew.loc.X += lineNew.xOut; + lineNew.loc.Y += lineNew.yOut; + } - *line = lineNew; + *line = lineNew; - return DmtxPass; + return DmtxPass; } /** @@ -1840,79 +1954,88 @@ BresLineStep(DmtxBresLine *line, int travel, int outward) static void WriteDiagnosticImage(DmtxDecode *dec, DmtxRegion *reg, char *imagePath) { - int row, col; - int width, height; - unsigned char *cache; - int rgb[3]; - FILE *fp; - DmtxVector2 p; - DmtxImage *img; - - assert(reg != NULL); - - fp = fopen(imagePath, "wb"); - if(fp == NULL) { - exit(3); - } - - width = dmtxDecodeGetProp(dec, DmtxPropWidth); - height = dmtxDecodeGetProp(dec->image, DmtxPropHeight); - - img = dmtxImageCreate(NULL, width, height, DmtxPack24bppRGB); - - /* Populate image */ - for(row = 0; row < height; row++) { - for(col = 0; col < width; col++) { - - cache = dmtxDecodeGetCache(dec, col, row); - if(cache == NULL) { - rgb[0] = 0; - rgb[1] = 0; - rgb[2] = 128; - } - else { - dmtxDecodeGetPixelValue(dec, col, row, 0, &rgb[0]); - dmtxDecodeGetPixelValue(dec, col, row, 1, &rgb[1]); - dmtxDecodeGetPixelValue(dec, col, row, 2, &rgb[2]); - - p.X = col; - p.Y = row; - dmtxMatrix3VMultiplyBy(&p, reg->raw2fit); - - if(p.X < 0.0 || p.X > 1.0 || p.Y < 0.0 || p.Y > 1.0) { - rgb[0] = 0; - rgb[1] = 0; - rgb[2] = 128; + int row, col; + int width, height; + unsigned char *cache; + int rgb[3]; + FILE *fp; + DmtxVector2 p; + DmtxImage *img; + + assert(reg != NULL); + + fp = fopen(imagePath, "wb"); + if (fp == NULL) + { + exit(3); + } + + width = dmtxDecodeGetProp(dec, DmtxPropWidth); + height = dmtxDecodeGetProp(dec->image, DmtxPropHeight); + + img = dmtxImageCreate(NULL, width, height, DmtxPack24bppRGB); + + /* Populate image */ + for (row = 0; row < height; row++) + { + for (col = 0; col < width; col++) + { + + cache = dmtxDecodeGetCache(dec, col, row); + if (cache == NULL) + { + rgb[0] = 0; + rgb[1] = 0; + rgb[2] = 128; } - else if(p.X + p.Y > 1.0) { - rgb[0] += (0.4 * (255 - rgb[0])); - rgb[1] += (0.4 * (255 - rgb[1])); - rgb[2] += (0.4 * (255 - rgb[2])); + else + { + dmtxDecodeGetPixelValue(dec, col, row, 0, &rgb[0]); + dmtxDecodeGetPixelValue(dec, col, row, 1, &rgb[1]); + dmtxDecodeGetPixelValue(dec, col, row, 2, &rgb[2]); + + p.X = col; + p.Y = row; + dmtxMatrix3VMultiplyBy(&p, reg->raw2fit); + + if (p.X < 0.0 || p.X > 1.0 || p.Y < 0.0 || p.Y > 1.0) + { + rgb[0] = 0; + rgb[1] = 0; + rgb[2] = 128; + } + else if (p.X + p.Y > 1.0) + { + rgb[0] += (0.4 * (255 - rgb[0])); + rgb[1] += (0.4 * (255 - rgb[1])); + rgb[2] += (0.4 * (255 - rgb[2])); + } } - } - - dmtxImageSetRgb(img, col, row, rgb); - } - } - - /* Write additional markers */ - rgb[0] = 255; - rgb[1] = 0; - rgb[2] = 0; - dmtxImageSetRgb(img, reg->topLoc.X, reg->topLoc.Y, rgb); - dmtxImageSetRgb(img, reg->rightLoc.X, reg->rightLoc.Y, rgb); - - /* Write image to PNM file */ - fprintf(fp, "P6\n%d %d\n255\n", width, height); - for(row = height - 1; row >= 0; row--) { - for(col = 0; col < width; col++) { - dmtxImageGetRgb(img, col, row, rgb); - fwrite(rgb, sizeof(char), 3, fp); - } - } - - dmtxImageDestroy(&img); - - fclose(fp); + + dmtxImageSetRgb(img, col, row, rgb); + } + } + + /* Write additional markers */ + rgb[0] = 255; + rgb[1] = 0; + rgb[2] = 0; + dmtxImageSetRgb(img, reg->topLoc.X, reg->topLoc.Y, rgb); + dmtxImageSetRgb(img, reg->rightLoc.X, reg->rightLoc.Y, rgb); + + /* Write image to PNM file */ + fprintf(fp, "P6\n%d %d\n255\n", width, height); + for (row = height - 1; row >= 0; row--) + { + for (col = 0; col < width; col++) + { + dmtxImageGetRgb(img, col, row, rgb); + fwrite(rgb, sizeof(char), 3, fp); + } + } + + dmtxImageDestroy(&img); + + fclose(fp); } #endif diff --git a/dmtxscangrid.c b/dmtxscangrid.c index 80d867da..0838a6ac 100644 --- a/dmtxscangrid.c +++ b/dmtxscangrid.c @@ -22,44 +22,44 @@ static DmtxScanGrid InitScanGrid(DmtxDecode *dec) { - int scale, smallestFeature; - int xExtent, yExtent, maxExtent; - int extent; - DmtxScanGrid grid; + int scale, smallestFeature; + int xExtent, yExtent, maxExtent; + int extent; + DmtxScanGrid grid; - memset(&grid, 0x00, sizeof(DmtxScanGrid)); + memset(&grid, 0x00, sizeof(DmtxScanGrid)); - scale = dmtxDecodeGetProp(dec, DmtxPropScale); - smallestFeature = dmtxDecodeGetProp(dec, DmtxPropScanGap) / scale; + scale = dmtxDecodeGetProp(dec, DmtxPropScale); + smallestFeature = dmtxDecodeGetProp(dec, DmtxPropScanGap) / scale; - grid.xMin = dmtxDecodeGetProp(dec, DmtxPropXmin); - grid.xMax = dmtxDecodeGetProp(dec, DmtxPropXmax); - grid.yMin = dmtxDecodeGetProp(dec, DmtxPropYmin); - grid.yMax = dmtxDecodeGetProp(dec, DmtxPropYmax); + grid.xMin = dmtxDecodeGetProp(dec, DmtxPropXmin); + grid.xMax = dmtxDecodeGetProp(dec, DmtxPropXmax); + grid.yMin = dmtxDecodeGetProp(dec, DmtxPropYmin); + grid.yMax = dmtxDecodeGetProp(dec, DmtxPropYmax); - /* Values that get set once */ - xExtent = grid.xMax - grid.xMin; - yExtent = grid.yMax - grid.yMin; - maxExtent = (xExtent > yExtent) ? xExtent : yExtent; + /* Values that get set once */ + xExtent = grid.xMax - grid.xMin; + yExtent = grid.yMax - grid.yMin; + maxExtent = (xExtent > yExtent) ? xExtent : yExtent; - assert(maxExtent > 1); + assert(maxExtent > 1); - for(extent = 1; extent < maxExtent; extent = ((extent + 1) * 2) - 1) - if(extent <= smallestFeature) - grid.minExtent = extent; + for (extent = 1; extent < maxExtent; extent = ((extent + 1) * 2) - 1) + if (extent <= smallestFeature) + grid.minExtent = extent; - grid.maxExtent = extent; + grid.maxExtent = extent; - grid.xOffset = (grid.xMin + grid.xMax - grid.maxExtent) / 2; - grid.yOffset = (grid.yMin + grid.yMax - grid.maxExtent) / 2; + grid.xOffset = (grid.xMin + grid.xMax - grid.maxExtent) / 2; + grid.yOffset = (grid.yMin + grid.yMax - grid.maxExtent) / 2; - /* Values that get reset for every level */ - grid.total = 1; - grid.extent = grid.maxExtent; + /* Values that get reset for every level */ + grid.total = 1; + grid.extent = grid.maxExtent; - SetDerivedFields(&grid); + SetDerivedFields(&grid); - return grid; + return grid; } /** @@ -72,17 +72,18 @@ InitScanGrid(DmtxDecode *dec) static int PopGridLocation(DmtxScanGrid *grid, DmtxPixelLoc *locPtr) { - int locStatus; + int locStatus; - do { - locStatus = GetGridCoordinates(grid, locPtr); + do + { + locStatus = GetGridCoordinates(grid, locPtr); - /* Always leave grid pointing at next available location */ - grid->pixelCount++; + /* Always leave grid pointing at next available location */ + grid->pixelCount++; - } while(locStatus == DmtxRangeBad); + } while (locStatus == DmtxRangeBad); - return locStatus; + return locStatus; } /** @@ -94,72 +95,80 @@ PopGridLocation(DmtxScanGrid *grid, DmtxPixelLoc *locPtr) static int GetGridCoordinates(DmtxScanGrid *grid, DmtxPixelLoc *locPtr) { - int count, half, quarter; - DmtxPixelLoc loc; - - /* Initially pixelCount may fall beyond acceptable limits. Update grid - * state before testing coordinates */ - - /* Jump to next cross pattern horizontally if current column is done */ - if(grid->pixelCount >= grid->pixelTotal) { - grid->pixelCount = 0; - grid->xCenter += grid->jumpSize; - } - - /* Jump to next cross pattern vertically if current row is done */ - if(grid->xCenter > grid->maxExtent) { - grid->xCenter = grid->startPos; - grid->yCenter += grid->jumpSize; - } - - /* Increment level when vertical step goes too far */ - if(grid->yCenter > grid->maxExtent) { - grid->total *= 4; - grid->extent /= 2; - SetDerivedFields(grid); - } - - if(grid->extent == 0 || grid->extent < grid->minExtent) { - locPtr->X = locPtr->Y = -1; - return DmtxRangeEnd; - } - - count = grid->pixelCount; - - assert(count < grid->pixelTotal); - - if(count == grid->pixelTotal - 1) { - /* center pixel */ - loc.X = grid->xCenter; - loc.Y = grid->yCenter; - } - else { - half = grid->pixelTotal / 2; - quarter = half / 2; - - /* horizontal portion */ - if(count < half) { - loc.X = grid->xCenter + ((count < quarter) ? (count - quarter) : (half - count)); - loc.Y = grid->yCenter; - } - /* vertical portion */ - else { - count -= half; - loc.X = grid->xCenter; - loc.Y = grid->yCenter + ((count < quarter) ? (count - quarter) : (half - count)); - } - } - - loc.X += grid->xOffset; - loc.Y += grid->yOffset; - - *locPtr = loc; - - if(loc.X < grid->xMin || loc.X > grid->xMax || - loc.Y < grid->yMin || loc.Y > grid->yMax) - return DmtxRangeBad; - - return DmtxRangeGood; + int count, half, quarter; + DmtxPixelLoc loc; + + /* Initially pixelCount may fall beyond acceptable limits. Update grid + * state before testing coordinates */ + + /* Jump to next cross pattern horizontally if current column is done */ + if (grid->pixelCount >= grid->pixelTotal) + { + grid->pixelCount = 0; + grid->xCenter += grid->jumpSize; + } + + /* Jump to next cross pattern vertically if current row is done */ + if (grid->xCenter > grid->maxExtent) + { + grid->xCenter = grid->startPos; + grid->yCenter += grid->jumpSize; + } + + /* Increment level when vertical step goes too far */ + if (grid->yCenter > grid->maxExtent) + { + grid->total *= 4; + grid->extent /= 2; + SetDerivedFields(grid); + } + + if (grid->extent == 0 || grid->extent < grid->minExtent) + { + locPtr->X = locPtr->Y = -1; + return DmtxRangeEnd; + } + + count = grid->pixelCount; + + assert(count < grid->pixelTotal); + + if (count == grid->pixelTotal - 1) + { + /* center pixel */ + loc.X = grid->xCenter; + loc.Y = grid->yCenter; + } + else + { + half = grid->pixelTotal / 2; + quarter = half / 2; + + /* horizontal portion */ + if (count < half) + { + loc.X = grid->xCenter + ((count < quarter) ? (count - quarter) : (half - count)); + loc.Y = grid->yCenter; + } + /* vertical portion */ + else + { + count -= half; + loc.X = grid->xCenter; + loc.Y = grid->yCenter + ((count < quarter) ? (count - quarter) : (half - count)); + } + } + + loc.X += grid->xOffset; + loc.Y += grid->yOffset; + + *locPtr = loc; + + if (loc.X < grid->xMin || loc.X > grid->xMax || + loc.Y < grid->yMin || loc.Y > grid->yMax) + return DmtxRangeBad; + + return DmtxRangeGood; } /** @@ -170,9 +179,9 @@ GetGridCoordinates(DmtxScanGrid *grid, DmtxPixelLoc *locPtr) static void SetDerivedFields(DmtxScanGrid *grid) { - grid->jumpSize = grid->extent + 1; - grid->pixelTotal = 2 * grid->extent - 1; - grid->startPos = grid->extent / 2; - grid->pixelCount = 0; - grid->xCenter = grid->yCenter = grid->startPos; + grid->jumpSize = grid->extent + 1; + grid->pixelTotal = 2 * grid->extent - 1; + grid->startPos = grid->extent / 2; + grid->pixelCount = 0; + grid->xCenter = grid->yCenter = grid->startPos; } diff --git a/dmtxstatic.h b/dmtxstatic.h index 3672ccea..04451421 100644 --- a/dmtxstatic.h +++ b/dmtxstatic.h @@ -58,21 +58,23 @@ #define DmtxChannelCannotUnlatch 0x01 << 1 #undef min -#define min(X,Y) (((X) < (Y)) ? (X) : (Y)) +#define min(X, Y) (((X) < (Y)) ? (X) : (Y)) #undef max -#define max(X,Y) (((X) > (Y)) ? (X) : (Y)) +#define max(X, Y) (((X) > (Y)) ? (X) : (Y)) -typedef enum { - DmtxEncodeNormal, /* Use normal scheme behavior (e.g., ASCII auto) */ - DmtxEncodeCompact, /* Use only compact format within scheme */ - DmtxEncodeFull /* Use only fully expanded format within scheme */ +typedef enum +{ + DmtxEncodeNormal, /* Use normal scheme behavior (e.g., ASCII auto) */ + DmtxEncodeCompact, /* Use only compact format within scheme */ + DmtxEncodeFull /* Use only fully expanded format within scheme */ } DmtxEncodeOption; -typedef enum { - DmtxRangeGood, - DmtxRangeBad, - DmtxRangeEnd +typedef enum +{ + DmtxRangeGood, + DmtxRangeBad, + DmtxRangeEnd } DmtxRange; typedef enum { @@ -176,9 +178,9 @@ static unsigned char *DecodeSchemeBase256(DmtxMessage *msg, unsigned char *ptr, /* dmtxencode.c */ static void PrintPattern(DmtxEncode *encode); #ifdef HAVE_READER_PROGRAMMING - static int EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming); +static int EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming); #else - static int EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1); +static int EncodeDataCodewords(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1); #endif /* dmtxplacemod.c */ @@ -189,7 +191,7 @@ static void PatternShapeSpecial2(unsigned char *modules, int mappingRows, int ma 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); + unsigned char *codeword, int mask, int moduleOnColor); /* dmtxreedsol.c */ static DmtxPassFail RsEncode(DmtxMessage *message, int sizeIdx); @@ -228,9 +230,9 @@ static void StreamInputAdvancePrev(DmtxEncodeStream *stream); /* dmtxencodescheme.c */ #ifdef HAVE_READER_PROGRAMMING - static int EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming); +static int EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1, DmtxBoolean bReaderProgramming); #else - static int EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1); +static int EncodeSingleScheme(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, DmtxScheme scheme, int fnc1); #endif static void EncodeNextChunk(DmtxEncodeStream *stream, int scheme, int subScheme, int sizeIdxRequest); @@ -240,13 +242,13 @@ static int GetRemainingSymbolCapacity(int outputLength, int sizeIdx); /* dmtxencodeoptimize.c */ static int EncodeOptimizeBest(DmtxByteList *input, DmtxByteList *output, int sizeIdxRequest, int fnc1); static void StreamAdvanceFromBest(DmtxEncodeStream *streamNext, - DmtxEncodeStream *streamList, int targeteState, int sizeIdxRequest); + DmtxEncodeStream *streamList, int targeteState, int sizeIdxRequest); static void AdvanceAsciiCompact(DmtxEncodeStream *streamNext, DmtxEncodeStream *streamList, - int state, int inputNext, int sizeIdxRequest); + int state, int inputNext, int sizeIdxRequest); static void AdvanceCTX(DmtxEncodeStream *streamNext, DmtxEncodeStream *streamList, - int state, int inputNext, int ctxValueCount, int sizeIdxRequest); + int state, int inputNext, int ctxValueCount, int sizeIdxRequest); static void AdvanceEdifact(DmtxEncodeStream *streamNext, DmtxEncodeStream *streamList, - int state, int inputNext, int sizeIdxRequest); + int state, int inputNext, int sizeIdxRequest); static int GetScheme(int state); static DmtxBoolean ValidStateSwitch(int fromState, int targetState); @@ -322,30 +324,30 @@ static int rHvY[] = /*@ -charint @*/ -enum DmtxErrorMessage { - DmtxErrorUnknown, - DmtxErrorUnsupportedCharacter, - DmtxErrorNotOnByteBoundary, - DmtxErrorIllegalParameterValue, - DmtxErrorEmptyList, - DmtxErrorOutOfBounds, - DmtxErrorMessageTooLarge, - DmtxErrorCantCompactNonDigits, - DmtxErrorUnexpectedScheme, - DmtxErrorIncompleteValueList +enum DmtxErrorMessage +{ + DmtxErrorUnknown, + DmtxErrorUnsupportedCharacter, + DmtxErrorNotOnByteBoundary, + DmtxErrorIllegalParameterValue, + DmtxErrorEmptyList, + DmtxErrorOutOfBounds, + DmtxErrorMessageTooLarge, + DmtxErrorCantCompactNonDigits, + DmtxErrorUnexpectedScheme, + DmtxErrorIncompleteValueList }; static char *dmtxErrorMessage[] = { - "Unknown error", - "Unsupported character", - "Not on byte boundary", - "Illegal parameter value", - "Encountered empty list", - "Out of bounds", - "Message too large", - "Can't compact non-digits", - "Encountered unexpected scheme", - "Encountered incomplete value list" -}; + "Unknown error", + "Unsupported character", + "Not on byte boundary", + "Illegal parameter value", + "Encountered empty list", + "Out of bounds", + "Message too large", + "Can't compact non-digits", + "Encountered unexpected scheme", + "Encountered incomplete value list"}; #endif diff --git a/dmtxsymbol.c b/dmtxsymbol.c index 408cd1de..ea806680 100644 --- a/dmtxsymbol.c +++ b/dmtxsymbol.c @@ -15,28 +15,28 @@ * \brief Data Matrix symbol attributes */ - /** * \brief Retrieve symbol index from rows and columns * \param rows * \param cols * \return sizeIdx value */ -extern int +extern int getSizeIdxFromSymbolDimension(int rows, int cols) { - int symbolRows, symbolCols, i; - for (i=0; i<30; i++){ - symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, i); - symbolCols = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, i); - if (rows==symbolRows && cols==symbolCols){ - return i; + int symbolRows, symbolCols, i; + for (i = 0; i < 30; i++) + { + symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, i); + symbolCols = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, i); + if (rows == symbolRows && cols == symbolCols) + { + return i; + } } - } - return -1; + return -1; } - /** * \brief Retrieve property based on symbol size * \param attribute @@ -100,42 +100,43 @@ dmtxGetSymbolAttribute(int attribute, int sizeIdx) 34, 31, 31, 3, 5, 7, 9, 12, 14 }; - if(sizeIdx < 0 || sizeIdx >= DmtxSymbolSquareCount + DmtxSymbolRectCount) - return DmtxUndefined; - - switch(attribute) { - case DmtxSymAttribSymbolRows: - return symbolRows[sizeIdx]; - case DmtxSymAttribSymbolCols: - return symbolCols[sizeIdx]; - case DmtxSymAttribDataRegionRows: - return dataRegionRows[sizeIdx]; - case DmtxSymAttribDataRegionCols: - return dataRegionCols[sizeIdx]; - case DmtxSymAttribHorizDataRegions: - return horizDataRegions[sizeIdx]; - case DmtxSymAttribVertDataRegions: - return (sizeIdx < DmtxSymbolSquareCount) ? horizDataRegions[sizeIdx] : 1; - case DmtxSymAttribMappingMatrixRows: - return dataRegionRows[sizeIdx] * + if (sizeIdx < 0 || sizeIdx >= DmtxSymbolSquareCount + DmtxSymbolRectCount) + return DmtxUndefined; + + switch (attribute) + { + case DmtxSymAttribSymbolRows: + return symbolRows[sizeIdx]; + case DmtxSymAttribSymbolCols: + return symbolCols[sizeIdx]; + case DmtxSymAttribDataRegionRows: + return dataRegionRows[sizeIdx]; + case DmtxSymAttribDataRegionCols: + return dataRegionCols[sizeIdx]; + case DmtxSymAttribHorizDataRegions: + return horizDataRegions[sizeIdx]; + case DmtxSymAttribVertDataRegions: + return (sizeIdx < DmtxSymbolSquareCount) ? horizDataRegions[sizeIdx] : 1; + case DmtxSymAttribMappingMatrixRows: + return dataRegionRows[sizeIdx] * dmtxGetSymbolAttribute(DmtxSymAttribVertDataRegions, sizeIdx); - case DmtxSymAttribMappingMatrixCols: - return dataRegionCols[sizeIdx] * horizDataRegions[sizeIdx]; - case DmtxSymAttribInterleavedBlocks: - return interleavedBlocks[sizeIdx]; - case DmtxSymAttribBlockErrorWords: - return blockErrorWords[sizeIdx]; - case DmtxSymAttribBlockMaxCorrectable: - return blockMaxCorrectable[sizeIdx]; - case DmtxSymAttribSymbolDataWords: - return symbolDataWords[sizeIdx]; - case DmtxSymAttribSymbolErrorWords: - return blockErrorWords[sizeIdx] * interleavedBlocks[sizeIdx]; - case DmtxSymAttribSymbolMaxCorrectable: - return blockMaxCorrectable[sizeIdx] * interleavedBlocks[sizeIdx]; - } - - return DmtxUndefined; + case DmtxSymAttribMappingMatrixCols: + return dataRegionCols[sizeIdx] * horizDataRegions[sizeIdx]; + case DmtxSymAttribInterleavedBlocks: + return interleavedBlocks[sizeIdx]; + case DmtxSymAttribBlockErrorWords: + return blockErrorWords[sizeIdx]; + case DmtxSymAttribBlockMaxCorrectable: + return blockMaxCorrectable[sizeIdx]; + case DmtxSymAttribSymbolDataWords: + return symbolDataWords[sizeIdx]; + case DmtxSymAttribSymbolErrorWords: + return blockErrorWords[sizeIdx] * interleavedBlocks[sizeIdx]; + case DmtxSymAttribSymbolMaxCorrectable: + return blockMaxCorrectable[sizeIdx] * interleavedBlocks[sizeIdx]; + } + + return DmtxUndefined; } /** @@ -147,19 +148,19 @@ dmtxGetSymbolAttribute(int attribute, int sizeIdx) extern int dmtxGetBlockDataSize(int sizeIdx, int blockIdx) { - int symbolDataWords; - int interleavedBlocks; - int count; + int symbolDataWords; + int interleavedBlocks; + int count; - symbolDataWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx); - interleavedBlocks = dmtxGetSymbolAttribute(DmtxSymAttribInterleavedBlocks, sizeIdx); + symbolDataWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx); + interleavedBlocks = dmtxGetSymbolAttribute(DmtxSymAttribInterleavedBlocks, sizeIdx); - if(symbolDataWords < 1 || interleavedBlocks < 1) - return DmtxUndefined; + if (symbolDataWords < 1 || interleavedBlocks < 1) + return DmtxUndefined; - count = (int)(symbolDataWords/interleavedBlocks); + count = (int)(symbolDataWords / interleavedBlocks); - return (sizeIdx == DmtxSymbol144x144 && blockIdx < 8) ? count + 1 : count; + return (sizeIdx == DmtxSymbol144x144 && blockIdx < 8) ? count + 1 : count; } /** @@ -171,37 +172,42 @@ dmtxGetBlockDataSize(int sizeIdx, int blockIdx) static int FindSymbolSize(int dataWords, int sizeIdxRequest) { - int sizeIdx; - int idxBeg, idxEnd; - - if(dataWords <= 0) - return DmtxUndefined; - - if(sizeIdxRequest == DmtxSymbolSquareAuto || sizeIdxRequest == DmtxSymbolRectAuto) { - - if(sizeIdxRequest == DmtxSymbolSquareAuto) { - idxBeg = 0; - idxEnd = DmtxSymbolSquareCount; - } - else { - idxBeg = DmtxSymbolSquareCount; - idxEnd = DmtxSymbolSquareCount + DmtxSymbolRectCount; - } - - for(sizeIdx = idxBeg; sizeIdx < idxEnd; sizeIdx++) { - if(dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx) >= dataWords) - break; - } - - if(sizeIdx == idxEnd) - return DmtxUndefined; - } - else { - sizeIdx = sizeIdxRequest; - } - - if(dataWords > dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx)) - return DmtxUndefined; - - return sizeIdx; + int sizeIdx; + int idxBeg, idxEnd; + + if (dataWords <= 0) + return DmtxUndefined; + + if (sizeIdxRequest == DmtxSymbolSquareAuto || sizeIdxRequest == DmtxSymbolRectAuto) + { + + if (sizeIdxRequest == DmtxSymbolSquareAuto) + { + idxBeg = 0; + idxEnd = DmtxSymbolSquareCount; + } + else + { + idxBeg = DmtxSymbolSquareCount; + idxEnd = DmtxSymbolSquareCount + DmtxSymbolRectCount; + } + + for (sizeIdx = idxBeg; sizeIdx < idxEnd; sizeIdx++) + { + if (dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx) >= dataWords) + break; + } + + if (sizeIdx == idxEnd) + return DmtxUndefined; + } + else + { + sizeIdx = sizeIdxRequest; + } + + if (dataWords > dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx)) + return DmtxUndefined; + + return sizeIdx; } diff --git a/dmtxtime.c b/dmtxtime.c index 2f30e74b..0ba86163 100644 --- a/dmtxtime.c +++ b/dmtxtime.c @@ -29,18 +29,18 @@ extern DmtxTime dmtxTimeNow(void) { - DmtxPassFail err; - struct timeval tv; - DmtxTime tNow; + DmtxPassFail err; + struct timeval tv; + DmtxTime tNow; - err = gettimeofday(&tv, NULL); - if(err != 0) - ; /* XXX handle error better here */ + err = gettimeofday(&tv, NULL); + if (err != 0) + ; /* XXX handle error better here */ - tNow.sec = tv.tv_sec; - tNow.usec = tv.tv_usec; + tNow.sec = tv.tv_sec; + tNow.usec = tv.tv_usec; - return tNow; + return tNow; } #elif defined(_MSC_VER) @@ -55,21 +55,21 @@ dmtxTimeNow(void) extern DmtxTime dmtxTimeNow(void) { - FILETIME ft; - unsigned __int64 tm; - DmtxTime tNow; + FILETIME ft; + unsigned __int64 tm; + DmtxTime tNow; - GetSystemTimeAsFileTime(&ft); + GetSystemTimeAsFileTime(&ft); - tm = ft.dwHighDateTime; - tm <<= 32; - tm |= ft.dwLowDateTime; - tm /= 10; + tm = ft.dwHighDateTime; + tm <<= 32; + tm |= ft.dwLowDateTime; + tm /= 10; - tNow.sec = tm / 1000000UL; - tNow.usec = tm % 1000000UL; + tNow.sec = tm / 1000000UL; + tNow.usec = tm % 1000000UL; - return tNow; + return tNow; } #else @@ -84,17 +84,17 @@ dmtxTimeNow(void) extern DmtxTime dmtxTimeNow(void) { - time_t s; - DmtxTime tNow; + time_t s; + DmtxTime tNow; - s = time(NULL); - if(errno != 0) - ; /* XXX handle error better here */ + s = time(NULL); + if (errno != 0) + ; /* XXX handle error better here */ - tNow.sec = s; - tNow.usec = 0; + tNow.sec = s; + tNow.usec = 0; - return tNow; + return tNow; } #endif @@ -108,25 +108,26 @@ dmtxTimeNow(void) extern DmtxTime dmtxTimeAdd(DmtxTime t, long msec) { - int usec; + int usec; - usec = msec * 1000; + usec = msec * 1000; - /* Ensure that time difference will register on local system */ - if(usec > 0 && usec < DMTX_TIME_PREC_USEC) - usec = DMTX_TIME_PREC_USEC; + /* Ensure that time difference will register on local system */ + if (usec > 0 && usec < DMTX_TIME_PREC_USEC) + usec = DMTX_TIME_PREC_USEC; - /* Add time */ - t.sec += usec/DMTX_USEC_PER_SEC; - t.usec += usec%DMTX_USEC_PER_SEC; + /* Add time */ + t.sec += usec / DMTX_USEC_PER_SEC; + t.usec += usec % DMTX_USEC_PER_SEC; - /* Roll extra usecs into secs */ - while(t.usec >= DMTX_USEC_PER_SEC) { - t.sec++; - t.usec -= DMTX_USEC_PER_SEC; - } + /* Roll extra usecs into secs */ + while (t.usec >= DMTX_USEC_PER_SEC) + { + t.sec++; + t.usec -= DMTX_USEC_PER_SEC; + } - return t; + return t; } /** @@ -137,11 +138,11 @@ dmtxTimeAdd(DmtxTime t, long msec) extern int dmtxTimeExceeded(DmtxTime timeout) { - DmtxTime now; + DmtxTime now; - now = dmtxTimeNow(); + now = dmtxTimeNow(); - return (now.sec > timeout.sec || (now.sec == timeout.sec && now.usec > timeout.usec)); + return (now.sec > timeout.sec || (now.sec == timeout.sec && now.usec > timeout.usec)); } #undef DMTX_TIME_PREC_USEC diff --git a/dmtxvector2.c b/dmtxvector2.c index 90b513d6..b02e6532 100644 --- a/dmtxvector2.c +++ b/dmtxvector2.c @@ -21,10 +21,10 @@ extern DmtxVector2 * dmtxVector2AddTo(DmtxVector2 *v1, const DmtxVector2 *v2) { - v1->X += v2->X; - v1->Y += v2->Y; + v1->X += v2->X; + v1->Y += v2->Y; - return v1; + return v1; } /** @@ -34,9 +34,9 @@ dmtxVector2AddTo(DmtxVector2 *v1, const DmtxVector2 *v2) extern DmtxVector2 * dmtxVector2Add(DmtxVector2 *vOut, const DmtxVector2 *v1, const DmtxVector2 *v2) { - *vOut = *v1; + *vOut = *v1; - return dmtxVector2AddTo(vOut, v2); + return dmtxVector2AddTo(vOut, v2); } /** @@ -46,10 +46,10 @@ dmtxVector2Add(DmtxVector2 *vOut, const DmtxVector2 *v1, const DmtxVector2 *v2) extern DmtxVector2 * dmtxVector2SubFrom(DmtxVector2 *v1, const DmtxVector2 *v2) { - v1->X -= v2->X; - v1->Y -= v2->Y; + v1->X -= v2->X; + v1->Y -= v2->Y; - return v1; + return v1; } /** @@ -59,9 +59,9 @@ dmtxVector2SubFrom(DmtxVector2 *v1, const DmtxVector2 *v2) extern DmtxVector2 * dmtxVector2Sub(DmtxVector2 *vOut, const DmtxVector2 *v1, const DmtxVector2 *v2) { - *vOut = *v1; + *vOut = *v1; - return dmtxVector2SubFrom(vOut, v2); + return dmtxVector2SubFrom(vOut, v2); } /** @@ -71,10 +71,10 @@ dmtxVector2Sub(DmtxVector2 *vOut, const DmtxVector2 *v1, const DmtxVector2 *v2) extern DmtxVector2 * dmtxVector2ScaleBy(DmtxVector2 *v, double s) { - v->X *= s; - v->Y *= s; + v->X *= s; + v->Y *= s; - return v; + return v; } /** @@ -84,9 +84,9 @@ dmtxVector2ScaleBy(DmtxVector2 *v, double s) extern DmtxVector2 * dmtxVector2Scale(DmtxVector2 *vOut, const DmtxVector2 *v, double s) { - *vOut = *v; + *vOut = *v; - return dmtxVector2ScaleBy(vOut, s); + return dmtxVector2ScaleBy(vOut, s); } /** @@ -96,7 +96,7 @@ dmtxVector2Scale(DmtxVector2 *vOut, const DmtxVector2 *v, double s) extern double dmtxVector2Cross(const DmtxVector2 *v1, const DmtxVector2 *v2) { - return (v1->X * v2->Y) - (v1->Y * v2->X); + return (v1->X * v2->Y) - (v1->Y * v2->X); } /** @@ -106,16 +106,16 @@ dmtxVector2Cross(const DmtxVector2 *v1, const DmtxVector2 *v2) extern double dmtxVector2Norm(DmtxVector2 *v) { - double mag; + double mag; - mag = dmtxVector2Mag(v); + mag = dmtxVector2Mag(v); - if(mag <= DmtxAlmostZero) - return -1.0; /* XXX this doesn't look clean */ + if (mag <= DmtxAlmostZero) + return -1.0; /* XXX this doesn't look clean */ - dmtxVector2ScaleBy(v, 1/mag); + dmtxVector2ScaleBy(v, 1 / mag); - return mag; + return mag; } /** @@ -125,7 +125,7 @@ dmtxVector2Norm(DmtxVector2 *v) extern double dmtxVector2Dot(const DmtxVector2 *v1, const DmtxVector2 *v2) { - return (v1->X * v2->X) + (v1->Y * v2->Y); + return (v1->X * v2->X) + (v1->Y * v2->Y); } /** @@ -135,7 +135,7 @@ dmtxVector2Dot(const DmtxVector2 *v1, const DmtxVector2 *v2) extern double dmtxVector2Mag(const DmtxVector2 *v) { - return sqrt(v->X * v->X + v->Y * v->Y); + return sqrt(v->X * v->X + v->Y * v->Y); } /** @@ -145,12 +145,12 @@ dmtxVector2Mag(const DmtxVector2 *v) extern double dmtxDistanceFromRay2(const DmtxRay2 *r, const DmtxVector2 *q) { - DmtxVector2 vSubTmp; + DmtxVector2 vSubTmp; - /* Assumes that v is a unit vector */ - assert(fabs(1.0 - dmtxVector2Mag(&(r->v))) <= DmtxAlmostZero); + /* Assumes that v is a unit vector */ + assert(fabs(1.0 - dmtxVector2Mag(&(r->v))) <= DmtxAlmostZero); - return dmtxVector2Cross(&(r->v), dmtxVector2Sub(&vSubTmp, q, &(r->p))); + return dmtxVector2Cross(&(r->v), dmtxVector2Sub(&vSubTmp, q, &(r->p))); } /** @@ -160,16 +160,17 @@ dmtxDistanceFromRay2(const DmtxRay2 *r, const DmtxVector2 *q) extern double dmtxDistanceAlongRay2(const DmtxRay2 *r, const DmtxVector2 *q) { - DmtxVector2 vSubTmp; + DmtxVector2 vSubTmp; #ifdef DEBUG - /* Assumes that v is a unit vector */ - if(fabs(1.0 - dmtxVector2Mag(&(r->v))) > DmtxAlmostZero) { - ; /* XXX big error goes here */ - } + /* Assumes that v is a unit vector */ + if (fabs(1.0 - dmtxVector2Mag(&(r->v))) > DmtxAlmostZero) + { + ; /* XXX big error goes here */ + } #endif - return dmtxVector2Dot(dmtxVector2Sub(&vSubTmp, q, &(r->p)), &(r->v)); + return dmtxVector2Dot(dmtxVector2Sub(&vSubTmp, q, &(r->p)), &(r->v)); } /** @@ -179,17 +180,17 @@ dmtxDistanceAlongRay2(const DmtxRay2 *r, const DmtxVector2 *q) extern DmtxPassFail dmtxRay2Intersect(DmtxVector2 *point, const DmtxRay2 *p0, const DmtxRay2 *p1) { - double numer, denom; - DmtxVector2 w; + double numer, denom; + DmtxVector2 w; - denom = dmtxVector2Cross(&(p1->v), &(p0->v)); - if(fabs(denom) <= DmtxAlmostZero) - return DmtxFail; + denom = dmtxVector2Cross(&(p1->v), &(p0->v)); + if (fabs(denom) <= DmtxAlmostZero) + return DmtxFail; - dmtxVector2Sub(&w, &(p1->p), &(p0->p)); - numer = dmtxVector2Cross(&(p1->v), &w); + dmtxVector2Sub(&w, &(p1->p), &(p0->p)); + numer = dmtxVector2Cross(&(p1->v), &w); - return dmtxPointAlongRay2(point, p0, numer/denom); + return dmtxPointAlongRay2(point, p0, numer / denom); } /** @@ -199,13 +200,13 @@ dmtxRay2Intersect(DmtxVector2 *point, const DmtxRay2 *p0, const DmtxRay2 *p1) extern DmtxPassFail dmtxPointAlongRay2(DmtxVector2 *point, const DmtxRay2 *r, double t) { - DmtxVector2 vTmp; + DmtxVector2 vTmp; - /* Ray should always have unit length of 1 */ - assert(fabs(1.0 - dmtxVector2Mag(&(r->v))) <= DmtxAlmostZero); + /* Ray should always have unit length of 1 */ + assert(fabs(1.0 - dmtxVector2Mag(&(r->v))) <= DmtxAlmostZero); - dmtxVector2Scale(&vTmp, &(r->v), t); - dmtxVector2Add(point, &(r->p), &vTmp); + dmtxVector2Scale(&vTmp, &(r->v), t); + dmtxVector2Add(point, &(r->p), &vTmp); - return DmtxPass; + return DmtxPass; } From 0d88c8617295d742c8fb2ce7bfc70761494a9409 Mon Sep 17 00:00:00 2001 From: gpongelli Date: Wed, 21 Dec 2022 12:38:52 +0100 Subject: [PATCH 08/13] more recent windows build instruction, with cloned repo --- README.mingw | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/README.mingw b/README.mingw index 57d6942e..1ef3597e 100644 --- a/README.mingw +++ b/README.mingw @@ -57,6 +57,45 @@ Finally run: Now you should have working dmtx.dll in the folder .libs. +3.1. Building and installing the core library from different folder +------------------------------------------------------------------- + +Recent MSYS2 installation uses C:\msys64 root folder, To build libdmtx: + +1. install the MSYS2 packages: + + $ pacman -S --needed base-devel mingw-w64-x86_64-toolchain autoconf automake make libtool + +Details on how to install and setup MSYS2 environment on Windows can be found `here `_ +and `here `_ . + +2. clone git repository +3. open msys2 console and add msys' mingw64 bin folder to path environment variable + + $ export PATH=$PATH:/c/msys64/mingw64/bin + +4. to create configure script, run + $ ./autogen.sh + +5. open the configure file and put as very first instruction the following one + LDFLAGS="-Wl,-no-undefined" + +6. from within the libdmtx folder, run + + $ ./configure + $ make + +Now, into .libs subfolder, you should find following files: + + libdmtx.a libdmtx.la libdmtx.lai libdmtx_la-dmtx.o + +Then finally run: + + $ gcc -shared -o dmtx.dll libdmtx_la-dmtx.o -Wl,--out-implib,libdmtx.a + +Now you should have working dmtx.dll in the folder .libs. + + 4. This Document ----------------------------------------------------------------- From ee23fa338fcb0036c259edeae4e450780bd88793 Mon Sep 17 00:00:00 2001 From: gpongelli Date: Thu, 22 Dec 2022 16:58:05 +0100 Subject: [PATCH 09/13] use the version number coming from config.h --- dmtx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmtx.h b/dmtx.h index 310a3a29..e8112ad1 100644 --- a/dmtx.h +++ b/dmtx.h @@ -37,7 +37,7 @@ extern "C" #define M_PI_2 1.57079632679489661923 #endif -#define DmtxVersion "0.7.5" +#define DmtxVersion VERSION #define DmtxUndefined -1 From d50c1c313f85e40345fdd00351d5e178f4d78ea2 Mon Sep 17 00:00:00 2001 From: gpongelli Date: Thu, 22 Dec 2022 17:35:14 +0100 Subject: [PATCH 10/13] client utility method to know if feature was built --- dmtx.c | 10 ++++++++++ dmtx.h | 1 + 2 files changed, 11 insertions(+) diff --git a/dmtx.c b/dmtx.c index fdb8b44a..f5cc1295 100644 --- a/dmtx.c +++ b/dmtx.c @@ -90,3 +90,13 @@ dmtxVersion(void) { return DmtxVersion; } + +extern DmtxBoolean +dmtxReaderProgramming(void) +{ +#ifdef HAVE_READER_PROGRAMMING + return DmtxTrue; +#else + return DmtxFalse; +#endif +} diff --git a/dmtx.h b/dmtx.h index e8112ad1..d4a4ff1b 100644 --- a/dmtx.h +++ b/dmtx.h @@ -658,6 +658,7 @@ extern "C" extern void dmtxByteListPrint(DmtxByteList *list, char *prefix); extern char *dmtxVersion(void); + extern DmtxBoolean dmtxReaderProgramming(void); #ifdef __cplusplus } From f8c459089eced1e0f1554e5f0d1e82292bb63468 Mon Sep 17 00:00:00 2001 From: gpongelli Date: Wed, 28 Dec 2022 10:21:03 +0100 Subject: [PATCH 11/13] style dmtx.h back to a more human readability --- dmtx.h | 338 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 169 insertions(+), 169 deletions(-) diff --git a/dmtx.h b/dmtx.h index d4a4ff1b..2d0eb889 100644 --- a/dmtx.h +++ b/dmtx.h @@ -78,9 +78,9 @@ extern "C" typedef enum { - DmtxSchemeAutoFast = -2, - DmtxSchemeAutoBest = -1, - DmtxSchemeAscii = 0, + DmtxSchemeAutoFast = -2, + DmtxSchemeAutoBest = -1, + DmtxSchemeAscii = 0, DmtxSchemeC40, DmtxSchemeText, DmtxSchemeX12, @@ -90,10 +90,10 @@ extern "C" typedef enum { - DmtxSymbolRectAuto = -3, - DmtxSymbolSquareAuto = -2, - DmtxSymbolShapeAuto = -1, - DmtxSymbol10x10 = 0, + DmtxSymbolRectAuto = -3, + DmtxSymbolSquareAuto = -2, + DmtxSymbolShapeAuto = -1, + DmtxSymbol10x10 = 0, DmtxSymbol12x12, DmtxSymbol14x14, DmtxSymbol16x16, @@ -127,15 +127,15 @@ extern "C" typedef enum { - DmtxDirNone = 0x00, - DmtxDirUp = 0x01 << 0, - DmtxDirLeft = 0x01 << 1, - DmtxDirDown = 0x01 << 2, - DmtxDirRight = 0x01 << 3, - DmtxDirHorizontal = DmtxDirLeft | DmtxDirRight, - DmtxDirVertical = DmtxDirUp | DmtxDirDown, - DmtxDirRightUp = DmtxDirRight | DmtxDirUp, - DmtxDirLeftDown = DmtxDirLeft | DmtxDirDown + DmtxDirNone = 0x00, + DmtxDirUp = 0x01 << 0, + DmtxDirLeft = 0x01 << 1, + DmtxDirDown = 0x01 << 2, + DmtxDirRight = 0x01 << 3, + DmtxDirHorizontal = DmtxDirLeft | DmtxDirRight, + DmtxDirVertical = DmtxDirUp | DmtxDirDown, + DmtxDirRightUp = DmtxDirRight | DmtxDirUp, + DmtxDirLeftDown = DmtxDirLeft | DmtxDirDown } DmtxDirection; typedef enum @@ -158,29 +158,29 @@ extern "C" typedef enum { - DmtxCorner00 = 0x01 << 0, - DmtxCorner10 = 0x01 << 1, - DmtxCorner11 = 0x01 << 2, - DmtxCorner01 = 0x01 << 3 + DmtxCorner00 = 0x01 << 0, + DmtxCorner10 = 0x01 << 1, + DmtxCorner11 = 0x01 << 2, + DmtxCorner01 = 0x01 << 3 } DmtxCornerLoc; typedef enum { /* Encoding properties */ - DmtxPropScheme = 100, + DmtxPropScheme = 100, DmtxPropSizeRequest, DmtxPropMarginSize, DmtxPropModuleSize, DmtxPropFnc1, /* Decoding properties */ - DmtxPropEdgeMin = 200, + DmtxPropEdgeMin = 200, DmtxPropEdgeMax, DmtxPropScanGap, DmtxPropSquareDevn, DmtxPropSymbolSize, DmtxPropEdgeThresh, /* Image properties */ - DmtxPropWidth = 300, + DmtxPropWidth = 300, DmtxPropHeight, DmtxPropPixelPacking, DmtxPropBitsPerPixel, @@ -190,7 +190,7 @@ extern "C" DmtxPropImageFlip, DmtxPropChannelCount, /* Image modifiers */ - DmtxPropXmin = 400, + DmtxPropXmin = 400, DmtxPropXmax, DmtxPropYmin, DmtxPropYmax, @@ -200,13 +200,13 @@ extern "C" typedef enum { /* Custom format */ - DmtxPackCustom = 100, + DmtxPackCustom = 100, /* 1 bpp */ - DmtxPack1bppK = 200, + DmtxPack1bppK = 200, /* 8 bpp grayscale */ - DmtxPack8bppK = 300, + DmtxPack8bppK = 300, /* 16 bpp formats */ - DmtxPack16bppRGB = 400, + DmtxPack16bppRGB = 400, DmtxPack16bppRGBX, DmtxPack16bppXRGB, DmtxPack16bppBGR, @@ -214,11 +214,11 @@ extern "C" DmtxPack16bppXBGR, DmtxPack16bppYCbCr, /* 24 bpp formats */ - DmtxPack24bppRGB = 500, + DmtxPack24bppRGB = 500, DmtxPack24bppBGR, DmtxPack24bppYCbCr, /* 32 bpp formats */ - DmtxPack32bppRGBX = 600, + DmtxPack32bppRGBX = 600, DmtxPack32bppXRGB, DmtxPack32bppBGRX, DmtxPack32bppXBGR, @@ -227,9 +227,9 @@ extern "C" typedef enum { - DmtxFlipNone = 0x00, - DmtxFlipX = 0x01 << 0, - DmtxFlipY = 0x01 << 1 + DmtxFlipNone = 0x00, + DmtxFlipX = 0x01 << 0, + DmtxFlipY = 0x01 << 1 } DmtxFlip; typedef double DmtxMatrix3[3][3]; @@ -250,8 +250,8 @@ extern "C" */ typedef struct DmtxVector2_struct { - double X; - double Y; + double X; + double Y; } DmtxVector2; /** @@ -260,10 +260,10 @@ extern "C" */ typedef struct DmtxRay2_struct { - double tMin; - double tMax; - DmtxVector2 p; - DmtxVector2 v; + double tMin; + double tMax; + DmtxVector2 p; + DmtxVector2 v; } DmtxRay2; typedef unsigned char DmtxByte; @@ -303,18 +303,18 @@ extern "C" */ typedef struct DmtxImage_struct { - int width; - int height; - int pixelPacking; - int bitsPerPixel; - int bytesPerPixel; - int rowPadBytes; - int rowSizeBytes; - int imageFlip; - int channelCount; - int channelStart[4]; - int bitsPerChannel[4]; - unsigned char *pxl; + int width; + int height; + int pixelPacking; + int bitsPerPixel; + int bytesPerPixel; + int rowPadBytes; + int rowSizeBytes; + int imageFlip; + int channelCount; + int channelStart[4]; + int bitsPerChannel[4]; + unsigned char *pxl; } DmtxImage; /** @@ -323,11 +323,11 @@ extern "C" */ typedef struct DmtxPointFlow_struct { - int plane; - int arrive; - int depart; - int mag; - DmtxPixelLoc loc; + int plane; + int arrive; + int depart; + int mag; + DmtxPixelLoc loc; } DmtxPointFlow; /** @@ -336,17 +336,17 @@ extern "C" */ typedef struct DmtxBestLine_struct { - int angle; - int hOffset; - int mag; - int stepBeg; - int stepPos; - int stepNeg; - int distSq; - double devn; - DmtxPixelLoc locBeg; - DmtxPixelLoc locPos; - DmtxPixelLoc locNeg; + int angle; + int hOffset; + int mag; + int stepBeg; + int stepPos; + int stepNeg; + int distSq; + double devn; + DmtxPixelLoc locBeg; + DmtxPixelLoc locPos; + DmtxPixelLoc locNeg; } DmtxBestLine; /** @@ -357,50 +357,50 @@ extern "C" { /* Trail blazing values */ - int jumpToPos; /* */ - int jumpToNeg; /* */ - int stepsTotal; /* */ - DmtxPixelLoc finalPos; /* */ - DmtxPixelLoc finalNeg; /* */ - DmtxPixelLoc boundMin; /* */ - DmtxPixelLoc boundMax; /* */ - DmtxPointFlow flowBegin; /* */ + int jumpToPos; /* */ + int jumpToNeg; /* */ + int stepsTotal; /* */ + DmtxPixelLoc finalPos; /* */ + DmtxPixelLoc finalNeg; /* */ + DmtxPixelLoc boundMin; /* */ + DmtxPixelLoc boundMax; /* */ + DmtxPointFlow flowBegin; /* */ /* Orientation values */ - int polarity; /* */ - int stepR; - int stepT; - DmtxPixelLoc locR; /* remove if stepR works above */ - DmtxPixelLoc locT; /* remove if stepT works above */ + int polarity; /* */ + int stepR; + int stepT; + DmtxPixelLoc locR; /* remove if stepR works above */ + DmtxPixelLoc locT; /* remove if stepT works above */ /* Region fitting values */ - int leftKnown; /* known == 1; unknown == 0 */ - int leftAngle; /* hough angle of left edge */ - DmtxPixelLoc leftLoc; /* known (arbitrary) location on left edge */ - DmtxBestLine leftLine; /* */ - int bottomKnown; /* known == 1; unknown == 0 */ - int bottomAngle; /* hough angle of bottom edge */ - DmtxPixelLoc bottomLoc; /* known (arbitrary) location on bottom edge */ - DmtxBestLine bottomLine; /* */ - int topKnown; /* known == 1; unknown == 0 */ - int topAngle; /* hough angle of top edge */ - DmtxPixelLoc topLoc; /* known (arbitrary) location on top edge */ - int rightKnown; /* known == 1; unknown == 0 */ - int rightAngle; /* hough angle of right edge */ - DmtxPixelLoc rightLoc; /* known (arbitrary) location on right edge */ + int leftKnown; /* known == 1; unknown == 0 */ + int leftAngle; /* hough angle of left edge */ + DmtxPixelLoc leftLoc; /* known (arbitrary) location on left edge */ + DmtxBestLine leftLine; /* */ + int bottomKnown; /* known == 1; unknown == 0 */ + int bottomAngle; /* hough angle of bottom edge */ + DmtxPixelLoc bottomLoc; /* known (arbitrary) location on bottom edge */ + DmtxBestLine bottomLine; /* */ + int topKnown; /* known == 1; unknown == 0 */ + int topAngle; /* hough angle of top edge */ + DmtxPixelLoc topLoc; /* known (arbitrary) location on top edge */ + int rightKnown; /* known == 1; unknown == 0 */ + int rightAngle; /* hough angle of right edge */ + DmtxPixelLoc rightLoc; /* known (arbitrary) location on right edge */ /* Region calibration values */ - int onColor; /* */ - int offColor; /* */ - int sizeIdx; /* Index of arrays that store Data Matrix constants */ - int symbolRows; /* Number of total rows in symbol including alignment patterns */ - int symbolCols; /* Number of total columns in symbol including alignment patterns */ - int mappingRows; /* Number of data rows in symbol */ - int mappingCols; /* Number of data columns in symbol */ + int onColor; /* */ + int offColor; /* */ + int sizeIdx; /* Index of arrays that store Data Matrix constants */ + int symbolRows; /* Number of total rows in symbol including alignment patterns */ + int symbolCols; /* Number of total columns in symbol including alignment patterns */ + int mappingRows; /* Number of data rows in symbol */ + int mappingCols; /* Number of data columns in symbol */ /* Transform values */ - DmtxMatrix3 raw2fit; /* 3x3 transformation from raw image to fitted barcode grid */ - DmtxMatrix3 fit2raw; /* 3x3 transformation from fitted barcode grid to raw image */ + DmtxMatrix3 raw2fit; /* 3x3 transformation from raw image to fitted barcode grid */ + DmtxMatrix3 fit2raw; /* 3x3 transformation from fitted barcode grid to raw image */ } DmtxRegion; /** @@ -409,15 +409,15 @@ extern "C" */ typedef struct DmtxMessage_struct { - size_t arraySize; /* mappingRows * mappingCols */ - size_t codeSize; /* Size of encoded data (data words + error words) */ - size_t outputSize; /* Size of buffer used to hold decoded data */ - int outputIdx; /* Internal index used to store output progress */ - int padCount; - int fnc1; /* Character to represent FNC1, or DmtxUndefined */ - unsigned char *array; /* Pointer to internal representation of Data Matrix modules */ - unsigned char *code; /* Pointer to internal storage of code words (data and error) */ - unsigned char *output; /* Pointer to internal storage of decoded output */ + size_t arraySize; /* mappingRows * mappingCols */ + size_t codeSize; /* Size of encoded data (data words + error words) */ + size_t outputSize; /* Size of buffer used to hold decoded data */ + int outputIdx; /* Internal index used to store output progress */ + int padCount; + int fnc1; /* Character to represent FNC1, or DmtxUndefined */ + unsigned char *array; /* Pointer to internal representation of Data Matrix modules */ + unsigned char *code; /* Pointer to internal storage of code words (data and error) */ + unsigned char *output; /* Pointer to internal storage of decoded output */ } DmtxMessage; /** @@ -427,26 +427,26 @@ extern "C" typedef struct DmtxScanGrid_struct { /* set once */ - int minExtent; /* Smallest cross size used in scan */ - int maxExtent; /* Size of bounding grid region (2^N - 1) */ - int xOffset; /* Offset to obtain image X coordinate */ - int yOffset; /* Offset to obtain image Y coordinate */ - int xMin; /* Minimum X in image coordinate system */ - int xMax; /* Maximum X in image coordinate system */ - int yMin; /* Minimum Y in image coordinate system */ - int yMax; /* Maximum Y in image coordinate system */ + int minExtent; /* Smallest cross size used in scan */ + int maxExtent; /* Size of bounding grid region (2^N - 1) */ + int xOffset; /* Offset to obtain image X coordinate */ + int yOffset; /* Offset to obtain image Y coordinate */ + int xMin; /* Minimum X in image coordinate system */ + int xMax; /* Maximum X in image coordinate system */ + int yMin; /* Minimum Y in image coordinate system */ + int yMax; /* Maximum Y in image coordinate system */ /* reset for each level */ - int total; /* Total number of crosses at this size */ - int extent; /* Length/width of cross in pixels */ - int jumpSize; /* Distance in pixels between cross centers */ - int pixelTotal; /* Total pixel count within an individual cross path */ - int startPos; /* X and Y coordinate of first cross center in pattern */ + int total; /* Total number of crosses at this size */ + int extent; /* Length/width of cross in pixels */ + int jumpSize; /* Distance in pixels between cross centers */ + int pixelTotal; /* Total pixel count within an individual cross path */ + int startPos; /* X and Y coordinate of first cross center in pattern */ /* reset for each cross */ - int pixelCount; /* Progress (pixel count) within current cross pattern */ - int xCenter; /* X center of current cross pattern */ - int yCenter; /* Y center of current cross pattern */ + int pixelCount; /* Progress (pixel count) within current cross pattern */ + int xCenter; /* X center of current cross pattern */ + int yCenter; /* Y center of current cross pattern */ } DmtxScanGrid; /** @@ -455,8 +455,8 @@ extern "C" */ typedef struct DmtxTime_struct { - time_t sec; - unsigned long usec; + time_t sec; + unsigned long usec; } DmtxTime; /** @@ -466,26 +466,26 @@ extern "C" typedef struct DmtxDecode_struct { /* Options */ - int edgeMin; - int edgeMax; - int scanGap; - int fnc1; - double squareDevn; - int sizeIdxExpected; - int edgeThresh; + int edgeMin; + int edgeMax; + int scanGap; + int fnc1; + double squareDevn; + int sizeIdxExpected; + int edgeThresh; /* Image modifiers */ - int xMin; - int xMax; - int yMin; - int yMax; - int scale; + int xMin; + int xMax; + int yMin; + int yMax; + int scale; /* Internals */ /* int cacheComplete; */ - unsigned char *cache; - DmtxImage *image; - DmtxScanGrid grid; + unsigned char *cache; + DmtxImage *image; + DmtxScanGrid grid; } DmtxDecode; /** @@ -494,20 +494,20 @@ extern "C" */ typedef struct DmtxEncode_struct { - int method; - int scheme; - int sizeIdxRequest; - int marginSize; - int moduleSize; - int pixelPacking; - int imageFlip; - int rowPadBytes; - int fnc1; - DmtxMessage *message; - DmtxImage *image; - DmtxRegion region; - DmtxMatrix3 xfrm; /* XXX still necessary? */ - DmtxMatrix3 rxfrm; /* XXX still necessary? */ + int method; + int scheme; + int sizeIdxRequest; + int marginSize; + int moduleSize; + int pixelPacking; + int imageFlip; + int rowPadBytes; + int fnc1; + DmtxMessage *message; + DmtxImage *image; + DmtxRegion region; + DmtxMatrix3 xfrm; /* XXX still necessary? */ + DmtxMatrix3 rxfrm; /* XXX still necessary? */ } DmtxEncode; /** @@ -516,14 +516,14 @@ extern "C" */ typedef struct DmtxChannel_struct { - int encScheme; /* current encodation scheme */ - int invalid; /* channel status (invalid if non-zero) */ - unsigned char *inputPtr; /* pointer to current input character */ - unsigned char *inputStop; /* pointer to position after final input character */ - int encodedLength; /* encoded length (units of 2/3 bits) */ - int currentLength; /* current length (units of 2/3 bits) */ - int firstCodeWord; /* */ - unsigned char encodedWords[1558]; + int encScheme; /* current encodation scheme */ + int invalid; /* channel status (invalid if non-zero) */ + unsigned char *inputPtr; /* pointer to current input character */ + unsigned char *inputStop; /* pointer to position after final input character */ + int encodedLength; /* encoded length (units of 2/3 bits) */ + int currentLength; /* current length (units of 2/3 bits) */ + int firstCodeWord; /* */ + unsigned char encodedWords[1558]; } DmtxChannel; /* Wrap in a struct for fast copies */ @@ -542,7 +542,7 @@ extern "C" */ typedef struct DmtxTriplet_struct { - unsigned char value[3]; + unsigned char value[3]; } DmtxTriplet; /** @@ -551,7 +551,7 @@ extern "C" */ typedef struct DmtxQuadruplet_struct { - unsigned char value[4]; + unsigned char value[4]; } DmtxQuadruplet; /* dmtxtime.c */ From 01b1a827fe0e1fcb6fea202b8d23073b6e99ce8c Mon Sep 17 00:00:00 2001 From: gpongelli Date: Wed, 28 Dec 2022 10:23:58 +0100 Subject: [PATCH 12/13] meaningful name for utility method --- dmtx.c | 2 +- dmtx.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dmtx.c b/dmtx.c index f5cc1295..95125a94 100644 --- a/dmtx.c +++ b/dmtx.c @@ -92,7 +92,7 @@ dmtxVersion(void) } extern DmtxBoolean -dmtxReaderProgramming(void) +dmtxHasReaderProgramming(void) { #ifdef HAVE_READER_PROGRAMMING return DmtxTrue; diff --git a/dmtx.h b/dmtx.h index 2d0eb889..59cd98bf 100644 --- a/dmtx.h +++ b/dmtx.h @@ -658,7 +658,7 @@ extern "C" extern void dmtxByteListPrint(DmtxByteList *list, char *prefix); extern char *dmtxVersion(void); - extern DmtxBoolean dmtxReaderProgramming(void); + extern DmtxBoolean dmtxHasReaderProgramming(void); #ifdef __cplusplus } From ed566f447f587c8b98141b1e3d6439782b423974 Mon Sep 17 00:00:00 2001 From: gpongelli Date: Wed, 28 Dec 2022 11:05:14 +0100 Subject: [PATCH 13/13] bump to v1.0.0 for reader programming breaking API --- CMakeLists.txt | 2 +- configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0531d404..a9a568f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.0) -project(DMTX VERSION 0.7.7 LANGUAGES C) +project(DMTX VERSION 1.0.0 LANGUAGES C) # DMTX library option(DMTX_SHARED "Build DMTX as shared library" ${BUILD_SHARED_LIBS}) diff --git a/configure.ac b/configure.ac index 80a0859b..7d854391 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([libdmtx], [0.7.7], [https://github.com/dmtx/libdmtx/issues], [libdmtx], [https://github.com/dmtx/libdmtx]) +AC_INIT([libdmtx], [1.0.0], [https://github.com/dmtx/libdmtx/issues], [libdmtx], [https://github.com/dmtx/libdmtx]) AM_INIT_AUTOMAKE([-Wall -Werror]) AC_CONFIG_MACRO_DIR([m4])